基础版本
diff --git a/platforms/android/.gitignore b/platforms/android/.gitignore
new file mode 100644
index 0000000..427a160
--- /dev/null
+++ b/platforms/android/.gitignore
@@ -0,0 +1,21 @@
+# Non-project-specific build files:
+build.xml
+local.properties
+/gradlew
+/gradlew.bat
+/gradle
+# Ant builds
+ant-build
+ant-gen
+# Eclipse builds
+gen
+out
+# Gradle build artifacts
+.gradle
+.gradletasknamecache
+/build
+/CordovaLib/build
+/app/build
+gradle-app.setting
+# Android Studio
+.idea
diff --git a/platforms/android/CordovaLib/AndroidManifest.xml b/platforms/android/CordovaLib/AndroidManifest.xml
new file mode 100755
index 0000000..1625b89
--- /dev/null
+++ b/platforms/android/CordovaLib/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
+    <uses-sdk android:minSdkVersion="19" />
+</manifest>
diff --git a/platforms/android/CordovaLib/build.gradle b/platforms/android/CordovaLib/build.gradle
new file mode 100644
index 0000000..b92c9a3
--- /dev/null
+++ b/platforms/android/CordovaLib/build.gradle
@@ -0,0 +1,136 @@
+/* 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.
+*/
+
+ext {
+    apply from: 'cordova.gradle'
+    cdvCompileSdkVersion = privateHelpers.getProjectTarget()
+    cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
+}
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        // The gradle plugin and the maven plugin have to be updated after each version of Android
+        // studio comes out
+        classpath 'com.android.tools.build:gradle:3.3.0'
+        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
+        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
+    }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'com.github.dcendents.android-maven'
+apply plugin: 'com.jfrog.bintray'
+
+group = 'org.apache.cordova'
+version = '8.0.0'
+
+android {
+    compileSdkVersion cdvCompileSdkVersion
+    buildToolsVersion cdvBuildToolsVersion
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            resources.srcDirs = ['src']
+            aidl.srcDirs = ['src']
+            renderscript.srcDirs = ['src']
+            res.srcDirs = ['res']
+            assets.srcDirs = ['assets']
+        }
+    }
+
+    packagingOptions {
+        exclude 'META-INF/LICENSE'
+        exclude 'META-INF/LICENSE.txt'
+        exclude 'META-INF/DEPENDENCIES'
+        exclude 'META-INF/NOTICE'
+    }
+}
+
+install {
+    repositories.mavenInstaller {
+        pom {
+            project {
+                packaging 'aar'
+                name 'Cordova'
+                url 'https://cordova.apache.org'
+                licenses {
+                    license {
+                        name 'The Apache Software License, Version 2.0'
+                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+                    }
+                }
+                developers {
+                    developer {
+                        id 'stevengill'
+                        name 'Steve Gill'
+                    }
+                }
+                scm {
+                    connection 'scm:git:https://github.com/apache/cordova-android.git'
+                    developerConnection 'scm:git:git@github.com:apache/cordova-android.git'
+                    url 'https://github.com/apache/cordova-android'
+
+                }
+            }
+        }
+    }
+}
+
+task sourcesJar(type: Jar) {
+    from android.sourceSets.main.java.srcDirs
+    classifier = 'sources'
+}
+
+artifacts {
+    archives sourcesJar
+}
+
+bintray {
+    user = System.getenv('BINTRAY_USER')
+    key = System.getenv('BINTRAY_KEY')
+    configurations = ['archives']
+    pkg {
+        repo = 'maven'
+        name = 'cordova-android'
+        userOrg = 'cordova'
+        licenses = ['Apache-2.0']
+        vcsUrl = 'https://github.com/apache/cordova-android'
+        websiteUrl = 'https://cordova.apache.org'
+        issueTrackerUrl = 'https://github.com/apache/cordova-android/issues'
+        publicDownloadNumbers = true
+        licenses = ['Apache-2.0']
+        labels = ['android', 'cordova', 'phonegap']
+        version {
+            name = '8.0.0'
+            released  = new Date()
+            vcsTag = '8.0.0'
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/cordova.gradle b/platforms/android/CordovaLib/cordova.gradle
new file mode 100644
index 0000000..6c6819a
--- /dev/null
+++ b/platforms/android/CordovaLib/cordova.gradle
@@ -0,0 +1,205 @@
+/*
+       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.
+*/
+
+import java.util.regex.Pattern
+import groovy.swing.SwingBuilder
+
+String doEnsureValueExists(filePath, props, key) {
+    if (props.get(key) == null) {
+        throw new GradleException(filePath + ': Missing key required "' + key + '"')
+    }
+    return props.get(key)
+}
+
+String doGetProjectTarget() {
+    def props = new Properties()
+    def propertiesFile = 'project.properties';
+    if(!(file(propertiesFile).exists())) {
+      propertiesFile = '../project.properties';
+    }
+    file(propertiesFile).withReader { reader ->
+        props.load(reader)
+    }
+    return doEnsureValueExists('project.properties', props, 'target')
+}
+
+String[] getAvailableBuildTools() {
+    def buildToolsDir = new File(getAndroidSdkDir(), "build-tools")
+    buildToolsDir.list()
+        .findAll { it ==~ /[0-9.]+/ }
+        .sort { a, b -> compareVersions(b, a) }
+}
+
+String doFindLatestInstalledBuildTools(String minBuildToolsVersion) {
+    def availableBuildToolsVersions
+    try {
+        availableBuildToolsVersions = getAvailableBuildTools()
+    } catch (e) {
+        println "An exception occurred while trying to find the Android build tools."
+        throw e
+    }
+    if (availableBuildToolsVersions.length > 0) {
+        def highestBuildToolsVersion = availableBuildToolsVersions[0]
+        if (compareVersions(highestBuildToolsVersion, minBuildToolsVersion) < 0) {
+            throw new RuntimeException(
+                "No usable Android build tools found. Highest installed version is " +
+                highestBuildToolsVersion + "; minimum version required is " +
+                minBuildToolsVersion + ".")
+        }
+        highestBuildToolsVersion
+    } else {
+        throw new RuntimeException(
+            "No installed build tools found. Install the Android build tools version " +
+            minBuildToolsVersion + " or higher.")
+    }
+}
+
+// Return the first non-zero result of subtracting version list elements
+// pairwise. If they are all identical, return the difference in length of
+// the two lists.
+int compareVersionList(Collection aParts, Collection bParts) {
+    def pairs = ([aParts, bParts]).transpose()
+    pairs.findResult(aParts.size()-bParts.size()) {it[0] - it[1] != 0 ? it[0] - it[1] : null}
+}
+
+// Compare two version strings, such as "19.0.0" and "18.1.1.0". If all matched
+// elements are identical, the longer version is the largest by this method.
+// Examples:
+//   "19.0.0" > "19"
+//   "19.0.1" > "19.0.0"
+//   "19.1.0" > "19.0.1"
+//   "19" > "18.999.999"
+int compareVersions(String a, String b) {
+    def aParts = a.tokenize('.').collect {it.toInteger()}
+    def bParts = b.tokenize('.').collect {it.toInteger()}
+    compareVersionList(aParts, bParts)
+}
+
+String getAndroidSdkDir() {
+    def rootDir = project.rootDir
+    def androidSdkDir = null
+    String envVar = System.getenv("ANDROID_HOME")
+    def localProperties = new File(rootDir, 'local.properties')
+    String systemProperty = System.getProperty("android.home")
+    if (envVar != null) {
+        androidSdkDir = envVar
+    } else if (localProperties.exists()) {
+        Properties properties = new Properties()
+        localProperties.withInputStream { instr ->
+            properties.load(instr)
+        }
+        def sdkDirProp = properties.getProperty('sdk.dir')
+        if (sdkDirProp != null) {
+            androidSdkDir = sdkDirProp
+        } else {
+            sdkDirProp = properties.getProperty('android.dir')
+            if (sdkDirProp != null) {
+                androidSdkDir = (new File(rootDir, sdkDirProp)).getAbsolutePath()
+            }
+        }
+    }
+    if (androidSdkDir == null && systemProperty != null) {
+        androidSdkDir = systemProperty
+    }
+    if (androidSdkDir == null) {
+        throw new RuntimeException(
+            "Unable to determine Android SDK directory.")
+    }
+    androidSdkDir
+}
+
+def doExtractIntFromManifest(name) {
+    def manifestFile = file(android.sourceSets.main.manifest.srcFile)
+    def pattern = Pattern.compile(name + "=\"(\\d+)\"")
+    def matcher = pattern.matcher(manifestFile.getText())
+    matcher.find()
+    return new BigInteger(matcher.group(1))
+}
+
+def doExtractStringFromManifest(name) {
+    def manifestFile = file(android.sourceSets.main.manifest.srcFile)
+    def pattern = Pattern.compile(name + "=\"(\\S+)\"")
+    def matcher = pattern.matcher(manifestFile.getText())
+    matcher.find()
+    return matcher.group(1)
+}
+
+def doPromptForPassword(msg) {
+    if (System.console() == null) {
+        def ret = null
+        new SwingBuilder().edt {
+            dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) {
+                vbox {
+                    label(text: msg)
+                    def input = passwordField()
+                    button(defaultButton: true, text: 'OK', actionPerformed: {
+                        ret = input.password;
+                        dispose();
+                    })
+                }
+            }
+        }
+        if (!ret) {
+            throw new GradleException('User canceled build')
+        }
+        return new String(ret)
+    } else {
+        return System.console().readPassword('\n' + msg);
+    }
+}
+
+def doGetConfigXml() {
+    def xml = file("src/main/res/xml/config.xml").getText()
+    // Disable namespace awareness since Cordova doesn't use them properly
+    return new XmlParser(false, false).parseText(xml)
+}
+
+def doGetConfigPreference(name, defaultValue) {
+    name = name.toLowerCase()
+    def root = doGetConfigXml()
+
+    def ret = defaultValue
+    root.preference.each { it ->
+        def attrName = it.attribute("name")
+        if (attrName && attrName.toLowerCase() == name) {
+            ret = it.attribute("value")
+        }
+    }
+    return ret
+}
+
+// Properties exported here are visible to all plugins.
+ext {
+    // These helpers are shared, but are not guaranteed to be stable / unchanged.
+    privateHelpers = {}
+    privateHelpers.getProjectTarget = { doGetProjectTarget() }
+    privateHelpers.findLatestInstalledBuildTools = { doFindLatestInstalledBuildTools('19.1.0') }
+    privateHelpers.extractIntFromManifest = { name -> doExtractIntFromManifest(name) }
+    privateHelpers.extractStringFromManifest = { name -> doExtractStringFromManifest(name) }
+    privateHelpers.promptForPassword = { msg -> doPromptForPassword(msg) }
+    privateHelpers.ensureValueExists = { filePath, props, key -> doEnsureValueExists(filePath, props, key) }
+
+    // These helpers can be used by plugins / projects and will not change.
+    cdvHelpers = {}
+    // Returns a XmlParser for the config.xml. Added in 4.1.0.
+    cdvHelpers.getConfigXml = { doGetConfigXml() }
+    // Returns the value for the desired <preference>. Added in 4.1.0.
+    cdvHelpers.getConfigPreference = { name, defaultValue -> doGetConfigPreference(name, defaultValue) }
+}
+
diff --git a/platforms/android/CordovaLib/project.properties b/platforms/android/CordovaLib/project.properties
new file mode 100644
index 0000000..cbb644c
--- /dev/null
+++ b/platforms/android/CordovaLib/project.properties
@@ -0,0 +1,11 @@
+# This file was originally created by the Android Tools, but is now
+# used by cordova-android to manage the project configuration.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+
+# Project target.
+target=android-28
+apk-configurations=
+renderscript.opt.level=O0
+android.library=true
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/AuthenticationToken.java b/platforms/android/CordovaLib/src/org/apache/cordova/AuthenticationToken.java
new file mode 100644
index 0000000..d3a231a
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/AuthenticationToken.java
@@ -0,0 +1,69 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+/**
+ * The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource
+ */
+public class AuthenticationToken {
+    private String userName;
+    private String password;
+
+    /**
+     * Gets the user name.
+     *
+     * @return the user name
+     */
+    public String getUserName() {
+        return userName;
+    }
+
+    /**
+     * Sets the user name.
+     *
+     * @param userName
+     *            the new user name
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    /**
+     * Gets the password.
+     *
+     * @return the password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password.
+     *
+     * @param password
+     *            the new password
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+
+
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/BuildHelper.java b/platforms/android/CordovaLib/src/org/apache/cordova/BuildHelper.java
new file mode 100644
index 0000000..6d9daa4
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/BuildHelper.java
@@ -0,0 +1,70 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+/*
+ * This is a utility class that allows us to get the BuildConfig variable, which is required
+ * for the use of different providers.  This is not guaranteed to work, and it's better for this
+ * to be set in the build step in config.xml
+ *
+ */
+
+import android.app.Activity;
+import android.content.Context;
+
+import java.lang.reflect.Field;
+
+
+public class BuildHelper {
+
+
+    private static String TAG="BuildHelper";
+
+    /*
+     * This needs to be implemented if you wish to use the Camera Plugin or other plugins
+     * that read the Build Configuration.
+     *
+     * Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to
+     * StackOverflow.  This is annoying as hell!  However, this method does not work with
+     * ProGuard, and you should use the config.xml to define the application_id
+     *
+     */
+
+    public static Object getBuildConfigValue(Context ctx, String key)
+    {
+        try
+        {
+            Class<?> clazz = Class.forName(ctx.getPackageName() + ".BuildConfig");
+            Field field = clazz.getField(key);
+            return field.get(null);
+        } catch (ClassNotFoundException e) {
+            LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?");
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            LOG.d(TAG, key + " is not a valid field. Check your build.gradle");
+        } catch (IllegalAccessException e) {
+            LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace.");
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CallbackContext.java b/platforms/android/CordovaLib/src/org/apache/cordova/CallbackContext.java
new file mode 100644
index 0000000..4336386
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CallbackContext.java
@@ -0,0 +1,142 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import org.json.JSONArray;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginResult;
+import org.json.JSONObject;
+
+public class CallbackContext {
+    private static final String LOG_TAG = "CordovaPlugin";
+
+    private String callbackId;
+    private CordovaWebView webView;
+    protected boolean finished;
+    private int changingThreads;
+
+    public CallbackContext(String callbackId, CordovaWebView webView) {
+        this.callbackId = callbackId;
+        this.webView = webView;
+    }
+
+    public boolean isFinished() {
+        return finished;
+    }
+
+    public boolean isChangingThreads() {
+        return changingThreads > 0;
+    }
+
+    public String getCallbackId() {
+        return callbackId;
+    }
+
+    public void sendPluginResult(PluginResult pluginResult) {
+        synchronized (this) {
+            if (finished) {
+                LOG.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage());
+                return;
+            } else {
+                finished = !pluginResult.getKeepCallback();
+            }
+        }
+        webView.sendPluginResult(pluginResult, callbackId);
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(JSONObject message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(String message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(JSONArray message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(byte[] message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     *
+     * @param message           The message to add to the success result.
+     */
+    public void success(int message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+    }
+
+    /**
+     * Helper for success callbacks that just returns the Status.OK by default
+     */
+    public void success() {
+        sendPluginResult(new PluginResult(PluginResult.Status.OK));
+    }
+
+    /**
+     * Helper for error callbacks that just returns the Status.ERROR by default
+     *
+     * @param message           The message to add to the error result.
+     */
+    public void error(JSONObject message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
+    }
+
+    /**
+     * Helper for error callbacks that just returns the Status.ERROR by default
+     *
+     * @param message           The message to add to the error result.
+     */
+    public void error(String message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
+    }
+
+    /**
+     * Helper for error callbacks that just returns the Status.ERROR by default
+     *
+     * @param message           The message to add to the error result.
+     */
+    public void error(int message) {
+        sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CallbackMap.java b/platforms/android/CordovaLib/src/org/apache/cordova/CallbackMap.java
new file mode 100644
index 0000000..050daa0
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CallbackMap.java
@@ -0,0 +1,65 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.util.Pair;
+import android.util.SparseArray;
+
+/**
+ * Provides a collection that maps unique request codes to CordovaPlugins and Integers.
+ * Used to ensure that when plugins make requests for runtime permissions, those requests do not
+ * collide with requests from other plugins that use the same request code value.
+ */
+public class CallbackMap {
+    private int currentCallbackId = 0;
+    private SparseArray<Pair<CordovaPlugin, Integer>> callbacks;
+
+    public CallbackMap() {
+        this.callbacks = new SparseArray<Pair<CordovaPlugin, Integer>>();
+    }
+
+    /**
+     * Stores a CordovaPlugin and request code and returns a new unique request code to use
+     * in a permission request.
+     *
+     * @param receiver      The plugin that is making the request
+     * @param requestCode   The original request code used by the plugin
+     * @return              A unique request code that can be used to retrieve this callback
+     *                      with getAndRemoveCallback()
+     */
+    public synchronized int registerCallback(CordovaPlugin receiver, int requestCode) {
+        int mappedId = this.currentCallbackId++;
+        callbacks.put(mappedId, new Pair<CordovaPlugin, Integer>(receiver, requestCode));
+        return mappedId;
+    }
+
+    /**
+     * Retrieves and removes a callback stored in the map using the mapped request code
+     * obtained from registerCallback()
+     *
+     * @param mappedId      The request code obtained from registerCallback()
+     * @return              The CordovaPlugin and orignal request code that correspond to the
+     *                      given mappedCode
+     */
+    public synchronized Pair<CordovaPlugin, Integer> getAndRemoveCallback(int mappedId) {
+        Pair<CordovaPlugin, Integer> callback = callbacks.get(mappedId);
+        callbacks.remove(mappedId);
+        return callback;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/Config.java b/platforms/android/CordovaLib/src/org/apache/cordova/Config.java
new file mode 100644
index 0000000..0739795
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/Config.java
@@ -0,0 +1,71 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import java.util.List;
+
+import android.app.Activity;
+
+@Deprecated // Use Whitelist, CordovaPrefences, etc. directly.
+public class Config {
+    private static final String TAG = "Config";
+
+    static ConfigXmlParser parser;
+
+    private Config() {
+    }
+
+    public static void init(Activity action) {
+        parser = new ConfigXmlParser();
+        parser.parse(action);
+        //TODO: Add feature to bring this back.  Some preferences should be overridden by intents, but not all
+        parser.getPreferences().setPreferencesBundle(action.getIntent().getExtras());
+    }
+
+    // Intended to be used for testing only; creates an empty configuration.
+    public static void init() {
+        if (parser == null) {
+            parser = new ConfigXmlParser();
+        }
+    }
+
+    public static String getStartUrl() {
+        if (parser == null) {
+            return "file:///android_asset/www/index.html";
+        }
+        return parser.getLaunchUrl();
+    }
+
+    public static String getErrorUrl() {
+        return parser.getPreferences().getString("errorurl", null);
+    }
+
+    public static List<PluginEntry> getPluginEntries() {
+        return parser.getPluginEntries();
+    }
+
+    public static CordovaPreferences getPreferences() {
+        return parser.getPreferences();
+    }
+
+    public static boolean isInitialized() {
+        return parser != null;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ConfigXmlParser.java b/platforms/android/CordovaLib/src/org/apache/cordova/ConfigXmlParser.java
new file mode 100644
index 0000000..01a97f2
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ConfigXmlParser.java
@@ -0,0 +1,145 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+
+public class ConfigXmlParser {
+    private static String TAG = "ConfigXmlParser";
+
+    private String launchUrl = "file:///android_asset/www/index.html";
+    private CordovaPreferences prefs = new CordovaPreferences();
+    private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
+
+    public CordovaPreferences getPreferences() {
+        return prefs;
+    }
+
+    public ArrayList<PluginEntry> getPluginEntries() {
+        return pluginEntries;
+    }
+
+    public String getLaunchUrl() {
+        return launchUrl;
+    }
+
+    public void parse(Context action) {
+        // First checking the class namespace for config.xml
+        int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName());
+        if (id == 0) {
+            // If we couldn't find config.xml there, we'll look in the namespace from AndroidManifest.xml
+            id = action.getResources().getIdentifier("config", "xml", action.getPackageName());
+            if (id == 0) {
+                LOG.e(TAG, "res/xml/config.xml is missing!");
+                return;
+            }
+        }
+        parse(action.getResources().getXml(id));
+    }
+
+    boolean insideFeature = false;
+    String service = "", pluginClass = "", paramType = "";
+    boolean onload = false;
+
+    public void parse(XmlPullParser xml) {
+        int eventType = -1;
+
+        while (eventType != XmlPullParser.END_DOCUMENT) {
+            if (eventType == XmlPullParser.START_TAG) {
+                handleStartTag(xml);
+            }
+            else if (eventType == XmlPullParser.END_TAG)
+            {
+                handleEndTag(xml);
+            }
+            try {
+                eventType = xml.next();
+            } catch (XmlPullParserException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public void handleStartTag(XmlPullParser xml) {
+        String strNode = xml.getName();
+        if (strNode.equals("feature")) {
+            //Check for supported feature sets  aka. plugins (Accelerometer, Geolocation, etc)
+            //Set the bit for reading params
+            insideFeature = true;
+            service = xml.getAttributeValue(null, "name");
+        }
+        else if (insideFeature && strNode.equals("param")) {
+            paramType = xml.getAttributeValue(null, "name");
+            if (paramType.equals("service")) // check if it is using the older service param
+                service = xml.getAttributeValue(null, "value");
+            else if (paramType.equals("package") || paramType.equals("android-package"))
+                pluginClass = xml.getAttributeValue(null,"value");
+            else if (paramType.equals("onload"))
+                onload = "true".equals(xml.getAttributeValue(null, "value"));
+        }
+        else if (strNode.equals("preference")) {
+            String name = xml.getAttributeValue(null, "name").toLowerCase(Locale.ENGLISH);
+            String value = xml.getAttributeValue(null, "value");
+            prefs.set(name, value);
+        }
+        else if (strNode.equals("content")) {
+            String src = xml.getAttributeValue(null, "src");
+            if (src != null) {
+                setStartUrl(src);
+            }
+        }
+    }
+
+    public void handleEndTag(XmlPullParser xml) {
+        String strNode = xml.getName();
+        if (strNode.equals("feature")) {
+            pluginEntries.add(new PluginEntry(service, pluginClass, onload));
+
+            service = "";
+            pluginClass = "";
+            insideFeature = false;
+            onload = false;
+        }
+    }
+
+    private void setStartUrl(String src) {
+        Pattern schemeRegex = Pattern.compile("^[a-z-]+://");
+        Matcher matcher = schemeRegex.matcher(src);
+        if (matcher.find()) {
+            launchUrl = src;
+        } else {
+            if (src.charAt(0) == '/') {
+                src = src.substring(1);
+            }
+            launchUrl = "file:///android_asset/www/" + src;
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java
new file mode 100755
index 0000000..dbbb48f
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java
@@ -0,0 +1,519 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.annotation.SuppressLint;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.media.AudioManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+
+/**
+ * This class is the main Android activity that represents the Cordova
+ * application. It should be extended by the user to load the specific
+ * html file that contains the application.
+ *
+ * As an example:
+ *
+ * <pre>
+ *     package org.apache.cordova.examples;
+ *
+ *     import android.os.Bundle;
+ *     import org.apache.cordova.*;
+ *
+ *     public class Example extends CordovaActivity {
+ *       &#64;Override
+ *       public void onCreate(Bundle savedInstanceState) {
+ *         super.onCreate(savedInstanceState);
+ *         super.init();
+ *         // Load your application
+ *         loadUrl(launchUrl);
+ *       }
+ *     }
+ * </pre>
+ *
+ * Cordova xml configuration: Cordova uses a configuration file at
+ * res/xml/config.xml to specify its settings. See "The config.xml File"
+ * guide in cordova-docs at http://cordova.apache.org/docs for the documentation
+ * for the configuration. The use of the set*Property() methods is
+ * deprecated in favor of the config.xml file.
+ *
+ */
+public class CordovaActivity extends Activity {
+    public static String TAG = "CordovaActivity";
+
+    // The webview for our app
+    protected CordovaWebView appView;
+
+    private static int ACTIVITY_STARTING = 0;
+    private static int ACTIVITY_RUNNING = 1;
+    private static int ACTIVITY_EXITING = 2;
+
+    // Keep app running when pause is received. (default = true)
+    // If true, then the JavaScript and native code continue to run in the background
+    // when another application (activity) is started.
+    protected boolean keepRunning = true;
+
+    // Flag to keep immersive mode if set to fullscreen
+    protected boolean immersiveMode;
+
+    // Read from config.xml:
+    protected CordovaPreferences preferences;
+    protected String launchUrl;
+    protected ArrayList<PluginEntry> pluginEntries;
+    protected CordovaInterfaceImpl cordovaInterface;
+
+    /**
+     * Called when the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
+        loadConfig();
+
+        String logLevel = preferences.getString("loglevel", "ERROR");
+        LOG.setLogLevel(logLevel);
+
+        LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
+        LOG.d(TAG, "CordovaActivity.onCreate()");
+
+        if (!preferences.getBoolean("ShowTitle", false)) {
+            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+        }
+
+        if (preferences.getBoolean("SetFullscreen", false)) {
+            LOG.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
+            preferences.set("Fullscreen", true);
+        }
+        if (preferences.getBoolean("Fullscreen", false)) {
+            // NOTE: use the FullscreenNotImmersive configuration key to set the activity in a REAL full screen
+            // (as was the case in previous cordova versions)
+            if (!preferences.getBoolean("FullscreenNotImmersive", false)) {
+                immersiveMode = true;
+            } else {
+                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+                        WindowManager.LayoutParams.FLAG_FULLSCREEN);
+            }
+        } else {
+            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
+                    WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+        }
+
+        super.onCreate(savedInstanceState);
+
+        cordovaInterface = makeCordovaInterface();
+        if (savedInstanceState != null) {
+            cordovaInterface.restoreInstanceState(savedInstanceState);
+        }
+    }
+
+    protected void init() {
+        appView = makeWebView();
+        createViews();
+        if (!appView.isInitialized()) {
+            appView.init(cordovaInterface, pluginEntries, preferences);
+        }
+        cordovaInterface.onCordovaInit(appView.getPluginManager());
+
+        // Wire the hardware volume controls to control media if desired.
+        String volumePref = preferences.getString("DefaultVolumeStream", "");
+        if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
+            setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void loadConfig() {
+        ConfigXmlParser parser = new ConfigXmlParser();
+        parser.parse(this);
+        preferences = parser.getPreferences();
+        preferences.setPreferencesBundle(getIntent().getExtras());
+        launchUrl = parser.getLaunchUrl();
+        pluginEntries = parser.getPluginEntries();
+        Config.parser = parser;
+    }
+
+    //Suppressing warnings in AndroidStudio
+    @SuppressWarnings({"deprecation", "ResourceType"})
+    protected void createViews() {
+        //Why are we setting a constant as the ID? This should be investigated
+        appView.getView().setId(100);
+        appView.getView().setLayoutParams(new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        setContentView(appView.getView());
+
+        if (preferences.contains("BackgroundColor")) {
+            try {
+                int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
+                // Background of activity:
+                appView.getView().setBackgroundColor(backgroundColor);
+            }
+            catch (NumberFormatException e){
+                e.printStackTrace();
+            }
+        }
+
+        appView.getView().requestFocusFromTouch();
+    }
+
+    /**
+     * Construct the default web view object.
+     * <p/>
+     * Override this to customize the webview that is used.
+     */
+    protected CordovaWebView makeWebView() {
+        return new CordovaWebViewImpl(makeWebViewEngine());
+    }
+
+    protected CordovaWebViewEngine makeWebViewEngine() {
+        return CordovaWebViewImpl.createEngine(this, preferences);
+    }
+
+    protected CordovaInterfaceImpl makeCordovaInterface() {
+        return new CordovaInterfaceImpl(this) {
+            @Override
+            public Object onMessage(String id, Object data) {
+                // Plumb this to CordovaActivity.onMessage for backwards compatibility
+                return CordovaActivity.this.onMessage(id, data);
+            }
+        };
+    }
+
+    /**
+     * Load the url into the webview.
+     */
+    public void loadUrl(String url) {
+        if (appView == null) {
+            init();
+        }
+
+        // If keepRunning
+        this.keepRunning = preferences.getBoolean("KeepRunning", true);
+
+        appView.loadUrlIntoView(url, true);
+    }
+
+    /**
+     * Called when the system is about to start resuming a previous activity.
+     */
+    @Override
+    protected void onPause() {
+        super.onPause();
+        LOG.d(TAG, "Paused the activity.");
+
+        if (this.appView != null) {
+            // CB-9382 If there is an activity that started for result and main activity is waiting for callback
+            // result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
+            boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
+            this.appView.handlePause(keepRunning);
+        }
+    }
+
+    /**
+     * Called when the activity receives a new intent
+     */
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        //Forward to plugins
+        if (this.appView != null)
+            this.appView.onNewIntent(intent);
+    }
+
+    /**
+     * Called when the activity will start interacting with the user.
+     */
+    @Override
+    protected void onResume() {
+        super.onResume();
+        LOG.d(TAG, "Resumed the activity.");
+
+        if (this.appView == null) {
+            return;
+        }
+        // Force window to have focus, so application always
+        // receive user input. Workaround for some devices (Samsung Galaxy Note 3 at least)
+        this.getWindow().getDecorView().requestFocus();
+
+        this.appView.handleResume(this.keepRunning);
+    }
+
+    /**
+     * Called when the activity is no longer visible to the user.
+     */
+    @Override
+    protected void onStop() {
+        super.onStop();
+        LOG.d(TAG, "Stopped the activity.");
+
+        if (this.appView == null) {
+            return;
+        }
+        this.appView.handleStop();
+    }
+
+    /**
+     * Called when the activity is becoming visible to the user.
+     */
+    @Override
+    protected void onStart() {
+        super.onStart();
+        LOG.d(TAG, "Started the activity.");
+
+        if (this.appView == null) {
+            return;
+        }
+        this.appView.handleStart();
+    }
+
+    /**
+     * The final call you receive before your activity is destroyed.
+     */
+    @Override
+    public void onDestroy() {
+        LOG.d(TAG, "CordovaActivity.onDestroy()");
+        super.onDestroy();
+
+        if (this.appView != null) {
+            appView.handleDestroy();
+        }
+    }
+
+    /**
+     * Called when view focus is changed
+     */
+    @SuppressLint("InlinedApi")
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (hasFocus && immersiveMode) {
+            final int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+
+            getWindow().getDecorView().setSystemUiVisibility(uiOptions);
+        }
+    }
+
+    @SuppressLint("NewApi")
+    @Override
+    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
+        // Capture requestCode here so that it is captured in the setActivityResultCallback() case.
+        cordovaInterface.setActivityResultRequestCode(requestCode);
+        super.startActivityForResult(intent, requestCode, options);
+    }
+
+    /**
+     * Called when an activity you launched exits, giving you the requestCode you started it with,
+     * the resultCode it returned, and any additional data from it.
+     *
+     * @param requestCode The request code originally supplied to startActivityForResult(),
+     *                    allowing you to identify who this result came from.
+     * @param resultCode  The integer result code returned by the child activity through its setResult().
+     * @param intent      An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+     */
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        LOG.d(TAG, "Incoming Result. Request code = " + requestCode);
+        super.onActivityResult(requestCode, resultCode, intent);
+        cordovaInterface.onActivityResult(requestCode, resultCode, intent);
+    }
+
+    /**
+     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
+     * The errorCode parameter corresponds to one of the ERROR_* constants.
+     *
+     * @param errorCode   The error code corresponding to an ERROR_* value.
+     * @param description A String describing the error.
+     * @param failingUrl  The url that failed to load.
+     */
+    public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
+        final CordovaActivity me = this;
+
+        // If errorUrl specified, then load it
+        final String errorUrl = preferences.getString("errorUrl", null);
+        if ((errorUrl != null) && (!failingUrl.equals(errorUrl)) && (appView != null)) {
+            // Load URL on UI thread
+            me.runOnUiThread(new Runnable() {
+                public void run() {
+                    me.appView.showWebPage(errorUrl, false, true, null);
+                }
+            });
+        }
+        // If not, then display error dialog
+        else {
+            final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
+            me.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (exit) {
+                        me.appView.getView().setVisibility(View.GONE);
+                        me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Display an error dialog and optionally exit application.
+     */
+    public void displayError(final String title, final String message, final String button, final boolean exit) {
+        final CordovaActivity me = this;
+        me.runOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    AlertDialog.Builder dlg = new AlertDialog.Builder(me);
+                    dlg.setMessage(message);
+                    dlg.setTitle(title);
+                    dlg.setCancelable(false);
+                    dlg.setPositiveButton(button,
+                            new AlertDialog.OnClickListener() {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    dialog.dismiss();
+                                    if (exit) {
+                                        finish();
+                                    }
+                                }
+                            });
+                    dlg.create();
+                    dlg.show();
+                } catch (Exception e) {
+                    finish();
+                }
+            }
+        });
+    }
+
+    /*
+     * Hook in Cordova for menu plugins
+     */
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (appView != null) {
+            appView.getPluginManager().postMessage("onCreateOptionsMenu", menu);
+        }
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        if (appView != null) {
+            appView.getPluginManager().postMessage("onPrepareOptionsMenu", menu);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (appView != null) {
+            appView.getPluginManager().postMessage("onOptionsItemSelected", item);
+        }
+        return true;
+    }
+
+    /**
+     * Called when a message is sent to plugin.
+     *
+     * @param id   The message id
+     * @param data The message data
+     * @return Object or null
+     */
+    public Object onMessage(String id, Object data) {
+        if ("onReceivedError".equals(id)) {
+            JSONObject d = (JSONObject) data;
+            try {
+                this.onReceivedError(d.getInt("errorCode"), d.getString("description"), d.getString("url"));
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+        } else if ("exit".equals(id)) {
+            finish();
+        }
+        return null;
+    }
+
+    protected void onSaveInstanceState(Bundle outState) {
+        cordovaInterface.onSaveInstanceState(outState);
+        super.onSaveInstanceState(outState);
+    }
+
+    /**
+     * Called by the system when the device configuration changes while your activity is running.
+     *
+     * @param newConfig The new device configuration
+     */
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (this.appView == null) {
+            return;
+        }
+        PluginManager pm = this.appView.getPluginManager();
+        if (pm != null) {
+            pm.onConfigurationChanged(newConfig);
+        }
+    }
+
+    /**
+     * Called by the system when the user grants permissions
+     *
+     * @param requestCode
+     * @param permissions
+     * @param grantResults
+     */
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String permissions[],
+                                           int[] grantResults) {
+        try
+        {
+            cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
+        }
+        catch (JSONException e)
+        {
+            LOG.d(TAG, "JSONException: Parameters fed into the method are not valid");
+            e.printStackTrace();
+        }
+
+    }
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java
new file mode 100644
index 0000000..d40d26e
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java
@@ -0,0 +1,113 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.util.Base64;
+
+public class CordovaArgs {
+    private JSONArray baseArgs;
+
+    public CordovaArgs(JSONArray args) {
+        this.baseArgs = args;
+    }
+
+
+    // Pass through the basics to the base args.
+    public Object get(int index) throws JSONException {
+        return baseArgs.get(index);
+    }
+
+    public boolean getBoolean(int index) throws JSONException {
+        return baseArgs.getBoolean(index);
+    }
+
+    public double getDouble(int index) throws JSONException {
+        return baseArgs.getDouble(index);
+    }
+
+    public int getInt(int index) throws JSONException {
+        return baseArgs.getInt(index);
+    }
+
+    public JSONArray getJSONArray(int index) throws JSONException {
+        return baseArgs.getJSONArray(index);
+    }
+
+    public JSONObject getJSONObject(int index) throws JSONException {
+        return baseArgs.getJSONObject(index);
+    }
+
+    public long getLong(int index) throws JSONException {
+        return baseArgs.getLong(index);
+    }
+
+    public String getString(int index) throws JSONException {
+        return baseArgs.getString(index);
+    }
+
+
+    public Object opt(int index) {
+        return baseArgs.opt(index);
+    }
+
+    public boolean optBoolean(int index) {
+        return baseArgs.optBoolean(index);
+    }
+
+    public double optDouble(int index) {
+        return baseArgs.optDouble(index);
+    }
+
+    public int optInt(int index) {
+        return baseArgs.optInt(index);
+    }
+
+    public JSONArray optJSONArray(int index) {
+        return baseArgs.optJSONArray(index);
+    }
+
+    public JSONObject optJSONObject(int index) {
+        return baseArgs.optJSONObject(index);
+    }
+
+    public long optLong(int index) {
+        return baseArgs.optLong(index);
+    }
+
+    public String optString(int index) {
+        return baseArgs.optString(index);
+    }
+
+    public boolean isNull(int index) {
+        return baseArgs.isNull(index);
+    }
+
+
+    // The interesting custom helpers.
+    public byte[] getArrayBuffer(int index) throws JSONException {
+        String encoded = baseArgs.getString(index);
+        return Base64.decode(encoded, Base64.DEFAULT);
+    }
+}
+
+
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
new file mode 100644
index 0000000..28c407f
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
@@ -0,0 +1,187 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.annotation.SuppressLint;
+
+import java.security.SecureRandom;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+/**
+ * Contains APIs that the JS can call. All functions in here should also have
+ * an equivalent entry in CordovaChromeClient.java, and be added to
+ * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
+ */
+public class CordovaBridge {
+    private static final String LOG_TAG = "CordovaBridge";
+    private PluginManager pluginManager;
+    private NativeToJsMessageQueue jsMessageQueue;
+    private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
+
+    public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
+        this.pluginManager = pluginManager;
+        this.jsMessageQueue = jsMessageQueue;
+    }
+
+    public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
+        if (!verifySecret("exec()", bridgeSecret)) {
+            return null;
+        }
+        // If the arguments weren't received, send a message back to JS.  It will switch bridge modes and try again.  See CB-2666.
+        // We send a message meant specifically for this case.  It starts with "@" so no other message can be encoded into the same string.
+        if (arguments == null) {
+            return "@Null arguments.";
+        }
+
+        jsMessageQueue.setPaused(true);
+        try {
+            // Tell the resourceApi what thread the JS is running on.
+            CordovaResourceApi.jsThread = Thread.currentThread();
+
+            pluginManager.exec(service, action, callbackId, arguments);
+            String ret = null;
+            if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
+                ret = jsMessageQueue.popAndEncode(false);
+            }
+            return ret;
+        } catch (Throwable e) {
+            e.printStackTrace();
+            return "";
+        } finally {
+            jsMessageQueue.setPaused(false);
+        }
+    }
+
+    public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
+        if (!verifySecret("setNativeToJsBridgeMode()", bridgeSecret)) {
+            return;
+        }
+        jsMessageQueue.setBridgeMode(value);
+    }
+
+    public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
+        if (!verifySecret("retrieveJsMessages()", bridgeSecret)) {
+            return null;
+        }
+        return jsMessageQueue.popAndEncode(fromOnlineEvent);
+    }
+
+    private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
+        if (!jsMessageQueue.isBridgeEnabled()) {
+            if (bridgeSecret == -1) {
+                LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
+            } else {
+                LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
+            }
+            return false;
+        }
+        // Bridge secret wrong and bridge not due to it being from the previous page.
+        if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) {
+            LOG.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!");
+            clearBridgeSecret();
+            throw new IllegalAccessException();
+        }
+        return true;
+    }
+
+    /** Called on page transitions */
+    void clearBridgeSecret() {
+        expectedBridgeSecret = -1;
+    }
+
+    public boolean isSecretEstablished() {
+        return expectedBridgeSecret != -1;
+    }
+
+    /** Called by cordova.js to initialize the bridge. */
+    //On old Androids SecureRandom isn't really secure, this is the least of your problems if
+    //you're running Android 4.3 and below in 2017
+    @SuppressLint("TrulyRandom")
+    int generateBridgeSecret() {
+        SecureRandom randGen = new SecureRandom();
+        expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
+        return expectedBridgeSecret;
+    }
+
+    public void reset() {
+        jsMessageQueue.reset();
+        clearBridgeSecret();
+    }
+
+    public String promptOnJsPrompt(String origin, String message, String defaultValue) {
+        if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
+            JSONArray array;
+            try {
+                array = new JSONArray(defaultValue.substring(4));
+                int bridgeSecret = array.getInt(0);
+                String service = array.getString(1);
+                String action = array.getString(2);
+                String callbackId = array.getString(3);
+                String r = jsExec(bridgeSecret, service, action, callbackId, message);
+                return r == null ? "" : r;
+            } catch (JSONException e) {
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            }
+            return "";
+        }
+        // Sets the native->JS bridge mode.
+        else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
+            try {
+                int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
+                jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
+            } catch (NumberFormatException e){
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            }
+            return "";
+        }
+        // Polling for JavaScript messages
+        else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
+            int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
+            try {
+                String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
+                return r == null ? "" : r;
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+            }
+            return "";
+        }
+        else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
+            // Protect against random iframes being able to talk through the bridge.
+            // Trust only pages which the app would have been allowed to navigate to anyway.
+            if (pluginManager.shouldAllowBridgeAccess(origin)) {
+                // Enable the bridge
+                int bridgeMode = Integer.parseInt(defaultValue.substring(9));
+                jsMessageQueue.setBridgeMode(bridgeMode);
+                // Tell JS the bridge secret.
+                int secret = generateBridgeSecret();
+                return ""+secret;
+            } else {
+                LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
+            }
+            return "";
+        }
+        return null;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
new file mode 100644
index 0000000..ccda027
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
@@ -0,0 +1,105 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import android.annotation.SuppressLint;
+import android.webkit.ClientCertRequest;
+
+/**
+ * Implementation of the ICordovaClientCertRequest for Android WebView.
+ *
+ */
+public class CordovaClientCertRequest implements ICordovaClientCertRequest {
+
+    private final ClientCertRequest request;
+
+    public CordovaClientCertRequest(ClientCertRequest request) {
+        this.request = request;
+    }
+    
+    /**
+     * Cancel this request
+     */
+    @SuppressLint("NewApi")
+    public void cancel()
+    {
+        request.cancel();
+    }
+    
+    /*
+     * Returns the host name of the server requesting the certificate.
+     */
+    @SuppressLint("NewApi")
+    public String getHost()
+    {
+        return request.getHost();
+    }
+    
+    /*
+     * Returns the acceptable types of asymmetric keys (can be null).
+     */
+    @SuppressLint("NewApi")
+    public String[] getKeyTypes()
+    {
+        return request.getKeyTypes();
+    }
+    
+    /*
+     * Returns the port number of the server requesting the certificate.
+     */
+    @SuppressLint("NewApi")
+    public int getPort()
+    {
+        return request.getPort();
+    }
+    
+    /*
+     * Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
+     */
+    @SuppressLint("NewApi")
+    public Principal[] getPrincipals()
+    {
+        return request.getPrincipals();
+    }
+    
+    /*
+     * Ignore the request for now. Do not remember user's choice.
+     */
+    @SuppressLint("NewApi")
+    public void ignore()
+    {
+        request.ignore();
+    }
+    
+    /*
+     * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
+     * 
+     * @param privateKey The privateKey
+     * @param chain The certificate chain 
+     */
+    @SuppressLint("NewApi")
+    public void proceed(PrivateKey privateKey, X509Certificate[] chain)
+    {
+        request.proceed(privateKey, chain);
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
new file mode 100644
index 0000000..a219c99
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
@@ -0,0 +1,152 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.KeyEvent;
+import android.widget.EditText;
+
+/**
+ * Helper class for WebViews to implement prompt(), alert(), confirm() dialogs.
+ */
+public class CordovaDialogsHelper {
+    private final Context context;
+    private AlertDialog lastHandledDialog;
+
+    public CordovaDialogsHelper(Context context) {
+        this.context = context;
+    }
+
+    public void showAlert(String message, final Result result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+        dlg.setMessage(message);
+        dlg.setTitle("Alert");
+        //Don't let alerts break the back button
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new AlertDialog.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.gotResult(true, null);
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.gotResult(false, null);
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.gotResult(true, null);
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        lastHandledDialog = dlg.show();
+    }
+
+    public void showConfirm(String message, final Result result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+        dlg.setMessage(message);
+        dlg.setTitle("Confirm");
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.gotResult(true, null);
+                    }
+                });
+        dlg.setNegativeButton(android.R.string.cancel,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.gotResult(false, null);
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.gotResult(false, null);
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.gotResult(false, null);
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        lastHandledDialog = dlg.show();
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * Since we are hacking prompts for our own purposes, we should not be using them for
+     * this purpose, perhaps we should hack console.log to do this instead!
+     */
+    public void showPrompt(String message, String defaultValue, final Result result) {
+        // Returning false would also show a dialog, but the default one shows the origin (ugly).
+        AlertDialog.Builder dlg = new AlertDialog.Builder(context);
+        dlg.setMessage(message);
+        final EditText input = new EditText(context);
+        if (defaultValue != null) {
+            input.setText(defaultValue);
+        }
+        dlg.setView(input);
+        dlg.setCancelable(false);
+        dlg.setPositiveButton(android.R.string.ok,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        String userText = input.getText().toString();
+                        result.gotResult(true, userText);
+                    }
+                });
+        dlg.setNegativeButton(android.R.string.cancel,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.gotResult(false, null);
+                    }
+                });
+        lastHandledDialog = dlg.show();
+    }
+
+    public void destroyLastDialog(){
+        if (lastHandledDialog != null){
+            lastHandledDialog.cancel();
+        }
+    }
+
+    public interface Result {
+        public void gotResult(boolean success, String value);
+    }
+}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
new file mode 100644
index 0000000..724381e
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
@@ -0,0 +1,51 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.webkit.HttpAuthHandler;
+
+/**
+ * Specifies interface for HTTP auth handler object which is used to handle auth requests and
+ * specifying user credentials.
+ */
+public class CordovaHttpAuthHandler implements ICordovaHttpAuthHandler {
+
+    private final HttpAuthHandler handler;
+
+    public CordovaHttpAuthHandler(HttpAuthHandler handler) {
+        this.handler = handler;
+    }
+    
+    /**
+     * Instructs the WebView to cancel the authentication request.
+     */
+    public void cancel () {
+        this.handler.cancel();
+    }
+    
+    /**
+     * Instructs the WebView to proceed with the authentication with the given credentials.
+     * 
+     * @param username
+     * @param password
+     */
+    public void proceed (String username, String password) {
+        this.handler.proceed(username, password);
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
new file mode 100755
index 0000000..ff90683
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
@@ -0,0 +1,97 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import org.apache.cordova.CordovaPlugin;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * The Activity interface that is implemented by CordovaActivity.
+ * It is used to isolate plugin development, and remove dependency on entire Cordova library.
+ */
+public interface CordovaInterface {
+
+    /**
+     * Launch an activity for which you would like a result when it finished. When this activity exits,
+     * your onActivityResult() method will be called.
+     *
+     * @param command     The command object
+     * @param intent      The intent to start
+     * @param requestCode   The request code that is passed to callback to identify the activity
+     */
+    abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode);
+
+    /**
+     * Set the plugin to be called when a sub-activity exits.
+     *
+     * @param plugin      The plugin on which onActivityResult is to be called
+     */
+    abstract public void setActivityResultCallback(CordovaPlugin plugin);
+
+    /**
+     * Get the Android activity.
+     *
+     * If a custom engine lives outside of the Activity's lifecycle the return value may be null.
+     *
+     * @return the Activity
+     */
+    public abstract Activity getActivity();
+
+    /**
+     * Get the Android context.
+     *
+     * @return the Context
+     */
+    public Context getContext();
+
+    /**
+     * Called when a message is sent to plugin.
+     *
+     * @param id            The message id
+     * @param data          The message data
+     * @return              Object or null
+     */
+    public Object onMessage(String id, Object data);
+    
+    /**
+     * Returns a shared thread pool that can be used for background tasks.
+     */
+    public ExecutorService getThreadPool();
+
+    /**
+     * Sends a permission request to the activity for one permission.
+     */
+    public void requestPermission(CordovaPlugin plugin, int requestCode, String permission);
+
+    /**
+     * Sends a permission request to the activity for a group of permissions
+     */
+    public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions);
+
+    /**
+     * Check for a permission.  Returns true if the permission is granted, false otherwise.
+     */
+    public boolean hasPermission(String permission);
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
new file mode 100644
index 0000000..9a6e924
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
@@ -0,0 +1,249 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Pair;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Default implementation of CordovaInterface.
+ */
+public class CordovaInterfaceImpl implements CordovaInterface {
+    private static final String TAG = "CordovaInterfaceImpl";
+    protected Activity activity;
+    protected ExecutorService threadPool;
+    protected PluginManager pluginManager;
+
+    protected ActivityResultHolder savedResult;
+    protected CallbackMap permissionResultCallbacks;
+    protected CordovaPlugin activityResultCallback;
+    protected String initCallbackService;
+    protected int activityResultRequestCode;
+    protected boolean activityWasDestroyed = false;
+    protected Bundle savedPluginState;
+
+    public CordovaInterfaceImpl(Activity activity) {
+        this(activity, Executors.newCachedThreadPool());
+    }
+
+    public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) {
+        this.activity = activity;
+        this.threadPool = threadPool;
+        this.permissionResultCallbacks = new CallbackMap();
+    }
+
+    @Override
+    public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
+        setActivityResultCallback(command);
+        try {
+            activity.startActivityForResult(intent, requestCode);
+        } catch (RuntimeException e) { // E.g.: ActivityNotFoundException
+            activityResultCallback = null;
+            throw e;
+        }
+    }
+
+    @Override
+    public void setActivityResultCallback(CordovaPlugin plugin) {
+        // Cancel any previously pending activity.
+        if (activityResultCallback != null) {
+            activityResultCallback.onActivityResult(activityResultRequestCode, Activity.RESULT_CANCELED, null);
+        }
+        activityResultCallback = plugin;
+    }
+
+    @Override
+    public Activity getActivity() {
+        return activity;
+    }
+
+    @Override
+    public Context getContext() {
+        return activity;
+    }
+
+    @Override
+    public Object onMessage(String id, Object data) {
+        if ("exit".equals(id)) {
+            activity.finish();
+        }
+        return null;
+    }
+
+    @Override
+    public ExecutorService getThreadPool() {
+        return threadPool;
+    }
+
+    /**
+     * Dispatches any pending onActivityResult callbacks and sends the resume event if the
+     * Activity was destroyed by the OS.
+     */
+    public void onCordovaInit(PluginManager pluginManager) {
+        this.pluginManager = pluginManager;
+        if (savedResult != null) {
+            onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent);
+        } else if(activityWasDestroyed) {
+            // If there was no Activity result, we still need to send out the resume event if the
+            // Activity was destroyed by the OS
+            activityWasDestroyed = false;
+            if(pluginManager != null)
+            {
+                CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
+                if(appPlugin != null) {
+                    JSONObject obj = new JSONObject();
+                    try {
+                        obj.put("action", "resume");
+                    } catch (JSONException e) {
+                        LOG.e(TAG, "Failed to create event message", e);
+                    }
+                    appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, obj));
+                }
+            }
+
+        }
+    }
+
+    /**
+     * Routes the result to the awaiting plugin. Returns false if no plugin was waiting.
+     */
+    public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
+        CordovaPlugin callback = activityResultCallback;
+        if(callback == null && initCallbackService != null) {
+            // The application was restarted, but had defined an initial callback
+            // before being shut down.
+            savedResult = new ActivityResultHolder(requestCode, resultCode, intent);
+            if (pluginManager != null) {
+                callback = pluginManager.getPlugin(initCallbackService);
+                if(callback != null) {
+                    callback.onRestoreStateForActivityResult(savedPluginState.getBundle(callback.getServiceName()),
+                            new ResumeCallback(callback.getServiceName(), pluginManager));
+                }
+            }
+        }
+        activityResultCallback = null;
+
+        if (callback != null) {
+            LOG.d(TAG, "Sending activity result to plugin");
+            initCallbackService = null;
+            savedResult = null;
+            callback.onActivityResult(requestCode, resultCode, intent);
+            return true;
+        }
+        LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : "."));
+        return false;
+    }
+
+    /**
+     * Call this from your startActivityForResult() overload. This is required to catch the case
+     * where plugins use Activity.startActivityForResult() + CordovaInterface.setActivityResultCallback()
+     * rather than CordovaInterface.startActivityForResult().
+     */
+    public void setActivityResultRequestCode(int requestCode) {
+        activityResultRequestCode = requestCode;
+    }
+
+    /**
+     * Saves parameters for startActivityForResult().
+     */
+    public void onSaveInstanceState(Bundle outState) {
+        if (activityResultCallback != null) {
+            String serviceName = activityResultCallback.getServiceName();
+            outState.putString("callbackService", serviceName);
+        }
+        if(pluginManager != null){
+            outState.putBundle("plugin", pluginManager.onSaveInstanceState());
+        }
+
+    }
+
+    /**
+     * Call this from onCreate() so that any saved startActivityForResult parameters will be restored.
+     */
+    public void restoreInstanceState(Bundle savedInstanceState) {
+        initCallbackService = savedInstanceState.getString("callbackService");
+        savedPluginState = savedInstanceState.getBundle("plugin");
+        activityWasDestroyed = true;
+    }
+
+    private static class ActivityResultHolder {
+        private int requestCode;
+        private int resultCode;
+        private Intent intent;
+
+        public ActivityResultHolder(int requestCode, int resultCode, Intent intent) {
+            this.requestCode = requestCode;
+            this.resultCode = resultCode;
+            this.intent = intent;
+        }
+    }
+
+    /**
+     * Called by the system when the user grants permissions
+     *
+     * @param requestCode
+     * @param permissions
+     * @param grantResults
+     */
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+        Pair<CordovaPlugin, Integer> callback = permissionResultCallbacks.getAndRemoveCallback(requestCode);
+        if(callback != null) {
+            callback.first.onRequestPermissionResult(callback.second, permissions, grantResults);
+        }
+    }
+
+    public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
+        String[] permissions = new String [1];
+        permissions[0] = permission;
+        requestPermissions(plugin, requestCode, permissions);
+    }
+
+        @SuppressLint("NewApi")
+    public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) {
+        int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode);
+        getActivity().requestPermissions(permissions, mappedRequestCode);
+    }
+
+    public boolean hasPermission(String permission)
+    {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+        {
+            int result = activity.checkSelfPermission(permission);
+            return PackageManager.PERMISSION_GRANTED == result;
+        }
+        else
+        {
+            return true;
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
new file mode 100644
index 0000000..41af1db
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
@@ -0,0 +1,422 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CallbackContext;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Plugins must extend this class and override one of the execute methods.
+ */
+public class CordovaPlugin {
+    public CordovaWebView webView;
+    public CordovaInterface cordova;
+    protected CordovaPreferences preferences;
+    private String serviceName;
+
+    /**
+     * Call this after constructing to initialize the plugin.
+     * Final because we want to be able to change args without breaking plugins.
+     */
+    public final void privateInitialize(String serviceName, CordovaInterface cordova, CordovaWebView webView, CordovaPreferences preferences) {
+        assert this.cordova == null;
+        this.serviceName = serviceName;
+        this.cordova = cordova;
+        this.webView = webView;
+        this.preferences = preferences;
+        initialize(cordova, webView);
+        pluginInitialize();
+    }
+
+    /**
+     * Called after plugin construction and fields have been initialized.
+     * Prefer to use pluginInitialize instead since there is no value in
+     * having parameters on the initialize() function.
+     */
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+    }
+
+    /**
+     * Called after plugin construction and fields have been initialized.
+     */
+    protected void pluginInitialize() {
+    }
+
+    /**
+     * Returns the plugin's service name (what you'd use when calling pluginManger.getPlugin())
+     */
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    /**
+     * Executes the request.
+     *
+     * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+     *     cordova.getThreadPool().execute(runnable);
+     *
+     * To run on the UI thread, use:
+     *     cordova.getActivity().runOnUiThread(runnable);
+     *
+     * @param action          The action to execute.
+     * @param rawArgs         The exec() arguments in JSON form.
+     * @param callbackContext The callback context used when calling back into JavaScript.
+     * @return                Whether the action was valid.
+     */
+    public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
+        JSONArray args = new JSONArray(rawArgs);
+        return execute(action, args, callbackContext);
+    }
+
+    /**
+     * Executes the request.
+     *
+     * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+     *     cordova.getThreadPool().execute(runnable);
+     *
+     * To run on the UI thread, use:
+     *     cordova.getActivity().runOnUiThread(runnable);
+     *
+     * @param action          The action to execute.
+     * @param args            The exec() arguments.
+     * @param callbackContext The callback context used when calling back into JavaScript.
+     * @return                Whether the action was valid.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+        CordovaArgs cordovaArgs = new CordovaArgs(args);
+        return execute(action, cordovaArgs, callbackContext);
+    }
+
+    /**
+     * Executes the request.
+     *
+     * This method is called from the WebView thread. To do a non-trivial amount of work, use:
+     *     cordova.getThreadPool().execute(runnable);
+     *
+     * To run on the UI thread, use:
+     *     cordova.getActivity().runOnUiThread(runnable);
+     *
+     * @param action          The action to execute.
+     * @param args            The exec() arguments, wrapped with some Cordova helpers.
+     * @param callbackContext The callback context used when calling back into JavaScript.
+     * @return                Whether the action was valid.
+     */
+    public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
+        return false;
+    }
+
+    /**
+     * Called when the system is about to start resuming a previous activity.
+     *
+     * @param multitasking		Flag indicating if multitasking is turned on for app
+     */
+    public void onPause(boolean multitasking) {
+    }
+
+    /**
+     * Called when the activity will start interacting with the user.
+     *
+     * @param multitasking		Flag indicating if multitasking is turned on for app
+     */
+    public void onResume(boolean multitasking) {
+    }
+
+    /**
+     * Called when the activity is becoming visible to the user.
+     */
+    public void onStart() {
+    }
+
+    /**
+     * Called when the activity is no longer visible to the user.
+     */
+    public void onStop() {
+    }
+
+    /**
+     * Called when the activity receives a new intent.
+     */
+    public void onNewIntent(Intent intent) {
+    }
+
+    /**
+     * The final call you receive before your activity is destroyed.
+     */
+    public void onDestroy() {
+    }
+
+    /**
+     * Called when the Activity is being destroyed (e.g. if a plugin calls out to an external
+     * Activity and the OS kills the CordovaActivity in the background). The plugin should save its
+     * state in this method only if it is awaiting the result of an external Activity and needs
+     * to preserve some information so as to handle that result; onRestoreStateForActivityResult()
+     * will only be called if the plugin is the recipient of an Activity result
+     *
+     * @return  Bundle containing the state of the plugin or null if state does not need to be saved
+     */
+    public Bundle onSaveInstanceState() {
+        return null;
+    }
+
+    /**
+     * Called when a plugin is the recipient of an Activity result after the CordovaActivity has
+     * been destroyed. The Bundle will be the same as the one the plugin returned in
+     * onSaveInstanceState()
+     *
+     * @param state             Bundle containing the state of the plugin
+     * @param callbackContext   Replacement Context to return the plugin result to
+     */
+    public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {}
+
+    /**
+     * Called when a message is sent to plugin.
+     *
+     * @param id            The message id
+     * @param data          The message data
+     * @return              Object to stop propagation or null
+     */
+    public Object onMessage(String id, Object data) {
+        return null;
+    }
+
+    /**
+     * Called when an activity you launched exits, giving you the requestCode you started it with,
+     * the resultCode it returned, and any additional data from it.
+     *
+     * @param requestCode   The request code originally supplied to startActivityForResult(),
+     *                      allowing you to identify who this result came from.
+     * @param resultCode    The integer result code returned by the child activity through its setResult().
+     * @param intent        An Intent, which can return result data to the caller (various data can be
+     *                      attached to Intent "extras").
+     */
+    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+    }
+
+    /**
+     * Hook for blocking the loading of external resources.
+     *
+     * This will be called when the WebView's shouldInterceptRequest wants to
+     * know whether to open a connection to an external resource. Return false
+     * to block the request: if any plugin returns false, Cordova will block
+     * the request. If all plugins return null, the default policy will be
+     * enforced. If at least one plugin returns true, and no plugins return
+     * false, then the request will proceed.
+     *
+     * Note that this only affects resource requests which are routed through
+     * WebViewClient.shouldInterceptRequest, such as XMLHttpRequest requests and
+     * img tag loads. WebSockets and media requests (such as <video> and <audio>
+     * tags) are not affected by this method. Use CSP headers to control access
+     * to such resources.
+     */
+    public Boolean shouldAllowRequest(String url) {
+        return null;
+    }
+
+    /**
+     * Hook for blocking navigation by the Cordova WebView. This applies both to top-level and
+     * iframe navigations.
+     *
+     * This will be called when the WebView's needs to know whether to navigate
+     * to a new page. Return false to block the navigation: if any plugin
+     * returns false, Cordova will block the navigation. If all plugins return
+     * null, the default policy will be enforced. It at least one plugin returns
+     * true, and no plugins return false, then the navigation will proceed.
+     */
+    public Boolean shouldAllowNavigation(String url) {
+        return null;
+    }
+
+    /**
+     * Hook for allowing page to call exec(). By default, this returns the result of
+     * shouldAllowNavigation(). It's generally unsafe to allow untrusted content to be loaded
+     * into a CordovaWebView, even within an iframe, so it's best not to touch this.
+     */
+    public Boolean shouldAllowBridgeAccess(String url) {
+        return shouldAllowNavigation(url);
+    }
+
+    /**
+     * Hook for blocking the launching of Intents by the Cordova application.
+     *
+     * This will be called when the WebView will not navigate to a page, but
+     * could launch an intent to handle the URL. Return false to block this: if
+     * any plugin returns false, Cordova will block the navigation. If all
+     * plugins return null, the default policy will be enforced. If at least one
+     * plugin returns true, and no plugins return false, then the URL will be
+     * opened.
+     */
+    public Boolean shouldOpenExternalUrl(String url) {
+        return null;
+    }
+
+    /**
+     * Allows plugins to handle a link being clicked. Return true here to cancel the navigation.
+     *
+     * @param url           The URL that is trying to be loaded in the Cordova webview.
+     * @return              Return true to prevent the URL from loading. Default is false.
+     */
+    public boolean onOverrideUrlLoading(String url) {
+        return false;
+    }
+
+    /**
+     * Hook for redirecting requests. Applies to WebView requests as well as requests made by plugins.
+     * To handle the request directly, return a URI in the form:
+     *
+     *    cdvplugin://pluginId/...
+     *
+     * And implement handleOpenForRead().
+     * To make this easier, use the toPluginUri() and fromPluginUri() helpers:
+     *
+     *     public Uri remapUri(Uri uri) { return toPluginUri(uri); }
+     *
+     *     public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
+     *         Uri origUri = fromPluginUri(uri);
+     *         ...
+     *     }
+     */
+    public Uri remapUri(Uri uri) {
+        return null;
+    }
+
+    /**
+     * Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.
+     * Should never return null.
+     * Added in cordova-android@4.0.0
+     */
+    public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
+        throw new FileNotFoundException("Plugin can't handle uri: " + uri);
+    }
+
+    /**
+     * Refer to remapUri()
+     * Added in cordova-android@4.0.0
+     */
+    protected Uri toPluginUri(Uri origUri) {
+        return new Uri.Builder()
+            .scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)
+            .authority(serviceName)
+            .appendQueryParameter("origUri", origUri.toString())
+            .build();
+    }
+
+    /**
+     * Refer to remapUri()
+     * Added in cordova-android@4.0.0
+     */
+    protected Uri fromPluginUri(Uri pluginUri) {
+        return Uri.parse(pluginUri.getQueryParameter("origUri"));
+    }
+
+    /**
+     * Called when the WebView does a top-level navigation or refreshes.
+     *
+     * Plugins should stop any long-running processes and clean up internal state.
+     *
+     * Does nothing by default.
+     */
+    public void onReset() {
+    }
+
+    /**
+     * Called when the system received an HTTP authentication request. Plugin can use
+     * the supplied HttpAuthHandler to process this auth challenge.
+     *
+     * @param view              The WebView that is initiating the callback
+     * @param handler           The HttpAuthHandler used to set the WebView's response
+     * @param host              The host requiring authentication
+     * @param realm             The realm for which authentication is required
+     *
+     * @return                  Returns True if plugin will resolve this auth challenge, otherwise False
+     *
+     */
+    public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
+        return false;
+    }
+
+    /**
+     * Called when he system received an SSL client certificate request.  Plugin can use
+     * the supplied ClientCertRequest to process this certificate challenge.
+     *
+     * @param view              The WebView that is initiating the callback
+     * @param request           The client certificate request
+     *
+     * @return                  Returns True if plugin will resolve this auth challenge, otherwise False
+     *
+     */
+    public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
+        return false;
+    }
+
+    /**
+     * Called by the system when the device configuration changes while your activity is running.
+     *
+     * @param newConfig		The new device configuration
+     */
+    public void onConfigurationChanged(Configuration newConfig) {
+    }
+
+    /**
+     * Called by the Plugin Manager when we need to actually request permissions
+     *
+     * @param requestCode   Passed to the activity to track the request
+     *
+     * @return              Returns the permission that was stored in the plugin
+     */
+
+    public void requestPermissions(int requestCode) {
+    }
+
+    /*
+     * Called by the WebView implementation to check for geolocation permissions, can be used
+     * by other Java methods in the event that a plugin is using this as a dependency.
+     *
+     * @return          Returns true if the plugin has all the permissions it needs to operate.
+     */
+
+    public boolean hasPermisssion() {
+        return true;
+    }
+
+    /**
+     * Called by the system when the user grants permissions
+     *
+     * @param requestCode
+     * @param permissions
+     * @param grantResults
+     */
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
new file mode 100644
index 0000000..4dbc93e
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
@@ -0,0 +1,101 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.cordova.LOG;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CordovaPreferences {
+    private HashMap<String, String> prefs = new HashMap<String, String>(20);
+    private Bundle preferencesBundleExtras;
+
+    public void setPreferencesBundle(Bundle extras) {
+        preferencesBundleExtras = extras;
+    }
+
+    public void set(String name, String value) {
+        prefs.put(name.toLowerCase(Locale.ENGLISH), value);
+    }
+
+    public void set(String name, boolean value) {
+        set(name, "" + value);
+    }
+
+    public void set(String name, int value) {
+        set(name, "" + value);
+    }
+    
+    public void set(String name, double value) {
+        set(name, "" + value);
+    }
+    
+    public Map<String, String> getAll() {
+        return prefs;
+    }
+
+    public boolean getBoolean(String name, boolean defaultValue) {
+        name = name.toLowerCase(Locale.ENGLISH);
+        String value = prefs.get(name);
+        if (value != null) {
+            return Boolean.parseBoolean(value);
+        }
+        return defaultValue;
+    }
+
+    // Added in 4.0.0
+    public boolean contains(String name) {
+        return getString(name, null) != null;
+    }
+
+    public int getInteger(String name, int defaultValue) {
+        name = name.toLowerCase(Locale.ENGLISH);
+        String value = prefs.get(name);
+        if (value != null) {
+            // Use Integer.decode() can't handle it if the highest bit is set.
+            return (int)(long)Long.decode(value);
+        }
+        return defaultValue;
+    }
+
+    public double getDouble(String name, double defaultValue) {
+        name = name.toLowerCase(Locale.ENGLISH);
+        String value = prefs.get(name);
+        if (value != null) {
+            return Double.valueOf(value);
+        }
+        return defaultValue;
+    }
+
+    public String getString(String name, String defaultValue) {
+        name = name.toLowerCase(Locale.ENGLISH);
+        String value = prefs.get(name);
+        if (value != null) {
+            return value;
+        }
+        return defaultValue;
+    }
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
new file mode 100644
index 0000000..3c438e2
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
@@ -0,0 +1,472 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Looper;
+import android.util.Base64;
+import android.webkit.MimeTypeMap;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.channels.FileChannel;
+import java.util.Locale;
+
+/**
+ * What this class provides:
+ * 1. Helpers for reading & writing to URLs.
+ *   - E.g. handles assets, resources, content providers, files, data URIs, http[s]
+ *   - E.g. Can be used to query for mime-type & content length.
+ *
+ * 2. To allow plugins to redirect URLs (via remapUrl).
+ *   - All plugins should call remapUrl() on URLs they receive from JS *before*
+ *     passing the URL onto other utility functions in this class.
+ *   - For an example usage of this, refer to the org.apache.cordova.file plugin.
+ *
+ * Future Work:
+ *   - Consider using a Cursor to query content URLs for their size (like the file plugin does).
+ *   - Allow plugins to remapUri to "cdv-plugin://plugin-name/foo", which CordovaResourceApi
+ *     would then delegate to pluginManager.getPlugin(plugin-name).openForRead(url)
+ *     - Currently, plugins *can* do this by remapping to a data: URL, but it's inefficient
+ *       for large payloads.
+ */
+public class CordovaResourceApi {
+    @SuppressWarnings("unused")
+    private static final String LOG_TAG = "CordovaResourceApi";
+
+    public static final int URI_TYPE_FILE = 0;
+    public static final int URI_TYPE_ASSET = 1;
+    public static final int URI_TYPE_CONTENT = 2;
+    public static final int URI_TYPE_RESOURCE = 3;
+    public static final int URI_TYPE_DATA = 4;
+    public static final int URI_TYPE_HTTP = 5;
+    public static final int URI_TYPE_HTTPS = 6;
+    public static final int URI_TYPE_PLUGIN = 7;
+    public static final int URI_TYPE_UNKNOWN = -1;
+
+    public static final String PLUGIN_URI_SCHEME = "cdvplugin";
+
+    private static final String[] LOCAL_FILE_PROJECTION = { "_data" };
+    
+    public static Thread jsThread;
+
+    private final AssetManager assetManager;
+    private final ContentResolver contentResolver;
+    private final PluginManager pluginManager;
+    private boolean threadCheckingEnabled = true;
+
+
+    public CordovaResourceApi(Context context, PluginManager pluginManager) {
+        this.contentResolver = context.getContentResolver();
+        this.assetManager = context.getAssets();
+        this.pluginManager = pluginManager;
+    }
+    
+    public void setThreadCheckingEnabled(boolean value) {
+        threadCheckingEnabled = value;
+    }
+
+    public boolean isThreadCheckingEnabled() {
+        return threadCheckingEnabled;
+    }
+    
+    
+    public static int getUriType(Uri uri) {
+        assertNonRelative(uri);
+        String scheme = uri.getScheme();
+        if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
+            return URI_TYPE_CONTENT;
+        }
+        if (ContentResolver.SCHEME_ANDROID_RESOURCE.equalsIgnoreCase(scheme)) {
+            return URI_TYPE_RESOURCE;
+        }
+        if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
+            if (uri.getPath().startsWith("/android_asset/")) {
+                return URI_TYPE_ASSET;
+            }
+            return URI_TYPE_FILE;
+        }
+        if ("data".equalsIgnoreCase(scheme)) {
+            return URI_TYPE_DATA;
+        }
+        if ("http".equalsIgnoreCase(scheme)) {
+            return URI_TYPE_HTTP;
+        }
+        if ("https".equalsIgnoreCase(scheme)) {
+            return URI_TYPE_HTTPS;
+        }
+        if (PLUGIN_URI_SCHEME.equalsIgnoreCase(scheme)) {
+            return URI_TYPE_PLUGIN;
+        }
+        return URI_TYPE_UNKNOWN;
+    }
+    
+    public Uri remapUri(Uri uri) {
+        assertNonRelative(uri);
+        Uri pluginUri = pluginManager.remapUri(uri);
+        return pluginUri != null ? pluginUri : uri;
+    }
+
+    public String remapPath(String path) {
+        return remapUri(Uri.fromFile(new File(path))).getPath();
+    }
+    
+    /**
+     * Returns a File that points to the resource, or null if the resource
+     * is not on the local filesystem.
+     */
+    public File mapUriToFile(Uri uri) {
+        assertBackgroundThread();
+        switch (getUriType(uri)) {
+            case URI_TYPE_FILE:
+                return new File(uri.getPath());
+            case URI_TYPE_CONTENT: {
+                Cursor cursor = contentResolver.query(uri, LOCAL_FILE_PROJECTION, null, null, null);
+                if (cursor != null) {
+                    try {
+                        int columnIndex = cursor.getColumnIndex(LOCAL_FILE_PROJECTION[0]);
+                        if (columnIndex != -1 && cursor.getCount() > 0) {
+                            cursor.moveToFirst();
+                            String realPath = cursor.getString(columnIndex);
+                            if (realPath != null) {
+                                return new File(realPath);
+                            }
+                        }
+                    } finally {
+                        cursor.close();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    public String getMimeType(Uri uri) {
+        switch (getUriType(uri)) {
+            case URI_TYPE_FILE:
+            case URI_TYPE_ASSET:
+                return getMimeTypeFromPath(uri.getPath());
+            case URI_TYPE_CONTENT:
+            case URI_TYPE_RESOURCE:
+                return contentResolver.getType(uri);
+            case URI_TYPE_DATA: {
+                return getDataUriMimeType(uri);
+            }
+            case URI_TYPE_HTTP:
+            case URI_TYPE_HTTPS: {
+                try {
+                    HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
+                    conn.setDoInput(false);
+                    conn.setRequestMethod("HEAD");
+                    String mimeType = conn.getHeaderField("Content-Type");
+                    if (mimeType != null) {
+                        mimeType = mimeType.split(";")[0];
+                    }
+                    return mimeType;
+                } catch (IOException e) {
+                }
+            }
+        }
+        
+        return null;
+    }
+    
+    
+    //This already exists
+    private String getMimeTypeFromPath(String path) {
+        String extension = path;
+        int lastDot = extension.lastIndexOf('.');
+        if (lastDot != -1) {
+            extension = extension.substring(lastDot + 1);
+        }
+        // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
+        extension = extension.toLowerCase(Locale.getDefault());
+        if (extension.equals("3ga")) {
+            return "audio/3gpp";
+        } else if (extension.equals("js")) {
+            // Missing from the map :(.
+            return "text/javascript";
+        }
+        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+    }
+    
+    /**
+     * Opens a stream to the given URI, also providing the MIME type & length.
+     * @return Never returns null.
+     * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+     *     resolved before being passed into this function.
+     * @throws Throws an IOException if the URI cannot be opened.
+     * @throws Throws an IllegalStateException if called on a foreground thread.
+     */
+    public OpenForReadResult openForRead(Uri uri) throws IOException {
+        return openForRead(uri, false);
+    }
+
+    /**
+     * Opens a stream to the given URI, also providing the MIME type & length.
+     * @return Never returns null.
+     * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+     *     resolved before being passed into this function.
+     * @throws Throws an IOException if the URI cannot be opened.
+     * @throws Throws an IllegalStateException if called on a foreground thread and skipThreadCheck is false.
+     */
+    public OpenForReadResult openForRead(Uri uri, boolean skipThreadCheck) throws IOException {
+        if (!skipThreadCheck) {
+            assertBackgroundThread();
+        }
+        switch (getUriType(uri)) {
+            case URI_TYPE_FILE: {
+                FileInputStream inputStream = new FileInputStream(uri.getPath());
+                String mimeType = getMimeTypeFromPath(uri.getPath());
+                long length = inputStream.getChannel().size();
+                return new OpenForReadResult(uri, inputStream, mimeType, length, null);
+            }
+            case URI_TYPE_ASSET: {
+                String assetPath = uri.getPath().substring(15);
+                AssetFileDescriptor assetFd = null;
+                InputStream inputStream;
+                long length = -1;
+                try {
+                    assetFd = assetManager.openFd(assetPath);
+                    inputStream = assetFd.createInputStream();
+                    length = assetFd.getLength();
+                } catch (FileNotFoundException e) {
+                    // Will occur if the file is compressed.
+                    inputStream = assetManager.open(assetPath);
+                    length = inputStream.available();
+                }
+                String mimeType = getMimeTypeFromPath(assetPath);
+                return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
+            }
+            case URI_TYPE_CONTENT:
+            case URI_TYPE_RESOURCE: {
+                String mimeType = contentResolver.getType(uri);
+                AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, "r");
+                InputStream inputStream = assetFd.createInputStream();
+                long length = assetFd.getLength();
+                return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
+            }
+            case URI_TYPE_DATA: {
+                OpenForReadResult ret = readDataUri(uri);
+                if (ret == null) {
+                    break;
+                }
+                return ret;
+            }
+            case URI_TYPE_HTTP:
+            case URI_TYPE_HTTPS: {
+                HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
+                conn.setDoInput(true);
+                String mimeType = conn.getHeaderField("Content-Type");
+                if (mimeType != null) {
+                    mimeType = mimeType.split(";")[0];
+                }
+                int length = conn.getContentLength();
+                InputStream inputStream = conn.getInputStream();
+                return new OpenForReadResult(uri, inputStream, mimeType, length, null);
+            }
+            case URI_TYPE_PLUGIN: {
+                String pluginId = uri.getHost();
+                CordovaPlugin plugin = pluginManager.getPlugin(pluginId);
+                if (plugin == null) {
+                    throw new FileNotFoundException("Invalid plugin ID in URI: " + uri);
+                }
+                return plugin.handleOpenForRead(uri);
+            }
+        }
+        throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
+    }
+
+    public OutputStream openOutputStream(Uri uri) throws IOException {
+        return openOutputStream(uri, false);
+    }
+
+    /**
+     * Opens a stream to the given URI.
+     * @return Never returns null.
+     * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
+     *     resolved before being passed into this function.
+     * @throws Throws an IOException if the URI cannot be opened.
+     */
+    public OutputStream openOutputStream(Uri uri, boolean append) throws IOException {
+        assertBackgroundThread();
+        switch (getUriType(uri)) {
+            case URI_TYPE_FILE: {
+                File localFile = new File(uri.getPath());
+                File parent = localFile.getParentFile();
+                if (parent != null) {
+                    parent.mkdirs();
+                }
+                return new FileOutputStream(localFile, append);
+            }
+            case URI_TYPE_CONTENT:
+            case URI_TYPE_RESOURCE: {
+                AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, append ? "wa" : "w");
+                return assetFd.createOutputStream();
+            }
+        }
+        throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
+    }
+
+    public HttpURLConnection createHttpConnection(Uri uri) throws IOException {
+        assertBackgroundThread();
+        return (HttpURLConnection)new URL(uri.toString()).openConnection();
+    }
+    
+    // Copies the input to the output in the most efficient manner possible.
+    // Closes both streams.
+    public void copyResource(OpenForReadResult input, OutputStream outputStream) throws IOException {
+        assertBackgroundThread();
+        try {
+            InputStream inputStream = input.inputStream;
+            if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
+                FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
+                FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
+                long offset = 0;
+                long length = input.length;
+                if (input.assetFd != null) {
+                    offset = input.assetFd.getStartOffset();
+                }
+                // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
+                // position first.
+                inChannel.position(offset);
+                outChannel.transferFrom(inChannel, 0, length);
+            } else {
+                final int BUFFER_SIZE = 8192;
+                byte[] buffer = new byte[BUFFER_SIZE];
+                
+                for (;;) {
+                    int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+                    
+                    if (bytesRead <= 0) {
+                        break;
+                    }
+                    outputStream.write(buffer, 0, bytesRead);
+                }
+            }            
+        } finally {
+            input.inputStream.close();
+            if (outputStream != null) {
+                outputStream.close();
+            }
+        }
+    }
+
+    public void copyResource(Uri sourceUri, OutputStream outputStream) throws IOException {
+        copyResource(openForRead(sourceUri), outputStream);
+    }
+
+    // Added in 3.5.0.
+    public void copyResource(Uri sourceUri, Uri dstUri) throws IOException {
+        copyResource(openForRead(sourceUri), openOutputStream(dstUri));
+    }
+    
+    private void assertBackgroundThread() {
+        if (threadCheckingEnabled) {
+            Thread curThread = Thread.currentThread();
+            if (curThread == Looper.getMainLooper().getThread()) {
+                throw new IllegalStateException("Do not perform IO operations on the UI thread. Use CordovaInterface.getThreadPool() instead.");
+            }
+            if (curThread == jsThread) {
+                throw new IllegalStateException("Tried to perform an IO operation on the WebCore thread. Use CordovaInterface.getThreadPool() instead.");
+            }
+        }
+    }
+    
+    private String getDataUriMimeType(Uri uri) {
+        String uriAsString = uri.getSchemeSpecificPart();
+        int commaPos = uriAsString.indexOf(',');
+        if (commaPos == -1) {
+            return null;
+        }
+        String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
+        if (mimeParts.length > 0) {
+            return mimeParts[0];
+        }
+        return null;
+    }
+
+    private OpenForReadResult readDataUri(Uri uri) {
+        String uriAsString = uri.getSchemeSpecificPart();
+        int commaPos = uriAsString.indexOf(',');
+        if (commaPos == -1) {
+            return null;
+        }
+        String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
+        String contentType = null;
+        boolean base64 = false;
+        if (mimeParts.length > 0) {
+            contentType = mimeParts[0];
+        }
+        for (int i = 1; i < mimeParts.length; ++i) {
+            if ("base64".equalsIgnoreCase(mimeParts[i])) {
+                base64 = true;
+            }
+        }
+        String dataPartAsString = uriAsString.substring(commaPos + 1);
+        byte[] data;
+        if (base64) {
+            data = Base64.decode(dataPartAsString, Base64.DEFAULT);
+        } else {
+            try {
+                data = dataPartAsString.getBytes("UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                data = dataPartAsString.getBytes();
+            }
+        }
+        InputStream inputStream = new ByteArrayInputStream(data);
+        return new OpenForReadResult(uri, inputStream, contentType, data.length, null);
+    }
+    
+    private static void assertNonRelative(Uri uri) {
+        if (!uri.isAbsolute()) {
+            throw new IllegalArgumentException("Relative URIs are not supported.");
+        }
+    }
+    
+    public static final class OpenForReadResult {
+        public final Uri uri;
+        public final InputStream inputStream;
+        public final String mimeType;
+        public final long length;
+        public final AssetFileDescriptor assetFd;
+        
+        public OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
+            this.uri = uri;
+            this.inputStream = inputStream;
+            this.mimeType = mimeType;
+            this.length = length;
+            this.assetFd = assetFd;
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
new file mode 100644
index 0000000..20aea80
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
@@ -0,0 +1,142 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+         http://www.apache.org/licenses/LICENSE-2.0
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.util.List;
+import java.util.Map;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.webkit.WebChromeClient.CustomViewCallback;
+
+/**
+ * Main interface for interacting with a Cordova webview - implemented by CordovaWebViewImpl.
+ * This is an interface so that it can be easily mocked in tests.
+ * Methods may be added to this interface without a major version bump, as plugins & embedders
+ * are not expected to implement it.
+ */
+public interface CordovaWebView {
+    public static final String CORDOVA_VERSION = "8.0.0";
+
+    void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);
+
+    boolean isInitialized();
+
+    View getView();
+
+    void loadUrlIntoView(String url, boolean recreatePlugins);
+
+    void stopLoading();
+
+    boolean canGoBack();
+
+    void clearCache();
+
+    /** Use parameter-less overload */
+    @Deprecated
+    void clearCache(boolean b);
+
+    void clearHistory();
+
+    boolean backHistory();
+
+    void handlePause(boolean keepRunning);
+
+    void onNewIntent(Intent intent);
+
+    void handleResume(boolean keepRunning);
+
+    void handleStart();
+
+    void handleStop();
+
+    void handleDestroy();
+
+    /**
+     * Send JavaScript statement back to JavaScript.
+     *
+     * Deprecated (https://issues.apache.org/jira/browse/CB-6851)
+     * Instead of executing snippets of JS, you should use the exec bridge
+     * to create a Java->JS communication channel.
+     * To do this:
+     * 1. Within plugin.xml (to have your JS run before deviceready):
+     *    <js-module><runs/></js-module>
+     * 2. Within your .js (call exec on start-up):
+     *    require('cordova/channel').onCordovaReady.subscribe(function() {
+     *      require('cordova/exec')(win, null, 'Plugin', 'method', []);
+     *      function win(message) {
+     *        ... process message from java here ...
+     *      }
+     *    });
+     * 3. Within your .java:
+     *    PluginResult dataResult = new PluginResult(PluginResult.Status.OK, CODE);
+     *    dataResult.setKeepCallback(true);
+     *    savedCallbackContext.sendPluginResult(dataResult);
+     */
+    @Deprecated
+    void sendJavascript(String statememt);
+
+    /**
+     * Load the specified URL in the Cordova webview or a new browser instance.
+     *
+     * NOTE: If openExternal is false, only whitelisted URLs can be loaded.
+     *
+     * @param url           The url to load.
+     * @param openExternal  Load url in browser instead of Cordova webview.
+     * @param clearHistory  Clear the history stack, so new page becomes top of history
+     * @param params        Parameters for new app
+     */
+    void showWebPage(String url, boolean openExternal, boolean clearHistory, Map<String, Object> params);
+
+    /**
+     * Deprecated in 4.0.0. Use your own View-toggling logic.
+     */
+    @Deprecated
+    boolean isCustomViewShowing();
+
+    /**
+     * Deprecated in 4.0.0. Use your own View-toggling logic.
+     */
+    @Deprecated
+    void showCustomView(View view, CustomViewCallback callback);
+
+    /**
+     * Deprecated in 4.0.0. Use your own View-toggling logic.
+     */
+    @Deprecated
+    void hideCustomView();
+
+    CordovaResourceApi getResourceApi();
+
+    void setButtonPlumbedToJs(int keyCode, boolean override);
+    boolean isButtonPlumbedToJs(int keyCode);
+
+    void sendPluginResult(PluginResult cr, String callbackId);
+
+    PluginManager getPluginManager();
+    CordovaWebViewEngine getEngine();
+    CordovaPreferences getPreferences();
+    ICordovaCookieManager getCookieManager();
+
+    String getUrl();
+
+    // TODO: Work on deleting these by removing refs from plugins.
+    Context getContext();
+    void loadUrl(String url);
+    Object postMessage(String id, Object data);
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
new file mode 100644
index 0000000..c8e5a55
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
@@ -0,0 +1,85 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.view.KeyEvent;
+import android.view.View;
+import android.webkit.ValueCallback;
+
+/**
+ * Interface for all Cordova engines.
+ * No methods will be added to this class (in order to be compatible with existing engines).
+ * Instead, we will create a new interface: e.g. CordovaWebViewEngineV2
+ */
+public interface CordovaWebViewEngine {
+    void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client,
+              CordovaResourceApi resourceApi, PluginManager pluginManager,
+              NativeToJsMessageQueue nativeToJsMessageQueue);
+
+    CordovaWebView getCordovaWebView();
+    ICordovaCookieManager getCookieManager();
+    View getView();
+
+    void loadUrl(String url, boolean clearNavigationStack);
+
+    void stopLoading();
+
+    /** Return the currently loaded URL */
+    String getUrl();
+
+    void clearCache();
+
+    /** After calling clearHistory(), canGoBack() should be false. */
+    void clearHistory();
+
+    boolean canGoBack();
+
+    /** Returns whether a navigation occurred */
+    boolean goBack();
+
+    /** Pauses / resumes the WebView's event loop. */
+    void setPaused(boolean value);
+
+    /** Clean up all resources associated with the WebView. */
+    void destroy();
+
+    /** Add the evaulate Javascript method **/
+    void evaluateJavascript(String js, ValueCallback<String> callback);
+
+    /**
+     * Used to retrieve the associated CordovaWebView given a View without knowing the type of Engine.
+     * E.g. ((CordovaWebView.EngineView)activity.findViewById(android.R.id.webView)).getCordovaWebView();
+     */
+    public interface EngineView {
+        CordovaWebView getCordovaWebView();
+    }
+
+    /**
+     * Contains methods that an engine uses to communicate with the parent CordovaWebView.
+     * Methods may be added in future cordova versions, but never removed.
+     */
+    public interface Client {
+        Boolean onDispatchKeyEvent(KeyEvent event);
+        void clearLoadTimeoutTimer();
+        void onPageStarted(String newUrl);
+        void onReceivedError(int errorCode, String description, String failingUrl);
+        void onPageFinishedLoading(String url);
+        boolean onNavigationAttempt(String url);
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java
new file mode 100644
index 0000000..1db2e95
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java
@@ -0,0 +1,617 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebChromeClient;
+import android.widget.FrameLayout;
+
+import org.apache.cordova.engine.SystemWebViewEngine;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Main class for interacting with a Cordova webview. Manages plugins, events, and a CordovaWebViewEngine.
+ * Class uses two-phase initialization. You must call init() before calling any other methods.
+ */
+public class CordovaWebViewImpl implements CordovaWebView {
+
+    public static final String TAG = "CordovaWebViewImpl";
+
+    private PluginManager pluginManager;
+
+    protected final CordovaWebViewEngine engine;
+    private CordovaInterface cordova;
+
+    // Flag to track that a loadUrl timeout occurred
+    private int loadUrlTimeout = 0;
+
+    private CordovaResourceApi resourceApi;
+    private CordovaPreferences preferences;
+    private CoreAndroid appPlugin;
+    private NativeToJsMessageQueue nativeToJsMessageQueue;
+    private EngineClient engineClient = new EngineClient();
+    private boolean hasPausedEver;
+
+    // The URL passed to loadUrl(), not necessarily the URL of the current page.
+    String loadedUrl;
+
+    /** custom view created by the browser (a video player for example) */
+    private View mCustomView;
+    private WebChromeClient.CustomViewCallback mCustomViewCallback;
+
+    private Set<Integer> boundKeyCodes = new HashSet<Integer>();
+
+    public static CordovaWebViewEngine createEngine(Context context, CordovaPreferences preferences) {
+        String className = preferences.getString("webview", SystemWebViewEngine.class.getCanonicalName());
+        try {
+            Class<?> webViewClass = Class.forName(className);
+            Constructor<?> constructor = webViewClass.getConstructor(Context.class, CordovaPreferences.class);
+            return (CordovaWebViewEngine) constructor.newInstance(context, preferences);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to create webview. ", e);
+        }
+    }
+
+    public CordovaWebViewImpl(CordovaWebViewEngine cordovaWebViewEngine) {
+        this.engine = cordovaWebViewEngine;
+    }
+
+    // Convenience method for when creating programmatically (not from Config.xml).
+    public void init(CordovaInterface cordova) {
+        init(cordova, new ArrayList<PluginEntry>(), new CordovaPreferences());
+    }
+
+    @SuppressLint("Assert")
+    @Override
+    public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences) {
+        if (this.cordova != null) {
+            throw new IllegalStateException();
+        }
+        this.cordova = cordova;
+        this.preferences = preferences;
+        pluginManager = new PluginManager(this, this.cordova, pluginEntries);
+        resourceApi = new CordovaResourceApi(engine.getView().getContext(), pluginManager);
+        nativeToJsMessageQueue = new NativeToJsMessageQueue();
+        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.NoOpBridgeMode());
+        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.LoadUrlBridgeMode(engine, cordova));
+
+        if (preferences.getBoolean("DisallowOverscroll", false)) {
+            engine.getView().setOverScrollMode(View.OVER_SCROLL_NEVER);
+        }
+        engine.init(this, cordova, engineClient, resourceApi, pluginManager, nativeToJsMessageQueue);
+        // This isn't enforced by the compiler, so assert here.
+        assert engine.getView() instanceof CordovaWebViewEngine.EngineView;
+
+        pluginManager.addService(CoreAndroid.PLUGIN_NAME, "org.apache.cordova.CoreAndroid");
+        pluginManager.init();
+
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return cordova != null;
+    }
+
+    @Override
+    public void loadUrlIntoView(final String url, boolean recreatePlugins) {
+        LOG.d(TAG, ">>> loadUrl(" + url + ")");
+        if (url.equals("about:blank") || url.startsWith("javascript:")) {
+            engine.loadUrl(url, false);
+            return;
+        }
+
+        recreatePlugins = recreatePlugins || (loadedUrl == null);
+
+        if (recreatePlugins) {
+            // Don't re-initialize on first load.
+            if (loadedUrl != null) {
+                appPlugin = null;
+                pluginManager.init();
+            }
+            loadedUrl = url;
+        }
+
+        // Create a timeout timer for loadUrl
+        final int currentLoadUrlTimeout = loadUrlTimeout;
+        final int loadUrlTimeoutValue = preferences.getInteger("LoadUrlTimeoutValue", 20000);
+
+        // Timeout error method
+        final Runnable loadError = new Runnable() {
+            public void run() {
+                stopLoading();
+                LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
+
+                // Handle other errors by passing them to the webview in JS
+                JSONObject data = new JSONObject();
+                try {
+                    data.put("errorCode", -6);
+                    data.put("description", "The connection to the server was unsuccessful.");
+                    data.put("url", url);
+                } catch (JSONException e) {
+                    // Will never happen.
+                }
+                pluginManager.postMessage("onReceivedError", data);
+            }
+        };
+
+        // Timeout timer method
+        final Runnable timeoutCheck = new Runnable() {
+            public void run() {
+                try {
+                    synchronized (this) {
+                        wait(loadUrlTimeoutValue);
+                    }
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+
+                // If timeout, then stop loading and handle error
+                if (loadUrlTimeout == currentLoadUrlTimeout) {
+                    cordova.getActivity().runOnUiThread(loadError);
+                }
+            }
+        };
+
+        final boolean _recreatePlugins = recreatePlugins;
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                if (loadUrlTimeoutValue > 0) {
+                    cordova.getThreadPool().execute(timeoutCheck);
+                }
+                engine.loadUrl(url, _recreatePlugins);
+            }
+        });
+    }
+
+
+    @Override
+    public void loadUrl(String url) {
+        loadUrlIntoView(url, true);
+    }
+
+    @Override
+    public void showWebPage(String url, boolean openExternal, boolean clearHistory, Map<String, Object> params) {
+        LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap)", url, openExternal, clearHistory);
+
+        // If clearing history
+        if (clearHistory) {
+            engine.clearHistory();
+        }
+
+        // If loading into our webview
+        if (!openExternal) {
+            // Make sure url is in whitelist
+            if (pluginManager.shouldAllowNavigation(url)) {
+                // TODO: What about params?
+                // Load new URL
+                loadUrlIntoView(url, true);
+                return;
+            } else {
+                LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the <allow-navigation> whitelist. URL=" + url);
+                return;
+            }
+        }
+        if (!pluginManager.shouldOpenExternalUrl(url)) {
+            LOG.w(TAG, "showWebPage: Refusing to send intent for URL since it is not in the <allow-intent> whitelist. URL=" + url);
+            return;
+        }
+        try {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            // To send an intent without CATEGORY_BROWSER, a custom plugin should be used.
+            intent.addCategory(Intent.CATEGORY_BROWSABLE);
+            Uri uri = Uri.parse(url);
+            // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
+            // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
+            if ("file".equals(uri.getScheme())) {
+                intent.setDataAndType(uri, resourceApi.getMimeType(uri));
+            } else {
+                intent.setData(uri);
+            }
+            cordova.getActivity().startActivity(intent);
+        } catch (android.content.ActivityNotFoundException e) {
+            LOG.e(TAG, "Error loading url " + url, e);
+        }
+    }
+
+    @Override
+    @Deprecated
+    public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        LOG.d(TAG, "showing Custom View");
+        // if a view already exists then immediately terminate the new one
+        if (mCustomView != null) {
+            callback.onCustomViewHidden();
+            return;
+        }
+
+        // Store the view and its callback for later (to kill it properly)
+        mCustomView = view;
+        mCustomViewCallback = callback;
+
+        // Add the custom view to its container.
+        ViewGroup parent = (ViewGroup) engine.getView().getParent();
+        parent.addView(view, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                Gravity.CENTER));
+
+        // Hide the content view.
+        engine.getView().setVisibility(View.GONE);
+
+        // Finally show the custom view container.
+        parent.setVisibility(View.VISIBLE);
+        parent.bringToFront();
+    }
+
+    @Override
+    @Deprecated
+    public void hideCustomView() {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        if (mCustomView == null) return;
+        LOG.d(TAG, "Hiding Custom View");
+
+        // Hide the custom view.
+        mCustomView.setVisibility(View.GONE);
+
+        // Remove the custom view from its container.
+        ViewGroup parent = (ViewGroup) engine.getView().getParent();
+        parent.removeView(mCustomView);
+        mCustomView = null;
+        mCustomViewCallback.onCustomViewHidden();
+
+        // Show the content view.
+        engine.getView().setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    @Deprecated
+    public boolean isCustomViewShowing() {
+        return mCustomView != null;
+    }
+
+    @Override
+    @Deprecated
+    public void sendJavascript(String statement) {
+        nativeToJsMessageQueue.addJavaScript(statement);
+    }
+
+    @Override
+    public void sendPluginResult(PluginResult cr, String callbackId) {
+        nativeToJsMessageQueue.addPluginResult(cr, callbackId);
+    }
+
+    @Override
+    public PluginManager getPluginManager() {
+        return pluginManager;
+    }
+    @Override
+    public CordovaPreferences getPreferences() {
+        return preferences;
+    }
+    @Override
+    public ICordovaCookieManager getCookieManager() {
+        return engine.getCookieManager();
+    }
+    @Override
+    public CordovaResourceApi getResourceApi() {
+        return resourceApi;
+    }
+    @Override
+    public CordovaWebViewEngine getEngine() {
+        return engine;
+    }
+    @Override
+    public View getView() {
+        return engine.getView();
+    }
+    @Override
+    public Context getContext() {
+        return engine.getView().getContext();
+    }
+
+    private void sendJavascriptEvent(String event) {
+        if (appPlugin == null) {
+            appPlugin = (CoreAndroid)pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
+        }
+
+        if (appPlugin == null) {
+            LOG.w(TAG, "Unable to fire event without existing plugin");
+            return;
+        }
+        appPlugin.fireJavascriptEvent(event);
+    }
+
+    @Override
+    public void setButtonPlumbedToJs(int keyCode, boolean override) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_MENU:
+                // TODO: Why are search and menu buttons handled separately?
+                if (override) {
+                    boundKeyCodes.add(keyCode);
+                } else {
+                    boundKeyCodes.remove(keyCode);
+                }
+                return;
+            default:
+                throw new IllegalArgumentException("Unsupported keycode: " + keyCode);
+        }
+    }
+
+    @Override
+    public boolean isButtonPlumbedToJs(int keyCode) {
+        return boundKeyCodes.contains(keyCode);
+    }
+
+    @Override
+    public Object postMessage(String id, Object data) {
+        return pluginManager.postMessage(id, data);
+    }
+
+    // Engine method proxies:
+    @Override
+    public String getUrl() {
+        return engine.getUrl();
+    }
+
+    @Override
+    public void stopLoading() {
+        // Clear timeout flag
+        loadUrlTimeout++;
+    }
+
+    @Override
+    public boolean canGoBack() {
+        return engine.canGoBack();
+    }
+
+    @Override
+    public void clearCache() {
+        engine.clearCache();
+    }
+
+    @Override
+    @Deprecated
+    public void clearCache(boolean b) {
+        engine.clearCache();
+    }
+
+    @Override
+    public void clearHistory() {
+        engine.clearHistory();
+    }
+
+    @Override
+    public boolean backHistory() {
+        return engine.goBack();
+    }
+
+    /////// LifeCycle methods ///////
+    @Override
+    public void onNewIntent(Intent intent) {
+        if (this.pluginManager != null) {
+            this.pluginManager.onNewIntent(intent);
+        }
+    }
+    @Override
+    public void handlePause(boolean keepRunning) {
+        if (!isInitialized()) {
+            return;
+        }
+        hasPausedEver = true;
+        pluginManager.onPause(keepRunning);
+        sendJavascriptEvent("pause");
+
+        // If app doesn't want to run in background
+        if (!keepRunning) {
+            // Pause JavaScript timers. This affects all webviews within the app!
+            engine.setPaused(true);
+        }
+    }
+    @Override
+    public void handleResume(boolean keepRunning) {
+        if (!isInitialized()) {
+            return;
+        }
+
+        // Resume JavaScript timers. This affects all webviews within the app!
+        engine.setPaused(false);
+        this.pluginManager.onResume(keepRunning);
+
+        // In order to match the behavior of the other platforms, we only send onResume after an
+        // onPause has occurred. The resume event might still be sent if the Activity was killed
+        // while waiting for the result of an external Activity once the result is obtained
+        if (hasPausedEver) {
+            sendJavascriptEvent("resume");
+        }
+    }
+    @Override
+    public void handleStart() {
+        if (!isInitialized()) {
+            return;
+        }
+        pluginManager.onStart();
+    }
+    @Override
+    public void handleStop() {
+        if (!isInitialized()) {
+            return;
+        }
+        pluginManager.onStop();
+    }
+    @Override
+    public void handleDestroy() {
+        if (!isInitialized()) {
+            return;
+        }
+        // Cancel pending timeout timer.
+        loadUrlTimeout++;
+
+        // Forward to plugins
+        this.pluginManager.onDestroy();
+
+        // TODO: about:blank is a bit special (and the default URL for new frames)
+        // We should use a blank data: url instead so it's more obvious
+        this.loadUrl("about:blank");
+
+        // TODO: Should not destroy webview until after about:blank is done loading.
+        engine.destroy();
+        hideCustomView();
+    }
+
+    protected class EngineClient implements CordovaWebViewEngine.Client {
+        @Override
+        public void clearLoadTimeoutTimer() {
+            loadUrlTimeout++;
+        }
+
+        @Override
+        public void onPageStarted(String newUrl) {
+            LOG.d(TAG, "onPageDidNavigate(" + newUrl + ")");
+            boundKeyCodes.clear();
+            pluginManager.onReset();
+            pluginManager.postMessage("onPageStarted", newUrl);
+        }
+
+        @Override
+        public void onReceivedError(int errorCode, String description, String failingUrl) {
+            clearLoadTimeoutTimer();
+            JSONObject data = new JSONObject();
+            try {
+                data.put("errorCode", errorCode);
+                data.put("description", description);
+                data.put("url", failingUrl);
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+            pluginManager.postMessage("onReceivedError", data);
+        }
+
+        @Override
+        public void onPageFinishedLoading(String url) {
+            LOG.d(TAG, "onPageFinished(" + url + ")");
+
+            clearLoadTimeoutTimer();
+
+            // Broadcast message that page has loaded
+            pluginManager.postMessage("onPageFinished", url);
+
+            // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
+            if (engine.getView().getVisibility() != View.VISIBLE) {
+                Thread t = new Thread(new Runnable() {
+                    public void run() {
+                        try {
+                            Thread.sleep(2000);
+                            cordova.getActivity().runOnUiThread(new Runnable() {
+                                public void run() {
+                                    pluginManager.postMessage("spinner", "stop");
+                                }
+                            });
+                        } catch (InterruptedException e) {
+                        }
+                    }
+                });
+                t.start();
+            }
+
+            // Shutdown if blank loaded
+            if (url.equals("about:blank")) {
+                pluginManager.postMessage("exit", null);
+            }
+        }
+
+        @Override
+        public Boolean onDispatchKeyEvent(KeyEvent event) {
+            int keyCode = event.getKeyCode();
+            boolean isBackButton = keyCode == KeyEvent.KEYCODE_BACK;
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                if (isBackButton && mCustomView != null) {
+                    return true;
+                } else if (boundKeyCodes.contains(keyCode)) {
+                    return true;
+                } else if (isBackButton) {
+                    return engine.canGoBack();
+                }
+            } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                if (isBackButton && mCustomView != null) {
+                    hideCustomView();
+                    return true;
+                } else if (boundKeyCodes.contains(keyCode)) {
+                    String eventName = null;
+                    switch (keyCode) {
+                        case KeyEvent.KEYCODE_VOLUME_DOWN:
+                            eventName = "volumedownbutton";
+                            break;
+                        case KeyEvent.KEYCODE_VOLUME_UP:
+                            eventName = "volumeupbutton";
+                            break;
+                        case KeyEvent.KEYCODE_SEARCH:
+                            eventName = "searchbutton";
+                            break;
+                        case KeyEvent.KEYCODE_MENU:
+                            eventName = "menubutton";
+                            break;
+                        case KeyEvent.KEYCODE_BACK:
+                            eventName = "backbutton";
+                            break;
+                    }
+                    if (eventName != null) {
+                        sendJavascriptEvent(eventName);
+                        return true;
+                    }
+                } else if (isBackButton) {
+                    return engine.goBack();
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean onNavigationAttempt(String url) {
+            // Give plugins the chance to handle the url
+            if (pluginManager.onOverrideUrlLoading(url)) {
+                return true;
+            } else if (pluginManager.shouldAllowNavigation(url)) {
+                return false;
+            } else if (pluginManager.shouldOpenExternalUrl(url)) {
+                showWebPage(url, true, false, null);
+                return true;
+            }
+            LOG.w(TAG, "Blocked (possibly sub-frame) navigation to non-allowed URL: " + url);
+            return true;
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java b/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java
new file mode 100755
index 0000000..3945cdd
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java
@@ -0,0 +1,407 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.telephony.TelephonyManager;
+import android.view.KeyEvent;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+
+/**
+ * This class exposes methods in Cordova that can be called from JavaScript.
+ */
+public class CoreAndroid extends CordovaPlugin {
+
+    public static final String PLUGIN_NAME = "CoreAndroid";
+    protected static final String TAG = "CordovaApp";
+    private BroadcastReceiver telephonyReceiver;
+    private CallbackContext messageChannel;
+    private PluginResult pendingResume;
+    private PluginResult pendingPause;
+    private final Object messageChannelLock = new Object();
+
+    /**
+     * Send an event to be fired on the Javascript side.
+     *
+     * @param action The name of the event to be fired
+     */
+    public void fireJavascriptEvent(String action) {
+        sendEventMessage(action);
+    }
+
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     */
+    @Override
+    public void pluginInitialize() {
+        this.initTelephonyReceiver();
+    }
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action            The action to execute.
+     * @param args              JSONArry of arguments for the plugin.
+     * @param callbackContext   The callback context from which we were invoked.
+     * @return                  A PluginResult object with a status and message.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+        PluginResult.Status status = PluginResult.Status.OK;
+        String result = "";
+
+        try {
+            if (action.equals("clearCache")) {
+                this.clearCache();
+            }
+            else if (action.equals("show")) {
+                // This gets called from JavaScript onCordovaReady to show the webview.
+                // I recommend we change the name of the Message as spinner/stop is not
+                // indicative of what this actually does (shows the webview).
+                cordova.getActivity().runOnUiThread(new Runnable() {
+                    public void run() {
+                        webView.getPluginManager().postMessage("spinner", "stop");
+                    }
+                });
+            }
+            else if (action.equals("loadUrl")) {
+                this.loadUrl(args.getString(0), args.optJSONObject(1));
+            }
+            else if (action.equals("cancelLoadUrl")) {
+                //this.cancelLoadUrl();
+            }
+            else if (action.equals("clearHistory")) {
+                this.clearHistory();
+            }
+            else if (action.equals("backHistory")) {
+                this.backHistory();
+            }
+            else if (action.equals("overrideButton")) {
+                this.overrideButton(args.getString(0), args.getBoolean(1));
+            }
+            else if (action.equals("overrideBackbutton")) {
+                this.overrideBackbutton(args.getBoolean(0));
+            }
+            else if (action.equals("exitApp")) {
+                this.exitApp();
+            }
+			else if (action.equals("messageChannel")) {
+                synchronized(messageChannelLock) {
+                    messageChannel = callbackContext;
+                    if (pendingPause != null) {
+                        sendEventMessage(pendingPause);
+                        pendingPause = null;
+                    }
+                    if (pendingResume != null) {
+                        sendEventMessage(pendingResume);
+                        pendingResume = null;
+                    }
+                }
+                return true;
+            }
+
+            callbackContext.sendPluginResult(new PluginResult(status, result));
+            return true;
+        } catch (JSONException e) {
+            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+            return false;
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+
+    /**
+     * Clear the resource cache.
+     */
+    public void clearCache() {
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                webView.clearCache();
+            }
+        });
+    }
+
+    /**
+     * Load the url into the webview.
+     *
+     * @param url
+     * @param props			Properties that can be passed in to the Cordova activity (i.e. loadingDialog, wait, ...)
+     * @throws JSONException
+     */
+    public void loadUrl(String url, JSONObject props) throws JSONException {
+        LOG.d("App", "App.loadUrl("+url+","+props+")");
+        int wait = 0;
+        boolean openExternal = false;
+        boolean clearHistory = false;
+
+        // If there are properties, then set them on the Activity
+        HashMap<String, Object> params = new HashMap<String, Object>();
+        if (props != null) {
+            JSONArray keys = props.names();
+            for (int i = 0; i < keys.length(); i++) {
+                String key = keys.getString(i);
+                if (key.equals("wait")) {
+                    wait = props.getInt(key);
+                }
+                else if (key.equalsIgnoreCase("openexternal")) {
+                    openExternal = props.getBoolean(key);
+                }
+                else if (key.equalsIgnoreCase("clearhistory")) {
+                    clearHistory = props.getBoolean(key);
+                }
+                else {
+                    Object value = props.get(key);
+                    if (value == null) {
+
+                    }
+                    else if (value.getClass().equals(String.class)) {
+                        params.put(key, (String)value);
+                    }
+                    else if (value.getClass().equals(Boolean.class)) {
+                        params.put(key, (Boolean)value);
+                    }
+                    else if (value.getClass().equals(Integer.class)) {
+                        params.put(key, (Integer)value);
+                    }
+                }
+            }
+        }
+
+        // If wait property, then delay loading
+
+        if (wait > 0) {
+            try {
+                synchronized(this) {
+                    this.wait(wait);
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        this.webView.showWebPage(url, openExternal, clearHistory, params);
+    }
+
+    /**
+     * Clear page history for the app.
+     */
+    public void clearHistory() {
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                webView.clearHistory();
+            }
+        });
+    }
+
+    /**
+     * Go to previous page displayed.
+     * This is the same as pressing the backbutton on Android device.
+     */
+    public void backHistory() {
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                webView.backHistory();
+            }
+        });
+    }
+
+    /**
+     * Override the default behavior of the Android back button.
+     * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+     *
+     * @param override		T=override, F=cancel override
+     */
+    public void overrideBackbutton(boolean override) {
+        LOG.i("App", "WARNING: Back Button Default Behavior will be overridden.  The backbutton event will be fired!");
+        webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_BACK, override);
+    }
+
+    /**
+     * Override the default behavior of the Android volume buttons.
+     * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired.
+     *
+     * @param button        volumeup, volumedown
+     * @param override      T=override, F=cancel override
+     */
+    public void overrideButton(String button, boolean override) {
+        LOG.i("App", "WARNING: Volume Button Default Behavior will be overridden.  The volume event will be fired!");
+        if (button.equals("volumeup")) {
+            webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override);
+        }
+        else if (button.equals("volumedown")) {
+            webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_DOWN, override);
+        }
+        else if (button.equals("menubutton")) {
+            webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_MENU, override);
+        }
+    }
+
+    /**
+     * Return whether the Android back button is overridden by the user.
+     *
+     * @return boolean
+     */
+    public boolean isBackbuttonOverridden() {
+        return webView.isButtonPlumbedToJs(KeyEvent.KEYCODE_BACK);
+    }
+
+    /**
+     * Exit the Android application.
+     */
+    public void exitApp() {
+        this.webView.getPluginManager().postMessage("exit", null);
+    }
+
+
+    /**
+     * Listen for telephony events: RINGING, OFFHOOK and IDLE
+     * Send these events to all plugins using
+     *      CordovaActivity.onMessage("telephone", "ringing" | "offhook" | "idle")
+     */
+    private void initTelephonyReceiver() {
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
+        //final CordovaInterface mycordova = this.cordova;
+        this.telephonyReceiver = new BroadcastReceiver() {
+
+            @Override
+            public void onReceive(Context context, Intent intent) {
+
+                // If state has changed
+                if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
+                    if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
+                        String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+                        if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
+                            LOG.i(TAG, "Telephone RINGING");
+                            webView.getPluginManager().postMessage("telephone", "ringing");
+                        }
+                        else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
+                            LOG.i(TAG, "Telephone OFFHOOK");
+                            webView.getPluginManager().postMessage("telephone", "offhook");
+                        }
+                        else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
+                            LOG.i(TAG, "Telephone IDLE");
+                            webView.getPluginManager().postMessage("telephone", "idle");
+                        }
+                    }
+                }
+            }
+        };
+
+        // Register the receiver
+        webView.getContext().registerReceiver(this.telephonyReceiver, intentFilter);
+    }
+
+    private void sendEventMessage(String action) {
+        JSONObject obj = new JSONObject();
+        try {
+            obj.put("action", action);
+        } catch (JSONException e) {
+            LOG.e(TAG, "Failed to create event message", e);
+        }
+        PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
+
+        if (messageChannel == null) {
+            LOG.i(TAG, "Request to send event before messageChannel initialised: " + action);
+            if ("pause".equals(action)) {
+                pendingPause = result;
+            } else if ("resume".equals(action)) {
+                // When starting normally onPause then onResume is called
+                pendingPause = null;
+            }
+        } else {
+            sendEventMessage(result);
+        }
+    }
+
+    private void sendEventMessage(PluginResult payload) {
+        payload.setKeepCallback(true);
+        if (messageChannel != null) {
+            messageChannel.sendPluginResult(payload);
+        }
+    }
+
+    /*
+     * Unregister the receiver
+     *
+     */
+    public void onDestroy()
+    {
+        webView.getContext().unregisterReceiver(this.telephonyReceiver);
+    }
+
+    /**
+     * Used to send the resume event in the case that the Activity is destroyed by the OS
+     *
+     * @param resumeEvent PluginResult containing the payload for the resume event to be fired
+     */
+    public void sendResumeEvent(PluginResult resumeEvent) {
+        // This operation must be synchronized because plugin results that trigger resume
+        // events can be processed asynchronously
+        synchronized(messageChannelLock) {
+            if (messageChannel != null) {
+                sendEventMessage(resumeEvent);
+            } else {
+                // Might get called before the page loads, so we need to store it until the
+                // messageChannel gets created
+                this.pendingResume = resumeEvent;
+            }
+        }
+    }
+
+      /*
+     * This needs to be implemented if you wish to use the Camera Plugin or other plugins
+     * that read the Build Configuration.
+     *
+     * Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to
+     * StackOverflow.  This is annoying as hell!
+     *
+     */
+
+    public static Object getBuildConfigValue(Context ctx, String key)
+    {
+        try
+        {
+            Class<?> clazz = Class.forName(ctx.getPackageName() + ".BuildConfig");
+            Field field = clazz.getField(key);
+            return field.get(null);
+        } catch (ClassNotFoundException e) {
+            LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?");
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            LOG.d(TAG, key + " is not a valid field. Check your build.gradle");
+        } catch (IllegalAccessException e) {
+            LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace.");
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java
new file mode 100644
index 0000000..acc65c6
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java
@@ -0,0 +1,31 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+import org.json.JSONException;
+
+/*
+ * Any exposed Javascript API MUST implement these three things!
+ */
+public interface ExposedJsApi {
+    public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException;
+    public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException;
+    public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException;
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java
new file mode 100644
index 0000000..455d2f9
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java
@@ -0,0 +1,66 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * Specifies interface for handling certificate requests.
+ */
+public interface ICordovaClientCertRequest {
+    /**
+     * Cancel this request
+     */
+    public void cancel();
+    
+    /*
+     * Returns the host name of the server requesting the certificate.
+     */
+    public String getHost();
+    
+    /*
+     * Returns the acceptable types of asymmetric keys (can be null).
+     */
+    public String[] getKeyTypes();
+    
+    /*
+     * Returns the port number of the server requesting the certificate.
+     */
+    public int getPort();
+    
+    /*
+     * Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
+     */
+    public Principal[] getPrincipals();
+    
+    /*
+     * Ignore the request for now. Do not remember user's choice.
+     */
+    public void ignore();
+    
+    /*
+     * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
+     * 
+     * @param privateKey The privateKey
+     * @param chain The certificate chain 
+     */
+    public void proceed(PrivateKey privateKey, X509Certificate[] chain);
+}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java
new file mode 100644
index 0000000..e776194
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java
@@ -0,0 +1,33 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova;
+
+public interface ICordovaCookieManager {
+
+    public void setCookiesEnabled(boolean accept);
+
+    public void setCookie(final String url, final String value);
+
+    public String getCookie(final String url);
+
+    public void clearCookies();
+
+    public void flush();
+};
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java
new file mode 100644
index 0000000..c55818a
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java
@@ -0,0 +1,38 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+/**
+ * Specifies interface for HTTP auth handler object which is used to handle auth requests and
+ * specifying user credentials.
+ */
+ public interface ICordovaHttpAuthHandler {
+    /**
+     * Instructs the WebView to cancel the authentication request.
+     */
+    public void cancel ();
+    
+    /**
+     * Instructs the WebView to proceed with the authentication with the given credentials.
+     * 
+     * @param username The user name
+     * @param password The password
+     */
+    public void proceed (String username, String password);
+}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java b/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java
new file mode 100755
index 0000000..9fe7a7d
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java
@@ -0,0 +1,244 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import android.util.Log;
+
+/**
+ * Log to Android logging system.
+ *
+ * Log message can be a string or a printf formatted string with arguments.
+ * See http://developer.android.com/reference/java/util/Formatter.html
+ */
+public class LOG {
+
+    public static final int VERBOSE = Log.VERBOSE;
+    public static final int DEBUG = Log.DEBUG;
+    public static final int INFO = Log.INFO;
+    public static final int WARN = Log.WARN;
+    public static final int ERROR = Log.ERROR;
+
+    // Current log level
+    public static int LOGLEVEL = Log.ERROR;
+
+    /**
+     * Set the current log level.
+     *
+     * @param logLevel
+     */
+    public static void setLogLevel(int logLevel) {
+        LOGLEVEL = logLevel;
+        Log.i("CordovaLog", "Changing log level to " + logLevel);
+    }
+
+    /**
+     * Set the current log level.
+     *
+     * @param logLevel
+     */
+    public static void setLogLevel(String logLevel) {
+        if ("VERBOSE".equals(logLevel)) LOGLEVEL = VERBOSE;
+        else if ("DEBUG".equals(logLevel)) LOGLEVEL = DEBUG;
+        else if ("INFO".equals(logLevel)) LOGLEVEL = INFO;
+        else if ("WARN".equals(logLevel)) LOGLEVEL = WARN;
+        else if ("ERROR".equals(logLevel)) LOGLEVEL = ERROR;
+        Log.i("CordovaLog", "Changing log level to " + logLevel + "(" + LOGLEVEL + ")");
+    }
+
+    /**
+     * Determine if log level will be logged
+     *
+     * @param logLevel
+     * @return true if the parameter passed in is greater than or equal to the current log level
+     */
+    public static boolean isLoggable(int logLevel) {
+        return (logLevel >= LOGLEVEL);
+    }
+
+    /**
+     * Verbose log message.
+     *
+     * @param tag
+     * @param s
+     */
+    public static void v(String tag, String s) {
+        if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s);
+    }
+
+    /**
+     * Debug log message.
+     *
+     * @param tag
+     * @param s
+     */
+    public static void d(String tag, String s) {
+        if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s);
+    }
+
+    /**
+     * Info log message.
+     *
+     * @param tag
+     * @param s
+     */
+    public static void i(String tag, String s) {
+        if (LOG.INFO >= LOGLEVEL) Log.i(tag, s);
+    }
+
+    /**
+     * Warning log message.
+     *
+     * @param tag
+     * @param s
+     */
+    public static void w(String tag, String s) {
+        if (LOG.WARN >= LOGLEVEL) Log.w(tag, s);
+    }
+
+    /**
+     * Error log message.
+     *
+     * @param tag
+     * @param s
+     */
+    public static void e(String tag, String s) {
+        if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s);
+    }
+
+    /**
+     * Verbose log message.
+     *
+     * @param tag
+     * @param s
+     * @param e
+     */
+    public static void v(String tag, String s, Throwable e) {
+        if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s, e);
+    }
+
+    /**
+     * Debug log message.
+     *
+     * @param tag
+     * @param s
+     * @param e
+     */
+    public static void d(String tag, String s, Throwable e) {
+        if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s, e);
+    }
+
+    /**
+     * Info log message.
+     *
+     * @param tag
+     * @param s
+     * @param e
+     */
+    public static void i(String tag, String s, Throwable e) {
+        if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e);
+    }
+
+    /**
+     * Warning log message.
+     *
+     * @param tag
+     * @param e
+     */
+    public static void w(String tag, Throwable e) {
+        if (LOG.WARN >= LOGLEVEL) Log.w(tag, e);
+    }
+
+    /**
+     * Warning log message.
+     *
+     * @param tag
+     * @param s
+     * @param e
+     */
+    public static void w(String tag, String s, Throwable e) {
+        if (LOG.WARN >= LOGLEVEL) Log.w(tag, s, e);
+    }
+
+    /**
+     * Error log message.
+     *
+     * @param tag
+     * @param s
+     * @param e
+     */
+    public static void e(String tag, String s, Throwable e) {
+        if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s, e);
+    }
+
+    /**
+     * Verbose log message with printf formatting.
+     *
+     * @param tag
+     * @param s
+     * @param args
+     */
+    public static void v(String tag, String s, Object... args) {
+        if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, String.format(s, args));
+    }
+
+    /**
+     * Debug log message with printf formatting.
+     *
+     * @param tag
+     * @param s
+     * @param args
+     */
+    public static void d(String tag, String s, Object... args) {
+        if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, String.format(s, args));
+    }
+
+    /**
+     * Info log message with printf formatting.
+     *
+     * @param tag
+     * @param s
+     * @param args
+     */
+    public static void i(String tag, String s, Object... args) {
+        if (LOG.INFO >= LOGLEVEL) Log.i(tag, String.format(s, args));
+    }
+
+    /**
+     * Warning log message with printf formatting.
+     *
+     * @param tag
+     * @param s
+     * @param args
+     */
+    public static void w(String tag, String s, Object... args) {
+        if (LOG.WARN >= LOGLEVEL) Log.w(tag, String.format(s, args));
+    }
+
+    /**
+     * Error log message with printf formatting.
+     *
+     * @param tag
+     * @param s
+     * @param args
+     */
+    public static void e(String tag, String s, Object... args) {
+        if (LOG.ERROR >= LOGLEVEL) Log.e(tag, String.format(s, args));
+    }
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java b/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java
new file mode 100755
index 0000000..d17b1c4
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -0,0 +1,542 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * Holds the list of messages to be sent to the WebView.
+ */
+public class NativeToJsMessageQueue {
+    private static final String LOG_TAG = "JsMessageQueue";
+
+    // Set this to true to force plugin results to be encoding as
+    // JS instead of the custom format (useful for benchmarking).
+    // Doesn't work for multipart messages.
+    private static final boolean FORCE_ENCODE_USING_EVAL = false;
+
+    // Disable sending back native->JS messages during an exec() when the active
+    // exec() is asynchronous. Set this to true when running bridge benchmarks.
+    static final boolean DISABLE_EXEC_CHAINING = false;
+
+    // Arbitrarily chosen upper limit for how much data to send to JS in one shot.
+    // This currently only chops up on message boundaries. It may be useful
+    // to allow it to break up messages.
+    private static int MAX_PAYLOAD_SIZE = 50 * 1024 * 10240;
+
+    /**
+     * When true, the active listener is not fired upon enqueue. When set to false,
+     * the active listener will be fired if the queue is non-empty.
+     */
+    private boolean paused;
+
+    /**
+     * The list of JavaScript statements to be sent to JavaScript.
+     */
+    private final LinkedList<JsMessage> queue = new LinkedList<JsMessage>();
+
+    /**
+     * The array of listeners that can be used to send messages to JS.
+     */
+    private ArrayList<BridgeMode> bridgeModes = new ArrayList<BridgeMode>();
+
+    /**
+     * When null, the bridge is disabled. This occurs during page transitions.
+     * When disabled, all callbacks are dropped since they are assumed to be
+     * relevant to the previous page.
+     */
+    private BridgeMode activeBridgeMode;
+
+    public void addBridgeMode(BridgeMode bridgeMode) {
+        bridgeModes.add(bridgeMode);
+    }
+
+    public boolean isBridgeEnabled() {
+        return activeBridgeMode != null;
+    }
+
+    public boolean isEmpty() {
+        return queue.isEmpty();
+    }
+
+    /**
+     * Changes the bridge mode.
+     */
+    public void setBridgeMode(int value) {
+        if (value < -1 || value >= bridgeModes.size()) {
+            LOG.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value);
+        } else {
+            BridgeMode newMode = value < 0 ? null : bridgeModes.get(value);
+            if (newMode != activeBridgeMode) {
+                LOG.d(LOG_TAG, "Set native->JS mode to " + (newMode == null ? "null" : newMode.getClass().getSimpleName()));
+                synchronized (this) {
+                    activeBridgeMode = newMode;
+                    if (newMode != null) {
+                        newMode.reset();
+                        if (!paused && !queue.isEmpty()) {
+                            newMode.onNativeToJsMessageAvailable(this);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Clears all messages and resets to the default bridge mode.
+     */
+    public void reset() {
+        synchronized (this) {
+            queue.clear();
+            setBridgeMode(-1);
+        }
+    }
+
+    private int calculatePackedMessageLength(JsMessage message) {
+        int messageLen = message.calculateEncodedLength();
+        String messageLenStr = String.valueOf(messageLen);
+        return messageLenStr.length() + messageLen + 1;
+    }
+
+    private void packMessage(JsMessage message, StringBuilder sb) {
+        int len = message.calculateEncodedLength();
+        sb.append(len)
+          .append(' ');
+        message.encodeAsMessage(sb);
+    }
+
+    /**
+     * Combines and returns queued messages combined into a single string.
+     * Combines as many messages as possible, while staying under MAX_PAYLOAD_SIZE.
+     * Returns null if the queue is empty.
+     */
+    public String popAndEncode(boolean fromOnlineEvent) {
+        synchronized (this) {
+            if (activeBridgeMode == null) {
+                return null;
+            }
+            activeBridgeMode.notifyOfFlush(this, fromOnlineEvent);
+            if (queue.isEmpty()) {
+                return null;
+            }
+            int totalPayloadLen = 0;
+            int numMessagesToSend = 0;
+            for (JsMessage message : queue) {
+                int messageSize = calculatePackedMessageLength(message);
+                if (numMessagesToSend > 0 && totalPayloadLen + messageSize > MAX_PAYLOAD_SIZE && MAX_PAYLOAD_SIZE > 0) {
+                    break;
+                }
+                totalPayloadLen += messageSize;
+                numMessagesToSend += 1;
+            }
+
+            StringBuilder sb = new StringBuilder(totalPayloadLen);
+            for (int i = 0; i < numMessagesToSend; ++i) {
+                JsMessage message = queue.removeFirst();
+                packMessage(message, sb);
+            }
+
+            if (!queue.isEmpty()) {
+                // Attach a char to indicate that there are more messages pending.
+                sb.append('*');
+            }
+            String ret = sb.toString();
+            return ret;
+        }
+    }
+
+    /**
+     * Same as popAndEncode(), except encodes in a form that can be executed as JS.
+     */
+    public String popAndEncodeAsJs() {
+        synchronized (this) {
+            int length = queue.size();
+            if (length == 0) {
+                return null;
+            }
+            int totalPayloadLen = 0;
+            int numMessagesToSend = 0;
+            for (JsMessage message : queue) {
+                int messageSize = message.calculateEncodedLength() + 50; // overestimate.
+                if (numMessagesToSend > 0 && totalPayloadLen + messageSize > MAX_PAYLOAD_SIZE && MAX_PAYLOAD_SIZE > 0) {
+                    break;
+                }
+                totalPayloadLen += messageSize;
+                numMessagesToSend += 1;
+            }
+            boolean willSendAllMessages = numMessagesToSend == queue.size();
+            StringBuilder sb = new StringBuilder(totalPayloadLen + (willSendAllMessages ? 0 : 100));
+            // Wrap each statement in a try/finally so that if one throws it does
+            // not affect the next.
+            for (int i = 0; i < numMessagesToSend; ++i) {
+                JsMessage message = queue.removeFirst();
+                if (willSendAllMessages && (i + 1 == numMessagesToSend)) {
+                    message.encodeAsJsMessage(sb);
+                } else {
+                    sb.append("try{");
+                    message.encodeAsJsMessage(sb);
+                    sb.append("}finally{");
+                }
+            }
+            if (!willSendAllMessages) {
+                sb.append("window.setTimeout(function(){cordova.require('cordova/plugin/android/polling').pollOnce();},0);");
+            }
+            for (int i = willSendAllMessages ? 1 : 0; i < numMessagesToSend; ++i) {
+                sb.append('}');
+            }
+            String ret = sb.toString();
+            return ret;
+        }
+    }
+
+    /**
+     * Add a JavaScript statement to the list.
+     */
+    public void addJavaScript(String statement) {
+        enqueueMessage(new JsMessage(statement));
+    }
+
+    /**
+     * Add a JavaScript statement to the list.
+     */
+    public void addPluginResult(PluginResult result, String callbackId) {
+        if (callbackId == null) {
+            LOG.e(LOG_TAG, "Got plugin result with no callbackId", new Throwable());
+            return;
+        }
+        // Don't send anything if there is no result and there is no need to
+        // clear the callbacks.
+        boolean noResult = result.getStatus() == PluginResult.Status.NO_RESULT.ordinal();
+        boolean keepCallback = result.getKeepCallback();
+        if (noResult && keepCallback) {
+            return;
+        }
+        JsMessage message = new JsMessage(result, callbackId);
+        if (FORCE_ENCODE_USING_EVAL) {
+            StringBuilder sb = new StringBuilder(message.calculateEncodedLength() + 50);
+            message.encodeAsJsMessage(sb);
+            message = new JsMessage(sb.toString());
+        }
+
+        enqueueMessage(message);
+    }
+
+    private void enqueueMessage(JsMessage message) {
+        synchronized (this) {
+            if (activeBridgeMode == null) {
+                LOG.d(LOG_TAG, "Dropping Native->JS message due to disabled bridge");
+                return;
+            }
+            queue.add(message);
+            if (!paused) {
+                activeBridgeMode.onNativeToJsMessageAvailable(this);
+            }
+        }
+    }
+
+    public void setPaused(boolean value) {
+        if (paused && value) {
+            // This should never happen. If a use-case for it comes up, we should
+            // change pause to be a counter.
+            LOG.e(LOG_TAG, "nested call to setPaused detected.", new Throwable());
+        }
+        paused = value;
+        if (!value) {
+            synchronized (this) {
+                if (!queue.isEmpty() && activeBridgeMode != null) {
+                    activeBridgeMode.onNativeToJsMessageAvailable(this);
+                }
+            }
+        }
+    }
+
+    public static abstract class BridgeMode {
+        public abstract void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue);
+        public void notifyOfFlush(NativeToJsMessageQueue queue, boolean fromOnlineEvent) {}
+        public void reset() {}
+    }
+
+    /** Uses JS polls for messages on a timer.. */
+    public static class NoOpBridgeMode extends BridgeMode {
+        @Override public void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue) {
+        }
+    }
+
+    /** Uses webView.loadUrl("javascript:") to execute messages. */
+    public static class LoadUrlBridgeMode extends BridgeMode {
+        private final CordovaWebViewEngine engine;
+        private final CordovaInterface cordova;
+
+        public LoadUrlBridgeMode(CordovaWebViewEngine engine, CordovaInterface cordova) {
+            this.engine = engine;
+            this.cordova = cordova;
+        }
+
+        @Override
+        public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
+            cordova.getActivity().runOnUiThread(new Runnable() {
+                public void run() {
+                    String js = queue.popAndEncodeAsJs();
+                    if (js != null) {
+                        engine.loadUrl("javascript:" + js, false);
+                    }
+                }
+            });
+        }
+    }
+
+    /** Uses online/offline events to tell the JS when to poll for messages. */
+    public static class OnlineEventsBridgeMode extends BridgeMode {
+        private final OnlineEventsBridgeModeDelegate delegate;
+        private boolean online;
+        private boolean ignoreNextFlush;
+
+        public interface OnlineEventsBridgeModeDelegate {
+            void setNetworkAvailable(boolean value);
+            void runOnUiThread(Runnable r);
+        }
+
+        public OnlineEventsBridgeMode(OnlineEventsBridgeModeDelegate delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void reset() {
+            delegate.runOnUiThread(new Runnable() {
+                public void run() {
+                    online = false;
+                    // If the following call triggers a notifyOfFlush, then ignore it.
+                    ignoreNextFlush = true;
+                    delegate.setNetworkAvailable(true);
+                }
+            });
+        }
+
+        @Override
+        public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
+            delegate.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (!queue.isEmpty()) {
+                        ignoreNextFlush = false;
+                        delegate.setNetworkAvailable(online);
+                    }
+                }
+            });
+        }
+        // Track when online/offline events are fired so that we don't fire excess events.
+        @Override
+        public void notifyOfFlush(final NativeToJsMessageQueue queue, boolean fromOnlineEvent) {
+            if (fromOnlineEvent && !ignoreNextFlush) {
+                online = !online;
+            }
+        }
+    }
+
+    /** Uses webView.evaluateJavascript to execute messages. */
+    public static class EvalBridgeMode extends BridgeMode {
+        private final CordovaWebViewEngine engine;
+        private final CordovaInterface cordova;
+
+        public EvalBridgeMode(CordovaWebViewEngine engine, CordovaInterface cordova) {
+            this.engine = engine;
+            this.cordova = cordova;
+        }
+
+        @Override
+        public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
+            cordova.getActivity().runOnUiThread(new Runnable() {
+                public void run() {
+                    String js = queue.popAndEncodeAsJs();
+                    if (js != null) {
+                        engine.evaluateJavascript(js, null);
+                    }
+                }
+            });
+        }
+    }
+
+
+
+    private static class JsMessage {
+        final String jsPayloadOrCallbackId;
+        final PluginResult pluginResult;
+        JsMessage(String js) {
+            if (js == null) {
+                throw new NullPointerException();
+            }
+            jsPayloadOrCallbackId = js;
+            pluginResult = null;
+        }
+        JsMessage(PluginResult pluginResult, String callbackId) {
+            if (callbackId == null || pluginResult == null) {
+                throw new NullPointerException();
+            }
+            jsPayloadOrCallbackId = callbackId;
+            this.pluginResult = pluginResult;
+        }
+
+        static int calculateEncodedLengthHelper(PluginResult pluginResult) {
+            switch (pluginResult.getMessageType()) {
+                case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
+                case PluginResult.MESSAGE_TYPE_NULL: // N
+                    return 1;
+                case PluginResult.MESSAGE_TYPE_NUMBER: // n
+                    return 1 + pluginResult.getMessage().length();
+                case PluginResult.MESSAGE_TYPE_STRING: // s
+                    return 1 + pluginResult.getStrMessage().length();
+                case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+                    return 1 + pluginResult.getMessage().length();
+                case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+                    return 1 + pluginResult.getMessage().length();
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    int ret = 1;
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        int length = calculateEncodedLengthHelper(pluginResult.getMultipartMessage(i));
+                        int argLength = String.valueOf(length).length();
+                        ret += argLength + 1 + length;
+                    }
+                    return ret;
+                case PluginResult.MESSAGE_TYPE_JSON:
+                default:
+                    return pluginResult.getMessage().length();
+            }
+        }
+
+        int calculateEncodedLength() {
+            if (pluginResult == null) {
+                return jsPayloadOrCallbackId.length() + 1;
+            }
+            int statusLen = String.valueOf(pluginResult.getStatus()).length();
+            int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
+            return ret + calculateEncodedLengthHelper(pluginResult);
+            }
+
+        static void encodeAsMessageHelper(StringBuilder sb, PluginResult pluginResult) {
+            switch (pluginResult.getMessageType()) {
+                case PluginResult.MESSAGE_TYPE_BOOLEAN:
+                    sb.append(pluginResult.getMessage().charAt(0)); // t or f.
+                    break;
+                case PluginResult.MESSAGE_TYPE_NULL: // N
+                    sb.append('N');
+                    break;
+                case PluginResult.MESSAGE_TYPE_NUMBER: // n
+                    sb.append('n')
+                      .append(pluginResult.getMessage());
+                    break;
+                case PluginResult.MESSAGE_TYPE_STRING: // s
+                    sb.append('s');
+                    sb.append(pluginResult.getStrMessage());
+                    break;
+                case PluginResult.MESSAGE_TYPE_BINARYSTRING: // S
+                    sb.append('S');
+                    sb.append(pluginResult.getMessage());
+                    break;
+                case PluginResult.MESSAGE_TYPE_ARRAYBUFFER: // A
+                    sb.append('A');
+                    sb.append(pluginResult.getMessage());
+                    break;
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    sb.append('M');
+                    for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
+                        PluginResult multipartMessage = pluginResult.getMultipartMessage(i);
+                        sb.append(String.valueOf(calculateEncodedLengthHelper(multipartMessage)));
+                        sb.append(' ');
+                        encodeAsMessageHelper(sb, multipartMessage);
+                    }
+                    break;
+                case PluginResult.MESSAGE_TYPE_JSON:
+                default:
+                    sb.append(pluginResult.getMessage()); // [ or {
+            }
+        }
+
+        void encodeAsMessage(StringBuilder sb) {
+            if (pluginResult == null) {
+                sb.append('J')
+                  .append(jsPayloadOrCallbackId);
+                return;
+            }
+            int status = pluginResult.getStatus();
+            boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
+            boolean resultOk = status == PluginResult.Status.OK.ordinal();
+            boolean keepCallback = pluginResult.getKeepCallback();
+
+            sb.append((noResult || resultOk) ? 'S' : 'F')
+              .append(keepCallback ? '1' : '0')
+              .append(status)
+              .append(' ')
+              .append(jsPayloadOrCallbackId)
+              .append(' ');
+
+            encodeAsMessageHelper(sb, pluginResult);
+        }
+
+        void buildJsMessage(StringBuilder sb) {
+            switch (pluginResult.getMessageType()) {
+                case PluginResult.MESSAGE_TYPE_MULTIPART:
+                    int size = pluginResult.getMultipartMessagesSize();
+                    for (int i=0; i<size; i++) {
+                        PluginResult subresult = pluginResult.getMultipartMessage(i);
+                        JsMessage submessage = new JsMessage(subresult, jsPayloadOrCallbackId);
+                        submessage.buildJsMessage(sb);
+                        if (i < (size-1)) {
+                            sb.append(",");
+                        }
+                    }
+                    break;
+                case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+                    sb.append("atob('")
+                            .append(pluginResult.getMessage())
+                            .append("')");
+                    break;
+                case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+                    sb.append("cordova.require('cordova/base64').toArrayBuffer('")
+                            .append(pluginResult.getMessage())
+                            .append("')");
+                    break;
+                case PluginResult.MESSAGE_TYPE_NULL:
+                    sb.append("null");
+                    break;
+                default:
+                    sb.append(pluginResult.getMessage());
+            }
+        }
+
+        void encodeAsJsMessage(StringBuilder sb) {
+            if (pluginResult == null) {
+                sb.append(jsPayloadOrCallbackId);
+            } else {
+                int status = pluginResult.getStatus();
+                boolean success = (status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal());
+                sb.append("cordova.callbackFromNative('")
+                        .append(jsPayloadOrCallbackId)
+                        .append("',")
+                        .append(success)
+                        .append(",")
+                        .append(status)
+                        .append(",[");
+                buildJsMessage(sb);
+                sb.append("],")
+                        .append(pluginResult.getKeepCallback())
+                        .append(");");
+            }
+        }
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/PermissionHelper.java b/platforms/android/CordovaLib/src/org/apache/cordova/PermissionHelper.java
new file mode 100644
index 0000000..52f6e14
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/PermissionHelper.java
@@ -0,0 +1,87 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.util.Arrays;
+
+import org.json.JSONException;
+
+import android.content.pm.PackageManager;
+
+/**
+ * This class provides reflective methods for permission requesting and checking so that plugins
+ * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions.
+ */
+public class PermissionHelper {
+    private static final String LOG_TAG = "CordovaPermissionHelper";
+
+    /**
+     * Requests a "dangerous" permission for the application at runtime. This is a helper method
+     * alternative to cordovaInterface.requestPermission() that does not require the project to be
+     * built with cordova-android 5.0.0+
+     *
+     * @param plugin        The plugin the permission is being requested for
+     * @param requestCode   A requestCode to be passed to the plugin's onRequestPermissionResult()
+     *                      along with the result of the permission request
+     * @param permission    The permission to be requested
+     */
+    public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
+        PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission});
+    }
+
+    /**
+     * Requests "dangerous" permissions for the application at runtime. This is a helper method
+     * alternative to cordovaInterface.requestPermissions() that does not require the project to be
+     * built with cordova-android 5.0.0+
+     *
+     * @param plugin        The plugin the permissions are being requested for
+     * @param requestCode   A requestCode to be passed to the plugin's onRequestPermissionResult()
+     *                      along with the result of the permissions request
+     * @param permissions   The permissions to be requested
+     */
+    public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {
+        plugin.cordova.requestPermissions(plugin, requestCode, permissions);
+    }
+
+    /**
+     * Checks at runtime to see if the application has been granted a permission. This is a helper
+     * method alternative to cordovaInterface.hasPermission() that does not require the project to
+     * be built with cordova-android 5.0.0+
+     *
+     * @param plugin        The plugin the permission is being checked against
+     * @param permission    The permission to be checked
+     *
+     * @return              True if the permission has already been granted and false otherwise
+     */
+    public static boolean hasPermission(CordovaPlugin plugin, String permission) {
+        return plugin.cordova.hasPermission(permission);
+    }
+
+    private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) {
+        // Generate the request results
+        int[] requestResults = new int[permissions.length];
+        Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED);
+
+        try {
+            plugin.onRequestPermissionResult(requestCode, permissions, requestResults);
+        } catch (JSONException e) {
+            LOG.e(LOG_TAG, "JSONException when delivering permissions results", e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/PluginEntry.java b/platforms/android/CordovaLib/src/org/apache/cordova/PluginEntry.java
new file mode 100755
index 0000000..c56c453
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/PluginEntry.java
@@ -0,0 +1,70 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova;
+
+import org.apache.cordova.CordovaPlugin;
+
+/**
+ * This class represents a service entry object.
+ */
+public final class PluginEntry {
+
+    /**
+     * The name of the service that this plugin implements
+     */
+    public final String service;
+
+    /**
+     * The plugin class name that implements the service.
+     */
+    public final String pluginClass;
+
+    /**
+     * The pre-instantiated plugin to use for this entry.
+     */
+    public final CordovaPlugin plugin;
+
+    /**
+     * Flag that indicates the plugin object should be created when PluginManager is initialized.
+     */
+    public final boolean onload;
+
+    /**
+     * Constructs with a CordovaPlugin already instantiated.
+     */
+    public PluginEntry(String service, CordovaPlugin plugin) {
+        this(service, plugin.getClass().getName(), true, plugin);
+    }
+
+    /**
+     * @param service               The name of the service
+     * @param pluginClass           The plugin class name
+     * @param onload                Create plugin object when HTML page is loaded
+     */
+    public PluginEntry(String service, String pluginClass, boolean onload) {
+        this(service, pluginClass, onload, null);
+    }
+
+    private PluginEntry(String service, String pluginClass, boolean onload, CordovaPlugin plugin) {
+        this.service = service;
+        this.pluginClass = pluginClass;
+        this.onload = onload;
+        this.plugin = plugin;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/PluginManager.java b/platforms/android/CordovaLib/src/org/apache/cordova/PluginManager.java
new file mode 100755
index 0000000..c9576a6
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/PluginManager.java
@@ -0,0 +1,526 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+
+import org.json.JSONException;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Debug;
+
+/**
+ * PluginManager is exposed to JavaScript in the Cordova WebView.
+ *
+ * Calling native plugin code can be done by calling PluginManager.exec(...)
+ * from JavaScript.
+ */
+public class PluginManager {
+    private static String TAG = "PluginManager";
+    private static final int SLOW_EXEC_WARNING_THRESHOLD = Debug.isDebuggerConnected() ? 60 : 16;
+
+    // List of service entries
+    private final LinkedHashMap<String, CordovaPlugin> pluginMap = new LinkedHashMap<String, CordovaPlugin>();
+    private final LinkedHashMap<String, PluginEntry> entryMap = new LinkedHashMap<String, PluginEntry>();
+
+    private final CordovaInterface ctx;
+    private final CordovaWebView app;
+    private boolean isInitialized;
+
+    private CordovaPlugin permissionRequester;
+
+    public PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, Collection<PluginEntry> pluginEntries) {
+        this.ctx = cordova;
+        this.app = cordovaWebView;
+        setPluginEntries(pluginEntries);
+    }
+
+    public Collection<PluginEntry> getPluginEntries() {
+        return entryMap.values();
+    }
+
+    public void setPluginEntries(Collection<PluginEntry> pluginEntries) {
+        if (isInitialized) {
+            this.onPause(false);
+            this.onDestroy();
+            pluginMap.clear();
+            entryMap.clear();
+        }
+        for (PluginEntry entry : pluginEntries) {
+            addService(entry);
+        }
+        if (isInitialized) {
+            startupPlugins();
+        }
+    }
+
+    /**
+     * Init when loading a new HTML page into webview.
+     */
+    public void init() {
+        LOG.d(TAG, "init()");
+        isInitialized = true;
+        this.onPause(false);
+        this.onDestroy();
+        pluginMap.clear();
+        this.startupPlugins();
+    }
+
+    /**
+     * Create plugins objects that have onload set.
+     */
+    private void startupPlugins() {
+        for (PluginEntry entry : entryMap.values()) {
+            // Add a null entry to for each non-startup plugin to avoid ConcurrentModificationException
+            // When iterating plugins.
+            if (entry.onload) {
+                getPlugin(entry.service);
+            } else {
+                pluginMap.put(entry.service, null);
+            }
+        }
+    }
+
+    /**
+     * Receives a request for execution and fulfills it by finding the appropriate
+     * Java class and calling it's execute method.
+     *
+     * PluginManager.exec can be used either synchronously or async. In either case, a JSON encoded
+     * string is returned that will indicate if any errors have occurred when trying to find
+     * or execute the class denoted by the clazz argument.
+     *
+     * @param service       String containing the service to run
+     * @param action        String containing the action that the class is supposed to perform. This is
+     *                      passed to the plugin execute method and it is up to the plugin developer
+     *                      how to deal with it.
+     * @param callbackId    String containing the id of the callback that is execute in JavaScript if
+     *                      this is an async plugin call.
+     * @param rawArgs       An Array literal string containing any arguments needed in the
+     *                      plugin execute method.
+     */
+    public void exec(final String service, final String action, final String callbackId, final String rawArgs) {
+        CordovaPlugin plugin = getPlugin(service);
+        if (plugin == null) {
+            LOG.d(TAG, "exec() call to unknown plugin: " + service);
+            PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
+            app.sendPluginResult(cr, callbackId);
+            return;
+        }
+        CallbackContext callbackContext = new CallbackContext(callbackId, app);
+        try {
+            long pluginStartTime = System.currentTimeMillis();
+            boolean wasValidAction = plugin.execute(action, rawArgs, callbackContext);
+            long duration = System.currentTimeMillis() - pluginStartTime;
+
+            if (duration > SLOW_EXEC_WARNING_THRESHOLD) {
+                LOG.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool().");
+            }
+            if (!wasValidAction) {
+                PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION);
+                callbackContext.sendPluginResult(cr);
+            }
+        } catch (JSONException e) {
+            PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+            callbackContext.sendPluginResult(cr);
+        } catch (Exception e) {
+            LOG.e(TAG, "Uncaught exception from plugin", e);
+            callbackContext.error(e.getMessage());
+        }
+    }
+
+    /**
+     * Get the plugin object that implements the service.
+     * If the plugin object does not already exist, then create it.
+     * If the service doesn't exist, then return null.
+     *
+     * @param service       The name of the service.
+     * @return              CordovaPlugin or null
+     */
+    public CordovaPlugin getPlugin(String service) {
+        CordovaPlugin ret = pluginMap.get(service);
+        if (ret == null) {
+            PluginEntry pe = entryMap.get(service);
+            if (pe == null) {
+                return null;
+            }
+            if (pe.plugin != null) {
+                ret = pe.plugin;
+            } else {
+                ret = instantiatePlugin(pe.pluginClass);
+            }
+            ret.privateInitialize(service, ctx, app, app.getPreferences());
+            pluginMap.put(service, ret);
+        }
+        return ret;
+    }
+
+    /**
+     * Add a plugin class that implements a service to the service entry table.
+     * This does not create the plugin object instance.
+     *
+     * @param service           The service name
+     * @param className         The plugin class name
+     */
+    public void addService(String service, String className) {
+        PluginEntry entry = new PluginEntry(service, className, false);
+        this.addService(entry);
+    }
+
+    /**
+     * Add a plugin class that implements a service to the service entry table.
+     * This does not create the plugin object instance.
+     *
+     * @param entry             The plugin entry
+     */
+    public void addService(PluginEntry entry) {
+        this.entryMap.put(entry.service, entry);
+        if (entry.plugin != null) {
+            entry.plugin.privateInitialize(entry.service, ctx, app, app.getPreferences());
+            pluginMap.put(entry.service, entry.plugin);
+        }
+    }
+
+    /**
+     * Called when the system is about to start resuming a previous activity.
+     *
+     * @param multitasking      Flag indicating if multitasking is turned on for app
+     */
+    public void onPause(boolean multitasking) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onPause(multitasking);
+            }
+        }
+    }
+
+    /**
+     * Called when the system received an HTTP authentication request. Plugins can use
+     * the supplied HttpAuthHandler to process this auth challenge.
+     *
+     * @param view              The WebView that is initiating the callback
+     * @param handler           The HttpAuthHandler used to set the WebView's response
+     * @param host              The host requiring authentication
+     * @param realm             The realm for which authentication is required
+     *
+     * @return                  Returns True if there is a plugin which will resolve this auth challenge, otherwise False
+     *
+     */
+    public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null && plugin.onReceivedHttpAuthRequest(app, handler, host, realm)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called when he system received an SSL client certificate request.  Plugin can use
+     * the supplied ClientCertRequest to process this certificate challenge.
+     *
+     * @param view              The WebView that is initiating the callback
+     * @param request           The client certificate request
+     *
+     * @return                  Returns True if plugin will resolve this auth challenge, otherwise False
+     *
+     */
+    public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null && plugin.onReceivedClientCertRequest(app, request)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called when the activity will start interacting with the user.
+     *
+     * @param multitasking      Flag indicating if multitasking is turned on for app
+     */
+    public void onResume(boolean multitasking) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onResume(multitasking);
+            }
+        }
+    }
+
+    /**
+     * Called when the activity is becoming visible to the user.
+     */
+    public void onStart() {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onStart();
+            }
+        }
+    }
+
+    /**
+     * Called when the activity is no longer visible to the user.
+     */
+    public void onStop() {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onStop();
+            }
+        }
+    }
+
+    /**
+     * The final call you receive before your activity is destroyed.
+     */
+    public void onDestroy() {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onDestroy();
+            }
+        }
+    }
+
+    /**
+     * Send a message to all plugins.
+     *
+     * @param id                The message id
+     * @param data              The message data
+     * @return                  Object to stop propagation or null
+     */
+    public Object postMessage(String id, Object data) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                Object obj = plugin.onMessage(id, data);
+                if (obj != null) {
+                    return obj;
+                }
+            }
+        }
+        return ctx.onMessage(id, data);
+    }
+
+    /**
+     * Called when the activity receives a new intent.
+     */
+    public void onNewIntent(Intent intent) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onNewIntent(intent);
+            }
+        }
+    }
+
+    /**
+     * Called when the webview is going to request an external resource.
+     *
+     * This delegates to the installed plugins, and returns true/false for the
+     * first plugin to provide a non-null result.  If no plugins respond, then
+     * the default policy is applied.
+     *
+     * @param url       The URL that is being requested.
+     * @return          Returns true to allow the resource to load,
+     *                  false to block the resource.
+     */
+    public boolean shouldAllowRequest(String url) {
+        for (PluginEntry entry : this.entryMap.values()) {
+            CordovaPlugin plugin = pluginMap.get(entry.service);
+            if (plugin != null) {
+                Boolean result = plugin.shouldAllowRequest(url);
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+
+        // Default policy:
+        if (url.startsWith("blob:") || url.startsWith("data:") || url.startsWith("about:blank")) {
+            return true;
+        }
+        // TalkBack requires this, so allow it by default.
+        if (url.startsWith("https://ssl.gstatic.com/accessibility/javascript/android/")) {
+            return true;
+        }
+        if (url.startsWith("file://")) {
+            //This directory on WebKit/Blink based webviews contains SQLite databases!
+            //DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!
+            return !url.contains("/app_webview/");
+        }
+        return false;
+    }
+
+    /**
+     * Called when the webview is going to change the URL of the loaded content.
+     *
+     * This delegates to the installed plugins, and returns true/false for the
+     * first plugin to provide a non-null result.  If no plugins respond, then
+     * the default policy is applied.
+     *
+     * @param url       The URL that is being requested.
+     * @return          Returns true to allow the navigation,
+     *                  false to block the navigation.
+     */
+    public boolean shouldAllowNavigation(String url) {
+        for (PluginEntry entry : this.entryMap.values()) {
+            CordovaPlugin plugin = pluginMap.get(entry.service);
+            if (plugin != null) {
+                Boolean result = plugin.shouldAllowNavigation(url);
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+
+        // Default policy:
+        return url.startsWith("file://") || url.startsWith("about:blank");
+    }
+
+
+    /**
+     * Called when the webview is requesting the exec() bridge be enabled.
+     */
+    public boolean shouldAllowBridgeAccess(String url) {
+        for (PluginEntry entry : this.entryMap.values()) {
+            CordovaPlugin plugin = pluginMap.get(entry.service);
+            if (plugin != null) {
+                Boolean result = plugin.shouldAllowBridgeAccess(url);
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+
+        // Default policy:
+        return url.startsWith("file://");
+    }
+
+    /**
+     * Called when the webview is going not going to navigate, but may launch
+     * an Intent for an URL.
+     *
+     * This delegates to the installed plugins, and returns true/false for the
+     * first plugin to provide a non-null result.  If no plugins respond, then
+     * the default policy is applied.
+     *
+     * @param url       The URL that is being requested.
+     * @return          Returns true to allow the URL to launch an intent,
+     *                  false to block the intent.
+     */
+    public Boolean shouldOpenExternalUrl(String url) {
+        for (PluginEntry entry : this.entryMap.values()) {
+            CordovaPlugin plugin = pluginMap.get(entry.service);
+            if (plugin != null) {
+                Boolean result = plugin.shouldOpenExternalUrl(url);
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+        // Default policy:
+        // External URLs are not allowed
+        return false;
+    }
+
+    /**
+     * Called when the URL of the webview changes.
+     *
+     * @param url               The URL that is being changed to.
+     * @return                  Return false to allow the URL to load, return true to prevent the URL from loading.
+     */
+    public boolean onOverrideUrlLoading(String url) {
+        for (PluginEntry entry : this.entryMap.values()) {
+            CordovaPlugin plugin = pluginMap.get(entry.service);
+            if (plugin != null && plugin.onOverrideUrlLoading(url)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called when the app navigates or refreshes.
+     */
+    public void onReset() {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onReset();
+            }
+        }
+    }
+
+    Uri remapUri(Uri uri) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                Uri ret = plugin.remapUri(uri);
+                if (ret != null) {
+                    return ret;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create a plugin based on class name.
+     */
+    private CordovaPlugin instantiatePlugin(String className) {
+        CordovaPlugin ret = null;
+        try {
+            Class<?> c = null;
+            if ((className != null) && !("".equals(className))) {
+                c = Class.forName(className);
+            }
+            if (c != null & CordovaPlugin.class.isAssignableFrom(c)) {
+                ret = (CordovaPlugin) c.newInstance();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.out.println("Error adding plugin " + className + ".");
+        }
+        return ret;
+    }
+
+    /**
+     * Called by the system when the device configuration changes while your activity is running.
+     *
+     * @param newConfig		The new device configuration
+     */
+    public void onConfigurationChanged(Configuration newConfig) {
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                plugin.onConfigurationChanged(newConfig);
+            }
+        }
+    }
+
+    public Bundle onSaveInstanceState() {
+        Bundle state = new Bundle();
+        for (CordovaPlugin plugin : this.pluginMap.values()) {
+            if (plugin != null) {
+                Bundle pluginState = plugin.onSaveInstanceState();
+                if(pluginState != null) {
+                    state.putBundle(plugin.getServiceName(), pluginState);
+                }
+            }
+        }
+        return state;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java b/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java
new file mode 100644
index 0000000..2b3ac72
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java
@@ -0,0 +1,198 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import android.util.Base64;
+
+public class PluginResult {
+    private final int status;
+    private final int messageType;
+    private boolean keepCallback = false;
+    private String strMessage;
+    private String encodedMessage;
+    private List<PluginResult> multipartMessages;
+
+    public PluginResult(Status status) {
+        this(status, PluginResult.StatusMessages[status.ordinal()]);
+    }
+
+    public PluginResult(Status status, String message) {
+        this.status = status.ordinal();
+        this.messageType = message == null ? MESSAGE_TYPE_NULL : MESSAGE_TYPE_STRING;
+        this.strMessage = message;
+    }
+
+    public PluginResult(Status status, JSONArray message) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_JSON;
+        encodedMessage = message.toString();
+    }
+
+    public PluginResult(Status status, JSONObject message) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_JSON;
+        encodedMessage = message.toString();
+    }
+
+    public PluginResult(Status status, int i) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_NUMBER;
+        this.encodedMessage = ""+i;
+    }
+
+    public PluginResult(Status status, float f) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_NUMBER;
+        this.encodedMessage = ""+f;
+    }
+
+    public PluginResult(Status status, boolean b) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_BOOLEAN;
+        this.encodedMessage = Boolean.toString(b);
+    }
+
+    public PluginResult(Status status, byte[] data) {
+        this(status, data, false);
+    }
+
+    public PluginResult(Status status, byte[] data, boolean binaryString) {
+        this.status = status.ordinal();
+        this.messageType = binaryString ? MESSAGE_TYPE_BINARYSTRING : MESSAGE_TYPE_ARRAYBUFFER;
+        this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
+    }
+    
+    // The keepCallback and status of multipartMessages are ignored.
+    public PluginResult(Status status, List<PluginResult> multipartMessages) {
+        this.status = status.ordinal();
+        this.messageType = MESSAGE_TYPE_MULTIPART;
+        this.multipartMessages = multipartMessages;
+    }
+
+    public void setKeepCallback(boolean b) {
+        this.keepCallback = b;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public int getMessageType() {
+        return messageType;
+    }
+
+    public String getMessage() {
+        if (encodedMessage == null) {
+            encodedMessage = JSONObject.quote(strMessage);
+        }
+        return encodedMessage;
+    }
+
+    public int getMultipartMessagesSize() {
+        return multipartMessages.size();
+    }
+
+    public PluginResult getMultipartMessage(int index) {
+        return multipartMessages.get(index);
+    }
+
+    /**
+     * If messageType == MESSAGE_TYPE_STRING, then returns the message string.
+     * Otherwise, returns null.
+     */
+    public String getStrMessage() {
+        return strMessage;
+    }
+
+    public boolean getKeepCallback() {
+        return this.keepCallback;
+    }
+
+    @Deprecated // Use sendPluginResult instead of sendJavascript.
+    public String getJSONString() {
+        return "{\"status\":" + this.status + ",\"message\":" + this.getMessage() + ",\"keepCallback\":" + this.keepCallback + "}";
+    }
+
+    @Deprecated // Use sendPluginResult instead of sendJavascript.
+    public String toCallbackString(String callbackId) {
+        // If no result to be sent and keeping callback, then no need to sent back to JavaScript
+        if ((status == PluginResult.Status.NO_RESULT.ordinal()) && keepCallback) {
+        	return null;
+        }
+
+        // Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
+        if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
+            return toSuccessCallbackString(callbackId);
+        }
+
+        return toErrorCallbackString(callbackId);
+    }
+
+    @Deprecated // Use sendPluginResult instead of sendJavascript.
+    public String toSuccessCallbackString(String callbackId) {
+        return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");";
+    }
+
+    @Deprecated // Use sendPluginResult instead of sendJavascript.
+    public String toErrorCallbackString(String callbackId) {
+        return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");";
+    }
+
+    public static final int MESSAGE_TYPE_STRING = 1;
+    public static final int MESSAGE_TYPE_JSON = 2;
+    public static final int MESSAGE_TYPE_NUMBER = 3;
+    public static final int MESSAGE_TYPE_BOOLEAN = 4;
+    public static final int MESSAGE_TYPE_NULL = 5;
+    public static final int MESSAGE_TYPE_ARRAYBUFFER = 6;
+    // Use BINARYSTRING when your string may contain null characters.
+    // This is required to work around a bug in the platform :(.
+    public static final int MESSAGE_TYPE_BINARYSTRING = 7;
+    public static final int MESSAGE_TYPE_MULTIPART = 8;
+
+    public static String[] StatusMessages = new String[] {
+        "No result",
+        "OK",
+        "Class not found",
+        "Illegal access",
+        "Instantiation error",
+        "Malformed url",
+        "IO error",
+        "Invalid action",
+        "JSON error",
+        "Error"
+    };
+
+    public enum Status {
+        NO_RESULT,
+        OK,
+        CLASS_NOT_FOUND_EXCEPTION,
+        ILLEGAL_ACCESS_EXCEPTION,
+        INSTANTIATION_EXCEPTION,
+        MALFORMED_URL_EXCEPTION,
+        IO_EXCEPTION,
+        INVALID_ACTION,
+        JSON_EXCEPTION,
+        ERROR
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java b/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java
new file mode 100644
index 0000000..49a43b5
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java
@@ -0,0 +1,76 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ResumeCallback extends CallbackContext {
+    private final String TAG = "CordovaResumeCallback";
+    private String serviceName;
+    private PluginManager pluginManager;
+
+    public ResumeCallback(String serviceName, PluginManager pluginManager) {
+        super("resumecallback", null);
+        this.serviceName = serviceName;
+        this.pluginManager = pluginManager;
+    }
+
+    @Override
+    public void sendPluginResult(PluginResult pluginResult) {
+        synchronized (this) {
+            if (finished) {
+                LOG.w(TAG, serviceName + " attempted to send a second callback to ResumeCallback\nResult was: " + pluginResult.getMessage());
+                return;
+            } else {
+                finished = true;
+            }
+        }
+
+        JSONObject event = new JSONObject();
+        JSONObject pluginResultObject = new JSONObject();
+
+        try {
+            pluginResultObject.put("pluginServiceName", this.serviceName);
+            pluginResultObject.put("pluginStatus", PluginResult.StatusMessages[pluginResult.getStatus()]);
+
+            event.put("action", "resume");
+            event.put("pendingResult", pluginResultObject);
+        } catch (JSONException e) {
+            LOG.e(TAG, "Unable to create resume object for Activity Result");
+        }
+
+        PluginResult eventResult = new PluginResult(PluginResult.Status.OK, event);
+
+        // We send a list of results to the js so that we don't have to decode
+        // the PluginResult passed to this CallbackContext into JSON twice.
+        // The results are combined into an event payload before the event is
+        // fired on the js side of things (see platform.js)
+        List<PluginResult> result = new ArrayList<PluginResult>();
+        result.add(eventResult);
+        result.add(pluginResult);
+
+        CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
+        appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, result));
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java b/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java
new file mode 100644
index 0000000..d0f823c
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java
@@ -0,0 +1,170 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova;
+
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.cordova.LOG;
+
+import android.net.Uri;
+
+public class Whitelist {
+    private static class URLPattern {
+        public Pattern scheme;
+        public Pattern host;
+        public Integer port;
+        public Pattern path;
+
+        private String regexFromPattern(String pattern, boolean allowWildcards) {
+            final String toReplace = "\\.[]{}()^$?+|";
+            StringBuilder regex = new StringBuilder();
+            for (int i=0; i < pattern.length(); i++) {
+                char c = pattern.charAt(i);
+                if (c == '*' && allowWildcards) {
+                    regex.append(".");
+                } else if (toReplace.indexOf(c) > -1) {
+                    regex.append('\\');
+                }
+                regex.append(c);
+            }
+            return regex.toString();
+        }
+
+        public URLPattern(String scheme, String host, String port, String path) throws MalformedURLException {
+            try {
+                if (scheme == null || "*".equals(scheme)) {
+                    this.scheme = null;
+                } else {
+                    this.scheme = Pattern.compile(regexFromPattern(scheme, false), Pattern.CASE_INSENSITIVE);
+                }
+                if ("*".equals(host)) {
+                    this.host = null;
+                } else if (host.startsWith("*.")) {
+                    this.host = Pattern.compile("([a-z0-9.-]*\\.)?" + regexFromPattern(host.substring(2), false), Pattern.CASE_INSENSITIVE);
+                } else {
+                    this.host = Pattern.compile(regexFromPattern(host, false), Pattern.CASE_INSENSITIVE);
+                }
+                if (port == null || "*".equals(port)) {
+                    this.port = null;
+                } else {
+                    this.port = Integer.parseInt(port,10);
+                }
+                if (path == null || "/*".equals(path)) {
+                    this.path = null;
+                } else {
+                    this.path = Pattern.compile(regexFromPattern(path, true));
+                }
+            } catch (NumberFormatException e) {
+                throw new MalformedURLException("Port must be a number");
+            }
+        }
+
+        public boolean matches(Uri uri) {
+            try {
+                return ((scheme == null || scheme.matcher(uri.getScheme()).matches()) &&
+                        (host == null || host.matcher(uri.getHost()).matches()) &&
+                        (port == null || port.equals(uri.getPort())) &&
+                        (path == null || path.matcher(uri.getPath()).matches()));
+            } catch (Exception e) {
+                LOG.d(TAG, e.toString());
+                return false;
+            }
+        }
+    }
+
+    private ArrayList<URLPattern> whiteList;
+
+    public static final String TAG = "Whitelist";
+
+    public Whitelist() {
+        this.whiteList = new ArrayList<URLPattern>();
+    }
+
+    /* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
+     *
+     * <url-pattern> := <scheme>://<host><path>
+     * <scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'chrome-extension'
+     * <host> := '*' | '*.' <any char except '/' and '*'>+
+     * <path> := '/' <any chars>
+     *
+     * We extend this to explicitly allow a port attached to the host, and we allow
+     * the scheme to be omitted for backwards compatibility. (Also host is not required
+     * to begin with a "*" or "*.".)
+     */
+    public void addWhiteListEntry(String origin, boolean subdomains) {
+        if (whiteList != null) {
+            try {
+                // Unlimited access to network resources
+                if (origin.compareTo("*") == 0) {
+                    LOG.d(TAG, "Unlimited access to network resources");
+                    whiteList = null;
+                }
+                else { // specific access
+                    Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
+                    Matcher m = parts.matcher(origin);
+                    if (m.matches()) {
+                        String scheme = m.group(2);
+                        String host = m.group(4);
+                        // Special case for two urls which are allowed to have empty hosts
+                        if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
+                        String port = m.group(8);
+                        String path = m.group(9);
+                        if (scheme == null) {
+                            // XXX making it stupid friendly for people who forget to include protocol/SSL
+                            whiteList.add(new URLPattern("http", host, port, path));
+                            whiteList.add(new URLPattern("https", host, port, path));
+                        } else {
+                            whiteList.add(new URLPattern(scheme, host, port, path));
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                LOG.d(TAG, "Failed to add origin %s", origin);
+            }
+        }
+    }
+
+
+    /**
+     * Determine if URL is in approved list of URLs to load.
+     *
+     * @param uri
+     * @return true if wide open or whitelisted
+     */
+    public boolean isUrlWhiteListed(String uri) {
+        // If there is no whitelist, then it's wide open
+        if (whiteList == null) return true;
+
+        Uri parsedUri = Uri.parse(uri);
+        // Look for match in white list
+        Iterator<URLPattern> pit = whiteList.iterator();
+        while (pit.hasNext()) {
+            URLPattern p = pit.next();
+            if (p.matches(parsedUri)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java
new file mode 100644
index 0000000..3e5df51
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java
@@ -0,0 +1,73 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.engine;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.webkit.CookieManager;
+import android.webkit.WebView;
+
+import org.apache.cordova.ICordovaCookieManager;
+
+class SystemCookieManager implements ICordovaCookieManager {
+
+    protected final WebView webView;
+    private final CookieManager cookieManager;
+
+    //Added because lint can't see the conditional RIGHT ABOVE this
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public SystemCookieManager(WebView webview) {
+        webView = webview;
+        cookieManager = CookieManager.getInstance();
+
+        //REALLY? Nobody has seen this UNTIL NOW?
+        cookieManager.setAcceptFileSchemeCookies(true);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            cookieManager.setAcceptThirdPartyCookies(webView, true);
+        }
+    }
+
+    public void setCookiesEnabled(boolean accept) {
+        cookieManager.setAcceptCookie(accept);
+    }
+
+    public void setCookie(final String url, final String value) {
+        cookieManager.setCookie(url, value);
+    }
+
+    public String getCookie(final String url) {
+        return cookieManager.getCookie(url);
+    }
+
+    public void clearCookies() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            cookieManager.removeAllCookies(null);
+        } else {
+            cookieManager.removeAllCookie();
+        }
+    }
+
+    public void flush() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            cookieManager.flush();
+        }
+    }
+};
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java
new file mode 100755
index 0000000..94c3d93
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java
@@ -0,0 +1,53 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.engine;
+
+import android.webkit.JavascriptInterface;
+
+import org.apache.cordova.CordovaBridge;
+import org.apache.cordova.ExposedJsApi;
+import org.json.JSONException;
+
+/**
+ * Contains APIs that the JS can call. All functions in here should also have
+ * an equivalent entry in CordovaChromeClient.java, and be added to
+ * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
+ */
+class SystemExposedJsApi implements ExposedJsApi {
+    private final CordovaBridge bridge;
+
+    SystemExposedJsApi(CordovaBridge bridge) {
+        this.bridge = bridge;
+    }
+
+    @JavascriptInterface
+    public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
+        return bridge.jsExec(bridgeSecret, service, action, callbackId, arguments);
+    }
+
+    @JavascriptInterface
+    public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
+        bridge.jsSetNativeToJsBridgeMode(bridgeSecret, value);
+    }
+
+    @JavascriptInterface
+    public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
+        return bridge.jsRetrieveJsMessages(bridgeSecret, fromOnlineEvent);
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java
new file mode 100755
index 0000000..72846f0
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java
@@ -0,0 +1,280 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.engine;
+
+import java.util.Arrays;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions.Callback;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.PermissionRequest;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+
+import org.apache.cordova.CordovaDialogsHelper;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.LOG;
+
+/**
+ * This class is the WebChromeClient that implements callbacks for our web view.
+ * The kind of callbacks that happen here are on the chrome outside the document,
+ * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
+ * to but different than CordovaWebViewClient.
+ */
+public class SystemWebChromeClient extends WebChromeClient {
+
+    private static final int FILECHOOSER_RESULTCODE = 5173;
+    private static final String LOG_TAG = "SystemWebChromeClient";
+    private long MAX_QUOTA = 100 * 1024 * 1024;
+    protected final SystemWebViewEngine parentEngine;
+
+    // the video progress view
+    private View mVideoProgressView;
+
+    private CordovaDialogsHelper dialogsHelper;
+    private Context appContext;
+
+    private WebChromeClient.CustomViewCallback mCustomViewCallback;
+    private View mCustomView;
+
+    public SystemWebChromeClient(SystemWebViewEngine parentEngine) {
+        this.parentEngine = parentEngine;
+        appContext = parentEngine.webView.getContext();
+        dialogsHelper = new CordovaDialogsHelper(appContext);
+    }
+
+    /**
+     * Tell the client to display a javascript alert dialog.
+     */
+    @Override
+    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
+        dialogsHelper.showAlert(message, new CordovaDialogsHelper.Result() {
+            @Override public void gotResult(boolean success, String value) {
+                if (success) {
+                    result.confirm();
+                } else {
+                    result.cancel();
+                }
+            }
+        });
+        return true;
+    }
+
+    /**
+     * Tell the client to display a confirm dialog to the user.
+     */
+    @Override
+    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
+        dialogsHelper.showConfirm(message, new CordovaDialogsHelper.Result() {
+            @Override
+            public void gotResult(boolean success, String value) {
+                if (success) {
+                    result.confirm();
+                } else {
+                    result.cancel();
+                }
+            }
+        });
+        return true;
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * Since we are hacking prompts for our own purposes, we should not be using them for
+     * this purpose, perhaps we should hack console.log to do this instead!
+     */
+    @Override
+    public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) {
+        // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread.
+        String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);
+        if (handledRet != null) {
+            result.confirm(handledRet);
+        } else {
+            dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() {
+                @Override
+                public void gotResult(boolean success, String value) {
+                    if (success) {
+                        result.confirm(value);
+                    } else {
+                        result.cancel();
+                    }
+                }
+            });
+        }
+        return true;
+    }
+
+    /**
+     * Handle database quota exceeded notification.
+     */
+    @Override
+    @SuppressWarnings("deprecation")
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
+    {
+        LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
+        quotaUpdater.updateQuota(MAX_QUOTA);
+    }
+
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
+    {
+        if (consoleMessage.message() != null)
+            LOG.d(LOG_TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
+         return super.onConsoleMessage(consoleMessage);
+    }
+
+    @Override
+    /**
+     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+     *
+     * This also checks for the Geolocation Plugin and requests permission from the application  to use Geolocation.
+     *
+     * @param origin
+     * @param callback
+     */
+    public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        callback.invoke(origin, true, false);
+        //Get the plugin, it should be loaded
+        CordovaPlugin geolocation = parentEngine.pluginManager.getPlugin("Geolocation");
+        if(geolocation != null && !geolocation.hasPermisssion())
+        {
+            geolocation.requestPermissions(0);
+        }
+
+    }
+
+    // API level 7 is required for this, see if we could lower this using something else
+    @Override
+    @SuppressWarnings("deprecation")
+    public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+        parentEngine.getCordovaWebView().showCustomView(view, callback);
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    public void onHideCustomView() {
+        parentEngine.getCordovaWebView().hideCustomView();
+    }
+
+    @Override
+    /**
+     * Ask the host application for a custom progress view to show while
+     * a <video> is loading.
+     * @return View The progress view.
+     */
+    public View getVideoLoadingProgressView() {
+
+        if (mVideoProgressView == null) {
+            // Create a new Loading view programmatically.
+
+            // create the linear layout
+            LinearLayout layout = new LinearLayout(parentEngine.getView().getContext());
+            layout.setOrientation(LinearLayout.VERTICAL);
+            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+            layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
+            layout.setLayoutParams(layoutParams);
+            // the proress bar
+            ProgressBar bar = new ProgressBar(parentEngine.getView().getContext());
+            LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+            barLayoutParams.gravity = Gravity.CENTER;
+            bar.setLayoutParams(barLayoutParams);
+            layout.addView(bar);
+
+            mVideoProgressView = layout;
+        }
+    return mVideoProgressView;
+    }
+
+    // <input type=file> support:
+    // openFileChooser() is for pre KitKat and in KitKat mr1 (it's known broken in KitKat).
+    // For Lollipop, we use onShowFileChooser().
+    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        this.openFileChooser(uploadMsg, "*/*");
+    }
+
+    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
+        this.openFileChooser(uploadMsg, acceptType, null);
+    }
+
+    public void openFileChooser(final ValueCallback<Uri> uploadMsg, String acceptType, String capture)
+    {
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType("*/*");
+        parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
+            @Override
+            public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+                Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
+                LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
+                uploadMsg.onReceiveValue(result);
+            }
+        }, intent, FILECHOOSER_RESULTCODE);
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @Override
+    public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
+        Intent intent = fileChooserParams.createIntent();
+        try {
+            parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
+                @Override
+                public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+                    Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
+                    LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
+                    filePathsCallback.onReceiveValue(result);
+                }
+            }, intent, FILECHOOSER_RESULTCODE);
+        } catch (ActivityNotFoundException e) {
+            LOG.w("No activity found to handle file chooser intent.", e);
+            filePathsCallback.onReceiveValue(null);
+        }
+        return true;
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @Override
+    public void onPermissionRequest(final PermissionRequest request) {
+        LOG.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources()));
+        request.grant(request.getResources());
+    }
+
+    public void destroyLastDialog(){
+        dialogsHelper.destroyLastDialog();
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java
new file mode 100644
index 0000000..01c2f00
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java
@@ -0,0 +1,88 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.engine;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaWebViewEngine;
+
+/**
+ * Custom WebView subclass that enables us to capture events needed for Cordova.
+ */
+public class SystemWebView extends WebView implements CordovaWebViewEngine.EngineView {
+    private SystemWebViewClient viewClient;
+    SystemWebChromeClient chromeClient;
+    private SystemWebViewEngine parentEngine;
+    private CordovaInterface cordova;
+
+    public SystemWebView(Context context) {
+        this(context, null);
+    }
+
+    public SystemWebView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    // Package visibility to enforce that only SystemWebViewEngine should call this method.
+    void init(SystemWebViewEngine parentEngine, CordovaInterface cordova) {
+        this.cordova = cordova;
+        this.parentEngine = parentEngine;
+        if (this.viewClient == null) {
+            setWebViewClient(new SystemWebViewClient(parentEngine));
+        }
+
+        if (this.chromeClient == null) {
+            setWebChromeClient(new SystemWebChromeClient(parentEngine));
+        }
+    }
+
+    @Override
+    public CordovaWebView getCordovaWebView() {
+        return parentEngine != null ? parentEngine.getCordovaWebView() : null;
+    }
+
+    @Override
+    public void setWebViewClient(WebViewClient client) {
+        viewClient = (SystemWebViewClient)client;
+        super.setWebViewClient(client);
+    }
+
+    @Override
+    public void setWebChromeClient(WebChromeClient client) {
+        chromeClient = (SystemWebChromeClient)client;
+        super.setWebChromeClient(client);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        Boolean ret = parentEngine.client.onDispatchKeyEvent(event);
+        if (ret != null) {
+            return ret.booleanValue();
+        }
+        return super.dispatchKeyEvent(event);
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java
new file mode 100755
index 0000000..616cef1
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java
@@ -0,0 +1,370 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.engine;
+
+import android.annotation.TargetApi;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.Build;
+import android.webkit.ClientCertRequest;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import org.apache.cordova.AuthenticationToken;
+import org.apache.cordova.CordovaClientCertRequest;
+import org.apache.cordova.CordovaHttpAuthHandler;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginManager;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Hashtable;
+
+
+/**
+ * This class is the WebViewClient that implements callbacks for our web view.
+ * The kind of callbacks that happen here are regarding the rendering of the
+ * document instead of the chrome surrounding it, such as onPageStarted(), 
+ * shouldOverrideUrlLoading(), etc. Related to but different than
+ * CordovaChromeClient.
+ */
+public class SystemWebViewClient extends WebViewClient {
+
+    private static final String TAG = "SystemWebViewClient";
+    protected final SystemWebViewEngine parentEngine;
+    private boolean doClearHistory = false;
+    boolean isCurrentlyLoading;
+
+    /** The authorization tokens. */
+    private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
+
+    public SystemWebViewClient(SystemWebViewEngine parentEngine) {
+        this.parentEngine = parentEngine;
+    }
+
+    /**
+     * Give the host application a chance to take over the control when a new url
+     * is about to be loaded in the current WebView.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param url           The url to be loaded.
+     * @return              true to override, false for default behavior
+     */
+    @Override
+    @SuppressWarnings("deprecation")
+    public boolean shouldOverrideUrlLoading(WebView view, String url) {
+        return parentEngine.client.onNavigationAttempt(url);
+    }
+
+    /**
+     * On received http auth request.
+     * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
+     */
+    @Override
+    public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
+
+        // Get the authentication token (if specified)
+        AuthenticationToken token = this.getAuthenticationToken(host, realm);
+        if (token != null) {
+            handler.proceed(token.getUserName(), token.getPassword());
+            return;
+        }
+
+        // Check if there is some plugin which can resolve this auth challenge
+        PluginManager pluginManager = this.parentEngine.pluginManager;
+        if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(null, new CordovaHttpAuthHandler(handler), host, realm)) {
+            parentEngine.client.clearLoadTimeoutTimer();
+            return;
+        }
+
+        // By default handle 401 like we'd normally do!
+        super.onReceivedHttpAuthRequest(view, handler, host, realm);
+    }
+    
+    /**
+     * On received client cert request.
+     * The method forwards the request to any running plugins before using the default implementation.
+     *
+     * @param view
+     * @param request
+     */
+    @Override
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public void onReceivedClientCertRequest (WebView view, ClientCertRequest request)
+    {
+
+        // Check if there is some plugin which can resolve this certificate request
+        PluginManager pluginManager = this.parentEngine.pluginManager;
+        if (pluginManager != null && pluginManager.onReceivedClientCertRequest(null, new CordovaClientCertRequest(request))) {
+            parentEngine.client.clearLoadTimeoutTimer();
+            return;
+        }
+
+        // By default pass to WebViewClient
+        super.onReceivedClientCertRequest(view, request);
+    }
+
+    /**
+     * Notify the host application that a page has started loading.
+     * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
+     * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
+     * embedded frame changes, i.e. clicking a link whose target is an iframe.
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageStarted(WebView view, String url, Bitmap favicon) {
+        super.onPageStarted(view, url, favicon);
+        isCurrentlyLoading = true;
+        // Flush stale messages & reset plugins.
+        parentEngine.bridge.reset();
+        parentEngine.client.onPageStarted(url);
+    }
+
+    /**
+     * Notify the host application that a page has finished loading.
+     * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
+     *
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageFinished(WebView view, String url) {
+        super.onPageFinished(view, url);
+        // Ignore excessive calls, if url is not about:blank (CB-8317).
+        if (!isCurrentlyLoading && !url.startsWith("about:")) {
+            return;
+        }
+        isCurrentlyLoading = false;
+
+        /**
+         * Because of a timing issue we need to clear this history in onPageFinished as well as
+         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
+         * true. You see when you load a url with a # in it which is common in jQuery applications
+         * onPageStared is not called. Clearing the history at that point would break jQuery apps.
+         */
+        if (this.doClearHistory) {
+            view.clearHistory();
+            this.doClearHistory = false;
+        }
+        parentEngine.client.onPageFinishedLoading(url);
+
+    }
+
+    /**
+     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
+     * The errorCode parameter corresponds to one of the ERROR_* constants.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param errorCode     The error code corresponding to an ERROR_* value.
+     * @param description   A String describing the error.
+     * @param failingUrl    The url that failed to load.
+     */
+    @Override
+    @SuppressWarnings("deprecation")
+    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+        // Ignore error due to stopLoading().
+        if (!isCurrentlyLoading) {
+            return;
+        }
+        LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
+
+        // If this is a "Protocol Not Supported" error, then revert to the previous
+        // page. If there was no previous page, then punt. The application's config
+        // is likely incorrect (start page set to sms: or something like that)
+        if (errorCode == WebViewClient.ERROR_UNSUPPORTED_SCHEME) {
+            parentEngine.client.clearLoadTimeoutTimer();
+
+            if (view.canGoBack()) {
+                view.goBack();
+                return;
+            } else {
+                super.onReceivedError(view, errorCode, description, failingUrl);
+            }
+        }
+        parentEngine.client.onReceivedError(errorCode, description, failingUrl);
+    }
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a resource.
+     * The host application must call either handler.cancel() or handler.proceed().
+     * Note that the decision may be retained for use in response to future SSL errors.
+     * The default behavior is to cancel the load.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param handler       An SslErrorHandler object that will handle the user's response.
+     * @param error         The SSL error object.
+     */
+    @Override
+    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+
+        final String packageName = parentEngine.cordova.getActivity().getPackageName();
+        final PackageManager pm = parentEngine.cordova.getActivity().getPackageManager();
+
+        ApplicationInfo appInfo;
+        try {
+            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                // debug = true
+                handler.proceed();
+                return;
+            } else {
+                // debug = false
+                super.onReceivedSslError(view, handler, error);
+            }
+        } catch (NameNotFoundException e) {
+            // When it doubt, lock it out!
+            super.onReceivedSslError(view, handler, error);
+        }
+    }
+
+
+    /**
+     * Sets the authentication token.
+     *
+     * @param authenticationToken
+     * @param host
+     * @param realm
+     */
+    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
+        if (host == null) {
+            host = "";
+        }
+        if (realm == null) {
+            realm = "";
+        }
+        this.authenticationTokens.put(host.concat(realm), authenticationToken);
+    }
+
+    /**
+     * Removes the authentication token.
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token or null if did not exist
+     */
+    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
+        return this.authenticationTokens.remove(host.concat(realm));
+    }
+
+    /**
+     * Gets the authentication token.
+     *
+     * In order it tries:
+     * 1- host + realm
+     * 2- host
+     * 3- realm
+     * 4- no host, no realm
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token
+     */
+    public AuthenticationToken getAuthenticationToken(String host, String realm) {
+        AuthenticationToken token = null;
+        token = this.authenticationTokens.get(host.concat(realm));
+
+        if (token == null) {
+            // try with just the host
+            token = this.authenticationTokens.get(host);
+
+            // Try the realm
+            if (token == null) {
+                token = this.authenticationTokens.get(realm);
+            }
+
+            // if no host found, just query for default
+            if (token == null) {
+                token = this.authenticationTokens.get("");
+            }
+        }
+
+        return token;
+    }
+
+    /**
+     * Clear all authentication tokens.
+     */
+    public void clearAuthenticationTokens() {
+        this.authenticationTokens.clear();
+    }
+
+    @Override
+    @SuppressWarnings("deprecation")
+    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+        try {
+            // Check the against the whitelist and lock out access to the WebView directory
+            // Changing this will cause problems for your application
+            if (!parentEngine.pluginManager.shouldAllowRequest(url)) {
+                LOG.w(TAG, "URL blocked by whitelist: " + url);
+                // Results in a 404.
+                return new WebResourceResponse("text/plain", "UTF-8", null);
+            }
+
+            CordovaResourceApi resourceApi = parentEngine.resourceApi;
+            Uri origUri = Uri.parse(url);
+            // Allow plugins to intercept WebView requests.
+            Uri remappedUri = resourceApi.remapUri(origUri);
+
+            if (!origUri.equals(remappedUri) || needsSpecialsInAssetUrlFix(origUri) || needsKitKatContentUrlFix(origUri)) {
+                CordovaResourceApi.OpenForReadResult result = resourceApi.openForRead(remappedUri, true);
+                return new WebResourceResponse(result.mimeType, "UTF-8", result.inputStream);
+            }
+            // If we don't need to special-case the request, let the browser load it.
+            return null;
+        } catch (IOException e) {
+            if (!(e instanceof FileNotFoundException)) {
+                LOG.e(TAG, "Error occurred while loading a file (returning a 404).", e);
+            }
+            // Results in a 404.
+            return new WebResourceResponse("text/plain", "UTF-8", null);
+        }
+    }
+
+    private static boolean needsKitKatContentUrlFix(Uri uri) {
+        return "content".equals(uri.getScheme());
+    }
+
+    private static boolean needsSpecialsInAssetUrlFix(Uri uri) {
+        if (CordovaResourceApi.getUriType(uri) != CordovaResourceApi.URI_TYPE_ASSET) {
+            return false;
+        }
+        if (uri.getQuery() != null || uri.getFragment() != null) {
+            return true;
+        }
+
+        if (!uri.toString().contains("%")) {
+            return false;
+        }
+
+        return false;
+    }
+}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java
new file mode 100755
index 0000000..1cbd7f8
--- /dev/null
+++ b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java
@@ -0,0 +1,319 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.engine;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.os.Build;
+import android.view.View;
+import android.webkit.ValueCallback;
+import android.webkit.WebSettings;
+import android.webkit.WebSettings.LayoutAlgorithm;
+import android.webkit.WebView;
+
+import org.apache.cordova.CordovaBridge;
+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.ICordovaCookieManager;
+import org.apache.cordova.LOG;
+import org.apache.cordova.NativeToJsMessageQueue;
+import org.apache.cordova.PluginManager;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Glue class between CordovaWebView (main Cordova logic) and SystemWebView (the actual View).
+ * We make the Engine separate from the actual View so that:
+ *  A) We don't need to worry about WebView methods clashing with CordovaWebViewEngine methods
+ *     (e.g.: goBack() is void for WebView, and boolean for CordovaWebViewEngine)
+ *  B) Separating the actual View from the Engine makes API surfaces smaller.
+ * Class uses two-phase initialization. However, CordovaWebView is responsible for calling .init().
+ */
+public class SystemWebViewEngine implements CordovaWebViewEngine {
+    public static final String TAG = "SystemWebViewEngine";
+
+    protected final SystemWebView webView;
+    protected final SystemCookieManager cookieManager;
+    protected CordovaPreferences preferences;
+    protected CordovaBridge bridge;
+    protected CordovaWebViewEngine.Client client;
+    protected CordovaWebView parentWebView;
+    protected CordovaInterface cordova;
+    protected PluginManager pluginManager;
+    protected CordovaResourceApi resourceApi;
+    protected NativeToJsMessageQueue nativeToJsMessageQueue;
+    private BroadcastReceiver receiver;
+
+    /** Used when created via reflection. */
+    public SystemWebViewEngine(Context context, CordovaPreferences preferences) {
+        this(new SystemWebView(context), preferences);
+    }
+
+    public SystemWebViewEngine(SystemWebView webView) {
+        this(webView, null);
+    }
+
+    public SystemWebViewEngine(SystemWebView webView, CordovaPreferences preferences) {
+        this.preferences = preferences;
+        this.webView = webView;
+        cookieManager = new SystemCookieManager(webView);
+    }
+
+    @Override
+    public void init(CordovaWebView parentWebView, CordovaInterface cordova, CordovaWebViewEngine.Client client,
+              CordovaResourceApi resourceApi, PluginManager pluginManager,
+              NativeToJsMessageQueue nativeToJsMessageQueue) {
+        if (this.cordova != null) {
+            throw new IllegalStateException();
+        }
+        // Needed when prefs are not passed by the constructor
+        if (preferences == null) {
+            preferences = parentWebView.getPreferences();
+        }
+        this.parentWebView = parentWebView;
+        this.cordova = cordova;
+        this.client = client;
+        this.resourceApi = resourceApi;
+        this.pluginManager = pluginManager;
+        this.nativeToJsMessageQueue = nativeToJsMessageQueue;
+        webView.init(this, cordova);
+
+        initWebViewSettings();
+
+        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode.OnlineEventsBridgeModeDelegate() {
+            @Override
+            public void setNetworkAvailable(boolean value) {
+                //sometimes this can be called after calling webview.destroy() on destroy()
+                //thus resulting in a NullPointerException
+                if(webView!=null) {
+                   webView.setNetworkAvailable(value); 
+                }
+            }
+            @Override
+            public void runOnUiThread(Runnable r) {
+                SystemWebViewEngine.this.cordova.getActivity().runOnUiThread(r);
+            }
+        }));
+        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.EvalBridgeMode(this, cordova));
+        bridge = new CordovaBridge(pluginManager, nativeToJsMessageQueue);
+        exposeJsInterface(webView, bridge);
+    }
+
+    @Override
+    public CordovaWebView getCordovaWebView() {
+        return parentWebView;
+    }
+
+    @Override
+    public ICordovaCookieManager getCookieManager() {
+        return cookieManager;
+    }
+
+    @Override
+    public View getView() {
+        return webView;
+    }
+
+    @SuppressLint({"NewApi", "SetJavaScriptEnabled"})
+    @SuppressWarnings("deprecation")
+    private void initWebViewSettings() {
+        webView.setInitialScale(0);
+        webView.setVerticalScrollBarEnabled(false);
+        // Enable JavaScript
+        final WebSettings settings = webView.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
+
+        String manufacturer = android.os.Build.MANUFACTURER;
+        LOG.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
+
+        //We don't save any form data in the application
+        settings.setSaveFormData(false);
+        settings.setSavePassword(false);
+
+        // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
+        // while we do this
+        settings.setAllowUniversalAccessFromFileURLs(true);
+        settings.setMediaPlaybackRequiresUserGesture(false);
+
+        // Enable database
+        // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
+        String databasePath = webView.getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
+        settings.setDatabaseEnabled(true);
+        settings.setDatabasePath(databasePath);
+
+
+        //Determine whether we're in debug or release mode, and turn on Debugging!
+        ApplicationInfo appInfo = webView.getContext().getApplicationContext().getApplicationInfo();
+        if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+            enableRemoteDebugging();
+        }
+
+        settings.setGeolocationDatabasePath(databasePath);
+
+        // Enable DOM storage
+        settings.setDomStorageEnabled(true);
+
+        // Enable built-in geolocation
+        settings.setGeolocationEnabled(true);
+
+        // Enable AppCache
+        // Fix for CB-2282
+        settings.setAppCacheMaxSize(5 * 1048576);
+        settings.setAppCachePath(databasePath);
+        settings.setAppCacheEnabled(true);
+
+        // Fix for CB-1405
+        // Google issue 4641
+        String defaultUserAgent = settings.getUserAgentString();
+
+        // Fix for CB-3360
+        String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
+        if (overrideUserAgent != null) {
+            settings.setUserAgentString(overrideUserAgent);
+        } else {
+            String appendUserAgent = preferences.getString("AppendUserAgent", null);
+            if (appendUserAgent != null) {
+                settings.setUserAgentString(defaultUserAgent + " " + appendUserAgent);
+            }
+        }
+        // End CB-3360
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        if (this.receiver == null) {
+            this.receiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    settings.getUserAgentString();
+                }
+            };
+            webView.getContext().registerReceiver(this.receiver, intentFilter);
+        }
+        // end CB-1405
+    }
+
+    private void enableRemoteDebugging() {
+        try {
+            WebView.setWebContentsDebuggingEnabled(true);
+        } catch (IllegalArgumentException e) {
+            LOG.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
+            e.printStackTrace();
+        }
+    }
+
+    // Yeah, we know. It'd be great if lint was just a little smarter.
+    @SuppressLint("AddJavascriptInterface")
+    private static void exposeJsInterface(WebView webView, CordovaBridge bridge) {
+        SystemExposedJsApi exposedJsApi = new SystemExposedJsApi(bridge);
+        webView.addJavascriptInterface(exposedJsApi, "_cordovaNative");
+    }
+
+
+    /**
+     * Load the url into the webview.
+     */
+    @Override
+    public void loadUrl(final String url, boolean clearNavigationStack) {
+        webView.loadUrl(url);
+    }
+
+    @Override
+    public String getUrl() {
+        return webView.getUrl();
+    }
+
+    @Override
+    public void stopLoading() {
+        webView.stopLoading();
+    }
+
+    @Override
+    public void clearCache() {
+        webView.clearCache(true);
+    }
+
+    @Override
+    public void clearHistory() {
+        webView.clearHistory();
+    }
+
+    @Override
+    public boolean canGoBack() {
+        return webView.canGoBack();
+    }
+
+    /**
+     * Go to previous page in history.  (We manage our own history)
+     *
+     * @return true if we went back, false if we are already at top
+     */
+    @Override
+    public boolean goBack() {
+        // Check webview first to see if there is a history
+        // This is needed to support curPage#diffLink, since they are added to parentEngine's history, but not our history url array (JQMobile behavior)
+        if (webView.canGoBack()) {
+            webView.goBack();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void setPaused(boolean value) {
+        if (value) {
+            webView.onPause();
+            webView.pauseTimers();
+        } else {
+            webView.onResume();
+            webView.resumeTimers();
+        }
+    }
+
+    @Override
+    public void destroy() {
+        webView.chromeClient.destroyLastDialog();
+        webView.destroy();
+        // unregister the receiver
+        if (receiver != null) {
+            try {
+                webView.getContext().unregisterReceiver(receiver);
+            } catch (Exception e) {
+                LOG.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
+            }
+        }
+    }
+
+    @Override
+    public void evaluateJavascript(String js, ValueCallback<String> callback) {
+        webView.evaluateJavascript(js, callback);
+    }
+}
diff --git a/platforms/android/android.json b/platforms/android/android.json
new file mode 100644
index 0000000..825de01
--- /dev/null
+++ b/platforms/android/android.json
@@ -0,0 +1,490 @@
+{
+  "prepare_queue": {
+    "installed": [],
+    "uninstalled": []
+  },
+  "config_munge": {
+    "files": {
+      "res/xml/config.xml": {
+        "parents": {
+          "/*": [
+            {
+              "xml": "<feature name=\"Fingerprint\"><param name=\"android-package\" value=\"de.niklasmerz.cordova.fingerprint.Fingerprint\" /></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=\"File\"><param name=\"android-package\" value=\"org.apache.cordova.file.FileUtils\" /><param name=\"onload\" value=\"true\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<allow-navigation href=\"cdvfile:*\" />",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"CordovaHttpPlugin\"><param name=\"android-package\" value=\"com.silkimen.cordovahttp.CordovaHttpPlugin\" /></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=\"QRScanner\"><param name=\"android-package\" value=\"com.bitpay.cordova.qrscanner.QRScanner\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Camera\"><param name=\"android-package\" value=\"org.apache.cordova.camera.CameraLauncher\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Device\"><param name=\"android-package\" value=\"org.apache.cordova.device.Device\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"ThemeableBrowser\"><param name=\"android-package\" value=\"com.initialxy.cordova.themeablebrowser.ThemeableBrowser\" /></feature>",
+              "count": 1
+            }
+          ]
+        }
+      },
+      "AndroidManifest.xml": {
+        "parents": {
+          "/*": [
+            {
+              "xml": "<uses-permission android:name=\"android.permission.USE_FINGERPRINT\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
+              "count": 2
+            },
+            {
+              "xml": "<uses-permission android:name=\"android.permission.CAMERA\" android:required=\"false\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-feature android:name=\"android.hardware.camera\" android:required=\"false\" />",
+              "count": 1
+            },
+            {
+              "xml": "<uses-feature android:name=\"android.hardware.camera.front\" android:required=\"false\" />",
+              "count": 1
+            }
+          ],
+          "/manifest": [
+            {
+              "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=\"org.apache.cordova.camera.FileProvider\"><meta-data android:name=\"android.support.FILE_PROVIDER_PATHS\" android:resource=\"@xml/camera_provider_paths\" /></provider>",
+              "count": 1
+            }
+          ]
+        }
+      },
+      "*-Info.plist": {
+        "parents": {
+          "NSCameraUsageDescription": [
+            {
+              "xml": "<string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>",
+              "count": 1,
+              "mode": "merge",
+              "id": "config.xml"
+            }
+          ]
+        }
+      }
+    }
+  },
+  "installed_plugins": {
+    "cordova-plugin-add-swift-support": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-fingerprint-aio": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-touch-id": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-whitelist": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-file": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-advanced-http": {
+      "OKHTTP_VERSION": "3.10.0",
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-statusbar": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-disable-ios11-statusbar": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-qrscanner": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-camera": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-inappbrowser": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-device": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-themeablebrowser": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    }
+  },
+  "dependent_plugins": {},
+  "modules": [
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.androidFileSystem",
+      "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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-inappbrowser.inappbrowser",
+      "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+      "pluginId": "cordova-plugin-inappbrowser",
+      "clobbers": [
+        "cordova.InAppBrowser.open",
+        "window.open"
+      ]
+    },
+    {
+      "id": "cordova-plugin-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ],
+  "plugin_metadata": {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  }
+}
diff --git a/platforms/android/app/build.gradle b/platforms/android/app/build.gradle
new file mode 100644
index 0000000..871aabb
--- /dev/null
+++ b/platforms/android/app/build.gradle
@@ -0,0 +1,333 @@
+/*
+       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.
+*/
+
+apply plugin: 'com.android.application'
+
+buildscript {
+    repositories {
+        mavenCentral()
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.3.0'
+    }
+}
+
+// Allow plugins to declare Maven dependencies via build-extras.gradle.
+allprojects {
+    repositories {
+        mavenCentral()
+        jcenter()
+    }
+}
+
+task wrapper(type: Wrapper) {
+    gradleVersion = '4.10.3'
+}
+
+// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
+// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
+ext {
+    apply from: '../CordovaLib/cordova.gradle'
+
+    // The value for android.compileSdkVersion.
+    if (!project.hasProperty('cdvCompileSdkVersion')) {
+        cdvCompileSdkVersion = null;
+    }
+    // The value for android.buildToolsVersion.
+    if (!project.hasProperty('cdvBuildToolsVersion')) {
+        cdvBuildToolsVersion = null;
+    }
+    // Sets the versionCode to the given value.
+    if (!project.hasProperty('cdvVersionCode')) {
+        cdvVersionCode = null
+    }
+    // Sets the minSdkVersion to the given value.
+    if (!project.hasProperty('cdvMinSdkVersion')) {
+        cdvMinSdkVersion = null
+    }
+    // Whether to build architecture-specific APKs.
+    if (!project.hasProperty('cdvBuildMultipleApks')) {
+        cdvBuildMultipleApks = null
+    }
+    // Whether to append a 0 "abi digit" to versionCode when only a single APK is build
+    if (!project.hasProperty('cdvVersionCodeForceAbiDigit')) {
+        cdvVersionCodeForceAbiDigit = null
+    }
+    // .properties files to use for release signing.
+    if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
+        cdvReleaseSigningPropertiesFile = null
+    }
+    // .properties files to use for debug signing.
+    if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
+        cdvDebugSigningPropertiesFile = null
+    }
+    // Set by build.js script.
+    if (!project.hasProperty('cdvBuildArch')) {
+        cdvBuildArch = null
+    }
+
+    // Plugin gradle extensions can append to this to have code run at the end.
+    cdvPluginPostBuildExtras = []
+}
+
+// PLUGIN GRADLE EXTENSIONS START
+apply from: "../cordova-plugin-qrscanner/dlapp-qrscanner.gradle"
+// PLUGIN GRADLE EXTENSIONS END
+
+def hasBuildExtras1 = file('build-extras.gradle').exists()
+if (hasBuildExtras1) {
+    apply from: 'build-extras.gradle'
+}
+
+def hasBuildExtras2 = file('../build-extras.gradle').exists()
+if (hasBuildExtras2) {
+    apply from: '../build-extras.gradle'
+}
+
+// Set property defaults after extension .gradle files.
+if (ext.cdvCompileSdkVersion == null) {
+    ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
+    //ext.cdvCompileSdkVersion = project.ext.defaultCompileSdkVersion
+}
+if (ext.cdvBuildToolsVersion == null) {
+    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
+    //ext.cdvBuildToolsVersion = project.ext.defaultBuildToolsVersion
+}
+if (ext.cdvDebugSigningPropertiesFile == null && file('../debug-signing.properties').exists()) {
+    ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
+}
+if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.properties').exists()) {
+    ext.cdvReleaseSigningPropertiesFile = '../release-signing.properties'
+}
+
+// Cast to appropriate types.
+ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
+ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false : cdvVersionCodeForceAbiDigit.toBoolean();
+ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : Integer.parseInt('' + cdvMinSdkVersion)
+ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
+
+def computeBuildTargetName(debugBuild) {
+    def ret = 'assemble'
+    if (cdvBuildMultipleApks && cdvBuildArch) {
+        def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
+        ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
+    }
+    return ret + (debugBuild ? 'Debug' : 'Release')
+}
+
+// Make cdvBuild a task that depends on the debug/arch-sepecific task.
+task cdvBuildDebug
+cdvBuildDebug.dependsOn {
+    return computeBuildTargetName(true)
+}
+
+task cdvBuildRelease
+cdvBuildRelease.dependsOn {
+    return computeBuildTargetName(false)
+}
+
+task cdvPrintProps {
+    doLast {
+        println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
+        println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
+        println('cdvVersionCode=' + cdvVersionCode)
+        println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
+        println('cdvMinSdkVersion=' + cdvMinSdkVersion)
+        println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
+        println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
+        println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
+        println('cdvBuildArch=' + cdvBuildArch)
+        println('computedVersionCode=' + android.defaultConfig.versionCode)
+        android.productFlavors.each { flavor ->
+            println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
+        }
+    }
+}
+
+android {
+    defaultConfig {
+        versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
+        applicationId privateHelpers.extractStringFromManifest("package")
+
+        if (cdvMinSdkVersion != null) {
+            minSdkVersion cdvMinSdkVersion
+        }
+    }
+
+    lintOptions {
+      abortOnError false;
+    }
+
+    compileSdkVersion cdvCompileSdkVersion
+    buildToolsVersion cdvBuildToolsVersion
+
+    // This code exists for Crosswalk and other Native APIs.
+    // By default, we multiply the existing version code in the
+    // Android Manifest by 10 and add a number for each architecture.
+    // If you are not using Crosswalk or SQLite, you can
+    // ignore this chunk of code, and your version codes will be respected.
+
+    if (Boolean.valueOf(cdvBuildMultipleApks)) {
+        flavorDimensions "default"
+
+        productFlavors {
+            armeabi {
+                versionCode defaultConfig.versionCode*10 + 1
+                ndk {
+                    abiFilters = ["armeabi"]
+                }
+            }
+            armv7 {
+                versionCode defaultConfig.versionCode*10 + 2
+                ndk {
+                    abiFilters = ["armeabi-v7a"]
+                }
+            }
+            arm64 {
+                versionCode defaultConfig.versionCode*10 + 3
+                ndk {
+                    abiFilters = ["arm64-v8a"]
+                }
+            }
+            x86 {
+                versionCode defaultConfig.versionCode*10 + 4
+                ndk {
+                    abiFilters = ["x86"]
+                }
+            }
+            x86_64 {
+                versionCode defaultConfig.versionCode*10 + 5
+                ndk {
+                    abiFilters = ["x86_64"]
+                }
+            }
+        }
+    } else if (Boolean.valueOf(cdvVersionCodeForceAbiDigit)) {
+        // This provides compatibility to the default logic for versionCode before cordova-android 5.2.0
+        defaultConfig {
+            versionCode defaultConfig.versionCode*10
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    if (cdvReleaseSigningPropertiesFile) {
+        signingConfigs {
+            release {
+                // These must be set or Gradle will complain (even if they are overridden).
+                keyAlias = ""
+                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
+                storeFile = null
+                storePassword = "__unset"
+            }
+        }
+        buildTypes {
+            release {
+                signingConfig signingConfigs.release
+            }
+        }
+        addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
+    }
+
+    if (cdvDebugSigningPropertiesFile) {
+        addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
+    }
+}
+
+/*
+ * WARNING: Cordova Lib and platform scripts do management inside of this code here,
+ * if you are adding the dependencies manually, do so outside the comments, otherwise
+ * the Cordova tools will overwrite them
+ */
+
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: '*.jar')
+    // SUB-PROJECT DEPENDENCIES START
+    implementation(project(path: ":CordovaLib"))
+    implementation "com.squareup.okhttp3:okhttp-urlconnection:3.10.0"
+    implementation "com.android.support:support-v4:24.1.1+"
+    // SUB-PROJECT DEPENDENCIES END
+}
+
+def promptForReleaseKeyPassword() {
+    if (!cdvReleaseSigningPropertiesFile) {
+        return;
+    }
+    if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
+        android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
+    }
+    if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
+        android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
+    }
+}
+
+gradle.taskGraph.whenReady { taskGraph ->
+    taskGraph.getAllTasks().each() { task ->
+      if(['validateReleaseSigning', 'validateSigningRelease', 'validateSigningArmv7Release', 'validateSigningX76Release'].contains(task.name)) {
+         promptForReleaseKeyPassword()
+      }
+    }
+}
+
+def addSigningProps(propsFilePath, signingConfig) {
+    def propsFile = file(propsFilePath)
+    def props = new Properties()
+    propsFile.withReader { reader ->
+        props.load(reader)
+    }
+
+    def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
+    if (!storeFile.isAbsolute()) {
+        storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
+    }
+    if (!storeFile.exists()) {
+        throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
+    }
+    signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
+    signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
+    signingConfig.storeFile = storeFile
+    signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
+    def storeType = props.get('storeType', props.get('key.store.type', ''))
+    if (!storeType) {
+        def filename = storeFile.getName().toLowerCase();
+        if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
+            storeType = 'pkcs12'
+        } else {
+            storeType = signingConfig.storeType // "jks"
+        }
+    }
+    signingConfig.storeType = storeType
+}
+
+for (def func : cdvPluginPostBuildExtras) {
+    func()
+}
+
+// This can be defined within build-extras.gradle as:
+//     ext.postBuildExtras = { ... code here ... }
+if (hasProperty('postBuildExtras')) {
+    postBuildExtras()
+}
diff --git a/platforms/android/app/src/main/AndroidManifest.xml b/platforms/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5a16756
--- /dev/null
+++ b/platforms/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8'?>
+<manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="com.supwisdom.dlapp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <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/ic_launcher" android:label="@string/app_name" android:supportsRtl="true">
+        <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
+            <intent-filter android:label="@string/launcher_name">
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <provider android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true" android:name="org.apache.cordova.camera.FileProvider">
+            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/camera_provider_paths" />
+        </provider>
+    </application>
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
+    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.CAMERA" android:required="false" />
+    <uses-feature android:name="android.hardware.camera" android:required="false" />
+    <uses-feature android:name="android.hardware.camera.front" android:required="false" />
+</manifest>
diff --git a/platforms/android/app/src/main/assets/www/bill.html b/platforms/android/app/src/main/assets/www/bill.html
new file mode 100644
index 0000000..e70285f
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/bill.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>账单</title>
+</head>
+
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账单</div>
+    </header>
+    <div style="overflow: scroll;position: absolute;top:74px;bottom:0px;left: 0;right: 0">
+        <div class="aui-card-list" id="billcontent">
+            
+        </div>
+         <div class="aui-card-list-footer aui-text-center" id="loadNext" onclick="app.loadNext()" style="background:#fff;display: none;">
+            继续加载
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/bill.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/billdetail.html b/platforms/android/app/src/main/assets/www/billdetail.html
new file mode 100644
index 0000000..8bbde06
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/billdetail.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>账单详情</title>
+</head>
+
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账单详情</div>
+    </header>
+    <header class="demos-header">
+      <h1 class="demos-title" id="amount"></h1>
+      <h1 class="detail-title" id="status"></h1>
+    </header>
+    <div class="weui-form-preview">
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">交易名称</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="tranddes">&nbsp;</em>
+        </div>
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">交易时间</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="transtime">&nbsp;</em>
+        </div>
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">订单编号</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="refno">&nbsp;</em>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/billdetail.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/bindcard.html b/platforms/android/app/src/main/assets/www/bindcard.html
new file mode 100644
index 0000000..3ec9d26
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/bindcard.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>绑定银行卡</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">绑定银行卡</div>
+    </header>
+    <div>
+        <div class="weui-cells__title">市民卡信息</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">姓名</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="text" id="name" style="font-size: 14px;" placeholder="请输入您的真实姓名">
+                </div>
+            </div>
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">银行卡号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="text" id="cardnum" style="font-size: 14px;" placeholder="市民卡对应的银行卡号">
+                </div>
+            </div>
+        </div>
+
+        <div class="weui-cells__title">短信验证市民卡预留的手机号</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" disabled="disabled" >
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">下一步</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/bindcard.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/card.html b/platforms/android/app/src/main/assets/www/card.html
new file mode 100644
index 0000000..3c48354
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/card.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>市民卡挂失</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">市民卡挂失</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd"  pattern="[0-9]*" placeholder="请输入支付密码" maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">挂失</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/card.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/cordova-js-src/android/nativeapiprovider.js b/platforms/android/app/src/main/assets/www/cordova-js-src/android/nativeapiprovider.js
new file mode 100644
index 0000000..2e9aa67
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova-js-src/android/nativeapiprovider.js
@@ -0,0 +1,36 @@
+/*
+ * 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.
+*/
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
diff --git a/platforms/android/app/src/main/assets/www/cordova-js-src/android/promptbasednativeapi.js b/platforms/android/app/src/main/assets/www/cordova-js-src/android/promptbasednativeapi.js
new file mode 100644
index 0000000..f7fb6bc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova-js-src/android/promptbasednativeapi.js
@@ -0,0 +1,35 @@
+/*
+ * 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.
+*/
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
diff --git a/platforms/android/app/src/main/assets/www/cordova-js-src/exec.js b/platforms/android/app/src/main/assets/www/cordova-js-src/exec.js
new file mode 100644
index 0000000..39e8c97
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova-js-src/exec.js
@@ -0,0 +1,286 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1
+    },
+    nativeToJsModes = {
+        // Polls for messages using the JS->Native bridge.
+        POLLING: 0,
+        // For LOAD_URL to be viable, it would need to have a work-around for
+        // the bug where the soft-keyboard gets dismissed when a message is sent.
+        LOAD_URL: 1,
+        // For the ONLINE_EVENT to be viable, it would need to intercept all event
+        // listeners (both through addEventListener and window.ononline) as well
+        // as set the navigator property itself.
+        ONLINE_EVENT: 2,
+        EVAL_BRIDGE: 3
+    },
+    jsToNativeBridgeMode,  // Set lazily.
+    nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
+    pollEnabled = false,
+    bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
+
+function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
+    // Set default bridge modes if they have not already been set.
+    // By default, we use the failsafe, since addJavascriptInterface breaks too often
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    }
+
+    // If args is not provided, default to an empty array
+    args = args || [];
+
+    // Process any ArrayBuffers in the args into a string.
+    for (var i = 0; i < args.length; i++) {
+        if (utils.typeName(args[i]) == 'ArrayBuffer') {
+            args[i] = base64.fromArrayBuffer(args[i]);
+        }
+    }
+
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
+
+    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    } else if (msgs) {
+        messagesFromNative.push(msgs);
+        // Always process async to avoid exceptions messing up stack.
+        nextTick(processMessages);
+    }
+}
+
+androidExec.init = function() {
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
+
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+    if (msgs) {
+        messagesFromNative.push(msgs);
+        // Process sync since we know we're already top-of-stack.
+        processMessages();
+    }
+}
+
+function pollingTimerFunc() {
+    if (pollEnabled) {
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
+    }
+}
+
+function hookOnlineApis() {
+    function proxyEvent(e) {
+        cordova.fireWindowEvent(e.type);
+    }
+    // The network module takes care of firing online and offline events.
+    // It currently fires them only on document though, so we bridge them
+    // to window here (while first listening for exec()-releated online/offline
+    // events).
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+    cordova.addWindowEventHandler('online');
+    cordova.addWindowEventHandler('offline');
+    document.addEventListener('online', proxyEvent, false);
+    document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+        mode = jsToNativeModes.PROMPT;
+    }
+    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
+    jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
+        pollEnabled = false;
+    }
+
+    nativeToJsBridgeMode = mode;
+    // Tell the native side to switch modes.
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
+
+    if (mode == nativeToJsModes.POLLING) {
+        pollEnabled = true;
+        setTimeout(pollingTimerFunc, 1);
+    }
+};
+
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        payload.push(base64.toArrayBuffer(data));
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    var firstChar = message.charAt(0);
+    if (firstChar == 'J') {
+        // This is deprecated on the .java side. It doesn't work with CSP enabled.
+        eval(message.slice(1));
+    } else if (firstChar == 'S' || firstChar == 'F') {
+        var success = firstChar == 'S';
+        var keepCallback = message.charAt(1) == '1';
+        var spaceIdx = message.indexOf(' ', 2);
+        var status = +message.slice(2, spaceIdx);
+        var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+        var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+        var payloadMessage = message.slice(nextSpaceIdx + 1);
+        var payload = [];
+        buildPayload(payload, payloadMessage);
+        cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+    } else {
+        console.log("processMessage failed: invalid message: " + JSON.stringify(message));
+    }
+}
+
+function processMessages() {
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (messagesFromNative.length === 0) {
+        return;
+    }
+    isProcessing = true;
+    try {
+        var msg = popMessageFromQueue();
+        // The Java side can send a * message to indicate that it
+        // still has messages waiting to be retrieved.
+        if (msg == '*' && messagesFromNative.length === 0) {
+            nextTick(pollOnce);
+            return;
+        }
+        processMessage(msg);
+    } finally {
+        isProcessing = false;
+        if (messagesFromNative.length > 0) {
+            nextTick(processMessages);
+        }
+    }
+}
+
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
+module.exports = androidExec;
diff --git a/platforms/android/app/src/main/assets/www/cordova-js-src/platform.js b/platforms/android/app/src/main/assets/www/cordova-js-src/platform.js
new file mode 100644
index 0000000..2bfd024
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova-js-src/platform.js
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+    id: 'android',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
+
+        // Get the shared secret needed to use the bridge.
+        exec.init();
+
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+        var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+        // Inject a listener for the backbutton on the document.
+        var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+        backButtonChannel.onHasSubscribersChange = function() {
+            // If we just attached the first handler or detached the last handler,
+            // let native know we need to override the back button.
+            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
+        };
+
+        // Add hardware MENU and SEARCH button handlers
+        cordova.addDocumentEventHandler('menubutton');
+        cordova.addDocumentEventHandler('searchbutton');
+
+        function bindButtonChannel(buttonName) {
+            // generic button bind used for volumeup/volumedown buttons
+            var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+            volumeButtonChannel.onHasSubscribersChange = function() {
+                exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
+            };
+        }
+        // Inject a listener for the volume buttons on the document.
+        bindButtonChannel('volumeup');
+        bindButtonChannel('volumedown');
+
+        // The resume event is not "sticky", but it is possible that the event
+        // will contain the result of a plugin call. We need to ensure that the
+        // plugin result is delivered even after the event is fired (CB-10498)
+        var cordovaAddEventListener = document.addEventListener;
+
+        document.addEventListener = function(evt, handler, capture) {
+            cordovaAddEventListener(evt, handler, capture);
+
+            if (evt === 'resume' && lastResumeEvent) {
+                handler(lastResumeEvent);
+            }
+        };
+
+        // Let native code know we are all done on the JS side.
+        // Native code will then un-hide the WebView.
+        channel.onCordovaReady.subscribe(function() {
+            exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+            exec(null, null, APP_PLUGIN_NAME, "show", []);
+        });
+    }
+};
+
+function onMessageFromNative(msg) {
+    var cordova = require('cordova');
+    var action = msg.action;
+
+    switch (action)
+    {
+        // Button events
+        case 'backbutton':
+        case 'menubutton':
+        case 'searchbutton':
+        // App life cycle events
+        case 'pause':
+        // Volume events
+        case 'volumedownbutton':
+        case 'volumeupbutton':
+            cordova.fireDocumentEvent(action);
+            break;
+        case 'resume':
+            if(arguments.length > 1 && msg.pendingResult) {
+                if(arguments.length === 2) {
+                    msg.pendingResult.result = arguments[1];
+                } else {
+                    // The plugin returned a multipart message
+                    var res = [];
+                    for(var i = 1; i < arguments.length; i++) {
+                        res.push(arguments[i]);
+                    }
+                    msg.pendingResult.result = res;
+                }
+
+                // Save the plugin result so that it can be delivered to the js
+                // even if they miss the initial firing of the event
+                lastResumeEvent = msg;
+            }
+            cordova.fireDocumentEvent(action, msg);
+            break;
+        default:
+            throw new Error('Unknown event action ' + action);
+    }
+}
diff --git a/platforms/android/app/src/main/assets/www/cordova-js-src/plugin/android/app.js b/platforms/android/app/src/main/assets/www/cordova-js-src/plugin/android/app.js
new file mode 100644
index 0000000..22cf96e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova-js-src/plugin/android/app.js
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
+    },
+
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
+    },
+
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
+    },
+
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
+    },
+
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
+    },
+
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
+    },
+
+    /**
+    * Override the default behavior of the Android volume button.
+    * If overridden, when the volume button is pressed, the "volume[up|down]button"
+    * JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "volume[up|down]button" event, this is automatically done.
+    *
+    * @param button          volumeup, volumedown
+    * @param override        T=override, F=cancel override
+    */
+    overrideButton:function(button, override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
+    },
+
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
+    }
+};
diff --git a/platforms/android/app/src/main/assets/www/cordova.js b/platforms/android/app/src/main/assets/www/cordova.js
new file mode 100644
index 0000000..0f2d2e6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova.js
@@ -0,0 +1,1908 @@
+// Platform: android
+// 882658ab17740dbdece764e68c1f1f1f44fe3f9d
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '8.0.0';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+            'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1
+    },
+    nativeToJsModes = {
+        // Polls for messages using the JS->Native bridge.
+        POLLING: 0,
+        // For LOAD_URL to be viable, it would need to have a work-around for
+        // the bug where the soft-keyboard gets dismissed when a message is sent.
+        LOAD_URL: 1,
+        // For the ONLINE_EVENT to be viable, it would need to intercept all event
+        // listeners (both through addEventListener and window.ononline) as well
+        // as set the navigator property itself.
+        ONLINE_EVENT: 2,
+        EVAL_BRIDGE: 3
+    },
+    jsToNativeBridgeMode,  // Set lazily.
+    nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
+    pollEnabled = false,
+    bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
+
+function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
+    // Set default bridge modes if they have not already been set.
+    // By default, we use the failsafe, since addJavascriptInterface breaks too often
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    }
+
+    // If args is not provided, default to an empty array
+    args = args || [];
+
+    // Process any ArrayBuffers in the args into a string.
+    for (var i = 0; i < args.length; i++) {
+        if (utils.typeName(args[i]) == 'ArrayBuffer') {
+            args[i] = base64.fromArrayBuffer(args[i]);
+        }
+    }
+
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
+
+    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    } else if (msgs) {
+        messagesFromNative.push(msgs);
+        // Always process async to avoid exceptions messing up stack.
+        nextTick(processMessages);
+    }
+}
+
+androidExec.init = function() {
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
+
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+    if (msgs) {
+        messagesFromNative.push(msgs);
+        // Process sync since we know we're already top-of-stack.
+        processMessages();
+    }
+}
+
+function pollingTimerFunc() {
+    if (pollEnabled) {
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
+    }
+}
+
+function hookOnlineApis() {
+    function proxyEvent(e) {
+        cordova.fireWindowEvent(e.type);
+    }
+    // The network module takes care of firing online and offline events.
+    // It currently fires them only on document though, so we bridge them
+    // to window here (while first listening for exec()-releated online/offline
+    // events).
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+    cordova.addWindowEventHandler('online');
+    cordova.addWindowEventHandler('offline');
+    document.addEventListener('online', proxyEvent, false);
+    document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+        mode = jsToNativeModes.PROMPT;
+    }
+    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
+    jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
+        pollEnabled = false;
+    }
+
+    nativeToJsBridgeMode = mode;
+    // Tell the native side to switch modes.
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
+
+    if (mode == nativeToJsModes.POLLING) {
+        pollEnabled = true;
+        setTimeout(pollingTimerFunc, 1);
+    }
+};
+
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        payload.push(base64.toArrayBuffer(data));
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    var firstChar = message.charAt(0);
+    if (firstChar == 'J') {
+        // This is deprecated on the .java side. It doesn't work with CSP enabled.
+        eval(message.slice(1));
+    } else if (firstChar == 'S' || firstChar == 'F') {
+        var success = firstChar == 'S';
+        var keepCallback = message.charAt(1) == '1';
+        var spaceIdx = message.indexOf(' ', 2);
+        var status = +message.slice(2, spaceIdx);
+        var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+        var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+        var payloadMessage = message.slice(nextSpaceIdx + 1);
+        var payload = [];
+        buildPayload(payload, payloadMessage);
+        cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+    } else {
+        console.log("processMessage failed: invalid message: " + JSON.stringify(message));
+    }
+}
+
+function processMessages() {
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (messagesFromNative.length === 0) {
+        return;
+    }
+    isProcessing = true;
+    try {
+        var msg = popMessageFromQueue();
+        // The Java side can send a * message to indicate that it
+        // still has messages waiting to be retrieved.
+        if (msg == '*' && messagesFromNative.length === 0) {
+            nextTick(pollOnce);
+            return;
+        }
+        processMessage(msg);
+    } finally {
+        isProcessing = false;
+        if (messagesFromNative.length > 0) {
+            nextTick(processMessages);
+        }
+    }
+}
+
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
+module.exports = androidExec;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+    id: 'android',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
+
+        // Get the shared secret needed to use the bridge.
+        exec.init();
+
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+        var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+        // Inject a listener for the backbutton on the document.
+        var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+        backButtonChannel.onHasSubscribersChange = function() {
+            // If we just attached the first handler or detached the last handler,
+            // let native know we need to override the back button.
+            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
+        };
+
+        // Add hardware MENU and SEARCH button handlers
+        cordova.addDocumentEventHandler('menubutton');
+        cordova.addDocumentEventHandler('searchbutton');
+
+        function bindButtonChannel(buttonName) {
+            // generic button bind used for volumeup/volumedown buttons
+            var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+            volumeButtonChannel.onHasSubscribersChange = function() {
+                exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
+            };
+        }
+        // Inject a listener for the volume buttons on the document.
+        bindButtonChannel('volumeup');
+        bindButtonChannel('volumedown');
+
+        // The resume event is not "sticky", but it is possible that the event
+        // will contain the result of a plugin call. We need to ensure that the
+        // plugin result is delivered even after the event is fired (CB-10498)
+        var cordovaAddEventListener = document.addEventListener;
+
+        document.addEventListener = function(evt, handler, capture) {
+            cordovaAddEventListener(evt, handler, capture);
+
+            if (evt === 'resume' && lastResumeEvent) {
+                handler(lastResumeEvent);
+            }
+        };
+
+        // Let native code know we are all done on the JS side.
+        // Native code will then un-hide the WebView.
+        channel.onCordovaReady.subscribe(function() {
+            exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+            exec(null, null, APP_PLUGIN_NAME, "show", []);
+        });
+    }
+};
+
+function onMessageFromNative(msg) {
+    var cordova = require('cordova');
+    var action = msg.action;
+
+    switch (action)
+    {
+        // Button events
+        case 'backbutton':
+        case 'menubutton':
+        case 'searchbutton':
+        // App life cycle events
+        case 'pause':
+        // Volume events
+        case 'volumedownbutton':
+        case 'volumeupbutton':
+            cordova.fireDocumentEvent(action);
+            break;
+        case 'resume':
+            if(arguments.length > 1 && msg.pendingResult) {
+                if(arguments.length === 2) {
+                    msg.pendingResult.result = arguments[1];
+                } else {
+                    // The plugin returned a multipart message
+                    var res = [];
+                    for(var i = 1; i < arguments.length; i++) {
+                        res.push(arguments[i]);
+                    }
+                    msg.pendingResult.result = res;
+                }
+
+                // Save the plugin result so that it can be delivered to the js
+                // even if they miss the initial firing of the event
+                lastResumeEvent = msg;
+            }
+            cordova.fireDocumentEvent(action, msg);
+            break;
+        default:
+            throw new Error('Unknown event action ' + action);
+    }
+}
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/plugin/android/app.js
+define("cordova/plugin/android/app", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
+    },
+
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
+    },
+
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
+    },
+
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
+    },
+
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
+    },
+
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
+    },
+
+    /**
+    * Override the default behavior of the Android volume button.
+    * If overridden, when the volume button is pressed, the "volume[up|down]button"
+    * JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "volume[up|down]button" event, this is automatically done.
+    *
+    * @param button          volumeup, volumedown
+    * @param override        T=override, F=cancel override
+    */
+    overrideButton:function(button, override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
+    },
+
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
+    }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/cordova_plugins.js b/platforms/android/app/src/main/assets/www/cordova_plugins.js
new file mode 100644
index 0000000..049ccd6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/cordova_plugins.js
@@ -0,0 +1,339 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+  module.exports = [
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.androidFileSystem",
+      "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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-inappbrowser.inappbrowser",
+      "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+      "pluginId": "cordova-plugin-inappbrowser",
+      "clobbers": [
+        "cordova.InAppBrowser.open",
+        "window.open"
+      ]
+    },
+    {
+      "id": "cordova-plugin-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ];
+  module.exports.metadata = {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  };
+});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/css/aui-iconfont.ttf b/platforms/android/app/src/main/assets/www/css/aui-iconfont.ttf
new file mode 100755
index 0000000..2c9d80e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/css/aui-iconfont.ttf
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/css/aui.css b/platforms/android/app/src/main/assets/www/css/aui.css
new file mode 100644
index 0000000..c77e083
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/css/aui.css
@@ -0,0 +1,2731 @@
+/*

+ * =========================================================================

+ * APIClud - AUI UI 框架    流浪男  QQ:343757327  http://www.auicss.com

+ * Verson 2.1

+ * =========================================================================

+ */

+ /*初始化类*/

+@charset "UTF-8";

+html{

+	font-family: "Helvetica Neue", Helvetica, sans-serif;

+	font-size: 20px;

+}

+html,body {

+	-webkit-touch-callout:none;

+	-webkit-text-size-adjust:none;

+	-webkit-tap-highlight-color:rgba(0, 0, 0, 0);

+	-webkit-user-select:none;

+	width: 100%;

+}

+body {

+	line-height: 1.5;

+	font-size: 0.8rem;

+	color: #212121;

+	background-color: #f5f5f5;

+	outline: 0;

+}

+html,body,header,section,footer,div,ul,ol,li,img,a,span,em,del,legend,center,strong,var,fieldset,form,label,dl,dt,dd,cite,input,hr,time,mark,code,figcaption,figure,textarea,h1,h2,h3,h4,h5,h6,p{

+	margin:0;

+	border:0;

+	padding:0;

+	font-style:normal;

+}

+* {

+	-webkit-box-sizing: border-box;

+	      	box-sizing: border-box;

+	-webkit-user-select: none;

+	-webkit-tap-highlight-color: transparent;

+	outline: none;

+}

+@media only screen and (min-width: 400px) {

+	html {

+		font-size: 21.33333333px !important;

+	}

+}

+@media only screen and (min-width: 414px) {

+	html {

+		font-size: 21px !important;

+	}

+}

+@media only screen and (min-width: 480px) {

+	html {

+		font-size: 25.6px !important;

+	}

+}

+ul, li {

+	list-style: none;

+}

+p {

+	font-size: 0.7rem;

+	color: #757575;

+}

+a {

+	color: #0062cc;

+	text-decoration: none;

+	background-color: transparent;

+}

+textarea {

+	overflow: hidden;

+	resize: none;

+}

+button {

+	overflow: visible;

+}

+button,select {

+	text-transform: none;

+}

+button,input,select,textarea {

+	font: inherit;

+	color: inherit;

+}

+/*自动隐藏文字*/

+.aui-ellipsis-1 {

+	overflow: hidden;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+}

+.aui-ellipsis {

+	display: -webkit-box;

+	overflow: hidden;

+	text-overflow: ellipsis;

+	word-wrap: break-word;

+	word-break: break-all;

+	white-space: normal !important;

+	-webkit-line-clamp: 1;

+	-webkit-box-orient: vertical;

+}

+.aui-ellipsis-2 {

+	display: -webkit-box;

+	overflow: hidden;

+	text-overflow: ellipsis;

+	word-wrap: break-word;

+	word-break: break-all;

+	white-space: normal !important;

+	-webkit-line-clamp: 2;

+	-webkit-box-orient: vertical;

+}

+/*水平线*/

+.aui-hr {

+	width: 100%;

+	position: relative;

+	border-top: 1px solid #dddddd;

+	height: 1px;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-hr{

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+}

+/*内外边距类*/

+.aui-padded-0 {

+	padding: 0 !important;

+}

+.aui-padded-5 {

+	padding: 0.25rem !important;

+}

+.aui-padded-10 {

+	padding: 0.5rem !important;

+}

+.aui-padded-15 {

+	padding: 0.75rem !important;

+}

+.aui-padded-t-0 {

+	padding-top: 0 !important;

+}

+.aui-padded-t-5 {

+	padding-top: 0.25rem !important;

+}

+.aui-padded-t-10 {

+	padding-top: 0.5rem !important;

+}

+.aui-padded-t-15 {

+	padding-top: 0.75rem !important;

+}

+.aui-padded-b-0 {

+	padding-bottom: 0 !important;

+}

+.aui-padded-b-5 {

+	padding-bottom: 0.25rem !important;

+}

+.aui-padded-b-10 {

+	padding-bottom: 0.5rem !important;

+}

+.aui-padded-b-15 {

+	padding-bottom: 0.75rem !important;

+}

+.aui-padded-l-0 {

+	padding-left: 0 !important;

+}

+.aui-padded-l-5 {

+	padding-left: 0.25rem !important;

+}

+.aui-padded-l-10 {

+	padding-left: 0.5rem !important;

+}

+.aui-padded-l-15 {

+	padding-left: 0.75rem !important;

+}

+.aui-padded-r-0 {

+	padding-right: 0 !important;

+}

+.aui-padded-r-5 {

+	padding-right: 0.25rem !important;

+}

+.aui-padded-r-10 {

+	padding-right: 0.5rem !important;

+}

+.aui-padded-r-15 {

+	padding-right: 0.75rem !important;

+}

+.aui-margin-0 {

+	margin: 0 !important;

+}

+.aui-margin-5 {

+	margin: 0.25rem !important;

+}

+.aui-margin-10 {

+	margin: 0.5rem !important;

+}

+.aui-margin-15 {

+	margin: 0.75rem !important;

+}

+.aui-margin-t-0 {

+	margin-top: 0.25rem !important;

+}

+.aui-margin-t-5 {

+	margin-top: 0 !important;

+}

+.aui-margin-t-10 {

+	margin-top: 0.5rem !important;

+}

+.aui-margin-t-15 {

+	margin-top: 0.75rem !important;

+}

+.aui-margin-b-0 {

+	margin-bottom: 0 !important;

+}

+.aui-margin-b-5 {

+	margin-bottom: 0.25rem !important;

+}

+.aui-margin-b-10 {

+	margin-bottom: 0.5rem !important;

+}

+.aui-margin-b-15 {

+	margin-bottom: 0.75rem !important;

+}

+.aui-margin-l-0 {

+	margin-left: 0 !important;

+}

+.aui-margin-l-5 {

+	margin-left: 0.25rem !important;

+}

+.aui-margin-l-10 {

+	margin-left: 0.5rem !important;

+}

+.aui-margin-l-15 {

+	margin-left: 0.75rem !important;

+}

+.aui-margin-r-0 {

+	margin-right: 0 !important;

+}

+.aui-margin-r-5 {

+	margin-right: 0.25rem !important;

+}

+.aui-margin-r-10 {

+	margin-right: 0.5rem !important;

+}

+.aui-margin-r-15 {

+	margin-right: 0.75rem !important;

+}

+.aui-clearfix {

+	clear: both;

+}

+.aui-clearfix:before {

+	display: table;

+	content: " ";

+}

+.aui-clearfix:after {

+	clear: both;

+}

+/*文字对齐*/

+.aui-text-left {

+	text-align: left !important;

+}

+.aui-text-center {

+	text-align: center !important;

+}

+.aui-text-justify {

+	text-align: justify !important;

+}

+.aui-text-right {

+	text-align: right !important;

+}

+/*文字、背景颜色*/

+h1,h2,h3,h4,h5,h6 {

+	font-weight: 400;

+}

+h1 {

+	font-size: 1.2rem;

+}

+h2 {

+	font-size: 1rem;

+}

+h3 {

+	font-size: 0.8rem;

+}

+h4 {

+	font-size: 0.7rem;

+}

+h5 {

+	font-size: 0.7rem;

+	font-weight: normal;

+	color: #757575;

+}

+h6 {

+	font-size: 0.7rem;

+	font-weight: normal;

+	color: #757575;

+}

+h1 small,h2 small,h3 small,h4 small {

+	font-weight: normal;

+	line-height: 1;

+	color: #757575;

+}

+h5 small,h6 small {

+	font-weight: normal;

+	line-height: 1;

+	color: #757575;

+}

+h1 small,h2 small,h3 small {

+	font-size: 65%;

+}

+h4 small,h5 small,h6 small {

+	font-size: 75%;

+}

+img {

+	max-width: 100%;

+	display: block;

+}

+.aui-font-size-12 {

+	font-size: 0.6rem !important;

+}

+.aui-font-size-14 {

+	font-size: 0.7rem !important;

+}

+.aui-font-size-16 {

+	font-size: 0.8rem !important;

+}

+.aui-font-size-18 {

+	font-size: 0.9rem !important;

+}

+.aui-font-size-20 {

+	font-size: 1rem !important;

+}

+.aui-text-default {

+	color: #212121 !important;

+}

+.aui-text-white {

+	color: #ffffff !important;

+}

+.aui-text-primary {

+	color: #00bcd4 !important;

+}

+.aui-text-success {

+	color: #009688 !important;

+}

+.aui-text-info {

+	color: #03a9f4 !important;

+}

+.aui-text-warning {

+	color: #ffc107 !important;

+}

+.aui-text-danger {

+	color: #e51c23 !important;

+}

+.aui-text-pink {

+	color: #e91e63 !important;

+}

+.aui-text-purple {

+	color: #673ab7 !important;

+}

+.aui-text-indigo {

+	color: #3f51b5 !important;

+}

+.aui-text-green {

+	color: #7cba59 !important;

+}

+.aui-text-orange {

+	color: #e0620d !important;

+}

+.aui-bg-default {

+	background-color: #f5f5f5 !important;

+}

+.aui-bg-primary {

+	background-color: #00bcd4 !important;

+}

+.aui-bg-success {

+	background-color: #009688 !important;

+}

+.aui-bg-info {

+	background-color: #03a9f4 !important;

+}

+.aui-bg-warning {

+	background-color: #f1c40f !important;

+}

+.aui-bg-danger {

+	background-color: #e51c23 !important;

+}

+.aui-bg-pink {

+	background-color: #e91e63 !important;

+}

+.aui-bg-purple {

+	background-color: #673ab7 !important;

+}

+.aui-bg-indigo {

+	background-color: #3f51b5 !important;

+}

+.aui-bg-gray {

+	background-color: #8a8a8a !important;

+}

+

+/*警告、成功颜色*/

+.aui-warning,

+.aui-warning label,

+.aui-warning .aui-input,

+.aui-warning .aui-iconfont {

+	color: #e51c23 !important;

+}

+.aui-success,

+.aui-success label,

+.aui-success .aui-input,

+.aui-success .aui-iconfont {

+	color: #009688 !important;

+}

+/*对齐,显示,隐藏等*/

+.aui-pull-right {

+	float: right !important;

+}

+.aui-pull-left {

+	float: left !important;

+}

+.aui-hide {

+	display: none !important;

+}

+.aui-show {

+	display: block !important;

+}

+.aui-invisible {

+	visibility: hidden;

+}

+.aui-inline {

+	display: inline-block;

+	vertical-align: top;

+}

+.aui-mask {

+    position: fixed;

+    width: 100%;

+    height: 100%;

+    top: 0;

+    left: 0;

+    background: rgba(0, 0, 0, 0.3);

+    opacity: 0;

+    z-index: 8;

+    visibility: hidden;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+}

+.aui-mask.aui-mask-in {

+	visibility: visible;

+  	opacity: 1;

+}

+.aui-mask.aui-mask-out {

+	opacity: 0;

+}

+img.aui-img-round {

+	border-radius: 50%;

+}

+/*基本容器*/

+.aui-content {

+	-webkit-overflow-scrolling: touch;

+	overflow-x: hidden;

+	word-break: break-all;

+}

+.aui-content-padded {

+  	margin: 0.75rem;

+  	position: relative;

+  	word-break: break-all;

+  	-webkit-overflow-scrolling: touch;

+}

+/*栅格类*/

+.aui-row {

+	overflow: hidden;

+	margin: 0;

+}

+.aui-row-padded {

+	margin-left: -0.125rem;

+	margin-right: -0.125rem;

+}

+.aui-row-padded [class*=aui-col-xs-] {

+	padding: 0.125rem;

+}

+.aui-col-xs-1,.aui-col-xs-2,.aui-col-xs-3,.aui-col-xs-4,.aui-col-xs-5,.aui-col-xs-6,.aui-col-xs-7,.aui-col-xs-8,.aui-col-xs-9,.aui-col-xs-10,.aui-col-xs-11,.aui-col-5 {

+	position: relative;

+	float: left;

+}

+.aui-col-xs-12 {

+	width: 100%;

+	position: relative;

+}

+.aui-col-xs-11 {

+	width: 91.66666667%;

+}

+.aui-col-xs-10 {

+	width: 83.33333333%;

+}

+.aui-col-xs-9 {

+	width: 75%;

+}

+.aui-col-xs-8 {

+	width: 66.66666667%;

+}

+.aui-col-xs-7 {

+	width: 58.33333333%;

+}

+.aui-col-xs-6 {

+	width: 50%;

+}

+.aui-col-xs-5 {

+	width: 41.66666667%;

+}

+.aui-col-xs-4 {

+	width: 33.33333333%;

+}

+.aui-col-xs-3 {

+	width: 25%;

+}

+.aui-col-xs-2 {

+	width: 16.66666667%;

+}

+.aui-col-xs-1 {

+	width: 8.33333333%;

+}

+.aui-col-5 {

+	width: 20%;

+}

+/*标签*/

+.aui-label {

+	display: inline-block;

+	padding: 0.2em 0.25em;

+	font-size: 0.6rem;

+	line-height: 1;

+	color: #616161;

+    background-color: #dddddd;

+	text-align: center;

+	white-space: nowrap;

+	vertical-align: middle;

+	border-radius: 0.15em;

+	position: relative;

+}

+

+.aui-label-primary {

+	color: #ffffff;

+	background-color: #00bcd4;

+}

+.aui-label-success {

+	color: #ffffff;

+	background-color: #009688;

+}

+.aui-label-info {

+  color: #ffffff;

+  background-color: #03a9f4;

+}

+.aui-label-warning {

+	color: #ffffff;

+	background-color: #ffc107;

+}

+.aui-label-danger {

+	color: #ffffff;

+	background-color: #e51c23;

+}

+.aui-label-outlined {

+	background-color: transparent;

+	position: relative;

+}

+.aui-label-outlined:after {

+    -webkit-border-radius: 2px;

+    border-radius: 2px;

+    height: 200%;

+    content: '';

+    width: 200%;

+	border: 1px solid #d9d9d9;

+    position: absolute;

+    top: -1px;

+    left: -1px;

+    transform: scale(0.5);

+    -webkit-transform: scale(0.5);

+    transform-origin: 0 0;

+    -webkit-transform-origin: 0 0;

+    z-index: 1;

+}

+.aui-label-outlined.aui-label-primary,

+.aui-label-outlined.aui-label-primary:after {

+	color: #00bcd4;

+	border-color: #00bcd4;

+}

+.aui-label-outlined.aui-label-success,

+.aui-label-outlined.aui-label-success:after {

+	color: #009688;

+	border-color: #009688;

+}

+.aui-label-outlined.aui-label-info,

+.aui-label-outlined.aui-label-info:after {

+  	color: #03a9f4;

+  	border-color: #03a9f4;

+}

+.aui-label-outlined.aui-label-warning,

+.aui-label-outlined.aui-label-warning:after {

+	color: #ffc107;

+	border-color: #ffc107;

+}

+.aui-label-outlined.aui-label-danger,

+.aui-label-outlined.aui-label-danger:after {

+	color: #e51c23;

+	border-color: #e51c23;

+}

+.aui-label .aui-iconfont {

+	font-size: 0.6rem;

+}

+/*角标*/

+.aui-badge {

+	display: inline-block;

+	width: auto;

+	text-align: center;

+	min-width: 0.8rem;

+	height: 0.8rem;

+    line-height: 0.8rem;

+    padding: 0 0.2rem;

+    font-size: 0.6rem;

+    color: #ffffff;

+    background-color: #ff2600;

+    border-radius: 0.4rem;

+    position: absolute;

+    top: 0.2rem;

+    left: 60%;

+    z-index: 99;

+}

+.aui-dot {

+	display: inline-block;

+    width: 0.4rem;

+    height: 0.4rem;

+    background: #ff2600;

+    border-radius: 0.5rem;

+    position: absolute;

+    top: 0.3rem;

+    right: 20%;

+    z-index: 99;

+}

+/*按钮样式*/

+button, .aui-btn {

+	position: relative;

+	display: inline-block;

+	font-size: 0.7rem;

+	font-weight: 400;

+	font-family: inherit;

+	text-decoration: none;

+	text-align: center;

+	margin: 0;

+	background: #dddddd;

+	padding: 0 0.6rem;

+	height: 1.5rem;

+	line-height: 1.5rem;

+	border-radius: 0.2rem;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+	vertical-align: middle;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	-webkit-user-select: none;

+	      	user-select: none;

+}

+.aui-btn:active {

+	color: #212121;

+	background-color: #bdbdbd;

+}

+.aui-btn-primary {

+	color: #ffffff;

+	background-color: #00bcd4;

+}

+.aui-btn-primary.aui-active, .aui-btn-primary:active {

+	color: #ffffff;

+	background-color: #00acc1;

+}

+.aui-btn-success {

+	color: #ffffff;

+	background-color: #009688;

+}

+.aui-btn-success.aui-active, .aui-btn-success:active {

+	color: #fff;

+	background-color: #00897b;

+}

+.aui-btn-info {

+	color: #ffffff !important;

+	background-color: #03a9f4 !important;

+}

+.aui-btn-info.aui-active, .aui-btn-info:active {

+	color: #fff !important;

+	background-color: #067cb1 !important;

+}

+.aui-btn-warning {

+	color: #ffffff !important;

+	background-color: #ffc107 !important;

+}

+.aui-btn-warning.aui-active, .aui-btn-warning:active {

+	color: #ffffff !important;

+	background-color: #ffb300 !important;

+}

+.aui-btn-danger {

+	color: #ffffff !important;

+	background-color: #e51c23 !important;

+}

+.aui-btn-danger.aui-active, .aui-btn-danger:active {

+	color: #ffffff !important;

+	background-color: #dd191b !important;

+}

+.aui-btn-orangle {

+	color: #ffffff !important;

+	background-color: #efb336 !important;

+}

+.aui-btn-orangle.aui-active, .aui-btn-orangle:active {

+	color: #fff !important;

+	background-color: #e98f36 !important;

+}

+.aui-btn-blue {

+	color: #ffffff !important;

+	background-color: #17abe3 !important;

+}

+.aui-btn-blue.aui-active, .aui-btn-blue:active {

+	color: #fff !important;

+	background-color: #1195db !important;

+}

+.aui-btn-green {

+	color: #ffffff !important;

+	background-color: #36ab60 !important;

+}

+.aui-btn-green.aui-active, .aui-btn-green:active {

+	color: #fff !important;

+	background-color: #36ab60 !important;

+}

+.aui-btn-block {

+	display: block;

+	width: 100%;

+	height: 2.5rem;

+	line-height: 2.55rem;

+	margin-bottom: 0;

+	font-size: 0.9rem;

+}

+.aui-btn-block.aui-btn-sm {

+	font-size: 0.7rem;

+	height: 1.8rem;

+	line-height: 1.85rem;

+}

+.aui-btn .aui-iconfont, .aui-btn-block .aui-iconfont {

+	margin-right: 0.3rem;

+}

+.aui-btn .aui-badge, .aui-btn-block .aui-badge {

+	margin-left: 0.3rem;

+}

+.aui-btn-outlined {

+	background: transparent !important;

+	border: 1px solid #bdbdbd;

+}

+.aui-btn-outlined:active {

+	background: transparent !important;

+}

+.aui-btn-default.aui-btn-outlined {

+	color: #bdc3c7 !important;

+	border: 1px solid #dcdcdc !important;

+}

+.aui-btn-primary.aui-btn-outlined {

+	color: #00bcd4 !important;

+	border: 1px solid #00bcd4 !important;

+}

+.aui-btn-success.aui-btn-outlined {

+	color: #009688 !important;

+	border: 1px solid #009688 !important;

+}

+.aui-btn-info.aui-btn-outlined {

+	color: #03a9f4 !important;

+	border: 1px solid #03a9f4 !important;

+}

+.aui-btn-warning.aui-btn-outlined {

+	color: #ffc107 !important;

+	border: 1px solid #ffc107 !important;

+}

+.aui-btn-danger.aui-btn-outlined {

+	color: #e51c23 !important;

+	border: 1px solid #e51c23 !important;

+}

+/*

+*表单类\输入框\radio\checkbox

+**/

+.aui-input,

+input[type="text"],

+input[type="password"],

+input[type="search"],

+input[type="email"],

+input[type="tel"],

+input[type="url"],

+input[type="date"],

+input[type="datetime-local"],

+input[type="time"],

+input[type="number"],

+select,

+textarea {

+    border: none;

+    background-color: transparent;

+    border-radius: 0;

+    box-shadow: none;

+    display: block;

+    padding: 0;

+    margin: 0;

+    width: 100%;

+    height: 2.2rem;

+    line-height: normal;

+    color: #424242;

+    font-size: 0.8rem;

+    font-family: inherit;

+    box-sizing: border-box;

+    -webkit-user-select: text;

+            user-select: text;

+    -webkit-appearance: none;

+            appearance: none;

+}

+input[type="search"]::-webkit-search-cancel-button {

+	display: none;

+}

+.aui-scroll-x {

+	position: relative;

+	overflow-y: auto;

+	-webkit-overflow-scrolling: touch;

+}

+.aui-scroll-y {

+	position: relative;

+	width: 100%;

+	overflow-x: auto;

+	-webkit-overflow-scrolling: touch;

+}

+::-webkit-scrollbar{

+	width:0px;

+}

+/*列表*/

+.aui-list {

+    position: relative;

+    font-size: 0.8rem;

+    background-color: #ffffff;

+    border-top: 1px solid #dddddd;

+}

+.aui-list .aui-content {

+	overflow: hidden;

+}

+.aui-list.aui-list-noborder,

+.aui-list.aui-list-noborder {

+    border-top: none;

+}

+.aui-list .aui-list-header {

+    background-color: #dddddd;

+    color: #212121;

+    position: relative;

+    font-size: 0.6rem;

+    padding: 0.4rem 0.75rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item {

+    list-style: none;

+    margin: 0;

+    padding: 0;

+    padding-left: 0.75rem;

+    color: #212121;

+    border-bottom: 1px solid #f2f2f2;

+    position: relative;

+    min-height: 2.2rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+}

+.aui-list.aui-list-noborder .aui-list-item:last-child {

+    border-bottom: 0;

+}

+.aui-list .aui-list-item-inner {

+    position: relative;

+    min-height: 2.2rem;

+	padding-right: 0.75rem;

+    width: 100%;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-flex: 1;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+			justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+			align-items: center;

+}

+

+.aui-list .aui-list-item:active {

+    background-color: #f5f5f5;

+}

+.aui-list .aui-list-item-text {

+    font-size: 0.7rem;

+    color: #757575;

+    position: relative;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+            justify-content: space-between;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item-title {

+    font-size: 0.8rem;

+    position: relative;

+    max-width: 100%;

+    color: #212121;

+}

+.aui-list .aui-list-item-right,

+.aui-list-item-title-row em {

+	max-width: 50%;

+	position: relative;

+    font-size: 0.6rem;

+    color: #757575;

+    margin-left: 0.25rem;

+}

+.aui-list .aui-list-item-inner p {

+    overflow: hidden;

+}

+.aui-list .aui-list-media-list {

+    -webkit-box-orient: vertical;

+    -webkit-box-direction: normal;

+    -webkit-flex-direction: column;

+            flex-direction: column;

+}

+.aui-media-list-item-inner {

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+}

+.aui-media-list .aui-list-item {

+	display: block;

+}

+.aui-media-list .aui-list-item-inner {

+	display: block;

+	padding-top: 0.5rem;

+    padding-bottom: 0.5rem;

+}

+.aui-media-list-item-inner + .aui-info {

+	margin-right: 0.75rem;

+}

+.aui-list .aui-list-item-media {

+	width: 4.5rem;

+	position: relative;

+    padding: 0.5rem 0;

+    padding-right: 0.75rem;

+    display: inherit;

+    -webkit-flex-shrink: 0;

+    		flex-shrink: 0;

+    -webkit-flex-wrap: nowrap;

+    		flex-wrap: nowrap;

+    -webkit-box-align: center;

+    -webkit-align-items: flex-start;

+            align-items: flex-start;

+}

+.aui-list .aui-list-item-media img {

+	width: 100%;

+    display: block;

+}

+.aui-list .aui-list-item-media-list {

+	margin-top: 0.25rem;

+	padding-right: 0;

+	display: block;

+}

+.aui-list [class*=aui-col-xs-] img{

+    max-width: 100%;

+    width: 100%;

+    display: block;

+}

+.aui-list-item-middle .aui-list-item-inner:after {

+	display: block;

+}

+.aui-list .aui-list-item-middle > .aui-list-item-media,

+.aui-list .aui-list-item-middle > .aui-list-item-inner,

+.aui-list .aui-list-item-middle > * {

+    -webkit-box-align: center;

+    		box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item-center > .aui-list-item-media,

+.aui-list .aui-list-item-center > .aui-list-item-inner,

+.aui-list .aui-list-item-center {

+    -webkit-box-pack: center;

+    -webkit-justify-content: center;

+        	justify-content: center;

+}

+.aui-list .aui-list-item i.aui-iconfont {

+    -webkit-align-self: center;

+            align-self: center;

+    font-size: 0.8rem;

+}

+.aui-list-item-inner.aui-list-item-arrow {

+    overflow: hidden;

+    padding-right: 1.5rem;

+}

+.aui-list-item-arrow:before {

+    content: '';

+    width: 0.4rem;

+    height: 0.4rem;

+    position: absolute;

+    top: 50%;

+    right: 0.75rem;

+    margin-top: -0.2rem;

+    background: transparent;

+    border: 1px solid #dddddd;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-135deg);

+            transform: rotate(-135deg);

+}

+.aui-list-item.aui-list-item-arrow {

+    padding-right: 0.75rem;

+}

+.aui-list label {

+    line-height: 1.3rem;

+}

+.aui-list.aui-form-list .aui-list-item:active {

+	background-color: #ffffff;

+}

+.aui-list.aui-form-list .aui-list-item-inner {

+	-webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+	padding: 0;

+}

+.aui-list .aui-list-item-label,

+.aui-list .aui-list-item-label-icon {

+	color: #212121;

+    width: 35%;

+    min-width: 1.5rem;

+    margin: 0;

+    padding: 0;

+    padding-right: 0.25rem;

+    line-height: 2.2rem;

+    position: relative;

+    overflow: hidden;

+    white-space: nowrap;

+    max-width: 100%;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-list .aui-list-item-label-icon {

+    width: auto;

+    padding-right: 0.75rem;

+}

+.aui-list .aui-list-item-input {

+    width: 100%;

+    padding: 0;

+    padding-right: 0.75rem;

+    -webkit-box-flex: 1;

+            box-flex: 1;

+    -webkit-flex-shrink: 1;

+            flex-shrink: 1;

+}

+.aui-list.aui-select-list .aui-list-item:active {

+	background-color: #ffffff;

+}

+.aui-list.aui-select-list .aui-list-item-inner {

+    display: block;

+    padding-top: 0.5rem;

+    padding-bottom: 0.5rem;

+    -webkit-align-self: stretch;

+    		align-self: stretch;

+}

+.aui-list.aui-select-list .aui-list-item-label {

+	width: auto;

+	min-width: 2.2rem;

+    padding: 0.5rem 0;

+    padding-right: 0.75rem;

+}

+.aui-list.aui-form-list .aui-list-item-btn {

+	padding: 0.75rem 0.75rem 0.75rem 0;

+}

+.aui-list textarea {

+    overflow: auto;

+    margin: 0.5rem 0;

+    height: 3rem;

+    line-height: 1rem;

+    resize: none;

+}

+.aui-list .aui-list-item-right .aui-badge,

+.aui-list .aui-list-item-right .aui-dot {

+	display: inherit;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-list {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-list .aui-list-item {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+

+	.aui-list.aui-list-in .aui-list-item {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: 0.75rem bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-list.aui-list-in .aui-list-item:last-child {

+		background-position: bottom;

+	}

+	.aui-list.aui-list-noborder,

+	.aui-list.aui-list-noborder .aui-list-item:last-child {

+		border: none;

+        background-size: 100% 0;

+        background-image: none;

+	}

+}

+/*tab切换类*/

+.aui-tab {

+	position: relative;

+    background-color: #ffffff;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-flex-wrap: nowrap;

+            flex-wrap: nowrap;

+    -webkit-align-self: center;

+            align-self: center;

+}

+.aui-tab-item {

+    width: 100%;

+    height: 2.2rem;

+    line-height: 2.2rem;

+    position: relative;

+    font-size: 0.7rem;

+    text-align: center;

+    color: #212121;

+    margin-left: -1px;

+    -webkit-box-flex: 1;

+            box-flex: 1;

+}

+.aui-tab-item.aui-active {

+    color: #03a9f4;

+    border-bottom: 2px solid #03a9f4;

+}

+/*卡片列表布局*/

+.aui-card-list {

+	position: relative;

+    margin-bottom: 0.35rem;

+    background: #ffffff;

+}

+.aui-card-list-header,

+.aui-card-list-footer {

+	position: relative;

+	min-height: 2.2rem;

+    padding: 0.5rem 0.75rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-card-list-header {

+	font-size: 0.8rem;

+	color: #212121;

+}

+.aui-card-list-header.aui-card-list-user {

+	display: block;

+}

+.aui-card-list-user-avatar {

+	width: 2rem;

+	float: left;

+	margin-right: 0.5rem;

+}

+.aui-card-list-user-avatar img {

+	width: 100%;

+	display: block;

+}

+.aui-card-list-user-name {

+	color: #212121;

+	position: relative;

+	font-size: 0.7rem;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-card-list-user-name > *,

+.aui-card-list-user-name small {

+	position: relative;

+}

+.aui-card-list-user-name small {

+	color: #757575;

+}

+.aui-card-list-user-info {

+	color: #757575;

+	font-size: 0.6rem;

+}

+.aui-card-list-content {

+	position: relative;

+}

+.aui-card-list-content-padded {

+	position: relative;

+	padding: 0.5rem 0.75rem;

+}

+.aui-card-list-content,

+.aui-card-list-content-padded {

+	word-break: break-all;

+	font-size: 0.7rem;

+	color: #212121;

+}

+.aui-card-list-content img,

+.aui-card-list-content-padded img {

+	width: 100%;

+	display: block;

+}

+.aui-card-list-footer {

+	font-size: 0.7rem;

+	color: #757575;

+}

+.aui-card-list-footer > * {

+	position: relative;

+}

+.aui-card-list-footer.aui-text-center {

+	display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+	-webkit-box-pack: center;

+    box-pack: center;

+    -webkit-justify-content: center;

+    justify-content: center;

+}

+.aui-card-list-footer .aui-iconfont {

+	font-size: 0.9rem;

+}

+/*宫格布局*/

+.aui-grid {

+	width: 100%;

+	background-color: #ffffff;

+	display: table;

+	table-layout: fixed;

+}

+.aui-grid [class*=aui-col-] {

+	display: table-cell;

+	position: relative;

+    text-align: center;

+    vertical-align: middle;

+    padding: 0.6rem 0;

+}

+.aui-grid [class*=aui-col-xs-]:active {

+	background-color: #f5f5f5;

+}

+.aui-grid [class*=top-btn]:active {

+	background-color: #048cca;

+}

+.aui-grid .aui-iconfont {

+	position: relative;

+    z-index: 20;

+    top: 0;

+    height: 1.4rem;

+    font-size: 1.4rem;

+    line-height: 1.4rem;

+}

+.aui-grid .aui-grid-label {

+	display: block;

+    font-size: 0.7rem;

+    position: relative;

+    margin-top: 0.25rem;

+}

+.aui-grid .aui-badge {

+	position: absolute;

+    top: 0.5rem;

+    left: 60%;

+    z-index: 99;

+}

+.aui-grid .aui-dot {

+	position: absolute;

+    top: 0.5rem;

+    right: 20%;

+    z-index: 99;

+}

+/*单选、多选、开关*/

+.aui-radio,

+.aui-checkbox {

+    width: 1.2rem;

+    height: 1.2rem;

+    background-color: #ffffff;

+    border: solid 1px #dddddd;

+    -webkit-border-radius: 0.6rem;

+    border-radius: 0.6rem;

+    font-size: 0.8rem;

+    margin: 0;

+    padding: 0;

+    position: relative;

+    display: inline-block;

+    vertical-align: top;

+    cursor: default;

+    -webkit-appearance: none;

+    -webkit-user-select: none;

+            user-select: none;

+    -webkit-transition: background-color ease 0.1s;

+            transition: background-color ease 0.1s;

+}

+.aui-checkbox {

+    border-radius: 0.1rem;

+}

+.aui-radio:checked,

+.aui-radio.aui-checked,

+.aui-checkbox:checked,

+.aui-checkbox.aui-checked {

+    background-color: #03a9f4;

+    border: solid 1px #03a9f4;

+    text-align: center;

+    background-clip: padding-box;

+}

+.aui-radio:checked:before,

+.aui-radio.aui-checked:before,

+.aui-checkbox:checked:before,

+.aui-checkbox.aui-checked:before,

+.aui-radio:checked:after,

+.aui-radio.aui-checked:after,

+.aui-checkbox:checked:after,

+.aui-checkbox.aui-checked:after {

+    content: '';

+    width: 0.5rem;

+    height: 0.3rem;

+    position: absolute;

+    top: 50%;

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.25rem;

+    background: transparent;

+    border: 1px solid #ffffff;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+}

+.aui-radio:disabled,

+.aui-radio.aui-disabled,

+.aui-checkbox:disabled,

+.aui-checkbox.aui-disabled {

+    background-color: #dddddd;

+    border: solid 1px #dddddd;

+}

+.aui-radio:disabled:before,

+.aui-radio.aui-disabled:before,

+.aui-radio:disabled:after,

+.aui-radio.aui-disabled:after,

+.aui-checkbox:disabled:before,

+.aui-checkbox.aui-disabled:before,

+.aui-checkbox:disabled:after,

+.aui-checkbox.aui-disabled:after {

+    content: '';

+    width: 0.5rem;

+    height: 0.3rem;

+    position: absolute;

+    top: 50%;

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.25rem;

+    background: transparent;

+    border: 1px solid #ffffff;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+}

+.aui-switch {

+    width: 2.3rem;

+    height: 1.2rem;

+    position: relative;

+    vertical-align: top;

+    border: 1px solid #dddddd;

+    background-color: #dddddd;

+    border-radius: 0.6rem;

+    background-clip: content-box;

+    display: inline-block;

+    outline: none;

+    -webkit-appearance: none;

+            appearance: none;

+    -webkit-user-select: none;

+            user-select: none;

+    -webkit-box-sizing: border-box;

+            box-sizing: border-box;

+    -webkit-background-clip: padding-box;

+            background-clip: padding-box;

+    -webkit-transition: all 0.2s linear;

+            transition: all 0.2s linear;

+}

+.aui-switch:before {

+    width: 1.1rem;

+    height: 1.1rem;

+    position: absolute;

+    top: 0;

+    left: 0;

+    border-radius: 0.6rem;

+    background-color: #fff;

+    content: '';

+    -webkit-transition: left 0.2s;

+            transition: left 0.2s;

+}

+.aui-switch:checked {

+    border-color: #03a9f4;

+    background-color: #03a9f4;

+}

+.aui-switch:checked:before {

+    left: 1.1rem;

+}

+/*导航栏*/

+.aui-bar {

+	position: relative;

+	top: 0;

+	right: 0;

+	left: 0;

+	z-index: 10;

+	width: 100%;

+	min-height: 2.25rem;

+	font-size: 0.9rem;

+	text-align: center;

+	display: table;

+}

+.aui-bar-nav {

+	top: 0;

+	line-height: 2.25rem;

+	background-color: #03a9f4;

+	color: #ffffff;

+}

+.aui-title a {

+	color: inherit;

+}

+.aui-bar-nav .aui-title {

+	min-height: 2.25rem;

+	position: absolute;

+	margin: 0;

+	text-align: center;

+	white-space: nowrap;

+	right: 2rem;

+	left: 2rem;

+	width: auto;

+	overflow: hidden;

+	/*text-overflow: ellipsis;*/

+	z-index: 2;

+}

+.aui-bar-nav a {

+	color: #ffffff;

+}

+.aui-bar-nav .aui-iconfont {

+	position: relative;

+	z-index: 20;

+	font-size: 0.9rem;

+	color: #ffffff;

+	font-weight: 400;

+	line-height: 2.25rem;

+}

+.aui-bar-nav .aui-pull-left {

+	padding: 0 0.5rem;

+	font-size: 0.8rem;

+	font-weight: 400;

+	z-index: 2;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-bar-nav .aui-pull-right {

+	padding: 0 0.5rem;

+	font-size: 0.8rem;

+	font-weight: 400;

+	z-index: 2;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-bar-nav .aui-btn {

+	position: relative;

+	z-index: 20;

+	height: 2.25rem;

+	line-height: 2.25rem;

+	padding-top: 0;

+	padding-bottom: 0;

+	margin: 0;

+	border-radius: 0.1rem;

+	border-width: 0;

+	background: transparent !important;

+}

+.aui-bar-nav .aui-btn.aui-btn-outlined {

+	position: relative;

+	padding: 0 0.15rem;

+	margin: 0.5rem;

+	height: 1.25rem;

+	line-height: 1.25rem;

+	border-width: 1px;

+	background: transparent !important;

+	border-color: #ffffff;

+}

+.aui-bar-nav .aui-btn:active {

+	background: none;

+}

+.aui-bar-nav .aui-btn .aui-iconfont {

+	font-size: 0.9rem;

+	line-height: 1.25rem;

+	padding: 0;

+	margin: 0;

+	color: #ffffff;

+}

+.aui-bar-light {

+	color: #03a9f4;

+	background-color: #ffffff;

+	border-bottom: 1px solid #dddddd;

+}

+.aui-bar-nav.aui-bar-light .aui-iconfont {

+	color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-btn-outlined {

+	border-color: #03a9f4;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-bar.aui-bar-light {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+}

+/*底部切换栏*/

+.aui-bar-tab {

+	position: fixed;

+	top: auto;

+	bottom: 0;

+	table-layout: fixed;

+	background-color: #ffffff;

+	color: #757575;

+}

+.aui-bar-tab .aui-bar-tab-item {

+	display: table-cell;

+	position: relative;

+    width: 1%;

+    height: 2.5rem;

+    text-align: center;

+    vertical-align: middle;

+}

+.aui-bar-tab .aui-active {

+	color: #03a9f4;

+}

+.aui-bar-tab .aui-bar-tab-item .aui-iconfont {

+	position: relative;

+    z-index: 20;

+    top: 0.1rem;

+    height: 1.2rem;

+    font-size: 1rem;

+    line-height: 1rem;

+}

+.aui-bar-tab .aui-bar-tab-label {

+	display: block;

+    font-size: 0.6rem;

+    position: relative;

+}

+.aui-bar-tab .aui-badge {

+    position: absolute;

+    top: 0.1rem;

+    left: 55%;

+    z-index: 99;

+}

+.aui-bar-tab .aui-dot {

+    position: absolute;

+    top: 0.1rem;

+    right: 30%;

+    z-index: 99;

+}

+/*按钮工具栏*/

+.aui-bar-btn {

+	position: relative;

+    font-size: 0.7rem;

+    display: table;

+    white-space: nowrap;

+    margin: 0 auto;

+    padding: 0;

+    border: none;

+    width: 100%;

+    min-height: 1.8rem;

+}

+.aui-bar-btn-item {

+    display: table-cell;

+    position: relative;

+    width: 1%;

+    line-height: 1.6rem;

+    text-align: center;

+    vertical-align: middle;

+    border-radius: 0;

+    position: relative;

+    border-width: 1px;

+    border-style: solid;

+    border-color: #03a9f4;

+    border-left-width: 0;

+}

+.aui-bar-btn .aui-input,

+.aui-bar-btn input,

+.aui-bar-btn select {

+	padding-left: 0.25rem;

+	padding-right: 0.25rem;

+    height: 1.8rem;

+}

+.aui-bar-btn-sm {

+    min-height: 1.3rem;

+}

+.aui-bar-btn.aui-bar-btn-sm  .aui-input,

+.aui-bar-btn.aui-bar-btn-sm  input,

+.aui-bar-btn.aui-bar-btn-sm  select {

+    height: 1.2rem;

+}

+.aui-bar-btn-sm .aui-bar-btn-item {

+    line-height: 1.3rem;

+    font-size: 0.6rem;

+}

+.aui-bar-btn-item.aui-active {

+    background-color: #03a9f4;

+    color: #ffffff;

+}

+.aui-bar-btn-item:first-child {

+    border-left-width: 1px;

+    border-top-left-radius: 0.2rem;

+    border-bottom-left-radius: 0.2rem;

+}

+.aui-bar-btn-item:last-child {

+    border-top-right-radius: 0.2rem;

+    border-bottom-right-radius: 0.2rem;

+    border-left: 0px;

+}

+.aui-bar-btn.aui-bar-btn-full .aui-bar-btn-item:first-child {

+    border-left-width: 0;

+    border-top-left-radius: 0;

+    border-bottom-left-radius: 0;

+}

+.aui-bar-btn.aui-bar-btn-full .aui-bar-btn-item:last-child {

+    border-right-width: 0;

+    border-top-right-radius: 0;

+    border-bottom-right-radius: 0;

+}

+.aui-bar-btn.aui-bar-btn-round .aui-bar-btn-item:first-child {

+    border-top-left-radius: 1.5rem;

+    border-bottom-left-radius: 1.5rem;

+}

+.aui-bar-btn.aui-bar-btn-round .aui-bar-btn-item:last-child {

+    border-top-right-radius: 1.5rem;

+    border-bottom-right-radius: 1.5rem;

+}

+.aui-bar-nav .aui-bar-btn {

+	margin-top: 0.45rem;

+	margin-bottom: 0.4rem;

+    min-height: 1.3rem;

+}

+.aui-bar-nav .aui-bar-btn-item {

+    line-height: 1.3rem;

+    border-color: #ffffff;

+}

+.aui-bar-nav .aui-bar-btn-item.aui-active {

+    background-color: #ffffff;

+    color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-bar-btn-item {

+    border-color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-bar-btn-item.aui-active {

+    background-color: #03a9f4;

+    color: #ffffff;

+}

+.aui-bar-nav > .aui-bar-btn {

+	width: 50%;

+}

+.aui-info {

+	position: relative;

+    padding: 0.5rem 0;

+    font-size: 0.7rem;

+    color: #757575;

+    background-color: transparent;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+

+}

+.aui-info-item {

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-info-item > *,

+.aui-info > * {

+	display: inherit;

+	position: relative;

+}

+/*进度条*/

+.aui-progress {

+	width: 100%;

+	height: 1rem;

+	border-radius: 0.2rem;

+	overflow: hidden;

+	background-color: #f0f0f0;

+}

+.aui-progress-bar {

+	float: left;

+	width: 0;

+	height: 100%;

+	font-size: 0.6rem;

+	line-height: 1rem;

+	color: #ffffff;

+	text-align: center;

+	background-color: #03a9f4;

+}

+.aui-progress.sm,

+.aui-progress-sm {

+	height: 0.5rem;

+}

+.aui-progress.sm,

+.aui-progress-sm,

+.aui-progress.sm .aui-progress-bar,

+.aui-progress-sm .aui-progress-bar {

+	border-radius: 1px;

+}

+.aui-progress.xs,

+.aui-progress-xs {

+	height: 0.35rem;

+}

+.aui-progress.xs,

+.aui-progress-xs,

+.aui-progress.xs .progress-bar,

+.aui-progress-xs .progress-bar {

+	border-radius: 1px;

+}

+.aui-progress.xxs,

+.aui-progress-xxs {

+	height: 0.15rem;

+}

+.aui-progress.xxs,

+.aui-progress-xxs,

+.aui-progress.xxs .progress-bar,

+.aui-progress-xxs .progress-bar {

+	border-radius: 1px;

+}

+/*滑块*/

+.aui-range {

+    position: relative;

+    display: inline-block;

+}

+.aui-range input[type='range']{

+    height: 0.2rem;

+    border: 0;

+    border-radius: 2px;

+    background-color: #f0f0f0;

+    position: relative;

+    -webkit-appearance: none !important;

+}

+.aui-range input[type='range']::-webkit-slider-thumb {

+    width: 1.2rem;

+    height: 1.2rem;

+    border-radius: 50%;

+    border-color: #03a9f4;

+    background-color: #03a9f4;

+    -webkit-appearance: none !important;

+}

+.aui-range .aui-range-tip {

+    font-size: 1rem;

+    position: absolute;

+    z-index: 999;

+    top: -1.5rem;

+    width: 2.4rem;

+    height: 1.5rem;

+    line-height: 1.5rem;

+    text-align: center;

+    color: #666666;

+    border: 1px solid #dddddd;

+    border-radius: 0.3rem;

+    background-color: #ffffff;

+}

+.aui-input-row .aui-range input[type='range'] {

+	width: 90%;

+	margin-left: 5%;

+}

+/*搜索条*/

+.aui-searchbar {

+    display: -webkit-box;

+    -webkit-box-pack: center;

+    -webkit-box-align: center;

+    height: 2.2rem;

+    overflow: hidden;

+    width: 100%;

+    background-color: #ebeced;

+    color: #9e9e9e;

+    -webkit-backface-visibility: hidden;

+  			backface-visibility: hidden;

+}

+.aui-searchbar.focus {

+    -webkit-box-pack: start;

+}

+.aui-searchbar-input {

+    margin: 0 0.5rem;

+	background-color: #ffffff;

+    border-radius: 0.25rem;

+    height: 1.4rem;

+    line-height: 1.4rem;

+    font-size: 0.7rem;

+    position: relative;

+    padding-left: 0.5rem;

+    display: -webkit-box;

+    -webkit-box-flex: 1;

+}

+.aui-searchbar form {

+	width: 90%;

+}

+.aui-searchbar-input input {

+    color: #666666;

+    width: 80%;

+    padding: 0;

+    margin: 0;

+    height: 1.4rem;

+    line-height: normal;

+    border: 0;

+    -webkit-appearance: none;

+    font-size: 0.7rem;

+}

+.aui-searchbar input::-webkit-input-placeholder {

+	color: #ccc;

+}

+.aui-searchbar .aui-iconfont {

+    line-height: 1.4rem;

+    margin-right: 0.25rem;

+    color: #9e9e9e !important;

+}

+.aui-searchbar .aui-searchbar-btn {

+	font-size: 0.7rem;

+	color: #666666;

+	margin-right: -2.2rem;

+	width: 2.2rem;

+	height: 1.4rem;

+	padding-right: 0.5rem;

+	line-height: 1.4rem;

+	text-align: center;

+	-webkit-transition: all .3s;

+	      	transition: all .3s;

+}

+.aui-searchbar-clear-btn {

+	position: absolute;

+	right: 5px;

+	top: 3px;

+	width: 1.1rem;

+	height: 1.1rem;

+	background: #eeeeee;

+	border-radius: 50%;

+	line-height: 0.6rem;

+	text-align: center;

+	display: none;

+}

+.aui-searchbar-clear-btn .aui-iconfont {

+	font-size: 0.6rem;

+	margin: 0 auto;

+	position: relative;

+	top: -2px;

+}

+.aui-searchbar .aui-searchbar-btn .aui-iconfont {

+	color: #666666;

+}

+/*信息提示条*/

+.aui-tips {

+    padding: 0 0.75rem;

+    width: 100%;

+    z-index: 99;

+    height: 1.9rem;

+    line-height: 1.9rem;

+   	position: relative;

+    background-color: rgba(0,0,0,.6);

+    color: #ffffff;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+            justify-content: space-between;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-tips .aui-tips-title {

+	padding: 0 0.5rem;

+	font-size: 0.7rem;

+    position: relative;

+    max-width: 100%;

+}

+/*toast*/

+.aui-toast {

+	background: rgba(0, 0, 0, 0.7);

+	text-align: center;

+	border-radius: 0.25rem;

+	color: #ffffff;

+	position: fixed;

+	z-index: 300;

+	top: 45%;

+	left: 50%;

+	width: 7.5em;

+	min-height: 6em;

+	margin-left: -3.75em;

+	margin-top: -4rem;

+	display: none;

+}

+.aui-toast .aui-iconfont {

+	margin-top: 0.2rem;

+	display: block;

+	font-size: 2.6rem;

+}

+.aui-toast-content {

+  margin: 0 0 0.75rem;

+}

+.aui-toast-loading {

+    background-color: #ffffff;

+    border-radius: 100%;

+    margin: 0.75rem 0;

+    -webkit-animation-fill-mode: both;

+        	animation-fill-mode: both;

+    border: 2px solid #ffffff;

+    border-bottom-color: transparent;

+    height: 2.25rem;

+    width: 2.25rem;

+    background: transparent !important;

+    display: inline-block;

+    -webkit-animation: rotate 1s 0s linear infinite;

+        	animation: rotate 1s 0s linear infinite;

+}

+/*dialog*/

+.aui-dialog {

+	width: 13.5rem;

+	text-align: center;

+	position: fixed;

+	z-index: 999;

+	left: 50%;

+	margin-left: -6.75rem;

+	margin-top: 0;

+	top: 45%;

+	border-radius: 0.3rem;

+	opacity: 0;

+	background-color: #ffffff;

+	-webkit-transform: translate3d(0, 0, 0) scale(1.2);

+          	transform: translate3d(0, 0, 0) scale(1.2);

+ 	-webkit-transition-property: -webkit-transform, opacity;

+          	transition-property: transform, opacity;

+    /*display: none;*/

+}

+.aui-dialog-header {

+    padding: 0.5rem 0.75rem 0 0.75rem;

+    text-align: center;

+    font-size: 1em;

+    color: #212121;

+}

+.aui-dialog-body {

+    padding: 0.75rem;

+    overflow: hidden;

+    font-size: 0.875em;

+    color: #757575;

+}

+.aui-dialog-body input {

+	border: 1px solid #dddddd;

+	height: 1.8rem;

+	line-height: 1.8rem;

+	min-height: 1.8rem;

+	padding-left: 0.25rem;

+	padding-right: 0.25rem;

+}

+.aui-dialog-footer {

+    position: relative;

+    font-size: 1em;

+    border-top: 1px solid #dddddd;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: center;

+	-webkit-justify-content: center;

+			justify-content: center;

+}

+.aui-dialog-btn {

+	position: relative;

+	display: block;

+    width: 100%;

+	padding: 0 0.25rem;

+	height: 2.2rem;

+	font-size: 0.8rem;

+	line-height: 2.2rem;

+	text-align: center;

+	color: #0894ec;

+	border-right: 1px solid #dddddd;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+	overflow: hidden;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	-webkit-box-flex: 1;

+			box-flex: 1;

+}

+.aui-dialog-btn:last-child {

+	border-right: none;

+}

+.aui-dialog.aui-dialog-in {

+	opacity: 1;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+	-webkit-transform: translate3d(0, 0, 0) scale(1);

+	      transform: translate3d(0, 0, 0) scale(1);

+}

+.aui-dialog.aui-dialog-out {

+	opacity: 0;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+	-webkit-transform: translate3d(0, 0, 0) scale(0.815);

+	      transform: translate3d(0, 0, 0) scale(0.815);

+}

+@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {

+    .aui-dialog-footer {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-dialog-btn {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: right;

+	}

+	.aui-dialog-btn:last-child {

+		border: none;

+        background-size: 0 100%;

+	}

+	.aui-dialog-body input {

+        border: none;

+        background-image: -webkit-linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(0, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%;

+        background-repeat: no-repeat;

+        background-position: top, right top, bottom, left top;

+    }

+}

+/*popup*/

+.aui-popup {

+    padding: 0;

+    margin: 0;

+    background: transparent;

+    position: fixed;

+    height: auto;

+    min-width: 7rem;

+    min-height: 4.5rem;

+    z-index: 999;

+    opacity: 0;

+ 	-webkit-transition-property: -webkit-transform, opacity;

+          	transition-property: transform, opacity;

+}

+.aui-popup.aui-popup-in {

+	opacity: 1;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+}

+.aui-popup.aui-popup-out {

+	opacity: 0;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+}

+.aui-popup-right {

+    right: 0.75rem;

+}

+.aui-popup-content {

+    background-color: #ffffff;

+    border-radius: 0.2rem;

+    overflow: hidden;

+    min-height: 4.5rem;

+    height: 100%;

+}

+.aui-popup-top,

+.aui-popup-top-left,

+.aui-popup-top-right {

+    top: 0.45rem;

+}

+.aui-popup-top {

+    left: 50%;

+    margin-left: -3.5rem;

+}

+.aui-popup-top-left {

+    left: 0.45rem;

+}

+.aui-popup-top-right {

+    right: 0.45rem;

+}

+.aui-popup-arrow {

+    position: absolute;

+    width: 10px;

+    height: 10px;

+    -webkit-transform-origin: 50% 50% 0;

+            transform-origin: 50% 50% 0;

+    background-color: transparent;

+    background-image: -webkit-linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+}

+.aui-popup-top .aui-popup-arrow,

+.aui-popup-top-left .aui-popup-arrow,

+.aui-popup-top-right .aui-popup-arrow {

+    top: 0.2rem;

+    -webkit-transform: rotate(135deg);

+            transform: rotate(135deg);

+}

+.aui-popup-top .aui-popup-arrow {

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-top-left .aui-popup-arrow {

+    left: 0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-top-right .aui-popup-arrow {

+    right: 0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-bottom,

+.aui-popup-bottom-left,

+.aui-popup-bottom-right {

+    bottom: 0.45rem;

+}

+.aui-popup-bottom {

+    left: 50%;

+    margin-left: -3.5rem;

+}

+.aui-popup-bottom-left {

+    left: 0.45rem;

+}

+.aui-popup-bottom-right {

+    right: 0.45rem;

+}

+.aui-popup-bottom .aui-popup-arrow,

+.aui-popup-bottom-left .aui-popup-arrow,

+.aui-popup-bottom-right .aui-popup-arrow {

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+    bottom: 0.2rem;

+}

+.aui-popup-bottom .aui-popup-arrow {

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup-bottom-left .aui-popup-arrow {

+    left: 0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup-bottom-right .aui-popup-arrow {

+    right: 0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup .aui-list {

+	background: transparent;

+}

+.aui-popup-content .aui-list img {

+	display: block;

+	width: 1rem;

+}

+/*actionsheet*/

+.aui-actionsheet {

+    width: 100%;

+    position: fixed;

+    bottom: 0;

+    left: 0;

+    padding: 0 0.5rem;

+    z-index: 999;

+    opacity: 0;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+    -webkit-transform: translate3d(0,100%,0);

+    transform: translate3d(0,100%,0);

+}

+.aui-actionsheet-btn {

+    background-color: #ffffff;

+    border-radius: 6px;

+    text-align: center;

+    margin-bottom: 0.5rem;

+}

+.aui-actionsheet-title {

+    font-size: 0.6rem;

+    color: #999999;

+    line-height: 1.8rem;

+}

+.aui-actionsheet-btn-item {

+    height: 2.2rem;

+    line-height: 2.2rem;

+    color: #0075f0;

+}

+/*sharebox*/

+.aui-sharebox {

+    width: 100%;

+    position: fixed;

+    bottom: 0;

+    left: 0;

+    z-index: 999;

+    background-color: #ffffff;

+    opacity: 0;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+    -webkit-transform: translate3d(0,100%,0);

+    transform: translate3d(0,100%,0);

+}

+.aui-sharebox .aui-row {

+    padding: 0.5rem 0;

+}

+.aui-sharebox img {

+    display: block;

+    width: 50%;

+    margin: 0 auto;

+}

+.aui-sharebox.aui-grid [class*=aui-col-] {

+    padding: 0.5rem 0;

+}

+.aui-sharebox.aui-grid .aui-grid-label {

+    font-size: 0.6rem;

+    color: #757575;

+}

+.aui-sharebox-close-btn {

+    width: 100%;

+    height: 2.2rem;

+    line-height: 2.2rem;

+    color: #757575;

+    text-align: center;

+    font-size: 0.7rem;

+}

+/*折叠菜单*/

+.aui-collapse-header.aui-active {

+    background: #ececec;

+}

+.aui-collapse .aui-list-item:active{

+    background: #ececec;

+}

+.aui-collapse-content {

+    display: none;

+}

+.aui-collapse-content .aui-list-item:last-child {

+    border-bottom: 0;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+    .aui-collapse-content .aui-list-item:last-child {

+        background-position: bottom;

+    }

+    .aui-list.aui-collapse.aui-list-noborder,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-content:last-child .aui-list-item:last-child {

+        border: none;

+        background-size: 100% 1px;

+        background-repeat: no-repeat;

+        background-position: 0 bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+    }

+    .aui-list.aui-collapse.aui-list-noborder,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-item:last-child .aui-list-item:last-child {

+        border: none;

+        background-size: 100% 0;

+        background-image: none;

+    }

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-item:last-child .aui-list-item.aui-collapse-header,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-content .aui-list-item:last-child  {

+        border: none;

+        background-size: 100% 0;

+        background-image: none;

+    }

+}

+.aui-collapse-header.aui-active .aui-collapse-arrow {

+    display: block;

+    transform: rotate(180deg);

+    -webkit-transform: rotate(180deg);

+}

+/*聊天气泡*/

+.aui-chat {

+    width: 100%;

+    height: 100%;

+    padding: 0.5rem;

+}

+.aui-chat .aui-chat-item {

+    position: relative;

+    width: 100%;

+    margin-bottom: 0.75rem;

+    overflow: hidden;

+    display: block;

+}

+.aui-chat .aui-chat-header {

+    width: 100%;

+    text-align: center;

+    margin-bottom: 0.75rem;

+    font-size: 0.6rem;

+    color: #757575;

+}

+.aui-chat .aui-chat-left {

+    float: left;

+}

+.aui-chat .aui-chat-right {

+    float: right;

+}

+.aui-chat .aui-chat-media {

+    display: inline-block;

+    max-width: 2rem;

+}

+.aui-chat .aui-chat-media img {

+    width: 100%;

+    border-radius: 50%;

+}

+.aui-chat .aui-chat-inner {

+    position: relative;

+    overflow: hidden;

+    display: inherit;

+}

+.aui-chat .aui-chat-arrow {

+    content: '';

+    position: absolute;

+    width: 0.6rem;

+    height: 0.6rem;

+    top: 0.2rem;

+    -webkit-transform-origin: 50% 50% 0;

+            transform-origin: 50% 50% 0;

+    background-color: transparent;

+}

+.aui-chat .aui-chat-left .aui-chat-arrow {

+    background-image: -webkit-linear-gradient(45deg, #b3e5fc, #b3e5fc 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #b3e5fc, #b3e5fc 50%, transparent 50%);

+    -webkit-transform: rotate(45deg);

+            transform: rotate(45deg);

+    left: -0.25rem;

+}

+.aui-chat .aui-chat-right .aui-chat-arrow {

+    background-image: -webkit-linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    -webkit-transform: rotate(-135deg);

+            transform: rotate(-135deg);

+    right: -0.25rem;

+}

+.aui-chat .aui-chat-content {

+    color: #212121;

+    font-size: 0.7rem;

+    border-radius: 0.2rem;

+    min-height: 2rem;

+    position: relative;

+    padding: 0.5rem;

+    max-width: 80%;

+    word-break: break-all;

+    word-wrap: break-word;

+}

+.aui-chat .aui-chat-content img {

+    max-width: 100%;

+    display: block;

+}

+.aui-chat .aui-chat-status {

+    position: relative;

+    width: 2rem;

+    height: 2rem;

+    line-height: 2rem;

+    text-align: center;

+}

+.aui-chat .aui-chat-name {

+    width: 100%;

+    position: relative;

+    font-size: 0.6rem;

+    color: #757575;

+    margin-bottom: 0.25rem;

+}

+.aui-chat .aui-chat-left .aui-chat-name {

+    left: 0.5rem;

+}

+.aui-chat .aui-chat-left .aui-chat-status {

+    left: 0.5rem;

+    float: left;

+}

+.aui-chat .aui-chat-left .aui-chat-media {

+    width: 2rem;

+    float: left;

+}

+.aui-chat .aui-chat-left .aui-chat-inner {

+    max-width: 70%;

+}

+.aui-chat .aui-chat-left .aui-chat-content{

+    background-color: #b3e5fc;

+    float: left;

+    left: 0.5rem;

+}

+.aui-chat .aui-chat-right .aui-chat-media {

+    width: 2rem;

+    float: right;

+}

+.aui-chat .aui-chat-right .aui-chat-inner {

+    float: right;

+    max-width: 70%;

+}

+.aui-chat .aui-chat-right .aui-chat-name {

+    float: right;

+    right: 0.5rem;

+    text-align: right;

+}

+.aui-chat .aui-chat-right .aui-chat-content {

+    background-color: #ffffff;

+    right: 0.5rem;

+    float: right;

+}

+.aui-chat .aui-chat-right .aui-chat-status {

+    float: right;

+    right: 0.5rem;

+}

+/*边框样式*/

+.aui-border-l {

+    border-left: 1px solid #dddddd;

+}

+.aui-border-r {

+    border-right: 1px solid #dddddd;

+}

+.aui-border-t {

+    border-top: 1px solid #dddddd;

+}

+.aui-border-b {

+    border-bottom: 1px solid #dddddd;

+}

+.aui-border {

+    border: 1px solid #dddddd;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-border-l {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: left;

+	}

+	.aui-border-r {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: right;

+	}

+	.aui-border-t{

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-border-b {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-border{

+        border: none;

+        background-image: -webkit-linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(0, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%;

+        background-repeat: no-repeat;

+        background-position: top, right top, bottom, left top;

+    }

+}

+/*时间轴*/

+.aui-timeline {

+    position: relative;

+    padding: 0;

+    list-style: none;

+}

+.aui-timeline:before {

+    content: '';

+    position: absolute;

+    top: 0;

+    left: 1.85rem;

+    width: 2px;

+    height: 100%;

+    background: #ececec;

+    z-index: 0;

+}

+.aui-timeline .aui-timeline-item {

+    position: relative;

+    margin-bottom: 0.35rem;

+}

+.aui-timeline .aui-timeline-item-header {

+	background-color: #ececec;

+	padding: 0.2rem 0.5rem;

+	margin: 0.75rem;

+    text-align: center;

+    display: inline-block;

+    position: relative;

+    z-index: 1;

+    font-size: 0.7rem;

+}

+.aui-timeline .aui-timeline-item-label {

+    width: 2.5rem;

+    height: 1.5rem;

+    line-height: 1.5rem;

+    font-size: 0.7em;

+    background-color: #ececec;

+    position: absolute;

+    text-align: center;

+    left: 0.75rem;

+    top: 0;

+}

+.aui-timeline .aui-timeline-item-label-icon {

+    width: 1.5rem;

+    height: 1.5rem;

+    font-size: 0.7rem;

+    line-height: 1.5rem;

+    background-color: #ececec;

+    position: absolute;

+    border-radius: 50%;

+    text-align: center;

+    left: 1.15rem;

+    top: 0;

+}

+.aui-timeline .aui-timeline-item-inner {

+    margin-left: 3.75rem;

+    margin-right: 0.75rem;

+    padding: 0;

+    position: relative;

+}

+/*基础动画类*/

+@keyframes rotate {

+    0% {

+        -webkit-transform: rotate(0deg) scale(1);

+            	transform: rotate(0deg) scale(1);

+    }

+    50% {

+        -webkit-transform: rotate(180deg) scale(1);

+            	transform: rotate(180deg) scale(1);

+    }

+    100% {

+        -webkit-transform: rotate(360deg) scale(1);

+            	transform: rotate(360deg) scale(1);

+    }

+}

+@-webkit-keyframes rotate {

+    0% {

+        -webkit-transform: rotate(0deg) scale(1);

+            	transform: rotate(0deg) scale(1);

+    }

+    50% {

+        -webkit-transform: rotate(180deg) scale(1);

+            	transform: rotate(180deg) scale(1);

+    }

+    100% {

+        -webkit-transform: rotate(360deg) scale(1);

+            	transform: rotate(360deg) scale(1);

+    }

+}

+@keyframes bounce {

+	0%, 100% {

+	-webkit-transform: scale(0.0);

+			transform: scale(0.0);

+	}

+	50% {

+	-webkit-transform: scale(1.0);

+			transform: scale(1.0);

+	}

+}

+@-webkit-keyframes bounce {

+	0%, 100% {

+		-webkit-transform: scale(0.0);

+				transform: scale(0.0);

+	}

+	50% {

+		-webkit-transform: scale(1.0);

+				transform: scale(1.0);

+	}

+}

+@keyframes fadeIn {

+    from { opacity: 0.3; }

+    to { opacity: 1; }

+}

+@-webkit-keyframes fadeIn {

+    from { opacity: 0.3; }

+    to { opacity: 1; }

+}

+@font-face {

+	font-family: "aui_iconfont";

+	src: url('aui-iconfont.ttf') format('truetype');

+}

+.aui-iconfont {

+	position: relative;

+	font-family:"aui_iconfont" !important;

+	font-size: 0.7rem;

+	font-style:normal;

+	-webkit-font-smoothing: antialiased;

+	-moz-osx-font-smoothing: grayscale;

+}

+.aui-icon-menu:before { content: "\e6eb"; }

+.aui-icon-paper:before { content: "\e6ec"; }

+.aui-icon-info:before { content: "\e6ed"; }

+.aui-icon-question:before { content: "\e6ee"; }

+.aui-icon-left:before { content: "\e6f4"; }

+.aui-icon-right:before { content: "\e6f5"; }

+.aui-icon-top:before { content: "\e6f6"; }

+.aui-icon-down:before { content: "\e6f7"; }

+.aui-icon-share:before { content: "\e700"; }

+.aui-icon-comment:before { content: "\e701"; }

+.aui-icon-edit:before { content: "\e6d3"; }

+.aui-icon-trash:before { content: "\e6d4"; }

+.aui-icon-recovery:before { content: "\e6dc"; }

+.aui-icon-refresh:before { content: "\e6dd"; }

+.aui-icon-close:before { content: "\e6d8"; }

+.aui-icon-cart:before { content: "\e6df"; }

+.aui-icon-star:before { content: "\e6e0"; }

+.aui-icon-plus:before { content: "\e6e3"; }

+.aui-icon-minus:before { content: "\e62d"; }

+.aui-icon-correct:before { content: "\e6e5"; }

+.aui-icon-search:before { content: "\e6e6"; }

+.aui-icon-gear:before { content: "\e6e8"; }

+.aui-icon-map:before { content: "\e6d2"; }

+.aui-icon-location:before { content: "\e6d1"; }

+.aui-icon-image:before { content: "\e6ce"; }

+.aui-icon-phone:before { content: "\e6c4"; }

+.aui-icon-camera:before { content: "\e6cd"; }

+.aui-icon-video:before { content: "\e6cc"; }

+.aui-icon-qq:before { content: "\e6cb"; }

+.aui-icon-wechat:before { content: "\e6c9"; }

+.aui-icon-weibo:before { content: "\e6c8"; }

+.aui-icon-note:before { content: "\e6c6"; }

+.aui-icon-mail:before { content: "\e6c5"; }

+.aui-icon-wechat-circle:before { content: "\e6ca"; }

+.aui-icon-home:before { content: "\e706"; }

+.aui-icon-forward:before { content: "\e6d9"; }

+.aui-icon-back:before { content: "\e6da"; }

+.aui-icon-laud:before { content: "\e64b"; }

+.aui-icon-lock:before { content: "\e6ef"; }

+.aui-icon-unlock:before { content: "\e62f"; }

+.aui-icon-like:before { content: "\e62b"; }

+.aui-icon-my:before { content: "\e610"; }

+.aui-icon-more:before { content: "\e625"; }

+.aui-icon-mobile:before { content: "\e697"; }

+.aui-icon-calendar:before { content: "\e68a"; }

+.aui-icon-date:before { content: "\e68c"; }

+.aui-icon-display:before { content: "\e612"; }

+.aui-icon-hide:before { content: "\e624"; }

+.aui-icon-pencil:before { content: "\e615"; }

+.aui-icon-flag:before { content: "\e6f1"; }

+.aui-icon-cert:before { content: "\e704"; }

+

+.aui-card-list-user:after {

+	width: 100%;

+    height: 1px;

+    background-color: #f2f2f2;

+    display: block;

+    content: '';

+    position: absolute;

+    top: auto;

+    right: auto;

+    bottom: 0;

+    left: 0;

+    z-index: 2;

+    -webkit-transform-origin: 50% 100%;

+            transform-origin: 50% 100%;

+    pointer-events: none;

+}

+.aui-list [class*=top-btn]:active {

+	background-color: #048cca;

+}

diff --git a/platforms/android/app/src/main/assets/www/css/index.css b/platforms/android/app/src/main/assets/www/css/index.css
new file mode 100644
index 0000000..b23e33c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/css/index.css
@@ -0,0 +1,149 @@
+body {
+    background: #F1F4F4;
+}
+
+.mainbg {
+    background: #03a9f4;
+}
+
+.lightbg {
+    background: #54C8FF;
+}
+
+.tab-bottom button.active::after {
+    background-color: transparent;
+}
+
+.maincolor {
+    color: #03a9f4;
+}
+
+.qrscanner {
+    width: 100%;
+    background: transparent none !important;
+    padding-top: 52px;
+}
+
+.qrscanner-area {
+    height: 100mm;
+    background: url(../img/scanner.svg) no-repeat center center;
+    background-size: contain;
+}
+
+.through-line {
+    left: 20%;
+    width: 60%;
+    height: 2px;
+    background: red;
+    position: absolute;
+    animation: myfirst 2s linear infinite alternate;
+}
+
+@keyframes myfirst {
+    0% {
+        background: #03a9f4;
+        top: 180px;
+    }
+
+    25% {
+        background: #03a9f4;
+        top: 215px;
+    }
+
+    50% {
+        background: #03a9f4;
+        top: 250px;
+    }
+
+    75% {
+        background: #03a9f4;
+        top: 285px;
+    }
+
+    100% {
+        background: #03a9f4;
+        top: 320px;
+    }
+}
+
+.button-bottom {
+    width: 128px;
+    position: absolute;
+    left: 50%;
+    bottom: 80px;
+    margin-left: -64px;
+}
+
+.icon-camera {
+    float: left;
+}
+
+.vcodedisabled {
+    color: #999 !important;
+}
+
+.login-top {
+    height: 200px;
+    background: #03a9f4;
+    color: #fff;
+    font-size: 36px;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+}
+
+.weui-toast_content {
+    color: #fff;
+}
+
+.center-in {
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    display: flex;
+}
+
+.top-title {
+    color: #fff;
+    font-size: 20px !important;
+    margin-top: 5px;
+}
+
+.user-info {
+    width: 150%;
+    position: relative;
+    left: -25%;
+    padding-left: 25%;
+    border-bottom-left-radius: 50%;
+    border-bottom-right-radius: 50%;
+    padding-bottom: 1.5rem;
+}
+
+.text-white {
+    color: #ffffff !important;
+}
+
+.text-light {
+    color: #999 !important;
+}
+
+.bg-white {
+    background-color: #ffffff;
+}
+.demos-header {
+    padding: 20px 0;
+    background-color: #03a9f4;
+}
+.demos-title {
+    text-align: center;
+    font-size: 40px;
+    color: #fff;
+    font-weight: 400;
+    margin: 0 15%;
+}
+.detail-title{
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+}
diff --git a/platforms/android/app/src/main/assets/www/css/jquery-weui.min.css b/platforms/android/app/src/main/assets/www/css/jquery-weui.min.css
new file mode 100755
index 0000000..145c336
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/css/jquery-weui.min.css
@@ -0,0 +1,6 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+.preloader{width:20px;height:20px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:preloader-spin 1s steps(12,end) infinite;animation:preloader-spin 1s steps(12,end) infinite}.preloader:after{display:block;width:100%;height:100%;content:"";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-repeat:no-repeat;background-position:50%;background-size:100%}@-webkit-keyframes preloader-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}label>*{pointer-events:none}html{font-size:20px}body{font-size:16px}@media only screen and (min-width:400px){html{font-size:21.33px!important}}@media only screen and (min-width:414px){html{font-size:22.08px!important}}@media only screen and (min-width:480px){html{font-size:25.6px!important}}.weui_navbar{z-index:10}.weui-mask,.weui-popup-container,.weui-popup-overlay{z-index:1000}.weui-row{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.weui-row>[class*=col-]{box-sizing:border-box}.weui-row .col-auto{width:100%}.weui-row .weui-col-100{width:100%;width:calc((100% - 15px*0)/ 1)}.weui-row.weui-no-gutter .weui-col-100{width:100%}.weui-row .weui-col-95{width:95%;width:calc((100% - 15px*.05263157894736836)/ 1.0526315789473684)}.weui-row.weui-no-gutter .weui-col-95{width:95%}.weui-row .weui-col-90{width:90%;width:calc((100% - 15px*.11111111111111116)/ 1.1111111111111112)}.weui-row.weui-no-gutter .weui-col-90{width:90%}.weui-row .weui-col-85{width:85%;width:calc((100% - 15px*.17647058823529416)/ 1.1764705882352942)}.weui-row.weui-no-gutter .weui-col-85{width:85%}.weui-row .weui-col-80{width:80%;width:calc((100% - 15px*.25)/ 1.25)}.weui-row.weui-no-gutter .weui-col-80{width:80%}.weui-row .weui-col-75{width:75%;width:calc((100% - 15px*.33333333333333326)/ 1.3333333333333333)}.weui-row.weui-no-gutter .weui-col-75{width:75%}.weui-row .weui-col-66{width:66.66666666666666%;width:calc((100% - 15px*.5000000000000002)/ 1.5000000000000002)}.weui-row.weui-no-gutter .weui-col-66{width:66.66666666666666%}.weui-row .weui-col-60{width:60%;width:calc((100% - 15px*.6666666666666667)/ 1.6666666666666667)}.weui-row.weui-no-gutter .weui-col-60{width:60%}.weui-row .weui-col-50{width:50%;width:calc((100% - 15px*1)/ 2)}.weui-row.weui-no-gutter .weui-col-50{width:50%}.weui-row .weui-col-40{width:40%;width:calc((100% - 15px*1.5)/ 2.5)}.weui-row.weui-no-gutter .weui-col-40{width:40%}.weui-row .weui-col-33{width:33.333333333333336%;width:calc((100% - 15px*2)/ 3)}.weui-row.weui-no-gutter .weui-col-33{width:33.333333333333336%}.weui-row .weui-col-25{width:25%;width:calc((100% - 15px*3)/ 4)}.weui-row.weui-no-gutter .weui-col-25{width:25%}.weui-row .weui-col-20{width:20%;width:calc((100% - 15px*4)/ 5)}.weui-row.weui-no-gutter .weui-col-20{width:20%}.weui-row .weui-col-15{width:15%;width:calc((100% - 15px*5.666666666666667)/ 6.666666666666667)}.weui-row.weui-no-gutter .weui-col-15{width:15%}.weui-row .weui-col-10{width:10%;width:calc((100% - 15px*9)/ 10)}.weui-row.weui-no-gutter .weui-col-10{width:10%}.weui-row .weui-col-5{width:5%;width:calc((100% - 15px*19)/ 20)}.weui-row.weui-no-gutter .weui-col-5{width:5%}.weui-row .weui-col-auto:nth-last-child(1),.weui-row .weui-col-auto:nth-last-child(1)~.weui-col-auto{width:100%;width:calc((100% - 15px*0)/ 1)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(1),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(1)~.weui-col-auto{width:100%}.weui-row .weui-col-auto:nth-last-child(2),.weui-row .weui-col-auto:nth-last-child(2)~.weui-col-auto{width:50%;width:calc((100% - 15px*1)/ 2)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(2),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(2)~.weui-col-auto{width:50%}.weui-row .weui-col-auto:nth-last-child(3),.weui-row .weui-col-auto:nth-last-child(3)~.weui-col-auto{width:33.33333333%;width:calc((100% - 15px*2)/ 3)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(3),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(3)~.weui-col-auto{width:33.33333333%}.weui-row .weui-col-auto:nth-last-child(4),.weui-row .weui-col-auto:nth-last-child(4)~.weui-col-auto{width:25%;width:calc((100% - 15px*3)/ 4)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(4),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(4)~.weui-col-auto{width:25%}.weui-row .weui-col-auto:nth-last-child(5),.weui-row .weui-col-auto:nth-last-child(5)~.weui-col-auto{width:20%;width:calc((100% - 15px*4)/ 5)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(5),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(5)~.weui-col-auto{width:20%}.weui-row .weui-col-auto:nth-last-child(6),.weui-row .weui-col-auto:nth-last-child(6)~.weui-col-auto{width:16.66666667%;width:calc((100% - 15px*5)/ 6)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(6),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(6)~.weui-col-auto{width:16.66666667%}.weui-row .weui-col-auto:nth-last-child(7),.weui-row .weui-col-auto:nth-last-child(7)~.weui-col-auto{width:14.28571429%;width:calc((100% - 15px*6)/ 7)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(7),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(7)~.weui-col-auto{width:14.28571429%}.weui-row .weui-col-auto:nth-last-child(8),.weui-row .weui-col-auto:nth-last-child(8)~.weui-col-auto{width:12.5%;width:calc((100% - 15px*7)/ 8)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(8),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(8)~.weui-col-auto{width:12.5%}.weui-row .weui-col-auto:nth-last-child(9),.weui-row .weui-col-auto:nth-last-child(9)~.weui-col-auto{width:11.11111111%;width:calc((100% - 15px*8)/ 9)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(9),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(9)~.weui-col-auto{width:11.11111111%}.weui-row .weui-col-auto:nth-last-child(10),.weui-row .weui-col-auto:nth-last-child(10)~.weui-col-auto{width:10%;width:calc((100% - 15px*9)/ 10)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(10),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(10)~.weui-col-auto{width:10%}.weui-row .weui-col-auto:nth-last-child(11),.weui-row .weui-col-auto:nth-last-child(11)~.weui-col-auto{width:9.09090909%;width:calc((100% - 15px*10)/ 11)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(11),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(11)~.weui-col-auto{width:9.09090909%}.weui-row .weui-col-auto:nth-last-child(12),.weui-row .weui-col-auto:nth-last-child(12)~.weui-col-auto{width:8.33333333%;width:calc((100% - 15px*11)/ 12)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(12),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(12)~.weui-col-auto{width:8.33333333%}.weui-row .weui-col-auto:nth-last-child(13),.weui-row .weui-col-auto:nth-last-child(13)~.weui-col-auto{width:7.69230769%;width:calc((100% - 15px*12)/ 13)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(13),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(13)~.weui-col-auto{width:7.69230769%}.weui-row .weui-col-auto:nth-last-child(14),.weui-row .weui-col-auto:nth-last-child(14)~.weui-col-auto{width:7.14285714%;width:calc((100% - 15px*13)/ 14)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(14),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(14)~.weui-col-auto{width:7.14285714%}.weui-row .weui-col-auto:nth-last-child(15),.weui-row .weui-col-auto:nth-last-child(15)~.weui-col-auto{width:6.66666667%;width:calc((100% - 15px*14)/ 15)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(15),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(15)~.weui-col-auto{width:6.66666667%}@media all and (min-width:768px){.row .tablet-100{width:100%;width:calc((100% - 15px*0)/ 1)}.row.no-gutter .tablet-100{width:100%}.row .tablet-95{width:95%;width:calc((100% - 15px*.05263157894736836)/ 1.0526315789473684)}.row.no-gutter .tablet-95{width:95%}.row .tablet-90{width:90%;width:calc((100% - 15px*.11111111111111116)/ 1.1111111111111112)}.row.no-gutter .tablet-90{width:90%}.row .tablet-85{width:85%;width:calc((100% - 15px*.17647058823529416)/ 1.1764705882352942)}.row.no-gutter .tablet-85{width:85%}.row .tablet-80{width:80%;width:calc((100% - 15px*.25)/ 1.25)}.row.no-gutter .tablet-80{width:80%}.row .tablet-75{width:75%;width:calc((100% - 15px*.33333333333333326)/ 1.3333333333333333)}.row.no-gutter .tablet-75{width:75%}.row .tablet-66{width:66.66666666666666%;width:calc((100% - 15px*.5000000000000002)/ 1.5000000000000002)}.row.no-gutter .tablet-66{width:66.66666666666666%}.row .tablet-60{width:60%;width:calc((100% - 15px*.6666666666666667)/ 1.6666666666666667)}.row.no-gutter .tablet-60{width:60%}.row .tablet-50{width:50%;width:calc((100% - 15px*1)/ 2)}.row.no-gutter .tablet-50{width:50%}.row .tablet-40{width:40%;width:calc((100% - 15px*1.5)/ 2.5)}.row.no-gutter .tablet-40{width:40%}.row .tablet-33{width:33.333333333333336%;width:calc((100% - 15px*2)/ 3)}.row.no-gutter .tablet-33{width:33.333333333333336%}.row .tablet-25{width:25%;width:calc((100% - 15px*3)/ 4)}.row.no-gutter .tablet-25{width:25%}.row .tablet-20{width:20%;width:calc((100% - 15px*4)/ 5)}.row.no-gutter .tablet-20{width:20%}.row .tablet-15{width:15%;width:calc((100% - 15px*5.666666666666667)/ 6.666666666666667)}.row.no-gutter .tablet-15{width:15%}.row .tablet-10{width:10%;width:calc((100% - 15px*9)/ 10)}.row.no-gutter .tablet-10{width:10%}.row .tablet-5{width:5%;width:calc((100% - 15px*19)/ 20)}.row.no-gutter .tablet-5{width:5%}.row .tablet-auto:nth-last-child(1),.row .tablet-auto:nth-last-child(1)~.col-auto{width:100%;width:calc((100% - 15px*0)/ 1)}.row.no-gutter .tablet-auto:nth-last-child(1),.row.no-gutter .tablet-auto:nth-last-child(1)~.tablet-auto{width:100%}.row .tablet-auto:nth-last-child(2),.row .tablet-auto:nth-last-child(2)~.col-auto{width:50%;width:calc((100% - 15px*1)/ 2)}.row.no-gutter .tablet-auto:nth-last-child(2),.row.no-gutter .tablet-auto:nth-last-child(2)~.tablet-auto{width:50%}.row .tablet-auto:nth-last-child(3),.row .tablet-auto:nth-last-child(3)~.col-auto{width:33.33333333%;width:calc((100% - 15px*2)/ 3)}.row.no-gutter .tablet-auto:nth-last-child(3),.row.no-gutter .tablet-auto:nth-last-child(3)~.tablet-auto{width:33.33333333%}.row .tablet-auto:nth-last-child(4),.row .tablet-auto:nth-last-child(4)~.col-auto{width:25%;width:calc((100% - 15px*3)/ 4)}.row.no-gutter .tablet-auto:nth-last-child(4),.row.no-gutter .tablet-auto:nth-last-child(4)~.tablet-auto{width:25%}.row .tablet-auto:nth-last-child(5),.row .tablet-auto:nth-last-child(5)~.col-auto{width:20%;width:calc((100% - 15px*4)/ 5)}.row.no-gutter .tablet-auto:nth-last-child(5),.row.no-gutter .tablet-auto:nth-last-child(5)~.tablet-auto{width:20%}.row .tablet-auto:nth-last-child(6),.row .tablet-auto:nth-last-child(6)~.col-auto{width:16.66666667%;width:calc((100% - 15px*5)/ 6)}.row.no-gutter .tablet-auto:nth-last-child(6),.row.no-gutter .tablet-auto:nth-last-child(6)~.tablet-auto{width:16.66666667%}.row .tablet-auto:nth-last-child(7),.row .tablet-auto:nth-last-child(7)~.col-auto{width:14.28571429%;width:calc((100% - 15px*6)/ 7)}.row.no-gutter .tablet-auto:nth-last-child(7),.row.no-gutter .tablet-auto:nth-last-child(7)~.tablet-auto{width:14.28571429%}.row .tablet-auto:nth-last-child(8),.row .tablet-auto:nth-last-child(8)~.col-auto{width:12.5%;width:calc((100% - 15px*7)/ 8)}.row.no-gutter .tablet-auto:nth-last-child(8),.row.no-gutter .tablet-auto:nth-last-child(8)~.tablet-auto{width:12.5%}.row .tablet-auto:nth-last-child(9),.row .tablet-auto:nth-last-child(9)~.col-auto{width:11.11111111%;width:calc((100% - 15px*8)/ 9)}.row.no-gutter .tablet-auto:nth-last-child(9),.row.no-gutter .tablet-auto:nth-last-child(9)~.tablet-auto{width:11.11111111%}.row .tablet-auto:nth-last-child(10),.row .tablet-auto:nth-last-child(10)~.col-auto{width:10%;width:calc((100% - 15px*9)/ 10)}.row.no-gutter .tablet-auto:nth-last-child(10),.row.no-gutter .tablet-auto:nth-last-child(10)~.tablet-auto{width:10%}.row .tablet-auto:nth-last-child(11),.row .tablet-auto:nth-last-child(11)~.col-auto{width:9.09090909%;width:calc((100% - 15px*10)/ 11)}.row.no-gutter .tablet-auto:nth-last-child(11),.row.no-gutter .tablet-auto:nth-last-child(11)~.tablet-auto{width:9.09090909%}.row .tablet-auto:nth-last-child(12),.row .tablet-auto:nth-last-child(12)~.col-auto{width:8.33333333%;width:calc((100% - 15px*11)/ 12)}.row.no-gutter .tablet-auto:nth-last-child(12),.row.no-gutter .tablet-auto:nth-last-child(12)~.tablet-auto{width:8.33333333%}.row .tablet-auto:nth-last-child(13),.row .tablet-auto:nth-last-child(13)~.col-auto{width:7.69230769%;width:calc((100% - 15px*12)/ 13)}.row.no-gutter .tablet-auto:nth-last-child(13),.row.no-gutter .tablet-auto:nth-last-child(13)~.tablet-auto{width:7.69230769%}.row .tablet-auto:nth-last-child(14),.row .tablet-auto:nth-last-child(14)~.col-auto{width:7.14285714%;width:calc((100% - 15px*13)/ 14)}.row.no-gutter .tablet-auto:nth-last-child(14),.row.no-gutter .tablet-auto:nth-last-child(14)~.tablet-auto{width:7.14285714%}.row .tablet-auto:nth-last-child(15),.row .tablet-auto:nth-last-child(15)~.col-auto{width:6.66666667%;width:calc((100% - 15px*14)/ 15)}.row.no-gutter .tablet-auto:nth-last-child(15),.row.no-gutter .tablet-auto:nth-last-child(15)~.tablet-auto{width:6.66666667%}}.weui-cell__hd img{display:block;margin-right:5px}.weui-cell_swiped .weui-cell__bd{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.swipeout-touching .weui-cell__bd{-webkit-transition:none;transition:none}.weui-dialog,.weui-toast{-webkit-transition-duration:.2s;transition-duration:.2s;opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:0 0;transform-origin:0 0;visibility:hidden;margin:0;top:45%;z-index:2000}.weui-dialog .weui-dialog__btn.default,.weui-toast .weui-dialog__btn.default{color:#5f646e}.weui-dialog .weui-dialog__btn+.weui-dialog__btn,.weui-toast .weui-dialog__btn+.weui-dialog__btn{position:relative}.weui-dialog .weui-dialog__btn+.weui-dialog__btn:after,.weui-toast .weui-dialog__btn+.weui-dialog__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;height:100%;border-left:1px solid #D5D5D6;color:#D5D5D6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-dialog.weui-dialog--visible,.weui-dialog.weui-toast--visible,.weui-toast.weui-dialog--visible,.weui-toast.weui-toast--visible{opacity:1;visibility:visible}.weui-toast_forbidden{color:#F76260}.weui-toast_cancel .weui-icon-toast:before{content:"\EA0D"}.weui-toast_forbidden .weui-icon-toast:before{content:"\EA0B";color:#F76260}.weui-toast_text{min-height:1em;width:auto;height:45px;border-radius:25px;margin-left:0;-webkit-transform:scale(.9) translate3d(-50%,0,0);transform:scale(.9) translate3d(-50%,0,0);-webkit-transform-origin:left;transform-origin:left}.weui-toast_text.weui-toast--visible{-webkit-transform:scale(1) translate3d(-50%,0,0);transform:scale(1) translate3d(-50%,0,0)}.weui-toast_text .weui-icon-toast{display:none}.weui-toast_text .weui-toast_content{margin:10px 15px}.weui-mask{opacity:0;-webkit-transition-duration:.3s;transition-duration:.3s;visibility:hidden}.weui-mask.weui-mask--visible{opacity:1;visibility:visible}.weui-prompt-input{padding:4px 6px;border:1px solid #ccc;box-sizing:border-box;height:2em;width:80%;margin-top:10px}.weui-pull-to-refresh{margin-top:-50px;-webkit-transition:-webkit-transform .4s;transition:-webkit-transform .4s;transition:transform .4s;transition:transform .4s,-webkit-transform .4s}.weui-pull-to-refresh.refreshing{-webkit-transform:translate3d(0,50px,0);transform:translate3d(0,50px,0)}.weui-pull-to-refresh.touching{-webkit-transition-duration:0s;transition-duration:0s}.weui-pull-to-refresh__layer{height:30px;line-height:30px;padding:10px;text-align:center}.weui-pull-to-refresh__layer .down{display:inline-block}.weui-pull-to-refresh__layer .refresh,.weui-pull-to-refresh__layer .up{display:none}.weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:inline-block;z-index:10;width:20px;height:20px;margin-right:4px;vertical-align:-4px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2026%2040'%3E%3Cpolygon%20points%3D'9%2C22%209%2C0%2017%2C0%2017%2C22%2026%2C22%2013.5%2C40%200%2C22'%20fill%3D'%238c8c8c'%2F%3E%3C%2Fsvg%3E") center no-repeat;background-size:13px 20px;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:rotate(0) translate3d(0,0,0);transform:rotate(0) translate3d(0,0,0)}.weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader{display:none;vertical-align:-4px;margin-right:4px;width:20px;height:20px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:preloader-spin 1s steps(12,end) infinite;animation:preloader-spin 1s steps(12,end) infinite}.weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader:after{display:block;width:100%;height:100%;content:"";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-repeat:no-repeat;background-position:50%;background-size:100%}.pull-up .weui-pull-to-refresh__layer .down,.refreshing .weui-pull-to-refresh__layer .down{display:none}.pull-up .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:inline-block;-webkit-transform:rotate(180deg) translate3d(0,0,0);transform:rotate(180deg) translate3d(0,0,0)}.pull-down .weui-pull-to-refresh__layer .down,.pull-down .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow,.pull-up .weui-pull-to-refresh__layer .up{display:inline-block}.refreshing .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:none}.refreshing .weui-pull-to-refresh__layer .refresh,.refreshing .weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader{display:inline-block}@keyframes preloader-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.weui-tab__bd-item.weui-pull-to-refresh{position:absolute;top:50px}.toolbar,.weui-tabbar__item{position:relative}.weui-tabbar__item.weui-bar__item--on .weui-tabbar__label{color:#04BE02}.weui-navbar__item{color:#888}.weui-navbar__item.weui-bar__item--on{color:#666;background-color:#f1f1f1}.toolbar,.toolbar .title{font-size:.85rem;color:#3d4145;width:100%}.weui-tab__bd{box-sizing:border-box;height:100%}.weui-tab__bd .weui-tab__bd-item{display:none;height:100%;overflow:auto}.weui-tab__bd .weui-tab__bd-item.weui-tab__bd-item--active{display:block}.weui-navbar+.weui-tab__bd{padding-top:50px}.toolbar{line-height:1.5;background:#f7f7f8}.toolbar:before{content:'';position:absolute;left:0;top:0;bottom:auto;right:auto;height:1px;width:100%;background-color:#d9d9d9;display:block;z-index:15;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.toolbar:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.toolbar:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.toolbar .toolbar-inner{height:2.2rem;display:-webkit-box;display:-ms-flexbox;display:flex;text-align:center}.toolbar .title{position:absolute;display:block;padding:0;font-weight:400;line-height:2.2rem;text-align:center;white-space:nowrap}.toolbar .picker-button{position:absolute;right:0;box-sizing:border-box;height:2.2rem;line-height:2.2rem;color:#04BE02;z-index:1;padding:0 .5rem}.weui-picker-modal{width:100%;position:absolute;bottom:0;text-align:center;border-radius:0;opacity:.6;color:#3d4145;-webkit-transition-duration:.3s;transition-duration:.3s;height:13rem;background:#EFEFF4;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.weui-picker-modal.picker-modal-inline{height:10.8rem;opacity:1;position:static;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-picker-modal.picker-modal-inline .toolbar{display:none}.weui-picker-modal.picker-columns-single .picker-items-col{width:100%}.weui-picker-modal.weui-picker-modal-visible{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-picker-modal .picker-modal-inner{position:relative;height:10.8rem}.weui-picker-modal .picker-columns{width:100%;height:13rem;z-index:11500}.popover .weui-picker-modal .picker-columns,.weui-picker-modal .picker-columns.picker-modal-inline{height:10rem}@media (orientation:landscape) and (max-height:415px){.weui-picker-modal .picker-columns:not(.picker-modal-inline){height:10rem}}.weui-picker-modal .popover.popover-picker-columns{width:14rem}.weui-picker-modal .picker-items{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%;padding:0;text-align:right;font-size:1rem;font-weight:400;-webkit-mask-box-image:-webkit-linear-gradient(bottom,transparent,transparent 5%,#fff 20%,#fff 80%,transparent 95%,transparent);-webkit-mask-box-image:linear-gradient(to top,transparent,transparent 5%,#fff 20%,#fff 80%,transparent 95%,transparent)}.weui-picker-modal .bar+.picker-items{height:10.8rem}.weui-picker-modal .picker-items-col{overflow:hidden;position:relative;max-height:100%}.weui-picker-modal .picker-items-col.picker-items-col-left{text-align:left}.weui-picker-modal .picker-items-col.picker-items-col-center{text-align:center}.weui-picker-modal .picker-items-col.picker-items-col-right{text-align:right}.weui-picker-modal .picker-items-col.picker-items-col-divider{color:#3d4145;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.weui-picker-modal .picker-items-col-wrapper{-webkit-transition:.3s;transition:.3s;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.weui-picker-modal .picker-item{height:32px;line-height:32px;padding:0 10px;white-space:nowrap;position:relative;overflow:hidden;text-overflow:ellipsis;color:#9b9b9b;left:0;top:0;width:100%;box-sizing:border-box;-webkit-transition:.3s;transition:.3s}.picker-items-col-absolute .weui-picker-modal .picker-item{position:absolute}.weui-picker-modal .picker-item.picker-item-far{pointer-events:none}.weui-picker-modal .picker-item.picker-selected{color:#3d4145;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transform:rotateX(0);transform:rotateX(0)}.weui-picker-modal .picker-center-highlight{height:32px;box-sizing:border-box;position:absolute;left:0;width:100%;top:50%;margin-top:-16px;pointer-events:none}.weui-picker-modal .picker-center-highlight:after,.weui-picker-modal .picker-center-highlight:before{content:'';position:absolute;right:auto;height:1px;background-color:#D9D9D9;display:block;z-index:15;left:0;width:100%}.weui-picker-modal .picker-center-highlight:before{top:0;bottom:auto;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.weui-picker-modal .picker-center-highlight:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.weui-picker-modal .picker-center-highlight:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-center-highlight:after{bottom:0;top:auto;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.weui-picker-modal .picker-center-highlight:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.weui-picker-modal .picker-center-highlight:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-3d .picker-items{overflow:hidden;-webkit-perspective:1200px;perspective:1200px}.weui-picker-modal .picker-3d .picker-item,.weui-picker-modal .picker-3d .picker-items-col,.weui-picker-modal .picker-3d .picker-items-col-wrapper{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.weui-picker-modal .picker-3d .picker-items-col{overflow:visible}.weui-picker-modal .picker-3d .picker-item{-webkit-transform-origin:center center -110px;transform-origin:center center -110px;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.weui-picker-container,.weui-picker-overlay{position:fixed;bottom:0;left:0;right:0;height:0;width:100%;z-index:1000}.picker-calendar-row:after,.picker-calendar-week-days:after{content:'';z-index:15;left:0;right:auto}.city-picker .picker-items-col{-webkit-box-flex:1;-ms-flex:1;flex:1;max-width:7rem}.weui-picker-container .weui-cells{margin:0;text-align:left}.datetime-picker .picker-item{text-overflow:initial}.weui-select-modal{height:auto}.weui-select-modal .weui-cells{margin:0;text-align:left;overflow-y:auto;overflow-x:hidden;max-height:16rem}.weui-select-modal .weui-cells:after{display:none}.weui-picker-calendar{background:#fff;height:15rem;width:100%;overflow:hidden}.weui-picker-calendar .picker-modal-inner{overflow:hidden;height:12.8rem}.picker-calendar-week-days{height:.9rem;background:#f7f7f8;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:11px;box-sizing:border-box;position:relative}.picker-calendar-week-days:after{position:absolute;bottom:0;top:auto;height:1px;width:100%;background-color:#c4c4c4;display:block;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar-week-days:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar-week-days:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.picker-calendar-week-days .picker-calendar-week-day{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;width:14.28571429%;width:calc(100% / 7);line-height:17px;text-align:center}.picker-calendar-week-days+.picker-calendar-months{height:11.9rem}.picker-calendar-months{width:100%;height:100%;overflow:hidden;position:relative}.picker-calendar-months-wrapper{position:relative;width:100%;height:100%;-webkit-transition:.3s;transition:.3s}.picker-calendar-month{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column;width:100%;height:100%;position:absolute;left:0;top:0}.picker-calendar-row{height:16.66666667%;height:calc(100% / 6);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;width:100%;position:relative}.picker-calendar-row:after{position:absolute;bottom:0;top:auto;height:1px;width:100%;background-color:#ccc;display:block;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar-row:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar-row:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-calendar-row:last-child:after{display:none}.picker-calendar-day{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;box-sizing:border-box;width:14.28571429%;width:calc(100% / 7);text-align:center;color:#3d4145;font-size:15px;cursor:pointer}.picker-calendar-day.picker-calendar-day-next,.picker-calendar-day.picker-calendar-day-prev{color:#ccc}.picker-calendar-day.picker-calendar-day-disabled{color:#d4d4d4;cursor:auto}.picker-calendar-day.picker-calendar-day-today span{background:#e3e3e3}.picker-calendar-day.picker-calendar-day-selected span{background:#04BE02;color:#fff}.picker-calendar-day span{display:inline-block;border-radius:100%;width:30px;height:30px;line-height:30px}.picker-calendar-month-picker,.picker-calendar-year-picker{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:50%;max-width:200px;-webkit-flex-shrink:10;-ms-flex-negative:10;flex-shrink:10}.picker-calendar-month-picker span,.picker-calendar-year-picker span{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;position:relative;overflow:hidden;text-overflow:ellipsis}.picker-calendar.picker-modal-inline .picker-calendar-week-days,.popover .picker-calendar .picker-calendar-week-days{background:0 0}.swiper-button-next,.swiper-button-prev,i.icon{background-position:center;background-repeat:no-repeat}.picker-calendar.picker-modal-inline .picker-calendar-week-days:after,.picker-calendar.picker-modal-inline .picker-calendar-week-days:before,.picker-calendar.picker-modal-inline .toolbar:after,.picker-calendar.picker-modal-inline .toolbar:before,.popover .picker-calendar .picker-calendar-week-days:after,.popover .picker-calendar .picker-calendar-week-days:before,.popover .picker-calendar .toolbar:after,.popover .picker-calendar .toolbar:before{display:none}.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{content:'';position:absolute;left:0;top:0;bottom:auto;right:auto;height:1px;width:100%;background-color:#c4c4c4;display:block;z-index:15;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.picker-calendar-month-picker,.picker-calendar-year-picker{display:block;line-height:2.2rem;-webkit-box-flex:1;-ms-flex:1;flex:1}.picker-calendar-month-picker a.icon-only,.picker-calendar-year-picker a.icon-only{min-width:36px;float:left;width:25%;height:2.2rem;line-height:2rem}.picker-calendar-month-picker .current-month-value,.picker-calendar-month-picker .current-year-value,.picker-calendar-year-picker .current-month-value,.picker-calendar-year-picker .current-year-value{float:left;width:50%;height:2.2rem}i.icon{display:inline-block;vertical-align:middle;background-size:100% auto;font-style:normal;position:relative}i.icon.icon-next,i.icon.icon-prev{width:.75rem;height:.75rem}.swiper-slide,.swiper-wrapper{width:100%;height:100%;position:relative}i.icon.icon-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%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%2304BE02'%20d%3D'M1%2C1.6l11.8%2C5.8L1%2C13.4V1.6%20M0%2C0v15l15-7.6L0%2C0L0%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}i.icon.icon-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%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%2304BE02'%20d%3D'M14%2C1.6v11.8L2.2%2C7.6L14%2C1.6%20M15%2C0L0%2C7.6L15%2C15V0L15%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.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;-ms-flex-direction:column;flex-direction:column}.swiper-wrapper{z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-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;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{-webkit-flex-shrink:0;-ms-flex:0 0 auto;-ms-flex-negative:0;flex-shrink:0}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-webkit-transition-property:height,-webkit-transform;transition-property:height,-webkit-transform;transition-property:transform,height;transition-property:transform,height,-webkit-transform}.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;background-size:27px 44px}.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;transition:.3s;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.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;background:#04BE02}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.swiper-container-3d{-webkit-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;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: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: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: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:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-coverflow .swiper-wrapper,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.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,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-slide{visibility:hidden;-webkit-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-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-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-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none;-webkit-transition-property:opacity;transition-property:opacity}.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-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%;transform-origin:50%;-webkit-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%;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%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.weui-actionsheet{z-index:10000}.weui-popup__container,.weui-popup__overlay{position:fixed;bottom:0;left:0;right:0;width:100%;height:100%;z-index:10}.weui-popup__overlay{background-color:rgba(0,0,0,.6);opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-popup__container{display:none}.weui-popup__container.weui-popup__container--visible{display:block}.weui-popup__container .weui-cells{margin:0;text-align:left}.weui-popup__modal{width:100%;position:absolute;z-index:100;bottom:0;border-radius:0;opacity:.6;color:#3d4145;-webkit-transition-duration:.3s;transition-duration:.3s;height:100%;background:#EFEFF4;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;overflow-x:hidden;overflow-y:auto}.popup-bottom .weui-popup__modal{height:auto}.weui-popup__modal .toolbar{position:absolute;left:0;top:0;right:0;z-index:1}.weui-popup__modal .modal-content{height:100%;padding-top:2.2rem;overflow:auto;box-sizing:border-box}.weui-popup__container--visible .weui-popup__overlay{opacity:1}.weui-popup__container--visible .weui-popup__modal{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-notification{position:fixed;width:100%;min-height:3.4rem;top:-2rem;padding-top:2rem;left:0;right:0;z-index:9999;background-color:rgba(0,0,0,.85);color:#fff;font-size:.65rem;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);-webkit-transition:.4s;transition:.4s}.weui-notification.weui-notification--in{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-notification.weui-notification--touching{-webkit-transition-duration:0s;transition-duration:0s}.weui-notification .weui-notification__inner{padding:.4rem .6rem 1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.weui-notification .weui-notification__content{width:100%;margin:0 .4rem}.weui-notification .weui-notification__title{font-weight:700}.weui-notification .weui-notification__text{line-height:1}.weui-notification .weui-notification__media{height:1rem;width:1rem}.weui-notification .weui-notification__media img{width:100%}.weui-notification .weui-notification__handle-bar{position:absolute;bottom:.2rem;left:50%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);width:2rem;height:.3rem;border-radius:.15rem;background:#fff;opacity:.5}.weui-photo-browser-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:#000;display:none;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-photo-browser-modal.weui-photo-browser-modal-visible{opacity:1}.weui-photo-browser-modal .swiper-container{height:100%;-webkit-transform:scale(.2);transform:scale(.2);-webkit-transition:-webkit-transform .5s;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}.weui-photo-browser-modal .swiper-container .swiper-pagination-bullet{background:#fff;visibility:hidden}.weui-photo-browser-modal .swiper-container.swiper-container-visible{-webkit-transform:scale(1);transform:scale(1)}.weui-photo-browser-modal .swiper-container.swiper-container-visible .swiper-pagination-bullet{visibility:visible;-webkit-transition-property:visibility;transition-property:visibility;-webkit-transition-delay:.5s;transition-delay:.5s}.weui-photo-browser-modal .swiper-container .swiper-pagination{bottom:10px;left:0;width:100%}.weui-photo-browser-modal .photo-container{height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden}.weui-photo-browser-modal .photo-container img{max-width:100%;margin-top:-30px}.weui-photo-browser-modal .caption{position:absolute;bottom:40px;left:0;right:0;color:#fff;text-align:center;padding:0 12px;min-height:3rem;font-size:14px;z-index:10;-webkit-transition:opacity .3s;transition:opacity .3s;-webkit-transition-delay:.5s;transition-delay:.5s;opacity:0}.weui-photo-browser-modal .caption .caption-item{display:none;opacity:0;-webkit-transition:opacity .15s;transition:opacity .15s}.weui-photo-browser-modal .caption .caption-item.active{display:block;opacity:1}.weui-photo-browser-modal .swiper-container-visible .caption{opacity:1}.color-primary{color:#04BE02}.color-danger,.color-error{color:#f6383a}.color-warning{color:#f60}.color-success{color:#4cd964}.bg-danger,.bg-error,.bg-primary,.bg-success,.bg-warning{color:#fff}.bg-primary{background-color:#04BE02}.bg-danger,.bg-error{background-color:#f6383a}.bg-warning{background-color:#f60}.bg-success{background-color:#4cd964}.weui-toptips{z-index:100;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-toptips.weui-toptips_visible{opacity:1}.weui-icon_toast{font-size:55px;color:#fff;margin-bottom:6px}.weui-toast--forbidden .weui-icon_toast{color:#f6383a}.weui-toast--text{min-height:initial;font-size:18px;padding:8px 16px;width:auto;top:40%}.weui-toast--text .weui-icon_toast{display:none}.weui-count{display:inline-block;height:25px;line-height:25px}.weui-count .weui-count__btn{height:21px;width:21px;line-height:21px;display:inline-block;position:relative;border:1px solid #04BE02;border-radius:50%;vertical-align:-6px}.weui-count .weui-count__btn:after,.weui-count .weui-count__btn:before{content:" ";position:absolute;height:1px;width:11px;background-color:#04BE02;left:50%;top:50%;margin-left:-5.5px}.weui-count .weui-count__btn:after{height:11px;width:1px;margin-top:-5.5px;margin-left:-1px}.weui-count .weui-count__decrease:after{display:none}.weui-count .weui-count__increase{background-color:#04BE02}.weui-count .weui-count__increase:after,.weui-count .weui-count__increase:before{background-color:#fff}.weui-count .weui-count__number{background-color:transparent;font-size:.8rem;border:0;width:1.3rem;text-align:center;color:#5f646e}.weui-panel .weui-media-box__title-after{color:#9b9b9b;font-size:.65rem;float:right}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/css/weui.min.css b/platforms/android/app/src/main/assets/www/css/weui.min.css
new file mode 100755
index 0000000..1371e18
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/css/weui.min.css
@@ -0,0 +1,5 @@
+/*!
+ * WeUI v1.1.3 (https://github.com/weui/weui)
+ * Copyright 2018 Tencent, Inc.
+ * Licensed under the MIT license
+ */html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{line-height:1.6;font-family:-apple-system-font,Helvetica Neue,sans-serif}*{margin:0;padding:0}a img{border:0}a{text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}@font-face{font-weight:400;font-style:normal;font-family:weui;src:url('data:application/octet-stream;base64,AAEAAAALAIAAAwAwR1NVQrD+s+0AAAE4AAAAQk9TLzJAKEx+AAABfAAAAFZjbWFw65cFHQAAAhwAAAJQZ2x5ZvCRR/EAAASUAAAKtGhlYWQMPROtAAAA4AAAADZoaGVhCCwD+gAAALwAAAAkaG10eEJo//8AAAHUAAAASGxvY2EYqhW4AAAEbAAAACZtYXhwASEAVQAAARgAAAAgbmFtZeNcHtgAAA9IAAAB5nBvc3T6bLhLAAARMAAAAOYAAQAAA+gAAABaA+j/////A+kAAQAAAAAAAAAAAAAAAAAAABIAAQAAAAEAACbZbxtfDzz1AAsD6AAAAADUm2dvAAAAANSbZ2///wAAA+kD6gAAAAgAAgAAAAAAAAABAAAAEgBJAAUAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKAB4ALAABREZMVAAIAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAAAAQOwAZAABQAIAnoCvAAAAIwCegK8AAAB4AAxAQIAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA6gHqEQPoAAAAWgPqAAAAAAABAAAAAAAAAAAAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+j//wPoAAAD6AAAAAAABQAAAAMAAAAsAAAABAAAAXQAAQAAAAAAbgADAAEAAAAsAAMACgAAAXQABABCAAAABAAEAAEAAOoR//8AAOoB//8AAAABAAQAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAAAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAANwAAAAAAAAAEQAA6gEAAOoBAAAAAQAA6gIAAOoCAAAAAgAA6gMAAOoDAAAAAwAA6gQAAOoEAAAABAAA6gUAAOoFAAAABQAA6gYAAOoGAAAABgAA6gcAAOoHAAAABwAA6ggAAOoIAAAACAAA6gkAAOoJAAAACQAA6goAAOoKAAAACgAA6gsAAOoLAAAACwAA6gwAAOoMAAAADAAA6g0AAOoNAAAADQAA6g4AAOoOAAAADgAA6g8AAOoPAAAADwAA6hAAAOoQAAAAEAAA6hEAAOoRAAAAEQAAAAAARgCMANIBJAF4AcQCMgJgAqgC/ANIA6YD/gROBKAE9AVaAAAAAgAAAAADrwOtABQAKQAAASIHBgcGFBcWFxYyNzY3NjQnJicmAyInJicmNDc2NzYyFxYXFhQHBgcGAfV4Z2Q7PDw7ZGfwZmQ7PDw7ZGZ4bl5bNjc3Nlte215bNjc3NlteA608O2Rn8GdjOzw8O2Nn8GdkOzz8rzc1W17bXlw1Nzc1XF7bXls1NwAAAAACAAAAAAOzA7MAFwAtAAABIgcGBwYVFBcWFxYzMjc2NzY1NCcmJyYTBwYiLwEmNjsBETQ2OwEyFhURMzIWAe52Z2Q7PT07ZGd2fGpmOz4+O2ZpIXYOKA52Dg0XXQsHJgcLXRcNA7M+O2ZqfHZnZDs9PTtkZ3Z9aWY7Pv3wmhISmhIaARcICwsI/ukaAAMAAAAAA+UD5QAXACMALAAAASIHBgcGFRQXFhcWMzI3Njc2NTQnJicmAxQrASI1AzQ7ATIHJyImNDYyFhQGAe6Ecm9BRERBb3KEiXZxQkREQnF1aQIxAwgCQgMBIxIZGSQZGQPkREJxdomEcm9BRERBb3KEinVxQkT9HQICAWICAjEZIxkZIxkAAAAAAgAAAAADsQPkABkALgAAAQYHBgc2BREUFxYXFhc2NzY3NjURJBcmJyYTAQYvASY/ATYyHwEWNjclNjIfARYB9VVVQk+v/tFHPmxebGxdbT1I/tGvT0JVo/7VBASKAwMSAQUBcQEFAgESAgUBEQQD4xMYEhk3YP6sjnVlSD8cHD9IZXWOAVRgNxkSGP62/tkDA48EBBkCAVYCAQHlAQIQBAAAAAADAAAAAAOxA+QAGwAqADMAAAEGBwYHBgcGNxEUFxYXFhc2NzY3NjURJBcmJyYHMzIWFQMUBisBIicDNDYTIiY0NjIWFAYB9UFBODssO38gRz5sXmxsXW09SP7YqFBBVW80BAYMAwImBQELBh4PFhYeFRUD5A8SDhIOEikK/q2PdWRJPh0dPklkdY8BU141GRIY/AYE/sYCAwUBOgQG/kAVHxUVHxUAAAACAAAAAAPkA+QAFwAtAAABIgcGBwYVFBcWFxYzMjc2NzY1NCcmJyYTAQYiLwEmPwE2Mh8BFjI3ATYyHwEWAe6Ecm9BQ0NCbnODiXVxQkREQnF1kf6gAQUBowMDFgEFAYUCBQEBQwIFARUEA+NEQnF1iYNzbkJDQ0FvcoSJdXFCRP6j/qUBAagEBR4CAWYBAQENAgIVBAAAAAQAAAAAA68DrQAUACkAPwBDAAABIgcGBwYUFxYXFjI3Njc2NCcmJyYDIicmJyY0NzY3NjIXFhcWFAcGBwYTBQ4BLwEmBg8BBhYfARYyNwE+ASYiFzAfAQH1eGdkOzw8O2Rn8GZkOzw8O2RmeG5eWzY3NzZbXtteWzY3NzZbXmn+9gYSBmAGDwUDBQEGfQUQBgElBQELEBUBAQOtPDtkZ/BnYzs8PDtjZ/BnZDs8/K83NVte215cNTc3NVxe215bNTcCJt0FAQVJBQIGBAcRBoAGBQEhBQ8LBAEBAAABAAAAAAO7AzoAFwAAEy4BPwE+AR8BFjY3ATYWFycWFAcBBiInPQoGBwUHGgzLDCELAh0LHwsNCgr9uQoeCgGzCyEOCw0HCZMJAQoBvgkCCg0LHQv9sQsKAAAAAAIAAAAAA+UD5gAXACwAAAEiBwYHBhUUFxYXFjMyNzY3NjU0JyYnJhMHBi8BJicmNRM0NjsBMhYVExceAQHvhHJvQUNDQm5zg4l1cUJEREJxdVcQAwT6AwIEEAMCKwIDDsUCAQPlREJxdYmDc25CQ0NBb3KEiXVxQkT9VhwEAncCAgMGAXoCAwMC/q2FAgQAAAQAAAAAA68DrQADABgALQAzAAABMB8BAyIHBgcGFBcWFxYyNzY3NjQnJicmAyInJicmNDc2NzYyFxYXFhQHBgcGAyMVMzUjAuUBAfJ4Z2Q7PDw7ZGfwZmQ7PDw7ZGZ4bl5bNjc3Nlte215bNjc3NltemyT92QKDAQEBLDw7ZGfwZ2M7PDw7Y2fwZ2Q7PPyvNzVbXtteXDU3NzVcXtteWzU3AjH9JAAAAAMAAAAAA+QD5AAXACcAMAAAASIHBgcGFRQXFhcWMzI3Njc2NTQnJicmAzMyFhUDFAYrASImNQM0NhMiJjQ2MhYUBgHuhHJvQUNDQm5zg4l1cUJEREJxdZ42BAYMAwInAwMMBh8PFhYeFhYD40RCcXWJg3NuQkNDQW9yhIl1cUJE/vYGBf7AAgMDAgFABQb+NhYfFhYfFgAABAAAAAADwAPAAAgAEgAoAD0AAAEyNjQmIgYUFhcjFTMRIxUzNSMDIgcGBwYVFBYXFjMyNzY3NjU0Jy4BAyInJicmNDc2NzYyFxYXFhQHBgcGAfQYISEwISFRjzk5yTorhG5rPT99am+DdmhlPD4+PMyFbV5bNTc3NVte2l5bNTc3NVteAqAiLyIiLyI5Hf7EHBwCsT89a26Ed8w8Pj48ZWh2g29qffyjNzVbXtpeWzU3NzVbXtpeWzU3AAADAAAAAAOoA6gACwAgADUAAAEHJwcXBxc3FzcnNwMiBwYHBhQXFhcWMjc2NzY0JyYnJgMiJyYnJjQ3Njc2MhcWFxYUBwYHBgKOmpocmpocmpocmpq2dmZiOjs7OmJm7GZiOjs7OmJmdmtdWTQ2NjRZXdZdWTQ2NjRZXQKqmpocmpocmpocmpoBGTs6YmbsZmI6Ozs6YmbsZmI6O/zCNjRZXdZdWTQ2NjRZXdZdWTQ2AAMAAAAAA+kD6gAaAC8AMAAAAQYHBiMiJyYnJjQ3Njc2MhcWFxYVFAcGBwEHATI3Njc2NCcmJyYiBwYHBhQXFhcWMwKONUBCR21dWjU3NzVaXdpdWzU2GBcrASM5/eBXS0grKysrSEuuSkkqLCwqSUpXASMrFxg2NVtd2l1aNTc3NVpdbUdCQDX+3jkBGSsrSEuuSkkqLCwqSUquS0grKwAC//8AAAPoA+gAFAAwAAABIgcGBwYQFxYXFiA3Njc2ECcmJyYTFg4BIi8BBwYuATQ/AScmPgEWHwE3Nh4BBg8BAfSIdHFDRERDcXQBEHRxQ0REQ3F0SQoBFBsKoqgKGxMKqKIKARQbCqKoChsUAQqoA+hEQ3F0/vB0cUNERENxdAEQdHFDRP1jChsTCqiiCgEUGwqiqAobFAEKqKIKARQbCqIAAAIAAAAAA+QD5AAXADQAAAEiBwYHBhUUFxYXFjMyNzY3NjU0JyYnJhMUBiMFFxYUDwEGLwEuAT8BNh8BFhQPAQUyFh0BAe6Ecm9BQ0NCbnODiXVxQkREQnF1fwQC/pGDAQEVAwTsAgEC7AQEFAIBhAFwAgMD40RCcXWJg3NuQkNDQW9yhIl1cUJE/fYCAwuVAgQCFAQE0AIFAtEEBBQCBQGVCwMDJwAAAAUAAAAAA9QD0wAjACcANwBHAEgAAAERFAYjISImNREjIiY9ATQ2MyE1NDYzITIWHQEhMhYdARQGIyERIREHIgYVERQWOwEyNjURNCYjISIGFREUFjsBMjY1ETQmKwEDeyYb/XYbJkMJDQ0JAQYZEgEvExkBBgkNDQn9CQJc0QkNDQktCQ0NCf7sCQ0NCS0JDQ0JLQMi/TQbJiYbAswMCiwJDS4SGRkSLg0JLAoM/UwCtGsNCf5NCQ0NCQGzCQ0NCf5NCQ0NCQGzCQ0AAAAAEADGAAEAAAAAAAEABAAAAAEAAAAAAAIABwAEAAEAAAAAAAMABAALAAEAAAAAAAQABAAPAAEAAAAAAAUACwATAAEAAAAAAAYABAAeAAEAAAAAAAoAKwAiAAEAAAAAAAsAEwBNAAMAAQQJAAEACABgAAMAAQQJAAIADgBoAAMAAQQJAAMACAB2AAMAAQQJAAQACAB+AAMAAQQJAAUAFgCGAAMAAQQJAAYACACcAAMAAQQJAAoAVgCkAAMAAQQJAAsAJgD6d2V1aVJlZ3VsYXJ3ZXVpd2V1aVZlcnNpb24gMS4wd2V1aUdlbmVyYXRlZCBieSBzdmcydHRmIGZyb20gRm9udGVsbG8gcHJvamVjdC5odHRwOi8vZm9udGVsbG8uY29tAHcAZQB1AGkAUgBlAGcAdQBsAGEAcgB3AGUAdQBpAHcAZQB1AGkAVgBlAHIAcwBpAG8AbgAgADEALgAwAHcAZQB1AGkARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAgAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAQIBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETAAZjaXJjbGUIZG93bmxvYWQEaW5mbwxzYWZlX3N1Y2Nlc3MJc2FmZV93YXJuB3N1Y2Nlc3MOc3VjY2Vzcy1jaXJjbGURc3VjY2Vzcy1uby1jaXJjbGUHd2FpdGluZw53YWl0aW5nLWNpcmNsZQR3YXJuC2luZm8tY2lyY2xlBmNhbmNlbAZzZWFyY2gFY2xlYXIEYmFjawZkZWxldGUAAAAA') format('truetype')}[class*=" weui-icon-"],[class^=weui-icon-]{display:inline-block;vertical-align:middle;font:normal normal normal 14px/1 weui;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}[class*=" weui-icon-"]:before,[class^=weui-icon-]:before{display:inline-block;margin-left:.2em;margin-right:.2em}.weui-icon-circle:before{content:"\EA01"}.weui-icon-download:before{content:"\EA02"}.weui-icon-info:before{content:"\EA03"}.weui-icon-safe-success:before{content:"\EA04"}.weui-icon-safe-warn:before{content:"\EA05"}.weui-icon-success:before{content:"\EA06"}.weui-icon-success-circle:before{content:"\EA07"}.weui-icon-success-no-circle:before{content:"\EA08"}.weui-icon-waiting:before{content:"\EA09"}.weui-icon-waiting-circle:before{content:"\EA0A"}.weui-icon-warn:before{content:"\EA0B"}.weui-icon-info-circle:before{content:"\EA0C"}.weui-icon-cancel:before{content:"\EA0D"}.weui-icon-search:before{content:"\EA0E"}.weui-icon-clear:before{content:"\EA0F"}.weui-icon-back:before{content:"\EA10"}.weui-icon-delete:before{content:"\EA11"}[class*=" weui-icon_"]:before,[class^=weui-icon_]:before{margin:0}.weui-icon-success{font-size:23px;color:#09bb07}.weui-icon-waiting{font-size:23px;color:#10aeff}.weui-icon-warn{font-size:23px;color:#f43530}.weui-icon-info{font-size:23px;color:#10aeff}.weui-icon-success-circle,.weui-icon-success-no-circle{font-size:23px;color:#09bb07}.weui-icon-waiting-circle{font-size:23px;color:#10aeff}.weui-icon-circle{font-size:23px;color:#c9c9c9}.weui-icon-download,.weui-icon-info-circle{font-size:23px;color:#09bb07}.weui-icon-safe-success{color:#09bb07}.weui-icon-safe-warn{color:#ffbe00}.weui-icon-cancel{color:#f43530;font-size:22px}.weui-icon-clear,.weui-icon-search{color:#b2b2b2;font-size:14px}.weui-icon-delete.weui-icon_gallery-delete{color:#fff;font-size:22px}.weui-icon_msg{font-size:93px}.weui-icon_msg.weui-icon-warn{color:#f76260}.weui-icon_msg-primary{font-size:93px}.weui-icon_msg-primary.weui-icon-warn{color:#ffbe00}.weui-btn{position:relative;display:block;margin-left:auto;margin-right:auto;padding-left:14px;padding-right:14px;box-sizing:border-box;font-size:18px;text-align:center;text-decoration:none;color:#fff;line-height:2.55555556;border-radius:5px;-webkit-tap-highlight-color:rgba(0,0,0,0);overflow:hidden}.weui-btn:after{content:" ";width:200%;height:200%;position:absolute;top:0;left:0;border:1px solid rgba(0,0,0,.2);-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;box-sizing:border-box;border-radius:10px}.weui-btn_inline{display:inline-block}.weui-btn_default{color:#000;background-color:#f8f8f8}.weui-btn_default:not(.weui-btn_disabled):visited{color:#000}.weui-btn_default:not(.weui-btn_disabled):active{color:rgba(0,0,0,.6);background-color:#dedede}.weui-btn_primary{background-color:#1aad19}.weui-btn_primary:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_primary:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#179b16}.weui-btn_warn{background-color:#e64340}.weui-btn_warn:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_warn:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#ce3c39}.weui-btn_disabled{color:hsla(0,0%,100%,.6)}.weui-btn_disabled.weui-btn_default{color:rgba(0,0,0,.3);background-color:#f7f7f7}.weui-btn_disabled.weui-btn_primary{background-color:#9ed99d}.weui-btn_disabled.weui-btn_warn{background-color:#ec8b89}.weui-btn_loading .weui-loading{margin:-.2em .34em 0 0}.weui-btn_loading.weui-btn_primary,.weui-btn_loading.weui-btn_warn{color:hsla(0,0%,100%,.6)}.weui-btn_loading.weui-btn_primary{background-color:#179b16}.weui-btn_loading.weui-btn_warn{background-color:#ce3c39}.weui-btn_plain-primary{color:#1aad19;border:1px solid #1aad19}.weui-btn_plain-primary:not(.weui-btn_plain-disabled):active{color:rgba(26,173,25,.6);border-color:rgba(26,173,25,.6)}.weui-btn_plain-primary:after{border-width:0}.weui-btn_plain-default{color:#353535;border:1px solid #353535}.weui-btn_plain-default:not(.weui-btn_plain-disabled):active{color:rgba(53,53,53,.6);border-color:rgba(53,53,53,.6)}.weui-btn_plain-default:after{border-width:0}.weui-btn_plain-disabled{color:rgba(0,0,0,.2);border-color:rgba(0,0,0,.2)}button.weui-btn,input.weui-btn{width:100%;border-width:0;outline:0;-webkit-appearance:none}button.weui-btn:focus,input.weui-btn:focus{outline:0}button.weui-btn_inline,button.weui-btn_mini,input.weui-btn_inline,input.weui-btn_mini{width:auto}button.weui-btn_plain-default,button.weui-btn_plain-primary,input.weui-btn_plain-default,input.weui-btn_plain-primary{border-width:1px;background-color:transparent}.weui-btn_mini{display:inline-block;padding:0 1.32em;line-height:2.3;font-size:13px}.weui-btn+.weui-btn{margin-top:15px}.weui-btn.weui-btn_inline+.weui-btn.weui-btn_inline{margin-top:auto;margin-left:15px}.weui-btn-area{margin:1.17647059em 15px .3em}.weui-btn-area_inline{display:-webkit-box;display:-webkit-flex;display:flex}.weui-btn-area_inline .weui-btn{margin-top:auto;margin-right:15px;width:100%;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-btn-area_inline .weui-btn:last-child{margin-right:0}.weui-cells{margin-top:1.17647059em;background-color:#fff;line-height:1.47058824;font-size:17px;overflow:hidden;position:relative}.weui-cells:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells:after,.weui-cells:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5;z-index:2}.weui-cells:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells__title{margin-top:.77em;margin-bottom:.3em;padding-left:15px;padding-right:15px;color:#999;font-size:14px}.weui-cells__title+.weui-cells{margin-top:0}.weui-cells__tips{margin-top:.3em;color:#999;padding-left:15px;padding-right:15px;font-size:14px}.weui-cell{padding:10px 15px;position:relative;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px;z-index:2}.weui-cell:first-child:before{display:none}.weui-cell_primary{-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start}.weui-cell__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-cell__ft{text-align:right;color:#999}.weui-cell_swiped{display:block;padding:0}.weui-cell_swiped>.weui-cell__bd{position:relative;z-index:1;background-color:#fff}.weui-cell_swiped>.weui-cell__ft{position:absolute;right:0;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:flex;color:#fff}.weui-swiped-btn{display:block;padding:10px 1em;line-height:1.47058824;color:inherit}.weui-swiped-btn_default{background-color:#c7c7cc}.weui-swiped-btn_warn{background-color:#ff3b30}.weui-cell_access{-webkit-tap-highlight-color:rgba(0,0,0,0);color:inherit}.weui-cell_access:active{background-color:#ececec}.weui-cell_access .weui-cell__ft{padding-right:13px;position:relative}.weui-cell_access .weui-cell__ft:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;margin-top:-4px;right:2px}.weui-cell_link{color:#586c94;font-size:14px}.weui-cell_link:first-child:before{display:block}.weui-check__label{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-check__label:active{background-color:#ececec}.weui-check{position:absolute;left:-9999em}.weui-cells_radio .weui-cell__ft{padding-left:.35em}.weui-cells_radio .weui-check+.weui-icon-checked{min-width:16px}.weui-cells_radio .weui-check:checked+.weui-icon-checked:before{display:block;content:'\EA08';color:#09bb07;font-size:16px}.weui-cells_checkbox .weui-cell__hd{padding-right:.35em}.weui-cells_checkbox .weui-icon-checked:before{content:'\EA01';color:#c9c9c9;font-size:23px;display:block}.weui-cells_checkbox .weui-check:checked+.weui-icon-checked:before{content:'\EA06';color:#09bb07}.weui-label{display:block;width:105px;word-wrap:break-word;word-break:break-all}.weui-input{width:100%;border:0;outline:0;-webkit-appearance:none;background-color:transparent;font-size:inherit;color:inherit;height:1.47058824em;line-height:1.47058824}.weui-input::-webkit-inner-spin-button,.weui-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.weui-textarea{display:block;border:0;resize:none;width:100%;color:inherit;font-size:1em;line-height:inherit;outline:0}.weui-textarea-counter{color:#b2b2b2;text-align:right}.weui-cell_warn .weui-textarea-counter{color:#e64340}.weui-toptips{display:none;position:fixed;-webkit-transform:translateZ(0);transform:translateZ(0);top:0;left:0;right:0;padding:5px;font-size:14px;text-align:center;color:#fff;z-index:5000;word-wrap:break-word;word-break:break-all}.weui-toptips_warn{background-color:#e64340}.weui-cells_form .weui-cell__ft{font-size:0}.weui-cells_form .weui-icon-warn{display:none}.weui-cells_form input,.weui-cells_form label[for],.weui-cells_form textarea{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-cell_warn{color:#e64340}.weui-cell_warn .weui-icon-warn{display:inline-block}.weui-form-preview{position:relative;background-color:#fff}.weui-form-preview:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview:after,.weui-form-preview:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-form-preview:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__hd{position:relative;padding:10px 15px;text-align:right;line-height:2.5em}.weui-form-preview__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-form-preview__hd .weui-form-preview__value{font-style:normal;font-size:1.6em}.weui-form-preview__bd{padding:10px 15px;font-size:.9em;text-align:right;color:#999;line-height:2}.weui-form-preview__ft{position:relative;line-height:50px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-form-preview__ft:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__item{overflow:hidden}.weui-form-preview__label{float:left;margin-right:1em;min-width:4em;color:#999;text-align:justify;text-align-last:justify}.weui-form-preview__value{display:block;overflow:hidden;word-break:normal;word-wrap:break-word}.weui-form-preview__btn{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}button.weui-form-preview__btn{background-color:transparent;border:0;outline:0;line-height:inherit;font-size:inherit}.weui-form-preview__btn:active{background-color:#eee}.weui-form-preview__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-form-preview__btn:first-child:after{display:none}.weui-form-preview__btn_default{color:#999}.weui-form-preview__btn_primary{color:#0bb20c}.weui-cell_select{padding:0}.weui-cell_select .weui-select{padding-right:30px}.weui-cell_select .weui-cell__bd:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-select{-webkit-appearance:none;border:0;outline:0;background-color:transparent;width:100%;font-size:inherit;height:45px;line-height:45px;position:relative;z-index:1;padding-left:15px}.weui-cell_select-before{padding-right:15px}.weui-cell_select-before .weui-select{width:105px;box-sizing:border-box}.weui-cell_select-before .weui-cell__hd{position:relative}.weui-cell_select-before .weui-cell__hd:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-cell_select-before .weui-cell__hd:before{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-cell_select-before .weui-cell__bd{padding-left:15px}.weui-cell_select-before .weui-cell__bd:after{display:none}.weui-cell_select-after{padding-left:15px}.weui-cell_select-after .weui-select{padding-left:0}.weui-cell_vcode{padding-top:0;padding-right:0;padding-bottom:0}.weui-vcode-btn,.weui-vcode-img{margin-left:5px;height:45px;vertical-align:middle}.weui-vcode-btn{display:inline-block;padding:0 .6em 0 .7em;border-left:1px solid #e5e5e5;line-height:45px;font-size:17px;color:#3cc51f}button.weui-vcode-btn{background-color:transparent;border-top:0;border-right:0;border-bottom:0;outline:0}.weui-vcode-btn:active{color:#52a341}.weui-gallery{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000;z-index:1000}.weui-gallery__img{position:absolute;top:0;right:0;bottom:60px;left:0;background:50% no-repeat;background-size:contain}.weui-gallery__opr{position:absolute;right:0;bottom:0;left:0;background-color:#0d0d0d;color:#fff;line-height:60px;text-align:center}.weui-gallery__del{display:block}.weui-cell_switch{padding-top:6.5px;padding-bottom:6.5px}.weui-switch{-webkit-appearance:none;appearance:none}.weui-switch,.weui-switch-cp__box{position:relative;width:52px;height:32px;border:1px solid #dfdfdf;outline:0;border-radius:16px;box-sizing:border-box;background-color:#dfdfdf;-webkit-transition:background-color .1s,border .1s;transition:background-color .1s,border .1s}.weui-switch-cp__box:before,.weui-switch:before{content:" ";position:absolute;top:0;left:0;width:50px;height:30px;border-radius:15px;background-color:#fdfdfd;-webkit-transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1),-webkit-transform .35s cubic-bezier(.45,1,.4,1)}.weui-switch-cp__box:after,.weui-switch:after{content:" ";position:absolute;top:0;left:0;width:30px;height:30px;border-radius:15px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);-webkit-transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35),-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35)}.weui-switch-cp__input:checked~.weui-switch-cp__box,.weui-switch:checked{border-color:#04be02;background-color:#04be02}.weui-switch-cp__input:checked~.weui-switch-cp__box:before,.weui-switch:checked:before{-webkit-transform:scale(0);transform:scale(0)}.weui-switch-cp__input:checked~.weui-switch-cp__box:after,.weui-switch:checked:after{-webkit-transform:translateX(20px);transform:translateX(20px)}.weui-switch-cp__input{position:absolute;left:-9999px}.weui-switch-cp__box{display:block}.weui-uploader__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding-bottom:10px;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-uploader__title{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-uploader__info{color:#b2b2b2}.weui-uploader__bd{margin-bottom:-4px;margin-right:-9px;overflow:hidden}.weui-uploader__files{list-style:none}.weui-uploader__file{float:left;margin-right:9px;margin-bottom:9px;width:79px;height:79px;background:no-repeat 50%;background-size:cover}.weui-uploader__file_status{position:relative}.weui-uploader__file_status:before{content:" ";position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.5)}.weui-uploader__file_status .weui-uploader__file-content{display:block}.weui-uploader__file-content{display:none;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff}.weui-uploader__file-content .weui-icon-warn{display:inline-block}.weui-uploader__input-box{float:left;position:relative;margin-right:9px;margin-bottom:9px;width:77px;height:77px;border:1px solid #d9d9d9}.weui-uploader__input-box:after,.weui-uploader__input-box:before{content:" ";position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#d9d9d9}.weui-uploader__input-box:before{width:2px;height:39.5px}.weui-uploader__input-box:after{width:39.5px;height:2px}.weui-uploader__input-box:active{border-color:#999}.weui-uploader__input-box:active:after,.weui-uploader__input-box:active:before{background-color:#999}.weui-uploader__input{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;opacity:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-msg{padding-top:36px;text-align:center}.weui-msg__icon-area{margin-bottom:30px}.weui-msg__text-area{margin-bottom:25px;padding:0 20px}.weui-msg__text-area a{color:#586c94}.weui-msg__title{margin-bottom:5px;font-weight:400;font-size:20px}.weui-msg__desc,.weui-msg__title{word-wrap:break-word;word-break:break-all}.weui-msg__desc{font-size:14px;color:#999}.weui-msg__opr-area{margin-bottom:25px}.weui-msg__extra-area{margin-bottom:15px;font-size:14px;color:#999}.weui-msg__extra-area a{color:#586c94}@media screen and (min-height:438px){.weui-msg__extra-area{position:fixed;left:0;bottom:0;width:100%;text-align:center}}@media only screen and (device-width:375px) and (device-height:812px) and (-webkit-device-pixel-ratio:3){.weui-msg__extra-area{margin-bottom:49px}}.weui-article{padding:20px 15px;font-size:15px}.weui-article section{margin-bottom:1.5em}.weui-article h1{font-size:18px;font-weight:400;margin-bottom:.9em}.weui-article h2{font-size:16px}.weui-article h2,.weui-article h3{font-weight:400;margin-bottom:.34em}.weui-article h3{font-size:15px}.weui-article *{max-width:100%;box-sizing:border-box;word-wrap:break-word}.weui-article p{margin:0 0 .8em}.weui-tabbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;bottom:0;width:100%;background-color:#f7f7fa}.weui-tabbar:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #c0bfc4;color:#c0bfc4;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-tabbar__item{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:5px 0 0;font-size:0;color:#999;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon>i,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__label{color:#09bb07}.weui-tabbar__icon{display:inline-block;width:27px;height:27px}.weui-tabbar__icon>i,i.weui-tabbar__icon{font-size:24px;color:#999}.weui-tabbar__icon img{width:100%;height:100%}.weui-tabbar__label{text-align:center;color:#999;font-size:10px;line-height:1.8}.weui-navbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;top:0;width:100%;background-color:#fafafa}.weui-navbar:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #ccc;color:#ccc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-navbar+.weui-tab__panel{padding-top:50px;padding-bottom:0}.weui-navbar__item{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:13px 0;text-align:center;font-size:15px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-navbar__item:active{background-color:#ededed}.weui-navbar__item.weui-bar__item_on{background-color:#eaeaea}.weui-navbar__item:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #ccc;color:#ccc;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-navbar__item:last-child:after{display:none}.weui-tab{position:relative;height:100%}.weui-tab__panel{box-sizing:border-box;height:100%;padding-bottom:50px;overflow:auto;-webkit-overflow-scrolling:touch}.weui-tab__content{display:none}.weui-progress{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-progress__bar{background-color:#ebebeb;height:3px;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-progress__inner-bar{width:0;height:100%;background-color:#09bb07}.weui-progress__opr{display:block;margin-left:15px;font-size:0}.weui-panel{background-color:#fff;margin-top:10px;position:relative;overflow:hidden}.weui-panel:first-child{margin-top:0}.weui-panel:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel:after,.weui-panel:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-panel:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel__hd{padding:14px 15px 10px;color:#999;font-size:13px;position:relative}.weui-panel__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box{padding:15px;position:relative}.weui-media-box:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box:first-child:before{display:none}a.weui-media-box{color:#000;-webkit-tap-highlight-color:rgba(0,0,0,0)}a.weui-media-box:active{background-color:#ececec}.weui-media-box__title{font-weight:400;font-size:17px;width:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;word-wrap:break-word;word-break:break-all}.weui-media-box__desc{color:#999;font-size:13px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-media-box__info{margin-top:15px;padding-bottom:5px;font-size:13px;color:#cecece;line-height:1em;list-style:none;overflow:hidden}.weui-media-box__info__meta{float:left;padding-right:1em}.weui-media-box__info__meta_extra{padding-left:1em;border-left:1px solid #cecece}.weui-media-box_text .weui-media-box__title{margin-bottom:8px}.weui-media-box_appmsg{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-media-box_appmsg .weui-media-box__hd{margin-right:.8em;width:60px;height:60px;line-height:60px;text-align:center}.weui-media-box_appmsg .weui-media-box__thumb{width:100%;max-height:100%;vertical-align:top}.weui-media-box_appmsg .weui-media-box__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1;min-width:0}.weui-media-box_small-appmsg{padding:0}.weui-media-box_small-appmsg .weui-cells{margin-top:0}.weui-media-box_small-appmsg .weui-cells:before{display:none}.weui-grids{position:relative;overflow:hidden}.weui-grids:before{right:0;height:1px;border-top:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grids:after,.weui-grids:before{content:" ";position:absolute;left:0;top:0;color:#d9d9d9}.weui-grids:after{width:1px;bottom:0;border-left:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid{position:relative;float:left;padding:20px 10px;width:33.33333333%;box-sizing:border-box}.weui-grid:before{top:0;width:1px;border-right:1px solid #d9d9d9;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid:after,.weui-grid:before{content:" ";position:absolute;right:0;bottom:0;color:#d9d9d9}.weui-grid:after{left:0;height:1px;border-bottom:1px solid #d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grid:active{background-color:#ececec}.weui-grid__icon{width:28px;height:28px;margin:0 auto}.weui-grid__icon img{display:block;width:100%;height:100%}.weui-grid__icon+.weui-grid__label{margin-top:5px}.weui-grid__label{display:block;color:#000;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.weui-footer,.weui-grid__label{text-align:center;font-size:14px}.weui-footer{color:#999}.weui-footer a{color:#586c94}.weui-footer_fixed-bottom{position:fixed;bottom:.52em;left:0;right:0}.weui-footer__links{font-size:0}.weui-footer__link{display:inline-block;vertical-align:top;margin:0 .62em;position:relative;font-size:14px}.weui-footer__link:before{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #c7c7c7;color:#c7c7c7;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5);left:-.65em;top:.36em;bottom:.36em}.weui-footer__link:first-child:before{display:none}.weui-footer__text{padding:0 .34em;font-size:12px}.weui-flex{display:-webkit-box;display:-webkit-flex;display:flex}.weui-flex__item{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-dialog{position:fixed;z-index:5000;width:80%;max-width:300px;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#fff;text-align:center;border-radius:3px;overflow:hidden}.weui-dialog__hd{padding:1.3em 1.6em .5em}.weui-dialog__title{font-weight:400;font-size:18px}.weui-dialog__bd{padding:0 1.6em .8em;min-height:40px;font-size:15px;line-height:1.3;word-wrap:break-word;word-break:break-all;color:#999}.weui-dialog__bd:first-child{padding:2.7em 20px 1.7em;color:#353535}.weui-dialog__ft{position:relative;line-height:48px;font-size:18px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-dialog__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-dialog__btn{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0);position:relative}.weui-dialog__btn:active{background-color:#eee}.weui-dialog__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-dialog__btn:first-child:after{display:none}.weui-dialog__btn_default{color:#353535}.weui-dialog__btn_primary{color:#0bb20c}.weui-skin_android .weui-dialog{text-align:left;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-dialog__title{font-size:21px}.weui-skin_android .weui-dialog__hd{text-align:left}.weui-skin_android .weui-dialog__bd{color:#999;padding:.25em 1.6em 2em;font-size:17px;text-align:left}.weui-skin_android .weui-dialog__bd:first-child{padding:1.6em 1.6em 2em;color:#353535}.weui-skin_android .weui-dialog__ft{display:block;text-align:right;line-height:42px;font-size:16px;padding:0 1.6em .7em}.weui-skin_android .weui-dialog__ft:after{display:none}.weui-skin_android .weui-dialog__btn{display:inline-block;vertical-align:top;padding:0 .8em}.weui-skin_android .weui-dialog__btn:after{display:none}.weui-skin_android .weui-dialog__btn:active,.weui-skin_android .weui-dialog__btn:visited{background-color:rgba(0,0,0,.06)}.weui-skin_android .weui-dialog__btn:last-child{margin-right:-.8em}.weui-skin_android .weui-dialog__btn_default{color:gray}@media screen and (min-width:1024px){.weui-dialog{width:35%}}.weui-toast{position:fixed;z-index:5000;width:7.6em;min-height:7.6em;top:180px;left:50%;margin-left:-3.8em;background:hsla(0,0%,7%,.7);text-align:center;border-radius:5px;color:#fff}.weui-icon_toast{margin:22px 0 0;display:block}.weui-icon_toast.weui-icon-success-no-circle:before{color:#fff;font-size:55px}.weui-icon_toast.weui-loading{margin:30px 0 0;width:38px;height:38px;vertical-align:baseline}.weui-toast__content{margin:0 0 15px}.weui-mask{background:rgba(0,0,0,.6)}.weui-mask,.weui-mask_transparent{position:fixed;z-index:1000;top:0;right:0;left:0;bottom:0}.weui-actionsheet{position:fixed;left:0;bottom:0;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:5000;width:100%;background-color:#efeff4;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-actionsheet__title{position:relative;height:65px;padding:0 20px;line-height:1.4;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column;text-align:center;font-size:14px;color:#888;background:#fcfcfd}.weui-actionsheet__title:before{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-actionsheet__title .weui-actionsheet__title-text{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-actionsheet__menu{background-color:#fcfcfd}.weui-actionsheet__action{margin-top:6px;background-color:#fcfcfd}.weui-actionsheet__cell{position:relative;padding:10px 0;text-align:center;font-size:18px}.weui-actionsheet__cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-actionsheet__cell:active{background-color:#ececec}.weui-actionsheet__cell:first-child:before{display:none}.weui-skin_android .weui-actionsheet{position:fixed;left:50%;top:50%;bottom:auto;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:274px;box-sizing:border-box;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:transparent;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-skin_android .weui-actionsheet__action{display:none}.weui-skin_android .weui-actionsheet__menu{border-radius:2px;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-actionsheet__cell{padding:13px 24px;font-size:16px;line-height:1.4;text-align:left}.weui-skin_android .weui-actionsheet__cell:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.weui-skin_android .weui-actionsheet__cell:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.weui-actionsheet_toggle{-webkit-transform:translate(0);transform:translate(0)}.weui-loadmore{width:65%;margin:1.5em auto;line-height:1.6em;font-size:14px;text-align:center}.weui-loadmore__tips{display:inline-block;vertical-align:middle}.weui-loadmore_line{border-top:1px solid #e5e5e5;margin-top:2.4em}.weui-loadmore_line .weui-loadmore__tips{position:relative;top:-.9em;padding:0 .55em;background-color:#fff;color:#999}.weui-loadmore_dot .weui-loadmore__tips{padding:0 .16em}.weui-loadmore_dot .weui-loadmore__tips:before{content:" ";width:4px;height:4px;border-radius:50%;background-color:#e5e5e5;display:inline-block;position:relative;vertical-align:0;top:-.16em}.weui-badge{display:inline-block;padding:.15em .4em;min-width:8px;border-radius:18px;background-color:#f43530;color:#fff;line-height:1.2;text-align:center;font-size:12px;vertical-align:middle}.weui-badge_dot{padding:.4em;min-width:0}.weui-search-bar{position:relative;padding:8px 10px;display:-webkit-box;display:-webkit-flex;display:flex;box-sizing:border-box;background-color:#efeff4;-webkit-text-size-adjust:100%;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-search-bar:before{top:0;border-top:1px solid #d7d6dc;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar:after,.weui-search-bar:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d7d6dc}.weui-search-bar:after{bottom:0;border-bottom:1px solid #d7d6dc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__cancel-btn{display:block}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__label{display:none}.weui-search-bar__form{position:relative;-webkit-box-flex:1;-webkit-flex:auto;flex:auto;background-color:#efeff4}.weui-search-bar__form:after{content:'';position:absolute;left:0;top:0;width:200%;height:200%;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;border-radius:10px;border:1px solid #e6e6ea;box-sizing:border-box;background:#fff}.weui-search-bar__box{position:relative;padding-left:30px;padding-right:30px;height:100%;width:100%;box-sizing:border-box;z-index:1}.weui-search-bar__box .weui-search-bar__input{padding:4px 0;width:100%;height:1.42857143em;border:0;font-size:14px;line-height:1.42857143em;box-sizing:content-box;background:transparent}.weui-search-bar__box .weui-search-bar__input:focus{outline:none}.weui-search-bar__box .weui-icon-search{position:absolute;top:50%;left:10px;margin-top:-14px;line-height:28px}.weui-search-bar__box .weui-icon-clear{position:absolute;top:50%;right:0;margin-top:-14px;padding:0 10px;line-height:28px}.weui-search-bar__label{position:absolute;top:1px;right:1px;bottom:1px;left:1px;z-index:2;border-radius:3px;text-align:center;color:#9b9b9b;background:#fff}.weui-search-bar__label span{display:inline-block;font-size:14px;vertical-align:middle}.weui-search-bar__label .weui-icon-search{margin-right:5px}.weui-search-bar__cancel-btn{display:none;margin-left:10px;line-height:28px;color:#09bb07;white-space:nowrap}.weui-search-bar__input:not(:valid)~.weui-icon-clear{display:none}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none}.weui-picker{position:fixed;width:100%;left:0;bottom:0;z-index:5000;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-picker__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding:9px 15px;background-color:#fff;position:relative;text-align:center;font-size:17px}.weui-picker__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__action{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#1aad19}.weui-picker__action:first-child{text-align:left;color:#888}.weui-picker__action:last-child{text-align:right}.weui-picker__bd{display:-webkit-box;display:-webkit-flex;display:flex;position:relative;background-color:#fff;height:238px;overflow:hidden}.weui-picker__group{-webkit-box-flex:1;-webkit-flex:1;flex:1;position:relative;height:100%}.weui-picker__mask{top:0;height:100%;margin:0 auto;background:-webkit-linear-gradient(top,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),-webkit-linear-gradient(bottom,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background:linear-gradient(180deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),linear-gradient(0deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background-position:top,bottom;background-size:100% 102px;background-repeat:no-repeat;-webkit-transform:translateZ(0);transform:translateZ(0)}.weui-picker__indicator,.weui-picker__mask{position:absolute;left:0;width:100%;z-index:3}.weui-picker__indicator{height:34px;top:102px}.weui-picker__indicator:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__indicator:after,.weui-picker__indicator:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-picker__indicator:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__content{position:absolute;top:0;left:0;width:100%}.weui-picker__item{padding:0;height:34px;line-height:34px;text-align:center;color:#000;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.weui-picker__item_disabled{color:#999}@-webkit-keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.weui-animate-slide-up{-webkit-animation:a ease .3s forwards;animation:a ease .3s forwards}@-webkit-keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.weui-animate-slide-down{-webkit-animation:b ease .3s forwards;animation:b ease .3s forwards}@-webkit-keyframes c{0%{opacity:0}to{opacity:1}}@keyframes c{0%{opacity:0}to{opacity:1}}.weui-animate-fade-in{-webkit-animation:c ease .3s forwards;animation:c ease .3s forwards}@-webkit-keyframes d{0%{opacity:1}to{opacity:0}}@keyframes d{0%{opacity:1}to{opacity:0}}.weui-animate-fade-out{-webkit-animation:d ease .3s forwards;animation:d ease .3s forwards}.weui-agree{display:block;padding:.5em 15px;font-size:13px}.weui-agree a{color:#586c94}.weui-agree__text{color:#999}.weui-agree__checkbox{-webkit-appearance:none;appearance:none;outline:0;font-size:0;border:1px solid #d1d1d1;background-color:#fff;border-radius:3px;width:13px;height:13px;position:relative;vertical-align:0;top:2px}.weui-agree__checkbox:checked:before{font-family:weui;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-align:center;speak:none;display:inline-block;vertical-align:middle;text-decoration:inherit;content:"\EA08";color:#09bb07;font-size:13px;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-48%) scale(.73);transform:translate(-50%,-48%) scale(.73)}.weui-agree__checkbox:disabled{background-color:#e1e1e1}.weui-agree__checkbox:disabled:before{color:#adadad}.weui-loading{width:20px;height:20px;display:inline-block;vertical-align:middle;-webkit-animation:e 1s steps(12) infinite;animation:e 1s steps(12) infinite;background:transparent url("data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E9E9E9' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23989697' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%239B999A' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23A3A1A2' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23ABA9AA' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23B2B2B2' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23BAB8B9' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23C2C0C1' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23CBCBCB' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23D2D2D2' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23DADADA' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E2E2E2' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E") no-repeat;background-size:100%}.weui-btn_loading.weui-btn_primary .weui-loading,.weui-btn_loading.weui-btn_warn .weui-loading,.weui-loading.weui-loading_transparent{background-image:url("data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E")}@-webkit-keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.weui-slider{padding:15px 18px;-webkit-user-select:none;user-select:none}.weui-slider__inner{position:relative;height:2px;background-color:#e9e9e9}.weui-slider__track{height:2px;background-color:#1aad19;width:0}.weui-slider__handler{position:absolute;left:0;top:50%;width:28px;height:28px;margin-left:-14px;margin-top:-14px;border-radius:50%;background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.2)}.weui-slider-box{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-slider-box .weui-slider{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-slider-box__value{margin-left:.5em;min-width:24px;color:#888;text-align:center;font-size:14px}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/dobind.html b/platforms/android/app/src/main/assets/www/dobind.html
new file mode 100644
index 0000000..6d377b9
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/dobind.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>绑定银行卡</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="bindcard.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">绑定银行卡</div>
+    </header>
+    <div>
+        <div class="weui-cells__title">验证市民卡预留的手机号</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" disabled="disabled" value="13402184553">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">绑定</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/register.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/error.html b/platforms/android/app/src/main/assets/www/error.html
new file mode 100644
index 0000000..4902b3b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/error.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>错误</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back();">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">错误</div>
+    </header>
+    <p style="padding:10px;text-align: center;">系统错误</p>
+    <script type="text/javascript" src="cordova.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/findpwd.html b/platforms/android/app/src/main/assets/www/findpwd.html
new file mode 100644
index 0000000..a538505
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/findpwd.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>找回登录密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">找回登录密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="phone" style="font-size: 14px;" placeholder="请输入注册的手机号" maxlength="11">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doFind()">下一步</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/register.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/img/icon_auth.png b/platforms/android/app/src/main/assets/www/img/icon_auth.png
new file mode 100644
index 0000000..97d950d
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_auth.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_bill.png b/platforms/android/app/src/main/assets/www/img/icon_bill.png
new file mode 100644
index 0000000..37d5d65
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_bill.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_car.png b/platforms/android/app/src/main/assets/www/img/icon_car.png
new file mode 100644
index 0000000..d04eacc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_car.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_card.png b/platforms/android/app/src/main/assets/www/img/icon_card.png
new file mode 100644
index 0000000..595945e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_card.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_header.png b/platforms/android/app/src/main/assets/www/img/icon_header.png
new file mode 100644
index 0000000..b3a7ebe
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_header.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_meal.png b/platforms/android/app/src/main/assets/www/img/icon_meal.png
new file mode 100644
index 0000000..f503a14
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_meal.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_ok.png b/platforms/android/app/src/main/assets/www/img/icon_ok.png
new file mode 100644
index 0000000..e21b78a
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_ok.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_qrcode.png b/platforms/android/app/src/main/assets/www/img/icon_qrcode.png
new file mode 100644
index 0000000..bc1dfc7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_qrcode.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_scan.png b/platforms/android/app/src/main/assets/www/img/icon_scan.png
new file mode 100644
index 0000000..40b59db
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_scan.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_securty.png b/platforms/android/app/src/main/assets/www/img/icon_securty.png
new file mode 100644
index 0000000..16b4ddc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_securty.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/icon_water.png b/platforms/android/app/src/main/assets/www/img/icon_water.png
new file mode 100644
index 0000000..a65df7e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/icon_water.png
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/img/scanner.svg b/platforms/android/app/src/main/assets/www/img/scanner.svg
new file mode 100644
index 0000000..a13c92b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/img/scanner.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="210mm"
+   height="297mm"
+   viewBox="0 0 744.09448819 1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="aaa.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.7"
+     inkscape:cx="635.5236"
+     inkscape:cy="495.53637"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1017"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     showguides="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Ebene 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 139.32394,274.20898 c -2.43478,0 -4.74475,0.50716 -6.83985,1.41211 -1.96625,0.82082 -3.73345,2.01806 -5.21093,3.50391 -3.1756,3.1164 -5.14454,7.45787 -5.14454,12.2793 l 0,90.91406 c 0,9.5259 7.66941,17.19336 17.19532,17.19336 9.5259,0 17.19336,-7.66746 17.19336,-17.19336 l 0,-75.67774 75.13867,0 c 8.93724,0 16.13281,-7.19361 16.13281,-16.13085 0,-8.93723 -7.19557,-16.13282 -16.13281,-16.13282 l -90.04297,0 c -0.75087,-0.0994 -1.51019,-0.16797 -2.28906,-0.16797 z"
+       id="rect3338"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 631.50851,291.04712 c 0,-2.43478 -0.50716,-4.74475 -1.41211,-6.83985 -0.82082,-1.96625 -2.01806,-3.73345 -3.50391,-5.21093 -3.1164,-3.1756 -7.45787,-5.14454 -12.2793,-5.14454 l -90.91406,0 c -9.5259,0 -17.19336,7.66941 -17.19336,17.19532 0,9.5259 7.66746,17.19336 17.19336,17.19336 l 75.67774,0 0,75.13867 c 0,8.93724 7.19361,16.13281 16.13085,16.13281 8.93723,0 16.13282,-7.19557 16.13282,-16.13281 l 0,-90.04297 c 0.0994,-0.75087 0.16797,-1.51019 0.16797,-2.28906 z"
+       id="rect3338-2" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 122.12824,684.96063 c 0,2.43478 0.50716,4.74475 1.41211,6.83985 0.82082,1.96626 2.01806,3.73346 3.50391,5.21094 3.1164,3.1756 7.45787,5.14454 12.2793,5.14454 l 90.91406,0 c 9.5259,0 17.19336,-7.66941 17.19336,-17.19533 0,-9.5259 -7.66746,-17.19336 -17.19336,-17.19336 l -75.67774,0 0,-75.13866 c 0,-8.93724 -7.19361,-16.13281 -16.13085,-16.13281 -8.93723,0 -16.13282,7.19557 -16.13282,16.13281 l 0,90.04296 c -0.0994,0.75087 -0.16797,1.51019 -0.16797,2.28906 z"
+       id="rect3338-6" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 614.67107,702.15643 c 2.43478,0 4.74475,-0.50716 6.83985,-1.41211 1.96626,-0.82082 3.73346,-2.01806 5.21094,-3.50391 3.1756,-3.1164 5.14454,-7.45787 5.14454,-12.2793 l 0,-90.91406 c 0,-9.5259 -7.66941,-17.19336 -17.19533,-17.19336 -9.5259,0 -17.19336,7.66746 -17.19336,17.19336 l 0,75.67774 -75.13866,0 c -8.93724,0 -16.13281,7.19361 -16.13281,16.13085 0,8.93723 7.19557,16.13282 16.13281,16.13282 l 90.04296,0 c 0.75087,0.0994 1.51019,0.16797 2.28906,0.16797 z"
+       id="rect3338-6-1" />
+  </g>
+</svg>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/index.html b/platforms/android/app/src/main/assets/www/index.html
new file mode 100644
index 0000000..4afb0bf
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>大理市民卡</title>
+</head>
+<body class="mainbg">
+    <div class="weui-footer weui-footer_fixed-bottom">
+        <p class="weui-footer__links">
+            <a href="#" class="weui-footer__link" style="color: white">大理市民卡</a>
+        </p>
+        <p class="weui-footer__text" style="color: white">© 2019 上海树维</p>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/index.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.min.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript">
+</script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/bill.js b/platforms/android/app/src/main/assets/www/js/bill.js
new file mode 100644
index 0000000..4b0bca5
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/bill.js
@@ -0,0 +1,69 @@
+var curpage=1;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+    onDeviceReady: function() {
+        curpage = 1;
+        this.loadBill(curpage)
+    },
+    loadBill:function(pageno){
+        $.showLoading("加载中");
+        var param={
+            "pageno":pageno
+        }
+        V1Bills(param,function(ok,ret){
+            if(ok){
+                if(ret.code==200){
+                    if(ret.page&&ret.page.count>0){
+                        app.initBillView(ret.page)
+                    }else{
+                        $.alert("暂无数据", "提示"); 
+                    }    
+                }else{
+                    $.hideLoading();
+                    $.alert("数据加载异常,请稍后再试", "错误");
+                }
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
+            }            
+        })
+    },
+    initBillView:function(page){
+        //TODO img src
+        var data = page.data
+        var html ='';
+        for(var i=0;i<data.length;i++){
+            var bean=data[i]
+            html +='<div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail(\''+bean.refno+'\')">';
+            html +='<div class="aui-card-list-user-avatar"><img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />';
+            html +='</div><div class="aui-card-list-user-name">';
+            html +='<div>'+bean.transdesc+'</div>';
+           if(bean.tradeflag=='in'){
+                html +='<div class="aui-list-item-right">+'+bean.amount+'</div>';
+            }else{
+                html +='<div class="aui-list-item-right">'+bean.amount+'</div>';
+            }
+            html +='</div><div class="aui-card-list-user-info">'+formatDateNoYear(bean.transdate,bean.transtime)+'</div></div>';
+        }
+        $("#billcontent").append(html);
+        if(page.data.length==0){
+            $("#loadNext").hide();
+        }else{
+            $("#loadNext").show();
+        }
+        $.hideLoading();
+    },
+    toBillDetail: function(refno) {
+        window.localStorage.setItem("currentrefno",refno);
+        window.location='billdetail.html';
+    },
+    loadNext:function(){
+        curpage++;
+        this.loadBill(curpage)
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/billdetail.js b/platforms/android/app/src/main/assets/www/js/billdetail.js
new file mode 100644
index 0000000..057b106
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/billdetail.js
@@ -0,0 +1,58 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        this.loadBill()
+    },
+    loadBill: function() {
+        var refno = window.localStorage.getItem("currentrefno");
+        if (isEmpty(refno)) {
+            $.alert("加载失败了", "提示");
+            return;
+        }
+        $.showLoading("加载中");
+        var param = {
+            "billid": refno
+        }
+        V1Billdetail(param, function(ok, ret) {
+            if (ok) {
+                if (ret.code == 200) {
+                    if (ret.dtl == null) {
+                        $.hideLoading();
+                        $.alert("数据加载异常,请稍后再试", "错误");
+                    } else {
+                        app.initBillView(ret.dtl)
+                    }
+                } else {
+                    $.hideLoading();
+                    $.alert("数据加载异常,请稍后再试", "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status + "请稍后再试", "错误");
+            }
+        })
+    },
+    initBillView: function(data) {
+        console.log(data);
+        if (data.tradeflag == 'in') {
+            $("#amount").text('+' + data.amount)
+        } else {
+            $("#amount").text(data.amount)
+        }
+        if (data.status == 'success') {
+            $("#status").text("交易成功");
+        } else {
+            $("#status").text("交易失败");
+        }
+        $("#tranddes").text(data.transdesc);
+        $("#transtime").text(formatDate(data.transdate + '' + data.transtime, true));
+        $("#refno").text(data.refno);
+        $.hideLoading();
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/bindcard.js b/platforms/android/app/src/main/assets/www/js/bindcard.js
new file mode 100644
index 0000000..53ac0cf
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/bindcard.js
@@ -0,0 +1,89 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        var phone =  window.localStorage.getItem("phoneX");
+        if(!isEmpty(phone)){
+            $("#phone").val(phone)
+        }else{
+            phone =  window.localStorage.getItem("phone");
+            $("#phone").val(phone)
+        }
+    },
+    doNext: function() {
+        var code =  $("#code").val();
+        var cardnum =  $("#cardnum").val();
+        var name =  $("#name").val();
+        if(isEmpty(name)||isEmpty(code)||isEmpty(cardnum)){
+            return;
+        }
+        /*var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意用户协议与隐私条款", "提示");
+            return;
+        }*/
+        $.showLoading("正在处理");
+        var param={
+            "card":cardnum,
+            "code":code,
+            "name":name
+        }
+        V1Bindcard(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                console.log(ret)
+                if(ret.code==200){
+                     window.localStorage.setItem("paypwdtype","new"); 
+                     window.localStorage.setItem("userid",ret.userid);
+                     window.localStorage.setItem("signed",ret.signed); 
+                     window.localStorage.setItem("name",name); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     if(ret.paypwdset){
+                        if(!isEmpty(ret.signed)&&signed=='yes'){
+                            window.location='main.html'
+                        }else{
+                            window.location='signxy.html'
+                        }
+                     }else{
+                        window.location="paypwdset.html";
+                     }
+                }else{
+                    if(ret.code==-1){
+                        $.alert(ret.msg, "提示",function(){
+                            window.location="main.html"
+                        });
+                    }else{
+                       $.alert(ret.msg, "错误");
+                    }
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了 "+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        $.showLoading("请求中");
+        V1Code(function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/card.js b/platforms/android/app/src/main/assets/www/js/card.js
new file mode 100644
index 0000000..9e3fe81
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/card.js
@@ -0,0 +1,56 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doNext: function() {
+        var pwd =  $("#pwd").val();
+        if(isEmpty(pwd)){
+            return;
+        }
+        if(pwd.length!=6){
+            $.alert("支付密码为6位数字", "提示");
+            return;
+        }
+        var cum = new auiDialog({});
+        var confirm = cum.alert({
+            title: "提示",
+            msg: '确定挂失吗',
+            buttons: ['取消', '确定']
+        }, function(ret) {
+            if (ret.buttonIndex == 2) {
+                $.showLoading("正在处理");
+                var param={
+                    "pwd":pwd
+                }
+                V1CardLost(param,function(ok,ret){
+                    if(ok){
+                        $.hideLoading();
+                        if(ret.code==200){
+                             window.localStorage.removeItem("randomcode"); 
+                             var signed = window.localStorage.getItem("signed"); 
+                             window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                             if(isEmpty(signed)||signed!='yes'){
+                                window.location='signxy.html'   
+                             }else{
+                                window.location='main.html'   
+                             }
+                        }else{
+                            $.alert(ret.msg, "错误");
+                        } 
+                    }else{
+                        $.hideLoading();
+                        $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+                    }
+                })
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/db.js b/platforms/android/app/src/main/assets/www/js/db.js
new file mode 100644
index 0000000..d9f0e9b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/db.js
@@ -0,0 +1,8 @@
+var db = null;
+
+document.addEventListener('deviceready', function() {
+  db = window.sqlitePlugin.openDatabase({
+    name: 'my.db',
+    location: 'default',
+  });
+});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/index.js b/platforms/android/app/src/main/assets/www/js/index.js
new file mode 100644
index 0000000..a2381c8
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/index.js
@@ -0,0 +1,66 @@
+var app = {
+    /*
+    thirdapp:
+    closeBrowser(){
+        if(history.length==1){
+            window.open('mobile/close');
+        }else{
+            history.back();
+        }
+    }
+    <a href="javascript:;" onclick="closeBrowser()">Close</a>
+
+
+    client:
+    var ref = window.open(encodeURI(url), '_blank','location=no');
+     ref.addEventListener('loadstart', function(event) {
+         if (event.url.match("mobile/close")) {
+             ref.close();
+         }
+     });
+    */
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        if (isEmpty(uid)) {
+            window.location = "login.html";
+        } else {
+            //尝试登陆
+            V1Infor(function(ok, ret) {
+                console.log(ret)
+                if (ok) {
+                    if(ret.code==200){
+                        var exp =  window.localStorage.getItem("tokenexpire");
+                        var t = parseInt(exp);
+                        //token 小于10分钟了,需要刷新
+                        console.log((ret.now-t))
+                        if(ret.now-t>1000*60*10){
+                             window.location = "login.html";
+                        }else{
+                             window.localStorage.setItem("userid",ret.userid);
+                             window.localStorage.setItem("signed",ret.signed); 
+                             window.localStorage.setItem("paypwdset",ret.paypwdset);
+                             window.localStorage.setItem("name",ret.name); 
+                             window.location = "main.html";
+                        }
+                    }
+                } else {
+                    //alert('无法请求到服务器,请检查网络并稍后再试');
+                    if (ret.status == 401) {
+                        //need login
+                        window.location = "login.html";
+                    } else {
+                        //TODO ,没有网络
+                        
+                        window.location = "main.html";
+                    }
+                }
+            })
+        }
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-actionsheet.js b/platforms/android/app/src/main/assets/www/js/lib/aui-actionsheet.js
new file mode 100644
index 0000000..82b97a1
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-actionsheet.js
@@ -0,0 +1,118 @@
+/**
+ * aui-actionsheet.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiActionsheet = function() {
+    };
+    var isShow = false;
+    auiActionsheet.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.title = params.title;
+            this.buttons = params.buttons;
+            this.cancelTitle = params.cancelTitle;
+            this.destructiveTitle = params.destructiveTitle;
+            this.maskDiv;
+            this.actionsheetDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var titleHtml='',buttonsHtml='',destructiveHtml='',cancelHtml='',btnHtml='';
+        	var self = this;
+            if(self.actionsheetDiv || (!self.title && !self.buttons && !self.cancelTitle && !self.destructiveTitle))return;
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            self.actionsheetDiv = document.createElement("div");
+            self.actionsheetDiv.className = "aui-actionsheet";
+            document.body.appendChild(self.actionsheetDiv);
+            if(self.title){
+                titleHtml = '<div class="aui-actionsheet-title aui-border-b aui-font-size-12">'+self.title+'</div>';
+            }
+            if(self.buttons && self.buttons.length){
+                for(var i = 0; i < self.buttons.length;i++){
+                    if(i == self.buttons.length-1){
+                        buttonsHtml += '<div class="aui-actionsheet-btn-item">'+self.buttons[i]+'</div>';
+                    }else{
+                        buttonsHtml += '<div class="aui-actionsheet-btn-item aui-border-b">'+self.buttons[i]+'</div>';
+                    }
+                }
+            }
+            if(self.destructiveTitle){
+                destructiveHtml = '<div class="aui-actionsheet-btn-item aui-border-t aui-text-danger">'+self.destructiveTitle+'</div>';
+            }else{
+                var destructiveHtml = '';
+            }
+            if(self.title || (self.buttons && self.buttons.length)){
+                btnHtml = '<div class="aui-actionsheet-btn">'+titleHtml+''+buttonsHtml+''+destructiveHtml+'</div>';
+            }
+            if(self.cancelTitle){
+                cancelHtml = '<div class="aui-actionsheet-btn"><div class="aui-actionsheet-btn-item">'+self.cancelTitle+'</div></div>';
+            }
+            self.actionsheetDiv.insertAdjacentHTML('beforeend', btnHtml+cancelHtml);
+            var actionsheetHeight = document.querySelector(".aui-actionsheet").offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.actionsheetDiv.style.webkitTransform = self.actionsheetDiv.style.transform = "translate3d(0,0,0)";
+            self.actionsheetDiv.style.opacity = 1;
+            self.actionsheetDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var actionsheetButtons = document.querySelectorAll(".aui-actionsheet-btn-item");
+            if(actionsheetButtons && actionsheetButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < actionsheetButtons.length; ii++){
+                        (function(e){
+                            actionsheetButtons[e].onclick = function(){
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonTitle: this.textContent
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+            }
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.actionsheetDiv){
+                var actionsheetHeight = self.actionsheetDiv.offsetHeight;
+                self.actionsheetDiv.style.webkitTransform = self.actionsheetDiv.style.transform = "translate3d(0,"+actionsheetHeight+"px,0)";
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.actionsheetDiv.parentNode.removeChild(self.actionsheetDiv);
+                    self.actionsheetDiv = self.maskDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiActionsheet = auiActionsheet;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-collapse.js b/platforms/android/app/src/main/assets/www/js/lib/aui-collapse.js
new file mode 100644
index 0000000..491100f
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-collapse.js
@@ -0,0 +1,44 @@
+/**
+ * aui-collapse.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiCollapse = function(params) {
+        this.init(params);
+    };
+    auiCollapse.prototype = {
+        init: function(params,callback){
+            var collapseHeader = document.querySelectorAll(".aui-collapse-header");
+            if(collapseHeader.length){
+                for(var i=0;i<collapseHeader.length;i++){
+                    (function(e){
+                        collapseHeader[e].onclick = function(){
+                            if(collapseHeader[e].nextSibling.nextElementSibling.className.indexOf("aui-collapse-content") > -1){
+                                if(collapseHeader[e].nextSibling.nextElementSibling.className.indexOf("aui-show") > -1){
+                                    collapseHeader[e].nextSibling.nextElementSibling.classList.remove("aui-show");
+                                    collapseHeader[e].classList.remove("aui-active");
+                                }else{
+                                    if(params.autoHide){
+                                        if(document.querySelector(".aui-collapse-header.aui-active")){
+                                            document.querySelector(".aui-collapse-header.aui-active").classList.remove("aui-active");
+                                        }
+                                        if(document.querySelector(".aui-collapse-content.aui-show")){
+                                            document.querySelector(".aui-collapse-content.aui-show").classList.remove("aui-show");
+                                        }
+                                    }
+
+                                    collapseHeader[e].nextSibling.nextElementSibling.classList.toggle("aui-show");
+                                    collapseHeader[e].classList.toggle("aui-active");
+                                }
+                            }
+                        }
+                    })(i)
+                }
+            }
+        }
+    };
+	window.auiCollapse = auiCollapse;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-dialog.js b/platforms/android/app/src/main/assets/www/js/lib/aui-dialog.js
new file mode 100644
index 0000000..90e85aa
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-dialog.js
@@ -0,0 +1,125 @@
+/**
+ * aui-dialog.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiDialog = function() {
+    };
+    var isShow = false;
+    auiDialog.prototype = {
+        params: {
+            title:'',
+            msg:'',
+            buttons: ['取消','确定'],
+            input:false
+        },
+        create: function(params,callback) {
+        	var self = this;
+            var dialogHtml = '';
+            var buttonsHtml = '';
+            var headerHtml = params.title ? '<div class="aui-dialog-header">' + params.title + '</div>' : '<div class="aui-dialog-header">' + self.params.title + '</div>';
+            if(params.input){
+                params.text = params.text ? params.text: '';
+                var msgHtml = '<div class="aui-dialog-body"><input type="text" placeholder="'+params.text+'"></div>';
+            }else{
+                var msgHtml = params.msg ? '<div class="aui-dialog-body">' + params.msg + '</div>' : '<div class="aui-dialog-body">' + self.params.msg + '</div>';
+            }
+            var buttons = params.buttons ? params.buttons : self.params.buttons;
+            if (buttons && buttons.length > 0) {
+                for (var i = 0; i < buttons.length; i++) {
+                    buttonsHtml += '<div class="aui-dialog-btn" tapmode button-index="'+i+'">'+buttons[i]+'</div>';
+                }
+            }
+            var footerHtml = '<div class="aui-dialog-footer">'+buttonsHtml+'</div>';
+            dialogHtml = '<div class="aui-dialog">'+headerHtml+msgHtml+footerHtml+'</div>';
+            document.body.insertAdjacentHTML('beforeend', dialogHtml);
+            // listen buttons click
+            var dialogButtons = document.querySelectorAll(".aui-dialog-btn");
+            if(dialogButtons && dialogButtons.length > 0){
+                for(var ii = 0; ii < dialogButtons.length; ii++){
+                    dialogButtons[ii].onclick = function(){
+                        if(callback){
+                            if(params.input){
+                                callback({
+                                    buttonIndex: parseInt(this.getAttribute("button-index"))+1,
+                                    text: document.querySelector("input").value
+                                });
+                            }else{
+                                callback({
+                                    buttonIndex: parseInt(this.getAttribute("button-index"))+1
+                                });
+                            }
+                        };
+                        self.close();
+                        return;
+                    }
+                }
+            }
+            self.open();
+        },
+        open: function(){
+            if(!document.querySelector(".aui-dialog"))return;
+            var self = this;
+            document.querySelector(".aui-dialog").style.marginTop =  "-"+Math.round(document.querySelector(".aui-dialog").offsetHeight/2)+"px";
+            if(!document.querySelector(".aui-mask")){
+                var maskHtml = '<div class="aui-mask"></div>';
+                document.body.insertAdjacentHTML('beforeend', maskHtml);
+            }
+            // document.querySelector(".aui-dialog").style.display = "block";
+            setTimeout(function(){
+                document.querySelector(".aui-dialog").classList.add("aui-dialog-in");
+                document.querySelector(".aui-mask").classList.add("aui-mask-in");
+                document.querySelector(".aui-dialog").classList.add("aui-dialog-in");
+            }, 10)
+            document.querySelector(".aui-mask").addEventListener("touchmove", function(e){
+                e.preventDefault();
+            })
+            document.querySelector(".aui-dialog").addEventListener("touchmove", function(e){
+                e.preventDefault();
+            })
+            return;
+        },
+        close: function(){
+            var self = this;
+            document.querySelector(".aui-mask").classList.remove("aui-mask-in");
+            document.querySelector(".aui-dialog").classList.remove("aui-dialog-in");
+            document.querySelector(".aui-dialog").classList.add("aui-dialog-out");
+            if (document.querySelector(".aui-dialog:not(.aui-dialog-out)")) {
+                setTimeout(function(){
+                    if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+                    self.open();
+                    return true;
+                },200)
+            }else{
+                document.querySelector(".aui-mask").classList.add("aui-mask-out");
+                document.querySelector(".aui-dialog").addEventListener("webkitTransitionEnd", function(){
+                    self.remove();
+                })
+                document.querySelector(".aui-dialog").addEventListener("transitionend", function(){
+                    self.remove();
+                })
+            }
+        },
+        remove: function(){
+            if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+            if(document.querySelector(".aui-mask")){
+                document.querySelector(".aui-mask").classList.remove("aui-mask-out");
+            }
+            return true;
+        },
+        alert: function(params,callback){
+        	var self = this;
+            return self.create(params,callback);
+        },
+        prompt:function(params,callback){
+            var self = this;
+            params.input = true;
+            return self.create(params,callback);
+        }
+    };
+	window.auiDialog = auiDialog;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-lazyload.js b/platforms/android/app/src/main/assets/www/js/lib/aui-lazyload.js
new file mode 100644
index 0000000..17e24f0
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-lazyload.js
@@ -0,0 +1,48 @@
+/**

+ * aui-lazyload.js

+ * @author 流浪男

+ * Licensed under the MIT license.

+ * http://www.opensource.org/licenses/mit-license.php

+ */

+(function( window, undefined ) {

+    "use strict";

+    var _loadImgNodes;

+    var auiLazyload = function(params) {

+        this.errorImage = params.errorImage||false;

+        this._init(params);

+    };

+    auiLazyload.prototype = {

+        _init: function(params) {

+            var self = this;

+            _loadImgNodes = document.querySelectorAll('[data-src]');

+            self._judgeImages();

+            window.addEventListener('scroll', function(){

+                _loadImgNodes = document.querySelectorAll('[data-src]');

+                self._judgeImages();

+            }, false);

+        },

+        _judgeImages:function() {

+            var self = this;

+            if(_loadImgNodes.length){

+                for(var i = 0;  i < _loadImgNodes.length; i++){

+                    if (_loadImgNodes[i].getBoundingClientRect().top < window.innerHeight) {

+                        self._loadImage(_loadImgNodes[i]);

+                    }

+                }

+            }

+        },

+        _loadImage:function(el){

+            var self = this;

+            var img = new Image();

+            img.src = el.getAttribute('data-src');

+            el.src = el.getAttribute('data-src');

+            el.removeAttribute("data-src");

+            // // 图片加载失败

+            img.onerror = function() {

+                el.src = self.errorImage || el.getAttribute('src');

+                el.removeAttribute("data-src");

+            };

+        }

+    }

+    window.auiLazyload = auiLazyload;

+})(window);

diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe-backup.js b/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe-backup.js
new file mode 100644
index 0000000..7bffd23
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe-backup.js
@@ -0,0 +1,243 @@
+/**
+ * aui-list-swipe.js 列表页滑动菜单
+ * verson 0.0.3
+ * @author 流浪男 && Beck
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+ (function(window) {
+	"use strict";
+	var translateVal,
+		friction = 1,
+		firstTouchX,
+		firstTouchxy,
+		firstTouchY,
+		firstTouch,
+		firstTouchTime,
+		touchXDelta,
+		handleTranslateVal;
+	var TranslateZero = "translate3d(0,0,0)",
+		TranslateCent = "translate3d(100%,0,0)";
+	var swipeHandle = false,
+		btnWidth = false,
+		swipeBtnsRight = false;
+	var isMoved = false,isOpened=false;
+	var d = false;
+	var auiListSwipe = function (callback) {
+		this._init(callback);
+	}
+	auiListSwipe.prototype = {
+		// var self = this;
+		_init: function(callback){
+			var self = this;
+			// var d = document.querySelectorAll("selectors")
+			window.addEventListener('touchstart', function(event){
+				if(isOpened){
+					console.log(1)
+					// return;
+					isOpened = false;
+					return;
+				}
+				if(swipeHandle){
+					event.preventDefault();
+					self.setTranslate(swipeHandle,"0px");
+					swipeHandle.classList.remove("aui-swipe-opened");
+					swipeHandle = false;
+					return;
+				}
+				isMoved = false;
+				swipeHandle = false;
+				var target = event.target;
+				// 过滤点击
+				for(; target && target !== document; target = target.parentNode){
+					// console.log(target.classList)
+					if (target.classList){
+						if (target.classList.contains("aui-swipe-handle")) {
+							swipeHandle = target;
+							firstTouch = event.changedTouches[0];
+							firstTouchX = firstTouch.clientX;
+							firstTouchY = firstTouch.clientY;
+							firstTouchTime = event.timeStamp;
+							if(swipeHandle.className.indexOf("aui-swipe-opened") > -1){
+							// 	console.log(1)
+								// self.setTranslate(swipeHandle,"0px");
+								// swipeHandle.classList.remove("aui-swipe-opened");
+								event.preventDefault();
+								return;
+							}else{
+								// setTimeout(function(){
+									self.toggleEvents(swipeHandle,callback);
+								// }, 100)
+
+							}
+
+						}
+					}
+				}
+
+
+			})
+			// window.addEventListener('touchmove', function(event){
+			// 	if(swipeHandle){
+			// 		// event.preventDefault();
+			// 		// self.setTranslate(swipeHandle,"0px");
+			// 		// swipeHandle.classList.remove("aui-swipe-opened");
+			// 		// swipeHandle = false;
+			// 		// return;
+			// 	}
+			// 	if(document.querySelector(".aui-swipe-opened")){
+			// 		event.preventDefault();
+			// 		if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+			// 			self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			//         	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			//         	isOpened = false;
+
+			//         	event.stopPropagation()
+			//         	return;
+			// 		}
+			// 	}
+			// })
+			window.addEventListener("touchmove", function(){
+
+			})
+		},
+		toggleEvents:function(element,callback){
+			if(!swipeHandle){
+				return;
+			}
+			var self = this;
+			self.setTransform(element,300);
+			element.addEventListener('touchstart', function(event){
+				// if(element.className.indexOf("aui-swipe-opened") > -1){
+				// 	self.setTranslate(element,"0px");
+				// 	element.classList.remove("aui-swipe-opened");
+				// 	return;
+				// }
+				//:active样式引起列表背景色冲突
+
+				element.parentNode.style.backgroundColor = "#ffffff";
+				if(!element.nextSibling)return;
+			},false)
+			element.addEventListener('touchmove', function(event){
+				if(document.querySelector(".aui-swipe-opened")){
+					event.preventDefault();
+					if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+						self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			        	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			        	isOpened = false;
+			        	event.stopPropagation()
+			        	return;
+					}
+				}
+				// self.getAngle(event)
+				self.setTransform(element,0);
+				// if(element.className.indexOf("aui-swipe-opened") > -1)return;
+
+				if(element.parentNode.querySelector(".aui-swipe-btn")){
+					btnWidth = element.parentNode.querySelector(".aui-swipe-btn").offsetWidth;
+				}
+				// 列表触摸滑动时如果有已经显示的将其关闭,并退出。
+				var touchMoveObj = event.changedTouches[0],
+					touchX = touchMoveObj.clientX;
+				touchXDelta = -Math.pow(firstTouchX-touchX, 0.85);
+				handleTranslateVal = touchXDelta/friction;
+				// touchXDelta = touchX - firstTouchX;
+				// handleTranslateVal = touchXDelta/0.15;
+				// console.log(handleTranslateVal)
+		        var moveX = touchMoveObj.clientX - firstTouchX;
+		        var moveY = touchMoveObj.clientY - firstTouchY;
+		        var direction = self.getDirection(moveX,moveY);
+		        var angle = self.getAngle(Math.abs(moveX),Math.abs(moveY));
+		        // console.log(isMoved);
+
+		        // // 解决滑动屏幕返回时事件冲突,主要针对部分特殊机型
+		        // if(touchMoveObj.screenX < 0){
+		        // 	firstTouchxy = '';
+		        // }
+		        if(direction == "right"){
+		        	isMoved = false;
+		        	event.preventDefault();
+		        }
+		        if(direction == "top" || direction == "down"){
+		        	isMoved = false;
+		        	return;
+		        }
+		        if(angle <= 15 && direction === 'left'){
+		        	event.preventDefault()
+		        	isMoved = true;
+		        }
+		        // console.log(handleTranslateVal)
+		        // if(isMoved)self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+		        if((event.timeStamp - firstTouchTime) >= 100 && touchXDelta < 0 && touchMoveObj.screenX > 0 && isMoved){
+		        	// event.stopPropagation();
+		        	// element.classList.add("aui-swipe-moving");
+		        	// event.preventDefault();
+		        	if(element.className.indexOf("aui-swipe-opened") <= -1){
+						if((handleTranslateVal+10) > -btnWidth){
+				        	self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+				        }
+					}else{
+						return
+					}
+
+			    }
+			},false)
+			element.addEventListener('touchend', function(event){
+				self.setTransform(element,300);
+				var touchEndObj = event.changedTouches[0];
+				var touchEndxy = {
+						x: touchEndObj.clientX || 0,
+						y: touchEndObj.clientY || 0
+					};
+				var toucheEndX = touchEndObj.clientX - firstTouchX;
+		        var toucheEndY = touchEndObj.clientY - firstTouchY;
+		        var direction = self.getDirection(toucheEndX,toucheEndY);
+		        // element.classList.remove("aui-swipe-moving");
+	        	if(direction=='left' && handleTranslateVal < (-btnWidth/3) && isMoved){
+		        	self.setTranslate(element,""+-btnWidth+"px");
+		        	element.classList.add("aui-swipe-opened");
+		        	callback({
+		        		'status':true,
+		        		'dom':element
+		        	})
+		        	isOpened = true;
+				}else{
+					element.classList.remove("aui-swipe-opened");
+		        	self.setTranslate(element,"0px");
+		        	isOpened = false;
+				}
+				// isMoved = false;
+				console.log(isOpened)
+			},true)
+		},
+		setTransform : function (el,value){
+			el.style.webkitTransitionDuration = el.style.transitionDuration = value+'ms';
+		},
+		setTranslate : function (el,value){
+			if(el)el.style.webkitTransform = el.style.transform = "translate3d("+value+",0,0)";
+		},
+		getDistance : function(p1, p2, props) {
+			if (!props) { props = ['x', 'y'];}
+			var x = p2[props[0]] - p1[props[0]];
+			var y = p2[props[1]] - p1[props[1]];
+			return Math.sqrt((x * x) + (y * y));
+		},
+		getAngle:function(moveX, moveY){
+		       // var x = Math.abs(x1 - x2);
+		       // var y = Math.abs(y1 - y2);
+		       var z = Math.sqrt(moveX*moveX + moveY*moveY);
+		       return  Math.round((Math.asin(moveY / z) / Math.PI*180));
+		},
+		getDirection : function(x, y) {
+			if (x === y) { return '';}
+			if (Math.abs(x) >= Math.abs(y)) {
+	            return x > 0 ? 'right' : 'left';
+	        } else {
+	           	return y > 0 ? 'down' : 'up';
+	        }
+		}
+	}
+	window.auiListSwipe = auiListSwipe;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe.js b/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe.js
new file mode 100755
index 0000000..3669b70
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-list-swipe.js
@@ -0,0 +1,221 @@
+/**
+ * aui-list-swipe.js 列表页滑动菜单
+ * verson 0.0.3
+ * @author 流浪男 && Beck
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+ (function(window) {
+	"use strict";
+	var translateVal,
+		friction = 1,
+		firstTouchX,
+		firstTouchxy,
+		firstTouchY,
+		firstTouch,
+		firstTouchTime,
+		touchXDelta,
+		handleTranslateVal;
+	var TranslateZero = "translate3d(0,0,0)",
+		TranslateCent = "translate3d(100%,0,0)";
+	var swipeHandle = false,
+		btnWidth = false,
+		swipeBtnsRight = false;
+	var isMoved = false,isOpened=false;
+	var d = false;
+	var auiListSwipe = function (callback) {
+		this._init(callback);
+	}
+	auiListSwipe.prototype = {
+		// var self = this;
+		_init: function(callback){
+			var self = this;
+			// var d = document.querySelectorAll("selectors")
+			window.addEventListener('touchstart', function(event){
+				// 如果已经打开,将已经打开的关闭
+				if(isOpened && swipeHandle){
+					// isOpened = false;
+					self.setTranslate(swipeHandle,"0px");
+					swipeHandle.classList.remove("aui-swipe-opened");
+					return;
+				}else{
+					var target = event.target;
+					// 过滤点击
+					for(; target && target !== document; target = target.parentNode){
+						// console.log(target.classList)
+						if (target.classList){
+							if (target.classList.contains("aui-swipe-handle")) {
+								swipeHandle = target;
+								firstTouch = event.changedTouches[0];
+								firstTouchX = firstTouch.clientX;
+								firstTouchY = firstTouch.clientY;
+								firstTouchTime = event.timeStamp;
+								if(swipeHandle.className.indexOf("aui-swipe-opened") > -1){
+								// 	console.log(1)
+									// self.setTranslate(swipeHandle,"0px");
+									// swipeHandle.classList.remove("aui-swipe-opened");
+									event.preventDefault();
+									return;
+								}else{
+									// setTimeout(function(){
+										self.toggleEvents(swipeHandle,callback);
+									// }, 100)
+
+								}
+
+							}
+						}
+					}
+				}
+				// if(swipeHandle){
+				// 	event.preventDefault();
+				// 	self.setTranslate(swipeHandle,"0px");
+				// 	swipeHandle.classList.remove("aui-swipe-opened");
+				// 	swipeHandle = false;
+				// 	return;
+				// }
+				// isMoved = false;
+				// swipeHandle = false;
+			})
+		},
+		toggleEvents:function(element,callback){
+			if(!swipeHandle){
+				return;
+			}
+			var self = this;
+			self.setTransform(element,300);
+			element.addEventListener('touchstart', function(event){
+				// if(element.className.indexOf("aui-swipe-opened") > -1){
+				// 	self.setTranslate(element,"0px");
+				// 	element.classList.remove("aui-swipe-opened");
+				// 	return;
+				// }
+				//:active样式引起列表背景色冲突
+
+				element.parentNode.style.backgroundColor = "#ffffff";
+				if(!element.nextSibling)return;
+			},false)
+			element.addEventListener('touchmove', function(event){
+				event.preventDefault();
+				if(document.querySelector(".aui-swipe-opened")){
+					event.preventDefault();
+					if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+						self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			        	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			        	isOpened = false;
+			        	event.stopPropagation()
+			        	return;
+					}
+				}
+				// self.getAngle(event)
+				self.setTransform(element,0);
+				// if(element.className.indexOf("aui-swipe-opened") > -1)return;
+
+				if(element.parentNode.querySelector(".aui-swipe-btn")){
+					btnWidth = element.parentNode.querySelector(".aui-swipe-btn").offsetWidth;
+				}
+				// 列表触摸滑动时如果有已经显示的将其关闭,并退出。
+				var touchMoveObj = event.changedTouches[0],
+					touchX = touchMoveObj.clientX;
+				touchXDelta = -Math.pow(firstTouchX-touchX, 0.85);
+				handleTranslateVal = touchXDelta/friction;
+				// touchXDelta = touchX - firstTouchX;
+				// handleTranslateVal = touchXDelta/0.15;
+				// console.log(handleTranslateVal)
+		        var moveX = touchMoveObj.clientX - firstTouchX;
+		        var moveY = touchMoveObj.clientY - firstTouchY;
+		        var direction = self.getDirection(moveX,moveY);
+		        var angle = self.getAngle(Math.abs(moveX),Math.abs(moveY));
+		        // console.log(isMoved);
+
+		        // // 解决滑动屏幕返回时事件冲突,主要针对部分特殊机型
+		        // if(touchMoveObj.screenX < 0){
+		        // 	firstTouchxy = '';
+		        // }
+		        if(direction == "right"){
+		        	isMoved = false;
+		        	event.preventDefault();
+		        }
+		        if(direction == "top" || direction == "down"){
+		        	isMoved = false;
+		        	return;
+		        }
+		        if(angle <= 15 && direction === 'left'){
+		        	event.preventDefault()
+		        	isMoved = true;
+		        }
+		        // console.log(handleTranslateVal)
+		        // if(isMoved)self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+		        if((event.timeStamp - firstTouchTime) >= 100 && touchXDelta < 0 && touchMoveObj.screenX > 0 && isMoved){
+		        	// event.stopPropagation();
+		        	// element.classList.add("aui-swipe-moving");
+		        	// event.preventDefault();
+		        	if(element.className.indexOf("aui-swipe-opened") <= -1){
+						if((handleTranslateVal+10) > -btnWidth){
+				        	self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+				        }
+					}else{
+						return
+					}
+
+			    }
+			},false)
+			element.addEventListener('touchend', function(event){
+				self.setTransform(element,300);
+				var touchEndObj = event.changedTouches[0];
+				var touchEndxy = {
+						x: touchEndObj.clientX || 0,
+						y: touchEndObj.clientY || 0
+					};
+				var toucheEndX = touchEndObj.clientX - firstTouchX;
+		        var toucheEndY = touchEndObj.clientY - firstTouchY;
+		        var direction = self.getDirection(toucheEndX,toucheEndY);
+		        // element.classList.remove("aui-swipe-moving");
+	        	if(direction=='left' && handleTranslateVal < (-btnWidth/3) && isMoved){
+		        	self.setTranslate(element,""+-btnWidth+"px");
+		        	element.classList.add("aui-swipe-opened");
+		        	callback({
+		        		'status':true,
+		        		'dom':element
+		        	})
+		        	// isOpened = true;
+				}else{
+					element.classList.remove("aui-swipe-opened");
+		        	self.setTranslate(element,"0px");
+		        	isOpened = false;
+				}
+				// isMoved = false;
+				console.log(isOpened)
+			},true)
+		},
+		setTransform : function (el,value){
+			el.style.webkitTransitionDuration = el.style.transitionDuration = value+'ms';
+		},
+		setTranslate : function (el,value){
+			if(el)el.style.webkitTransform = el.style.transform = "translate3d("+value+",0,0)";
+		},
+		getDistance : function(p1, p2, props) {
+			if (!props) { props = ['x', 'y'];}
+			var x = p2[props[0]] - p1[props[0]];
+			var y = p2[props[1]] - p1[props[1]];
+			return Math.sqrt((x * x) + (y * y));
+		},
+		getAngle:function(moveX, moveY){
+		       // var x = Math.abs(x1 - x2);
+		       // var y = Math.abs(y1 - y2);
+		       var z = Math.sqrt(moveX*moveX + moveY*moveY);
+		       return  Math.round((Math.asin(moveY / z) / Math.PI*180));
+		},
+		getDirection : function(x, y) {
+			if (x === y) { return '';}
+			if (Math.abs(x) >= Math.abs(y)) {
+	            return x > 0 ? 'right' : 'left';
+	        } else {
+	           	return y > 0 ? 'down' : 'up';
+	        }
+		}
+	}
+	window.auiListSwipe = auiListSwipe;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-popup-new.js b/platforms/android/app/src/main/assets/www/js/lib/aui-popup-new.js
new file mode 100644
index 0000000..3c1a128
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-popup-new.js
@@ -0,0 +1,135 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiPopup = function() {
+    };
+    var isShow = false;
+    auiPopup.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.location = params.location;
+            this.buttons = params.buttons;
+            this.maskDiv;
+            this.popupDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var buttonsHtml='',locationClass = 'aui-popup-top';
+        	var self = this;
+            if(self.popupDiv){
+                self.close();
+                return;
+            }
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            switch (self.location) {
+                case "top":
+                    locationClass = 'aui-popup-top';
+                    break;
+                case "top-left":
+                    locationClass = 'aui-popup-top-left';
+                    break;
+                case "top-right":
+                    locationClass = 'aui-popup-top-right';
+                    break;
+                case "bottom":
+                    locationClass = 'aui-popup-bottom';
+                    break;
+                case "bottom-left":
+                    locationClass = 'aui-popup-bottom-left';
+                    break;
+                case "bottom-right":
+                    locationClass = 'aui-popup-bottom-right';
+                    break;
+                default:
+                    locationClass = 'aui-popup-top';
+                    break;
+            }
+            self.popupDiv = document.createElement("div");
+            self.popupDiv.className = "aui-popup "+locationClass;
+            self.popupDiv.innerHTML = '<div class="aui-popup-arrow"></div><div class="aui-popup-content"></div>';
+            document.body.appendChild(self.popupDiv);
+            if(self.buttons && self.buttons.length){
+                buttonsHtml += '<ul class="aui-list aui-list-noborder">';
+                for(var i = 0; i < self.buttons.length;i++){
+                    buttonsHtml += '<li class="aui-list-item aui-list-item-middle">';
+                    buttonsHtml += '<div class="aui-list-item-label-icon"><img src="'+self.buttons[i].image+'"></div>';
+                    buttonsHtml += '<div class="aui-list-item-inner">'+self.buttons[i].text+'</div>';
+                    buttonsHtml += '</li>';
+                }
+                buttonsHtml += '</ul>';
+            }
+            document.querySelector(".aui-popup .aui-popup-content").insertAdjacentHTML('beforeend', buttonsHtml);
+            var actionsheetHeight = document.querySelector(".aui-popup").offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.popupDiv.classList.add("aui-popup-in");
+            self.popupDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var popupButtons = document.querySelectorAll(".aui-popup .aui-list-item");
+            if(popupButtons && popupButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < popupButtons.length; ii++){
+                        (function(e){
+                            popupButtons[e].onclick = function(){
+                                if(self.buttons[e].value){
+                                    var _value = self.buttons[e].value;
+                                }else{
+                                    var _value = null;
+                                }
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonTitle: this.textContent,
+                                        buttonValue: _value
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+            }
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.popupDiv){
+                var actionsheetHeight = self.popupDiv.offsetHeight;
+                self.popupDiv.classList.add("aui-popup-out");
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.popupDiv.parentNode.removeChild(self.popupDiv);
+                    self.maskDiv = self.popupDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiPopup = auiPopup;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-popup.js b/platforms/android/app/src/main/assets/www/js/lib/aui-popup.js
new file mode 100644
index 0000000..fe26259
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-popup.js
@@ -0,0 +1,94 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiPopup = function() {
+        this._init();
+    };
+    var	CLASS_MASK = "aui-mask",
+    	CLASS_MASK_IN = 'aui-mask-in',
+    	CLASS_MASK_OUT = 'aui-mask-out',
+        CLASS_POPUP = 'aui-popup',
+    	CLASS_POPUP_IN = 'aui-popup-in',
+    	CLASS_POPUP_OUT = 'aui-popup-out',
+    	CLASS_POPUP_FOR = 'aui-popup-for';
+    var	__MASK = '.'+CLASS_MASK,
+    	__MASK_IN = '.'+CLASS_MASK_IN,
+    	__MASK_OUT = '.'+CLASS_MASK_OUT,
+        __POPUP = '.'+CLASS_POPUP,
+    	__POPUP_IN = '.'+CLASS_POPUP_IN,
+    	__POPUP_OUT = '.'+CLASS_POPUP_OUT;
+    var popupStatus = false;
+    auiPopup.prototype = {
+        _init: function() {
+        	var self = this;
+        	var _btn = document.querySelectorAll("["+CLASS_POPUP_FOR+"]");
+        	if(_btn){
+        		for(var i=0;i<_btn.length;i++){
+        			_btn[i].setAttribute("tapmode", "");
+        			_btn[i].onclick = function(e){
+        				var popupId = this.getAttribute(CLASS_POPUP_FOR);
+        				var popupDom = document.getElementById(popupId);
+        				if(popupDom){
+							if(popupDom.className.indexOf(CLASS_POPUP_IN) > -1 || document.querySelector(__POPUP_IN)){
+					            self.hide(popupDom);
+					        }else{
+					        	self.show(popupDom);
+					        }
+        				}else{
+        					return;
+        				}
+					}
+        		}
+        	}
+        },
+        show: function(el){
+        	var self = this;
+        	if(el.className.indexOf(CLASS_POPUP_IN) > -1 || document.querySelector(__POPUP_IN)){
+	            self.hide(el);
+	            return;
+	        }
+            if(popupStatus) return;
+        	if(!document.querySelector(__MASK)){
+				var maskHtml = '<div class="aui-mask"></div>';
+				document.body.insertAdjacentHTML('beforeend', maskHtml);
+			}
+        	el.style.display = "block";
+        	setTimeout(function(){
+        		document.querySelector(__MASK).classList.add(CLASS_MASK_IN);
+	            el.classList.add(CLASS_POPUP_IN);
+                popupStatus = true;
+	        }, 10)
+	        document.querySelector(__MASK).addEventListener("touchstart", function(event){
+	        	event.preventDefault();
+	        	self.hide(el);
+	        })
+            el.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            },false)
+        },
+        hide: function(el){
+            if(!popupStatus) return;
+        	document.querySelector(__MASK).classList.remove(CLASS_MASK_IN);
+        	document.querySelector(__MASK).classList.add(CLASS_MASK_OUT);
+        	if(!document.querySelector(__POPUP_IN))return;
+            document.querySelector(__POPUP_IN).classList.add(CLASS_POPUP_OUT);
+            document.querySelector(__POPUP_IN).classList.remove(CLASS_POPUP_IN);
+	        setTimeout(function(){
+                if(!document.querySelector(__POPUP_OUT))return;
+	        	document.querySelector(__POPUP_OUT).style.display = "none";
+	            document.querySelector(__POPUP_OUT).classList.remove(CLASS_POPUP_OUT);
+	            if(document.querySelector(__MASK)){
+					document.querySelector(__MASK).parentNode.removeChild(document.querySelector(__MASK));
+				}
+                popupStatus = false;
+	        }, 300)
+        }
+    };
+	window.auiPopup = auiPopup;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-pull-refresh.js b/platforms/android/app/src/main/assets/www/js/lib/aui-pull-refresh.js
new file mode 100644
index 0000000..8f3bba3
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-pull-refresh.js
@@ -0,0 +1,174 @@
+/**
+ * aui-pull-refresh.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	'use strict';
+	/**
+	 * Extend obj function
+	 *
+	 * This is an object extender function. It allows us to extend an object
+	 * by passing in additional variables and overwriting the defaults.
+	 */
+	var auiPullToRefresh = function (params,callback) {
+		this.extend(this.params, params);
+		this._init(callback);
+	}
+	var touchYDelta;
+	var isLoading = false;
+	var docElem = window.document.documentElement,
+		loadWrapH,
+		win = {width: window.innerWidth, height: window.innerHeight},
+		winfactor= 0.2,
+		translateVal,
+		isMoved = false,
+		firstTouchY, initialScroll;
+	auiPullToRefresh.prototype = {
+		params: {
+            container: document.querySelector('.aui-refresh-content'),
+			friction: 2.5,
+			triggerDistance: 100,
+			callback:false
+        },
+        _init : function(callback) {
+			var self = this;
+			var loadingHtml = '<div class="aui-refresh-load"><div class="aui-refresh-pull-arrow"></div></div>';
+			self.params.container.insertAdjacentHTML('afterbegin', loadingHtml);
+			self.params.container.addEventListener('touchstart', function(ev){
+				self.touchStart(ev)
+			});
+			self.params.container.addEventListener('touchmove', function(ev){
+				self.touchMove(ev)
+			});
+			self.params.container.addEventListener('touchend', function(ev){
+				self.touchEnd(ev,callback);
+			});
+		},
+		touchStart : function(ev) {
+			// this.params.container.classList.remove("refreshing");
+			if (isLoading) {
+				return;
+			}
+			isMoved = false;
+			this.params.container.style.webkitTransitionDuration =
+		    this.params.container.style.transitionDuration = '0ms';
+			touchYDelta = '';
+			var touchobj = ev.changedTouches[0];
+			// register first touch "y"
+			firstTouchY = parseInt(touchobj.clientY);
+			initialScroll = this.scrollY();
+		},
+		touchMove : function (ev) {
+			if (isLoading) {
+				ev.preventDefault();
+				return;
+			}
+			var self = this;
+			var moving = function() {
+				var touchobj = ev.changedTouches[0], // reference first touch point for this event
+					touchY = parseInt(touchobj.clientY);
+					touchYDelta = touchY - firstTouchY;
+				if ( self.scrollY() === 0 && touchYDelta > 0  ) {
+					ev.preventDefault();
+				}
+				if ( initialScroll > 0 || self.scrollY() > 0 || self.scrollY() === 0 && touchYDelta < 0 ) {
+					firstTouchY = touchY;
+					return;
+				}
+				translateVal = Math.pow(touchYDelta, 0.85);
+				self.params.container.style.webkitTransform = self.params.container.style.transform = 'translate3d(0, ' + translateVal + 'px, 0)';
+				isMoved = true;
+				if(touchYDelta > self.params.triggerDistance){
+					self.params.container.classList.add("aui-refresh-pull-up");
+					self.params.container.classList.remove("aui-refresh-pull-down");
+				}else{
+					self.params.container.classList.add("aui-refresh-pull-down");
+					self.params.container.classList.remove("aui-refresh-pull-up");
+				}
+			};
+			this.throttle(moving(), 20);
+		},
+		touchEnd : function (ev,callback) {
+			var self =this;
+			if (isLoading|| !isMoved) {
+				isMoved = false;
+				return;
+			}
+			// 根据下拉高度判断是否加载
+			if( touchYDelta >= this.params.triggerDistance) {
+				isLoading = true; //正在加载中
+				ev.preventDefault();
+				this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '300ms';
+				this.params.container.style.webkitTransform =
+				this.params.container.style.transform = 'translate3d(0,60px,0)';
+				document.querySelector(".aui-refresh-pull-arrow").style.webkitTransitionDuration =
+		    	document.querySelector(".aui-refresh-pull-arrow").style.transitionDuration = '0ms';
+				self.params.container.classList.add("aui-refreshing");
+				if(callback){
+					callback({
+						status:"success"
+					});
+				}
+			}else{
+				this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '300ms';
+				this.params.container.style.webkitTransform =
+				this.params.container.style.transform = 'translate3d(0,0,0)';
+				if(callback){
+					callback({
+						status:"fail"
+					});
+				}
+			}
+			isMoved = false;
+			return;
+		},
+		cancelLoading : function () {
+			var self =this;
+			isLoading = false;
+			self.params.container.classList.remove("aui-refreshing");
+			document.querySelector(".aui-refresh-pull-arrow").style.webkitTransitionDuration =
+		    	document.querySelector(".aui-refresh-pull-arrow").style.transitionDuration = '300ms';
+			this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '0ms';
+			self.params.container.style.webkitTransform =
+			self.params.container.style.transform = 'translate3d(0,0,0)';
+			self.params.container.classList.remove("aui-refresh-pull-up");
+			self.params.container.classList.add("aui-refresh-pull-down");
+			return;
+		},
+		scrollY : function() {
+			return window.pageYOffset || docElem.scrollTop;
+		},
+		throttle : function(fn, delay) {
+			var allowSample = true;
+			return function(e) {
+				if (allowSample) {
+					allowSample = false;
+					setTimeout(function() { allowSample = true; }, delay);
+					fn(e);
+				}
+			};
+		},
+		winresize : function () {
+			var resize = function() {
+				win = {width: window.innerWidth, height: window.innerHeight};
+			};
+			throttle(resize(), 10);
+		},
+		extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		 }
+	}
+	window.auiPullToRefresh = auiPullToRefresh;
+
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-range.js b/platforms/android/app/src/main/assets/www/js/lib/aui-range.js
new file mode 100644
index 0000000..ed42002
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-range.js
@@ -0,0 +1,53 @@
+/*

+ * AUI JAVASCRIPT PLUGIN

+ * 滑动 aui-range

+ * Copyright (c) 2015 auicss.com @流浪男  QQ:343757327  群:344869952

+ */

+ (function( window, undefined ) {

+    "use strict";

+    var auiRange = function(params,callback) {

+        this._init(params,callback);

+    };

+    var time=null;

+    var distance,offsetLeft,tooltipWidth;

+    auiRange.prototype = {

+        _init: function(params,callback) {

+            var self = this;

+            distance = Math.abs(params.element.max - params.element.min);

+            offsetLeft = params.element.offsetLeft;

+            tooltipWidth = params.element.offsetWidth - 28;

+            params.element.insertAdjacentHTML('afterend','<div class="aui-range-tip aui-hide">'+params.element.value+'</div>');

+            var scaleWidth = (tooltipWidth / distance) * Math.abs(params.element.value - params.element.min);

+            params.element.nextSibling.style.left = (offsetLeft + scaleWidth - 11)+'px';

+            params.element.addEventListener("input",function(){

+                self._showTip(params.element,callback);

+            });

+            params.element.addEventListener("touchmove",function(){

+                self._showTip(params.element,callback);

+            });

+            params.element.addEventListener("touchend",function(){

+                self._hideTip(params.element);

+            });

+        },

+        _showTip: function(el,callback){

+            el.nextSibling.classList.remove("aui-hide");

+            var scaleWidth = (tooltipWidth / distance) * Math.abs(el.value - el.min);

+            el.nextSibling.style.left = (offsetLeft + scaleWidth - 11)+'px';

+            el.nextSibling.innerText = el.value;

+            callback({

+                value:el.value

+            });

+        },

+        _hideTip : function(el){

+            if (time) {

+                clearTimeout(time);

+            }

+            time = setTimeout(function() {

+                el.nextSibling.classList.add("aui-hide");

+            }, 1500);

+        }

+    }

+    window.auiRange = auiRange;

+})(window);

+

+

diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-scroll.js b/platforms/android/app/src/main/assets/www/js/lib/aui-scroll.js
new file mode 100644
index 0000000..88cd0c6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-scroll.js
@@ -0,0 +1,66 @@
+/**
+ * aui-scroll.js
+ * @author  流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	'use strict';
+	var isToBottom = false,isMoved = false;
+	var auiScroll = function (params,callback) {
+		this.extend(this.params, params);
+		this._init(params,callback);
+	}
+	auiScroll.prototype = {
+		params: {
+			listren:false,
+            distance: 100
+        },
+		_init : function(params,callback) {
+			var self = this;
+			if(self.params.listen){
+				document.body.addEventListener("touchmove", function(e){
+					self.scroll(callback);
+				});
+				document.body.addEventListener("touchend", function(e){
+					self.scroll(callback);
+				});
+			}
+			window.onscroll = function(){
+				self.scroll(callback);
+			}
+		},
+		scroll : function (callback) {
+			var self = this;
+			var clientHeight = document.documentElement.scrollTop === 0 ? document.body.clientHeight : document.documentElement.clientHeight;
+			var scrollTop = document.documentElement.scrollTop === 0 ? document.body.scrollTop : document.documentElement.scrollTop;
+			var scrollHeight = document.documentElement.scrollTop === 0 ? document.body.scrollHeight : document.documentElement.scrollHeight;
+
+			if (scrollHeight-scrollTop-self.params.distance <= window.innerHeight) {
+	        	isToBottom = true;
+	        	if(isToBottom){
+	        		callback({
+	        			"scrollTop":scrollTop,
+	        			"isToBottom":true
+	        		})
+	        	}
+	        }else{
+	        	isToBottom = false;
+	        	callback({
+        			"scrollTop":scrollTop,
+        			"isToBottom":false
+        		})
+	        }
+		},
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+	}
+	window.auiScroll = auiScroll;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-sharebox.js b/platforms/android/app/src/main/assets/www/js/lib/aui-sharebox.js
new file mode 100644
index 0000000..45b1513
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-sharebox.js
@@ -0,0 +1,119 @@
+/**
+ * aui-sharebox.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiSharebox = function() {
+    };
+    var isShow = false;
+    auiSharebox.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.col = params.col;
+            this.buttons = params.buttons;
+            this.cancelTitle = params.cancelTitle;
+            this.maskDiv;
+            this.shareBoxDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var shareboxHtml='',buttonsHtml = '';
+        	var self = this;
+            if(self.shareBoxDiv || !self.buttons)return;
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            if(!self.col)self.col = 5;
+            self.shareBoxDiv = document.createElement("div");
+            self.shareBoxDiv.className = "aui-sharebox aui-grid";
+            document.body.appendChild(self.shareBoxDiv);
+            if(self.buttons && self.buttons.length){
+                buttonsHtml = '<div class="aui-row aui-row-padded">';
+                for(var i = 0; i < self.buttons.length;i++){
+                    if(self.col == 5){
+                        buttonsHtml += '<div class="aui-col-5 aui-sharebox-btn">';
+                    }else{
+                        buttonsHtml += '<div class="aui-col-xs-'+(12/self.col)+' aui-sharebox-btn">';
+                    }
+                    if(self.buttons[i].image)buttonsHtml += '<img src="'+self.buttons[i].image+'">';
+                    if(self.buttons[i].text)buttonsHtml += '<div class="aui-grid-label">'+self.buttons[i].text+'</div>';
+                    buttonsHtml += '</div>';
+                }
+                buttonsHtml += '</div>';
+            }
+            if(self.cancelTitle){
+                buttonsHtml += '<div class="aui-sharebox-close-btn aui-border-t">'+this.cancelTitle+'</div>';
+            }
+            self.shareBoxDiv.innerHTML = buttonsHtml;
+            var actionsheetHeight = self.shareBoxDiv.offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.shareBoxDiv.style.webkitTransform = self.shareBoxDiv.style.transform = "translate3d(0,0,0)";
+            self.shareBoxDiv.style.opacity = 1;
+            self.shareBoxDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var shareboxButtons = document.querySelectorAll(".aui-sharebox-btn");
+            if(shareboxButtons && shareboxButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < shareboxButtons.length; ii++){
+                        (function(e){
+                            shareboxButtons[e].onclick = function(){
+                                if(self.buttons[e].value){
+                                    var _value = self.buttons[e].value;
+                                }else{
+                                    var _value = null;
+                                }
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonValue:_value
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+
+            }
+            document.querySelector(".aui-sharebox-close-btn").onclick = function(){self.close();return;};
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.shareBoxDiv){
+                var actionsheetHeight = self.shareBoxDiv.offsetHeight;
+                self.shareBoxDiv.style.webkitTransform = self.shareBoxDiv.style.transform = "translate3d(0,"+actionsheetHeight+"px,0)";
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.shareBoxDiv.parentNode.removeChild(self.shareBoxDiv);
+                    self.maskDiv = self.shareBoxDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiSharebox = auiSharebox;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-skin.js b/platforms/android/app/src/main/assets/www/js/lib/aui-skin.js
new file mode 100644
index 0000000..1bf6039
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-skin.js
@@ -0,0 +1,89 @@
+/**
+ * aui-skin.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiSkin = function(params) {
+    	this.extend(this.params, params);
+        this._init();
+    };
+    var fileRef;
+    auiSkin.prototype = {
+        params: {
+            name: "", //主题名字
+            skinPath:  "",//主题路径
+            default:   false, //默认是否立即使用
+            beginTime: "",//开始时间
+            endTime:   ""//结束时间
+        },
+        _init: function() {
+        	var self = this;
+            if(!self.params.name)return;
+        	if(!self.params.skinPath)return;
+            fileRef = document.createElement('link');
+            fileRef.setAttribute("rel","stylesheet");
+            fileRef.setAttribute("type","text/css");
+            fileRef.setAttribute("aui-skin-name",self.params.name);
+            fileRef.setAttribute("href",self.params.skinPath);
+            if(self.params.default){
+                document.getElementsByTagName("head")[0].appendChild(fileRef);
+            }else{
+                if(!self.params.beginTime || !self.params.endTime)return;
+                if(!self.check(self.params.beginTime,self.params.endTime))return;
+                var _date = new Date();
+                if(_date.getMinutes() < 10){
+                    var nowM = "0"+_date.getMinutes();
+                }else{
+                    var nowM = _date.getMinutes();
+                }
+                var nowTime = _date.getHours()+":"+nowM;
+                var b = parseInt(self.params.beginTime.replace(":", ''));
+                var e = parseInt(self.params.endTime.replace(":", ''));
+                var n = parseInt(nowTime.replace(":", ''));
+                if(b > e){
+                    if(n >= b || n <= e)self.setSkin();
+                }else if(b < e){
+                    if(n >= b && n <= e)self.setSkin();
+                }else{
+                    self.removeSkin();
+                }
+            }
+        },
+        setSkin:function(){
+            document.getElementsByTagName("head")[0].appendChild(fileRef);
+        },
+        removeSkin:function(){
+            var self = this;
+            if(document.querySelector("link[aui-skin-name='"+self.params.name+"']"))
+            document.querySelector("link[aui-skin-name='"+self.params.name+"']").parentNode.removeChild(document.querySelector("link[aui-skin-name='"+self.params.name+"']"));
+        },
+        check:function(beginTime,endTime){
+            var strb = beginTime.split (":");
+            if (strb.length != 2)return false;
+            var stre = endTime.split (":");
+            if (stre.length != 2)return false;
+            var b = new Date ();
+            var e = new Date ();
+            b.setHours (strb[0]);
+            b.setMinutes (strb[1]);
+            e.setHours (stre[0]);
+            e.setMinutes (stre[1]);
+            if(strb[0] > 24 || strb[0] < 0 || stre[0] > 24 || stre[0] < 0)return false;
+            if(strb[1] > 59 || strb[1] < 0 || stre[1] > 59 || stre[1] < 0)return false;
+            return true;
+        },
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+    };
+	window.auiSkin = auiSkin;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-slide.js b/platforms/android/app/src/main/assets/www/js/lib/aui-slide.js
new file mode 100644
index 0000000..2f44157
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-slide.js
@@ -0,0 +1,333 @@
+/**
+ * aui-slide.js 轮播组件
+ * @author 流浪男
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	"use strict";
+
+	var translateVal,
+		firstTouchX,
+		firstTouchY,
+		touchXDelta,
+		handleTranslateVal;
+	var touchStartTime; //开始触摸事件
+	var offsetX,
+		offsetY,
+		isScrolling;
+	// CLASS 组装
+	var	CLASS_SLIDER_NODE = "aui-slide-node",
+		CLASS_SLIDE_PAGE_WRAP = "aui-slide-page-wrap",
+		CLASS_SLIDE_PAGE = "aui-slide-page",
+		CLASS_SLIDE_PAGE_ACTIVE = "aui-slide-page-active",
+		CLASS_SLIDE_PAGE_DOT = "aui-slide-page-dot",
+		CLASS_SLIDE_PAGE_LINE = "aui-slide-page-line";
+
+	var __SLIDER_NODE = "."+CLASS_SLIDER_NODE,
+		__SLIDE_PAGE_WRAP = "."+CLASS_SLIDE_PAGE_WRAP,
+		__SLIDE_PAGE = "."+CLASS_SLIDE_PAGE,
+		__SLIDE_PAGE_ACTIVE = "."+CLASS_SLIDE_PAGE_ACTIVE;
+
+	auiSlide.prototype.options = {
+		container:'',
+		width:'auto',
+		height:'auto',
+		speed: 300, //滑动速速
+		autoPlay: 0, //自动播放
+		pageShow: true, //是否显示分页器
+		pageStyle: 'dot',
+		dotPosition: 'center',
+		friction:1, //阻力
+		loop:true,
+		currentPage:false,
+		PageCount:false
+	};
+	auiSlide.prototype._init = function(options) {
+		extend(this.options, options);
+		if(!this.options.container){
+			return;
+		}
+		this.index = 0; //索引值
+		this.continuous = true;//用于判断长度为2时的特殊处理
+		this.container = this.options.container;
+		// console.log(this.options.loop);
+		this.loop = this.options.loop;
+		this.speed = this.options.speed;
+		this.container.style.position = "relative";
+		this.container.style.width = this.options.width+"px";
+		this.container.style.height = this.options.height+"px";
+
+		var element = this.container.children[0];
+		this.slideWrap = element;
+		this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
+		if(!element || !this.slideNodeList){
+			return;
+		}
+		// this.options.pageCount(this.slideNodeList.length);
+		this.slideWrapWidth = this.slideWrap.offsetWidth;
+		this.slideNodeListLength = this.slideNodeList.length;
+
+		if (this.slideNodeListLength == 2) { //当长度为2时作特殊处理
+			element.appendChild(this.slideWrap.children[0].cloneNode(true));
+			element.appendChild(this.slideWrap.children[1].cloneNode(true));
+			this.slideWrap = element;
+			this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
+	    	this.slideNodeListLength = this.slideNodeList.length;
+	    	this.continuous = false;
+	    }
+		for (var i = 0; i < this.slideNodeListLength; i++) {
+			this.slideNodeList[i] && (this.slideNodeList[i].style.webkitTransform = this.slideNodeList[i].style.transform = "translate3d("+(this.slideWrapWidth*i)+"px,0,0)");
+		}
+
+		if(this.slideNodeListLength > 1) {
+			if(this.options.pageShow){
+				this.createPagination(0);
+				this.setPageDotPosition();
+			}
+			if(this.options.autoPlay > 500 && this.loop){
+				this.autoPlay(0);
+			}
+			this.slideWrap.addEventListener('touchstart', this.touchStart.bind(this), false);
+			this.slideWrap.addEventListener('touchmove', this.touchMove.bind(this), false);
+			this.slideWrap.addEventListener('touchend', this.touchEnd.bind(this), false);
+		}
+	};
+	// 当分页器为圆点时位置设置
+	auiSlide.prototype.setPageDotPosition = function(){
+		var self = this;
+		var pageDotPosition = self.options.dotPosition;
+		this.container.querySelector(__SLIDE_PAGE_WRAP).style.textAlign = pageDotPosition;
+	};
+	// 自动播放
+	auiSlide.prototype.autoPlay = function (index) {
+		var self = this;
+		setInterval(function(){
+			self.slideTo(self.getCircle(self.index-1), -self.slideWrapWidth, 0);
+	        self.slideTo(self.getCircle(self.index+2), self.slideWrapWidth, 0);
+	        self.slideTo(self.index, -self.slideWrapWidth, self.options.speed);
+	        self.slideTo(self.getCircle(self.index+1), 0, self.options.speed);
+	        self.index = self.getCircle(self.index+1);
+	        self.setPaginationActive(self.index);
+		}, self.options.autoPlay)
+	};
+	// 设置当前分页
+	auiSlide.prototype.setPaginationActive = function(index){
+		var self = this;
+		if(self.options.currentPage){
+			self.options.currentPage(index);
+		}
+		if(!this.container.querySelector(__SLIDE_PAGE_WRAP)){
+			return;
+		}
+		var pageList = this.container.querySelectorAll(__SLIDE_PAGE);
+		if(this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE)){
+			this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE).classList.remove(CLASS_SLIDE_PAGE_ACTIVE);
+		}
+		if(!this.continuous){
+			if(this.index == 3){
+				pageList[1].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}else if(this.index==2){
+				pageList[0].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}else{
+				pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}
+		}else{
+			pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+		}
+
+	};
+	// 创建分页器
+	auiSlide.prototype.createPagination = function(index){
+		var self = this;
+		var pageWrap = this.container.querySelector(__SLIDE_PAGE_WRAP);
+		if(!pageWrap){
+			return;
+		}
+		pageWrap.innerHTML = '';
+		var pageShowHtml = '';
+		switch (self.options.pageStyle) {
+			case "dot":// 原点
+						if (!this.continuous) {
+							for (var i = 0; i < 2; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
+							}
+						}else{
+							for (var i = 0; i < this.slideNodeListLength; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
+							}
+						}
+						pageWrap.innerHTML = pageShowHtml;
+						self.setPaginationActive(0);
+				break;
+			case "line":// 线条
+						if (!this.continuous) {
+							for (var i = 0; i < 2; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:50%"></span>';
+							}
+						}else{
+							for (var i = 0; i < this.slideNodeListLength; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:'+(100/this.slideNodeListLength)+'%"></span>';
+							}
+						}
+						pageWrap.innerHTML = pageShowHtml;
+						self.setPaginationActive(0);
+				break;
+		}
+	};
+	// 总页数
+	auiSlide.prototype.pageCount = function() {
+		var self = this;
+		return self.slideNodeList.length;
+	};
+	auiSlide.prototype.touchStart = function(event) {
+		touchStartTime = new Date() * 1;
+		firstTouchX = parseInt(event.changedTouches[0].pageX);
+		firstTouchY = parseInt(event.changedTouches[0].pageY);
+		isScrolling = undefined;
+	};
+	auiSlide.prototype.touchMove = function(event) {
+		var touchMoveObj = event.changedTouches[0],
+				touchX = parseInt(touchMoveObj.pageX);
+			touchXDelta = touchX - firstTouchX;
+			handleTranslateVal = touchXDelta/this.options.friction;
+		//  滑动位移
+		offsetX = parseInt(touchMoveObj.pageX) - firstTouchX;
+        offsetY = parseInt(touchMoveObj.pageY) - firstTouchY;
+        var direction = this.getDirection(offsetX,offsetY);
+        if ( typeof isScrolling == 'undefined') {
+			isScrolling = !!( isScrolling || Math.abs(offsetX) < Math.abs(offsetY) );
+		}
+		if(!isScrolling){
+			event.preventDefault();
+			if(!this.loop){ //不循环
+				if(!this.continuous && this.index==1 && direction=='left'){
+					return;
+				}
+				if(!this.continuous && this.index==0 && direction=='right'){
+					return;
+				}
+				if(this.index == this.slideNodeList.length-1){
+					if(handleTranslateVal <= 0){
+						return;
+					}
+					this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
+				}else if(this.index == 0){
+					if(handleTranslateVal >= 0){
+						return;
+					}
+					this.setTranslate(this.getCircle(this.index+1), this.slideWrapWidth, 0);
+				}
+			}
+
+			this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
+			this.setTranslate(this.index, handleTranslateVal , 0);
+			this.setTranslate(this.getCircle(this.index+1), handleTranslateVal + this.slideWrapWidth, 0);
+
+		}
+	};
+	auiSlide.prototype.touchEnd = function(event) {
+		var touchEndObj = event.changedTouches[0];
+		var touchEndX = parseInt(touchEndObj.pageX) - firstTouchX;
+        var touchEndY = parseInt(touchEndObj.pageY) - firstTouchY;
+		var touchEndxy = {
+				x: touchEndObj.pageX || 0,
+				y: touchEndObj.pageY || 0
+			};
+		var moveDirection = this.getDirection(touchEndX,touchEndY); //滑动方向
+		var boundary = this.slideWrapWidth/4;
+		var duration = (new Date() * 1) - touchStartTime;
+		var isValid = Number(duration) < 250 && Math.abs(offsetX) > 20 || Math.abs(offsetX) > boundary;
+		if (isScrolling) {
+			return;
+		}
+        if(isValid){
+			if(offsetX < 0){
+				if(!this.loop && this.index == this.slideNodeList.length-1){
+					return;
+				}
+
+				if(!this.loop && !this.continuous && this.index==1){
+					return;
+				}
+
+	        	if(offsetX < -boundary && moveDirection == 'left'){
+	        		// left
+					this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, 0);
+		            this.slideTo(this.getCircle(this.index+2), this.slideWrapWidth, 0);
+		            this.slideTo(this.index, -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), 0, this.speed);
+		            this.index = this.getCircle(this.index+1);
+				}else{
+					// this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.index, 0, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+				}
+	        }else if(offsetX > 0){
+	        	if(!this.loop && this.index == 0){
+					return;
+				}
+				if(!this.loop && !this.continuous && this.index==0){
+					return;
+				}
+	        	if(offsetX > boundary && moveDirection == 'right'){
+	        		// right
+		        	this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, 0);
+		            this.slideTo(this.getCircle(this.index-2), -this.slideWrapWidth, 0);
+		            this.slideTo(this.index, this.slideWrapWidth, this.speed);
+		            this.slideTo(this.getCircle(this.index-1), 0, this.speed);
+		            this.index = this.getCircle(this.index-1);
+	        	}else{
+	        		// this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.index, 0, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+	        	}
+	        }
+        }else{
+        	if(offsetX){
+        		this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+	            this.slideTo(this.index, 0, this.speed);
+	            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+        	}
+
+        }
+        this.setPaginationActive(this.index);
+	};
+	auiSlide.prototype.setTranslate = function (index,dist,speed){
+		if(this.slideNodeList[index]){
+			this.slideNodeList[index].style.webkitTransitionDuration =
+	    	this.slideNodeList[index].style.transitionDuration = speed + 'ms';
+	    	this.slideNodeList[index].style.webkitTransform =
+	    	this.slideNodeList[index].style.transform = "translate3d("+dist+"px,0,0)";
+		}
+	};
+	auiSlide.prototype.slideTo = function (index, dist, speed) {
+		this.setTranslate(index, dist, speed);
+		// index = dist;
+	};
+	auiSlide.prototype.getCircle = function (index) {
+	    return (this.slideNodeListLength + (index % this.slideNodeListLength)) % this.slideNodeListLength;
+	};
+	auiSlide.prototype.getDirection = function(x, y) {
+		if (x === y) { return '';}
+		if (Math.abs(x) >= Math.abs(y)) {
+            return x > 0 ? 'right' : 'left';
+        } else {
+           	return y > 0 ? 'down' : 'up';
+        }
+	}
+	function extend (a, b) {
+		for (var key in b) {
+		  	if (b.hasOwnProperty(key)) {
+		  		a[key] = b[key];
+		  	}
+	  	}
+	  	return a;
+	}
+	function auiSlide (options) {
+		this._init(options);
+	}
+	window.auiSlide = auiSlide;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-tab.js b/platforms/android/app/src/main/assets/www/js/lib/aui-tab.js
new file mode 100644
index 0000000..cb228c4
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-tab.js
@@ -0,0 +1,69 @@
+/**
+ * aui-tab.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiTab = function(params,callback) {
+    	this.extend(this.params, params);
+        this._init(callback);
+    };
+    var tabItems;
+    auiTab.prototype = {
+        params: {
+            element: false,
+            index: 1, //默认选中
+            repeatClick: false //是否允许重复点击
+        },
+        _init: function(callback) {
+        	var self = this;
+        	if(!self.params.element || self.params.element.nodeType!=1){
+        		return;
+        	}
+        	tabItems = self.params.element.children;
+        	if(tabItems){
+        		self.setActive();
+        		for(var i=0; i<tabItems.length; i++){
+        			tabItems[i].setAttribute("tapmode","");
+        			tabItems[i].setAttribute("data-item-order",i);
+        			tabItems[i].onclick = function(e){
+                        if(!self.params.repeatClick){
+                            if(this.className.indexOf("aui-active") > -1)return;
+                        }
+        				if(callback){
+                            callback({
+                                index: parseInt(this.getAttribute("data-item-order"))+1,
+                                dom:this
+                            })
+                        };
+        				this.parentNode.querySelector(".aui-active").classList.remove("aui-active");
+            			this.classList.add("aui-active");
+        			}
+        		}
+        	}
+        },
+        setRepeat:function(value){
+            var self = this;
+            self.params.repeatClick = value ? value : false;
+        },
+        setActive: function(index){
+        	var self = this;
+        	index = index ? index : self.params.index;
+        	var _tab = tabItems[index-1];
+        	if(_tab.parentNode.querySelector(".aui-active"))_tab.parentNode.querySelector(".aui-active").classList.remove("aui-active");
+        	_tab.classList.add("aui-active");
+        },
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+    };
+	window.auiTab = auiTab;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/aui-toast.js b/platforms/android/app/src/main/assets/www/js/lib/aui-toast.js
new file mode 100644
index 0000000..68d41f6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/aui-toast.js
@@ -0,0 +1,92 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiToast = function() {
+        // this.create();
+    };
+    var isShow = false;
+    auiToast.prototype = {
+        create: function(params,callback) {
+            var self = this;
+            var toastHtml = '';
+            switch (params.type) {
+                case "success":
+                    var iconHtml = '<i class="aui-iconfont aui-icon-correct"></i>';
+                    break;
+                case "fail":
+                    var iconHtml = '<i class="aui-iconfont aui-icon-close"></i>';
+                    break;
+                case "custom":
+                    var iconHtml = params.html;
+                    break;
+                case "loading":
+                    var iconHtml = '<div class="aui-toast-loading"></div>';
+                    break;
+            }
+
+            var titleHtml = params.title ? '<div class="aui-toast-content">'+params.title+'</div>' : '';
+            toastHtml = '<div class="aui-toast">'+iconHtml+titleHtml+'</div>';
+            if(document.querySelector(".aui-toast"))return;
+            document.body.insertAdjacentHTML('beforeend', toastHtml);
+            var duration = params.duration ? params.duration : "2000";
+            self.show();
+            if(params.type == 'loading'){
+                if(callback){
+                    callback({
+                        status: "success"
+                    });
+                };
+            }else{
+                setTimeout(function(){
+                    self.hide();
+                }, duration)
+            }
+        },
+        show: function(){
+            var self = this;
+            document.querySelector(".aui-toast").style.display = "block";
+            document.querySelector(".aui-toast").style.marginTop =  "-"+Math.round(document.querySelector(".aui-toast").offsetHeight/2)+"px";
+            if(document.querySelector(".aui-toast"))return;
+        },
+        hide: function(){
+            var self = this;
+            if(document.querySelector(".aui-toast")){
+                document.querySelector(".aui-toast").parentNode.removeChild(document.querySelector(".aui-toast"));
+            }
+        },
+        remove: function(){
+            if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+            if(document.querySelector(".aui-mask")){
+                document.querySelector(".aui-mask").classList.remove("aui-mask-out");
+            }
+            return true;
+        },
+        success: function(params,callback){
+            var self = this;
+            params.type = "success";
+            return self.create(params,callback);
+        },
+        fail: function(params,callback){
+            var self = this;
+            params.type = "fail";
+            return self.create(params,callback);
+        },
+        custom:function(params,callback){
+            var self = this;
+            params.type = "custom";
+            return self.create(params,callback);
+        },
+        loading:function(params,callback){
+            var self = this;
+            params.type = "loading";
+            return self.create(params,callback);
+        }
+    };
+    window.auiToast = auiToast;
+})(window);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/city-picker.js b/platforms/android/app/src/main/assets/www/js/lib/city-picker.js
new file mode 100755
index 0000000..129755d
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/city-picker.js
@@ -0,0 +1,16713 @@
+// jshint ignore: start
++function($){
+
+$.rawCitiesData = [
+  {
+    "name":"北京",
+    "code":"110000",
+    "sub": [
+      {
+        "name": "北京市",
+        "code": "110000",
+        "sub":[
+            {
+              "name":"东城区",
+              "code":"110101"
+            },
+            {
+              "name":"西城区",
+              "code":"110102"
+            },
+            {
+              "name":"朝阳区",
+              "code":"110105"
+            },
+            {
+              "name":"丰台区",
+              "code":"110106"
+            },
+            {
+              "name":"石景山区",
+              "code":"110107"
+            },
+            {
+              "name":"海淀区",
+              "code":"110108"
+            },
+            {
+              "name":"门头沟区",
+              "code":"110109"
+            },
+            {
+              "name":"房山区",
+              "code":"110111"
+            },
+            {
+              "name":"通州区",
+              "code":"110112"
+            },
+            {
+              "name":"顺义区",
+              "code":"110113"
+            },
+            {
+              "name":"昌平区",
+              "code":"110114"
+            },
+            {
+              "name":"大兴区",
+              "code":"110115"
+            },
+            {
+              "name":"怀柔区",
+              "code":"110116"
+            },
+            {
+              "name":"平谷区",
+              "code":"110117"
+            },
+            {
+              "name":"密云县",
+              "code":"110228"
+            },
+            {
+              "name":"延庆县",
+              "code":"110229"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"天津",
+    "code":"120000",
+    "sub": [
+      {
+        "name": "天津市",
+        "code": "120000",
+        "sub":[
+            {
+              "name":"和平区",
+              "code":"120101"
+            },
+            {
+              "name":"河东区",
+              "code":"120102"
+            },
+            {
+              "name":"河西区",
+              "code":"120103"
+            },
+            {
+              "name":"南开区",
+              "code":"120104"
+            },
+            {
+              "name":"河北区",
+              "code":"120105"
+            },
+            {
+              "name":"红桥区",
+              "code":"120106"
+            },
+            {
+              "name":"东丽区",
+              "code":"120110"
+            },
+            {
+              "name":"西青区",
+              "code":"120111"
+            },
+            {
+              "name":"津南区",
+              "code":"120112"
+            },
+            {
+              "name":"北辰区",
+              "code":"120113"
+            },
+            {
+              "name":"武清区",
+              "code":"120114"
+            },
+            {
+              "name":"宝坻区",
+              "code":"120115"
+            },
+            {
+              "name":"滨海新区",
+              "code":"120116"
+            },
+            {
+              "name":"宁河县",
+              "code":"120221"
+            },
+            {
+              "name":"静海县",
+              "code":"120223"
+            },
+            {
+              "name":"蓟县",
+              "code":"120225"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"河北省",
+    "code":"130000",
+    "sub":[
+      {
+        "name":"石家庄市",
+        "code":"130100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130101"
+          },
+          {
+            "name":"长安区",
+            "code":"130102"
+          },
+          {
+            "name":"桥西区",
+            "code":"130104"
+          },
+          {
+            "name":"新华区",
+            "code":"130105"
+          },
+          {
+            "name":"井陉矿区",
+            "code":"130107"
+          },
+          {
+            "name":"裕华区",
+            "code":"130108"
+          },
+          {
+            "name":"藁城区",
+            "code":"130109"
+          },
+          {
+            "name":"鹿泉区",
+            "code":"130110"
+          },
+          {
+            "name":"栾城区",
+            "code":"130111"
+          },
+          {
+            "name":"井陉县",
+            "code":"130121"
+          },
+          {
+            "name":"正定县",
+            "code":"130123"
+          },
+          {
+            "name":"行唐县",
+            "code":"130125"
+          },
+          {
+            "name":"灵寿县",
+            "code":"130126"
+          },
+          {
+            "name":"高邑县",
+            "code":"130127"
+          },
+          {
+            "name":"深泽县",
+            "code":"130128"
+          },
+          {
+            "name":"赞皇县",
+            "code":"130129"
+          },
+          {
+            "name":"无极县",
+            "code":"130130"
+          },
+          {
+            "name":"平山县",
+            "code":"130131"
+          },
+          {
+            "name":"元氏县",
+            "code":"130132"
+          },
+          {
+            "name":"赵县",
+            "code":"130133"
+          },
+          {
+            "name":"辛集市",
+            "code":"130181"
+          },
+          {
+            "name":"晋州市",
+            "code":"130183"
+          },
+          {
+            "name":"新乐市",
+            "code":"130184"
+          }
+        ]
+      },
+      {
+        "name":"唐山市",
+        "code":"130200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130201"
+          },
+          {
+            "name":"路南区",
+            "code":"130202"
+          },
+          {
+            "name":"路北区",
+            "code":"130203"
+          },
+          {
+            "name":"古冶区",
+            "code":"130204"
+          },
+          {
+            "name":"开平区",
+            "code":"130205"
+          },
+          {
+            "name":"丰南区",
+            "code":"130207"
+          },
+          {
+            "name":"丰润区",
+            "code":"130208"
+          },
+          {
+            "name":"曹妃甸区",
+            "code":"130209"
+          },
+          {
+            "name":"滦县",
+            "code":"130223"
+          },
+          {
+            "name":"滦南县",
+            "code":"130224"
+          },
+          {
+            "name":"乐亭县",
+            "code":"130225"
+          },
+          {
+            "name":"迁西县",
+            "code":"130227"
+          },
+          {
+            "name":"玉田县",
+            "code":"130229"
+          },
+          {
+            "name":"遵化市",
+            "code":"130281"
+          },
+          {
+            "name":"迁安市",
+            "code":"130283"
+          }
+        ]
+      },
+      {
+        "name":"秦皇岛市",
+        "code":"130300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130301"
+          },
+          {
+            "name":"海港区",
+            "code":"130302"
+          },
+          {
+            "name":"山海关区",
+            "code":"130303"
+          },
+          {
+            "name":"北戴河区",
+            "code":"130304"
+          },
+          {
+            "name":"青龙满族自治县",
+            "code":"130321"
+          },
+          {
+            "name":"昌黎县",
+            "code":"130322"
+          },
+          {
+            "name":"抚宁县",
+            "code":"130323"
+          },
+          {
+            "name":"卢龙县",
+            "code":"130324"
+          }
+        ]
+      },
+      {
+        "name":"邯郸市",
+        "code":"130400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130401"
+          },
+          {
+            "name":"邯山区",
+            "code":"130402"
+          },
+          {
+            "name":"丛台区",
+            "code":"130403"
+          },
+          {
+            "name":"复兴区",
+            "code":"130404"
+          },
+          {
+            "name":"峰峰矿区",
+            "code":"130406"
+          },
+          {
+            "name":"邯郸县",
+            "code":"130421"
+          },
+          {
+            "name":"临漳县",
+            "code":"130423"
+          },
+          {
+            "name":"成安县",
+            "code":"130424"
+          },
+          {
+            "name":"大名县",
+            "code":"130425"
+          },
+          {
+            "name":"涉县",
+            "code":"130426"
+          },
+          {
+            "name":"磁县",
+            "code":"130427"
+          },
+          {
+            "name":"肥乡县",
+            "code":"130428"
+          },
+          {
+            "name":"永年县",
+            "code":"130429"
+          },
+          {
+            "name":"邱县",
+            "code":"130430"
+          },
+          {
+            "name":"鸡泽县",
+            "code":"130431"
+          },
+          {
+            "name":"广平县",
+            "code":"130432"
+          },
+          {
+            "name":"馆陶县",
+            "code":"130433"
+          },
+          {
+            "name":"魏县",
+            "code":"130434"
+          },
+          {
+            "name":"曲周县",
+            "code":"130435"
+          },
+          {
+            "name":"武安市",
+            "code":"130481"
+          }
+        ]
+      },
+      {
+        "name":"邢台市",
+        "code":"130500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130501"
+          },
+          {
+            "name":"桥东区",
+            "code":"130502"
+          },
+          {
+            "name":"桥西区",
+            "code":"130503"
+          },
+          {
+            "name":"邢台县",
+            "code":"130521"
+          },
+          {
+            "name":"临城县",
+            "code":"130522"
+          },
+          {
+            "name":"内丘县",
+            "code":"130523"
+          },
+          {
+            "name":"柏乡县",
+            "code":"130524"
+          },
+          {
+            "name":"隆尧县",
+            "code":"130525"
+          },
+          {
+            "name":"任县",
+            "code":"130526"
+          },
+          {
+            "name":"南和县",
+            "code":"130527"
+          },
+          {
+            "name":"宁晋县",
+            "code":"130528"
+          },
+          {
+            "name":"巨鹿县",
+            "code":"130529"
+          },
+          {
+            "name":"新河县",
+            "code":"130530"
+          },
+          {
+            "name":"广宗县",
+            "code":"130531"
+          },
+          {
+            "name":"平乡县",
+            "code":"130532"
+          },
+          {
+            "name":"威县",
+            "code":"130533"
+          },
+          {
+            "name":"清河县",
+            "code":"130534"
+          },
+          {
+            "name":"临西县",
+            "code":"130535"
+          },
+          {
+            "name":"南宫市",
+            "code":"130581"
+          },
+          {
+            "name":"沙河市",
+            "code":"130582"
+          }
+        ]
+      },
+      {
+        "name":"保定市",
+        "code":"130600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130601"
+          },
+          {
+            "name":"新市区",
+            "code":"130602"
+          },
+          {
+            "name":"北市区",
+            "code":"130603"
+          },
+          {
+            "name":"南市区",
+            "code":"130604"
+          },
+          {
+            "name":"满城县",
+            "code":"130621"
+          },
+          {
+            "name":"清苑县",
+            "code":"130622"
+          },
+          {
+            "name":"涞水县",
+            "code":"130623"
+          },
+          {
+            "name":"阜平县",
+            "code":"130624"
+          },
+          {
+            "name":"徐水县",
+            "code":"130625"
+          },
+          {
+            "name":"定兴县",
+            "code":"130626"
+          },
+          {
+            "name":"唐县",
+            "code":"130627"
+          },
+          {
+            "name":"高阳县",
+            "code":"130628"
+          },
+          {
+            "name":"容城县",
+            "code":"130629"
+          },
+          {
+            "name":"涞源县",
+            "code":"130630"
+          },
+          {
+            "name":"望都县",
+            "code":"130631"
+          },
+          {
+            "name":"安新县",
+            "code":"130632"
+          },
+          {
+            "name":"易县",
+            "code":"130633"
+          },
+          {
+            "name":"曲阳县",
+            "code":"130634"
+          },
+          {
+            "name":"蠡县",
+            "code":"130635"
+          },
+          {
+            "name":"顺平县",
+            "code":"130636"
+          },
+          {
+            "name":"博野县",
+            "code":"130637"
+          },
+          {
+            "name":"雄县",
+            "code":"130638"
+          },
+          {
+            "name":"涿州市",
+            "code":"130681"
+          },
+          {
+            "name":"定州市",
+            "code":"130682"
+          },
+          {
+            "name":"安国市",
+            "code":"130683"
+          },
+          {
+            "name":"高碑店市",
+            "code":"130684"
+          }
+        ]
+      },
+      {
+        "name":"张家口市",
+        "code":"130700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130701"
+          },
+          {
+            "name":"桥东区",
+            "code":"130702"
+          },
+          {
+            "name":"桥西区",
+            "code":"130703"
+          },
+          {
+            "name":"宣化区",
+            "code":"130705"
+          },
+          {
+            "name":"下花园区",
+            "code":"130706"
+          },
+          {
+            "name":"宣化县",
+            "code":"130721"
+          },
+          {
+            "name":"张北县",
+            "code":"130722"
+          },
+          {
+            "name":"康保县",
+            "code":"130723"
+          },
+          {
+            "name":"沽源县",
+            "code":"130724"
+          },
+          {
+            "name":"尚义县",
+            "code":"130725"
+          },
+          {
+            "name":"蔚县",
+            "code":"130726"
+          },
+          {
+            "name":"阳原县",
+            "code":"130727"
+          },
+          {
+            "name":"怀安县",
+            "code":"130728"
+          },
+          {
+            "name":"万全县",
+            "code":"130729"
+          },
+          {
+            "name":"怀来县",
+            "code":"130730"
+          },
+          {
+            "name":"涿鹿县",
+            "code":"130731"
+          },
+          {
+            "name":"赤城县",
+            "code":"130732"
+          },
+          {
+            "name":"崇礼县",
+            "code":"130733"
+          }
+        ]
+      },
+      {
+        "name":"承德市",
+        "code":"130800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130801"
+          },
+          {
+            "name":"双桥区",
+            "code":"130802"
+          },
+          {
+            "name":"双滦区",
+            "code":"130803"
+          },
+          {
+            "name":"鹰手营子矿区",
+            "code":"130804"
+          },
+          {
+            "name":"承德县",
+            "code":"130821"
+          },
+          {
+            "name":"兴隆县",
+            "code":"130822"
+          },
+          {
+            "name":"平泉县",
+            "code":"130823"
+          },
+          {
+            "name":"滦平县",
+            "code":"130824"
+          },
+          {
+            "name":"隆化县",
+            "code":"130825"
+          },
+          {
+            "name":"丰宁满族自治县",
+            "code":"130826"
+          },
+          {
+            "name":"宽城满族自治县",
+            "code":"130827"
+          },
+          {
+            "name":"围场满族蒙古族自治县",
+            "code":"130828"
+          }
+        ]
+      },
+      {
+        "name":"沧州市",
+        "code":"130900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130901"
+          },
+          {
+            "name":"新华区",
+            "code":"130902"
+          },
+          {
+            "name":"运河区",
+            "code":"130903"
+          },
+          {
+            "name":"沧县",
+            "code":"130921"
+          },
+          {
+            "name":"青县",
+            "code":"130922"
+          },
+          {
+            "name":"东光县",
+            "code":"130923"
+          },
+          {
+            "name":"海兴县",
+            "code":"130924"
+          },
+          {
+            "name":"盐山县",
+            "code":"130925"
+          },
+          {
+            "name":"肃宁县",
+            "code":"130926"
+          },
+          {
+            "name":"南皮县",
+            "code":"130927"
+          },
+          {
+            "name":"吴桥县",
+            "code":"130928"
+          },
+          {
+            "name":"献县",
+            "code":"130929"
+          },
+          {
+            "name":"孟村回族自治县",
+            "code":"130930"
+          },
+          {
+            "name":"泊头市",
+            "code":"130981"
+          },
+          {
+            "name":"任丘市",
+            "code":"130982"
+          },
+          {
+            "name":"黄骅市",
+            "code":"130983"
+          },
+          {
+            "name":"河间市",
+            "code":"130984"
+          }
+        ]
+      },
+      {
+        "name":"廊坊市",
+        "code":"131000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"131001"
+          },
+          {
+            "name":"安次区",
+            "code":"131002"
+          },
+          {
+            "name":"广阳区",
+            "code":"131003"
+          },
+          {
+            "name":"固安县",
+            "code":"131022"
+          },
+          {
+            "name":"永清县",
+            "code":"131023"
+          },
+          {
+            "name":"香河县",
+            "code":"131024"
+          },
+          {
+            "name":"大城县",
+            "code":"131025"
+          },
+          {
+            "name":"文安县",
+            "code":"131026"
+          },
+          {
+            "name":"大厂回族自治县",
+            "code":"131028"
+          },
+          {
+            "name":"霸州市",
+            "code":"131081"
+          },
+          {
+            "name":"三河市",
+            "code":"131082"
+          }
+        ]
+      },
+      {
+        "name":"衡水市",
+        "code":"131100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"131101"
+          },
+          {
+            "name":"桃城区",
+            "code":"131102"
+          },
+          {
+            "name":"枣强县",
+            "code":"131121"
+          },
+          {
+            "name":"武邑县",
+            "code":"131122"
+          },
+          {
+            "name":"武强县",
+            "code":"131123"
+          },
+          {
+            "name":"饶阳县",
+            "code":"131124"
+          },
+          {
+            "name":"安平县",
+            "code":"131125"
+          },
+          {
+            "name":"故城县",
+            "code":"131126"
+          },
+          {
+            "name":"景县",
+            "code":"131127"
+          },
+          {
+            "name":"阜城县",
+            "code":"131128"
+          },
+          {
+            "name":"冀州市",
+            "code":"131181"
+          },
+          {
+            "name":"深州市",
+            "code":"131182"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"山西省",
+    "code":"140000",
+    "sub":[
+      {
+        "name":"太原市",
+        "code":"140100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140101"
+          },
+          {
+            "name":"小店区",
+            "code":"140105"
+          },
+          {
+            "name":"迎泽区",
+            "code":"140106"
+          },
+          {
+            "name":"杏花岭区",
+            "code":"140107"
+          },
+          {
+            "name":"尖草坪区",
+            "code":"140108"
+          },
+          {
+            "name":"万柏林区",
+            "code":"140109"
+          },
+          {
+            "name":"晋源区",
+            "code":"140110"
+          },
+          {
+            "name":"清徐县",
+            "code":"140121"
+          },
+          {
+            "name":"阳曲县",
+            "code":"140122"
+          },
+          {
+            "name":"娄烦县",
+            "code":"140123"
+          },
+          {
+            "name":"古交市",
+            "code":"140181"
+          }
+        ]
+      },
+      {
+        "name":"大同市",
+        "code":"140200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140201"
+          },
+          {
+            "name":"城区",
+            "code":"140202"
+          },
+          {
+            "name":"矿区",
+            "code":"140203"
+          },
+          {
+            "name":"南郊区",
+            "code":"140211"
+          },
+          {
+            "name":"新荣区",
+            "code":"140212"
+          },
+          {
+            "name":"阳高县",
+            "code":"140221"
+          },
+          {
+            "name":"天镇县",
+            "code":"140222"
+          },
+          {
+            "name":"广灵县",
+            "code":"140223"
+          },
+          {
+            "name":"灵丘县",
+            "code":"140224"
+          },
+          {
+            "name":"浑源县",
+            "code":"140225"
+          },
+          {
+            "name":"左云县",
+            "code":"140226"
+          },
+          {
+            "name":"大同县",
+            "code":"140227"
+          }
+        ]
+      },
+      {
+        "name":"阳泉市",
+        "code":"140300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140301"
+          },
+          {
+            "name":"城区",
+            "code":"140302"
+          },
+          {
+            "name":"矿区",
+            "code":"140303"
+          },
+          {
+            "name":"郊区",
+            "code":"140311"
+          },
+          {
+            "name":"平定县",
+            "code":"140321"
+          },
+          {
+            "name":"盂县",
+            "code":"140322"
+          }
+        ]
+      },
+      {
+        "name":"长治市",
+        "code":"140400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140401"
+          },
+          {
+            "name":"城区",
+            "code":"140402"
+          },
+          {
+            "name":"郊区",
+            "code":"140411"
+          },
+          {
+            "name":"长治县",
+            "code":"140421"
+          },
+          {
+            "name":"襄垣县",
+            "code":"140423"
+          },
+          {
+            "name":"屯留县",
+            "code":"140424"
+          },
+          {
+            "name":"平顺县",
+            "code":"140425"
+          },
+          {
+            "name":"黎城县",
+            "code":"140426"
+          },
+          {
+            "name":"壶关县",
+            "code":"140427"
+          },
+          {
+            "name":"长子县",
+            "code":"140428"
+          },
+          {
+            "name":"武乡县",
+            "code":"140429"
+          },
+          {
+            "name":"沁县",
+            "code":"140430"
+          },
+          {
+            "name":"沁源县",
+            "code":"140431"
+          },
+          {
+            "name":"潞城市",
+            "code":"140481"
+          }
+        ]
+      },
+      {
+        "name":"晋城市",
+        "code":"140500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140501"
+          },
+          {
+            "name":"城区",
+            "code":"140502"
+          },
+          {
+            "name":"沁水县",
+            "code":"140521"
+          },
+          {
+            "name":"阳城县",
+            "code":"140522"
+          },
+          {
+            "name":"陵川县",
+            "code":"140524"
+          },
+          {
+            "name":"泽州县",
+            "code":"140525"
+          },
+          {
+            "name":"高平市",
+            "code":"140581"
+          }
+        ]
+      },
+      {
+        "name":"朔州市",
+        "code":"140600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140601"
+          },
+          {
+            "name":"朔城区",
+            "code":"140602"
+          },
+          {
+            "name":"平鲁区",
+            "code":"140603"
+          },
+          {
+            "name":"山阴县",
+            "code":"140621"
+          },
+          {
+            "name":"应县",
+            "code":"140622"
+          },
+          {
+            "name":"右玉县",
+            "code":"140623"
+          },
+          {
+            "name":"怀仁县",
+            "code":"140624"
+          }
+        ]
+      },
+      {
+        "name":"晋中市",
+        "code":"140700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140701"
+          },
+          {
+            "name":"榆次区",
+            "code":"140702"
+          },
+          {
+            "name":"榆社县",
+            "code":"140721"
+          },
+          {
+            "name":"左权县",
+            "code":"140722"
+          },
+          {
+            "name":"和顺县",
+            "code":"140723"
+          },
+          {
+            "name":"昔阳县",
+            "code":"140724"
+          },
+          {
+            "name":"寿阳县",
+            "code":"140725"
+          },
+          {
+            "name":"太谷县",
+            "code":"140726"
+          },
+          {
+            "name":"祁县",
+            "code":"140727"
+          },
+          {
+            "name":"平遥县",
+            "code":"140728"
+          },
+          {
+            "name":"灵石县",
+            "code":"140729"
+          },
+          {
+            "name":"介休市",
+            "code":"140781"
+          }
+        ]
+      },
+      {
+        "name":"运城市",
+        "code":"140800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140801"
+          },
+          {
+            "name":"盐湖区",
+            "code":"140802"
+          },
+          {
+            "name":"临猗县",
+            "code":"140821"
+          },
+          {
+            "name":"万荣县",
+            "code":"140822"
+          },
+          {
+            "name":"闻喜县",
+            "code":"140823"
+          },
+          {
+            "name":"稷山县",
+            "code":"140824"
+          },
+          {
+            "name":"新绛县",
+            "code":"140825"
+          },
+          {
+            "name":"绛县",
+            "code":"140826"
+          },
+          {
+            "name":"垣曲县",
+            "code":"140827"
+          },
+          {
+            "name":"夏县",
+            "code":"140828"
+          },
+          {
+            "name":"平陆县",
+            "code":"140829"
+          },
+          {
+            "name":"芮城县",
+            "code":"140830"
+          },
+          {
+            "name":"永济市",
+            "code":"140881"
+          },
+          {
+            "name":"河津市",
+            "code":"140882"
+          }
+        ]
+      },
+      {
+        "name":"忻州市",
+        "code":"140900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140901"
+          },
+          {
+            "name":"忻府区",
+            "code":"140902"
+          },
+          {
+            "name":"定襄县",
+            "code":"140921"
+          },
+          {
+            "name":"五台县",
+            "code":"140922"
+          },
+          {
+            "name":"代县",
+            "code":"140923"
+          },
+          {
+            "name":"繁峙县",
+            "code":"140924"
+          },
+          {
+            "name":"宁武县",
+            "code":"140925"
+          },
+          {
+            "name":"静乐县",
+            "code":"140926"
+          },
+          {
+            "name":"神池县",
+            "code":"140927"
+          },
+          {
+            "name":"五寨县",
+            "code":"140928"
+          },
+          {
+            "name":"岢岚县",
+            "code":"140929"
+          },
+          {
+            "name":"河曲县",
+            "code":"140930"
+          },
+          {
+            "name":"保德县",
+            "code":"140931"
+          },
+          {
+            "name":"偏关县",
+            "code":"140932"
+          },
+          {
+            "name":"原平市",
+            "code":"140981"
+          }
+        ]
+      },
+      {
+        "name":"临汾市",
+        "code":"141000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"141001"
+          },
+          {
+            "name":"尧都区",
+            "code":"141002"
+          },
+          {
+            "name":"曲沃县",
+            "code":"141021"
+          },
+          {
+            "name":"翼城县",
+            "code":"141022"
+          },
+          {
+            "name":"襄汾县",
+            "code":"141023"
+          },
+          {
+            "name":"洪洞县",
+            "code":"141024"
+          },
+          {
+            "name":"古县",
+            "code":"141025"
+          },
+          {
+            "name":"安泽县",
+            "code":"141026"
+          },
+          {
+            "name":"浮山县",
+            "code":"141027"
+          },
+          {
+            "name":"吉县",
+            "code":"141028"
+          },
+          {
+            "name":"乡宁县",
+            "code":"141029"
+          },
+          {
+            "name":"大宁县",
+            "code":"141030"
+          },
+          {
+            "name":"隰县",
+            "code":"141031"
+          },
+          {
+            "name":"永和县",
+            "code":"141032"
+          },
+          {
+            "name":"蒲县",
+            "code":"141033"
+          },
+          {
+            "name":"汾西县",
+            "code":"141034"
+          },
+          {
+            "name":"侯马市",
+            "code":"141081"
+          },
+          {
+            "name":"霍州市",
+            "code":"141082"
+          }
+        ]
+      },
+      {
+        "name":"吕梁市",
+        "code":"141100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"141101"
+          },
+          {
+            "name":"离石区",
+            "code":"141102"
+          },
+          {
+            "name":"文水县",
+            "code":"141121"
+          },
+          {
+            "name":"交城县",
+            "code":"141122"
+          },
+          {
+            "name":"兴县",
+            "code":"141123"
+          },
+          {
+            "name":"临县",
+            "code":"141124"
+          },
+          {
+            "name":"柳林县",
+            "code":"141125"
+          },
+          {
+            "name":"石楼县",
+            "code":"141126"
+          },
+          {
+            "name":"岚县",
+            "code":"141127"
+          },
+          {
+            "name":"方山县",
+            "code":"141128"
+          },
+          {
+            "name":"中阳县",
+            "code":"141129"
+          },
+          {
+            "name":"交口县",
+            "code":"141130"
+          },
+          {
+            "name":"孝义市",
+            "code":"141181"
+          },
+          {
+            "name":"汾阳市",
+            "code":"141182"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"内蒙古自治区",
+    "code":"150000",
+    "sub":[
+      {
+        "name":"呼和浩特市",
+        "code":"150100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150101"
+          },
+          {
+            "name":"新城区",
+            "code":"150102"
+          },
+          {
+            "name":"回民区",
+            "code":"150103"
+          },
+          {
+            "name":"玉泉区",
+            "code":"150104"
+          },
+          {
+            "name":"赛罕区",
+            "code":"150105"
+          },
+          {
+            "name":"土默特左旗",
+            "code":"150121"
+          },
+          {
+            "name":"托克托县",
+            "code":"150122"
+          },
+          {
+            "name":"和林格尔县",
+            "code":"150123"
+          },
+          {
+            "name":"清水河县",
+            "code":"150124"
+          },
+          {
+            "name":"武川县",
+            "code":"150125"
+          }
+        ]
+      },
+      {
+        "name":"包头市",
+        "code":"150200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150201"
+          },
+          {
+            "name":"东河区",
+            "code":"150202"
+          },
+          {
+            "name":"昆都仑区",
+            "code":"150203"
+          },
+          {
+            "name":"青山区",
+            "code":"150204"
+          },
+          {
+            "name":"石拐区",
+            "code":"150205"
+          },
+          {
+            "name":"白云鄂博矿区",
+            "code":"150206"
+          },
+          {
+            "name":"九原区",
+            "code":"150207"
+          },
+          {
+            "name":"土默特右旗",
+            "code":"150221"
+          },
+          {
+            "name":"固阳县",
+            "code":"150222"
+          },
+          {
+            "name":"达尔罕茂明安联合旗",
+            "code":"150223"
+          }
+        ]
+      },
+      {
+        "name":"乌海市",
+        "code":"150300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150301"
+          },
+          {
+            "name":"海勃湾区",
+            "code":"150302"
+          },
+          {
+            "name":"海南区",
+            "code":"150303"
+          },
+          {
+            "name":"乌达区",
+            "code":"150304"
+          }
+        ]
+      },
+      {
+        "name":"赤峰市",
+        "code":"150400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150401"
+          },
+          {
+            "name":"红山区",
+            "code":"150402"
+          },
+          {
+            "name":"元宝山区",
+            "code":"150403"
+          },
+          {
+            "name":"松山区",
+            "code":"150404"
+          },
+          {
+            "name":"阿鲁科尔沁旗",
+            "code":"150421"
+          },
+          {
+            "name":"巴林左旗",
+            "code":"150422"
+          },
+          {
+            "name":"巴林右旗",
+            "code":"150423"
+          },
+          {
+            "name":"林西县",
+            "code":"150424"
+          },
+          {
+            "name":"克什克腾旗",
+            "code":"150425"
+          },
+          {
+            "name":"翁牛特旗",
+            "code":"150426"
+          },
+          {
+            "name":"喀喇沁旗",
+            "code":"150428"
+          },
+          {
+            "name":"宁城县",
+            "code":"150429"
+          },
+          {
+            "name":"敖汉旗",
+            "code":"150430"
+          }
+        ]
+      },
+      {
+        "name":"通辽市",
+        "code":"150500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150501"
+          },
+          {
+            "name":"科尔沁区",
+            "code":"150502"
+          },
+          {
+            "name":"科尔沁左翼中旗",
+            "code":"150521"
+          },
+          {
+            "name":"科尔沁左翼后旗",
+            "code":"150522"
+          },
+          {
+            "name":"开鲁县",
+            "code":"150523"
+          },
+          {
+            "name":"库伦旗",
+            "code":"150524"
+          },
+          {
+            "name":"奈曼旗",
+            "code":"150525"
+          },
+          {
+            "name":"扎鲁特旗",
+            "code":"150526"
+          },
+          {
+            "name":"霍林郭勒市",
+            "code":"150581"
+          }
+        ]
+      },
+      {
+        "name":"鄂尔多斯市",
+        "code":"150600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150601"
+          },
+          {
+            "name":"东胜区",
+            "code":"150602"
+          },
+          {
+            "name":"达拉特旗",
+            "code":"150621"
+          },
+          {
+            "name":"准格尔旗",
+            "code":"150622"
+          },
+          {
+            "name":"鄂托克前旗",
+            "code":"150623"
+          },
+          {
+            "name":"鄂托克旗",
+            "code":"150624"
+          },
+          {
+            "name":"杭锦旗",
+            "code":"150625"
+          },
+          {
+            "name":"乌审旗",
+            "code":"150626"
+          },
+          {
+            "name":"伊金霍洛旗",
+            "code":"150627"
+          }
+        ]
+      },
+      {
+        "name":"呼伦贝尔市",
+        "code":"150700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150701"
+          },
+          {
+            "name":"海拉尔区",
+            "code":"150702"
+          },
+          {
+            "name":"扎赉诺尔区",
+            "code":"150703"
+          },
+          {
+            "name":"阿荣旗",
+            "code":"150721"
+          },
+          {
+            "name":"莫力达瓦达斡尔族自治旗",
+            "code":"150722"
+          },
+          {
+            "name":"鄂伦春自治旗",
+            "code":"150723"
+          },
+          {
+            "name":"鄂温克族自治旗",
+            "code":"150724"
+          },
+          {
+            "name":"陈巴尔虎旗",
+            "code":"150725"
+          },
+          {
+            "name":"新巴尔虎左旗",
+            "code":"150726"
+          },
+          {
+            "name":"新巴尔虎右旗",
+            "code":"150727"
+          },
+          {
+            "name":"满洲里市",
+            "code":"150781"
+          },
+          {
+            "name":"牙克石市",
+            "code":"150782"
+          },
+          {
+            "name":"扎兰屯市",
+            "code":"150783"
+          },
+          {
+            "name":"额尔古纳市",
+            "code":"150784"
+          },
+          {
+            "name":"根河市",
+            "code":"150785"
+          }
+        ]
+      },
+      {
+        "name":"巴彦淖尔市",
+        "code":"150800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150801"
+          },
+          {
+            "name":"临河区",
+            "code":"150802"
+          },
+          {
+            "name":"五原县",
+            "code":"150821"
+          },
+          {
+            "name":"磴口县",
+            "code":"150822"
+          },
+          {
+            "name":"乌拉特前旗",
+            "code":"150823"
+          },
+          {
+            "name":"乌拉特中旗",
+            "code":"150824"
+          },
+          {
+            "name":"乌拉特后旗",
+            "code":"150825"
+          },
+          {
+            "name":"杭锦后旗",
+            "code":"150826"
+          }
+        ]
+      },
+      {
+        "name":"乌兰察布市",
+        "code":"150900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150901"
+          },
+          {
+            "name":"集宁区",
+            "code":"150902"
+          },
+          {
+            "name":"卓资县",
+            "code":"150921"
+          },
+          {
+            "name":"化德县",
+            "code":"150922"
+          },
+          {
+            "name":"商都县",
+            "code":"150923"
+          },
+          {
+            "name":"兴和县",
+            "code":"150924"
+          },
+          {
+            "name":"凉城县",
+            "code":"150925"
+          },
+          {
+            "name":"察哈尔右翼前旗",
+            "code":"150926"
+          },
+          {
+            "name":"察哈尔右翼中旗",
+            "code":"150927"
+          },
+          {
+            "name":"察哈尔右翼后旗",
+            "code":"150928"
+          },
+          {
+            "name":"四子王旗",
+            "code":"150929"
+          },
+          {
+            "name":"丰镇市",
+            "code":"150981"
+          }
+        ]
+      },
+      {
+        "name":"兴安盟",
+        "code":"152200",
+        "sub":[
+          {
+            "name":"乌兰浩特市",
+            "code":"152201"
+          },
+          {
+            "name":"阿尔山市",
+            "code":"152202"
+          },
+          {
+            "name":"科尔沁右翼前旗",
+            "code":"152221"
+          },
+          {
+            "name":"科尔沁右翼中旗",
+            "code":"152222"
+          },
+          {
+            "name":"扎赉特旗",
+            "code":"152223"
+          },
+          {
+            "name":"突泉县",
+            "code":"152224"
+          }
+        ]
+      },
+      {
+        "name":"锡林郭勒盟",
+        "code":"152500",
+        "sub":[
+          {
+            "name":"二连浩特市",
+            "code":"152501"
+          },
+          {
+            "name":"锡林浩特市",
+            "code":"152502"
+          },
+          {
+            "name":"阿巴嘎旗",
+            "code":"152522"
+          },
+          {
+            "name":"苏尼特左旗",
+            "code":"152523"
+          },
+          {
+            "name":"苏尼特右旗",
+            "code":"152524"
+          },
+          {
+            "name":"东乌珠穆沁旗",
+            "code":"152525"
+          },
+          {
+            "name":"西乌珠穆沁旗",
+            "code":"152526"
+          },
+          {
+            "name":"太仆寺旗",
+            "code":"152527"
+          },
+          {
+            "name":"镶黄旗",
+            "code":"152528"
+          },
+          {
+            "name":"正镶白旗",
+            "code":"152529"
+          },
+          {
+            "name":"正蓝旗",
+            "code":"152530"
+          },
+          {
+            "name":"多伦县",
+            "code":"152531"
+          }
+        ]
+      },
+      {
+        "name":"阿拉善盟",
+        "code":"152900",
+        "sub":[
+          {
+            "name":"阿拉善左旗",
+            "code":"152921"
+          },
+          {
+            "name":"阿拉善右旗",
+            "code":"152922"
+          },
+          {
+            "name":"额济纳旗",
+            "code":"152923"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"辽宁省",
+    "code":"210000",
+    "sub":[
+      {
+        "name":"沈阳市",
+        "code":"210100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210101"
+          },
+          {
+            "name":"和平区",
+            "code":"210102"
+          },
+          {
+            "name":"沈河区",
+            "code":"210103"
+          },
+          {
+            "name":"大东区",
+            "code":"210104"
+          },
+          {
+            "name":"皇姑区",
+            "code":"210105"
+          },
+          {
+            "name":"铁西区",
+            "code":"210106"
+          },
+          {
+            "name":"苏家屯区",
+            "code":"210111"
+          },
+          {
+            "name":"浑南区",
+            "code":"210112"
+          },
+          {
+            "name":"沈北新区",
+            "code":"210113"
+          },
+          {
+            "name":"于洪区",
+            "code":"210114"
+          },
+          {
+            "name":"辽中县",
+            "code":"210122"
+          },
+          {
+            "name":"康平县",
+            "code":"210123"
+          },
+          {
+            "name":"法库县",
+            "code":"210124"
+          },
+          {
+            "name":"新民市",
+            "code":"210181"
+          }
+        ]
+      },
+      {
+        "name":"大连市",
+        "code":"210200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210201"
+          },
+          {
+            "name":"中山区",
+            "code":"210202"
+          },
+          {
+            "name":"西岗区",
+            "code":"210203"
+          },
+          {
+            "name":"沙河口区",
+            "code":"210204"
+          },
+          {
+            "name":"甘井子区",
+            "code":"210211"
+          },
+          {
+            "name":"旅顺口区",
+            "code":"210212"
+          },
+          {
+            "name":"金州区",
+            "code":"210213"
+          },
+          {
+            "name":"长海县",
+            "code":"210224"
+          },
+          {
+            "name":"瓦房店市",
+            "code":"210281"
+          },
+          {
+            "name":"普兰店市",
+            "code":"210282"
+          },
+          {
+            "name":"庄河市",
+            "code":"210283"
+          }
+        ]
+      },
+      {
+        "name":"鞍山市",
+        "code":"210300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210301"
+          },
+          {
+            "name":"铁东区",
+            "code":"210302"
+          },
+          {
+            "name":"铁西区",
+            "code":"210303"
+          },
+          {
+            "name":"立山区",
+            "code":"210304"
+          },
+          {
+            "name":"千山区",
+            "code":"210311"
+          },
+          {
+            "name":"台安县",
+            "code":"210321"
+          },
+          {
+            "name":"岫岩满族自治县",
+            "code":"210323"
+          },
+          {
+            "name":"海城市",
+            "code":"210381"
+          }
+        ]
+      },
+      {
+        "name":"抚顺市",
+        "code":"210400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210401"
+          },
+          {
+            "name":"新抚区",
+            "code":"210402"
+          },
+          {
+            "name":"东洲区",
+            "code":"210403"
+          },
+          {
+            "name":"望花区",
+            "code":"210404"
+          },
+          {
+            "name":"顺城区",
+            "code":"210411"
+          },
+          {
+            "name":"抚顺县",
+            "code":"210421"
+          },
+          {
+            "name":"新宾满族自治县",
+            "code":"210422"
+          },
+          {
+            "name":"清原满族自治县",
+            "code":"210423"
+          }
+        ]
+      },
+      {
+        "name":"本溪市",
+        "code":"210500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210501"
+          },
+          {
+            "name":"平山区",
+            "code":"210502"
+          },
+          {
+            "name":"溪湖区",
+            "code":"210503"
+          },
+          {
+            "name":"明山区",
+            "code":"210504"
+          },
+          {
+            "name":"南芬区",
+            "code":"210505"
+          },
+          {
+            "name":"本溪满族自治县",
+            "code":"210521"
+          },
+          {
+            "name":"桓仁满族自治县",
+            "code":"210522"
+          }
+        ]
+      },
+      {
+        "name":"丹东市",
+        "code":"210600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210601"
+          },
+          {
+            "name":"元宝区",
+            "code":"210602"
+          },
+          {
+            "name":"振兴区",
+            "code":"210603"
+          },
+          {
+            "name":"振安区",
+            "code":"210604"
+          },
+          {
+            "name":"宽甸满族自治县",
+            "code":"210624"
+          },
+          {
+            "name":"东港市",
+            "code":"210681"
+          },
+          {
+            "name":"凤城市",
+            "code":"210682"
+          }
+        ]
+      },
+      {
+        "name":"锦州市",
+        "code":"210700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210701"
+          },
+          {
+            "name":"古塔区",
+            "code":"210702"
+          },
+          {
+            "name":"凌河区",
+            "code":"210703"
+          },
+          {
+            "name":"太和区",
+            "code":"210711"
+          },
+          {
+            "name":"黑山县",
+            "code":"210726"
+          },
+          {
+            "name":"义县",
+            "code":"210727"
+          },
+          {
+            "name":"凌海市",
+            "code":"210781"
+          },
+          {
+            "name":"北镇市",
+            "code":"210782"
+          }
+        ]
+      },
+      {
+        "name":"营口市",
+        "code":"210800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210801"
+          },
+          {
+            "name":"站前区",
+            "code":"210802"
+          },
+          {
+            "name":"西市区",
+            "code":"210803"
+          },
+          {
+            "name":"鲅鱼圈区",
+            "code":"210804"
+          },
+          {
+            "name":"老边区",
+            "code":"210811"
+          },
+          {
+            "name":"盖州市",
+            "code":"210881"
+          },
+          {
+            "name":"大石桥市",
+            "code":"210882"
+          }
+        ]
+      },
+      {
+        "name":"阜新市",
+        "code":"210900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210901"
+          },
+          {
+            "name":"海州区",
+            "code":"210902"
+          },
+          {
+            "name":"新邱区",
+            "code":"210903"
+          },
+          {
+            "name":"太平区",
+            "code":"210904"
+          },
+          {
+            "name":"清河门区",
+            "code":"210905"
+          },
+          {
+            "name":"细河区",
+            "code":"210911"
+          },
+          {
+            "name":"阜新蒙古族自治县",
+            "code":"210921"
+          },
+          {
+            "name":"彰武县",
+            "code":"210922"
+          }
+        ]
+      },
+      {
+        "name":"辽阳市",
+        "code":"211000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211001"
+          },
+          {
+            "name":"白塔区",
+            "code":"211002"
+          },
+          {
+            "name":"文圣区",
+            "code":"211003"
+          },
+          {
+            "name":"宏伟区",
+            "code":"211004"
+          },
+          {
+            "name":"弓长岭区",
+            "code":"211005"
+          },
+          {
+            "name":"太子河区",
+            "code":"211011"
+          },
+          {
+            "name":"辽阳县",
+            "code":"211021"
+          },
+          {
+            "name":"灯塔市",
+            "code":"211081"
+          }
+        ]
+      },
+      {
+        "name":"盘锦市",
+        "code":"211100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211101"
+          },
+          {
+            "name":"双台子区",
+            "code":"211102"
+          },
+          {
+            "name":"兴隆台区",
+            "code":"211103"
+          },
+          {
+            "name":"大洼县",
+            "code":"211121"
+          },
+          {
+            "name":"盘山县",
+            "code":"211122"
+          }
+        ]
+      },
+      {
+        "name":"铁岭市",
+        "code":"211200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211201"
+          },
+          {
+            "name":"银州区",
+            "code":"211202"
+          },
+          {
+            "name":"清河区",
+            "code":"211204"
+          },
+          {
+            "name":"铁岭县",
+            "code":"211221"
+          },
+          {
+            "name":"西丰县",
+            "code":"211223"
+          },
+          {
+            "name":"昌图县",
+            "code":"211224"
+          },
+          {
+            "name":"调兵山市",
+            "code":"211281"
+          },
+          {
+            "name":"开原市",
+            "code":"211282"
+          }
+        ]
+      },
+      {
+        "name":"朝阳市",
+        "code":"211300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211301"
+          },
+          {
+            "name":"双塔区",
+            "code":"211302"
+          },
+          {
+            "name":"龙城区",
+            "code":"211303"
+          },
+          {
+            "name":"朝阳县",
+            "code":"211321"
+          },
+          {
+            "name":"建平县",
+            "code":"211322"
+          },
+          {
+            "name":"喀喇沁左翼蒙古族自治县",
+            "code":"211324"
+          },
+          {
+            "name":"北票市",
+            "code":"211381"
+          },
+          {
+            "name":"凌源市",
+            "code":"211382"
+          }
+        ]
+      },
+      {
+        "name":"葫芦岛市",
+        "code":"211400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211401"
+          },
+          {
+            "name":"连山区",
+            "code":"211402"
+          },
+          {
+            "name":"龙港区",
+            "code":"211403"
+          },
+          {
+            "name":"南票区",
+            "code":"211404"
+          },
+          {
+            "name":"绥中县",
+            "code":"211421"
+          },
+          {
+            "name":"建昌县",
+            "code":"211422"
+          },
+          {
+            "name":"兴城市",
+            "code":"211481"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"吉林省",
+    "code":"220000",
+    "sub":[
+      {
+        "name":"长春市",
+        "code":"220100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220101"
+          },
+          {
+            "name":"南关区",
+            "code":"220102"
+          },
+          {
+            "name":"宽城区",
+            "code":"220103"
+          },
+          {
+            "name":"朝阳区",
+            "code":"220104"
+          },
+          {
+            "name":"二道区",
+            "code":"220105"
+          },
+          {
+            "name":"绿园区",
+            "code":"220106"
+          },
+          {
+            "name":"双阳区",
+            "code":"220112"
+          },
+          {
+            "name":"九台区",
+            "code":"220113"
+          },
+          {
+            "name":"农安县",
+            "code":"220122"
+          },
+          {
+            "name":"榆树市",
+            "code":"220182"
+          },
+          {
+            "name":"德惠市",
+            "code":"220183"
+          }
+        ]
+      },
+      {
+        "name":"吉林市",
+        "code":"220200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220201"
+          },
+          {
+            "name":"昌邑区",
+            "code":"220202"
+          },
+          {
+            "name":"龙潭区",
+            "code":"220203"
+          },
+          {
+            "name":"船营区",
+            "code":"220204"
+          },
+          {
+            "name":"丰满区",
+            "code":"220211"
+          },
+          {
+            "name":"永吉县",
+            "code":"220221"
+          },
+          {
+            "name":"蛟河市",
+            "code":"220281"
+          },
+          {
+            "name":"桦甸市",
+            "code":"220282"
+          },
+          {
+            "name":"舒兰市",
+            "code":"220283"
+          },
+          {
+            "name":"磐石市",
+            "code":"220284"
+          }
+        ]
+      },
+      {
+        "name":"四平市",
+        "code":"220300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220301"
+          },
+          {
+            "name":"铁西区",
+            "code":"220302"
+          },
+          {
+            "name":"铁东区",
+            "code":"220303"
+          },
+          {
+            "name":"梨树县",
+            "code":"220322"
+          },
+          {
+            "name":"伊通满族自治县",
+            "code":"220323"
+          },
+          {
+            "name":"公主岭市",
+            "code":"220381"
+          },
+          {
+            "name":"双辽市",
+            "code":"220382"
+          }
+        ]
+      },
+      {
+        "name":"辽源市",
+        "code":"220400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220401"
+          },
+          {
+            "name":"龙山区",
+            "code":"220402"
+          },
+          {
+            "name":"西安区",
+            "code":"220403"
+          },
+          {
+            "name":"东丰县",
+            "code":"220421"
+          },
+          {
+            "name":"东辽县",
+            "code":"220422"
+          }
+        ]
+      },
+      {
+        "name":"通化市",
+        "code":"220500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220501"
+          },
+          {
+            "name":"东昌区",
+            "code":"220502"
+          },
+          {
+            "name":"二道江区",
+            "code":"220503"
+          },
+          {
+            "name":"通化县",
+            "code":"220521"
+          },
+          {
+            "name":"辉南县",
+            "code":"220523"
+          },
+          {
+            "name":"柳河县",
+            "code":"220524"
+          },
+          {
+            "name":"梅河口市",
+            "code":"220581"
+          },
+          {
+            "name":"集安市",
+            "code":"220582"
+          }
+        ]
+      },
+      {
+        "name":"白山市",
+        "code":"220600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220601"
+          },
+          {
+            "name":"浑江区",
+            "code":"220602"
+          },
+          {
+            "name":"江源区",
+            "code":"220605"
+          },
+          {
+            "name":"抚松县",
+            "code":"220621"
+          },
+          {
+            "name":"靖宇县",
+            "code":"220622"
+          },
+          {
+            "name":"长白朝鲜族自治县",
+            "code":"220623"
+          },
+          {
+            "name":"临江市",
+            "code":"220681"
+          }
+        ]
+      },
+      {
+        "name":"松原市",
+        "code":"220700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220701"
+          },
+          {
+            "name":"宁江区",
+            "code":"220702"
+          },
+          {
+            "name":"前郭尔罗斯蒙古族自治县",
+            "code":"220721"
+          },
+          {
+            "name":"长岭县",
+            "code":"220722"
+          },
+          {
+            "name":"乾安县",
+            "code":"220723"
+          },
+          {
+            "name":"扶余市",
+            "code":"220781"
+          }
+        ]
+      },
+      {
+        "name":"白城市",
+        "code":"220800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220801"
+          },
+          {
+            "name":"洮北区",
+            "code":"220802"
+          },
+          {
+            "name":"镇赉县",
+            "code":"220821"
+          },
+          {
+            "name":"通榆县",
+            "code":"220822"
+          },
+          {
+            "name":"洮南市",
+            "code":"220881"
+          },
+          {
+            "name":"大安市",
+            "code":"220882"
+          }
+        ]
+      },
+      {
+        "name":"延边朝鲜族自治州",
+        "code":"222400",
+        "sub":[
+          {
+            "name":"延吉市",
+            "code":"222401"
+          },
+          {
+            "name":"图们市",
+            "code":"222402"
+          },
+          {
+            "name":"敦化市",
+            "code":"222403"
+          },
+          {
+            "name":"珲春市",
+            "code":"222404"
+          },
+          {
+            "name":"龙井市",
+            "code":"222405"
+          },
+          {
+            "name":"和龙市",
+            "code":"222406"
+          },
+          {
+            "name":"汪清县",
+            "code":"222424"
+          },
+          {
+            "name":"安图县",
+            "code":"222426"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"黑龙江省",
+    "code":"230000",
+    "sub":[
+      {
+        "name":"哈尔滨市",
+        "code":"230100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230101"
+          },
+          {
+            "name":"道里区",
+            "code":"230102"
+          },
+          {
+            "name":"南岗区",
+            "code":"230103"
+          },
+          {
+            "name":"道外区",
+            "code":"230104"
+          },
+          {
+            "name":"平房区",
+            "code":"230108"
+          },
+          {
+            "name":"松北区",
+            "code":"230109"
+          },
+          {
+            "name":"香坊区",
+            "code":"230110"
+          },
+          {
+            "name":"呼兰区",
+            "code":"230111"
+          },
+          {
+            "name":"阿城区",
+            "code":"230112"
+          },
+          {
+            "name":"双城区",
+            "code":"230113"
+          },
+          {
+            "name":"依兰县",
+            "code":"230123"
+          },
+          {
+            "name":"方正县",
+            "code":"230124"
+          },
+          {
+            "name":"宾县",
+            "code":"230125"
+          },
+          {
+            "name":"巴彦县",
+            "code":"230126"
+          },
+          {
+            "name":"木兰县",
+            "code":"230127"
+          },
+          {
+            "name":"通河县",
+            "code":"230128"
+          },
+          {
+            "name":"延寿县",
+            "code":"230129"
+          },
+          {
+            "name":"尚志市",
+            "code":"230183"
+          },
+          {
+            "name":"五常市",
+            "code":"230184"
+          }
+        ]
+      },
+      {
+        "name":"齐齐哈尔市",
+        "code":"230200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230201"
+          },
+          {
+            "name":"龙沙区",
+            "code":"230202"
+          },
+          {
+            "name":"建华区",
+            "code":"230203"
+          },
+          {
+            "name":"铁锋区",
+            "code":"230204"
+          },
+          {
+            "name":"昂昂溪区",
+            "code":"230205"
+          },
+          {
+            "name":"富拉尔基区",
+            "code":"230206"
+          },
+          {
+            "name":"碾子山区",
+            "code":"230207"
+          },
+          {
+            "name":"梅里斯达斡尔族区",
+            "code":"230208"
+          },
+          {
+            "name":"龙江县",
+            "code":"230221"
+          },
+          {
+            "name":"依安县",
+            "code":"230223"
+          },
+          {
+            "name":"泰来县",
+            "code":"230224"
+          },
+          {
+            "name":"甘南县",
+            "code":"230225"
+          },
+          {
+            "name":"富裕县",
+            "code":"230227"
+          },
+          {
+            "name":"克山县",
+            "code":"230229"
+          },
+          {
+            "name":"克东县",
+            "code":"230230"
+          },
+          {
+            "name":"拜泉县",
+            "code":"230231"
+          },
+          {
+            "name":"讷河市",
+            "code":"230281"
+          }
+        ]
+      },
+      {
+        "name":"鸡西市",
+        "code":"230300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230301"
+          },
+          {
+            "name":"鸡冠区",
+            "code":"230302"
+          },
+          {
+            "name":"恒山区",
+            "code":"230303"
+          },
+          {
+            "name":"滴道区",
+            "code":"230304"
+          },
+          {
+            "name":"梨树区",
+            "code":"230305"
+          },
+          {
+            "name":"城子河区",
+            "code":"230306"
+          },
+          {
+            "name":"麻山区",
+            "code":"230307"
+          },
+          {
+            "name":"鸡东县",
+            "code":"230321"
+          },
+          {
+            "name":"虎林市",
+            "code":"230381"
+          },
+          {
+            "name":"密山市",
+            "code":"230382"
+          }
+        ]
+      },
+      {
+        "name":"鹤岗市",
+        "code":"230400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230401"
+          },
+          {
+            "name":"向阳区",
+            "code":"230402"
+          },
+          {
+            "name":"工农区",
+            "code":"230403"
+          },
+          {
+            "name":"南山区",
+            "code":"230404"
+          },
+          {
+            "name":"兴安区",
+            "code":"230405"
+          },
+          {
+            "name":"东山区",
+            "code":"230406"
+          },
+          {
+            "name":"兴山区",
+            "code":"230407"
+          },
+          {
+            "name":"萝北县",
+            "code":"230421"
+          },
+          {
+            "name":"绥滨县",
+            "code":"230422"
+          }
+        ]
+      },
+      {
+        "name":"双鸭山市",
+        "code":"230500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230501"
+          },
+          {
+            "name":"尖山区",
+            "code":"230502"
+          },
+          {
+            "name":"岭东区",
+            "code":"230503"
+          },
+          {
+            "name":"四方台区",
+            "code":"230505"
+          },
+          {
+            "name":"宝山区",
+            "code":"230506"
+          },
+          {
+            "name":"集贤县",
+            "code":"230521"
+          },
+          {
+            "name":"友谊县",
+            "code":"230522"
+          },
+          {
+            "name":"宝清县",
+            "code":"230523"
+          },
+          {
+            "name":"饶河县",
+            "code":"230524"
+          }
+        ]
+      },
+      {
+        "name":"大庆市",
+        "code":"230600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230601"
+          },
+          {
+            "name":"萨尔图区",
+            "code":"230602"
+          },
+          {
+            "name":"龙凤区",
+            "code":"230603"
+          },
+          {
+            "name":"让胡路区",
+            "code":"230604"
+          },
+          {
+            "name":"红岗区",
+            "code":"230605"
+          },
+          {
+            "name":"大同区",
+            "code":"230606"
+          },
+          {
+            "name":"肇州县",
+            "code":"230621"
+          },
+          {
+            "name":"肇源县",
+            "code":"230622"
+          },
+          {
+            "name":"林甸县",
+            "code":"230623"
+          },
+          {
+            "name":"杜尔伯特蒙古族自治县",
+            "code":"230624"
+          }
+        ]
+      },
+      {
+        "name":"伊春市",
+        "code":"230700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230701"
+          },
+          {
+            "name":"伊春区",
+            "code":"230702"
+          },
+          {
+            "name":"南岔区",
+            "code":"230703"
+          },
+          {
+            "name":"友好区",
+            "code":"230704"
+          },
+          {
+            "name":"西林区",
+            "code":"230705"
+          },
+          {
+            "name":"翠峦区",
+            "code":"230706"
+          },
+          {
+            "name":"新青区",
+            "code":"230707"
+          },
+          {
+            "name":"美溪区",
+            "code":"230708"
+          },
+          {
+            "name":"金山屯区",
+            "code":"230709"
+          },
+          {
+            "name":"五营区",
+            "code":"230710"
+          },
+          {
+            "name":"乌马河区",
+            "code":"230711"
+          },
+          {
+            "name":"汤旺河区",
+            "code":"230712"
+          },
+          {
+            "name":"带岭区",
+            "code":"230713"
+          },
+          {
+            "name":"乌伊岭区",
+            "code":"230714"
+          },
+          {
+            "name":"红星区",
+            "code":"230715"
+          },
+          {
+            "name":"上甘岭区",
+            "code":"230716"
+          },
+          {
+            "name":"嘉荫县",
+            "code":"230722"
+          },
+          {
+            "name":"铁力市",
+            "code":"230781"
+          }
+        ]
+      },
+      {
+        "name":"佳木斯市",
+        "code":"230800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230801"
+          },
+          {
+            "name":"向阳区",
+            "code":"230803"
+          },
+          {
+            "name":"前进区",
+            "code":"230804"
+          },
+          {
+            "name":"东风区",
+            "code":"230805"
+          },
+          {
+            "name":"郊区",
+            "code":"230811"
+          },
+          {
+            "name":"桦南县",
+            "code":"230822"
+          },
+          {
+            "name":"桦川县",
+            "code":"230826"
+          },
+          {
+            "name":"汤原县",
+            "code":"230828"
+          },
+          {
+            "name":"抚远县",
+            "code":"230833"
+          },
+          {
+            "name":"同江市",
+            "code":"230881"
+          },
+          {
+            "name":"富锦市",
+            "code":"230882"
+          }
+        ]
+      },
+      {
+        "name":"七台河市",
+        "code":"230900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230901"
+          },
+          {
+            "name":"新兴区",
+            "code":"230902"
+          },
+          {
+            "name":"桃山区",
+            "code":"230903"
+          },
+          {
+            "name":"茄子河区",
+            "code":"230904"
+          },
+          {
+            "name":"勃利县",
+            "code":"230921"
+          }
+        ]
+      },
+      {
+        "name":"牡丹江市",
+        "code":"231000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231001"
+          },
+          {
+            "name":"东安区",
+            "code":"231002"
+          },
+          {
+            "name":"阳明区",
+            "code":"231003"
+          },
+          {
+            "name":"爱民区",
+            "code":"231004"
+          },
+          {
+            "name":"西安区",
+            "code":"231005"
+          },
+          {
+            "name":"东宁县",
+            "code":"231024"
+          },
+          {
+            "name":"林口县",
+            "code":"231025"
+          },
+          {
+            "name":"绥芬河市",
+            "code":"231081"
+          },
+          {
+            "name":"海林市",
+            "code":"231083"
+          },
+          {
+            "name":"宁安市",
+            "code":"231084"
+          },
+          {
+            "name":"穆棱市",
+            "code":"231085"
+          }
+        ]
+      },
+      {
+        "name":"黑河市",
+        "code":"231100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231101"
+          },
+          {
+            "name":"爱辉区",
+            "code":"231102"
+          },
+          {
+            "name":"嫩江县",
+            "code":"231121"
+          },
+          {
+            "name":"逊克县",
+            "code":"231123"
+          },
+          {
+            "name":"孙吴县",
+            "code":"231124"
+          },
+          {
+            "name":"北安市",
+            "code":"231181"
+          },
+          {
+            "name":"五大连池市",
+            "code":"231182"
+          }
+        ]
+      },
+      {
+        "name":"绥化市",
+        "code":"231200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231201"
+          },
+          {
+            "name":"北林区",
+            "code":"231202"
+          },
+          {
+            "name":"望奎县",
+            "code":"231221"
+          },
+          {
+            "name":"兰西县",
+            "code":"231222"
+          },
+          {
+            "name":"青冈县",
+            "code":"231223"
+          },
+          {
+            "name":"庆安县",
+            "code":"231224"
+          },
+          {
+            "name":"明水县",
+            "code":"231225"
+          },
+          {
+            "name":"绥棱县",
+            "code":"231226"
+          },
+          {
+            "name":"安达市",
+            "code":"231281"
+          },
+          {
+            "name":"肇东市",
+            "code":"231282"
+          },
+          {
+            "name":"海伦市",
+            "code":"231283"
+          }
+        ]
+      },
+      {
+        "name":"大兴安岭地区",
+        "code":"232700",
+        "sub":[
+          {
+            "name":"呼玛县",
+            "code":"232721"
+          },
+          {
+            "name":"塔河县",
+            "code":"232722"
+          },
+          {
+            "name":"漠河县",
+            "code":"232723"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"上海",
+    "code":"310000",
+    "sub": [
+      {
+        "name":"上海市",
+        "code": "310000",
+        "sub":[
+            {
+              "name":"黄浦区",
+              "code":"310101"
+            },
+            {
+              "name":"徐汇区",
+              "code":"310104"
+            },
+            {
+              "name":"长宁区",
+              "code":"310105"
+            },
+            {
+              "name":"静安区",
+              "code":"310106"
+            },
+            {
+              "name":"普陀区",
+              "code":"310107"
+            },
+            {
+              "name":"闸北区",
+              "code":"310108"
+            },
+            {
+              "name":"虹口区",
+              "code":"310109"
+            },
+            {
+              "name":"杨浦区",
+              "code":"310110"
+            },
+            {
+              "name":"闵行区",
+              "code":"310112"
+            },
+            {
+              "name":"宝山区",
+              "code":"310113"
+            },
+            {
+              "name":"嘉定区",
+              "code":"310114"
+            },
+            {
+              "name":"浦东新区",
+              "code":"310115"
+            },
+            {
+              "name":"金山区",
+              "code":"310116"
+            },
+            {
+              "name":"松江区",
+              "code":"310117"
+            },
+            {
+              "name":"青浦区",
+              "code":"310118"
+            },
+            {
+              "name":"奉贤区",
+              "code":"310120"
+            },
+            {
+              "name":"崇明县",
+              "code":"310230"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"江苏省",
+    "code":"320000",
+    "sub":[
+      {
+        "name":"南京市",
+        "code":"320100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320101"
+          },
+          {
+            "name":"玄武区",
+            "code":"320102"
+          },
+          {
+            "name":"秦淮区",
+            "code":"320104"
+          },
+          {
+            "name":"建邺区",
+            "code":"320105"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"320106"
+          },
+          {
+            "name":"浦口区",
+            "code":"320111"
+          },
+          {
+            "name":"栖霞区",
+            "code":"320113"
+          },
+          {
+            "name":"雨花台区",
+            "code":"320114"
+          },
+          {
+            "name":"江宁区",
+            "code":"320115"
+          },
+          {
+            "name":"六合区",
+            "code":"320116"
+          },
+          {
+            "name":"溧水区",
+            "code":"320117"
+          },
+          {
+            "name":"高淳区",
+            "code":"320118"
+          }
+        ]
+      },
+      {
+        "name":"无锡市",
+        "code":"320200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320201"
+          },
+          {
+            "name":"崇安区",
+            "code":"320202"
+          },
+          {
+            "name":"南长区",
+            "code":"320203"
+          },
+          {
+            "name":"北塘区",
+            "code":"320204"
+          },
+          {
+            "name":"锡山区",
+            "code":"320205"
+          },
+          {
+            "name":"惠山区",
+            "code":"320206"
+          },
+          {
+            "name":"滨湖区",
+            "code":"320211"
+          },
+          {
+            "name":"江阴市",
+            "code":"320281"
+          },
+          {
+            "name":"宜兴市",
+            "code":"320282"
+          }
+        ]
+      },
+      {
+        "name":"徐州市",
+        "code":"320300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320301"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"320302"
+          },
+          {
+            "name":"云龙区",
+            "code":"320303"
+          },
+          {
+            "name":"贾汪区",
+            "code":"320305"
+          },
+          {
+            "name":"泉山区",
+            "code":"320311"
+          },
+          {
+            "name":"铜山区",
+            "code":"320312"
+          },
+          {
+            "name":"丰县",
+            "code":"320321"
+          },
+          {
+            "name":"沛县",
+            "code":"320322"
+          },
+          {
+            "name":"睢宁县",
+            "code":"320324"
+          },
+          {
+            "name":"新沂市",
+            "code":"320381"
+          },
+          {
+            "name":"邳州市",
+            "code":"320382"
+          }
+        ]
+      },
+      {
+        "name":"常州市",
+        "code":"320400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320401"
+          },
+          {
+            "name":"天宁区",
+            "code":"320402"
+          },
+          {
+            "name":"钟楼区",
+            "code":"320404"
+          },
+          {
+            "name":"戚墅堰区",
+            "code":"320405"
+          },
+          {
+            "name":"新北区",
+            "code":"320411"
+          },
+          {
+            "name":"武进区",
+            "code":"320412"
+          },
+          {
+            "name":"溧阳市",
+            "code":"320481"
+          },
+          {
+            "name":"金坛市",
+            "code":"320482"
+          }
+        ]
+      },
+      {
+        "name":"苏州市",
+        "code":"320500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320501"
+          },
+          {
+            "name":"虎丘区",
+            "code":"320505"
+          },
+          {
+            "name":"吴中区",
+            "code":"320506"
+          },
+          {
+            "name":"相城区",
+            "code":"320507"
+          },
+          {
+            "name":"姑苏区",
+            "code":"320508"
+          },
+          {
+            "name":"吴江区",
+            "code":"320509"
+          },
+          {
+            "name":"常熟市",
+            "code":"320581"
+          },
+          {
+            "name":"张家港市",
+            "code":"320582"
+          },
+          {
+            "name":"昆山市",
+            "code":"320583"
+          },
+          {
+            "name":"太仓市",
+            "code":"320585"
+          }
+        ]
+      },
+      {
+        "name":"南通市",
+        "code":"320600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320601"
+          },
+          {
+            "name":"崇川区",
+            "code":"320602"
+          },
+          {
+            "name":"港闸区",
+            "code":"320611"
+          },
+          {
+            "name":"通州区",
+            "code":"320612"
+          },
+          {
+            "name":"海安县",
+            "code":"320621"
+          },
+          {
+            "name":"如东县",
+            "code":"320623"
+          },
+          {
+            "name":"启东市",
+            "code":"320681"
+          },
+          {
+            "name":"如皋市",
+            "code":"320682"
+          },
+          {
+            "name":"海门市",
+            "code":"320684"
+          }
+        ]
+      },
+      {
+        "name":"连云港市",
+        "code":"320700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320701"
+          },
+          {
+            "name":"连云区",
+            "code":"320703"
+          },
+          {
+            "name":"海州区",
+            "code":"320706"
+          },
+          {
+            "name":"赣榆区",
+            "code":"320707"
+          },
+          {
+            "name":"东海县",
+            "code":"320722"
+          },
+          {
+            "name":"灌云县",
+            "code":"320723"
+          },
+          {
+            "name":"灌南县",
+            "code":"320724"
+          }
+        ]
+      },
+      {
+        "name":"淮安市",
+        "code":"320800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320801"
+          },
+          {
+            "name":"清河区",
+            "code":"320802"
+          },
+          {
+            "name":"淮安区",
+            "code":"320803"
+          },
+          {
+            "name":"淮阴区",
+            "code":"320804"
+          },
+          {
+            "name":"清浦区",
+            "code":"320811"
+          },
+          {
+            "name":"涟水县",
+            "code":"320826"
+          },
+          {
+            "name":"洪泽县",
+            "code":"320829"
+          },
+          {
+            "name":"盱眙县",
+            "code":"320830"
+          },
+          {
+            "name":"金湖县",
+            "code":"320831"
+          }
+        ]
+      },
+      {
+        "name":"盐城市",
+        "code":"320900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320901"
+          },
+          {
+            "name":"亭湖区",
+            "code":"320902"
+          },
+          {
+            "name":"盐都区",
+            "code":"320903"
+          },
+          {
+            "name":"响水县",
+            "code":"320921"
+          },
+          {
+            "name":"滨海县",
+            "code":"320922"
+          },
+          {
+            "name":"阜宁县",
+            "code":"320923"
+          },
+          {
+            "name":"射阳县",
+            "code":"320924"
+          },
+          {
+            "name":"建湖县",
+            "code":"320925"
+          },
+          {
+            "name":"东台市",
+            "code":"320981"
+          },
+          {
+            "name":"大丰市",
+            "code":"320982"
+          }
+        ]
+      },
+      {
+        "name":"扬州市",
+        "code":"321000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321001"
+          },
+          {
+            "name":"广陵区",
+            "code":"321002"
+          },
+          {
+            "name":"邗江区",
+            "code":"321003"
+          },
+          {
+            "name":"江都区",
+            "code":"321012"
+          },
+          {
+            "name":"宝应县",
+            "code":"321023"
+          },
+          {
+            "name":"仪征市",
+            "code":"321081"
+          },
+          {
+            "name":"高邮市",
+            "code":"321084"
+          }
+        ]
+      },
+      {
+        "name":"镇江市",
+        "code":"321100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321101"
+          },
+          {
+            "name":"京口区",
+            "code":"321102"
+          },
+          {
+            "name":"润州区",
+            "code":"321111"
+          },
+          {
+            "name":"丹徒区",
+            "code":"321112"
+          },
+          {
+            "name":"丹阳市",
+            "code":"321181"
+          },
+          {
+            "name":"扬中市",
+            "code":"321182"
+          },
+          {
+            "name":"句容市",
+            "code":"321183"
+          }
+        ]
+      },
+      {
+        "name":"泰州市",
+        "code":"321200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321201"
+          },
+          {
+            "name":"海陵区",
+            "code":"321202"
+          },
+          {
+            "name":"高港区",
+            "code":"321203"
+          },
+          {
+            "name":"姜堰区",
+            "code":"321204"
+          },
+          {
+            "name":"兴化市",
+            "code":"321281"
+          },
+          {
+            "name":"靖江市",
+            "code":"321282"
+          },
+          {
+            "name":"泰兴市",
+            "code":"321283"
+          }
+        ]
+      },
+      {
+        "name":"宿迁市",
+        "code":"321300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321301"
+          },
+          {
+            "name":"宿城区",
+            "code":"321302"
+          },
+          {
+            "name":"宿豫区",
+            "code":"321311"
+          },
+          {
+            "name":"沭阳县",
+            "code":"321322"
+          },
+          {
+            "name":"泗阳县",
+            "code":"321323"
+          },
+          {
+            "name":"泗洪县",
+            "code":"321324"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"浙江省",
+    "code":"330000",
+    "sub":[
+      {
+        "name":"杭州市",
+        "code":"330100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330101"
+          },
+          {
+            "name":"上城区",
+            "code":"330102"
+          },
+          {
+            "name":"下城区",
+            "code":"330103"
+          },
+          {
+            "name":"江干区",
+            "code":"330104"
+          },
+          {
+            "name":"拱墅区",
+            "code":"330105"
+          },
+          {
+            "name":"西湖区",
+            "code":"330106"
+          },
+          {
+            "name":"滨江区",
+            "code":"330108"
+          },
+          {
+            "name":"萧山区",
+            "code":"330109"
+          },
+          {
+            "name":"余杭区",
+            "code":"330110"
+          },
+          {
+            "name":"富阳区",
+            "code":"330111"
+          },
+          {
+            "name":"桐庐县",
+            "code":"330122"
+          },
+          {
+            "name":"淳安县",
+            "code":"330127"
+          },
+          {
+            "name":"建德市",
+            "code":"330182"
+          },
+          {
+            "name":"临安市",
+            "code":"330185"
+          }
+        ]
+      },
+      {
+        "name":"宁波市",
+        "code":"330200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330201"
+          },
+          {
+            "name":"海曙区",
+            "code":"330203"
+          },
+          {
+            "name":"江东区",
+            "code":"330204"
+          },
+          {
+            "name":"江北区",
+            "code":"330205"
+          },
+          {
+            "name":"北仑区",
+            "code":"330206"
+          },
+          {
+            "name":"镇海区",
+            "code":"330211"
+          },
+          {
+            "name":"鄞州区",
+            "code":"330212"
+          },
+          {
+            "name":"象山县",
+            "code":"330225"
+          },
+          {
+            "name":"宁海县",
+            "code":"330226"
+          },
+          {
+            "name":"余姚市",
+            "code":"330281"
+          },
+          {
+            "name":"慈溪市",
+            "code":"330282"
+          },
+          {
+            "name":"奉化市",
+            "code":"330283"
+          }
+        ]
+      },
+      {
+        "name":"温州市",
+        "code":"330300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330301"
+          },
+          {
+            "name":"鹿城区",
+            "code":"330302"
+          },
+          {
+            "name":"龙湾区",
+            "code":"330303"
+          },
+          {
+            "name":"瓯海区",
+            "code":"330304"
+          },
+          {
+            "name":"洞头县",
+            "code":"330322"
+          },
+          {
+            "name":"永嘉县",
+            "code":"330324"
+          },
+          {
+            "name":"平阳县",
+            "code":"330326"
+          },
+          {
+            "name":"苍南县",
+            "code":"330327"
+          },
+          {
+            "name":"文成县",
+            "code":"330328"
+          },
+          {
+            "name":"泰顺县",
+            "code":"330329"
+          },
+          {
+            "name":"瑞安市",
+            "code":"330381"
+          },
+          {
+            "name":"乐清市",
+            "code":"330382"
+          }
+        ]
+      },
+      {
+        "name":"嘉兴市",
+        "code":"330400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330401"
+          },
+          {
+            "name":"南湖区",
+            "code":"330402"
+          },
+          {
+            "name":"秀洲区",
+            "code":"330411"
+          },
+          {
+            "name":"嘉善县",
+            "code":"330421"
+          },
+          {
+            "name":"海盐县",
+            "code":"330424"
+          },
+          {
+            "name":"海宁市",
+            "code":"330481"
+          },
+          {
+            "name":"平湖市",
+            "code":"330482"
+          },
+          {
+            "name":"桐乡市",
+            "code":"330483"
+          }
+        ]
+      },
+      {
+        "name":"湖州市",
+        "code":"330500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330501"
+          },
+          {
+            "name":"吴兴区",
+            "code":"330502"
+          },
+          {
+            "name":"南浔区",
+            "code":"330503"
+          },
+          {
+            "name":"德清县",
+            "code":"330521"
+          },
+          {
+            "name":"长兴县",
+            "code":"330522"
+          },
+          {
+            "name":"安吉县",
+            "code":"330523"
+          }
+        ]
+      },
+      {
+        "name":"绍兴市",
+        "code":"330600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330601"
+          },
+          {
+            "name":"越城区",
+            "code":"330602"
+          },
+          {
+            "name":"柯桥区",
+            "code":"330603"
+          },
+          {
+            "name":"上虞区",
+            "code":"330604"
+          },
+          {
+            "name":"新昌县",
+            "code":"330624"
+          },
+          {
+            "name":"诸暨市",
+            "code":"330681"
+          },
+          {
+            "name":"嵊州市",
+            "code":"330683"
+          }
+        ]
+      },
+      {
+        "name":"金华市",
+        "code":"330700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330701"
+          },
+          {
+            "name":"婺城区",
+            "code":"330702"
+          },
+          {
+            "name":"金东区",
+            "code":"330703"
+          },
+          {
+            "name":"武义县",
+            "code":"330723"
+          },
+          {
+            "name":"浦江县",
+            "code":"330726"
+          },
+          {
+            "name":"磐安县",
+            "code":"330727"
+          },
+          {
+            "name":"兰溪市",
+            "code":"330781"
+          },
+          {
+            "name":"义乌市",
+            "code":"330782"
+          },
+          {
+            "name":"东阳市",
+            "code":"330783"
+          },
+          {
+            "name":"永康市",
+            "code":"330784"
+          }
+        ]
+      },
+      {
+        "name":"衢州市",
+        "code":"330800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330801"
+          },
+          {
+            "name":"柯城区",
+            "code":"330802"
+          },
+          {
+            "name":"衢江区",
+            "code":"330803"
+          },
+          {
+            "name":"常山县",
+            "code":"330822"
+          },
+          {
+            "name":"开化县",
+            "code":"330824"
+          },
+          {
+            "name":"龙游县",
+            "code":"330825"
+          },
+          {
+            "name":"江山市",
+            "code":"330881"
+          }
+        ]
+      },
+      {
+        "name":"舟山市",
+        "code":"330900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330901"
+          },
+          {
+            "name":"定海区",
+            "code":"330902"
+          },
+          {
+            "name":"普陀区",
+            "code":"330903"
+          },
+          {
+            "name":"岱山县",
+            "code":"330921"
+          },
+          {
+            "name":"嵊泗县",
+            "code":"330922"
+          }
+        ]
+      },
+      {
+        "name":"台州市",
+        "code":"331000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"331001"
+          },
+          {
+            "name":"椒江区",
+            "code":"331002"
+          },
+          {
+            "name":"黄岩区",
+            "code":"331003"
+          },
+          {
+            "name":"路桥区",
+            "code":"331004"
+          },
+          {
+            "name":"玉环县",
+            "code":"331021"
+          },
+          {
+            "name":"三门县",
+            "code":"331022"
+          },
+          {
+            "name":"天台县",
+            "code":"331023"
+          },
+          {
+            "name":"仙居县",
+            "code":"331024"
+          },
+          {
+            "name":"温岭市",
+            "code":"331081"
+          },
+          {
+            "name":"临海市",
+            "code":"331082"
+          }
+        ]
+      },
+      {
+        "name":"丽水市",
+        "code":"331100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"331101"
+          },
+          {
+            "name":"莲都区",
+            "code":"331102"
+          },
+          {
+            "name":"青田县",
+            "code":"331121"
+          },
+          {
+            "name":"缙云县",
+            "code":"331122"
+          },
+          {
+            "name":"遂昌县",
+            "code":"331123"
+          },
+          {
+            "name":"松阳县",
+            "code":"331124"
+          },
+          {
+            "name":"云和县",
+            "code":"331125"
+          },
+          {
+            "name":"庆元县",
+            "code":"331126"
+          },
+          {
+            "name":"景宁畲族自治县",
+            "code":"331127"
+          },
+          {
+            "name":"龙泉市",
+            "code":"331181"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"安徽省",
+    "code":"340000",
+    "sub":[
+      {
+        "name":"合肥市",
+        "code":"340100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340101"
+          },
+          {
+            "name":"瑶海区",
+            "code":"340102"
+          },
+          {
+            "name":"庐阳区",
+            "code":"340103"
+          },
+          {
+            "name":"蜀山区",
+            "code":"340104"
+          },
+          {
+            "name":"包河区",
+            "code":"340111"
+          },
+          {
+            "name":"长丰县",
+            "code":"340121"
+          },
+          {
+            "name":"肥东县",
+            "code":"340122"
+          },
+          {
+            "name":"肥西县",
+            "code":"340123"
+          },
+          {
+            "name":"庐江县",
+            "code":"340124"
+          },
+          {
+            "name":"巢湖市",
+            "code":"340181"
+          }
+        ]
+      },
+      {
+        "name":"芜湖市",
+        "code":"340200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340201"
+          },
+          {
+            "name":"镜湖区",
+            "code":"340202"
+          },
+          {
+            "name":"弋江区",
+            "code":"340203"
+          },
+          {
+            "name":"鸠江区",
+            "code":"340207"
+          },
+          {
+            "name":"三山区",
+            "code":"340208"
+          },
+          {
+            "name":"芜湖县",
+            "code":"340221"
+          },
+          {
+            "name":"繁昌县",
+            "code":"340222"
+          },
+          {
+            "name":"南陵县",
+            "code":"340223"
+          },
+          {
+            "name":"无为县",
+            "code":"340225"
+          }
+        ]
+      },
+      {
+        "name":"蚌埠市",
+        "code":"340300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340301"
+          },
+          {
+            "name":"龙子湖区",
+            "code":"340302"
+          },
+          {
+            "name":"蚌山区",
+            "code":"340303"
+          },
+          {
+            "name":"禹会区",
+            "code":"340304"
+          },
+          {
+            "name":"淮上区",
+            "code":"340311"
+          },
+          {
+            "name":"怀远县",
+            "code":"340321"
+          },
+          {
+            "name":"五河县",
+            "code":"340322"
+          },
+          {
+            "name":"固镇县",
+            "code":"340323"
+          }
+        ]
+      },
+      {
+        "name":"淮南市",
+        "code":"340400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340401"
+          },
+          {
+            "name":"大通区",
+            "code":"340402"
+          },
+          {
+            "name":"田家庵区",
+            "code":"340403"
+          },
+          {
+            "name":"谢家集区",
+            "code":"340404"
+          },
+          {
+            "name":"八公山区",
+            "code":"340405"
+          },
+          {
+            "name":"潘集区",
+            "code":"340406"
+          },
+          {
+            "name":"凤台县",
+            "code":"340421"
+          }
+        ]
+      },
+      {
+        "name":"马鞍山市",
+        "code":"340500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340501"
+          },
+          {
+            "name":"花山区",
+            "code":"340503"
+          },
+          {
+            "name":"雨山区",
+            "code":"340504"
+          },
+          {
+            "name":"博望区",
+            "code":"340506"
+          },
+          {
+            "name":"当涂县",
+            "code":"340521"
+          },
+          {
+            "name":"含山县",
+            "code":"340522"
+          },
+          {
+            "name":"和县",
+            "code":"340523"
+          }
+        ]
+      },
+      {
+        "name":"淮北市",
+        "code":"340600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340601"
+          },
+          {
+            "name":"杜集区",
+            "code":"340602"
+          },
+          {
+            "name":"相山区",
+            "code":"340603"
+          },
+          {
+            "name":"烈山区",
+            "code":"340604"
+          },
+          {
+            "name":"濉溪县",
+            "code":"340621"
+          }
+        ]
+      },
+      {
+        "name":"铜陵市",
+        "code":"340700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340701"
+          },
+          {
+            "name":"铜官山区",
+            "code":"340702"
+          },
+          {
+            "name":"狮子山区",
+            "code":"340703"
+          },
+          {
+            "name":"郊区",
+            "code":"340711"
+          },
+          {
+            "name":"铜陵县",
+            "code":"340721"
+          }
+        ]
+      },
+      {
+        "name":"安庆市",
+        "code":"340800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340801"
+          },
+          {
+            "name":"迎江区",
+            "code":"340802"
+          },
+          {
+            "name":"大观区",
+            "code":"340803"
+          },
+          {
+            "name":"宜秀区",
+            "code":"340811"
+          },
+          {
+            "name":"怀宁县",
+            "code":"340822"
+          },
+          {
+            "name":"枞阳县",
+            "code":"340823"
+          },
+          {
+            "name":"潜山县",
+            "code":"340824"
+          },
+          {
+            "name":"太湖县",
+            "code":"340825"
+          },
+          {
+            "name":"宿松县",
+            "code":"340826"
+          },
+          {
+            "name":"望江县",
+            "code":"340827"
+          },
+          {
+            "name":"岳西县",
+            "code":"340828"
+          },
+          {
+            "name":"桐城市",
+            "code":"340881"
+          }
+        ]
+      },
+      {
+        "name":"黄山市",
+        "code":"341000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341001"
+          },
+          {
+            "name":"屯溪区",
+            "code":"341002"
+          },
+          {
+            "name":"黄山区",
+            "code":"341003"
+          },
+          {
+            "name":"徽州区",
+            "code":"341004"
+          },
+          {
+            "name":"歙县",
+            "code":"341021"
+          },
+          {
+            "name":"休宁县",
+            "code":"341022"
+          },
+          {
+            "name":"黟县",
+            "code":"341023"
+          },
+          {
+            "name":"祁门县",
+            "code":"341024"
+          }
+        ]
+      },
+      {
+        "name":"滁州市",
+        "code":"341100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341101"
+          },
+          {
+            "name":"琅琊区",
+            "code":"341102"
+          },
+          {
+            "name":"南谯区",
+            "code":"341103"
+          },
+          {
+            "name":"来安县",
+            "code":"341122"
+          },
+          {
+            "name":"全椒县",
+            "code":"341124"
+          },
+          {
+            "name":"定远县",
+            "code":"341125"
+          },
+          {
+            "name":"凤阳县",
+            "code":"341126"
+          },
+          {
+            "name":"天长市",
+            "code":"341181"
+          },
+          {
+            "name":"明光市",
+            "code":"341182"
+          }
+        ]
+      },
+      {
+        "name":"阜阳市",
+        "code":"341200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341201"
+          },
+          {
+            "name":"颍州区",
+            "code":"341202"
+          },
+          {
+            "name":"颍东区",
+            "code":"341203"
+          },
+          {
+            "name":"颍泉区",
+            "code":"341204"
+          },
+          {
+            "name":"临泉县",
+            "code":"341221"
+          },
+          {
+            "name":"太和县",
+            "code":"341222"
+          },
+          {
+            "name":"阜南县",
+            "code":"341225"
+          },
+          {
+            "name":"颍上县",
+            "code":"341226"
+          },
+          {
+            "name":"界首市",
+            "code":"341282"
+          }
+        ]
+      },
+      {
+        "name":"宿州市",
+        "code":"341300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341301"
+          },
+          {
+            "name":"埇桥区",
+            "code":"341302"
+          },
+          {
+            "name":"砀山县",
+            "code":"341321"
+          },
+          {
+            "name":"萧县",
+            "code":"341322"
+          },
+          {
+            "name":"灵璧县",
+            "code":"341323"
+          },
+          {
+            "name":"泗县",
+            "code":"341324"
+          }
+        ]
+      },
+      {
+        "name":"六安市",
+        "code":"341500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341501"
+          },
+          {
+            "name":"金安区",
+            "code":"341502"
+          },
+          {
+            "name":"裕安区",
+            "code":"341503"
+          },
+          {
+            "name":"寿县",
+            "code":"341521"
+          },
+          {
+            "name":"霍邱县",
+            "code":"341522"
+          },
+          {
+            "name":"舒城县",
+            "code":"341523"
+          },
+          {
+            "name":"金寨县",
+            "code":"341524"
+          },
+          {
+            "name":"霍山县",
+            "code":"341525"
+          }
+        ]
+      },
+      {
+        "name":"亳州市",
+        "code":"341600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341601"
+          },
+          {
+            "name":"谯城区",
+            "code":"341602"
+          },
+          {
+            "name":"涡阳县",
+            "code":"341621"
+          },
+          {
+            "name":"蒙城县",
+            "code":"341622"
+          },
+          {
+            "name":"利辛县",
+            "code":"341623"
+          }
+        ]
+      },
+      {
+        "name":"池州市",
+        "code":"341700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341701"
+          },
+          {
+            "name":"贵池区",
+            "code":"341702"
+          },
+          {
+            "name":"东至县",
+            "code":"341721"
+          },
+          {
+            "name":"石台县",
+            "code":"341722"
+          },
+          {
+            "name":"青阳县",
+            "code":"341723"
+          }
+        ]
+      },
+      {
+        "name":"宣城市",
+        "code":"341800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341801"
+          },
+          {
+            "name":"宣州区",
+            "code":"341802"
+          },
+          {
+            "name":"郎溪县",
+            "code":"341821"
+          },
+          {
+            "name":"广德县",
+            "code":"341822"
+          },
+          {
+            "name":"泾县",
+            "code":"341823"
+          },
+          {
+            "name":"绩溪县",
+            "code":"341824"
+          },
+          {
+            "name":"旌德县",
+            "code":"341825"
+          },
+          {
+            "name":"宁国市",
+            "code":"341881"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"福建省",
+    "code":"350000",
+    "sub":[
+      {
+        "name":"福州市",
+        "code":"350100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350101"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"350102"
+          },
+          {
+            "name":"台江区",
+            "code":"350103"
+          },
+          {
+            "name":"仓山区",
+            "code":"350104"
+          },
+          {
+            "name":"马尾区",
+            "code":"350105"
+          },
+          {
+            "name":"晋安区",
+            "code":"350111"
+          },
+          {
+            "name":"闽侯县",
+            "code":"350121"
+          },
+          {
+            "name":"连江县",
+            "code":"350122"
+          },
+          {
+            "name":"罗源县",
+            "code":"350123"
+          },
+          {
+            "name":"闽清县",
+            "code":"350124"
+          },
+          {
+            "name":"永泰县",
+            "code":"350125"
+          },
+          {
+            "name":"平潭县",
+            "code":"350128"
+          },
+          {
+            "name":"福清市",
+            "code":"350181"
+          },
+          {
+            "name":"长乐市",
+            "code":"350182"
+          }
+        ]
+      },
+      {
+        "name":"厦门市",
+        "code":"350200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350201"
+          },
+          {
+            "name":"思明区",
+            "code":"350203"
+          },
+          {
+            "name":"海沧区",
+            "code":"350205"
+          },
+          {
+            "name":"湖里区",
+            "code":"350206"
+          },
+          {
+            "name":"集美区",
+            "code":"350211"
+          },
+          {
+            "name":"同安区",
+            "code":"350212"
+          },
+          {
+            "name":"翔安区",
+            "code":"350213"
+          }
+        ]
+      },
+      {
+        "name":"莆田市",
+        "code":"350300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350301"
+          },
+          {
+            "name":"城厢区",
+            "code":"350302"
+          },
+          {
+            "name":"涵江区",
+            "code":"350303"
+          },
+          {
+            "name":"荔城区",
+            "code":"350304"
+          },
+          {
+            "name":"秀屿区",
+            "code":"350305"
+          },
+          {
+            "name":"仙游县",
+            "code":"350322"
+          }
+        ]
+      },
+      {
+        "name":"三明市",
+        "code":"350400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350401"
+          },
+          {
+            "name":"梅列区",
+            "code":"350402"
+          },
+          {
+            "name":"三元区",
+            "code":"350403"
+          },
+          {
+            "name":"明溪县",
+            "code":"350421"
+          },
+          {
+            "name":"清流县",
+            "code":"350423"
+          },
+          {
+            "name":"宁化县",
+            "code":"350424"
+          },
+          {
+            "name":"大田县",
+            "code":"350425"
+          },
+          {
+            "name":"尤溪县",
+            "code":"350426"
+          },
+          {
+            "name":"沙县",
+            "code":"350427"
+          },
+          {
+            "name":"将乐县",
+            "code":"350428"
+          },
+          {
+            "name":"泰宁县",
+            "code":"350429"
+          },
+          {
+            "name":"建宁县",
+            "code":"350430"
+          },
+          {
+            "name":"永安市",
+            "code":"350481"
+          }
+        ]
+      },
+      {
+        "name":"泉州市",
+        "code":"350500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350501"
+          },
+          {
+            "name":"鲤城区",
+            "code":"350502"
+          },
+          {
+            "name":"丰泽区",
+            "code":"350503"
+          },
+          {
+            "name":"洛江区",
+            "code":"350504"
+          },
+          {
+            "name":"泉港区",
+            "code":"350505"
+          },
+          {
+            "name":"惠安县",
+            "code":"350521"
+          },
+          {
+            "name":"安溪县",
+            "code":"350524"
+          },
+          {
+            "name":"永春县",
+            "code":"350525"
+          },
+          {
+            "name":"德化县",
+            "code":"350526"
+          },
+          {
+            "name":"金门县",
+            "code":"350527"
+          },
+          {
+            "name":"石狮市",
+            "code":"350581"
+          },
+          {
+            "name":"晋江市",
+            "code":"350582"
+          },
+          {
+            "name":"南安市",
+            "code":"350583"
+          }
+        ]
+      },
+      {
+        "name":"漳州市",
+        "code":"350600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350601"
+          },
+          {
+            "name":"芗城区",
+            "code":"350602"
+          },
+          {
+            "name":"龙文区",
+            "code":"350603"
+          },
+          {
+            "name":"云霄县",
+            "code":"350622"
+          },
+          {
+            "name":"漳浦县",
+            "code":"350623"
+          },
+          {
+            "name":"诏安县",
+            "code":"350624"
+          },
+          {
+            "name":"长泰县",
+            "code":"350625"
+          },
+          {
+            "name":"东山县",
+            "code":"350626"
+          },
+          {
+            "name":"南靖县",
+            "code":"350627"
+          },
+          {
+            "name":"平和县",
+            "code":"350628"
+          },
+          {
+            "name":"华安县",
+            "code":"350629"
+          },
+          {
+            "name":"龙海市",
+            "code":"350681"
+          }
+        ]
+      },
+      {
+        "name":"南平市",
+        "code":"350700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350701"
+          },
+          {
+            "name":"延平区",
+            "code":"350702"
+          },
+          {
+            "name":"建阳区",
+            "code":"350703"
+          },
+          {
+            "name":"顺昌县",
+            "code":"350721"
+          },
+          {
+            "name":"浦城县",
+            "code":"350722"
+          },
+          {
+            "name":"光泽县",
+            "code":"350723"
+          },
+          {
+            "name":"松溪县",
+            "code":"350724"
+          },
+          {
+            "name":"政和县",
+            "code":"350725"
+          },
+          {
+            "name":"邵武市",
+            "code":"350781"
+          },
+          {
+            "name":"武夷山市",
+            "code":"350782"
+          },
+          {
+            "name":"建瓯市",
+            "code":"350783"
+          }
+        ]
+      },
+      {
+        "name":"龙岩市",
+        "code":"350800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350801"
+          },
+          {
+            "name":"新罗区",
+            "code":"350802"
+          },
+          {
+            "name":"永定区",
+            "code":"350803"
+          },
+          {
+            "name":"长汀县",
+            "code":"350821"
+          },
+          {
+            "name":"上杭县",
+            "code":"350823"
+          },
+          {
+            "name":"武平县",
+            "code":"350824"
+          },
+          {
+            "name":"连城县",
+            "code":"350825"
+          },
+          {
+            "name":"漳平市",
+            "code":"350881"
+          }
+        ]
+      },
+      {
+        "name":"宁德市",
+        "code":"350900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350901"
+          },
+          {
+            "name":"蕉城区",
+            "code":"350902"
+          },
+          {
+            "name":"霞浦县",
+            "code":"350921"
+          },
+          {
+            "name":"古田县",
+            "code":"350922"
+          },
+          {
+            "name":"屏南县",
+            "code":"350923"
+          },
+          {
+            "name":"寿宁县",
+            "code":"350924"
+          },
+          {
+            "name":"周宁县",
+            "code":"350925"
+          },
+          {
+            "name":"柘荣县",
+            "code":"350926"
+          },
+          {
+            "name":"福安市",
+            "code":"350981"
+          },
+          {
+            "name":"福鼎市",
+            "code":"350982"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"江西省",
+    "code":"360000",
+    "sub":[
+      {
+        "name":"南昌市",
+        "code":"360100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360101"
+          },
+          {
+            "name":"东湖区",
+            "code":"360102"
+          },
+          {
+            "name":"西湖区",
+            "code":"360103"
+          },
+          {
+            "name":"青云谱区",
+            "code":"360104"
+          },
+          {
+            "name":"湾里区",
+            "code":"360105"
+          },
+          {
+            "name":"青山湖区",
+            "code":"360111"
+          },
+          {
+            "name":"南昌县",
+            "code":"360121"
+          },
+          {
+            "name":"新建县",
+            "code":"360122"
+          },
+          {
+            "name":"安义县",
+            "code":"360123"
+          },
+          {
+            "name":"进贤县",
+            "code":"360124"
+          }
+        ]
+      },
+      {
+        "name":"景德镇市",
+        "code":"360200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360201"
+          },
+          {
+            "name":"昌江区",
+            "code":"360202"
+          },
+          {
+            "name":"珠山区",
+            "code":"360203"
+          },
+          {
+            "name":"浮梁县",
+            "code":"360222"
+          },
+          {
+            "name":"乐平市",
+            "code":"360281"
+          }
+        ]
+      },
+      {
+        "name":"萍乡市",
+        "code":"360300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360301"
+          },
+          {
+            "name":"安源区",
+            "code":"360302"
+          },
+          {
+            "name":"湘东区",
+            "code":"360313"
+          },
+          {
+            "name":"莲花县",
+            "code":"360321"
+          },
+          {
+            "name":"上栗县",
+            "code":"360322"
+          },
+          {
+            "name":"芦溪县",
+            "code":"360323"
+          }
+        ]
+      },
+      {
+        "name":"九江市",
+        "code":"360400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360401"
+          },
+          {
+            "name":"庐山区",
+            "code":"360402"
+          },
+          {
+            "name":"浔阳区",
+            "code":"360403"
+          },
+          {
+            "name":"九江县",
+            "code":"360421"
+          },
+          {
+            "name":"武宁县",
+            "code":"360423"
+          },
+          {
+            "name":"修水县",
+            "code":"360424"
+          },
+          {
+            "name":"永修县",
+            "code":"360425"
+          },
+          {
+            "name":"德安县",
+            "code":"360426"
+          },
+          {
+            "name":"星子县",
+            "code":"360427"
+          },
+          {
+            "name":"都昌县",
+            "code":"360428"
+          },
+          {
+            "name":"湖口县",
+            "code":"360429"
+          },
+          {
+            "name":"彭泽县",
+            "code":"360430"
+          },
+          {
+            "name":"瑞昌市",
+            "code":"360481"
+          },
+          {
+            "name":"共青城市",
+            "code":"360482"
+          }
+        ]
+      },
+      {
+        "name":"新余市",
+        "code":"360500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360501"
+          },
+          {
+            "name":"渝水区",
+            "code":"360502"
+          },
+          {
+            "name":"分宜县",
+            "code":"360521"
+          }
+        ]
+      },
+      {
+        "name":"鹰潭市",
+        "code":"360600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360601"
+          },
+          {
+            "name":"月湖区",
+            "code":"360602"
+          },
+          {
+            "name":"余江县",
+            "code":"360622"
+          },
+          {
+            "name":"贵溪市",
+            "code":"360681"
+          }
+        ]
+      },
+      {
+        "name":"赣州市",
+        "code":"360700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360701"
+          },
+          {
+            "name":"章贡区",
+            "code":"360702"
+          },
+          {
+            "name":"南康区",
+            "code":"360703"
+          },
+          {
+            "name":"赣县",
+            "code":"360721"
+          },
+          {
+            "name":"信丰县",
+            "code":"360722"
+          },
+          {
+            "name":"大余县",
+            "code":"360723"
+          },
+          {
+            "name":"上犹县",
+            "code":"360724"
+          },
+          {
+            "name":"崇义县",
+            "code":"360725"
+          },
+          {
+            "name":"安远县",
+            "code":"360726"
+          },
+          {
+            "name":"龙南县",
+            "code":"360727"
+          },
+          {
+            "name":"定南县",
+            "code":"360728"
+          },
+          {
+            "name":"全南县",
+            "code":"360729"
+          },
+          {
+            "name":"宁都县",
+            "code":"360730"
+          },
+          {
+            "name":"于都县",
+            "code":"360731"
+          },
+          {
+            "name":"兴国县",
+            "code":"360732"
+          },
+          {
+            "name":"会昌县",
+            "code":"360733"
+          },
+          {
+            "name":"寻乌县",
+            "code":"360734"
+          },
+          {
+            "name":"石城县",
+            "code":"360735"
+          },
+          {
+            "name":"瑞金市",
+            "code":"360781"
+          }
+        ]
+      },
+      {
+        "name":"吉安市",
+        "code":"360800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360801"
+          },
+          {
+            "name":"吉州区",
+            "code":"360802"
+          },
+          {
+            "name":"青原区",
+            "code":"360803"
+          },
+          {
+            "name":"吉安县",
+            "code":"360821"
+          },
+          {
+            "name":"吉水县",
+            "code":"360822"
+          },
+          {
+            "name":"峡江县",
+            "code":"360823"
+          },
+          {
+            "name":"新干县",
+            "code":"360824"
+          },
+          {
+            "name":"永丰县",
+            "code":"360825"
+          },
+          {
+            "name":"泰和县",
+            "code":"360826"
+          },
+          {
+            "name":"遂川县",
+            "code":"360827"
+          },
+          {
+            "name":"万安县",
+            "code":"360828"
+          },
+          {
+            "name":"安福县",
+            "code":"360829"
+          },
+          {
+            "name":"永新县",
+            "code":"360830"
+          },
+          {
+            "name":"井冈山市",
+            "code":"360881"
+          }
+        ]
+      },
+      {
+        "name":"宜春市",
+        "code":"360900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360901"
+          },
+          {
+            "name":"袁州区",
+            "code":"360902"
+          },
+          {
+            "name":"奉新县",
+            "code":"360921"
+          },
+          {
+            "name":"万载县",
+            "code":"360922"
+          },
+          {
+            "name":"上高县",
+            "code":"360923"
+          },
+          {
+            "name":"宜丰县",
+            "code":"360924"
+          },
+          {
+            "name":"靖安县",
+            "code":"360925"
+          },
+          {
+            "name":"铜鼓县",
+            "code":"360926"
+          },
+          {
+            "name":"丰城市",
+            "code":"360981"
+          },
+          {
+            "name":"樟树市",
+            "code":"360982"
+          },
+          {
+            "name":"高安市",
+            "code":"360983"
+          }
+        ]
+      },
+      {
+        "name":"抚州市",
+        "code":"361000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"361001"
+          },
+          {
+            "name":"临川区",
+            "code":"361002"
+          },
+          {
+            "name":"南城县",
+            "code":"361021"
+          },
+          {
+            "name":"黎川县",
+            "code":"361022"
+          },
+          {
+            "name":"南丰县",
+            "code":"361023"
+          },
+          {
+            "name":"崇仁县",
+            "code":"361024"
+          },
+          {
+            "name":"乐安县",
+            "code":"361025"
+          },
+          {
+            "name":"宜黄县",
+            "code":"361026"
+          },
+          {
+            "name":"金溪县",
+            "code":"361027"
+          },
+          {
+            "name":"资溪县",
+            "code":"361028"
+          },
+          {
+            "name":"东乡县",
+            "code":"361029"
+          },
+          {
+            "name":"广昌县",
+            "code":"361030"
+          }
+        ]
+      },
+      {
+        "name":"上饶市",
+        "code":"361100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"361101"
+          },
+          {
+            "name":"信州区",
+            "code":"361102"
+          },
+          {
+            "name":"上饶县",
+            "code":"361121"
+          },
+          {
+            "name":"广丰县",
+            "code":"361122"
+          },
+          {
+            "name":"玉山县",
+            "code":"361123"
+          },
+          {
+            "name":"铅山县",
+            "code":"361124"
+          },
+          {
+            "name":"横峰县",
+            "code":"361125"
+          },
+          {
+            "name":"弋阳县",
+            "code":"361126"
+          },
+          {
+            "name":"余干县",
+            "code":"361127"
+          },
+          {
+            "name":"鄱阳县",
+            "code":"361128"
+          },
+          {
+            "name":"万年县",
+            "code":"361129"
+          },
+          {
+            "name":"婺源县",
+            "code":"361130"
+          },
+          {
+            "name":"德兴市",
+            "code":"361181"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"山东省",
+    "code":"370000",
+    "sub":[
+      {
+        "name":"济南市",
+        "code":"370100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370101"
+          },
+          {
+            "name":"历下区",
+            "code":"370102"
+          },
+          {
+            "name":"市中区",
+            "code":"370103"
+          },
+          {
+            "name":"槐荫区",
+            "code":"370104"
+          },
+          {
+            "name":"天桥区",
+            "code":"370105"
+          },
+          {
+            "name":"历城区",
+            "code":"370112"
+          },
+          {
+            "name":"长清区",
+            "code":"370113"
+          },
+          {
+            "name":"平阴县",
+            "code":"370124"
+          },
+          {
+            "name":"济阳县",
+            "code":"370125"
+          },
+          {
+            "name":"商河县",
+            "code":"370126"
+          },
+          {
+            "name":"章丘市",
+            "code":"370181"
+          }
+        ]
+      },
+      {
+        "name":"青岛市",
+        "code":"370200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370201"
+          },
+          {
+            "name":"市南区",
+            "code":"370202"
+          },
+          {
+            "name":"市北区",
+            "code":"370203"
+          },
+          {
+            "name":"黄岛区",
+            "code":"370211"
+          },
+          {
+            "name":"崂山区",
+            "code":"370212"
+          },
+          {
+            "name":"李沧区",
+            "code":"370213"
+          },
+          {
+            "name":"城阳区",
+            "code":"370214"
+          },
+          {
+            "name":"胶州市",
+            "code":"370281"
+          },
+          {
+            "name":"即墨市",
+            "code":"370282"
+          },
+          {
+            "name":"平度市",
+            "code":"370283"
+          },
+          {
+            "name":"莱西市",
+            "code":"370285"
+          }
+        ]
+      },
+      {
+        "name":"淄博市",
+        "code":"370300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370301"
+          },
+          {
+            "name":"淄川区",
+            "code":"370302"
+          },
+          {
+            "name":"张店区",
+            "code":"370303"
+          },
+          {
+            "name":"博山区",
+            "code":"370304"
+          },
+          {
+            "name":"临淄区",
+            "code":"370305"
+          },
+          {
+            "name":"周村区",
+            "code":"370306"
+          },
+          {
+            "name":"桓台县",
+            "code":"370321"
+          },
+          {
+            "name":"高青县",
+            "code":"370322"
+          },
+          {
+            "name":"沂源县",
+            "code":"370323"
+          }
+        ]
+      },
+      {
+        "name":"枣庄市",
+        "code":"370400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370401"
+          },
+          {
+            "name":"市中区",
+            "code":"370402"
+          },
+          {
+            "name":"薛城区",
+            "code":"370403"
+          },
+          {
+            "name":"峄城区",
+            "code":"370404"
+          },
+          {
+            "name":"台儿庄区",
+            "code":"370405"
+          },
+          {
+            "name":"山亭区",
+            "code":"370406"
+          },
+          {
+            "name":"滕州市",
+            "code":"370481"
+          }
+        ]
+      },
+      {
+        "name":"东营市",
+        "code":"370500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370501"
+          },
+          {
+            "name":"东营区",
+            "code":"370502"
+          },
+          {
+            "name":"河口区",
+            "code":"370503"
+          },
+          {
+            "name":"垦利县",
+            "code":"370521"
+          },
+          {
+            "name":"利津县",
+            "code":"370522"
+          },
+          {
+            "name":"广饶县",
+            "code":"370523"
+          }
+        ]
+      },
+      {
+        "name":"烟台市",
+        "code":"370600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370601"
+          },
+          {
+            "name":"芝罘区",
+            "code":"370602"
+          },
+          {
+            "name":"福山区",
+            "code":"370611"
+          },
+          {
+            "name":"牟平区",
+            "code":"370612"
+          },
+          {
+            "name":"莱山区",
+            "code":"370613"
+          },
+          {
+            "name":"长岛县",
+            "code":"370634"
+          },
+          {
+            "name":"龙口市",
+            "code":"370681"
+          },
+          {
+            "name":"莱阳市",
+            "code":"370682"
+          },
+          {
+            "name":"莱州市",
+            "code":"370683"
+          },
+          {
+            "name":"蓬莱市",
+            "code":"370684"
+          },
+          {
+            "name":"招远市",
+            "code":"370685"
+          },
+          {
+            "name":"栖霞市",
+            "code":"370686"
+          },
+          {
+            "name":"海阳市",
+            "code":"370687"
+          }
+        ]
+      },
+      {
+        "name":"潍坊市",
+        "code":"370700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370701"
+          },
+          {
+            "name":"潍城区",
+            "code":"370702"
+          },
+          {
+            "name":"寒亭区",
+            "code":"370703"
+          },
+          {
+            "name":"坊子区",
+            "code":"370704"
+          },
+          {
+            "name":"奎文区",
+            "code":"370705"
+          },
+          {
+            "name":"临朐县",
+            "code":"370724"
+          },
+          {
+            "name":"昌乐县",
+            "code":"370725"
+          },
+          {
+            "name":"青州市",
+            "code":"370781"
+          },
+          {
+            "name":"诸城市",
+            "code":"370782"
+          },
+          {
+            "name":"寿光市",
+            "code":"370783"
+          },
+          {
+            "name":"安丘市",
+            "code":"370784"
+          },
+          {
+            "name":"高密市",
+            "code":"370785"
+          },
+          {
+            "name":"昌邑市",
+            "code":"370786"
+          }
+        ]
+      },
+      {
+        "name":"济宁市",
+        "code":"370800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370801"
+          },
+          {
+            "name":"任城区",
+            "code":"370811"
+          },
+          {
+            "name":"兖州区",
+            "code":"370812"
+          },
+          {
+            "name":"微山县",
+            "code":"370826"
+          },
+          {
+            "name":"鱼台县",
+            "code":"370827"
+          },
+          {
+            "name":"金乡县",
+            "code":"370828"
+          },
+          {
+            "name":"嘉祥县",
+            "code":"370829"
+          },
+          {
+            "name":"汶上县",
+            "code":"370830"
+          },
+          {
+            "name":"泗水县",
+            "code":"370831"
+          },
+          {
+            "name":"梁山县",
+            "code":"370832"
+          },
+          {
+            "name":"曲阜市",
+            "code":"370881"
+          },
+          {
+            "name":"邹城市",
+            "code":"370883"
+          }
+        ]
+      },
+      {
+        "name":"泰安市",
+        "code":"370900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370901"
+          },
+          {
+            "name":"泰山区",
+            "code":"370902"
+          },
+          {
+            "name":"岱岳区",
+            "code":"370911"
+          },
+          {
+            "name":"宁阳县",
+            "code":"370921"
+          },
+          {
+            "name":"东平县",
+            "code":"370923"
+          },
+          {
+            "name":"新泰市",
+            "code":"370982"
+          },
+          {
+            "name":"肥城市",
+            "code":"370983"
+          }
+        ]
+      },
+      {
+        "name":"威海市",
+        "code":"371000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371001"
+          },
+          {
+            "name":"环翠区",
+            "code":"371002"
+          },
+          {
+            "name":"文登市",
+            "code":"371081"
+          },
+          {
+            "name":"荣成市",
+            "code":"371082"
+          },
+          {
+            "name":"乳山市",
+            "code":"371083"
+          }
+        ]
+      },
+      {
+        "name":"日照市",
+        "code":"371100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371101"
+          },
+          {
+            "name":"东港区",
+            "code":"371102"
+          },
+          {
+            "name":"岚山区",
+            "code":"371103"
+          },
+          {
+            "name":"五莲县",
+            "code":"371121"
+          },
+          {
+            "name":"莒县",
+            "code":"371122"
+          }
+        ]
+      },
+      {
+        "name":"莱芜市",
+        "code":"371200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371201"
+          },
+          {
+            "name":"莱城区",
+            "code":"371202"
+          },
+          {
+            "name":"钢城区",
+            "code":"371203"
+          }
+        ]
+      },
+      {
+        "name":"临沂市",
+        "code":"371300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371301"
+          },
+          {
+            "name":"兰山区",
+            "code":"371302"
+          },
+          {
+            "name":"罗庄区",
+            "code":"371311"
+          },
+          {
+            "name":"河东区",
+            "code":"371312"
+          },
+          {
+            "name":"沂南县",
+            "code":"371321"
+          },
+          {
+            "name":"郯城县",
+            "code":"371322"
+          },
+          {
+            "name":"沂水县",
+            "code":"371323"
+          },
+          {
+            "name":"兰陵县",
+            "code":"371324"
+          },
+          {
+            "name":"费县",
+            "code":"371325"
+          },
+          {
+            "name":"平邑县",
+            "code":"371326"
+          },
+          {
+            "name":"莒南县",
+            "code":"371327"
+          },
+          {
+            "name":"蒙阴县",
+            "code":"371328"
+          },
+          {
+            "name":"临沭县",
+            "code":"371329"
+          }
+        ]
+      },
+      {
+        "name":"德州市",
+        "code":"371400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371401"
+          },
+          {
+            "name":"德城区",
+            "code":"371402"
+          },
+          {
+            "name":"陵城区",
+            "code":"371403"
+          },
+          {
+            "name":"宁津县",
+            "code":"371422"
+          },
+          {
+            "name":"庆云县",
+            "code":"371423"
+          },
+          {
+            "name":"临邑县",
+            "code":"371424"
+          },
+          {
+            "name":"齐河县",
+            "code":"371425"
+          },
+          {
+            "name":"平原县",
+            "code":"371426"
+          },
+          {
+            "name":"夏津县",
+            "code":"371427"
+          },
+          {
+            "name":"武城县",
+            "code":"371428"
+          },
+          {
+            "name":"乐陵市",
+            "code":"371481"
+          },
+          {
+            "name":"禹城市",
+            "code":"371482"
+          }
+        ]
+      },
+      {
+        "name":"聊城市",
+        "code":"371500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371501"
+          },
+          {
+            "name":"东昌府区",
+            "code":"371502"
+          },
+          {
+            "name":"阳谷县",
+            "code":"371521"
+          },
+          {
+            "name":"莘县",
+            "code":"371522"
+          },
+          {
+            "name":"茌平县",
+            "code":"371523"
+          },
+          {
+            "name":"东阿县",
+            "code":"371524"
+          },
+          {
+            "name":"冠县",
+            "code":"371525"
+          },
+          {
+            "name":"高唐县",
+            "code":"371526"
+          },
+          {
+            "name":"临清市",
+            "code":"371581"
+          }
+        ]
+      },
+      {
+        "name":"滨州市",
+        "code":"371600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371601"
+          },
+          {
+            "name":"滨城区",
+            "code":"371602"
+          },
+          {
+            "name":"沾化区",
+            "code":"371603"
+          },
+          {
+            "name":"惠民县",
+            "code":"371621"
+          },
+          {
+            "name":"阳信县",
+            "code":"371622"
+          },
+          {
+            "name":"无棣县",
+            "code":"371623"
+          },
+          {
+            "name":"博兴县",
+            "code":"371625"
+          },
+          {
+            "name":"邹平县",
+            "code":"371626"
+          }
+        ]
+      },
+      {
+        "name":"菏泽市",
+        "code":"371700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371701"
+          },
+          {
+            "name":"牡丹区",
+            "code":"371702"
+          },
+          {
+            "name":"曹县",
+            "code":"371721"
+          },
+          {
+            "name":"单县",
+            "code":"371722"
+          },
+          {
+            "name":"成武县",
+            "code":"371723"
+          },
+          {
+            "name":"巨野县",
+            "code":"371724"
+          },
+          {
+            "name":"郓城县",
+            "code":"371725"
+          },
+          {
+            "name":"鄄城县",
+            "code":"371726"
+          },
+          {
+            "name":"定陶县",
+            "code":"371727"
+          },
+          {
+            "name":"东明县",
+            "code":"371728"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"河南省",
+    "code":"410000",
+    "sub":[
+      {
+        "name":"郑州市",
+        "code":"410100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410101"
+          },
+          {
+            "name":"中原区",
+            "code":"410102"
+          },
+          {
+            "name":"二七区",
+            "code":"410103"
+          },
+          {
+            "name":"管城回族区",
+            "code":"410104"
+          },
+          {
+            "name":"金水区",
+            "code":"410105"
+          },
+          {
+            "name":"上街区",
+            "code":"410106"
+          },
+          {
+            "name":"惠济区",
+            "code":"410108"
+          },
+          {
+            "name":"中牟县",
+            "code":"410122"
+          },
+          {
+            "name":"巩义市",
+            "code":"410181"
+          },
+          {
+            "name":"荥阳市",
+            "code":"410182"
+          },
+          {
+            "name":"新密市",
+            "code":"410183"
+          },
+          {
+            "name":"新郑市",
+            "code":"410184"
+          },
+          {
+            "name":"登封市",
+            "code":"410185"
+          }
+        ]
+      },
+      {
+        "name":"开封市",
+        "code":"410200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410201"
+          },
+          {
+            "name":"龙亭区",
+            "code":"410202"
+          },
+          {
+            "name":"顺河回族区",
+            "code":"410203"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"410204"
+          },
+          {
+            "name":"禹王台区",
+            "code":"410205"
+          },
+          {
+            "name":"祥符区",
+            "code":"410212"
+          },
+          {
+            "name":"杞县",
+            "code":"410221"
+          },
+          {
+            "name":"通许县",
+            "code":"410222"
+          },
+          {
+            "name":"尉氏县",
+            "code":"410223"
+          },
+          {
+            "name":"兰考县",
+            "code":"410225"
+          }
+        ]
+      },
+      {
+        "name":"洛阳市",
+        "code":"410300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410301"
+          },
+          {
+            "name":"老城区",
+            "code":"410302"
+          },
+          {
+            "name":"西工区",
+            "code":"410303"
+          },
+          {
+            "name":"瀍河回族区",
+            "code":"410304"
+          },
+          {
+            "name":"涧西区",
+            "code":"410305"
+          },
+          {
+            "name":"吉利区",
+            "code":"410306"
+          },
+          {
+            "name":"洛龙区",
+            "code":"410311"
+          },
+          {
+            "name":"孟津县",
+            "code":"410322"
+          },
+          {
+            "name":"新安县",
+            "code":"410323"
+          },
+          {
+            "name":"栾川县",
+            "code":"410324"
+          },
+          {
+            "name":"嵩县",
+            "code":"410325"
+          },
+          {
+            "name":"汝阳县",
+            "code":"410326"
+          },
+          {
+            "name":"宜阳县",
+            "code":"410327"
+          },
+          {
+            "name":"洛宁县",
+            "code":"410328"
+          },
+          {
+            "name":"伊川县",
+            "code":"410329"
+          },
+          {
+            "name":"偃师市",
+            "code":"410381"
+          }
+        ]
+      },
+      {
+        "name":"平顶山市",
+        "code":"410400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410401"
+          },
+          {
+            "name":"新华区",
+            "code":"410402"
+          },
+          {
+            "name":"卫东区",
+            "code":"410403"
+          },
+          {
+            "name":"石龙区",
+            "code":"410404"
+          },
+          {
+            "name":"湛河区",
+            "code":"410411"
+          },
+          {
+            "name":"宝丰县",
+            "code":"410421"
+          },
+          {
+            "name":"叶县",
+            "code":"410422"
+          },
+          {
+            "name":"鲁山县",
+            "code":"410423"
+          },
+          {
+            "name":"郏县",
+            "code":"410425"
+          },
+          {
+            "name":"舞钢市",
+            "code":"410481"
+          },
+          {
+            "name":"汝州市",
+            "code":"410482"
+          }
+        ]
+      },
+      {
+        "name":"安阳市",
+        "code":"410500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410501"
+          },
+          {
+            "name":"文峰区",
+            "code":"410502"
+          },
+          {
+            "name":"北关区",
+            "code":"410503"
+          },
+          {
+            "name":"殷都区",
+            "code":"410505"
+          },
+          {
+            "name":"龙安区",
+            "code":"410506"
+          },
+          {
+            "name":"安阳县",
+            "code":"410522"
+          },
+          {
+            "name":"汤阴县",
+            "code":"410523"
+          },
+          {
+            "name":"滑县",
+            "code":"410526"
+          },
+          {
+            "name":"内黄县",
+            "code":"410527"
+          },
+          {
+            "name":"林州市",
+            "code":"410581"
+          }
+        ]
+      },
+      {
+        "name":"鹤壁市",
+        "code":"410600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410601"
+          },
+          {
+            "name":"鹤山区",
+            "code":"410602"
+          },
+          {
+            "name":"山城区",
+            "code":"410603"
+          },
+          {
+            "name":"淇滨区",
+            "code":"410611"
+          },
+          {
+            "name":"浚县",
+            "code":"410621"
+          },
+          {
+            "name":"淇县",
+            "code":"410622"
+          }
+        ]
+      },
+      {
+        "name":"新乡市",
+        "code":"410700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410701"
+          },
+          {
+            "name":"红旗区",
+            "code":"410702"
+          },
+          {
+            "name":"卫滨区",
+            "code":"410703"
+          },
+          {
+            "name":"凤泉区",
+            "code":"410704"
+          },
+          {
+            "name":"牧野区",
+            "code":"410711"
+          },
+          {
+            "name":"新乡县",
+            "code":"410721"
+          },
+          {
+            "name":"获嘉县",
+            "code":"410724"
+          },
+          {
+            "name":"原阳县",
+            "code":"410725"
+          },
+          {
+            "name":"延津县",
+            "code":"410726"
+          },
+          {
+            "name":"封丘县",
+            "code":"410727"
+          },
+          {
+            "name":"长垣县",
+            "code":"410728"
+          },
+          {
+            "name":"卫辉市",
+            "code":"410781"
+          },
+          {
+            "name":"辉县市",
+            "code":"410782"
+          }
+        ]
+      },
+      {
+        "name":"焦作市",
+        "code":"410800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410801"
+          },
+          {
+            "name":"解放区",
+            "code":"410802"
+          },
+          {
+            "name":"中站区",
+            "code":"410803"
+          },
+          {
+            "name":"马村区",
+            "code":"410804"
+          },
+          {
+            "name":"山阳区",
+            "code":"410811"
+          },
+          {
+            "name":"修武县",
+            "code":"410821"
+          },
+          {
+            "name":"博爱县",
+            "code":"410822"
+          },
+          {
+            "name":"武陟县",
+            "code":"410823"
+          },
+          {
+            "name":"温县",
+            "code":"410825"
+          },
+          {
+            "name":"沁阳市",
+            "code":"410882"
+          },
+          {
+            "name":"孟州市",
+            "code":"410883"
+          }
+        ]
+      },
+      {
+        "name":"濮阳市",
+        "code":"410900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410901"
+          },
+          {
+            "name":"华龙区",
+            "code":"410902"
+          },
+          {
+            "name":"清丰县",
+            "code":"410922"
+          },
+          {
+            "name":"南乐县",
+            "code":"410923"
+          },
+          {
+            "name":"范县",
+            "code":"410926"
+          },
+          {
+            "name":"台前县",
+            "code":"410927"
+          },
+          {
+            "name":"濮阳县",
+            "code":"410928"
+          }
+        ]
+      },
+      {
+        "name":"许昌市",
+        "code":"411000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411001"
+          },
+          {
+            "name":"魏都区",
+            "code":"411002"
+          },
+          {
+            "name":"许昌县",
+            "code":"411023"
+          },
+          {
+            "name":"鄢陵县",
+            "code":"411024"
+          },
+          {
+            "name":"襄城县",
+            "code":"411025"
+          },
+          {
+            "name":"禹州市",
+            "code":"411081"
+          },
+          {
+            "name":"长葛市",
+            "code":"411082"
+          }
+        ]
+      },
+      {
+        "name":"漯河市",
+        "code":"411100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411101"
+          },
+          {
+            "name":"源汇区",
+            "code":"411102"
+          },
+          {
+            "name":"郾城区",
+            "code":"411103"
+          },
+          {
+            "name":"召陵区",
+            "code":"411104"
+          },
+          {
+            "name":"舞阳县",
+            "code":"411121"
+          },
+          {
+            "name":"临颍县",
+            "code":"411122"
+          }
+        ]
+      },
+      {
+        "name":"三门峡市",
+        "code":"411200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411201"
+          },
+          {
+            "name":"湖滨区",
+            "code":"411202"
+          },
+          {
+            "name":"渑池县",
+            "code":"411221"
+          },
+          {
+            "name":"陕县",
+            "code":"411222"
+          },
+          {
+            "name":"卢氏县",
+            "code":"411224"
+          },
+          {
+            "name":"义马市",
+            "code":"411281"
+          },
+          {
+            "name":"灵宝市",
+            "code":"411282"
+          }
+        ]
+      },
+      {
+        "name":"南阳市",
+        "code":"411300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411301"
+          },
+          {
+            "name":"宛城区",
+            "code":"411302"
+          },
+          {
+            "name":"卧龙区",
+            "code":"411303"
+          },
+          {
+            "name":"南召县",
+            "code":"411321"
+          },
+          {
+            "name":"方城县",
+            "code":"411322"
+          },
+          {
+            "name":"西峡县",
+            "code":"411323"
+          },
+          {
+            "name":"镇平县",
+            "code":"411324"
+          },
+          {
+            "name":"内乡县",
+            "code":"411325"
+          },
+          {
+            "name":"淅川县",
+            "code":"411326"
+          },
+          {
+            "name":"社旗县",
+            "code":"411327"
+          },
+          {
+            "name":"唐河县",
+            "code":"411328"
+          },
+          {
+            "name":"新野县",
+            "code":"411329"
+          },
+          {
+            "name":"桐柏县",
+            "code":"411330"
+          },
+          {
+            "name":"邓州市",
+            "code":"411381"
+          }
+        ]
+      },
+      {
+        "name":"商丘市",
+        "code":"411400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411401"
+          },
+          {
+            "name":"梁园区",
+            "code":"411402"
+          },
+          {
+            "name":"睢阳区",
+            "code":"411403"
+          },
+          {
+            "name":"民权县",
+            "code":"411421"
+          },
+          {
+            "name":"睢县",
+            "code":"411422"
+          },
+          {
+            "name":"宁陵县",
+            "code":"411423"
+          },
+          {
+            "name":"柘城县",
+            "code":"411424"
+          },
+          {
+            "name":"虞城县",
+            "code":"411425"
+          },
+          {
+            "name":"夏邑县",
+            "code":"411426"
+          },
+          {
+            "name":"永城市",
+            "code":"411481"
+          }
+        ]
+      },
+      {
+        "name":"信阳市",
+        "code":"411500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411501"
+          },
+          {
+            "name":"浉河区",
+            "code":"411502"
+          },
+          {
+            "name":"平桥区",
+            "code":"411503"
+          },
+          {
+            "name":"罗山县",
+            "code":"411521"
+          },
+          {
+            "name":"光山县",
+            "code":"411522"
+          },
+          {
+            "name":"新县",
+            "code":"411523"
+          },
+          {
+            "name":"商城县",
+            "code":"411524"
+          },
+          {
+            "name":"固始县",
+            "code":"411525"
+          },
+          {
+            "name":"潢川县",
+            "code":"411526"
+          },
+          {
+            "name":"淮滨县",
+            "code":"411527"
+          },
+          {
+            "name":"息县",
+            "code":"411528"
+          }
+        ]
+      },
+      {
+        "name":"周口市",
+        "code":"411600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411601"
+          },
+          {
+            "name":"川汇区",
+            "code":"411602"
+          },
+          {
+            "name":"扶沟县",
+            "code":"411621"
+          },
+          {
+            "name":"西华县",
+            "code":"411622"
+          },
+          {
+            "name":"商水县",
+            "code":"411623"
+          },
+          {
+            "name":"沈丘县",
+            "code":"411624"
+          },
+          {
+            "name":"郸城县",
+            "code":"411625"
+          },
+          {
+            "name":"淮阳县",
+            "code":"411626"
+          },
+          {
+            "name":"太康县",
+            "code":"411627"
+          },
+          {
+            "name":"鹿邑县",
+            "code":"411628"
+          },
+          {
+            "name":"项城市",
+            "code":"411681"
+          }
+        ]
+      },
+      {
+        "name":"驻马店市",
+        "code":"411700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411701"
+          },
+          {
+            "name":"驿城区",
+            "code":"411702"
+          },
+          {
+            "name":"西平县",
+            "code":"411721"
+          },
+          {
+            "name":"上蔡县",
+            "code":"411722"
+          },
+          {
+            "name":"平舆县",
+            "code":"411723"
+          },
+          {
+            "name":"正阳县",
+            "code":"411724"
+          },
+          {
+            "name":"确山县",
+            "code":"411725"
+          },
+          {
+            "name":"泌阳县",
+            "code":"411726"
+          },
+          {
+            "name":"汝南县",
+            "code":"411727"
+          },
+          {
+            "name":"遂平县",
+            "code":"411728"
+          },
+          {
+            "name":"新蔡县",
+            "code":"411729"
+          }
+        ]
+      },
+      {
+        "name":"济源市",
+        "code":"419001"
+      }
+    ]
+  },
+  {
+    "name":"湖北省",
+    "code":"420000",
+    "sub":[
+      {
+        "name":"武汉市",
+        "code":"420100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420101"
+          },
+          {
+            "name":"江岸区",
+            "code":"420102"
+          },
+          {
+            "name":"江汉区",
+            "code":"420103"
+          },
+          {
+            "name":"硚口区",
+            "code":"420104"
+          },
+          {
+            "name":"汉阳区",
+            "code":"420105"
+          },
+          {
+            "name":"武昌区",
+            "code":"420106"
+          },
+          {
+            "name":"青山区",
+            "code":"420107"
+          },
+          {
+            "name":"洪山区",
+            "code":"420111"
+          },
+          {
+            "name":"东西湖区",
+            "code":"420112"
+          },
+          {
+            "name":"汉南区",
+            "code":"420113"
+          },
+          {
+            "name":"蔡甸区",
+            "code":"420114"
+          },
+          {
+            "name":"江夏区",
+            "code":"420115"
+          },
+          {
+            "name":"黄陂区",
+            "code":"420116"
+          },
+          {
+            "name":"新洲区",
+            "code":"420117"
+          }
+        ]
+      },
+      {
+        "name":"黄石市",
+        "code":"420200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420201"
+          },
+          {
+            "name":"黄石港区",
+            "code":"420202"
+          },
+          {
+            "name":"西塞山区",
+            "code":"420203"
+          },
+          {
+            "name":"下陆区",
+            "code":"420204"
+          },
+          {
+            "name":"铁山区",
+            "code":"420205"
+          },
+          {
+            "name":"阳新县",
+            "code":"420222"
+          },
+          {
+            "name":"大冶市",
+            "code":"420281"
+          }
+        ]
+      },
+      {
+        "name":"十堰市",
+        "code":"420300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420301"
+          },
+          {
+            "name":"茅箭区",
+            "code":"420302"
+          },
+          {
+            "name":"张湾区",
+            "code":"420303"
+          },
+          {
+            "name":"郧阳区",
+            "code":"420304"
+          },
+          {
+            "name":"郧西县",
+            "code":"420322"
+          },
+          {
+            "name":"竹山县",
+            "code":"420323"
+          },
+          {
+            "name":"竹溪县",
+            "code":"420324"
+          },
+          {
+            "name":"房县",
+            "code":"420325"
+          },
+          {
+            "name":"丹江口市",
+            "code":"420381"
+          }
+        ]
+      },
+      {
+        "name":"宜昌市",
+        "code":"420500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420501"
+          },
+          {
+            "name":"西陵区",
+            "code":"420502"
+          },
+          {
+            "name":"伍家岗区",
+            "code":"420503"
+          },
+          {
+            "name":"点军区",
+            "code":"420504"
+          },
+          {
+            "name":"猇亭区",
+            "code":"420505"
+          },
+          {
+            "name":"夷陵区",
+            "code":"420506"
+          },
+          {
+            "name":"远安县",
+            "code":"420525"
+          },
+          {
+            "name":"兴山县",
+            "code":"420526"
+          },
+          {
+            "name":"秭归县",
+            "code":"420527"
+          },
+          {
+            "name":"长阳土家族自治县",
+            "code":"420528"
+          },
+          {
+            "name":"五峰土家族自治县",
+            "code":"420529"
+          },
+          {
+            "name":"宜都市",
+            "code":"420581"
+          },
+          {
+            "name":"当阳市",
+            "code":"420582"
+          },
+          {
+            "name":"枝江市",
+            "code":"420583"
+          }
+        ]
+      },
+      {
+        "name":"襄阳市",
+        "code":"420600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420601"
+          },
+          {
+            "name":"襄城区",
+            "code":"420602"
+          },
+          {
+            "name":"樊城区",
+            "code":"420606"
+          },
+          {
+            "name":"襄州区",
+            "code":"420607"
+          },
+          {
+            "name":"南漳县",
+            "code":"420624"
+          },
+          {
+            "name":"谷城县",
+            "code":"420625"
+          },
+          {
+            "name":"保康县",
+            "code":"420626"
+          },
+          {
+            "name":"老河口市",
+            "code":"420682"
+          },
+          {
+            "name":"枣阳市",
+            "code":"420683"
+          },
+          {
+            "name":"宜城市",
+            "code":"420684"
+          }
+        ]
+      },
+      {
+        "name":"鄂州市",
+        "code":"420700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420701"
+          },
+          {
+            "name":"梁子湖区",
+            "code":"420702"
+          },
+          {
+            "name":"华容区",
+            "code":"420703"
+          },
+          {
+            "name":"鄂城区",
+            "code":"420704"
+          }
+        ]
+      },
+      {
+        "name":"荆门市",
+        "code":"420800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420801"
+          },
+          {
+            "name":"东宝区",
+            "code":"420802"
+          },
+          {
+            "name":"掇刀区",
+            "code":"420804"
+          },
+          {
+            "name":"京山县",
+            "code":"420821"
+          },
+          {
+            "name":"沙洋县",
+            "code":"420822"
+          },
+          {
+            "name":"钟祥市",
+            "code":"420881"
+          }
+        ]
+      },
+      {
+        "name":"孝感市",
+        "code":"420900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420901"
+          },
+          {
+            "name":"孝南区",
+            "code":"420902"
+          },
+          {
+            "name":"孝昌县",
+            "code":"420921"
+          },
+          {
+            "name":"大悟县",
+            "code":"420922"
+          },
+          {
+            "name":"云梦县",
+            "code":"420923"
+          },
+          {
+            "name":"应城市",
+            "code":"420981"
+          },
+          {
+            "name":"安陆市",
+            "code":"420982"
+          },
+          {
+            "name":"汉川市",
+            "code":"420984"
+          }
+        ]
+      },
+      {
+        "name":"荆州市",
+        "code":"421000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421001"
+          },
+          {
+            "name":"沙市区",
+            "code":"421002"
+          },
+          {
+            "name":"荆州区",
+            "code":"421003"
+          },
+          {
+            "name":"公安县",
+            "code":"421022"
+          },
+          {
+            "name":"监利县",
+            "code":"421023"
+          },
+          {
+            "name":"江陵县",
+            "code":"421024"
+          },
+          {
+            "name":"石首市",
+            "code":"421081"
+          },
+          {
+            "name":"洪湖市",
+            "code":"421083"
+          },
+          {
+            "name":"松滋市",
+            "code":"421087"
+          }
+        ]
+      },
+      {
+        "name":"黄冈市",
+        "code":"421100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421101"
+          },
+          {
+            "name":"黄州区",
+            "code":"421102"
+          },
+          {
+            "name":"团风县",
+            "code":"421121"
+          },
+          {
+            "name":"红安县",
+            "code":"421122"
+          },
+          {
+            "name":"罗田县",
+            "code":"421123"
+          },
+          {
+            "name":"英山县",
+            "code":"421124"
+          },
+          {
+            "name":"浠水县",
+            "code":"421125"
+          },
+          {
+            "name":"蕲春县",
+            "code":"421126"
+          },
+          {
+            "name":"黄梅县",
+            "code":"421127"
+          },
+          {
+            "name":"麻城市",
+            "code":"421181"
+          },
+          {
+            "name":"武穴市",
+            "code":"421182"
+          }
+        ]
+      },
+      {
+        "name":"咸宁市",
+        "code":"421200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421201"
+          },
+          {
+            "name":"咸安区",
+            "code":"421202"
+          },
+          {
+            "name":"嘉鱼县",
+            "code":"421221"
+          },
+          {
+            "name":"通城县",
+            "code":"421222"
+          },
+          {
+            "name":"崇阳县",
+            "code":"421223"
+          },
+          {
+            "name":"通山县",
+            "code":"421224"
+          },
+          {
+            "name":"赤壁市",
+            "code":"421281"
+          }
+        ]
+      },
+      {
+        "name":"随州市",
+        "code":"421300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421301"
+          },
+          {
+            "name":"曾都区",
+            "code":"421303"
+          },
+          {
+            "name":"随县",
+            "code":"421321"
+          },
+          {
+            "name":"广水市",
+            "code":"421381"
+          }
+        ]
+      },
+      {
+        "name":"恩施土家族苗族自治州",
+        "code":"422800",
+        "sub":[
+          {
+            "name":"恩施市",
+            "code":"422801"
+          },
+          {
+            "name":"利川市",
+            "code":"422802"
+          },
+          {
+            "name":"建始县",
+            "code":"422822"
+          },
+          {
+            "name":"巴东县",
+            "code":"422823"
+          },
+          {
+            "name":"宣恩县",
+            "code":"422825"
+          },
+          {
+            "name":"咸丰县",
+            "code":"422826"
+          },
+          {
+            "name":"来凤县",
+            "code":"422827"
+          },
+          {
+            "name":"鹤峰县",
+            "code":"422828"
+          }
+        ]
+      },
+      {
+        "name":"仙桃市",
+        "code":"429004"
+      },
+      {
+        "name":"潜江市",
+        "code":"429005"
+      },
+      {
+        "name":"天门市",
+        "code":"429006"
+      },
+      {
+        "name":"神农架林区",
+        "code":"429021"
+      }
+    ]
+  },
+  {
+    "name":"湖南省",
+    "code":"430000",
+    "sub":[
+      {
+        "name":"长沙市",
+        "code":"430100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430101"
+          },
+          {
+            "name":"芙蓉区",
+            "code":"430102"
+          },
+          {
+            "name":"天心区",
+            "code":"430103"
+          },
+          {
+            "name":"岳麓区",
+            "code":"430104"
+          },
+          {
+            "name":"开福区",
+            "code":"430105"
+          },
+          {
+            "name":"雨花区",
+            "code":"430111"
+          },
+          {
+            "name":"望城区",
+            "code":"430112"
+          },
+          {
+            "name":"长沙县",
+            "code":"430121"
+          },
+          {
+            "name":"宁乡县",
+            "code":"430124"
+          },
+          {
+            "name":"浏阳市",
+            "code":"430181"
+          }
+        ]
+      },
+      {
+        "name":"株洲市",
+        "code":"430200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430201"
+          },
+          {
+            "name":"荷塘区",
+            "code":"430202"
+          },
+          {
+            "name":"芦淞区",
+            "code":"430203"
+          },
+          {
+            "name":"石峰区",
+            "code":"430204"
+          },
+          {
+            "name":"天元区",
+            "code":"430211"
+          },
+          {
+            "name":"株洲县",
+            "code":"430221"
+          },
+          {
+            "name":"攸县",
+            "code":"430223"
+          },
+          {
+            "name":"茶陵县",
+            "code":"430224"
+          },
+          {
+            "name":"炎陵县",
+            "code":"430225"
+          },
+          {
+            "name":"醴陵市",
+            "code":"430281"
+          }
+        ]
+      },
+      {
+        "name":"湘潭市",
+        "code":"430300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430301"
+          },
+          {
+            "name":"雨湖区",
+            "code":"430302"
+          },
+          {
+            "name":"岳塘区",
+            "code":"430304"
+          },
+          {
+            "name":"湘潭县",
+            "code":"430321"
+          },
+          {
+            "name":"湘乡市",
+            "code":"430381"
+          },
+          {
+            "name":"韶山市",
+            "code":"430382"
+          }
+        ]
+      },
+      {
+        "name":"衡阳市",
+        "code":"430400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430401"
+          },
+          {
+            "name":"珠晖区",
+            "code":"430405"
+          },
+          {
+            "name":"雁峰区",
+            "code":"430406"
+          },
+          {
+            "name":"石鼓区",
+            "code":"430407"
+          },
+          {
+            "name":"蒸湘区",
+            "code":"430408"
+          },
+          {
+            "name":"南岳区",
+            "code":"430412"
+          },
+          {
+            "name":"衡阳县",
+            "code":"430421"
+          },
+          {
+            "name":"衡南县",
+            "code":"430422"
+          },
+          {
+            "name":"衡山县",
+            "code":"430423"
+          },
+          {
+            "name":"衡东县",
+            "code":"430424"
+          },
+          {
+            "name":"祁东县",
+            "code":"430426"
+          },
+          {
+            "name":"耒阳市",
+            "code":"430481"
+          },
+          {
+            "name":"常宁市",
+            "code":"430482"
+          }
+        ]
+      },
+      {
+        "name":"邵阳市",
+        "code":"430500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430501"
+          },
+          {
+            "name":"双清区",
+            "code":"430502"
+          },
+          {
+            "name":"大祥区",
+            "code":"430503"
+          },
+          {
+            "name":"北塔区",
+            "code":"430511"
+          },
+          {
+            "name":"邵东县",
+            "code":"430521"
+          },
+          {
+            "name":"新邵县",
+            "code":"430522"
+          },
+          {
+            "name":"邵阳县",
+            "code":"430523"
+          },
+          {
+            "name":"隆回县",
+            "code":"430524"
+          },
+          {
+            "name":"洞口县",
+            "code":"430525"
+          },
+          {
+            "name":"绥宁县",
+            "code":"430527"
+          },
+          {
+            "name":"新宁县",
+            "code":"430528"
+          },
+          {
+            "name":"城步苗族自治县",
+            "code":"430529"
+          },
+          {
+            "name":"武冈市",
+            "code":"430581"
+          }
+        ]
+      },
+      {
+        "name":"岳阳市",
+        "code":"430600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430601"
+          },
+          {
+            "name":"岳阳楼区",
+            "code":"430602"
+          },
+          {
+            "name":"云溪区",
+            "code":"430603"
+          },
+          {
+            "name":"君山区",
+            "code":"430611"
+          },
+          {
+            "name":"岳阳县",
+            "code":"430621"
+          },
+          {
+            "name":"华容县",
+            "code":"430623"
+          },
+          {
+            "name":"湘阴县",
+            "code":"430624"
+          },
+          {
+            "name":"平江县",
+            "code":"430626"
+          },
+          {
+            "name":"汨罗市",
+            "code":"430681"
+          },
+          {
+            "name":"临湘市",
+            "code":"430682"
+          }
+        ]
+      },
+      {
+        "name":"常德市",
+        "code":"430700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430701"
+          },
+          {
+            "name":"武陵区",
+            "code":"430702"
+          },
+          {
+            "name":"鼎城区",
+            "code":"430703"
+          },
+          {
+            "name":"安乡县",
+            "code":"430721"
+          },
+          {
+            "name":"汉寿县",
+            "code":"430722"
+          },
+          {
+            "name":"澧县",
+            "code":"430723"
+          },
+          {
+            "name":"临澧县",
+            "code":"430724"
+          },
+          {
+            "name":"桃源县",
+            "code":"430725"
+          },
+          {
+            "name":"石门县",
+            "code":"430726"
+          },
+          {
+            "name":"津市市",
+            "code":"430781"
+          }
+        ]
+      },
+      {
+        "name":"张家界市",
+        "code":"430800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430801"
+          },
+          {
+            "name":"永定区",
+            "code":"430802"
+          },
+          {
+            "name":"武陵源区",
+            "code":"430811"
+          },
+          {
+            "name":"慈利县",
+            "code":"430821"
+          },
+          {
+            "name":"桑植县",
+            "code":"430822"
+          }
+        ]
+      },
+      {
+        "name":"益阳市",
+        "code":"430900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430901"
+          },
+          {
+            "name":"资阳区",
+            "code":"430902"
+          },
+          {
+            "name":"赫山区",
+            "code":"430903"
+          },
+          {
+            "name":"南县",
+            "code":"430921"
+          },
+          {
+            "name":"桃江县",
+            "code":"430922"
+          },
+          {
+            "name":"安化县",
+            "code":"430923"
+          },
+          {
+            "name":"沅江市",
+            "code":"430981"
+          }
+        ]
+      },
+      {
+        "name":"郴州市",
+        "code":"431000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431001"
+          },
+          {
+            "name":"北湖区",
+            "code":"431002"
+          },
+          {
+            "name":"苏仙区",
+            "code":"431003"
+          },
+          {
+            "name":"桂阳县",
+            "code":"431021"
+          },
+          {
+            "name":"宜章县",
+            "code":"431022"
+          },
+          {
+            "name":"永兴县",
+            "code":"431023"
+          },
+          {
+            "name":"嘉禾县",
+            "code":"431024"
+          },
+          {
+            "name":"临武县",
+            "code":"431025"
+          },
+          {
+            "name":"汝城县",
+            "code":"431026"
+          },
+          {
+            "name":"桂东县",
+            "code":"431027"
+          },
+          {
+            "name":"安仁县",
+            "code":"431028"
+          },
+          {
+            "name":"资兴市",
+            "code":"431081"
+          }
+        ]
+      },
+      {
+        "name":"永州市",
+        "code":"431100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431101"
+          },
+          {
+            "name":"零陵区",
+            "code":"431102"
+          },
+          {
+            "name":"冷水滩区",
+            "code":"431103"
+          },
+          {
+            "name":"祁阳县",
+            "code":"431121"
+          },
+          {
+            "name":"东安县",
+            "code":"431122"
+          },
+          {
+            "name":"双牌县",
+            "code":"431123"
+          },
+          {
+            "name":"道县",
+            "code":"431124"
+          },
+          {
+            "name":"江永县",
+            "code":"431125"
+          },
+          {
+            "name":"宁远县",
+            "code":"431126"
+          },
+          {
+            "name":"蓝山县",
+            "code":"431127"
+          },
+          {
+            "name":"新田县",
+            "code":"431128"
+          },
+          {
+            "name":"江华瑶族自治县",
+            "code":"431129"
+          }
+        ]
+      },
+      {
+        "name":"怀化市",
+        "code":"431200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431201"
+          },
+          {
+            "name":"鹤城区",
+            "code":"431202"
+          },
+          {
+            "name":"中方县",
+            "code":"431221"
+          },
+          {
+            "name":"沅陵县",
+            "code":"431222"
+          },
+          {
+            "name":"辰溪县",
+            "code":"431223"
+          },
+          {
+            "name":"溆浦县",
+            "code":"431224"
+          },
+          {
+            "name":"会同县",
+            "code":"431225"
+          },
+          {
+            "name":"麻阳苗族自治县",
+            "code":"431226"
+          },
+          {
+            "name":"新晃侗族自治县",
+            "code":"431227"
+          },
+          {
+            "name":"芷江侗族自治县",
+            "code":"431228"
+          },
+          {
+            "name":"靖州苗族侗族自治县",
+            "code":"431229"
+          },
+          {
+            "name":"通道侗族自治县",
+            "code":"431230"
+          },
+          {
+            "name":"洪江市",
+            "code":"431281"
+          }
+        ]
+      },
+      {
+        "name":"娄底市",
+        "code":"431300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431301"
+          },
+          {
+            "name":"娄星区",
+            "code":"431302"
+          },
+          {
+            "name":"双峰县",
+            "code":"431321"
+          },
+          {
+            "name":"新化县",
+            "code":"431322"
+          },
+          {
+            "name":"冷水江市",
+            "code":"431381"
+          },
+          {
+            "name":"涟源市",
+            "code":"431382"
+          }
+        ]
+      },
+      {
+        "name":"湘西土家族苗族自治州",
+        "code":"433100",
+        "sub":[
+          {
+            "name":"吉首市",
+            "code":"433101"
+          },
+          {
+            "name":"泸溪县",
+            "code":"433122"
+          },
+          {
+            "name":"凤凰县",
+            "code":"433123"
+          },
+          {
+            "name":"花垣县",
+            "code":"433124"
+          },
+          {
+            "name":"保靖县",
+            "code":"433125"
+          },
+          {
+            "name":"古丈县",
+            "code":"433126"
+          },
+          {
+            "name":"永顺县",
+            "code":"433127"
+          },
+          {
+            "name":"龙山县",
+            "code":"433130"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"广东省",
+    "code":"440000",
+    "sub":[
+      {
+        "name":"广州市",
+        "code":"440100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440101"
+          },
+          {
+            "name":"荔湾区",
+            "code":"440103"
+          },
+          {
+            "name":"越秀区",
+            "code":"440104"
+          },
+          {
+            "name":"海珠区",
+            "code":"440105"
+          },
+          {
+            "name":"天河区",
+            "code":"440106"
+          },
+          {
+            "name":"白云区",
+            "code":"440111"
+          },
+          {
+            "name":"黄埔区",
+            "code":"440112"
+          },
+          {
+            "name":"番禺区",
+            "code":"440113"
+          },
+          {
+            "name":"花都区",
+            "code":"440114"
+          },
+          {
+            "name":"南沙区",
+            "code":"440115"
+          },
+          {
+            "name":"从化区",
+            "code":"440117"
+          },
+          {
+            "name":"增城区",
+            "code":"440118"
+          }
+        ]
+      },
+      {
+        "name":"韶关市",
+        "code":"440200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440201"
+          },
+          {
+            "name":"武江区",
+            "code":"440203"
+          },
+          {
+            "name":"浈江区",
+            "code":"440204"
+          },
+          {
+            "name":"曲江区",
+            "code":"440205"
+          },
+          {
+            "name":"始兴县",
+            "code":"440222"
+          },
+          {
+            "name":"仁化县",
+            "code":"440224"
+          },
+          {
+            "name":"翁源县",
+            "code":"440229"
+          },
+          {
+            "name":"乳源瑶族自治县",
+            "code":"440232"
+          },
+          {
+            "name":"新丰县",
+            "code":"440233"
+          },
+          {
+            "name":"乐昌市",
+            "code":"440281"
+          },
+          {
+            "name":"南雄市",
+            "code":"440282"
+          }
+        ]
+      },
+      {
+        "name":"深圳市",
+        "code":"440300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440301"
+          },
+          {
+            "name":"罗湖区",
+            "code":"440303"
+          },
+          {
+            "name":"福田区",
+            "code":"440304"
+          },
+          {
+            "name":"南山区",
+            "code":"440305"
+          },
+          {
+            "name":"宝安区",
+            "code":"440306"
+          },
+          {
+            "name":"龙岗区",
+            "code":"440307"
+          },
+          {
+            "name":"盐田区",
+            "code":"440308"
+          }
+        ]
+      },
+      {
+        "name":"珠海市",
+        "code":"440400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440401"
+          },
+          {
+            "name":"香洲区",
+            "code":"440402"
+          },
+          {
+            "name":"斗门区",
+            "code":"440403"
+          },
+          {
+            "name":"金湾区",
+            "code":"440404"
+          }
+        ]
+      },
+      {
+        "name":"汕头市",
+        "code":"440500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440501"
+          },
+          {
+            "name":"龙湖区",
+            "code":"440507"
+          },
+          {
+            "name":"金平区",
+            "code":"440511"
+          },
+          {
+            "name":"濠江区",
+            "code":"440512"
+          },
+          {
+            "name":"潮阳区",
+            "code":"440513"
+          },
+          {
+            "name":"潮南区",
+            "code":"440514"
+          },
+          {
+            "name":"澄海区",
+            "code":"440515"
+          },
+          {
+            "name":"南澳县",
+            "code":"440523"
+          }
+        ]
+      },
+      {
+        "name":"佛山市",
+        "code":"440600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440601"
+          },
+          {
+            "name":"禅城区",
+            "code":"440604"
+          },
+          {
+            "name":"南海区",
+            "code":"440605"
+          },
+          {
+            "name":"顺德区",
+            "code":"440606"
+          },
+          {
+            "name":"三水区",
+            "code":"440607"
+          },
+          {
+            "name":"高明区",
+            "code":"440608"
+          }
+        ]
+      },
+      {
+        "name":"江门市",
+        "code":"440700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440701"
+          },
+          {
+            "name":"蓬江区",
+            "code":"440703"
+          },
+          {
+            "name":"江海区",
+            "code":"440704"
+          },
+          {
+            "name":"新会区",
+            "code":"440705"
+          },
+          {
+            "name":"台山市",
+            "code":"440781"
+          },
+          {
+            "name":"开平市",
+            "code":"440783"
+          },
+          {
+            "name":"鹤山市",
+            "code":"440784"
+          },
+          {
+            "name":"恩平市",
+            "code":"440785"
+          }
+        ]
+      },
+      {
+        "name":"湛江市",
+        "code":"440800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440801"
+          },
+          {
+            "name":"赤坎区",
+            "code":"440802"
+          },
+          {
+            "name":"霞山区",
+            "code":"440803"
+          },
+          {
+            "name":"坡头区",
+            "code":"440804"
+          },
+          {
+            "name":"麻章区",
+            "code":"440811"
+          },
+          {
+            "name":"遂溪县",
+            "code":"440823"
+          },
+          {
+            "name":"徐闻县",
+            "code":"440825"
+          },
+          {
+            "name":"廉江市",
+            "code":"440881"
+          },
+          {
+            "name":"雷州市",
+            "code":"440882"
+          },
+          {
+            "name":"吴川市",
+            "code":"440883"
+          }
+        ]
+      },
+      {
+        "name":"茂名市",
+        "code":"440900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440901"
+          },
+          {
+            "name":"茂南区",
+            "code":"440902"
+          },
+          {
+            "name":"电白区",
+            "code":"440904"
+          },
+          {
+            "name":"高州市",
+            "code":"440981"
+          },
+          {
+            "name":"化州市",
+            "code":"440982"
+          },
+          {
+            "name":"信宜市",
+            "code":"440983"
+          }
+        ]
+      },
+      {
+        "name":"肇庆市",
+        "code":"441200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441201"
+          },
+          {
+            "name":"端州区",
+            "code":"441202"
+          },
+          {
+            "name":"鼎湖区",
+            "code":"441203"
+          },
+          {
+            "name":"广宁县",
+            "code":"441223"
+          },
+          {
+            "name":"怀集县",
+            "code":"441224"
+          },
+          {
+            "name":"封开县",
+            "code":"441225"
+          },
+          {
+            "name":"德庆县",
+            "code":"441226"
+          },
+          {
+            "name":"高要市",
+            "code":"441283"
+          },
+          {
+            "name":"四会市",
+            "code":"441284"
+          }
+        ]
+      },
+      {
+        "name":"惠州市",
+        "code":"441300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441301"
+          },
+          {
+            "name":"惠城区",
+            "code":"441302"
+          },
+          {
+            "name":"惠阳区",
+            "code":"441303"
+          },
+          {
+            "name":"博罗县",
+            "code":"441322"
+          },
+          {
+            "name":"惠东县",
+            "code":"441323"
+          },
+          {
+            "name":"龙门县",
+            "code":"441324"
+          }
+        ]
+      },
+      {
+        "name":"梅州市",
+        "code":"441400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441401"
+          },
+          {
+            "name":"梅江区",
+            "code":"441402"
+          },
+          {
+            "name":"梅县区",
+            "code":"441403"
+          },
+          {
+            "name":"大埔县",
+            "code":"441422"
+          },
+          {
+            "name":"丰顺县",
+            "code":"441423"
+          },
+          {
+            "name":"五华县",
+            "code":"441424"
+          },
+          {
+            "name":"平远县",
+            "code":"441426"
+          },
+          {
+            "name":"蕉岭县",
+            "code":"441427"
+          },
+          {
+            "name":"兴宁市",
+            "code":"441481"
+          }
+        ]
+      },
+      {
+        "name":"汕尾市",
+        "code":"441500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441501"
+          },
+          {
+            "name":"城区",
+            "code":"441502"
+          },
+          {
+            "name":"海丰县",
+            "code":"441521"
+          },
+          {
+            "name":"陆河县",
+            "code":"441523"
+          },
+          {
+            "name":"陆丰市",
+            "code":"441581"
+          }
+        ]
+      },
+      {
+        "name":"河源市",
+        "code":"441600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441601"
+          },
+          {
+            "name":"源城区",
+            "code":"441602"
+          },
+          {
+            "name":"紫金县",
+            "code":"441621"
+          },
+          {
+            "name":"龙川县",
+            "code":"441622"
+          },
+          {
+            "name":"连平县",
+            "code":"441623"
+          },
+          {
+            "name":"和平县",
+            "code":"441624"
+          },
+          {
+            "name":"东源县",
+            "code":"441625"
+          }
+        ]
+      },
+      {
+        "name":"阳江市",
+        "code":"441700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441701"
+          },
+          {
+            "name":"江城区",
+            "code":"441702"
+          },
+          {
+            "name":"阳东区",
+            "code":"441704"
+          },
+          {
+            "name":"阳西县",
+            "code":"441721"
+          },
+          {
+            "name":"阳春市",
+            "code":"441781"
+          }
+        ]
+      },
+      {
+        "name":"清远市",
+        "code":"441800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441801"
+          },
+          {
+            "name":"清城区",
+            "code":"441802"
+          },
+          {
+            "name":"清新区",
+            "code":"441803"
+          },
+          {
+            "name":"佛冈县",
+            "code":"441821"
+          },
+          {
+            "name":"阳山县",
+            "code":"441823"
+          },
+          {
+            "name":"连山壮族瑶族自治县",
+            "code":"441825"
+          },
+          {
+            "name":"连南瑶族自治县",
+            "code":"441826"
+          },
+          {
+            "name":"英德市",
+            "code":"441881"
+          },
+          {
+            "name":"连州市",
+            "code":"441882"
+          }
+        ]
+      },
+      {
+        "name":"东莞市",
+        "code":"441900",
+        "sub":[
+
+        ]
+      },
+      {
+        "name":"中山市",
+        "code":"442000",
+        "sub":[
+
+        ]
+      },
+      {
+        "name":"潮州市",
+        "code":"445100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445101"
+          },
+          {
+            "name":"湘桥区",
+            "code":"445102"
+          },
+          {
+            "name":"潮安区",
+            "code":"445103"
+          },
+          {
+            "name":"饶平县",
+            "code":"445122"
+          }
+        ]
+      },
+      {
+        "name":"揭阳市",
+        "code":"445200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445201"
+          },
+          {
+            "name":"榕城区",
+            "code":"445202"
+          },
+          {
+            "name":"揭东区",
+            "code":"445203"
+          },
+          {
+            "name":"揭西县",
+            "code":"445222"
+          },
+          {
+            "name":"惠来县",
+            "code":"445224"
+          },
+          {
+            "name":"普宁市",
+            "code":"445281"
+          }
+        ]
+      },
+      {
+        "name":"云浮市",
+        "code":"445300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445301"
+          },
+          {
+            "name":"云城区",
+            "code":"445302"
+          },
+          {
+            "name":"云安区",
+            "code":"445303"
+          },
+          {
+            "name":"新兴县",
+            "code":"445321"
+          },
+          {
+            "name":"郁南县",
+            "code":"445322"
+          },
+          {
+            "name":"罗定市",
+            "code":"445381"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"广西壮族自治区",
+    "code":"450000",
+    "sub":[
+      {
+        "name":"南宁市",
+        "code":"450100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450101"
+          },
+          {
+            "name":"兴宁区",
+            "code":"450102"
+          },
+          {
+            "name":"青秀区",
+            "code":"450103"
+          },
+          {
+            "name":"江南区",
+            "code":"450105"
+          },
+          {
+            "name":"西乡塘区",
+            "code":"450107"
+          },
+          {
+            "name":"良庆区",
+            "code":"450108"
+          },
+          {
+            "name":"邕宁区",
+            "code":"450109"
+          },
+          {
+            "name":"武鸣县",
+            "code":"450122"
+          },
+          {
+            "name":"隆安县",
+            "code":"450123"
+          },
+          {
+            "name":"马山县",
+            "code":"450124"
+          },
+          {
+            "name":"上林县",
+            "code":"450125"
+          },
+          {
+            "name":"宾阳县",
+            "code":"450126"
+          },
+          {
+            "name":"横县",
+            "code":"450127"
+          }
+        ]
+      },
+      {
+        "name":"柳州市",
+        "code":"450200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450201"
+          },
+          {
+            "name":"城中区",
+            "code":"450202"
+          },
+          {
+            "name":"鱼峰区",
+            "code":"450203"
+          },
+          {
+            "name":"柳南区",
+            "code":"450204"
+          },
+          {
+            "name":"柳北区",
+            "code":"450205"
+          },
+          {
+            "name":"柳江县",
+            "code":"450221"
+          },
+          {
+            "name":"柳城县",
+            "code":"450222"
+          },
+          {
+            "name":"鹿寨县",
+            "code":"450223"
+          },
+          {
+            "name":"融安县",
+            "code":"450224"
+          },
+          {
+            "name":"融水苗族自治县",
+            "code":"450225"
+          },
+          {
+            "name":"三江侗族自治县",
+            "code":"450226"
+          }
+        ]
+      },
+      {
+        "name":"桂林市",
+        "code":"450300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450301"
+          },
+          {
+            "name":"秀峰区",
+            "code":"450302"
+          },
+          {
+            "name":"叠彩区",
+            "code":"450303"
+          },
+          {
+            "name":"象山区",
+            "code":"450304"
+          },
+          {
+            "name":"七星区",
+            "code":"450305"
+          },
+          {
+            "name":"雁山区",
+            "code":"450311"
+          },
+          {
+            "name":"临桂区",
+            "code":"450312"
+          },
+          {
+            "name":"阳朔县",
+            "code":"450321"
+          },
+          {
+            "name":"灵川县",
+            "code":"450323"
+          },
+          {
+            "name":"全州县",
+            "code":"450324"
+          },
+          {
+            "name":"兴安县",
+            "code":"450325"
+          },
+          {
+            "name":"永福县",
+            "code":"450326"
+          },
+          {
+            "name":"灌阳县",
+            "code":"450327"
+          },
+          {
+            "name":"龙胜各族自治县",
+            "code":"450328"
+          },
+          {
+            "name":"资源县",
+            "code":"450329"
+          },
+          {
+            "name":"平乐县",
+            "code":"450330"
+          },
+          {
+            "name":"荔浦县",
+            "code":"450331"
+          },
+          {
+            "name":"恭城瑶族自治县",
+            "code":"450332"
+          }
+        ]
+      },
+      {
+        "name":"梧州市",
+        "code":"450400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450401"
+          },
+          {
+            "name":"万秀区",
+            "code":"450403"
+          },
+          {
+            "name":"长洲区",
+            "code":"450405"
+          },
+          {
+            "name":"龙圩区",
+            "code":"450406"
+          },
+          {
+            "name":"苍梧县",
+            "code":"450421"
+          },
+          {
+            "name":"藤县",
+            "code":"450422"
+          },
+          {
+            "name":"蒙山县",
+            "code":"450423"
+          },
+          {
+            "name":"岑溪市",
+            "code":"450481"
+          }
+        ]
+      },
+      {
+        "name":"北海市",
+        "code":"450500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450501"
+          },
+          {
+            "name":"海城区",
+            "code":"450502"
+          },
+          {
+            "name":"银海区",
+            "code":"450503"
+          },
+          {
+            "name":"铁山港区",
+            "code":"450512"
+          },
+          {
+            "name":"合浦县",
+            "code":"450521"
+          }
+        ]
+      },
+      {
+        "name":"防城港市",
+        "code":"450600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450601"
+          },
+          {
+            "name":"港口区",
+            "code":"450602"
+          },
+          {
+            "name":"防城区",
+            "code":"450603"
+          },
+          {
+            "name":"上思县",
+            "code":"450621"
+          },
+          {
+            "name":"东兴市",
+            "code":"450681"
+          }
+        ]
+      },
+      {
+        "name":"钦州市",
+        "code":"450700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450701"
+          },
+          {
+            "name":"钦南区",
+            "code":"450702"
+          },
+          {
+            "name":"钦北区",
+            "code":"450703"
+          },
+          {
+            "name":"灵山县",
+            "code":"450721"
+          },
+          {
+            "name":"浦北县",
+            "code":"450722"
+          }
+        ]
+      },
+      {
+        "name":"贵港市",
+        "code":"450800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450801"
+          },
+          {
+            "name":"港北区",
+            "code":"450802"
+          },
+          {
+            "name":"港南区",
+            "code":"450803"
+          },
+          {
+            "name":"覃塘区",
+            "code":"450804"
+          },
+          {
+            "name":"平南县",
+            "code":"450821"
+          },
+          {
+            "name":"桂平市",
+            "code":"450881"
+          }
+        ]
+      },
+      {
+        "name":"玉林市",
+        "code":"450900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450901"
+          },
+          {
+            "name":"玉州区",
+            "code":"450902"
+          },
+          {
+            "name":"福绵区",
+            "code":"450903"
+          },
+          {
+            "name":"容县",
+            "code":"450921"
+          },
+          {
+            "name":"陆川县",
+            "code":"450922"
+          },
+          {
+            "name":"博白县",
+            "code":"450923"
+          },
+          {
+            "name":"兴业县",
+            "code":"450924"
+          },
+          {
+            "name":"北流市",
+            "code":"450981"
+          }
+        ]
+      },
+      {
+        "name":"百色市",
+        "code":"451000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451001"
+          },
+          {
+            "name":"右江区",
+            "code":"451002"
+          },
+          {
+            "name":"田阳县",
+            "code":"451021"
+          },
+          {
+            "name":"田东县",
+            "code":"451022"
+          },
+          {
+            "name":"平果县",
+            "code":"451023"
+          },
+          {
+            "name":"德保县",
+            "code":"451024"
+          },
+          {
+            "name":"靖西县",
+            "code":"451025"
+          },
+          {
+            "name":"那坡县",
+            "code":"451026"
+          },
+          {
+            "name":"凌云县",
+            "code":"451027"
+          },
+          {
+            "name":"乐业县",
+            "code":"451028"
+          },
+          {
+            "name":"田林县",
+            "code":"451029"
+          },
+          {
+            "name":"西林县",
+            "code":"451030"
+          },
+          {
+            "name":"隆林各族自治县",
+            "code":"451031"
+          }
+        ]
+      },
+      {
+        "name":"贺州市",
+        "code":"451100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451101"
+          },
+          {
+            "name":"八步区",
+            "code":"451102"
+          },
+          {
+            "name":"平桂管理区",
+            "code":"451119"
+          },
+          {
+            "name":"昭平县",
+            "code":"451121"
+          },
+          {
+            "name":"钟山县",
+            "code":"451122"
+          },
+          {
+            "name":"富川瑶族自治县",
+            "code":"451123"
+          }
+        ]
+      },
+      {
+        "name":"河池市",
+        "code":"451200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451201"
+          },
+          {
+            "name":"金城江区",
+            "code":"451202"
+          },
+          {
+            "name":"南丹县",
+            "code":"451221"
+          },
+          {
+            "name":"天峨县",
+            "code":"451222"
+          },
+          {
+            "name":"凤山县",
+            "code":"451223"
+          },
+          {
+            "name":"东兰县",
+            "code":"451224"
+          },
+          {
+            "name":"罗城仫佬族自治县",
+            "code":"451225"
+          },
+          {
+            "name":"环江毛南族自治县",
+            "code":"451226"
+          },
+          {
+            "name":"巴马瑶族自治县",
+            "code":"451227"
+          },
+          {
+            "name":"都安瑶族自治县",
+            "code":"451228"
+          },
+          {
+            "name":"大化瑶族自治县",
+            "code":"451229"
+          },
+          {
+            "name":"宜州市",
+            "code":"451281"
+          }
+        ]
+      },
+      {
+        "name":"来宾市",
+        "code":"451300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451301"
+          },
+          {
+            "name":"兴宾区",
+            "code":"451302"
+          },
+          {
+            "name":"忻城县",
+            "code":"451321"
+          },
+          {
+            "name":"象州县",
+            "code":"451322"
+          },
+          {
+            "name":"武宣县",
+            "code":"451323"
+          },
+          {
+            "name":"金秀瑶族自治县",
+            "code":"451324"
+          },
+          {
+            "name":"合山市",
+            "code":"451381"
+          }
+        ]
+      },
+      {
+        "name":"崇左市",
+        "code":"451400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451401"
+          },
+          {
+            "name":"江州区",
+            "code":"451402"
+          },
+          {
+            "name":"扶绥县",
+            "code":"451421"
+          },
+          {
+            "name":"宁明县",
+            "code":"451422"
+          },
+          {
+            "name":"龙州县",
+            "code":"451423"
+          },
+          {
+            "name":"大新县",
+            "code":"451424"
+          },
+          {
+            "name":"天等县",
+            "code":"451425"
+          },
+          {
+            "name":"凭祥市",
+            "code":"451481"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"海南省",
+    "code":"460000",
+    "sub":[
+      {
+        "name":"海口市",
+        "code":"460100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"460101"
+          },
+          {
+            "name":"秀英区",
+            "code":"460105"
+          },
+          {
+            "name":"龙华区",
+            "code":"460106"
+          },
+          {
+            "name":"琼山区",
+            "code":"460107"
+          },
+          {
+            "name":"美兰区",
+            "code":"460108"
+          }
+        ]
+      },
+      {
+        "name":"三亚市",
+        "code":"460200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"460201"
+          },
+          {
+            "name":"海棠区",
+            "code":"460202"
+          },
+          {
+            "name":"吉阳区",
+            "code":"460203"
+          },
+          {
+            "name":"天涯区",
+            "code":"460204"
+          },
+          {
+            "name":"崖州区",
+            "code":"460205"
+          }
+        ]
+      },
+      {
+        "name":"三沙市",
+        "code":"460300",
+        "sub":[
+          {
+            "name":"西沙群岛",
+            "code":"460321"
+          },
+          {
+            "name":"南沙群岛",
+            "code":"460322"
+          },
+          {
+            "name":"中沙群岛的岛礁及其海域",
+            "code":"460323"
+          }
+        ]
+      },
+      {
+        "name":"五指山市",
+        "code":"469001"
+      },
+      {
+        "name":"琼海市",
+        "code":"469002"
+      },
+      {
+        "name":"儋州市",
+        "code":"469003"
+      },
+      {
+        "name":"文昌市",
+        "code":"469005"
+      },
+      {
+        "name":"万宁市",
+        "code":"469006"
+      },
+      {
+        "name":"东方市",
+        "code":"469007"
+      },
+      {
+        "name":"定安县",
+        "code":"469021"
+      },
+      {
+        "name":"屯昌县",
+        "code":"469022"
+      },
+      {
+        "name":"澄迈县",
+        "code":"469023"
+      },
+      {
+        "name":"临高县",
+        "code":"469024"
+      },
+      {
+        "name":"白沙黎族自治县",
+        "code":"469025"
+      },
+      {
+        "name":"昌江黎族自治县",
+        "code":"469026"
+      },
+      {
+        "name":"乐东黎族自治县",
+        "code":"469027"
+      },
+      {
+        "name":"陵水黎族自治县",
+        "code":"469028"
+      },
+      {
+        "name":"保亭黎族苗族自治县",
+        "code":"469029"
+      },
+      {
+        "name":"琼中黎族苗族自治县",
+        "code":"469030"
+      }
+    ]
+  },
+  {
+    "name":"重庆",
+    "code":"500000",
+    "sub": [
+      {
+        "name": "重庆市",
+        "code": "500000",
+        "sub":[
+            {
+              "name":"万州区",
+              "code":"500101"
+            },
+            {
+              "name":"涪陵区",
+              "code":"500102"
+            },
+            {
+              "name":"渝中区",
+              "code":"500103"
+            },
+            {
+              "name":"大渡口区",
+              "code":"500104"
+            },
+            {
+              "name":"江北区",
+              "code":"500105"
+            },
+            {
+              "name":"沙坪坝区",
+              "code":"500106"
+            },
+            {
+              "name":"九龙坡区",
+              "code":"500107"
+            },
+            {
+              "name":"南岸区",
+              "code":"500108"
+            },
+            {
+              "name":"北碚区",
+              "code":"500109"
+            },
+            {
+              "name":"綦江区",
+              "code":"500110"
+            },
+            {
+              "name":"大足区",
+              "code":"500111"
+            },
+            {
+              "name":"渝北区",
+              "code":"500112"
+            },
+            {
+              "name":"巴南区",
+              "code":"500113"
+            },
+            {
+              "name":"黔江区",
+              "code":"500114"
+            },
+            {
+              "name":"长寿区",
+              "code":"500115"
+            },
+            {
+              "name":"江津区",
+              "code":"500116"
+            },
+            {
+              "name":"合川区",
+              "code":"500117"
+            },
+            {
+              "name":"永川区",
+              "code":"500118"
+            },
+            {
+              "name":"南川区",
+              "code":"500119"
+            },
+            {
+              "name":"璧山区",
+              "code":"500120"
+            },
+            {
+              "name":"铜梁区",
+              "code":"500151"
+            },
+            {
+              "name":"潼南县",
+              "code":"500223"
+            },
+            {
+              "name":"荣昌县",
+              "code":"500226"
+            },
+            {
+              "name":"梁平县",
+              "code":"500228"
+            },
+            {
+              "name":"城口县",
+              "code":"500229"
+            },
+            {
+              "name":"丰都县",
+              "code":"500230"
+            },
+            {
+              "name":"垫江县",
+              "code":"500231"
+            },
+            {
+              "name":"武隆县",
+              "code":"500232"
+            },
+            {
+              "name":"忠县",
+              "code":"500233"
+            },
+            {
+              "name":"开县",
+              "code":"500234"
+            },
+            {
+              "name":"云阳县",
+              "code":"500235"
+            },
+            {
+              "name":"奉节县",
+              "code":"500236"
+            },
+            {
+              "name":"巫山县",
+              "code":"500237"
+            },
+            {
+              "name":"巫溪县",
+              "code":"500238"
+            },
+            {
+              "name":"石柱土家族自治县",
+              "code":"500240"
+            },
+            {
+              "name":"秀山土家族苗族自治县",
+              "code":"500241"
+            },
+            {
+              "name":"酉阳土家族苗族自治县",
+              "code":"500242"
+            },
+            {
+              "name":"彭水苗族土家族自治县",
+              "code":"500243"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"四川省",
+    "code":"510000",
+    "sub":[
+      {
+        "name":"成都市",
+        "code":"510100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510101"
+          },
+          {
+            "name":"锦江区",
+            "code":"510104"
+          },
+          {
+            "name":"青羊区",
+            "code":"510105"
+          },
+          {
+            "name":"金牛区",
+            "code":"510106"
+          },
+          {
+            "name":"武侯区",
+            "code":"510107"
+          },
+          {
+            "name":"成华区",
+            "code":"510108"
+          },
+          {
+            "name":"龙泉驿区",
+            "code":"510112"
+          },
+          {
+            "name":"青白江区",
+            "code":"510113"
+          },
+          {
+            "name":"新都区",
+            "code":"510114"
+          },
+          {
+            "name":"温江区",
+            "code":"510115"
+          },
+          {
+            "name":"金堂县",
+            "code":"510121"
+          },
+          {
+            "name":"双流县",
+            "code":"510122"
+          },
+          {
+            "name":"郫县",
+            "code":"510124"
+          },
+          {
+            "name":"大邑县",
+            "code":"510129"
+          },
+          {
+            "name":"蒲江县",
+            "code":"510131"
+          },
+          {
+            "name":"新津县",
+            "code":"510132"
+          },
+          {
+            "name":"都江堰市",
+            "code":"510181"
+          },
+          {
+            "name":"彭州市",
+            "code":"510182"
+          },
+          {
+            "name":"邛崃市",
+            "code":"510183"
+          },
+          {
+            "name":"崇州市",
+            "code":"510184"
+          }
+        ]
+      },
+      {
+        "name":"自贡市",
+        "code":"510300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510301"
+          },
+          {
+            "name":"自流井区",
+            "code":"510302"
+          },
+          {
+            "name":"贡井区",
+            "code":"510303"
+          },
+          {
+            "name":"大安区",
+            "code":"510304"
+          },
+          {
+            "name":"沿滩区",
+            "code":"510311"
+          },
+          {
+            "name":"荣县",
+            "code":"510321"
+          },
+          {
+            "name":"富顺县",
+            "code":"510322"
+          }
+        ]
+      },
+      {
+        "name":"攀枝花市",
+        "code":"510400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510401"
+          },
+          {
+            "name":"东区",
+            "code":"510402"
+          },
+          {
+            "name":"西区",
+            "code":"510403"
+          },
+          {
+            "name":"仁和区",
+            "code":"510411"
+          },
+          {
+            "name":"米易县",
+            "code":"510421"
+          },
+          {
+            "name":"盐边县",
+            "code":"510422"
+          }
+        ]
+      },
+      {
+        "name":"泸州市",
+        "code":"510500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510501"
+          },
+          {
+            "name":"江阳区",
+            "code":"510502"
+          },
+          {
+            "name":"纳溪区",
+            "code":"510503"
+          },
+          {
+            "name":"龙马潭区",
+            "code":"510504"
+          },
+          {
+            "name":"泸县",
+            "code":"510521"
+          },
+          {
+            "name":"合江县",
+            "code":"510522"
+          },
+          {
+            "name":"叙永县",
+            "code":"510524"
+          },
+          {
+            "name":"古蔺县",
+            "code":"510525"
+          }
+        ]
+      },
+      {
+        "name":"德阳市",
+        "code":"510600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510601"
+          },
+          {
+            "name":"旌阳区",
+            "code":"510603"
+          },
+          {
+            "name":"中江县",
+            "code":"510623"
+          },
+          {
+            "name":"罗江县",
+            "code":"510626"
+          },
+          {
+            "name":"广汉市",
+            "code":"510681"
+          },
+          {
+            "name":"什邡市",
+            "code":"510682"
+          },
+          {
+            "name":"绵竹市",
+            "code":"510683"
+          }
+        ]
+      },
+      {
+        "name":"绵阳市",
+        "code":"510700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510701"
+          },
+          {
+            "name":"涪城区",
+            "code":"510703"
+          },
+          {
+            "name":"游仙区",
+            "code":"510704"
+          },
+          {
+            "name":"三台县",
+            "code":"510722"
+          },
+          {
+            "name":"盐亭县",
+            "code":"510723"
+          },
+          {
+            "name":"安县",
+            "code":"510724"
+          },
+          {
+            "name":"梓潼县",
+            "code":"510725"
+          },
+          {
+            "name":"北川羌族自治县",
+            "code":"510726"
+          },
+          {
+            "name":"平武县",
+            "code":"510727"
+          },
+          {
+            "name":"江油市",
+            "code":"510781"
+          }
+        ]
+      },
+      {
+        "name":"广元市",
+        "code":"510800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510801"
+          },
+          {
+            "name":"利州区",
+            "code":"510802"
+          },
+          {
+            "name":"昭化区",
+            "code":"510811"
+          },
+          {
+            "name":"朝天区",
+            "code":"510812"
+          },
+          {
+            "name":"旺苍县",
+            "code":"510821"
+          },
+          {
+            "name":"青川县",
+            "code":"510822"
+          },
+          {
+            "name":"剑阁县",
+            "code":"510823"
+          },
+          {
+            "name":"苍溪县",
+            "code":"510824"
+          }
+        ]
+      },
+      {
+        "name":"遂宁市",
+        "code":"510900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510901"
+          },
+          {
+            "name":"船山区",
+            "code":"510903"
+          },
+          {
+            "name":"安居区",
+            "code":"510904"
+          },
+          {
+            "name":"蓬溪县",
+            "code":"510921"
+          },
+          {
+            "name":"射洪县",
+            "code":"510922"
+          },
+          {
+            "name":"大英县",
+            "code":"510923"
+          }
+        ]
+      },
+      {
+        "name":"内江市",
+        "code":"511000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511001"
+          },
+          {
+            "name":"市中区",
+            "code":"511002"
+          },
+          {
+            "name":"东兴区",
+            "code":"511011"
+          },
+          {
+            "name":"威远县",
+            "code":"511024"
+          },
+          {
+            "name":"资中县",
+            "code":"511025"
+          },
+          {
+            "name":"隆昌县",
+            "code":"511028"
+          }
+        ]
+      },
+      {
+        "name":"乐山市",
+        "code":"511100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511101"
+          },
+          {
+            "name":"市中区",
+            "code":"511102"
+          },
+          {
+            "name":"沙湾区",
+            "code":"511111"
+          },
+          {
+            "name":"五通桥区",
+            "code":"511112"
+          },
+          {
+            "name":"金口河区",
+            "code":"511113"
+          },
+          {
+            "name":"犍为县",
+            "code":"511123"
+          },
+          {
+            "name":"井研县",
+            "code":"511124"
+          },
+          {
+            "name":"夹江县",
+            "code":"511126"
+          },
+          {
+            "name":"沐川县",
+            "code":"511129"
+          },
+          {
+            "name":"峨边彝族自治县",
+            "code":"511132"
+          },
+          {
+            "name":"马边彝族自治县",
+            "code":"511133"
+          },
+          {
+            "name":"峨眉山市",
+            "code":"511181"
+          }
+        ]
+      },
+      {
+        "name":"南充市",
+        "code":"511300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511301"
+          },
+          {
+            "name":"顺庆区",
+            "code":"511302"
+          },
+          {
+            "name":"高坪区",
+            "code":"511303"
+          },
+          {
+            "name":"嘉陵区",
+            "code":"511304"
+          },
+          {
+            "name":"南部县",
+            "code":"511321"
+          },
+          {
+            "name":"营山县",
+            "code":"511322"
+          },
+          {
+            "name":"蓬安县",
+            "code":"511323"
+          },
+          {
+            "name":"仪陇县",
+            "code":"511324"
+          },
+          {
+            "name":"西充县",
+            "code":"511325"
+          },
+          {
+            "name":"阆中市",
+            "code":"511381"
+          }
+        ]
+      },
+      {
+        "name":"眉山市",
+        "code":"511400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511401"
+          },
+          {
+            "name":"东坡区",
+            "code":"511402"
+          },
+          {
+            "name":"彭山区",
+            "code":"511403"
+          },
+          {
+            "name":"仁寿县",
+            "code":"511421"
+          },
+          {
+            "name":"洪雅县",
+            "code":"511423"
+          },
+          {
+            "name":"丹棱县",
+            "code":"511424"
+          },
+          {
+            "name":"青神县",
+            "code":"511425"
+          }
+        ]
+      },
+      {
+        "name":"宜宾市",
+        "code":"511500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511501"
+          },
+          {
+            "name":"翠屏区",
+            "code":"511502"
+          },
+          {
+            "name":"南溪区",
+            "code":"511503"
+          },
+          {
+            "name":"宜宾县",
+            "code":"511521"
+          },
+          {
+            "name":"江安县",
+            "code":"511523"
+          },
+          {
+            "name":"长宁县",
+            "code":"511524"
+          },
+          {
+            "name":"高县",
+            "code":"511525"
+          },
+          {
+            "name":"珙县",
+            "code":"511526"
+          },
+          {
+            "name":"筠连县",
+            "code":"511527"
+          },
+          {
+            "name":"兴文县",
+            "code":"511528"
+          },
+          {
+            "name":"屏山县",
+            "code":"511529"
+          }
+        ]
+      },
+      {
+        "name":"广安市",
+        "code":"511600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511601"
+          },
+          {
+            "name":"广安区",
+            "code":"511602"
+          },
+          {
+            "name":"前锋区",
+            "code":"511603"
+          },
+          {
+            "name":"岳池县",
+            "code":"511621"
+          },
+          {
+            "name":"武胜县",
+            "code":"511622"
+          },
+          {
+            "name":"邻水县",
+            "code":"511623"
+          },
+          {
+            "name":"华蓥市",
+            "code":"511681"
+          }
+        ]
+      },
+      {
+        "name":"达州市",
+        "code":"511700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511701"
+          },
+          {
+            "name":"通川区",
+            "code":"511702"
+          },
+          {
+            "name":"达川区",
+            "code":"511703"
+          },
+          {
+            "name":"宣汉县",
+            "code":"511722"
+          },
+          {
+            "name":"开江县",
+            "code":"511723"
+          },
+          {
+            "name":"大竹县",
+            "code":"511724"
+          },
+          {
+            "name":"渠县",
+            "code":"511725"
+          },
+          {
+            "name":"万源市",
+            "code":"511781"
+          }
+        ]
+      },
+      {
+        "name":"雅安市",
+        "code":"511800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511801"
+          },
+          {
+            "name":"雨城区",
+            "code":"511802"
+          },
+          {
+            "name":"名山区",
+            "code":"511803"
+          },
+          {
+            "name":"荥经县",
+            "code":"511822"
+          },
+          {
+            "name":"汉源县",
+            "code":"511823"
+          },
+          {
+            "name":"石棉县",
+            "code":"511824"
+          },
+          {
+            "name":"天全县",
+            "code":"511825"
+          },
+          {
+            "name":"芦山县",
+            "code":"511826"
+          },
+          {
+            "name":"宝兴县",
+            "code":"511827"
+          }
+        ]
+      },
+      {
+        "name":"巴中市",
+        "code":"511900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511901"
+          },
+          {
+            "name":"巴州区",
+            "code":"511902"
+          },
+          {
+            "name":"恩阳区",
+            "code":"511903"
+          },
+          {
+            "name":"通江县",
+            "code":"511921"
+          },
+          {
+            "name":"南江县",
+            "code":"511922"
+          },
+          {
+            "name":"平昌县",
+            "code":"511923"
+          }
+        ]
+      },
+      {
+        "name":"资阳市",
+        "code":"512000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"512001"
+          },
+          {
+            "name":"雁江区",
+            "code":"512002"
+          },
+          {
+            "name":"安岳县",
+            "code":"512021"
+          },
+          {
+            "name":"乐至县",
+            "code":"512022"
+          },
+          {
+            "name":"简阳市",
+            "code":"512081"
+          }
+        ]
+      },
+      {
+        "name":"阿坝藏族羌族自治州",
+        "code":"513200",
+        "sub":[
+          {
+            "name":"汶川县",
+            "code":"513221"
+          },
+          {
+            "name":"理县",
+            "code":"513222"
+          },
+          {
+            "name":"茂县",
+            "code":"513223"
+          },
+          {
+            "name":"松潘县",
+            "code":"513224"
+          },
+          {
+            "name":"九寨沟县",
+            "code":"513225"
+          },
+          {
+            "name":"金川县",
+            "code":"513226"
+          },
+          {
+            "name":"小金县",
+            "code":"513227"
+          },
+          {
+            "name":"黑水县",
+            "code":"513228"
+          },
+          {
+            "name":"马尔康县",
+            "code":"513229"
+          },
+          {
+            "name":"壤塘县",
+            "code":"513230"
+          },
+          {
+            "name":"阿坝县",
+            "code":"513231"
+          },
+          {
+            "name":"若尔盖县",
+            "code":"513232"
+          },
+          {
+            "name":"红原县",
+            "code":"513233"
+          }
+        ]
+      },
+      {
+        "name":"甘孜藏族自治州",
+        "code":"513300",
+        "sub":[
+          {
+            "name":"康定县",
+            "code":"513321"
+          },
+          {
+            "name":"泸定县",
+            "code":"513322"
+          },
+          {
+            "name":"丹巴县",
+            "code":"513323"
+          },
+          {
+            "name":"九龙县",
+            "code":"513324"
+          },
+          {
+            "name":"雅江县",
+            "code":"513325"
+          },
+          {
+            "name":"道孚县",
+            "code":"513326"
+          },
+          {
+            "name":"炉霍县",
+            "code":"513327"
+          },
+          {
+            "name":"甘孜县",
+            "code":"513328"
+          },
+          {
+            "name":"新龙县",
+            "code":"513329"
+          },
+          {
+            "name":"德格县",
+            "code":"513330"
+          },
+          {
+            "name":"白玉县",
+            "code":"513331"
+          },
+          {
+            "name":"石渠县",
+            "code":"513332"
+          },
+          {
+            "name":"色达县",
+            "code":"513333"
+          },
+          {
+            "name":"理塘县",
+            "code":"513334"
+          },
+          {
+            "name":"巴塘县",
+            "code":"513335"
+          },
+          {
+            "name":"乡城县",
+            "code":"513336"
+          },
+          {
+            "name":"稻城县",
+            "code":"513337"
+          },
+          {
+            "name":"得荣县",
+            "code":"513338"
+          }
+        ]
+      },
+      {
+        "name":"凉山彝族自治州",
+        "code":"513400",
+        "sub":[
+          {
+            "name":"西昌市",
+            "code":"513401"
+          },
+          {
+            "name":"木里藏族自治县",
+            "code":"513422"
+          },
+          {
+            "name":"盐源县",
+            "code":"513423"
+          },
+          {
+            "name":"德昌县",
+            "code":"513424"
+          },
+          {
+            "name":"会理县",
+            "code":"513425"
+          },
+          {
+            "name":"会东县",
+            "code":"513426"
+          },
+          {
+            "name":"宁南县",
+            "code":"513427"
+          },
+          {
+            "name":"普格县",
+            "code":"513428"
+          },
+          {
+            "name":"布拖县",
+            "code":"513429"
+          },
+          {
+            "name":"金阳县",
+            "code":"513430"
+          },
+          {
+            "name":"昭觉县",
+            "code":"513431"
+          },
+          {
+            "name":"喜德县",
+            "code":"513432"
+          },
+          {
+            "name":"冕宁县",
+            "code":"513433"
+          },
+          {
+            "name":"越西县",
+            "code":"513434"
+          },
+          {
+            "name":"甘洛县",
+            "code":"513435"
+          },
+          {
+            "name":"美姑县",
+            "code":"513436"
+          },
+          {
+            "name":"雷波县",
+            "code":"513437"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"贵州省",
+    "code":"520000",
+    "sub":[
+      {
+        "name":"贵阳市",
+        "code":"520100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520101"
+          },
+          {
+            "name":"南明区",
+            "code":"520102"
+          },
+          {
+            "name":"云岩区",
+            "code":"520103"
+          },
+          {
+            "name":"花溪区",
+            "code":"520111"
+          },
+          {
+            "name":"乌当区",
+            "code":"520112"
+          },
+          {
+            "name":"白云区",
+            "code":"520113"
+          },
+          {
+            "name":"观山湖区",
+            "code":"520115"
+          },
+          {
+            "name":"开阳县",
+            "code":"520121"
+          },
+          {
+            "name":"息烽县",
+            "code":"520122"
+          },
+          {
+            "name":"修文县",
+            "code":"520123"
+          },
+          {
+            "name":"清镇市",
+            "code":"520181"
+          }
+        ]
+      },
+      {
+        "name":"六盘水市",
+        "code":"520200",
+        "sub":[
+          {
+            "name":"钟山区",
+            "code":"520201"
+          },
+          {
+            "name":"六枝特区",
+            "code":"520203"
+          },
+          {
+            "name":"水城县",
+            "code":"520221"
+          },
+          {
+            "name":"盘县",
+            "code":"520222"
+          }
+        ]
+      },
+      {
+        "name":"遵义市",
+        "code":"520300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520301"
+          },
+          {
+            "name":"红花岗区",
+            "code":"520302"
+          },
+          {
+            "name":"汇川区",
+            "code":"520303"
+          },
+          {
+            "name":"遵义县",
+            "code":"520321"
+          },
+          {
+            "name":"桐梓县",
+            "code":"520322"
+          },
+          {
+            "name":"绥阳县",
+            "code":"520323"
+          },
+          {
+            "name":"正安县",
+            "code":"520324"
+          },
+          {
+            "name":"道真仡佬族苗族自治县",
+            "code":"520325"
+          },
+          {
+            "name":"务川仡佬族苗族自治县",
+            "code":"520326"
+          },
+          {
+            "name":"凤冈县",
+            "code":"520327"
+          },
+          {
+            "name":"湄潭县",
+            "code":"520328"
+          },
+          {
+            "name":"余庆县",
+            "code":"520329"
+          },
+          {
+            "name":"习水县",
+            "code":"520330"
+          },
+          {
+            "name":"赤水市",
+            "code":"520381"
+          },
+          {
+            "name":"仁怀市",
+            "code":"520382"
+          }
+        ]
+      },
+      {
+        "name":"安顺市",
+        "code":"520400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520401"
+          },
+          {
+            "name":"西秀区",
+            "code":"520402"
+          },
+          {
+            "name":"平坝区",
+            "code":"520403"
+          },
+          {
+            "name":"普定县",
+            "code":"520422"
+          },
+          {
+            "name":"镇宁布依族苗族自治县",
+            "code":"520423"
+          },
+          {
+            "name":"关岭布依族苗族自治县",
+            "code":"520424"
+          },
+          {
+            "name":"紫云苗族布依族自治县",
+            "code":"520425"
+          }
+        ]
+      },
+      {
+        "name":"毕节市",
+        "code":"520500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520501"
+          },
+          {
+            "name":"七星关区",
+            "code":"520502"
+          },
+          {
+            "name":"大方县",
+            "code":"520521"
+          },
+          {
+            "name":"黔西县",
+            "code":"520522"
+          },
+          {
+            "name":"金沙县",
+            "code":"520523"
+          },
+          {
+            "name":"织金县",
+            "code":"520524"
+          },
+          {
+            "name":"纳雍县",
+            "code":"520525"
+          },
+          {
+            "name":"威宁彝族回族苗族自治县",
+            "code":"520526"
+          },
+          {
+            "name":"赫章县",
+            "code":"520527"
+          }
+        ]
+      },
+      {
+        "name":"铜仁市",
+        "code":"520600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520601"
+          },
+          {
+            "name":"碧江区",
+            "code":"520602"
+          },
+          {
+            "name":"万山区",
+            "code":"520603"
+          },
+          {
+            "name":"江口县",
+            "code":"520621"
+          },
+          {
+            "name":"玉屏侗族自治县",
+            "code":"520622"
+          },
+          {
+            "name":"石阡县",
+            "code":"520623"
+          },
+          {
+            "name":"思南县",
+            "code":"520624"
+          },
+          {
+            "name":"印江土家族苗族自治县",
+            "code":"520625"
+          },
+          {
+            "name":"德江县",
+            "code":"520626"
+          },
+          {
+            "name":"沿河土家族自治县",
+            "code":"520627"
+          },
+          {
+            "name":"松桃苗族自治县",
+            "code":"520628"
+          }
+        ]
+      },
+      {
+        "name":"黔西南布依族苗族自治州",
+        "code":"522300",
+        "sub":[
+          {
+            "name":"兴义市",
+            "code":"522301"
+          },
+          {
+            "name":"兴仁县",
+            "code":"522322"
+          },
+          {
+            "name":"普安县",
+            "code":"522323"
+          },
+          {
+            "name":"晴隆县",
+            "code":"522324"
+          },
+          {
+            "name":"贞丰县",
+            "code":"522325"
+          },
+          {
+            "name":"望谟县",
+            "code":"522326"
+          },
+          {
+            "name":"册亨县",
+            "code":"522327"
+          },
+          {
+            "name":"安龙县",
+            "code":"522328"
+          }
+        ]
+      },
+      {
+        "name":"黔东南苗族侗族自治州",
+        "code":"522600",
+        "sub":[
+          {
+            "name":"凯里市",
+            "code":"522601"
+          },
+          {
+            "name":"黄平县",
+            "code":"522622"
+          },
+          {
+            "name":"施秉县",
+            "code":"522623"
+          },
+          {
+            "name":"三穗县",
+            "code":"522624"
+          },
+          {
+            "name":"镇远县",
+            "code":"522625"
+          },
+          {
+            "name":"岑巩县",
+            "code":"522626"
+          },
+          {
+            "name":"天柱县",
+            "code":"522627"
+          },
+          {
+            "name":"锦屏县",
+            "code":"522628"
+          },
+          {
+            "name":"剑河县",
+            "code":"522629"
+          },
+          {
+            "name":"台江县",
+            "code":"522630"
+          },
+          {
+            "name":"黎平县",
+            "code":"522631"
+          },
+          {
+            "name":"榕江县",
+            "code":"522632"
+          },
+          {
+            "name":"从江县",
+            "code":"522633"
+          },
+          {
+            "name":"雷山县",
+            "code":"522634"
+          },
+          {
+            "name":"麻江县",
+            "code":"522635"
+          },
+          {
+            "name":"丹寨县",
+            "code":"522636"
+          }
+        ]
+      },
+      {
+        "name":"黔南布依族苗族自治州",
+        "code":"522700",
+        "sub":[
+          {
+            "name":"都匀市",
+            "code":"522701"
+          },
+          {
+            "name":"福泉市",
+            "code":"522702"
+          },
+          {
+            "name":"荔波县",
+            "code":"522722"
+          },
+          {
+            "name":"贵定县",
+            "code":"522723"
+          },
+          {
+            "name":"瓮安县",
+            "code":"522725"
+          },
+          {
+            "name":"独山县",
+            "code":"522726"
+          },
+          {
+            "name":"平塘县",
+            "code":"522727"
+          },
+          {
+            "name":"罗甸县",
+            "code":"522728"
+          },
+          {
+            "name":"长顺县",
+            "code":"522729"
+          },
+          {
+            "name":"龙里县",
+            "code":"522730"
+          },
+          {
+            "name":"惠水县",
+            "code":"522731"
+          },
+          {
+            "name":"三都水族自治县",
+            "code":"522732"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"云南省",
+    "code":"530000",
+    "sub":[
+      {
+        "name":"昆明市",
+        "code":"530100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530101"
+          },
+          {
+            "name":"五华区",
+            "code":"530102"
+          },
+          {
+            "name":"盘龙区",
+            "code":"530103"
+          },
+          {
+            "name":"官渡区",
+            "code":"530111"
+          },
+          {
+            "name":"西山区",
+            "code":"530112"
+          },
+          {
+            "name":"东川区",
+            "code":"530113"
+          },
+          {
+            "name":"呈贡区",
+            "code":"530114"
+          },
+          {
+            "name":"晋宁县",
+            "code":"530122"
+          },
+          {
+            "name":"富民县",
+            "code":"530124"
+          },
+          {
+            "name":"宜良县",
+            "code":"530125"
+          },
+          {
+            "name":"石林彝族自治县",
+            "code":"530126"
+          },
+          {
+            "name":"嵩明县",
+            "code":"530127"
+          },
+          {
+            "name":"禄劝彝族苗族自治县",
+            "code":"530128"
+          },
+          {
+            "name":"寻甸回族彝族自治县",
+            "code":"530129"
+          },
+          {
+            "name":"安宁市",
+            "code":"530181"
+          }
+        ]
+      },
+      {
+        "name":"曲靖市",
+        "code":"530300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530301"
+          },
+          {
+            "name":"麒麟区",
+            "code":"530302"
+          },
+          {
+            "name":"马龙县",
+            "code":"530321"
+          },
+          {
+            "name":"陆良县",
+            "code":"530322"
+          },
+          {
+            "name":"师宗县",
+            "code":"530323"
+          },
+          {
+            "name":"罗平县",
+            "code":"530324"
+          },
+          {
+            "name":"富源县",
+            "code":"530325"
+          },
+          {
+            "name":"会泽县",
+            "code":"530326"
+          },
+          {
+            "name":"沾益县",
+            "code":"530328"
+          },
+          {
+            "name":"宣威市",
+            "code":"530381"
+          }
+        ]
+      },
+      {
+        "name":"玉溪市",
+        "code":"530400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530401"
+          },
+          {
+            "name":"红塔区",
+            "code":"530402"
+          },
+          {
+            "name":"江川县",
+            "code":"530421"
+          },
+          {
+            "name":"澄江县",
+            "code":"530422"
+          },
+          {
+            "name":"通海县",
+            "code":"530423"
+          },
+          {
+            "name":"华宁县",
+            "code":"530424"
+          },
+          {
+            "name":"易门县",
+            "code":"530425"
+          },
+          {
+            "name":"峨山彝族自治县",
+            "code":"530426"
+          },
+          {
+            "name":"新平彝族傣族自治县",
+            "code":"530427"
+          },
+          {
+            "name":"元江哈尼族彝族傣族自治县",
+            "code":"530428"
+          }
+        ]
+      },
+      {
+        "name":"保山市",
+        "code":"530500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530501"
+          },
+          {
+            "name":"隆阳区",
+            "code":"530502"
+          },
+          {
+            "name":"施甸县",
+            "code":"530521"
+          },
+          {
+            "name":"腾冲县",
+            "code":"530522"
+          },
+          {
+            "name":"龙陵县",
+            "code":"530523"
+          },
+          {
+            "name":"昌宁县",
+            "code":"530524"
+          }
+        ]
+      },
+      {
+        "name":"昭通市",
+        "code":"530600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530601"
+          },
+          {
+            "name":"昭阳区",
+            "code":"530602"
+          },
+          {
+            "name":"鲁甸县",
+            "code":"530621"
+          },
+          {
+            "name":"巧家县",
+            "code":"530622"
+          },
+          {
+            "name":"盐津县",
+            "code":"530623"
+          },
+          {
+            "name":"大关县",
+            "code":"530624"
+          },
+          {
+            "name":"永善县",
+            "code":"530625"
+          },
+          {
+            "name":"绥江县",
+            "code":"530626"
+          },
+          {
+            "name":"镇雄县",
+            "code":"530627"
+          },
+          {
+            "name":"彝良县",
+            "code":"530628"
+          },
+          {
+            "name":"威信县",
+            "code":"530629"
+          },
+          {
+            "name":"水富县",
+            "code":"530630"
+          }
+        ]
+      },
+      {
+        "name":"丽江市",
+        "code":"530700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530701"
+          },
+          {
+            "name":"古城区",
+            "code":"530702"
+          },
+          {
+            "name":"玉龙纳西族自治县",
+            "code":"530721"
+          },
+          {
+            "name":"永胜县",
+            "code":"530722"
+          },
+          {
+            "name":"华坪县",
+            "code":"530723"
+          },
+          {
+            "name":"宁蒗彝族自治县",
+            "code":"530724"
+          }
+        ]
+      },
+      {
+        "name":"普洱市",
+        "code":"530800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530801"
+          },
+          {
+            "name":"思茅区",
+            "code":"530802"
+          },
+          {
+            "name":"宁洱哈尼族彝族自治县",
+            "code":"530821"
+          },
+          {
+            "name":"墨江哈尼族自治县",
+            "code":"530822"
+          },
+          {
+            "name":"景东彝族自治县",
+            "code":"530823"
+          },
+          {
+            "name":"景谷傣族彝族自治县",
+            "code":"530824"
+          },
+          {
+            "name":"镇沅彝族哈尼族拉祜族自治县",
+            "code":"530825"
+          },
+          {
+            "name":"江城哈尼族彝族自治县",
+            "code":"530826"
+          },
+          {
+            "name":"孟连傣族拉祜族佤族自治县",
+            "code":"530827"
+          },
+          {
+            "name":"澜沧拉祜族自治县",
+            "code":"530828"
+          },
+          {
+            "name":"西盟佤族自治县",
+            "code":"530829"
+          }
+        ]
+      },
+      {
+        "name":"临沧市",
+        "code":"530900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530901"
+          },
+          {
+            "name":"临翔区",
+            "code":"530902"
+          },
+          {
+            "name":"凤庆县",
+            "code":"530921"
+          },
+          {
+            "name":"云县",
+            "code":"530922"
+          },
+          {
+            "name":"永德县",
+            "code":"530923"
+          },
+          {
+            "name":"镇康县",
+            "code":"530924"
+          },
+          {
+            "name":"双江拉祜族佤族布朗族傣族自治县",
+            "code":"530925"
+          },
+          {
+            "name":"耿马傣族佤族自治县",
+            "code":"530926"
+          },
+          {
+            "name":"沧源佤族自治县",
+            "code":"530927"
+          }
+        ]
+      },
+      {
+        "name":"楚雄彝族自治州",
+        "code":"532300",
+        "sub":[
+          {
+            "name":"楚雄市",
+            "code":"532301"
+          },
+          {
+            "name":"双柏县",
+            "code":"532322"
+          },
+          {
+            "name":"牟定县",
+            "code":"532323"
+          },
+          {
+            "name":"南华县",
+            "code":"532324"
+          },
+          {
+            "name":"姚安县",
+            "code":"532325"
+          },
+          {
+            "name":"大姚县",
+            "code":"532326"
+          },
+          {
+            "name":"永仁县",
+            "code":"532327"
+          },
+          {
+            "name":"元谋县",
+            "code":"532328"
+          },
+          {
+            "name":"武定县",
+            "code":"532329"
+          },
+          {
+            "name":"禄丰县",
+            "code":"532331"
+          }
+        ]
+      },
+      {
+        "name":"红河哈尼族彝族自治州",
+        "code":"532500",
+        "sub":[
+          {
+            "name":"个旧市",
+            "code":"532501"
+          },
+          {
+            "name":"开远市",
+            "code":"532502"
+          },
+          {
+            "name":"蒙自市",
+            "code":"532503"
+          },
+          {
+            "name":"弥勒市",
+            "code":"532504"
+          },
+          {
+            "name":"屏边苗族自治县",
+            "code":"532523"
+          },
+          {
+            "name":"建水县",
+            "code":"532524"
+          },
+          {
+            "name":"石屏县",
+            "code":"532525"
+          },
+          {
+            "name":"泸西县",
+            "code":"532527"
+          },
+          {
+            "name":"元阳县",
+            "code":"532528"
+          },
+          {
+            "name":"红河县",
+            "code":"532529"
+          },
+          {
+            "name":"金平苗族瑶族傣族自治县",
+            "code":"532530"
+          },
+          {
+            "name":"绿春县",
+            "code":"532531"
+          },
+          {
+            "name":"河口瑶族自治县",
+            "code":"532532"
+          }
+        ]
+      },
+      {
+        "name":"文山壮族苗族自治州",
+        "code":"532600",
+        "sub":[
+          {
+            "name":"文山市",
+            "code":"532601"
+          },
+          {
+            "name":"砚山县",
+            "code":"532622"
+          },
+          {
+            "name":"西畴县",
+            "code":"532623"
+          },
+          {
+            "name":"麻栗坡县",
+            "code":"532624"
+          },
+          {
+            "name":"马关县",
+            "code":"532625"
+          },
+          {
+            "name":"丘北县",
+            "code":"532626"
+          },
+          {
+            "name":"广南县",
+            "code":"532627"
+          },
+          {
+            "name":"富宁县",
+            "code":"532628"
+          }
+        ]
+      },
+      {
+        "name":"西双版纳傣族自治州",
+        "code":"532800",
+        "sub":[
+          {
+            "name":"景洪市",
+            "code":"532801"
+          },
+          {
+            "name":"勐海县",
+            "code":"532822"
+          },
+          {
+            "name":"勐腊县",
+            "code":"532823"
+          }
+        ]
+      },
+      {
+        "name":"大理白族自治州",
+        "code":"532900",
+        "sub":[
+          {
+            "name":"大理市",
+            "code":"532901"
+          },
+          {
+            "name":"漾濞彝族自治县",
+            "code":"532922"
+          },
+          {
+            "name":"祥云县",
+            "code":"532923"
+          },
+          {
+            "name":"宾川县",
+            "code":"532924"
+          },
+          {
+            "name":"弥渡县",
+            "code":"532925"
+          },
+          {
+            "name":"南涧彝族自治县",
+            "code":"532926"
+          },
+          {
+            "name":"巍山彝族回族自治县",
+            "code":"532927"
+          },
+          {
+            "name":"永平县",
+            "code":"532928"
+          },
+          {
+            "name":"云龙县",
+            "code":"532929"
+          },
+          {
+            "name":"洱源县",
+            "code":"532930"
+          },
+          {
+            "name":"剑川县",
+            "code":"532931"
+          },
+          {
+            "name":"鹤庆县",
+            "code":"532932"
+          }
+        ]
+      },
+      {
+        "name":"德宏傣族景颇族自治州",
+        "code":"533100",
+        "sub":[
+          {
+            "name":"瑞丽市",
+            "code":"533102"
+          },
+          {
+            "name":"芒市",
+            "code":"533103"
+          },
+          {
+            "name":"梁河县",
+            "code":"533122"
+          },
+          {
+            "name":"盈江县",
+            "code":"533123"
+          },
+          {
+            "name":"陇川县",
+            "code":"533124"
+          }
+        ]
+      },
+      {
+        "name":"怒江傈僳族自治州",
+        "code":"533300",
+        "sub":[
+          {
+            "name":"泸水县",
+            "code":"533321"
+          },
+          {
+            "name":"福贡县",
+            "code":"533323"
+          },
+          {
+            "name":"贡山独龙族怒族自治县",
+            "code":"533324"
+          },
+          {
+            "name":"兰坪白族普米族自治县",
+            "code":"533325"
+          }
+        ]
+      },
+      {
+        "name":"迪庆藏族自治州",
+        "code":"533400",
+        "sub":[
+          {
+            "name":"香格里拉市",
+            "code":"533401"
+          },
+          {
+            "name":"德钦县",
+            "code":"533422"
+          },
+          {
+            "name":"维西傈僳族自治县",
+            "code":"533423"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"西藏自治区",
+    "code":"540000",
+    "sub":[
+      {
+        "name":"拉萨市",
+        "code":"540100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540101"
+          },
+          {
+            "name":"城关区",
+            "code":"540102"
+          },
+          {
+            "name":"林周县",
+            "code":"540121"
+          },
+          {
+            "name":"当雄县",
+            "code":"540122"
+          },
+          {
+            "name":"尼木县",
+            "code":"540123"
+          },
+          {
+            "name":"曲水县",
+            "code":"540124"
+          },
+          {
+            "name":"堆龙德庆县",
+            "code":"540125"
+          },
+          {
+            "name":"达孜县",
+            "code":"540126"
+          },
+          {
+            "name":"墨竹工卡县",
+            "code":"540127"
+          }
+        ]
+      },
+      {
+        "name":"日喀则市",
+        "code":"540200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540201"
+          },
+          {
+            "name":"桑珠孜区",
+            "code":"540202"
+          },
+          {
+            "name":"南木林县",
+            "code":"540221"
+          },
+          {
+            "name":"江孜县",
+            "code":"540222"
+          },
+          {
+            "name":"定日县",
+            "code":"540223"
+          },
+          {
+            "name":"萨迦县",
+            "code":"540224"
+          },
+          {
+            "name":"拉孜县",
+            "code":"540225"
+          },
+          {
+            "name":"昂仁县",
+            "code":"540226"
+          },
+          {
+            "name":"谢通门县",
+            "code":"540227"
+          },
+          {
+            "name":"白朗县",
+            "code":"540228"
+          },
+          {
+            "name":"仁布县",
+            "code":"540229"
+          },
+          {
+            "name":"康马县",
+            "code":"540230"
+          },
+          {
+            "name":"定结县",
+            "code":"540231"
+          },
+          {
+            "name":"仲巴县",
+            "code":"540232"
+          },
+          {
+            "name":"亚东县",
+            "code":"540233"
+          },
+          {
+            "name":"吉隆县",
+            "code":"540234"
+          },
+          {
+            "name":"聂拉木县",
+            "code":"540235"
+          },
+          {
+            "name":"萨嘎县",
+            "code":"540236"
+          },
+          {
+            "name":"岗巴县",
+            "code":"540237"
+          }
+        ]
+      },
+      {
+        "name":"昌都市",
+        "code":"540300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540301"
+          },
+          {
+            "name":"卡若区",
+            "code":"540302"
+          },
+          {
+            "name":"江达县",
+            "code":"540321"
+          },
+          {
+            "name":"贡觉县",
+            "code":"540322"
+          },
+          {
+            "name":"类乌齐县",
+            "code":"540323"
+          },
+          {
+            "name":"丁青县",
+            "code":"540324"
+          },
+          {
+            "name":"察雅县",
+            "code":"540325"
+          },
+          {
+            "name":"八宿县",
+            "code":"540326"
+          },
+          {
+            "name":"左贡县",
+            "code":"540327"
+          },
+          {
+            "name":"芒康县",
+            "code":"540328"
+          },
+          {
+            "name":"洛隆县",
+            "code":"540329"
+          },
+          {
+            "name":"边坝县",
+            "code":"540330"
+          }
+        ]
+      },
+      {
+        "name":"山南地区",
+        "code":"542200",
+        "sub":[
+          {
+            "name":"乃东县",
+            "code":"542221"
+          },
+          {
+            "name":"扎囊县",
+            "code":"542222"
+          },
+          {
+            "name":"贡嘎县",
+            "code":"542223"
+          },
+          {
+            "name":"桑日县",
+            "code":"542224"
+          },
+          {
+            "name":"琼结县",
+            "code":"542225"
+          },
+          {
+            "name":"曲松县",
+            "code":"542226"
+          },
+          {
+            "name":"措美县",
+            "code":"542227"
+          },
+          {
+            "name":"洛扎县",
+            "code":"542228"
+          },
+          {
+            "name":"加查县",
+            "code":"542229"
+          },
+          {
+            "name":"隆子县",
+            "code":"542231"
+          },
+          {
+            "name":"错那县",
+            "code":"542232"
+          },
+          {
+            "name":"浪卡子县",
+            "code":"542233"
+          }
+        ]
+      },
+      {
+        "name":"那曲地区",
+        "code":"542400",
+        "sub":[
+          {
+            "name":"那曲县",
+            "code":"542421"
+          },
+          {
+            "name":"嘉黎县",
+            "code":"542422"
+          },
+          {
+            "name":"比如县",
+            "code":"542423"
+          },
+          {
+            "name":"聂荣县",
+            "code":"542424"
+          },
+          {
+            "name":"安多县",
+            "code":"542425"
+          },
+          {
+            "name":"申扎县",
+            "code":"542426"
+          },
+          {
+            "name":"索县",
+            "code":"542427"
+          },
+          {
+            "name":"班戈县",
+            "code":"542428"
+          },
+          {
+            "name":"巴青县",
+            "code":"542429"
+          },
+          {
+            "name":"尼玛县",
+            "code":"542430"
+          },
+          {
+            "name":"双湖县",
+            "code":"542431"
+          }
+        ]
+      },
+      {
+        "name":"阿里地区",
+        "code":"542500",
+        "sub":[
+          {
+            "name":"普兰县",
+            "code":"542521"
+          },
+          {
+            "name":"札达县",
+            "code":"542522"
+          },
+          {
+            "name":"噶尔县",
+            "code":"542523"
+          },
+          {
+            "name":"日土县",
+            "code":"542524"
+          },
+          {
+            "name":"革吉县",
+            "code":"542525"
+          },
+          {
+            "name":"改则县",
+            "code":"542526"
+          },
+          {
+            "name":"措勤县",
+            "code":"542527"
+          }
+        ]
+      },
+      {
+        "name":"林芝地区",
+        "code":"542600",
+        "sub":[
+          {
+            "name":"林芝县",
+            "code":"542621"
+          },
+          {
+            "name":"工布江达县",
+            "code":"542622"
+          },
+          {
+            "name":"米林县",
+            "code":"542623"
+          },
+          {
+            "name":"墨脱县",
+            "code":"542624"
+          },
+          {
+            "name":"波密县",
+            "code":"542625"
+          },
+          {
+            "name":"察隅县",
+            "code":"542626"
+          },
+          {
+            "name":"朗县",
+            "code":"542627"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"陕西省",
+    "code":"610000",
+    "sub":[
+      {
+        "name":"西安市",
+        "code":"610100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610101"
+          },
+          {
+            "name":"新城区",
+            "code":"610102"
+          },
+          {
+            "name":"碑林区",
+            "code":"610103"
+          },
+          {
+            "name":"莲湖区",
+            "code":"610104"
+          },
+          {
+            "name":"灞桥区",
+            "code":"610111"
+          },
+          {
+            "name":"未央区",
+            "code":"610112"
+          },
+          {
+            "name":"雁塔区",
+            "code":"610113"
+          },
+          {
+            "name":"阎良区",
+            "code":"610114"
+          },
+          {
+            "name":"临潼区",
+            "code":"610115"
+          },
+          {
+            "name":"长安区",
+            "code":"610116"
+          },
+          {
+            "name":"高陵区",
+            "code":"610117"
+          },
+          {
+            "name":"蓝田县",
+            "code":"610122"
+          },
+          {
+            "name":"周至县",
+            "code":"610124"
+          },
+          {
+            "name":"户县",
+            "code":"610125"
+          }
+        ]
+      },
+      {
+        "name":"铜川市",
+        "code":"610200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610201"
+          },
+          {
+            "name":"王益区",
+            "code":"610202"
+          },
+          {
+            "name":"印台区",
+            "code":"610203"
+          },
+          {
+            "name":"耀州区",
+            "code":"610204"
+          },
+          {
+            "name":"宜君县",
+            "code":"610222"
+          }
+        ]
+      },
+      {
+        "name":"宝鸡市",
+        "code":"610300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610301"
+          },
+          {
+            "name":"渭滨区",
+            "code":"610302"
+          },
+          {
+            "name":"金台区",
+            "code":"610303"
+          },
+          {
+            "name":"陈仓区",
+            "code":"610304"
+          },
+          {
+            "name":"凤翔县",
+            "code":"610322"
+          },
+          {
+            "name":"岐山县",
+            "code":"610323"
+          },
+          {
+            "name":"扶风县",
+            "code":"610324"
+          },
+          {
+            "name":"眉县",
+            "code":"610326"
+          },
+          {
+            "name":"陇县",
+            "code":"610327"
+          },
+          {
+            "name":"千阳县",
+            "code":"610328"
+          },
+          {
+            "name":"麟游县",
+            "code":"610329"
+          },
+          {
+            "name":"凤县",
+            "code":"610330"
+          },
+          {
+            "name":"太白县",
+            "code":"610331"
+          }
+        ]
+      },
+      {
+        "name":"咸阳市",
+        "code":"610400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610401"
+          },
+          {
+            "name":"秦都区",
+            "code":"610402"
+          },
+          {
+            "name":"杨陵区",
+            "code":"610403"
+          },
+          {
+            "name":"渭城区",
+            "code":"610404"
+          },
+          {
+            "name":"三原县",
+            "code":"610422"
+          },
+          {
+            "name":"泾阳县",
+            "code":"610423"
+          },
+          {
+            "name":"乾县",
+            "code":"610424"
+          },
+          {
+            "name":"礼泉县",
+            "code":"610425"
+          },
+          {
+            "name":"永寿县",
+            "code":"610426"
+          },
+          {
+            "name":"彬县",
+            "code":"610427"
+          },
+          {
+            "name":"长武县",
+            "code":"610428"
+          },
+          {
+            "name":"旬邑县",
+            "code":"610429"
+          },
+          {
+            "name":"淳化县",
+            "code":"610430"
+          },
+          {
+            "name":"武功县",
+            "code":"610431"
+          },
+          {
+            "name":"兴平市",
+            "code":"610481"
+          }
+        ]
+      },
+      {
+        "name":"渭南市",
+        "code":"610500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610501"
+          },
+          {
+            "name":"临渭区",
+            "code":"610502"
+          },
+          {
+            "name":"华县",
+            "code":"610521"
+          },
+          {
+            "name":"潼关县",
+            "code":"610522"
+          },
+          {
+            "name":"大荔县",
+            "code":"610523"
+          },
+          {
+            "name":"合阳县",
+            "code":"610524"
+          },
+          {
+            "name":"澄城县",
+            "code":"610525"
+          },
+          {
+            "name":"蒲城县",
+            "code":"610526"
+          },
+          {
+            "name":"白水县",
+            "code":"610527"
+          },
+          {
+            "name":"富平县",
+            "code":"610528"
+          },
+          {
+            "name":"韩城市",
+            "code":"610581"
+          },
+          {
+            "name":"华阴市",
+            "code":"610582"
+          }
+        ]
+      },
+      {
+        "name":"延安市",
+        "code":"610600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610601"
+          },
+          {
+            "name":"宝塔区",
+            "code":"610602"
+          },
+          {
+            "name":"延长县",
+            "code":"610621"
+          },
+          {
+            "name":"延川县",
+            "code":"610622"
+          },
+          {
+            "name":"子长县",
+            "code":"610623"
+          },
+          {
+            "name":"安塞县",
+            "code":"610624"
+          },
+          {
+            "name":"志丹县",
+            "code":"610625"
+          },
+          {
+            "name":"吴起县",
+            "code":"610626"
+          },
+          {
+            "name":"甘泉县",
+            "code":"610627"
+          },
+          {
+            "name":"富县",
+            "code":"610628"
+          },
+          {
+            "name":"洛川县",
+            "code":"610629"
+          },
+          {
+            "name":"宜川县",
+            "code":"610630"
+          },
+          {
+            "name":"黄龙县",
+            "code":"610631"
+          },
+          {
+            "name":"黄陵县",
+            "code":"610632"
+          }
+        ]
+      },
+      {
+        "name":"汉中市",
+        "code":"610700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610701"
+          },
+          {
+            "name":"汉台区",
+            "code":"610702"
+          },
+          {
+            "name":"南郑县",
+            "code":"610721"
+          },
+          {
+            "name":"城固县",
+            "code":"610722"
+          },
+          {
+            "name":"洋县",
+            "code":"610723"
+          },
+          {
+            "name":"西乡县",
+            "code":"610724"
+          },
+          {
+            "name":"勉县",
+            "code":"610725"
+          },
+          {
+            "name":"宁强县",
+            "code":"610726"
+          },
+          {
+            "name":"略阳县",
+            "code":"610727"
+          },
+          {
+            "name":"镇巴县",
+            "code":"610728"
+          },
+          {
+            "name":"留坝县",
+            "code":"610729"
+          },
+          {
+            "name":"佛坪县",
+            "code":"610730"
+          }
+        ]
+      },
+      {
+        "name":"榆林市",
+        "code":"610800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610801"
+          },
+          {
+            "name":"榆阳区",
+            "code":"610802"
+          },
+          {
+            "name":"神木县",
+            "code":"610821"
+          },
+          {
+            "name":"府谷县",
+            "code":"610822"
+          },
+          {
+            "name":"横山县",
+            "code":"610823"
+          },
+          {
+            "name":"靖边县",
+            "code":"610824"
+          },
+          {
+            "name":"定边县",
+            "code":"610825"
+          },
+          {
+            "name":"绥德县",
+            "code":"610826"
+          },
+          {
+            "name":"米脂县",
+            "code":"610827"
+          },
+          {
+            "name":"佳县",
+            "code":"610828"
+          },
+          {
+            "name":"吴堡县",
+            "code":"610829"
+          },
+          {
+            "name":"清涧县",
+            "code":"610830"
+          },
+          {
+            "name":"子洲县",
+            "code":"610831"
+          }
+        ]
+      },
+      {
+        "name":"安康市",
+        "code":"610900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610901"
+          },
+          {
+            "name":"汉阴县",
+            "code":"610921"
+          },
+          {
+            "name":"石泉县",
+            "code":"610922"
+          },
+          {
+            "name":"宁陕县",
+            "code":"610923"
+          },
+          {
+            "name":"紫阳县",
+            "code":"610924"
+          },
+          {
+            "name":"岚皋县",
+            "code":"610925"
+          },
+          {
+            "name":"平利县",
+            "code":"610926"
+          },
+          {
+            "name":"镇坪县",
+            "code":"610927"
+          },
+          {
+            "name":"旬阳县",
+            "code":"610928"
+          },
+          {
+            "name":"白河县",
+            "code":"610929"
+          }
+        ]
+      },
+      {
+        "name":"商洛市",
+        "code":"611000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"611001"
+          },
+          {
+            "name":"商州区",
+            "code":"611002"
+          },
+          {
+            "name":"洛南县",
+            "code":"611021"
+          },
+          {
+            "name":"丹凤县",
+            "code":"611022"
+          },
+          {
+            "name":"商南县",
+            "code":"611023"
+          },
+          {
+            "name":"山阳县",
+            "code":"611024"
+          },
+          {
+            "name":"镇安县",
+            "code":"611025"
+          },
+          {
+            "name":"柞水县",
+            "code":"611026"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"甘肃省",
+    "code":"620000",
+    "sub":[
+      {
+        "name":"兰州市",
+        "code":"620100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620101"
+          },
+          {
+            "name":"城关区",
+            "code":"620102"
+          },
+          {
+            "name":"七里河区",
+            "code":"620103"
+          },
+          {
+            "name":"西固区",
+            "code":"620104"
+          },
+          {
+            "name":"安宁区",
+            "code":"620105"
+          },
+          {
+            "name":"红古区",
+            "code":"620111"
+          },
+          {
+            "name":"永登县",
+            "code":"620121"
+          },
+          {
+            "name":"皋兰县",
+            "code":"620122"
+          },
+          {
+            "name":"榆中县",
+            "code":"620123"
+          }
+        ]
+      },
+      {
+        "name":"嘉峪关市",
+        "code":"620200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620201"
+          }
+        ]
+      },
+      {
+        "name":"金昌市",
+        "code":"620300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620301"
+          },
+          {
+            "name":"金川区",
+            "code":"620302"
+          },
+          {
+            "name":"永昌县",
+            "code":"620321"
+          }
+        ]
+      },
+      {
+        "name":"白银市",
+        "code":"620400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620401"
+          },
+          {
+            "name":"白银区",
+            "code":"620402"
+          },
+          {
+            "name":"平川区",
+            "code":"620403"
+          },
+          {
+            "name":"靖远县",
+            "code":"620421"
+          },
+          {
+            "name":"会宁县",
+            "code":"620422"
+          },
+          {
+            "name":"景泰县",
+            "code":"620423"
+          }
+        ]
+      },
+      {
+        "name":"天水市",
+        "code":"620500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620501"
+          },
+          {
+            "name":"秦州区",
+            "code":"620502"
+          },
+          {
+            "name":"麦积区",
+            "code":"620503"
+          },
+          {
+            "name":"清水县",
+            "code":"620521"
+          },
+          {
+            "name":"秦安县",
+            "code":"620522"
+          },
+          {
+            "name":"甘谷县",
+            "code":"620523"
+          },
+          {
+            "name":"武山县",
+            "code":"620524"
+          },
+          {
+            "name":"张家川回族自治县",
+            "code":"620525"
+          }
+        ]
+      },
+      {
+        "name":"武威市",
+        "code":"620600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620601"
+          },
+          {
+            "name":"凉州区",
+            "code":"620602"
+          },
+          {
+            "name":"民勤县",
+            "code":"620621"
+          },
+          {
+            "name":"古浪县",
+            "code":"620622"
+          },
+          {
+            "name":"天祝藏族自治县",
+            "code":"620623"
+          }
+        ]
+      },
+      {
+        "name":"张掖市",
+        "code":"620700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620701"
+          },
+          {
+            "name":"甘州区",
+            "code":"620702"
+          },
+          {
+            "name":"肃南裕固族自治县",
+            "code":"620721"
+          },
+          {
+            "name":"民乐县",
+            "code":"620722"
+          },
+          {
+            "name":"临泽县",
+            "code":"620723"
+          },
+          {
+            "name":"高台县",
+            "code":"620724"
+          },
+          {
+            "name":"山丹县",
+            "code":"620725"
+          }
+        ]
+      },
+      {
+        "name":"平凉市",
+        "code":"620800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620801"
+          },
+          {
+            "name":"崆峒区",
+            "code":"620802"
+          },
+          {
+            "name":"泾川县",
+            "code":"620821"
+          },
+          {
+            "name":"灵台县",
+            "code":"620822"
+          },
+          {
+            "name":"崇信县",
+            "code":"620823"
+          },
+          {
+            "name":"华亭县",
+            "code":"620824"
+          },
+          {
+            "name":"庄浪县",
+            "code":"620825"
+          },
+          {
+            "name":"静宁县",
+            "code":"620826"
+          }
+        ]
+      },
+      {
+        "name":"酒泉市",
+        "code":"620900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620901"
+          },
+          {
+            "name":"肃州区",
+            "code":"620902"
+          },
+          {
+            "name":"金塔县",
+            "code":"620921"
+          },
+          {
+            "name":"瓜州县",
+            "code":"620922"
+          },
+          {
+            "name":"肃北蒙古族自治县",
+            "code":"620923"
+          },
+          {
+            "name":"阿克塞哈萨克族自治县",
+            "code":"620924"
+          },
+          {
+            "name":"玉门市",
+            "code":"620981"
+          },
+          {
+            "name":"敦煌市",
+            "code":"620982"
+          }
+        ]
+      },
+      {
+        "name":"庆阳市",
+        "code":"621000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621001"
+          },
+          {
+            "name":"西峰区",
+            "code":"621002"
+          },
+          {
+            "name":"庆城县",
+            "code":"621021"
+          },
+          {
+            "name":"环县",
+            "code":"621022"
+          },
+          {
+            "name":"华池县",
+            "code":"621023"
+          },
+          {
+            "name":"合水县",
+            "code":"621024"
+          },
+          {
+            "name":"正宁县",
+            "code":"621025"
+          },
+          {
+            "name":"宁县",
+            "code":"621026"
+          },
+          {
+            "name":"镇原县",
+            "code":"621027"
+          }
+        ]
+      },
+      {
+        "name":"定西市",
+        "code":"621100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621101"
+          },
+          {
+            "name":"安定区",
+            "code":"621102"
+          },
+          {
+            "name":"通渭县",
+            "code":"621121"
+          },
+          {
+            "name":"陇西县",
+            "code":"621122"
+          },
+          {
+            "name":"渭源县",
+            "code":"621123"
+          },
+          {
+            "name":"临洮县",
+            "code":"621124"
+          },
+          {
+            "name":"漳县",
+            "code":"621125"
+          },
+          {
+            "name":"岷县",
+            "code":"621126"
+          }
+        ]
+      },
+      {
+        "name":"陇南市",
+        "code":"621200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621201"
+          },
+          {
+            "name":"武都区",
+            "code":"621202"
+          },
+          {
+            "name":"成县",
+            "code":"621221"
+          },
+          {
+            "name":"文县",
+            "code":"621222"
+          },
+          {
+            "name":"宕昌县",
+            "code":"621223"
+          },
+          {
+            "name":"康县",
+            "code":"621224"
+          },
+          {
+            "name":"西和县",
+            "code":"621225"
+          },
+          {
+            "name":"礼县",
+            "code":"621226"
+          },
+          {
+            "name":"徽县",
+            "code":"621227"
+          },
+          {
+            "name":"两当县",
+            "code":"621228"
+          }
+        ]
+      },
+      {
+        "name":"临夏回族自治州",
+        "code":"622900",
+        "sub":[
+          {
+            "name":"临夏市",
+            "code":"622901"
+          },
+          {
+            "name":"临夏县",
+            "code":"622921"
+          },
+          {
+            "name":"康乐县",
+            "code":"622922"
+          },
+          {
+            "name":"永靖县",
+            "code":"622923"
+          },
+          {
+            "name":"广河县",
+            "code":"622924"
+          },
+          {
+            "name":"和政县",
+            "code":"622925"
+          },
+          {
+            "name":"东乡族自治县",
+            "code":"622926"
+          },
+          {
+            "name":"积石山保安族东乡族撒拉族自治县",
+            "code":"622927"
+          }
+        ]
+      },
+      {
+        "name":"甘南藏族自治州",
+        "code":"623000",
+        "sub":[
+          {
+            "name":"合作市",
+            "code":"623001"
+          },
+          {
+            "name":"临潭县",
+            "code":"623021"
+          },
+          {
+            "name":"卓尼县",
+            "code":"623022"
+          },
+          {
+            "name":"舟曲县",
+            "code":"623023"
+          },
+          {
+            "name":"迭部县",
+            "code":"623024"
+          },
+          {
+            "name":"玛曲县",
+            "code":"623025"
+          },
+          {
+            "name":"碌曲县",
+            "code":"623026"
+          },
+          {
+            "name":"夏河县",
+            "code":"623027"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"青海省",
+    "code":"630000",
+    "sub":[
+      {
+        "name":"西宁市",
+        "code":"630100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"630101"
+          },
+          {
+            "name":"城东区",
+            "code":"630102"
+          },
+          {
+            "name":"城中区",
+            "code":"630103"
+          },
+          {
+            "name":"城西区",
+            "code":"630104"
+          },
+          {
+            "name":"城北区",
+            "code":"630105"
+          },
+          {
+            "name":"大通回族土族自治县",
+            "code":"630121"
+          },
+          {
+            "name":"湟中县",
+            "code":"630122"
+          },
+          {
+            "name":"湟源县",
+            "code":"630123"
+          }
+        ]
+      },
+      {
+        "name":"海东市",
+        "code":"630200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"630201"
+          },
+          {
+            "name":"乐都区",
+            "code":"630202"
+          },
+          {
+            "name":"平安县",
+            "code":"630221"
+          },
+          {
+            "name":"民和回族土族自治县",
+            "code":"630222"
+          },
+          {
+            "name":"互助土族自治县",
+            "code":"630223"
+          },
+          {
+            "name":"化隆回族自治县",
+            "code":"630224"
+          },
+          {
+            "name":"循化撒拉族自治县",
+            "code":"630225"
+          }
+        ]
+      },
+      {
+        "name":"海北藏族自治州",
+        "code":"632200",
+        "sub":[
+          {
+            "name":"门源回族自治县",
+            "code":"632221"
+          },
+          {
+            "name":"祁连县",
+            "code":"632222"
+          },
+          {
+            "name":"海晏县",
+            "code":"632223"
+          },
+          {
+            "name":"刚察县",
+            "code":"632224"
+          }
+        ]
+      },
+      {
+        "name":"黄南藏族自治州",
+        "code":"632300",
+        "sub":[
+          {
+            "name":"同仁县",
+            "code":"632321"
+          },
+          {
+            "name":"尖扎县",
+            "code":"632322"
+          },
+          {
+            "name":"泽库县",
+            "code":"632323"
+          },
+          {
+            "name":"河南蒙古族自治县",
+            "code":"632324"
+          }
+        ]
+      },
+      {
+        "name":"海南藏族自治州",
+        "code":"632500",
+        "sub":[
+          {
+            "name":"共和县",
+            "code":"632521"
+          },
+          {
+            "name":"同德县",
+            "code":"632522"
+          },
+          {
+            "name":"贵德县",
+            "code":"632523"
+          },
+          {
+            "name":"兴海县",
+            "code":"632524"
+          },
+          {
+            "name":"贵南县",
+            "code":"632525"
+          }
+        ]
+      },
+      {
+        "name":"果洛藏族自治州",
+        "code":"632600",
+        "sub":[
+          {
+            "name":"玛沁县",
+            "code":"632621"
+          },
+          {
+            "name":"班玛县",
+            "code":"632622"
+          },
+          {
+            "name":"甘德县",
+            "code":"632623"
+          },
+          {
+            "name":"达日县",
+            "code":"632624"
+          },
+          {
+            "name":"久治县",
+            "code":"632625"
+          },
+          {
+            "name":"玛多县",
+            "code":"632626"
+          }
+        ]
+      },
+      {
+        "name":"玉树藏族自治州",
+        "code":"632700",
+        "sub":[
+          {
+            "name":"玉树市",
+            "code":"632701"
+          },
+          {
+            "name":"杂多县",
+            "code":"632722"
+          },
+          {
+            "name":"称多县",
+            "code":"632723"
+          },
+          {
+            "name":"治多县",
+            "code":"632724"
+          },
+          {
+            "name":"囊谦县",
+            "code":"632725"
+          },
+          {
+            "name":"曲麻莱县",
+            "code":"632726"
+          }
+        ]
+      },
+      {
+        "name":"海西蒙古族藏族自治州",
+        "code":"632800",
+        "sub":[
+          {
+            "name":"格尔木市",
+            "code":"632801"
+          },
+          {
+            "name":"德令哈市",
+            "code":"632802"
+          },
+          {
+            "name":"乌兰县",
+            "code":"632821"
+          },
+          {
+            "name":"都兰县",
+            "code":"632822"
+          },
+          {
+            "name":"天峻县",
+            "code":"632823"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"宁夏回族自治区",
+    "code":"640000",
+    "sub":[
+      {
+        "name":"银川市",
+        "code":"640100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640101"
+          },
+          {
+            "name":"兴庆区",
+            "code":"640104"
+          },
+          {
+            "name":"西夏区",
+            "code":"640105"
+          },
+          {
+            "name":"金凤区",
+            "code":"640106"
+          },
+          {
+            "name":"永宁县",
+            "code":"640121"
+          },
+          {
+            "name":"贺兰县",
+            "code":"640122"
+          },
+          {
+            "name":"灵武市",
+            "code":"640181"
+          }
+        ]
+      },
+      {
+        "name":"石嘴山市",
+        "code":"640200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640201"
+          },
+          {
+            "name":"大武口区",
+            "code":"640202"
+          },
+          {
+            "name":"惠农区",
+            "code":"640205"
+          },
+          {
+            "name":"平罗县",
+            "code":"640221"
+          }
+        ]
+      },
+      {
+        "name":"吴忠市",
+        "code":"640300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640301"
+          },
+          {
+            "name":"利通区",
+            "code":"640302"
+          },
+          {
+            "name":"红寺堡区",
+            "code":"640303"
+          },
+          {
+            "name":"盐池县",
+            "code":"640323"
+          },
+          {
+            "name":"同心县",
+            "code":"640324"
+          },
+          {
+            "name":"青铜峡市",
+            "code":"640381"
+          }
+        ]
+      },
+      {
+        "name":"固原市",
+        "code":"640400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640401"
+          },
+          {
+            "name":"原州区",
+            "code":"640402"
+          },
+          {
+            "name":"西吉县",
+            "code":"640422"
+          },
+          {
+            "name":"隆德县",
+            "code":"640423"
+          },
+          {
+            "name":"泾源县",
+            "code":"640424"
+          },
+          {
+            "name":"彭阳县",
+            "code":"640425"
+          }
+        ]
+      },
+      {
+        "name":"中卫市",
+        "code":"640500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640501"
+          },
+          {
+            "name":"沙坡头区",
+            "code":"640502"
+          },
+          {
+            "name":"中宁县",
+            "code":"640521"
+          },
+          {
+            "name":"海原县",
+            "code":"640522"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"新疆维吾尔自治区",
+    "code":"650000",
+    "sub":[
+      {
+        "name":"乌鲁木齐市",
+        "code":"650100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"650101"
+          },
+          {
+            "name":"天山区",
+            "code":"650102"
+          },
+          {
+            "name":"沙依巴克区",
+            "code":"650103"
+          },
+          {
+            "name":"新市区",
+            "code":"650104"
+          },
+          {
+            "name":"水磨沟区",
+            "code":"650105"
+          },
+          {
+            "name":"头屯河区",
+            "code":"650106"
+          },
+          {
+            "name":"达坂城区",
+            "code":"650107"
+          },
+          {
+            "name":"米东区",
+            "code":"650109"
+          },
+          {
+            "name":"乌鲁木齐县",
+            "code":"650121"
+          }
+        ]
+      },
+      {
+        "name":"克拉玛依市",
+        "code":"650200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"650201"
+          },
+          {
+            "name":"独山子区",
+            "code":"650202"
+          },
+          {
+            "name":"克拉玛依区",
+            "code":"650203"
+          },
+          {
+            "name":"白碱滩区",
+            "code":"650204"
+          },
+          {
+            "name":"乌尔禾区",
+            "code":"650205"
+          }
+        ]
+      },
+      {
+        "name":"吐鲁番地区",
+        "code":"652100",
+        "sub":[
+          {
+            "name":"吐鲁番市",
+            "code":"652101"
+          },
+          {
+            "name":"鄯善县",
+            "code":"652122"
+          },
+          {
+            "name":"托克逊县",
+            "code":"652123"
+          }
+        ]
+      },
+      {
+        "name":"哈密地区",
+        "code":"652200",
+        "sub":[
+          {
+            "name":"哈密市",
+            "code":"652201"
+          },
+          {
+            "name":"巴里坤哈萨克自治县",
+            "code":"652222"
+          },
+          {
+            "name":"伊吾县",
+            "code":"652223"
+          }
+        ]
+      },
+      {
+        "name":"昌吉回族自治州",
+        "code":"652300",
+        "sub":[
+          {
+            "name":"昌吉市",
+            "code":"652301"
+          },
+          {
+            "name":"阜康市",
+            "code":"652302"
+          },
+          {
+            "name":"呼图壁县",
+            "code":"652323"
+          },
+          {
+            "name":"玛纳斯县",
+            "code":"652324"
+          },
+          {
+            "name":"奇台县",
+            "code":"652325"
+          },
+          {
+            "name":"吉木萨尔县",
+            "code":"652327"
+          },
+          {
+            "name":"木垒哈萨克自治县",
+            "code":"652328"
+          }
+        ]
+      },
+      {
+        "name":"博尔塔拉蒙古自治州",
+        "code":"652700",
+        "sub":[
+          {
+            "name":"博乐市",
+            "code":"652701"
+          },
+          {
+            "name":"阿拉山口市",
+            "code":"652702"
+          },
+          {
+            "name":"精河县",
+            "code":"652722"
+          },
+          {
+            "name":"温泉县",
+            "code":"652723"
+          }
+        ]
+      },
+      {
+        "name":"巴音郭楞蒙古自治州",
+        "code":"652800",
+        "sub":[
+          {
+            "name":"库尔勒市",
+            "code":"652801"
+          },
+          {
+            "name":"轮台县",
+            "code":"652822"
+          },
+          {
+            "name":"尉犁县",
+            "code":"652823"
+          },
+          {
+            "name":"若羌县",
+            "code":"652824"
+          },
+          {
+            "name":"且末县",
+            "code":"652825"
+          },
+          {
+            "name":"焉耆回族自治县",
+            "code":"652826"
+          },
+          {
+            "name":"和静县",
+            "code":"652827"
+          },
+          {
+            "name":"和硕县",
+            "code":"652828"
+          },
+          {
+            "name":"博湖县",
+            "code":"652829"
+          }
+        ]
+      },
+      {
+        "name":"阿克苏地区",
+        "code":"652900",
+        "sub":[
+          {
+            "name":"阿克苏市",
+            "code":"652901"
+          },
+          {
+            "name":"温宿县",
+            "code":"652922"
+          },
+          {
+            "name":"库车县",
+            "code":"652923"
+          },
+          {
+            "name":"沙雅县",
+            "code":"652924"
+          },
+          {
+            "name":"新和县",
+            "code":"652925"
+          },
+          {
+            "name":"拜城县",
+            "code":"652926"
+          },
+          {
+            "name":"乌什县",
+            "code":"652927"
+          },
+          {
+            "name":"阿瓦提县",
+            "code":"652928"
+          },
+          {
+            "name":"柯坪县",
+            "code":"652929"
+          }
+        ]
+      },
+      {
+        "name":"克孜勒苏柯尔克孜自治州",
+        "code":"653000",
+        "sub":[
+          {
+            "name":"阿图什市",
+            "code":"653001"
+          },
+          {
+            "name":"阿克陶县",
+            "code":"653022"
+          },
+          {
+            "name":"阿合奇县",
+            "code":"653023"
+          },
+          {
+            "name":"乌恰县",
+            "code":"653024"
+          }
+        ]
+      },
+      {
+        "name":"喀什地区",
+        "code":"653100",
+        "sub":[
+          {
+            "name":"喀什市",
+            "code":"653101"
+          },
+          {
+            "name":"疏附县",
+            "code":"653121"
+          },
+          {
+            "name":"疏勒县",
+            "code":"653122"
+          },
+          {
+            "name":"英吉沙县",
+            "code":"653123"
+          },
+          {
+            "name":"泽普县",
+            "code":"653124"
+          },
+          {
+            "name":"莎车县",
+            "code":"653125"
+          },
+          {
+            "name":"叶城县",
+            "code":"653126"
+          },
+          {
+            "name":"麦盖提县",
+            "code":"653127"
+          },
+          {
+            "name":"岳普湖县",
+            "code":"653128"
+          },
+          {
+            "name":"伽师县",
+            "code":"653129"
+          },
+          {
+            "name":"巴楚县",
+            "code":"653130"
+          },
+          {
+            "name":"塔什库尔干塔吉克自治县",
+            "code":"653131"
+          }
+        ]
+      },
+      {
+        "name":"和田地区",
+        "code":"653200",
+        "sub":[
+          {
+            "name":"和田市",
+            "code":"653201"
+          },
+          {
+            "name":"和田县",
+            "code":"653221"
+          },
+          {
+            "name":"墨玉县",
+            "code":"653222"
+          },
+          {
+            "name":"皮山县",
+            "code":"653223"
+          },
+          {
+            "name":"洛浦县",
+            "code":"653224"
+          },
+          {
+            "name":"策勒县",
+            "code":"653225"
+          },
+          {
+            "name":"于田县",
+            "code":"653226"
+          },
+          {
+            "name":"民丰县",
+            "code":"653227"
+          }
+        ]
+      },
+      {
+        "name":"伊犁哈萨克自治州",
+        "code":"654000",
+        "sub":[
+          {
+            "name":"伊宁市",
+            "code":"654002"
+          },
+          {
+            "name":"奎屯市",
+            "code":"654003"
+          },
+          {
+            "name":"霍尔果斯市",
+            "code":"654004"
+          },
+          {
+            "name":"伊宁县",
+            "code":"654021"
+          },
+          {
+            "name":"察布查尔锡伯自治县",
+            "code":"654022"
+          },
+          {
+            "name":"霍城县",
+            "code":"654023"
+          },
+          {
+            "name":"巩留县",
+            "code":"654024"
+          },
+          {
+            "name":"新源县",
+            "code":"654025"
+          },
+          {
+            "name":"昭苏县",
+            "code":"654026"
+          },
+          {
+            "name":"特克斯县",
+            "code":"654027"
+          },
+          {
+            "name":"尼勒克县",
+            "code":"654028"
+          },
+          {
+            "name":"塔城地区",
+            "code":"654200"
+          },
+          {
+            "name":"塔城市",
+            "code":"654201"
+          },
+          {
+            "name":"乌苏市",
+            "code":"654202"
+          },
+          {
+            "name":"额敏县",
+            "code":"654221"
+          },
+          {
+            "name":"沙湾县",
+            "code":"654223"
+          },
+          {
+            "name":"托里县",
+            "code":"654224"
+          },
+          {
+            "name":"裕民县",
+            "code":"654225"
+          },
+          {
+            "name":"和布克赛尔蒙古自治县",
+            "code":"654226"
+          },
+          {
+            "name":"阿勒泰地区",
+            "code":"654300"
+          },
+          {
+            "name":"阿勒泰市",
+            "code":"654301"
+          },
+          {
+            "name":"布尔津县",
+            "code":"654321"
+          },
+          {
+            "name":"富蕴县",
+            "code":"654322"
+          },
+          {
+            "name":"福海县",
+            "code":"654323"
+          },
+          {
+            "name":"哈巴河县",
+            "code":"654324"
+          },
+          {
+            "name":"青河县",
+            "code":"654325"
+          },
+          {
+            "name":"吉木乃县",
+            "code":"654326"
+          }
+        ]
+      },
+      {
+        "name":"自治区直辖县级行政区划",
+        "code":"659000",
+        "sub":[
+          {
+            "name":"石河子市",
+            "code":"659001"
+          },
+          {
+            "name":"阿拉尔市",
+            "code":"659002"
+          },
+          {
+            "name":"图木舒克市",
+            "code":"659003"
+          },
+          {
+            "name":"五家渠市",
+            "code":"659004"
+          },
+          {
+            "name":"北屯市",
+            "code":"659005"
+          },
+          {
+            "name":"铁门关市",
+            "code":"659006"
+          },
+          {
+            "name":"双河市",
+            "code":"659007"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"台湾省",
+    "code":"710000",
+    "sub":[
+      {
+        "name":"台北市",
+        "code":"710100",
+        "sub":[
+          {
+            "name":"松山区",
+            "code":"710101"
+          },
+          {
+            "name":"信义区",
+            "code":"710102"
+          },
+          {
+            "name":"大安区",
+            "code":"710103"
+          },
+          {
+            "name":"中山区",
+            "code":"710104"
+          },
+          {
+            "name":"中正区",
+            "code":"710105"
+          },
+          {
+            "name":"大同区",
+            "code":"710106"
+          },
+          {
+            "name":"万华区",
+            "code":"710107"
+          },
+          {
+            "name":"文山区",
+            "code":"710108"
+          },
+          {
+            "name":"南港区",
+            "code":"710109"
+          },
+          {
+            "name":"内湖区",
+            "code":"710110"
+          },
+          {
+            "name":"士林区",
+            "code":"710111"
+          },
+          {
+            "name":"北投区",
+            "code":"710112"
+          }
+        ]
+      },
+      {
+        "name":"高雄市",
+        "code":"710200",
+        "sub":[
+          {
+            "name":"盐埕区",
+            "code":"710201"
+          },
+          {
+            "name":"鼓山区",
+            "code":"710202"
+          },
+          {
+            "name":"左营区",
+            "code":"710203"
+          },
+          {
+            "name":"楠梓区",
+            "code":"710204"
+          },
+          {
+            "name":"三民区",
+            "code":"710205"
+          },
+          {
+            "name":"新兴区",
+            "code":"710206"
+          },
+          {
+            "name":"前金区",
+            "code":"710207"
+          },
+          {
+            "name":"苓雅区",
+            "code":"710208"
+          },
+          {
+            "name":"前镇区",
+            "code":"710209"
+          },
+          {
+            "name":"旗津区",
+            "code":"710210"
+          },
+          {
+            "name":"小港区",
+            "code":"710211"
+          },
+          {
+            "name":"凤山区",
+            "code":"710212"
+          },
+          {
+            "name":"林园区",
+            "code":"710213"
+          },
+          {
+            "name":"大寮区",
+            "code":"710214"
+          },
+          {
+            "name":"大树区",
+            "code":"710215"
+          },
+          {
+            "name":"大社区",
+            "code":"710216"
+          },
+          {
+            "name":"仁武区",
+            "code":"710217"
+          },
+          {
+            "name":"鸟松区",
+            "code":"710218"
+          },
+          {
+            "name":"冈山区",
+            "code":"710219"
+          },
+          {
+            "name":"桥头区",
+            "code":"710220"
+          },
+          {
+            "name":"燕巢区",
+            "code":"710221"
+          },
+          {
+            "name":"田寮区",
+            "code":"710222"
+          },
+          {
+            "name":"阿莲区",
+            "code":"710223"
+          },
+          {
+            "name":"路竹区",
+            "code":"710224"
+          },
+          {
+            "name":"湖内区",
+            "code":"710225"
+          },
+          {
+            "name":"茄萣区",
+            "code":"710226"
+          },
+          {
+            "name":"永安区",
+            "code":"710227"
+          },
+          {
+            "name":"弥陀区",
+            "code":"710228"
+          },
+          {
+            "name":"梓官区",
+            "code":"710229"
+          },
+          {
+            "name":"旗山区",
+            "code":"710230"
+          },
+          {
+            "name":"美浓区",
+            "code":"710231"
+          },
+          {
+            "name":"六龟区",
+            "code":"710232"
+          },
+          {
+            "name":"甲仙区",
+            "code":"710233"
+          },
+          {
+            "name":"杉林区",
+            "code":"710234"
+          },
+          {
+            "name":"内门区",
+            "code":"710235"
+          },
+          {
+            "name":"茂林区",
+            "code":"710236"
+          },
+          {
+            "name":"桃源区",
+            "code":"710237"
+          },
+          {
+            "name":"那玛夏区",
+            "code":"710238"
+          }
+        ]
+      },
+      {
+        "name":"基隆市",
+        "code":"710300",
+        "sub":[
+          {
+            "name":"中正区",
+            "code":"710301"
+          },
+          {
+            "name":"七堵区",
+            "code":"710302"
+          },
+          {
+            "name":"暖暖区",
+            "code":"710303"
+          },
+          {
+            "name":"仁爱区",
+            "code":"710304"
+          },
+          {
+            "name":"中山区",
+            "code":"710305"
+          },
+          {
+            "name":"安乐区",
+            "code":"710306"
+          },
+          {
+            "name":"信义区",
+            "code":"710307"
+          }
+        ]
+      },
+      {
+        "name":"台中市",
+        "code":"710400",
+        "sub":[
+          {
+            "name":"中区",
+            "code":"710401"
+          },
+          {
+            "name":"东区",
+            "code":"710402"
+          },
+          {
+            "name":"南区",
+            "code":"710403"
+          },
+          {
+            "name":"西区",
+            "code":"710404"
+          },
+          {
+            "name":"北区",
+            "code":"710405"
+          },
+          {
+            "name":"西屯区",
+            "code":"710406"
+          },
+          {
+            "name":"南屯区",
+            "code":"710407"
+          },
+          {
+            "name":"北屯区",
+            "code":"710408"
+          },
+          {
+            "name":"丰原区",
+            "code":"710409"
+          },
+          {
+            "name":"东势区",
+            "code":"710410"
+          },
+          {
+            "name":"大甲区",
+            "code":"710411"
+          },
+          {
+            "name":"清水区",
+            "code":"710412"
+          },
+          {
+            "name":"沙鹿区",
+            "code":"710413"
+          },
+          {
+            "name":"梧栖区",
+            "code":"710414"
+          },
+          {
+            "name":"后里区",
+            "code":"710415"
+          },
+          {
+            "name":"神冈区",
+            "code":"710416"
+          },
+          {
+            "name":"潭子区",
+            "code":"710417"
+          },
+          {
+            "name":"大雅区",
+            "code":"710418"
+          },
+          {
+            "name":"新社区",
+            "code":"710419"
+          },
+          {
+            "name":"石冈区",
+            "code":"710420"
+          },
+          {
+            "name":"外埔区",
+            "code":"710421"
+          },
+          {
+            "name":"大安区",
+            "code":"710422"
+          },
+          {
+            "name":"乌日区",
+            "code":"710423"
+          },
+          {
+            "name":"大肚区",
+            "code":"710424"
+          },
+          {
+            "name":"龙井区",
+            "code":"710425"
+          },
+          {
+            "name":"雾峰区",
+            "code":"710426"
+          },
+          {
+            "name":"太平区",
+            "code":"710427"
+          },
+          {
+            "name":"大里区",
+            "code":"710428"
+          },
+          {
+            "name":"和平区",
+            "code":"710429"
+          }
+        ]
+      },
+      {
+        "name":"台南市",
+        "code":"710500",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710501"
+          },
+          {
+            "name":"南区",
+            "code":"710502"
+          },
+          {
+            "name":"北区",
+            "code":"710504"
+          },
+          {
+            "name":"安南区",
+            "code":"710506"
+          },
+          {
+            "name":"安平区",
+            "code":"710507"
+          },
+          {
+            "name":"中西区",
+            "code":"710508"
+          },
+          {
+            "name":"新营区",
+            "code":"710509"
+          },
+          {
+            "name":"盐水区",
+            "code":"710510"
+          },
+          {
+            "name":"白河区",
+            "code":"710511"
+          },
+          {
+            "name":"柳营区",
+            "code":"710512"
+          },
+          {
+            "name":"后壁区",
+            "code":"710513"
+          },
+          {
+            "name":"东山区",
+            "code":"710514"
+          },
+          {
+            "name":"麻豆区",
+            "code":"710515"
+          },
+          {
+            "name":"下营区",
+            "code":"710516"
+          },
+          {
+            "name":"六甲区",
+            "code":"710517"
+          },
+          {
+            "name":"官田区",
+            "code":"710518"
+          },
+          {
+            "name":"大内区",
+            "code":"710519"
+          },
+          {
+            "name":"佳里区",
+            "code":"710520"
+          },
+          {
+            "name":"学甲区",
+            "code":"710521"
+          },
+          {
+            "name":"西港区",
+            "code":"710522"
+          },
+          {
+            "name":"七股区",
+            "code":"710523"
+          },
+          {
+            "name":"将军区",
+            "code":"710524"
+          },
+          {
+            "name":"北门区",
+            "code":"710525"
+          },
+          {
+            "name":"新化区",
+            "code":"710526"
+          },
+          {
+            "name":"善化区",
+            "code":"710527"
+          },
+          {
+            "name":"新市区",
+            "code":"710528"
+          },
+          {
+            "name":"安定区",
+            "code":"710529"
+          },
+          {
+            "name":"山上区",
+            "code":"710530"
+          },
+          {
+            "name":"玉井区",
+            "code":"710531"
+          },
+          {
+            "name":"楠西区",
+            "code":"710532"
+          },
+          {
+            "name":"南化区",
+            "code":"710533"
+          },
+          {
+            "name":"左镇区",
+            "code":"710534"
+          },
+          {
+            "name":"仁德区",
+            "code":"710535"
+          },
+          {
+            "name":"归仁区",
+            "code":"710536"
+          },
+          {
+            "name":"关庙区",
+            "code":"710537"
+          },
+          {
+            "name":"龙崎区",
+            "code":"710538"
+          },
+          {
+            "name":"永康区",
+            "code":"710539"
+          }
+        ]
+      },
+      {
+        "name":"新竹市",
+        "code":"710600",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710601"
+          },
+          {
+            "name":"北区",
+            "code":"710602"
+          },
+          {
+            "name":"香山区",
+            "code":"710603"
+          }
+        ]
+      },
+      {
+        "name":"嘉义市",
+        "code":"710700",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710701"
+          },
+          {
+            "name":"西区",
+            "code":"710702"
+          }
+        ]
+      },
+      {
+        "name":"新北市",
+        "code":"710800",
+        "sub":[
+          {
+            "name":"板桥区",
+            "code":"710801"
+          },
+          {
+            "name":"三重区",
+            "code":"710802"
+          },
+          {
+            "name":"中和区",
+            "code":"710803"
+          },
+          {
+            "name":"永和区",
+            "code":"710804"
+          },
+          {
+            "name":"新庄区",
+            "code":"710805"
+          },
+          {
+            "name":"新店区",
+            "code":"710806"
+          },
+          {
+            "name":"树林区",
+            "code":"710807"
+          },
+          {
+            "name":"莺歌区",
+            "code":"710808"
+          },
+          {
+            "name":"三峡区",
+            "code":"710809"
+          },
+          {
+            "name":"淡水区",
+            "code":"710810"
+          },
+          {
+            "name":"汐止区",
+            "code":"710811"
+          },
+          {
+            "name":"瑞芳区",
+            "code":"710812"
+          },
+          {
+            "name":"土城区",
+            "code":"710813"
+          },
+          {
+            "name":"芦洲区",
+            "code":"710814"
+          },
+          {
+            "name":"五股区",
+            "code":"710815"
+          },
+          {
+            "name":"泰山区",
+            "code":"710816"
+          },
+          {
+            "name":"林口区",
+            "code":"710817"
+          },
+          {
+            "name":"深坑区",
+            "code":"710818"
+          },
+          {
+            "name":"石碇区",
+            "code":"710819"
+          },
+          {
+            "name":"坪林区",
+            "code":"710820"
+          },
+          {
+            "name":"三芝区",
+            "code":"710821"
+          },
+          {
+            "name":"石门区",
+            "code":"710822"
+          },
+          {
+            "name":"八里区",
+            "code":"710823"
+          },
+          {
+            "name":"平溪区",
+            "code":"710824"
+          },
+          {
+            "name":"双溪区",
+            "code":"710825"
+          },
+          {
+            "name":"贡寮区",
+            "code":"710826"
+          },
+          {
+            "name":"金山区",
+            "code":"710827"
+          },
+          {
+            "name":"万里区",
+            "code":"710828"
+          },
+          {
+            "name":"乌来区",
+            "code":"710829"
+          }
+        ]
+      },
+      {
+        "name":"宜兰县",
+        "code":"712200",
+        "sub":[
+          {
+            "name":"宜兰市",
+            "code":"712201"
+          },
+          {
+            "name":"罗东镇",
+            "code":"712221"
+          },
+          {
+            "name":"苏澳镇",
+            "code":"712222"
+          },
+          {
+            "name":"头城镇",
+            "code":"712223"
+          },
+          {
+            "name":"礁溪乡",
+            "code":"712224"
+          },
+          {
+            "name":"壮围乡",
+            "code":"712225"
+          },
+          {
+            "name":"员山乡",
+            "code":"712226"
+          },
+          {
+            "name":"冬山乡",
+            "code":"712227"
+          },
+          {
+            "name":"五结乡",
+            "code":"712228"
+          },
+          {
+            "name":"三星乡",
+            "code":"712229"
+          },
+          {
+            "name":"大同乡",
+            "code":"712230"
+          },
+          {
+            "name":"南澳乡",
+            "code":"712231"
+          }
+        ]
+      },
+      {
+        "name":"桃园县",
+        "code":"712300",
+        "sub":[
+          {
+            "name":"桃园市",
+            "code":"712301"
+          },
+          {
+            "name":"中坜市",
+            "code":"712302"
+          },
+          {
+            "name":"平镇市",
+            "code":"712303"
+          },
+          {
+            "name":"八德市",
+            "code":"712304"
+          },
+          {
+            "name":"杨梅市",
+            "code":"712305"
+          },
+          {
+            "name":"大溪镇",
+            "code":"712321"
+          },
+          {
+            "name":"芦竹乡",
+            "code":"712323"
+          },
+          {
+            "name":"大园乡",
+            "code":"712324"
+          },
+          {
+            "name":"龟山乡",
+            "code":"712325"
+          },
+          {
+            "name":"龙潭乡",
+            "code":"712327"
+          },
+          {
+            "name":"新屋乡",
+            "code":"712329"
+          },
+          {
+            "name":"观音乡",
+            "code":"712330"
+          },
+          {
+            "name":"复兴乡",
+            "code":"712331"
+          }
+        ]
+      },
+      {
+        "name":"新竹县",
+        "code":"712400",
+        "sub":[
+          {
+            "name":"竹北市",
+            "code":"712401"
+          },
+          {
+            "name":"竹东镇",
+            "code":"712421"
+          },
+          {
+            "name":"新埔镇",
+            "code":"712422"
+          },
+          {
+            "name":"关西镇",
+            "code":"712423"
+          },
+          {
+            "name":"湖口乡",
+            "code":"712424"
+          },
+          {
+            "name":"新丰乡",
+            "code":"712425"
+          },
+          {
+            "name":"芎林乡",
+            "code":"712426"
+          },
+          {
+            "name":"橫山乡",
+            "code":"712427"
+          },
+          {
+            "name":"北埔乡",
+            "code":"712428"
+          },
+          {
+            "name":"宝山乡",
+            "code":"712429"
+          },
+          {
+            "name":"峨眉乡",
+            "code":"712430"
+          },
+          {
+            "name":"尖石乡",
+            "code":"712431"
+          },
+          {
+            "name":"五峰乡",
+            "code":"712432"
+          }
+        ]
+      },
+      {
+        "name":"苗栗县",
+        "code":"712500",
+        "sub":[
+          {
+            "name":"苗栗市",
+            "code":"712501"
+          },
+          {
+            "name":"苑里镇",
+            "code":"712521"
+          },
+          {
+            "name":"通霄镇",
+            "code":"712522"
+          },
+          {
+            "name":"竹南镇",
+            "code":"712523"
+          },
+          {
+            "name":"头份镇",
+            "code":"712524"
+          },
+          {
+            "name":"后龙镇",
+            "code":"712525"
+          },
+          {
+            "name":"卓兰镇",
+            "code":"712526"
+          },
+          {
+            "name":"大湖乡",
+            "code":"712527"
+          },
+          {
+            "name":"公馆乡",
+            "code":"712528"
+          },
+          {
+            "name":"铜锣乡",
+            "code":"712529"
+          },
+          {
+            "name":"南庄乡",
+            "code":"712530"
+          },
+          {
+            "name":"头屋乡",
+            "code":"712531"
+          },
+          {
+            "name":"三义乡",
+            "code":"712532"
+          },
+          {
+            "name":"西湖乡",
+            "code":"712533"
+          },
+          {
+            "name":"造桥乡",
+            "code":"712534"
+          },
+          {
+            "name":"三湾乡",
+            "code":"712535"
+          },
+          {
+            "name":"狮潭乡",
+            "code":"712536"
+          },
+          {
+            "name":"泰安乡",
+            "code":"712537"
+          }
+        ]
+      },
+      {
+        "name":"彰化县",
+        "code":"712700",
+        "sub":[
+          {
+            "name":"彰化市",
+            "code":"712701"
+          },
+          {
+            "name":"鹿港镇",
+            "code":"712721"
+          },
+          {
+            "name":"和美镇",
+            "code":"712722"
+          },
+          {
+            "name":"线西乡",
+            "code":"712723"
+          },
+          {
+            "name":"伸港乡",
+            "code":"712724"
+          },
+          {
+            "name":"福兴乡",
+            "code":"712725"
+          },
+          {
+            "name":"秀水乡",
+            "code":"712726"
+          },
+          {
+            "name":"花坛乡",
+            "code":"712727"
+          },
+          {
+            "name":"芬园乡",
+            "code":"712728"
+          },
+          {
+            "name":"员林镇",
+            "code":"712729"
+          },
+          {
+            "name":"溪湖镇",
+            "code":"712730"
+          },
+          {
+            "name":"田中镇",
+            "code":"712731"
+          },
+          {
+            "name":"大村乡",
+            "code":"712732"
+          },
+          {
+            "name":"埔盐乡",
+            "code":"712733"
+          },
+          {
+            "name":"埔心乡",
+            "code":"712734"
+          },
+          {
+            "name":"永靖乡",
+            "code":"712735"
+          },
+          {
+            "name":"社头乡",
+            "code":"712736"
+          },
+          {
+            "name":"二水乡",
+            "code":"712737"
+          },
+          {
+            "name":"北斗镇",
+            "code":"712738"
+          },
+          {
+            "name":"二林镇",
+            "code":"712739"
+          },
+          {
+            "name":"田尾乡",
+            "code":"712740"
+          },
+          {
+            "name":"埤头乡",
+            "code":"712741"
+          },
+          {
+            "name":"芳苑乡",
+            "code":"712742"
+          },
+          {
+            "name":"大城乡",
+            "code":"712743"
+          },
+          {
+            "name":"竹塘乡",
+            "code":"712744"
+          },
+          {
+            "name":"溪州乡",
+            "code":"712745"
+          }
+        ]
+      },
+      {
+        "name":"南投县",
+        "code":"712800",
+        "sub":[
+          {
+            "name":"南投市",
+            "code":"712801"
+          },
+          {
+            "name":"埔里镇",
+            "code":"712821"
+          },
+          {
+            "name":"草屯镇",
+            "code":"712822"
+          },
+          {
+            "name":"竹山镇",
+            "code":"712823"
+          },
+          {
+            "name":"集集镇",
+            "code":"712824"
+          },
+          {
+            "name":"名间乡",
+            "code":"712825"
+          },
+          {
+            "name":"鹿谷乡",
+            "code":"712826"
+          },
+          {
+            "name":"中寮乡",
+            "code":"712827"
+          },
+          {
+            "name":"鱼池乡",
+            "code":"712828"
+          },
+          {
+            "name":"国姓乡",
+            "code":"712829"
+          },
+          {
+            "name":"水里乡",
+            "code":"712830"
+          },
+          {
+            "name":"信义乡",
+            "code":"712831"
+          },
+          {
+            "name":"仁爱乡",
+            "code":"712832"
+          }
+        ]
+      },
+      {
+        "name":"云林县",
+        "code":"712900",
+        "sub":[
+          {
+            "name":"斗六市",
+            "code":"712901"
+          },
+          {
+            "name":"斗南镇",
+            "code":"712921"
+          },
+          {
+            "name":"虎尾镇",
+            "code":"712922"
+          },
+          {
+            "name":"西螺镇",
+            "code":"712923"
+          },
+          {
+            "name":"土库镇",
+            "code":"712924"
+          },
+          {
+            "name":"北港镇",
+            "code":"712925"
+          },
+          {
+            "name":"古坑乡",
+            "code":"712926"
+          },
+          {
+            "name":"大埤乡",
+            "code":"712927"
+          },
+          {
+            "name":"莿桐乡",
+            "code":"712928"
+          },
+          {
+            "name":"林内乡",
+            "code":"712929"
+          },
+          {
+            "name":"二仑乡",
+            "code":"712930"
+          },
+          {
+            "name":"仑背乡",
+            "code":"712931"
+          },
+          {
+            "name":"麦寮乡",
+            "code":"712932"
+          },
+          {
+            "name":"东势乡",
+            "code":"712933"
+          },
+          {
+            "name":"褒忠乡",
+            "code":"712934"
+          },
+          {
+            "name":"台西乡",
+            "code":"712935"
+          },
+          {
+            "name":"元长乡",
+            "code":"712936"
+          },
+          {
+            "name":"四湖乡",
+            "code":"712937"
+          },
+          {
+            "name":"口湖乡",
+            "code":"712938"
+          },
+          {
+            "name":"水林乡",
+            "code":"712939"
+          }
+        ]
+      },
+      {
+        "name":"嘉义县",
+        "code":"713000",
+        "sub":[
+          {
+            "name":"太保市",
+            "code":"713001"
+          },
+          {
+            "name":"朴子市",
+            "code":"713002"
+          },
+          {
+            "name":"布袋镇",
+            "code":"713023"
+          },
+          {
+            "name":"大林镇",
+            "code":"713024"
+          },
+          {
+            "name":"民雄乡",
+            "code":"713025"
+          },
+          {
+            "name":"溪口乡",
+            "code":"713026"
+          },
+          {
+            "name":"新港乡",
+            "code":"713027"
+          },
+          {
+            "name":"六脚乡",
+            "code":"713028"
+          },
+          {
+            "name":"东石乡",
+            "code":"713029"
+          },
+          {
+            "name":"义竹乡",
+            "code":"713030"
+          },
+          {
+            "name":"鹿草乡",
+            "code":"713031"
+          },
+          {
+            "name":"水上乡",
+            "code":"713032"
+          },
+          {
+            "name":"中埔乡",
+            "code":"713033"
+          },
+          {
+            "name":"竹崎乡",
+            "code":"713034"
+          },
+          {
+            "name":"梅山乡",
+            "code":"713035"
+          },
+          {
+            "name":"番路乡",
+            "code":"713036"
+          },
+          {
+            "name":"大埔乡",
+            "code":"713037"
+          },
+          {
+            "name":"阿里山乡",
+            "code":"713038"
+          }
+        ]
+      },
+      {
+        "name":"屏东县",
+        "code":"713300",
+        "sub":[
+          {
+            "name":"屏东市",
+            "code":"713301"
+          },
+          {
+            "name":"潮州镇",
+            "code":"713321"
+          },
+          {
+            "name":"东港镇",
+            "code":"713322"
+          },
+          {
+            "name":"恒春镇",
+            "code":"713323"
+          },
+          {
+            "name":"万丹乡",
+            "code":"713324"
+          },
+          {
+            "name":"长治乡",
+            "code":"713325"
+          },
+          {
+            "name":"麟洛乡",
+            "code":"713326"
+          },
+          {
+            "name":"九如乡",
+            "code":"713327"
+          },
+          {
+            "name":"里港乡",
+            "code":"713328"
+          },
+          {
+            "name":"盐埔乡",
+            "code":"713329"
+          },
+          {
+            "name":"高树乡",
+            "code":"713330"
+          },
+          {
+            "name":"万峦乡",
+            "code":"713331"
+          },
+          {
+            "name":"内埔乡",
+            "code":"713332"
+          },
+          {
+            "name":"竹田乡",
+            "code":"713333"
+          },
+          {
+            "name":"新埤乡",
+            "code":"713334"
+          },
+          {
+            "name":"枋寮乡",
+            "code":"713335"
+          },
+          {
+            "name":"新园乡",
+            "code":"713336"
+          },
+          {
+            "name":"崁顶乡",
+            "code":"713337"
+          },
+          {
+            "name":"林边乡",
+            "code":"713338"
+          },
+          {
+            "name":"南州乡",
+            "code":"713339"
+          },
+          {
+            "name":"佳冬乡",
+            "code":"713340"
+          },
+          {
+            "name":"琉球乡",
+            "code":"713341"
+          },
+          {
+            "name":"车城乡",
+            "code":"713342"
+          },
+          {
+            "name":"满州乡",
+            "code":"713343"
+          },
+          {
+            "name":"枋山乡",
+            "code":"713344"
+          },
+          {
+            "name":"三地门乡",
+            "code":"713345"
+          },
+          {
+            "name":"雾台乡",
+            "code":"713346"
+          },
+          {
+            "name":"玛家乡",
+            "code":"713347"
+          },
+          {
+            "name":"泰武乡",
+            "code":"713348"
+          },
+          {
+            "name":"来义乡",
+            "code":"713349"
+          },
+          {
+            "name":"春日乡",
+            "code":"713350"
+          },
+          {
+            "name":"狮子乡",
+            "code":"713351"
+          },
+          {
+            "name":"牡丹乡",
+            "code":"713352"
+          }
+        ]
+      },
+      {
+        "name":"台东县",
+        "code":"713400",
+        "sub":[
+          {
+            "name":"台东市",
+            "code":"713401"
+          },
+          {
+            "name":"成功镇",
+            "code":"713421"
+          },
+          {
+            "name":"关山镇",
+            "code":"713422"
+          },
+          {
+            "name":"卑南乡",
+            "code":"713423"
+          },
+          {
+            "name":"鹿野乡",
+            "code":"713424"
+          },
+          {
+            "name":"池上乡",
+            "code":"713425"
+          },
+          {
+            "name":"东河乡",
+            "code":"713426"
+          },
+          {
+            "name":"长滨乡",
+            "code":"713427"
+          },
+          {
+            "name":"太麻里乡",
+            "code":"713428"
+          },
+          {
+            "name":"大武乡",
+            "code":"713429"
+          },
+          {
+            "name":"绿岛乡",
+            "code":"713430"
+          },
+          {
+            "name":"海端乡",
+            "code":"713431"
+          },
+          {
+            "name":"延平乡",
+            "code":"713432"
+          },
+          {
+            "name":"金峰乡",
+            "code":"713433"
+          },
+          {
+            "name":"达仁乡",
+            "code":"713434"
+          },
+          {
+            "name":"兰屿乡",
+            "code":"713435"
+          }
+        ]
+      },
+      {
+        "name":"花莲县",
+        "code":"713500",
+        "sub":[
+          {
+            "name":"花莲市",
+            "code":"713501"
+          },
+          {
+            "name":"凤林镇",
+            "code":"713521"
+          },
+          {
+            "name":"玉里镇",
+            "code":"713522"
+          },
+          {
+            "name":"新城乡",
+            "code":"713523"
+          },
+          {
+            "name":"吉安乡",
+            "code":"713524"
+          },
+          {
+            "name":"寿丰乡",
+            "code":"713525"
+          },
+          {
+            "name":"光复乡",
+            "code":"713526"
+          },
+          {
+            "name":"丰滨乡",
+            "code":"713527"
+          },
+          {
+            "name":"瑞穗乡",
+            "code":"713528"
+          },
+          {
+            "name":"富里乡",
+            "code":"713529"
+          },
+          {
+            "name":"秀林乡",
+            "code":"713530"
+          },
+          {
+            "name":"万荣乡",
+            "code":"713531"
+          },
+          {
+            "name":"卓溪乡",
+            "code":"713532"
+          }
+        ]
+      },
+      {
+        "name":"澎湖县",
+        "code":"713600",
+        "sub":[
+          {
+            "name":"马公市",
+            "code":"713601"
+          },
+          {
+            "name":"湖西乡",
+            "code":"713621"
+          },
+          {
+            "name":"白沙乡",
+            "code":"713622"
+          },
+          {
+            "name":"西屿乡",
+            "code":"713623"
+          },
+          {
+            "name":"望安乡",
+            "code":"713624"
+          },
+          {
+            "name":"七美乡",
+            "code":"713625"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"香港特别行政区",
+    "code":"810000",
+    "sub":[
+      {
+        "name":"香港岛",
+        "code":"810100",
+        "sub":[
+          {
+            "name":"中西区",
+            "code":"810101"
+          },
+          {
+            "name":"湾仔区",
+            "code":"810102"
+          },
+          {
+            "name":"东区",
+            "code":"810103"
+          },
+          {
+            "name":"南区",
+            "code":"810104"
+          }
+        ]
+      },
+      {
+        "name":"九龙",
+        "code":"810200",
+        "sub":[
+          {
+            "name":"油尖旺区",
+            "code":"810201"
+          },
+          {
+            "name":"深水埗区",
+            "code":"810202"
+          },
+          {
+            "name":"九龙城区",
+            "code":"810203"
+          },
+          {
+            "name":"黄大仙区",
+            "code":"810204"
+          },
+          {
+            "name":"观塘区",
+            "code":"810205"
+          }
+        ]
+      },
+      {
+        "name":"新界",
+        "code":"810300",
+        "sub":[
+          {
+            "name":"荃湾区",
+            "code":"810301"
+          },
+          {
+            "name":"屯门区",
+            "code":"810302"
+          },
+          {
+            "name":"元朗区",
+            "code":"810303"
+          },
+          {
+            "name":"北区",
+            "code":"810304"
+          },
+          {
+            "name":"大埔区",
+            "code":"810305"
+          },
+          {
+            "name":"西贡区",
+            "code":"810306"
+          },
+          {
+            "name":"沙田区",
+            "code":"810307"
+          },
+          {
+            "name":"葵青区",
+            "code":"810308"
+          },
+          {
+            "name":"离岛区",
+            "code":"810309"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"澳门特别行政区",
+    "code":"820000",
+    "sub":[
+      {
+        "name":"澳门半岛",
+        "code":"820100",
+        "sub":[
+          {
+            "name":"花地玛堂区",
+            "code":"820101"
+          },
+          {
+            "name":"圣安多尼堂区",
+            "code":"820102"
+          },
+          {
+            "name":"大堂区",
+            "code":"820103"
+          },
+          {
+            "name":"望德堂区",
+            "code":"820104"
+          },
+          {
+            "name":"风顺堂区",
+            "code":"820105"
+          }
+        ]
+      },
+      {
+        "name":"氹仔岛",
+        "code":"820200",
+        "sub":[
+          {
+            "name":"嘉模堂区",
+            "code":"820201"
+          }
+        ]
+      },
+      {
+        "name":"路环岛",
+        "code":"820300",
+        "sub":[
+          {
+            "name":"圣方济各堂区",
+            "code":"820301"
+          }
+        ]
+      }
+    ]
+  }
+
+];
+}($);
+// jshint ignore: end
+
+/* global $:true */
+/* jshint unused:false*/
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  var raw = $.rawCitiesData;
+
+  var format = function(data) {
+    var result = [];
+    for(var i=0;i<data.length;i++) {
+      var d = data[i];
+      if(/^请选择|市辖区/.test(d.name)) continue;
+      result.push(d);
+    }
+    if(result.length) return result;
+    return [];
+  };
+
+  var sub = function(data) {
+    if(!data.sub) return [{ name: '', code: data.code }];  // 有可能某些县级市没有区
+    return format(data.sub);
+  };
+
+  var getCities = function(d) {
+    for(var i=0;i< raw.length;i++) {
+      if(raw[i].code === d || raw[i].name === d) return sub(raw[i]);
+    }
+    return [];
+  };
+
+  var getDistricts = function(p, c) {
+    for(var i=0;i< raw.length;i++) {
+      if(raw[i].code === p || raw[i].name === p) {
+        for(var j=0;j< raw[i].sub.length;j++) {
+          if(raw[i].sub[j].code === c || raw[i].sub[j].name === c) {
+            return sub(raw[i].sub[j]);
+          }
+        }
+      }
+    }
+  };
+
+  var parseInitValue = function (val) {
+    var p = raw[0], c, d;
+    var tokens = val.split(' ');
+    raw.map(function (t) {
+      if (t.name === tokens[0]) p = t;
+    });
+
+    p.sub.map(function (t) {
+      if (t.name === tokens[1]) c = t;
+    })
+
+    if (tokens[2]) {
+      c.sub.map(function (t) {
+        if (t.name === tokens[2]) d = t;
+      })
+    }
+
+    if (d) return [p.code, c.code, d.code];
+    return [p.code, c.code];
+  }
+
+  $.fn.cityPicker = function(params) {
+    params = $.extend({}, defaults, params);
+    return this.each(function() {
+      var self = this;
+      
+      var provincesName = raw.map(function(d) {
+        return d.name;
+      });
+      var provincesCode = raw.map(function(d) {
+        return d.code;
+      });
+      var initCities = sub(raw[0]);
+      var initCitiesName = initCities.map(function (c) {
+        return c.name;
+      });
+      var initCitiesCode = initCities.map(function (c) {
+        return c.code;
+      });
+      var initDistricts = sub(raw[0].sub[0]);
+
+      var initDistrictsName = initDistricts.map(function (c) {
+        return c.name;
+      });
+      var initDistrictsCode = initDistricts.map(function (c) {
+        return c.code;
+      });
+
+      var currentProvince = provincesName[0];
+      var currentCity = initCitiesName[0];
+      var currentDistrict = initDistrictsName[0];
+
+      var cols = [
+          {
+            displayValues: provincesName,
+            values: provincesCode,
+            cssClass: "col-province"
+          },
+          {
+            displayValues: initCitiesName,
+            values: initCitiesCode,
+            cssClass: "col-city"
+          }
+        ];
+
+        if(params.showDistrict) cols.push({
+          values: initDistrictsCode,
+          displayValues: initDistrictsName,
+          cssClass: "col-district"
+        });
+
+      var config = {
+
+        cssClass: "city-picker",
+        rotateEffect: false,  //为了性能
+        formatValue: function (p, values, displayValues) {
+          return displayValues.join(' ');
+        },
+        onChange: function (picker, values, displayValues) {
+          var newProvince = picker.cols[0].displayValue;
+          var newCity;
+          if(newProvince !== currentProvince) {
+            var newCities = getCities(newProvince);
+            newCity = newCities[0].name;
+            var newDistricts = getDistricts(newProvince, newCity);
+            picker.cols[1].replaceValues(newCities.map(function (c) {
+              return c.code;
+            }), newCities.map(function (c) {
+              return c.name;
+            }));
+            if(params.showDistrict) picker.cols[2].replaceValues(newDistricts.map(function (d) {
+              return d.code;
+            }), newDistricts.map(function (d) {
+              return d.name;
+            }));
+            currentProvince = newProvince;
+            currentCity = newCity;
+            picker.updateValue();
+            return false; // 因为数据未更新完,所以这里不进行后序的值的处理
+          } else {
+            if(params.showDistrict) {
+              newCity = picker.cols[1].displayValue;
+              if(newCity !== currentCity) {
+                var districts = getDistricts(newProvince, newCity);
+                picker.cols[2].replaceValues(districts.map(function (d) {
+                  return d.code;
+                }), districts.map(function (d) {
+                  return d.name;
+                }));
+                currentCity = newCity;
+                picker.updateValue();
+                return false; // 因为数据未更新完,所以这里不进行后序的值的处理
+              }
+            }
+          }
+          //如果最后一列是空的,那么取倒数第二列
+          var len = (values[values.length-1] ? values.length - 1 : values.length - 2)
+          $(self).attr('data-code', values[len]);
+          $(self).attr('data-codes', values.join(','));
+          if (params.onChange) {
+            params.onChange.call(self, picker, values, displayValues);
+          }
+        },
+
+        cols: cols
+      };
+
+      if(!this) return;
+      var p = $.extend({}, params, config);
+      //计算value
+      var val = $(this).val();
+      if (!val) val = '北京 北京市 东城区';
+      currentProvince = val.split(" ")[0];
+      currentCity = val.split(" ")[1];
+      currentDistrict= val.split(" ")[2];
+      if(val) {
+        p.value = parseInitValue(val);
+        if(p.value[0]) {
+          var cities = getCities(p.value[0]);
+          p.cols[1].values = cities.map(function (c) {
+            return c.code;
+          });
+          p.cols[1].displayValues = cities.map(function (c) {
+            return c.name;
+          });
+        }
+
+        if(p.value[1]) {
+          if (params.showDistrict) {
+            var dis = getDistricts(p.value[0], p.value[1]);
+            p.cols[2].values = dis.map(function (d) {
+              return d.code;
+            });
+            p.cols[2].displayValues = dis.map(function (d) {
+              return d.name;
+            });
+          }
+        } else {
+          if (params.showDistrict) {
+            var dis = getDistricts(p.value[0], p.cols[1].values[0]);
+            p.cols[2].values = dis.map(function (d) {
+              return d.code;
+            });
+            p.cols[2].displayValues = dis.map(function (d) {
+              return d.name;
+            });
+          }
+        }
+      }
+      $(this).picker(p);
+    });
+  };
+
+  defaults = $.fn.cityPicker.prototype.defaults = {
+    showDistrict: true //是否显示地区选择
+  };
+
+}($);
diff --git a/platforms/android/app/src/main/assets/www/js/lib/city-picker.min.js b/platforms/android/app/src/main/assets/www/js/lib/city-picker.min.js
new file mode 100755
index 0000000..8091f11
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/city-picker.min.js
@@ -0,0 +1,5 @@
+// jshint ignore: start
++function(e){e.rawCitiesData=[{name:"北京",code:"110000",sub:[{name:"北京市",code:"110000",sub:[{name:"东城区",code:"110101"},{name:"西城区",code:"110102"},{name:"朝阳区",code:"110105"},{name:"丰台区",code:"110106"},{name:"石景山区",code:"110107"},{name:"海淀区",code:"110108"},{name:"门头沟区",code:"110109"},{name:"房山区",code:"110111"},{name:"通州区",code:"110112"},{name:"顺义区",code:"110113"},{name:"昌平区",code:"110114"},{name:"大兴区",code:"110115"},{name:"怀柔区",code:"110116"},{name:"平谷区",code:"110117"},{name:"密云县",code:"110228"},{name:"延庆县",code:"110229"}]}]},{name:"天津",code:"120000",sub:[{name:"天津市",code:"120000",sub:[{name:"和平区",code:"120101"},{name:"河东区",code:"120102"},{name:"河西区",code:"120103"},{name:"南开区",code:"120104"},{name:"河北区",code:"120105"},{name:"红桥区",code:"120106"},{name:"东丽区",code:"120110"},{name:"西青区",code:"120111"},{name:"津南区",code:"120112"},{name:"北辰区",code:"120113"},{name:"武清区",code:"120114"},{name:"宝坻区",code:"120115"},{name:"滨海新区",code:"120116"},{name:"宁河县",code:"120221"},{name:"静海县",code:"120223"},{name:"蓟县",code:"120225"}]}]},{name:"河北省",code:"130000",sub:[{name:"石家庄市",code:"130100",sub:[{name:"市辖区",code:"130101"},{name:"长安区",code:"130102"},{name:"桥西区",code:"130104"},{name:"新华区",code:"130105"},{name:"井陉矿区",code:"130107"},{name:"裕华区",code:"130108"},{name:"藁城区",code:"130109"},{name:"鹿泉区",code:"130110"},{name:"栾城区",code:"130111"},{name:"井陉县",code:"130121"},{name:"正定县",code:"130123"},{name:"行唐县",code:"130125"},{name:"灵寿县",code:"130126"},{name:"高邑县",code:"130127"},{name:"深泽县",code:"130128"},{name:"赞皇县",code:"130129"},{name:"无极县",code:"130130"},{name:"平山县",code:"130131"},{name:"元氏县",code:"130132"},{name:"赵县",code:"130133"},{name:"辛集市",code:"130181"},{name:"晋州市",code:"130183"},{name:"新乐市",code:"130184"}]},{name:"唐山市",code:"130200",sub:[{name:"市辖区",code:"130201"},{name:"路南区",code:"130202"},{name:"路北区",code:"130203"},{name:"古冶区",code:"130204"},{name:"开平区",code:"130205"},{name:"丰南区",code:"130207"},{name:"丰润区",code:"130208"},{name:"曹妃甸区",code:"130209"},{name:"滦县",code:"130223"},{name:"滦南县",code:"130224"},{name:"乐亭县",code:"130225"},{name:"迁西县",code:"130227"},{name:"玉田县",code:"130229"},{name:"遵化市",code:"130281"},{name:"迁安市",code:"130283"}]},{name:"秦皇岛市",code:"130300",sub:[{name:"市辖区",code:"130301"},{name:"海港区",code:"130302"},{name:"山海关区",code:"130303"},{name:"北戴河区",code:"130304"},{name:"青龙满族自治县",code:"130321"},{name:"昌黎县",code:"130322"},{name:"抚宁县",code:"130323"},{name:"卢龙县",code:"130324"}]},{name:"邯郸市",code:"130400",sub:[{name:"市辖区",code:"130401"},{name:"邯山区",code:"130402"},{name:"丛台区",code:"130403"},{name:"复兴区",code:"130404"},{name:"峰峰矿区",code:"130406"},{name:"邯郸县",code:"130421"},{name:"临漳县",code:"130423"},{name:"成安县",code:"130424"},{name:"大名县",code:"130425"},{name:"涉县",code:"130426"},{name:"磁县",code:"130427"},{name:"肥乡县",code:"130428"},{name:"永年县",code:"130429"},{name:"邱县",code:"130430"},{name:"鸡泽县",code:"130431"},{name:"广平县",code:"130432"},{name:"馆陶县",code:"130433"},{name:"魏县",code:"130434"},{name:"曲周县",code:"130435"},{name:"武安市",code:"130481"}]},{name:"邢台市",code:"130500",sub:[{name:"市辖区",code:"130501"},{name:"桥东区",code:"130502"},{name:"桥西区",code:"130503"},{name:"邢台县",code:"130521"},{name:"临城县",code:"130522"},{name:"内丘县",code:"130523"},{name:"柏乡县",code:"130524"},{name:"隆尧县",code:"130525"},{name:"任县",code:"130526"},{name:"南和县",code:"130527"},{name:"宁晋县",code:"130528"},{name:"巨鹿县",code:"130529"},{name:"新河县",code:"130530"},{name:"广宗县",code:"130531"},{name:"平乡县",code:"130532"},{name:"威县",code:"130533"},{name:"清河县",code:"130534"},{name:"临西县",code:"130535"},{name:"南宫市",code:"130581"},{name:"沙河市",code:"130582"}]},{name:"保定市",code:"130600",sub:[{name:"市辖区",code:"130601"},{name:"新市区",code:"130602"},{name:"北市区",code:"130603"},{name:"南市区",code:"130604"},{name:"满城县",code:"130621"},{name:"清苑县",code:"130622"},{name:"涞水县",code:"130623"},{name:"阜平县",code:"130624"},{name:"徐水县",code:"130625"},{name:"定兴县",code:"130626"},{name:"唐县",code:"130627"},{name:"高阳县",code:"130628"},{name:"容城县",code:"130629"},{name:"涞源县",code:"130630"},{name:"望都县",code:"130631"},{name:"安新县",code:"130632"},{name:"易县",code:"130633"},{name:"曲阳县",code:"130634"},{name:"蠡县",code:"130635"},{name:"顺平县",code:"130636"},{name:"博野县",code:"130637"},{name:"雄县",code:"130638"},{name:"涿州市",code:"130681"},{name:"定州市",code:"130682"},{name:"安国市",code:"130683"},{name:"高碑店市",code:"130684"}]},{name:"张家口市",code:"130700",sub:[{name:"市辖区",code:"130701"},{name:"桥东区",code:"130702"},{name:"桥西区",code:"130703"},{name:"宣化区",code:"130705"},{name:"下花园区",code:"130706"},{name:"宣化县",code:"130721"},{name:"张北县",code:"130722"},{name:"康保县",code:"130723"},{name:"沽源县",code:"130724"},{name:"尚义县",code:"130725"},{name:"蔚县",code:"130726"},{name:"阳原县",code:"130727"},{name:"怀安县",code:"130728"},{name:"万全县",code:"130729"},{name:"怀来县",code:"130730"},{name:"涿鹿县",code:"130731"},{name:"赤城县",code:"130732"},{name:"崇礼县",code:"130733"}]},{name:"承德市",code:"130800",sub:[{name:"市辖区",code:"130801"},{name:"双桥区",code:"130802"},{name:"双滦区",code:"130803"},{name:"鹰手营子矿区",code:"130804"},{name:"承德县",code:"130821"},{name:"兴隆县",code:"130822"},{name:"平泉县",code:"130823"},{name:"滦平县",code:"130824"},{name:"隆化县",code:"130825"},{name:"丰宁满族自治县",code:"130826"},{name:"宽城满族自治县",code:"130827"},{name:"围场满族蒙古族自治县",code:"130828"}]},{name:"沧州市",code:"130900",sub:[{name:"市辖区",code:"130901"},{name:"新华区",code:"130902"},{name:"运河区",code:"130903"},{name:"沧县",code:"130921"},{name:"青县",code:"130922"},{name:"东光县",code:"130923"},{name:"海兴县",code:"130924"},{name:"盐山县",code:"130925"},{name:"肃宁县",code:"130926"},{name:"南皮县",code:"130927"},{name:"吴桥县",code:"130928"},{name:"献县",code:"130929"},{name:"孟村回族自治县",code:"130930"},{name:"泊头市",code:"130981"},{name:"任丘市",code:"130982"},{name:"黄骅市",code:"130983"},{name:"河间市",code:"130984"}]},{name:"廊坊市",code:"131000",sub:[{name:"市辖区",code:"131001"},{name:"安次区",code:"131002"},{name:"广阳区",code:"131003"},{name:"固安县",code:"131022"},{name:"永清县",code:"131023"},{name:"香河县",code:"131024"},{name:"大城县",code:"131025"},{name:"文安县",code:"131026"},{name:"大厂回族自治县",code:"131028"},{name:"霸州市",code:"131081"},{name:"三河市",code:"131082"}]},{name:"衡水市",code:"131100",sub:[{name:"市辖区",code:"131101"},{name:"桃城区",code:"131102"},{name:"枣强县",code:"131121"},{name:"武邑县",code:"131122"},{name:"武强县",code:"131123"},{name:"饶阳县",code:"131124"},{name:"安平县",code:"131125"},{name:"故城县",code:"131126"},{name:"景县",code:"131127"},{name:"阜城县",code:"131128"},{name:"冀州市",code:"131181"},{name:"深州市",code:"131182"}]}]},{name:"山西省",code:"140000",sub:[{name:"太原市",code:"140100",sub:[{name:"市辖区",code:"140101"},{name:"小店区",code:"140105"},{name:"迎泽区",code:"140106"},{name:"杏花岭区",code:"140107"},{name:"尖草坪区",code:"140108"},{name:"万柏林区",code:"140109"},{name:"晋源区",code:"140110"},{name:"清徐县",code:"140121"},{name:"阳曲县",code:"140122"},{name:"娄烦县",code:"140123"},{name:"古交市",code:"140181"}]},{name:"大同市",code:"140200",sub:[{name:"市辖区",code:"140201"},{name:"城区",code:"140202"},{name:"矿区",code:"140203"},{name:"南郊区",code:"140211"},{name:"新荣区",code:"140212"},{name:"阳高县",code:"140221"},{name:"天镇县",code:"140222"},{name:"广灵县",code:"140223"},{name:"灵丘县",code:"140224"},{name:"浑源县",code:"140225"},{name:"左云县",code:"140226"},{name:"大同县",code:"140227"}]},{name:"阳泉市",code:"140300",sub:[{name:"市辖区",code:"140301"},{name:"城区",code:"140302"},{name:"矿区",code:"140303"},{name:"郊区",code:"140311"},{name:"平定县",code:"140321"},{name:"盂县",code:"140322"}]},{name:"长治市",code:"140400",sub:[{name:"市辖区",code:"140401"},{name:"城区",code:"140402"},{name:"郊区",code:"140411"},{name:"长治县",code:"140421"},{name:"襄垣县",code:"140423"},{name:"屯留县",code:"140424"},{name:"平顺县",code:"140425"},{name:"黎城县",code:"140426"},{name:"壶关县",code:"140427"},{name:"长子县",code:"140428"},{name:"武乡县",code:"140429"},{name:"沁县",code:"140430"},{name:"沁源县",code:"140431"},{name:"潞城市",code:"140481"}]},{name:"晋城市",code:"140500",sub:[{name:"市辖区",code:"140501"},{name:"城区",code:"140502"},{name:"沁水县",code:"140521"},{name:"阳城县",code:"140522"},{name:"陵川县",code:"140524"},{name:"泽州县",code:"140525"},{name:"高平市",code:"140581"}]},{name:"朔州市",code:"140600",sub:[{name:"市辖区",code:"140601"},{name:"朔城区",code:"140602"},{name:"平鲁区",code:"140603"},{name:"山阴县",code:"140621"},{name:"应县",code:"140622"},{name:"右玉县",code:"140623"},{name:"怀仁县",code:"140624"}]},{name:"晋中市",code:"140700",sub:[{name:"市辖区",code:"140701"},{name:"榆次区",code:"140702"},{name:"榆社县",code:"140721"},{name:"左权县",code:"140722"},{name:"和顺县",code:"140723"},{name:"昔阳县",code:"140724"},{name:"寿阳县",code:"140725"},{name:"太谷县",code:"140726"},{name:"祁县",code:"140727"},{name:"平遥县",code:"140728"},{name:"灵石县",code:"140729"},{name:"介休市",code:"140781"}]},{name:"运城市",code:"140800",sub:[{name:"市辖区",code:"140801"},{name:"盐湖区",code:"140802"},{name:"临猗县",code:"140821"},{name:"万荣县",code:"140822"},{name:"闻喜县",code:"140823"},{name:"稷山县",code:"140824"},{name:"新绛县",code:"140825"},{name:"绛县",code:"140826"},{name:"垣曲县",code:"140827"},{name:"夏县",code:"140828"},{name:"平陆县",code:"140829"},{name:"芮城县",code:"140830"},{name:"永济市",code:"140881"},{name:"河津市",code:"140882"}]},{name:"忻州市",code:"140900",sub:[{name:"市辖区",code:"140901"},{name:"忻府区",code:"140902"},{name:"定襄县",code:"140921"},{name:"五台县",code:"140922"},{name:"代县",code:"140923"},{name:"繁峙县",code:"140924"},{name:"宁武县",code:"140925"},{name:"静乐县",code:"140926"},{name:"神池县",code:"140927"},{name:"五寨县",code:"140928"},{name:"岢岚县",code:"140929"},{name:"河曲县",code:"140930"},{name:"保德县",code:"140931"},{name:"偏关县",code:"140932"},{name:"原平市",code:"140981"}]},{name:"临汾市",code:"141000",sub:[{name:"市辖区",code:"141001"},{name:"尧都区",code:"141002"},{name:"曲沃县",code:"141021"},{name:"翼城县",code:"141022"},{name:"襄汾县",code:"141023"},{name:"洪洞县",code:"141024"},{name:"古县",code:"141025"},{name:"安泽县",code:"141026"},{name:"浮山县",code:"141027"},{name:"吉县",code:"141028"},{name:"乡宁县",code:"141029"},{name:"大宁县",code:"141030"},{name:"隰县",code:"141031"},{name:"永和县",code:"141032"},{name:"蒲县",code:"141033"},{name:"汾西县",code:"141034"},{name:"侯马市",code:"141081"},{name:"霍州市",code:"141082"}]},{name:"吕梁市",code:"141100",sub:[{name:"市辖区",code:"141101"},{name:"离石区",code:"141102"},{name:"文水县",code:"141121"},{name:"交城县",code:"141122"},{name:"兴县",code:"141123"},{name:"临县",code:"141124"},{name:"柳林县",code:"141125"},{name:"石楼县",code:"141126"},{name:"岚县",code:"141127"},{name:"方山县",code:"141128"},{name:"中阳县",code:"141129"},{name:"交口县",code:"141130"},{name:"孝义市",code:"141181"},{name:"汾阳市",code:"141182"}]}]},{name:"内蒙古自治区",code:"150000",sub:[{name:"呼和浩特市",code:"150100",sub:[{name:"市辖区",code:"150101"},{name:"新城区",code:"150102"},{name:"回民区",code:"150103"},{name:"玉泉区",code:"150104"},{name:"赛罕区",code:"150105"},{name:"土默特左旗",code:"150121"},{name:"托克托县",code:"150122"},{name:"和林格尔县",code:"150123"},{name:"清水河县",code:"150124"},{name:"武川县",code:"150125"}]},{name:"包头市",code:"150200",sub:[{name:"市辖区",code:"150201"},{name:"东河区",code:"150202"},{name:"昆都仑区",code:"150203"},{name:"青山区",code:"150204"},{name:"石拐区",code:"150205"},{name:"白云鄂博矿区",code:"150206"},{name:"九原区",code:"150207"},{name:"土默特右旗",code:"150221"},{name:"固阳县",code:"150222"},{name:"达尔罕茂明安联合旗",code:"150223"}]},{name:"乌海市",code:"150300",sub:[{name:"市辖区",code:"150301"},{name:"海勃湾区",code:"150302"},{name:"海南区",code:"150303"},{name:"乌达区",code:"150304"}]},{name:"赤峰市",code:"150400",sub:[{name:"市辖区",code:"150401"},{name:"红山区",code:"150402"},{name:"元宝山区",code:"150403"},{name:"松山区",code:"150404"},{name:"阿鲁科尔沁旗",code:"150421"},{name:"巴林左旗",code:"150422"},{name:"巴林右旗",code:"150423"},{name:"林西县",code:"150424"},{name:"克什克腾旗",code:"150425"},{name:"翁牛特旗",code:"150426"},{name:"喀喇沁旗",code:"150428"},{name:"宁城县",code:"150429"},{name:"敖汉旗",code:"150430"}]},{name:"通辽市",code:"150500",sub:[{name:"市辖区",code:"150501"},{name:"科尔沁区",code:"150502"},{name:"科尔沁左翼中旗",code:"150521"},{name:"科尔沁左翼后旗",code:"150522"},{name:"开鲁县",code:"150523"},{name:"库伦旗",code:"150524"},{name:"奈曼旗",code:"150525"},{name:"扎鲁特旗",code:"150526"},{name:"霍林郭勒市",code:"150581"}]},{name:"鄂尔多斯市",code:"150600",sub:[{name:"市辖区",code:"150601"},{name:"东胜区",code:"150602"},{name:"达拉特旗",code:"150621"},{name:"准格尔旗",code:"150622"},{name:"鄂托克前旗",code:"150623"},{name:"鄂托克旗",code:"150624"},{name:"杭锦旗",code:"150625"},{name:"乌审旗",code:"150626"},{name:"伊金霍洛旗",code:"150627"}]},{name:"呼伦贝尔市",code:"150700",sub:[{name:"市辖区",code:"150701"},{name:"海拉尔区",code:"150702"},{name:"扎赉诺尔区",code:"150703"},{name:"阿荣旗",code:"150721"},{name:"莫力达瓦达斡尔族自治旗",code:"150722"},{name:"鄂伦春自治旗",code:"150723"},{name:"鄂温克族自治旗",code:"150724"},{name:"陈巴尔虎旗",code:"150725"},{name:"新巴尔虎左旗",code:"150726"},{name:"新巴尔虎右旗",code:"150727"},{name:"满洲里市",code:"150781"},{name:"牙克石市",code:"150782"},{name:"扎兰屯市",code:"150783"},{name:"额尔古纳市",code:"150784"},{name:"根河市",code:"150785"}]},{name:"巴彦淖尔市",code:"150800",sub:[{name:"市辖区",code:"150801"},{name:"临河区",code:"150802"},{name:"五原县",code:"150821"},{name:"磴口县",code:"150822"},{name:"乌拉特前旗",code:"150823"},{name:"乌拉特中旗",code:"150824"},{name:"乌拉特后旗",code:"150825"},{name:"杭锦后旗",code:"150826"}]},{name:"乌兰察布市",code:"150900",sub:[{name:"市辖区",code:"150901"},{name:"集宁区",code:"150902"},{name:"卓资县",code:"150921"},{name:"化德县",code:"150922"},{name:"商都县",code:"150923"},{name:"兴和县",code:"150924"},{name:"凉城县",code:"150925"},{name:"察哈尔右翼前旗",code:"150926"},{name:"察哈尔右翼中旗",code:"150927"},{name:"察哈尔右翼后旗",code:"150928"},{name:"四子王旗",code:"150929"},{name:"丰镇市",code:"150981"}]},{name:"兴安盟",code:"152200",sub:[{name:"乌兰浩特市",code:"152201"},{name:"阿尔山市",code:"152202"},{name:"科尔沁右翼前旗",code:"152221"},{name:"科尔沁右翼中旗",code:"152222"},{name:"扎赉特旗",code:"152223"},{name:"突泉县",code:"152224"}]},{name:"锡林郭勒盟",code:"152500",sub:[{name:"二连浩特市",code:"152501"},{name:"锡林浩特市",code:"152502"},{name:"阿巴嘎旗",code:"152522"},{name:"苏尼特左旗",code:"152523"},{name:"苏尼特右旗",code:"152524"},{name:"东乌珠穆沁旗",code:"152525"},{name:"西乌珠穆沁旗",code:"152526"},{name:"太仆寺旗",code:"152527"},{name:"镶黄旗",code:"152528"},{name:"正镶白旗",code:"152529"},{name:"正蓝旗",code:"152530"},{name:"多伦县",code:"152531"}]},{name:"阿拉善盟",code:"152900",sub:[{name:"阿拉善左旗",code:"152921"},{name:"阿拉善右旗",code:"152922"},{name:"额济纳旗",code:"152923"}]}]},{name:"辽宁省",code:"210000",sub:[{name:"沈阳市",code:"210100",sub:[{name:"市辖区",code:"210101"},{name:"和平区",code:"210102"},{name:"沈河区",code:"210103"},{name:"大东区",code:"210104"},{name:"皇姑区",code:"210105"},{name:"铁西区",code:"210106"},{name:"苏家屯区",code:"210111"},{name:"浑南区",code:"210112"},{name:"沈北新区",code:"210113"},{name:"于洪区",code:"210114"},{name:"辽中县",code:"210122"},{name:"康平县",code:"210123"},{name:"法库县",code:"210124"},{name:"新民市",code:"210181"}]},{name:"大连市",code:"210200",sub:[{name:"市辖区",code:"210201"},{name:"中山区",code:"210202"},{name:"西岗区",code:"210203"},{name:"沙河口区",code:"210204"},{name:"甘井子区",code:"210211"},{name:"旅顺口区",code:"210212"},{name:"金州区",code:"210213"},{name:"长海县",code:"210224"},{name:"瓦房店市",code:"210281"},{name:"普兰店市",code:"210282"},{name:"庄河市",code:"210283"}]},{name:"鞍山市",code:"210300",sub:[{name:"市辖区",code:"210301"},{name:"铁东区",code:"210302"},{name:"铁西区",code:"210303"},{name:"立山区",code:"210304"},{name:"千山区",code:"210311"},{name:"台安县",code:"210321"},{name:"岫岩满族自治县",code:"210323"},{name:"海城市",code:"210381"}]},{name:"抚顺市",code:"210400",sub:[{name:"市辖区",code:"210401"},{name:"新抚区",code:"210402"},{name:"东洲区",code:"210403"},{name:"望花区",code:"210404"},{name:"顺城区",code:"210411"},{name:"抚顺县",code:"210421"},{name:"新宾满族自治县",code:"210422"},{name:"清原满族自治县",code:"210423"}]},{name:"本溪市",code:"210500",sub:[{name:"市辖区",code:"210501"},{name:"平山区",code:"210502"},{name:"溪湖区",code:"210503"},{name:"明山区",code:"210504"},{name:"南芬区",code:"210505"},{name:"本溪满族自治县",code:"210521"},{name:"桓仁满族自治县",code:"210522"}]},{name:"丹东市",code:"210600",sub:[{name:"市辖区",code:"210601"},{name:"元宝区",code:"210602"},{name:"振兴区",code:"210603"},{name:"振安区",code:"210604"},{name:"宽甸满族自治县",code:"210624"},{name:"东港市",code:"210681"},{name:"凤城市",code:"210682"}]},{name:"锦州市",code:"210700",sub:[{name:"市辖区",code:"210701"},{name:"古塔区",code:"210702"},{name:"凌河区",code:"210703"},{name:"太和区",code:"210711"},{name:"黑山县",code:"210726"},{name:"义县",code:"210727"},{name:"凌海市",code:"210781"},{name:"北镇市",code:"210782"}]},{name:"营口市",code:"210800",sub:[{name:"市辖区",code:"210801"},{name:"站前区",code:"210802"},{name:"西市区",code:"210803"},{name:"鲅鱼圈区",code:"210804"},{name:"老边区",code:"210811"},{name:"盖州市",code:"210881"},{name:"大石桥市",code:"210882"}]},{name:"阜新市",code:"210900",sub:[{name:"市辖区",code:"210901"},{name:"海州区",code:"210902"},{name:"新邱区",code:"210903"},{name:"太平区",code:"210904"},{name:"清河门区",code:"210905"},{name:"细河区",code:"210911"},{name:"阜新蒙古族自治县",code:"210921"},{name:"彰武县",code:"210922"}]},{name:"辽阳市",code:"211000",sub:[{name:"市辖区",code:"211001"},{name:"白塔区",code:"211002"},{name:"文圣区",code:"211003"},{name:"宏伟区",code:"211004"},{name:"弓长岭区",code:"211005"},{name:"太子河区",code:"211011"},{name:"辽阳县",code:"211021"},{name:"灯塔市",code:"211081"}]},{name:"盘锦市",code:"211100",sub:[{name:"市辖区",code:"211101"},{name:"双台子区",code:"211102"},{name:"兴隆台区",code:"211103"},{name:"大洼县",code:"211121"},{name:"盘山县",code:"211122"}]},{name:"铁岭市",code:"211200",sub:[{name:"市辖区",code:"211201"},{name:"银州区",code:"211202"},{name:"清河区",code:"211204"},{name:"铁岭县",code:"211221"},{name:"西丰县",code:"211223"},{name:"昌图县",code:"211224"},{name:"调兵山市",code:"211281"},{name:"开原市",code:"211282"}]},{name:"朝阳市",code:"211300",sub:[{name:"市辖区",code:"211301"},{name:"双塔区",code:"211302"},{name:"龙城区",code:"211303"},{name:"朝阳县",code:"211321"},{name:"建平县",code:"211322"},{name:"喀喇沁左翼蒙古族自治县",code:"211324"},{name:"北票市",code:"211381"},{name:"凌源市",code:"211382"}]},{name:"葫芦岛市",code:"211400",sub:[{name:"市辖区",code:"211401"},{name:"连山区",code:"211402"},{name:"龙港区",code:"211403"},{name:"南票区",code:"211404"},{name:"绥中县",code:"211421"},{name:"建昌县",code:"211422"},{name:"兴城市",code:"211481"}]}]},{name:"吉林省",code:"220000",sub:[{name:"长春市",code:"220100",sub:[{name:"市辖区",code:"220101"},{name:"南关区",code:"220102"},{name:"宽城区",code:"220103"},{name:"朝阳区",code:"220104"},{name:"二道区",code:"220105"},{name:"绿园区",code:"220106"},{name:"双阳区",code:"220112"},{name:"九台区",code:"220113"},{name:"农安县",code:"220122"},{name:"榆树市",code:"220182"},{name:"德惠市",code:"220183"}]},{name:"吉林市",code:"220200",sub:[{name:"市辖区",code:"220201"},{name:"昌邑区",code:"220202"},{name:"龙潭区",code:"220203"},{name:"船营区",code:"220204"},{name:"丰满区",code:"220211"},{name:"永吉县",code:"220221"},{name:"蛟河市",code:"220281"},{name:"桦甸市",code:"220282"},{name:"舒兰市",code:"220283"},{name:"磐石市",code:"220284"}]},{name:"四平市",code:"220300",sub:[{name:"市辖区",code:"220301"},{name:"铁西区",code:"220302"},{name:"铁东区",code:"220303"},{name:"梨树县",code:"220322"},{name:"伊通满族自治县",code:"220323"},{name:"公主岭市",code:"220381"},{name:"双辽市",code:"220382"}]},{name:"辽源市",code:"220400",sub:[{name:"市辖区",code:"220401"},{name:"龙山区",code:"220402"},{name:"西安区",code:"220403"},{name:"东丰县",code:"220421"},{name:"东辽县",code:"220422"}]},{name:"通化市",code:"220500",sub:[{name:"市辖区",code:"220501"},{name:"东昌区",code:"220502"},{name:"二道江区",code:"220503"},{name:"通化县",code:"220521"},{name:"辉南县",code:"220523"},{name:"柳河县",code:"220524"},{name:"梅河口市",code:"220581"},{name:"集安市",code:"220582"}]},{name:"白山市",code:"220600",sub:[{name:"市辖区",code:"220601"},{name:"浑江区",code:"220602"},{name:"江源区",code:"220605"},{name:"抚松县",code:"220621"},{name:"靖宇县",code:"220622"},{name:"长白朝鲜族自治县",code:"220623"},{name:"临江市",code:"220681"}]},{name:"松原市",code:"220700",sub:[{name:"市辖区",code:"220701"},{name:"宁江区",code:"220702"},{name:"前郭尔罗斯蒙古族自治县",code:"220721"},{name:"长岭县",code:"220722"},{name:"乾安县",code:"220723"},{name:"扶余市",code:"220781"}]},{name:"白城市",code:"220800",sub:[{name:"市辖区",code:"220801"},{name:"洮北区",code:"220802"},{name:"镇赉县",code:"220821"},{name:"通榆县",code:"220822"},{name:"洮南市",code:"220881"},{name:"大安市",code:"220882"}]},{name:"延边朝鲜族自治州",code:"222400",sub:[{name:"延吉市",code:"222401"},{name:"图们市",code:"222402"},{name:"敦化市",code:"222403"},{name:"珲春市",code:"222404"},{name:"龙井市",code:"222405"},{name:"和龙市",code:"222406"},{name:"汪清县",code:"222424"},{name:"安图县",code:"222426"}]}]},{name:"黑龙江省",code:"230000",sub:[{name:"哈尔滨市",code:"230100",sub:[{name:"市辖区",code:"230101"},{name:"道里区",code:"230102"},{name:"南岗区",code:"230103"},{name:"道外区",code:"230104"},{name:"平房区",code:"230108"},{name:"松北区",code:"230109"},{name:"香坊区",code:"230110"},{name:"呼兰区",code:"230111"},{name:"阿城区",code:"230112"},{name:"双城区",code:"230113"},{name:"依兰县",code:"230123"},{name:"方正县",code:"230124"},{name:"宾县",code:"230125"},{name:"巴彦县",code:"230126"},{name:"木兰县",code:"230127"},{name:"通河县",code:"230128"},{name:"延寿县",code:"230129"},{name:"尚志市",code:"230183"},{name:"五常市",code:"230184"}]},{name:"齐齐哈尔市",code:"230200",sub:[{name:"市辖区",code:"230201"},{name:"龙沙区",code:"230202"},{name:"建华区",code:"230203"},{name:"铁锋区",code:"230204"},{name:"昂昂溪区",code:"230205"},{name:"富拉尔基区",code:"230206"},{name:"碾子山区",code:"230207"},{name:"梅里斯达斡尔族区",code:"230208"},{name:"龙江县",code:"230221"},{name:"依安县",code:"230223"},{name:"泰来县",code:"230224"},{name:"甘南县",code:"230225"},{name:"富裕县",code:"230227"},{name:"克山县",code:"230229"},{name:"克东县",code:"230230"},{name:"拜泉县",code:"230231"},{name:"讷河市",code:"230281"}]},{name:"鸡西市",code:"230300",sub:[{name:"市辖区",code:"230301"},{name:"鸡冠区",code:"230302"},{name:"恒山区",code:"230303"},{name:"滴道区",code:"230304"},{name:"梨树区",code:"230305"},{name:"城子河区",code:"230306"},{name:"麻山区",code:"230307"},{name:"鸡东县",code:"230321"},{name:"虎林市",code:"230381"},{name:"密山市",code:"230382"}]},{name:"鹤岗市",code:"230400",sub:[{name:"市辖区",code:"230401"},{name:"向阳区",code:"230402"},{name:"工农区",code:"230403"},{name:"南山区",code:"230404"},{name:"兴安区",code:"230405"},{name:"东山区",code:"230406"},{name:"兴山区",code:"230407"},{name:"萝北县",code:"230421"},{name:"绥滨县",code:"230422"}]},{name:"双鸭山市",code:"230500",sub:[{name:"市辖区",code:"230501"},{name:"尖山区",code:"230502"},{name:"岭东区",code:"230503"},{name:"四方台区",code:"230505"},{name:"宝山区",code:"230506"},{name:"集贤县",code:"230521"},{name:"友谊县",code:"230522"},{name:"宝清县",code:"230523"},{name:"饶河县",code:"230524"}]},{name:"大庆市",code:"230600",sub:[{name:"市辖区",code:"230601"},{name:"萨尔图区",code:"230602"},{name:"龙凤区",code:"230603"},{name:"让胡路区",code:"230604"},{name:"红岗区",code:"230605"},{name:"大同区",code:"230606"},{name:"肇州县",code:"230621"},{name:"肇源县",code:"230622"},{name:"林甸县",code:"230623"},{name:"杜尔伯特蒙古族自治县",code:"230624"}]},{name:"伊春市",code:"230700",sub:[{name:"市辖区",code:"230701"},{name:"伊春区",code:"230702"},{name:"南岔区",code:"230703"},{name:"友好区",code:"230704"},{name:"西林区",code:"230705"},{name:"翠峦区",code:"230706"},{name:"新青区",code:"230707"},{name:"美溪区",code:"230708"},{name:"金山屯区",code:"230709"},{name:"五营区",code:"230710"},{name:"乌马河区",code:"230711"},{name:"汤旺河区",code:"230712"},{name:"带岭区",code:"230713"},{name:"乌伊岭区",code:"230714"},{name:"红星区",code:"230715"},{name:"上甘岭区",code:"230716"},{name:"嘉荫县",code:"230722"},{name:"铁力市",code:"230781"}]},{name:"佳木斯市",code:"230800",sub:[{name:"市辖区",code:"230801"},{name:"向阳区",code:"230803"},{name:"前进区",code:"230804"},{name:"东风区",code:"230805"},{name:"郊区",code:"230811"},{name:"桦南县",code:"230822"},{name:"桦川县",code:"230826"},{name:"汤原县",code:"230828"},{name:"抚远县",code:"230833"},{name:"同江市",code:"230881"},{name:"富锦市",code:"230882"}]},{name:"七台河市",code:"230900",sub:[{name:"市辖区",code:"230901"},{name:"新兴区",code:"230902"},{name:"桃山区",code:"230903"},{name:"茄子河区",code:"230904"},{name:"勃利县",code:"230921"}]},{name:"牡丹江市",code:"231000",sub:[{name:"市辖区",code:"231001"},{name:"东安区",code:"231002"},{name:"阳明区",code:"231003"},{name:"爱民区",code:"231004"},{name:"西安区",code:"231005"},{name:"东宁县",code:"231024"},{name:"林口县",code:"231025"},{name:"绥芬河市",code:"231081"},{name:"海林市",code:"231083"},{name:"宁安市",code:"231084"},{name:"穆棱市",code:"231085"}]},{name:"黑河市",code:"231100",sub:[{name:"市辖区",code:"231101"},{name:"爱辉区",code:"231102"},{name:"嫩江县",code:"231121"},{name:"逊克县",code:"231123"},{name:"孙吴县",code:"231124"},{name:"北安市",code:"231181"},{name:"五大连池市",code:"231182"}]},{name:"绥化市",code:"231200",sub:[{name:"市辖区",code:"231201"},{name:"北林区",code:"231202"},{name:"望奎县",code:"231221"},{name:"兰西县",code:"231222"},{name:"青冈县",code:"231223"},{name:"庆安县",code:"231224"},{name:"明水县",code:"231225"},{name:"绥棱县",code:"231226"},{name:"安达市",code:"231281"},{name:"肇东市",code:"231282"},{name:"海伦市",code:"231283"}]},{name:"大兴安岭地区",code:"232700",sub:[{name:"呼玛县",code:"232721"},{name:"塔河县",code:"232722"},{name:"漠河县",code:"232723"}]}]},{name:"上海",code:"310000",sub:[{name:"上海市",code:"310000",sub:[{name:"黄浦区",code:"310101"},{name:"徐汇区",code:"310104"},{name:"长宁区",code:"310105"},{name:"静安区",code:"310106"},{name:"普陀区",code:"310107"},{name:"闸北区",code:"310108"},{name:"虹口区",code:"310109"},{name:"杨浦区",code:"310110"},{name:"闵行区",code:"310112"},{name:"宝山区",code:"310113"},{name:"嘉定区",code:"310114"},{name:"浦东新区",code:"310115"},{name:"金山区",code:"310116"},{name:"松江区",code:"310117"},{name:"青浦区",code:"310118"},{name:"奉贤区",code:"310120"},{name:"崇明县",code:"310230"}]}]},{name:"江苏省",code:"320000",sub:[{name:"南京市",code:"320100",sub:[{name:"市辖区",code:"320101"},{name:"玄武区",code:"320102"},{name:"秦淮区",code:"320104"},{name:"建邺区",code:"320105"},{name:"鼓楼区",code:"320106"},{name:"浦口区",code:"320111"},{name:"栖霞区",code:"320113"},{name:"雨花台区",code:"320114"},{name:"江宁区",code:"320115"},{name:"六合区",code:"320116"},{name:"溧水区",code:"320117"},{name:"高淳区",code:"320118"}]},{name:"无锡市",code:"320200",sub:[{name:"市辖区",code:"320201"},{name:"崇安区",code:"320202"},{name:"南长区",code:"320203"},{name:"北塘区",code:"320204"},{name:"锡山区",code:"320205"},{name:"惠山区",code:"320206"},{name:"滨湖区",code:"320211"},{name:"江阴市",code:"320281"},{name:"宜兴市",code:"320282"}]},{name:"徐州市",code:"320300",sub:[{name:"市辖区",code:"320301"},{name:"鼓楼区",code:"320302"},{name:"云龙区",code:"320303"},{name:"贾汪区",code:"320305"},{name:"泉山区",code:"320311"},{name:"铜山区",code:"320312"},{name:"丰县",code:"320321"},{name:"沛县",code:"320322"},{name:"睢宁县",code:"320324"},{name:"新沂市",code:"320381"},{name:"邳州市",code:"320382"}]},{name:"常州市",code:"320400",sub:[{name:"市辖区",code:"320401"},{name:"天宁区",code:"320402"},{name:"钟楼区",code:"320404"},{name:"戚墅堰区",code:"320405"},{name:"新北区",code:"320411"},{name:"武进区",code:"320412"},{name:"溧阳市",code:"320481"},{name:"金坛市",code:"320482"}]},{name:"苏州市",code:"320500",sub:[{name:"市辖区",code:"320501"},{name:"虎丘区",code:"320505"},{name:"吴中区",code:"320506"},{name:"相城区",code:"320507"},{name:"姑苏区",code:"320508"},{name:"吴江区",code:"320509"},{name:"常熟市",code:"320581"},{name:"张家港市",code:"320582"},{name:"昆山市",code:"320583"},{name:"太仓市",code:"320585"}]},{name:"南通市",code:"320600",sub:[{name:"市辖区",code:"320601"},{name:"崇川区",code:"320602"},{name:"港闸区",code:"320611"},{name:"通州区",code:"320612"},{name:"海安县",code:"320621"},{name:"如东县",code:"320623"},{name:"启东市",code:"320681"},{name:"如皋市",code:"320682"},{name:"海门市",code:"320684"}]},{name:"连云港市",code:"320700",sub:[{name:"市辖区",code:"320701"},{name:"连云区",code:"320703"},{name:"海州区",code:"320706"},{name:"赣榆区",code:"320707"},{name:"东海县",code:"320722"},{name:"灌云县",code:"320723"},{name:"灌南县",code:"320724"}]},{name:"淮安市",code:"320800",sub:[{name:"市辖区",code:"320801"},{name:"清河区",code:"320802"},{name:"淮安区",code:"320803"},{name:"淮阴区",code:"320804"},{name:"清浦区",code:"320811"},{name:"涟水县",code:"320826"},{name:"洪泽县",code:"320829"},{name:"盱眙县",code:"320830"},{name:"金湖县",code:"320831"}]},{name:"盐城市",code:"320900",sub:[{name:"市辖区",code:"320901"},{name:"亭湖区",code:"320902"},{name:"盐都区",code:"320903"},{name:"响水县",code:"320921"},{name:"滨海县",code:"320922"},{name:"阜宁县",code:"320923"},{name:"射阳县",code:"320924"},{name:"建湖县",code:"320925"},{name:"东台市",code:"320981"},{name:"大丰市",code:"320982"}]},{name:"扬州市",code:"321000",sub:[{name:"市辖区",code:"321001"},{name:"广陵区",code:"321002"},{name:"邗江区",code:"321003"},{name:"江都区",code:"321012"},{name:"宝应县",code:"321023"},{name:"仪征市",code:"321081"},{name:"高邮市",code:"321084"}]},{name:"镇江市",code:"321100",sub:[{name:"市辖区",code:"321101"},{name:"京口区",code:"321102"},{name:"润州区",code:"321111"},{name:"丹徒区",code:"321112"},{name:"丹阳市",code:"321181"},{name:"扬中市",code:"321182"},{name:"句容市",code:"321183"}]},{name:"泰州市",code:"321200",sub:[{name:"市辖区",code:"321201"},{name:"海陵区",code:"321202"},{name:"高港区",code:"321203"},{name:"姜堰区",code:"321204"},{name:"兴化市",code:"321281"},{name:"靖江市",code:"321282"},{name:"泰兴市",code:"321283"}]},{name:"宿迁市",code:"321300",sub:[{name:"市辖区",code:"321301"},{name:"宿城区",code:"321302"},{name:"宿豫区",code:"321311"},{name:"沭阳县",code:"321322"},{name:"泗阳县",code:"321323"},{name:"泗洪县",code:"321324"}]}]},{name:"浙江省",code:"330000",sub:[{name:"杭州市",code:"330100",sub:[{name:"市辖区",code:"330101"},{name:"上城区",code:"330102"},{name:"下城区",code:"330103"},{name:"江干区",code:"330104"},{name:"拱墅区",code:"330105"},{name:"西湖区",code:"330106"},{name:"滨江区",code:"330108"},{name:"萧山区",code:"330109"},{name:"余杭区",code:"330110"},{name:"富阳区",code:"330111"},{name:"桐庐县",code:"330122"},{name:"淳安县",code:"330127"},{name:"建德市",code:"330182"},{name:"临安市",code:"330185"}]},{name:"宁波市",code:"330200",sub:[{name:"市辖区",code:"330201"},{name:"海曙区",code:"330203"},{name:"江东区",code:"330204"},{name:"江北区",code:"330205"},{name:"北仑区",code:"330206"},{name:"镇海区",code:"330211"},{name:"鄞州区",code:"330212"},{name:"象山县",code:"330225"},{name:"宁海县",code:"330226"},{name:"余姚市",code:"330281"},{name:"慈溪市",code:"330282"},{name:"奉化市",code:"330283"}]},{name:"温州市",code:"330300",sub:[{name:"市辖区",code:"330301"},{name:"鹿城区",code:"330302"},{name:"龙湾区",code:"330303"},{name:"瓯海区",code:"330304"},{name:"洞头县",code:"330322"},{name:"永嘉县",code:"330324"},{name:"平阳县",code:"330326"},{name:"苍南县",code:"330327"},{name:"文成县",code:"330328"},{name:"泰顺县",code:"330329"},{name:"瑞安市",code:"330381"},{name:"乐清市",code:"330382"}]},{name:"嘉兴市",code:"330400",sub:[{name:"市辖区",code:"330401"},{name:"南湖区",code:"330402"},{name:"秀洲区",code:"330411"},{name:"嘉善县",code:"330421"},{name:"海盐县",code:"330424"},{name:"海宁市",code:"330481"},{name:"平湖市",code:"330482"},{name:"桐乡市",code:"330483"}]},{name:"湖州市",code:"330500",sub:[{name:"市辖区",code:"330501"},{name:"吴兴区",code:"330502"},{name:"南浔区",code:"330503"},{name:"德清县",code:"330521"},{name:"长兴县",code:"330522"},{name:"安吉县",code:"330523"}]},{name:"绍兴市",code:"330600",sub:[{name:"市辖区",code:"330601"},{name:"越城区",code:"330602"},{name:"柯桥区",code:"330603"},{name:"上虞区",code:"330604"},{name:"新昌县",code:"330624"},{name:"诸暨市",code:"330681"},{name:"嵊州市",code:"330683"}]},{name:"金华市",code:"330700",sub:[{name:"市辖区",code:"330701"},{name:"婺城区",code:"330702"},{name:"金东区",code:"330703"},{name:"武义县",code:"330723"},{name:"浦江县",code:"330726"},{name:"磐安县",code:"330727"},{name:"兰溪市",code:"330781"},{name:"义乌市",code:"330782"},{name:"东阳市",code:"330783"},{name:"永康市",code:"330784"}]},{name:"衢州市",code:"330800",sub:[{name:"市辖区",code:"330801"},{name:"柯城区",code:"330802"},{name:"衢江区",code:"330803"},{name:"常山县",code:"330822"},{name:"开化县",code:"330824"},{name:"龙游县",code:"330825"},{name:"江山市",code:"330881"}]},{name:"舟山市",code:"330900",sub:[{name:"市辖区",code:"330901"},{name:"定海区",code:"330902"},{name:"普陀区",code:"330903"},{name:"岱山县",code:"330921"},{name:"嵊泗县",code:"330922"}]},{name:"台州市",code:"331000",sub:[{name:"市辖区",code:"331001"},{name:"椒江区",code:"331002"},{name:"黄岩区",code:"331003"},{name:"路桥区",code:"331004"},{name:"玉环县",code:"331021"},{name:"三门县",code:"331022"},{name:"天台县",code:"331023"},{name:"仙居县",code:"331024"},{name:"温岭市",code:"331081"},{name:"临海市",code:"331082"}]},{name:"丽水市",code:"331100",sub:[{name:"市辖区",code:"331101"},{name:"莲都区",code:"331102"},{name:"青田县",code:"331121"},{name:"缙云县",code:"331122"},{name:"遂昌县",code:"331123"},{name:"松阳县",code:"331124"},{name:"云和县",code:"331125"},{name:"庆元县",code:"331126"},{name:"景宁畲族自治县",code:"331127"},{name:"龙泉市",code:"331181"}]}]},{name:"安徽省",code:"340000",sub:[{name:"合肥市",code:"340100",sub:[{name:"市辖区",code:"340101"},{name:"瑶海区",code:"340102"},{name:"庐阳区",code:"340103"},{name:"蜀山区",code:"340104"},{name:"包河区",code:"340111"},{name:"长丰县",code:"340121"},{name:"肥东县",code:"340122"},{name:"肥西县",code:"340123"},{name:"庐江县",code:"340124"},{name:"巢湖市",code:"340181"}]},{name:"芜湖市",code:"340200",sub:[{name:"市辖区",code:"340201"},{name:"镜湖区",code:"340202"},{name:"弋江区",code:"340203"},{name:"鸠江区",code:"340207"},{name:"三山区",code:"340208"},{name:"芜湖县",code:"340221"},{name:"繁昌县",code:"340222"},{name:"南陵县",code:"340223"},{name:"无为县",code:"340225"}]},{name:"蚌埠市",code:"340300",sub:[{name:"市辖区",code:"340301"},{name:"龙子湖区",code:"340302"},{name:"蚌山区",code:"340303"},{name:"禹会区",code:"340304"},{name:"淮上区",code:"340311"},{name:"怀远县",code:"340321"},{name:"五河县",code:"340322"},{name:"固镇县",code:"340323"}]},{name:"淮南市",code:"340400",sub:[{name:"市辖区",code:"340401"},{name:"大通区",code:"340402"},{
+name:"田家庵区",code:"340403"},{name:"谢家集区",code:"340404"},{name:"八公山区",code:"340405"},{name:"潘集区",code:"340406"},{name:"凤台县",code:"340421"}]},{name:"马鞍山市",code:"340500",sub:[{name:"市辖区",code:"340501"},{name:"花山区",code:"340503"},{name:"雨山区",code:"340504"},{name:"博望区",code:"340506"},{name:"当涂县",code:"340521"},{name:"含山县",code:"340522"},{name:"和县",code:"340523"}]},{name:"淮北市",code:"340600",sub:[{name:"市辖区",code:"340601"},{name:"杜集区",code:"340602"},{name:"相山区",code:"340603"},{name:"烈山区",code:"340604"},{name:"濉溪县",code:"340621"}]},{name:"铜陵市",code:"340700",sub:[{name:"市辖区",code:"340701"},{name:"铜官山区",code:"340702"},{name:"狮子山区",code:"340703"},{name:"郊区",code:"340711"},{name:"铜陵县",code:"340721"}]},{name:"安庆市",code:"340800",sub:[{name:"市辖区",code:"340801"},{name:"迎江区",code:"340802"},{name:"大观区",code:"340803"},{name:"宜秀区",code:"340811"},{name:"怀宁县",code:"340822"},{name:"枞阳县",code:"340823"},{name:"潜山县",code:"340824"},{name:"太湖县",code:"340825"},{name:"宿松县",code:"340826"},{name:"望江县",code:"340827"},{name:"岳西县",code:"340828"},{name:"桐城市",code:"340881"}]},{name:"黄山市",code:"341000",sub:[{name:"市辖区",code:"341001"},{name:"屯溪区",code:"341002"},{name:"黄山区",code:"341003"},{name:"徽州区",code:"341004"},{name:"歙县",code:"341021"},{name:"休宁县",code:"341022"},{name:"黟县",code:"341023"},{name:"祁门县",code:"341024"}]},{name:"滁州市",code:"341100",sub:[{name:"市辖区",code:"341101"},{name:"琅琊区",code:"341102"},{name:"南谯区",code:"341103"},{name:"来安县",code:"341122"},{name:"全椒县",code:"341124"},{name:"定远县",code:"341125"},{name:"凤阳县",code:"341126"},{name:"天长市",code:"341181"},{name:"明光市",code:"341182"}]},{name:"阜阳市",code:"341200",sub:[{name:"市辖区",code:"341201"},{name:"颍州区",code:"341202"},{name:"颍东区",code:"341203"},{name:"颍泉区",code:"341204"},{name:"临泉县",code:"341221"},{name:"太和县",code:"341222"},{name:"阜南县",code:"341225"},{name:"颍上县",code:"341226"},{name:"界首市",code:"341282"}]},{name:"宿州市",code:"341300",sub:[{name:"市辖区",code:"341301"},{name:"埇桥区",code:"341302"},{name:"砀山县",code:"341321"},{name:"萧县",code:"341322"},{name:"灵璧县",code:"341323"},{name:"泗县",code:"341324"}]},{name:"六安市",code:"341500",sub:[{name:"市辖区",code:"341501"},{name:"金安区",code:"341502"},{name:"裕安区",code:"341503"},{name:"寿县",code:"341521"},{name:"霍邱县",code:"341522"},{name:"舒城县",code:"341523"},{name:"金寨县",code:"341524"},{name:"霍山县",code:"341525"}]},{name:"亳州市",code:"341600",sub:[{name:"市辖区",code:"341601"},{name:"谯城区",code:"341602"},{name:"涡阳县",code:"341621"},{name:"蒙城县",code:"341622"},{name:"利辛县",code:"341623"}]},{name:"池州市",code:"341700",sub:[{name:"市辖区",code:"341701"},{name:"贵池区",code:"341702"},{name:"东至县",code:"341721"},{name:"石台县",code:"341722"},{name:"青阳县",code:"341723"}]},{name:"宣城市",code:"341800",sub:[{name:"市辖区",code:"341801"},{name:"宣州区",code:"341802"},{name:"郎溪县",code:"341821"},{name:"广德县",code:"341822"},{name:"泾县",code:"341823"},{name:"绩溪县",code:"341824"},{name:"旌德县",code:"341825"},{name:"宁国市",code:"341881"}]}]},{name:"福建省",code:"350000",sub:[{name:"福州市",code:"350100",sub:[{name:"市辖区",code:"350101"},{name:"鼓楼区",code:"350102"},{name:"台江区",code:"350103"},{name:"仓山区",code:"350104"},{name:"马尾区",code:"350105"},{name:"晋安区",code:"350111"},{name:"闽侯县",code:"350121"},{name:"连江县",code:"350122"},{name:"罗源县",code:"350123"},{name:"闽清县",code:"350124"},{name:"永泰县",code:"350125"},{name:"平潭县",code:"350128"},{name:"福清市",code:"350181"},{name:"长乐市",code:"350182"}]},{name:"厦门市",code:"350200",sub:[{name:"市辖区",code:"350201"},{name:"思明区",code:"350203"},{name:"海沧区",code:"350205"},{name:"湖里区",code:"350206"},{name:"集美区",code:"350211"},{name:"同安区",code:"350212"},{name:"翔安区",code:"350213"}]},{name:"莆田市",code:"350300",sub:[{name:"市辖区",code:"350301"},{name:"城厢区",code:"350302"},{name:"涵江区",code:"350303"},{name:"荔城区",code:"350304"},{name:"秀屿区",code:"350305"},{name:"仙游县",code:"350322"}]},{name:"三明市",code:"350400",sub:[{name:"市辖区",code:"350401"},{name:"梅列区",code:"350402"},{name:"三元区",code:"350403"},{name:"明溪县",code:"350421"},{name:"清流县",code:"350423"},{name:"宁化县",code:"350424"},{name:"大田县",code:"350425"},{name:"尤溪县",code:"350426"},{name:"沙县",code:"350427"},{name:"将乐县",code:"350428"},{name:"泰宁县",code:"350429"},{name:"建宁县",code:"350430"},{name:"永安市",code:"350481"}]},{name:"泉州市",code:"350500",sub:[{name:"市辖区",code:"350501"},{name:"鲤城区",code:"350502"},{name:"丰泽区",code:"350503"},{name:"洛江区",code:"350504"},{name:"泉港区",code:"350505"},{name:"惠安县",code:"350521"},{name:"安溪县",code:"350524"},{name:"永春县",code:"350525"},{name:"德化县",code:"350526"},{name:"金门县",code:"350527"},{name:"石狮市",code:"350581"},{name:"晋江市",code:"350582"},{name:"南安市",code:"350583"}]},{name:"漳州市",code:"350600",sub:[{name:"市辖区",code:"350601"},{name:"芗城区",code:"350602"},{name:"龙文区",code:"350603"},{name:"云霄县",code:"350622"},{name:"漳浦县",code:"350623"},{name:"诏安县",code:"350624"},{name:"长泰县",code:"350625"},{name:"东山县",code:"350626"},{name:"南靖县",code:"350627"},{name:"平和县",code:"350628"},{name:"华安县",code:"350629"},{name:"龙海市",code:"350681"}]},{name:"南平市",code:"350700",sub:[{name:"市辖区",code:"350701"},{name:"延平区",code:"350702"},{name:"建阳区",code:"350703"},{name:"顺昌县",code:"350721"},{name:"浦城县",code:"350722"},{name:"光泽县",code:"350723"},{name:"松溪县",code:"350724"},{name:"政和县",code:"350725"},{name:"邵武市",code:"350781"},{name:"武夷山市",code:"350782"},{name:"建瓯市",code:"350783"}]},{name:"龙岩市",code:"350800",sub:[{name:"市辖区",code:"350801"},{name:"新罗区",code:"350802"},{name:"永定区",code:"350803"},{name:"长汀县",code:"350821"},{name:"上杭县",code:"350823"},{name:"武平县",code:"350824"},{name:"连城县",code:"350825"},{name:"漳平市",code:"350881"}]},{name:"宁德市",code:"350900",sub:[{name:"市辖区",code:"350901"},{name:"蕉城区",code:"350902"},{name:"霞浦县",code:"350921"},{name:"古田县",code:"350922"},{name:"屏南县",code:"350923"},{name:"寿宁县",code:"350924"},{name:"周宁县",code:"350925"},{name:"柘荣县",code:"350926"},{name:"福安市",code:"350981"},{name:"福鼎市",code:"350982"}]}]},{name:"江西省",code:"360000",sub:[{name:"南昌市",code:"360100",sub:[{name:"市辖区",code:"360101"},{name:"东湖区",code:"360102"},{name:"西湖区",code:"360103"},{name:"青云谱区",code:"360104"},{name:"湾里区",code:"360105"},{name:"青山湖区",code:"360111"},{name:"南昌县",code:"360121"},{name:"新建县",code:"360122"},{name:"安义县",code:"360123"},{name:"进贤县",code:"360124"}]},{name:"景德镇市",code:"360200",sub:[{name:"市辖区",code:"360201"},{name:"昌江区",code:"360202"},{name:"珠山区",code:"360203"},{name:"浮梁县",code:"360222"},{name:"乐平市",code:"360281"}]},{name:"萍乡市",code:"360300",sub:[{name:"市辖区",code:"360301"},{name:"安源区",code:"360302"},{name:"湘东区",code:"360313"},{name:"莲花县",code:"360321"},{name:"上栗县",code:"360322"},{name:"芦溪县",code:"360323"}]},{name:"九江市",code:"360400",sub:[{name:"市辖区",code:"360401"},{name:"庐山区",code:"360402"},{name:"浔阳区",code:"360403"},{name:"九江县",code:"360421"},{name:"武宁县",code:"360423"},{name:"修水县",code:"360424"},{name:"永修县",code:"360425"},{name:"德安县",code:"360426"},{name:"星子县",code:"360427"},{name:"都昌县",code:"360428"},{name:"湖口县",code:"360429"},{name:"彭泽县",code:"360430"},{name:"瑞昌市",code:"360481"},{name:"共青城市",code:"360482"}]},{name:"新余市",code:"360500",sub:[{name:"市辖区",code:"360501"},{name:"渝水区",code:"360502"},{name:"分宜县",code:"360521"}]},{name:"鹰潭市",code:"360600",sub:[{name:"市辖区",code:"360601"},{name:"月湖区",code:"360602"},{name:"余江县",code:"360622"},{name:"贵溪市",code:"360681"}]},{name:"赣州市",code:"360700",sub:[{name:"市辖区",code:"360701"},{name:"章贡区",code:"360702"},{name:"南康区",code:"360703"},{name:"赣县",code:"360721"},{name:"信丰县",code:"360722"},{name:"大余县",code:"360723"},{name:"上犹县",code:"360724"},{name:"崇义县",code:"360725"},{name:"安远县",code:"360726"},{name:"龙南县",code:"360727"},{name:"定南县",code:"360728"},{name:"全南县",code:"360729"},{name:"宁都县",code:"360730"},{name:"于都县",code:"360731"},{name:"兴国县",code:"360732"},{name:"会昌县",code:"360733"},{name:"寻乌县",code:"360734"},{name:"石城县",code:"360735"},{name:"瑞金市",code:"360781"}]},{name:"吉安市",code:"360800",sub:[{name:"市辖区",code:"360801"},{name:"吉州区",code:"360802"},{name:"青原区",code:"360803"},{name:"吉安县",code:"360821"},{name:"吉水县",code:"360822"},{name:"峡江县",code:"360823"},{name:"新干县",code:"360824"},{name:"永丰县",code:"360825"},{name:"泰和县",code:"360826"},{name:"遂川县",code:"360827"},{name:"万安县",code:"360828"},{name:"安福县",code:"360829"},{name:"永新县",code:"360830"},{name:"井冈山市",code:"360881"}]},{name:"宜春市",code:"360900",sub:[{name:"市辖区",code:"360901"},{name:"袁州区",code:"360902"},{name:"奉新县",code:"360921"},{name:"万载县",code:"360922"},{name:"上高县",code:"360923"},{name:"宜丰县",code:"360924"},{name:"靖安县",code:"360925"},{name:"铜鼓县",code:"360926"},{name:"丰城市",code:"360981"},{name:"樟树市",code:"360982"},{name:"高安市",code:"360983"}]},{name:"抚州市",code:"361000",sub:[{name:"市辖区",code:"361001"},{name:"临川区",code:"361002"},{name:"南城县",code:"361021"},{name:"黎川县",code:"361022"},{name:"南丰县",code:"361023"},{name:"崇仁县",code:"361024"},{name:"乐安县",code:"361025"},{name:"宜黄县",code:"361026"},{name:"金溪县",code:"361027"},{name:"资溪县",code:"361028"},{name:"东乡县",code:"361029"},{name:"广昌县",code:"361030"}]},{name:"上饶市",code:"361100",sub:[{name:"市辖区",code:"361101"},{name:"信州区",code:"361102"},{name:"上饶县",code:"361121"},{name:"广丰县",code:"361122"},{name:"玉山县",code:"361123"},{name:"铅山县",code:"361124"},{name:"横峰县",code:"361125"},{name:"弋阳县",code:"361126"},{name:"余干县",code:"361127"},{name:"鄱阳县",code:"361128"},{name:"万年县",code:"361129"},{name:"婺源县",code:"361130"},{name:"德兴市",code:"361181"}]}]},{name:"山东省",code:"370000",sub:[{name:"济南市",code:"370100",sub:[{name:"市辖区",code:"370101"},{name:"历下区",code:"370102"},{name:"市中区",code:"370103"},{name:"槐荫区",code:"370104"},{name:"天桥区",code:"370105"},{name:"历城区",code:"370112"},{name:"长清区",code:"370113"},{name:"平阴县",code:"370124"},{name:"济阳县",code:"370125"},{name:"商河县",code:"370126"},{name:"章丘市",code:"370181"}]},{name:"青岛市",code:"370200",sub:[{name:"市辖区",code:"370201"},{name:"市南区",code:"370202"},{name:"市北区",code:"370203"},{name:"黄岛区",code:"370211"},{name:"崂山区",code:"370212"},{name:"李沧区",code:"370213"},{name:"城阳区",code:"370214"},{name:"胶州市",code:"370281"},{name:"即墨市",code:"370282"},{name:"平度市",code:"370283"},{name:"莱西市",code:"370285"}]},{name:"淄博市",code:"370300",sub:[{name:"市辖区",code:"370301"},{name:"淄川区",code:"370302"},{name:"张店区",code:"370303"},{name:"博山区",code:"370304"},{name:"临淄区",code:"370305"},{name:"周村区",code:"370306"},{name:"桓台县",code:"370321"},{name:"高青县",code:"370322"},{name:"沂源县",code:"370323"}]},{name:"枣庄市",code:"370400",sub:[{name:"市辖区",code:"370401"},{name:"市中区",code:"370402"},{name:"薛城区",code:"370403"},{name:"峄城区",code:"370404"},{name:"台儿庄区",code:"370405"},{name:"山亭区",code:"370406"},{name:"滕州市",code:"370481"}]},{name:"东营市",code:"370500",sub:[{name:"市辖区",code:"370501"},{name:"东营区",code:"370502"},{name:"河口区",code:"370503"},{name:"垦利县",code:"370521"},{name:"利津县",code:"370522"},{name:"广饶县",code:"370523"}]},{name:"烟台市",code:"370600",sub:[{name:"市辖区",code:"370601"},{name:"芝罘区",code:"370602"},{name:"福山区",code:"370611"},{name:"牟平区",code:"370612"},{name:"莱山区",code:"370613"},{name:"长岛县",code:"370634"},{name:"龙口市",code:"370681"},{name:"莱阳市",code:"370682"},{name:"莱州市",code:"370683"},{name:"蓬莱市",code:"370684"},{name:"招远市",code:"370685"},{name:"栖霞市",code:"370686"},{name:"海阳市",code:"370687"}]},{name:"潍坊市",code:"370700",sub:[{name:"市辖区",code:"370701"},{name:"潍城区",code:"370702"},{name:"寒亭区",code:"370703"},{name:"坊子区",code:"370704"},{name:"奎文区",code:"370705"},{name:"临朐县",code:"370724"},{name:"昌乐县",code:"370725"},{name:"青州市",code:"370781"},{name:"诸城市",code:"370782"},{name:"寿光市",code:"370783"},{name:"安丘市",code:"370784"},{name:"高密市",code:"370785"},{name:"昌邑市",code:"370786"}]},{name:"济宁市",code:"370800",sub:[{name:"市辖区",code:"370801"},{name:"任城区",code:"370811"},{name:"兖州区",code:"370812"},{name:"微山县",code:"370826"},{name:"鱼台县",code:"370827"},{name:"金乡县",code:"370828"},{name:"嘉祥县",code:"370829"},{name:"汶上县",code:"370830"},{name:"泗水县",code:"370831"},{name:"梁山县",code:"370832"},{name:"曲阜市",code:"370881"},{name:"邹城市",code:"370883"}]},{name:"泰安市",code:"370900",sub:[{name:"市辖区",code:"370901"},{name:"泰山区",code:"370902"},{name:"岱岳区",code:"370911"},{name:"宁阳县",code:"370921"},{name:"东平县",code:"370923"},{name:"新泰市",code:"370982"},{name:"肥城市",code:"370983"}]},{name:"威海市",code:"371000",sub:[{name:"市辖区",code:"371001"},{name:"环翠区",code:"371002"},{name:"文登市",code:"371081"},{name:"荣成市",code:"371082"},{name:"乳山市",code:"371083"}]},{name:"日照市",code:"371100",sub:[{name:"市辖区",code:"371101"},{name:"东港区",code:"371102"},{name:"岚山区",code:"371103"},{name:"五莲县",code:"371121"},{name:"莒县",code:"371122"}]},{name:"莱芜市",code:"371200",sub:[{name:"市辖区",code:"371201"},{name:"莱城区",code:"371202"},{name:"钢城区",code:"371203"}]},{name:"临沂市",code:"371300",sub:[{name:"市辖区",code:"371301"},{name:"兰山区",code:"371302"},{name:"罗庄区",code:"371311"},{name:"河东区",code:"371312"},{name:"沂南县",code:"371321"},{name:"郯城县",code:"371322"},{name:"沂水县",code:"371323"},{name:"兰陵县",code:"371324"},{name:"费县",code:"371325"},{name:"平邑县",code:"371326"},{name:"莒南县",code:"371327"},{name:"蒙阴县",code:"371328"},{name:"临沭县",code:"371329"}]},{name:"德州市",code:"371400",sub:[{name:"市辖区",code:"371401"},{name:"德城区",code:"371402"},{name:"陵城区",code:"371403"},{name:"宁津县",code:"371422"},{name:"庆云县",code:"371423"},{name:"临邑县",code:"371424"},{name:"齐河县",code:"371425"},{name:"平原县",code:"371426"},{name:"夏津县",code:"371427"},{name:"武城县",code:"371428"},{name:"乐陵市",code:"371481"},{name:"禹城市",code:"371482"}]},{name:"聊城市",code:"371500",sub:[{name:"市辖区",code:"371501"},{name:"东昌府区",code:"371502"},{name:"阳谷县",code:"371521"},{name:"莘县",code:"371522"},{name:"茌平县",code:"371523"},{name:"东阿县",code:"371524"},{name:"冠县",code:"371525"},{name:"高唐县",code:"371526"},{name:"临清市",code:"371581"}]},{name:"滨州市",code:"371600",sub:[{name:"市辖区",code:"371601"},{name:"滨城区",code:"371602"},{name:"沾化区",code:"371603"},{name:"惠民县",code:"371621"},{name:"阳信县",code:"371622"},{name:"无棣县",code:"371623"},{name:"博兴县",code:"371625"},{name:"邹平县",code:"371626"}]},{name:"菏泽市",code:"371700",sub:[{name:"市辖区",code:"371701"},{name:"牡丹区",code:"371702"},{name:"曹县",code:"371721"},{name:"单县",code:"371722"},{name:"成武县",code:"371723"},{name:"巨野县",code:"371724"},{name:"郓城县",code:"371725"},{name:"鄄城县",code:"371726"},{name:"定陶县",code:"371727"},{name:"东明县",code:"371728"}]}]},{name:"河南省",code:"410000",sub:[{name:"郑州市",code:"410100",sub:[{name:"市辖区",code:"410101"},{name:"中原区",code:"410102"},{name:"二七区",code:"410103"},{name:"管城回族区",code:"410104"},{name:"金水区",code:"410105"},{name:"上街区",code:"410106"},{name:"惠济区",code:"410108"},{name:"中牟县",code:"410122"},{name:"巩义市",code:"410181"},{name:"荥阳市",code:"410182"},{name:"新密市",code:"410183"},{name:"新郑市",code:"410184"},{name:"登封市",code:"410185"}]},{name:"开封市",code:"410200",sub:[{name:"市辖区",code:"410201"},{name:"龙亭区",code:"410202"},{name:"顺河回族区",code:"410203"},{name:"鼓楼区",code:"410204"},{name:"禹王台区",code:"410205"},{name:"祥符区",code:"410212"},{name:"杞县",code:"410221"},{name:"通许县",code:"410222"},{name:"尉氏县",code:"410223"},{name:"兰考县",code:"410225"}]},{name:"洛阳市",code:"410300",sub:[{name:"市辖区",code:"410301"},{name:"老城区",code:"410302"},{name:"西工区",code:"410303"},{name:"瀍河回族区",code:"410304"},{name:"涧西区",code:"410305"},{name:"吉利区",code:"410306"},{name:"洛龙区",code:"410311"},{name:"孟津县",code:"410322"},{name:"新安县",code:"410323"},{name:"栾川县",code:"410324"},{name:"嵩县",code:"410325"},{name:"汝阳县",code:"410326"},{name:"宜阳县",code:"410327"},{name:"洛宁县",code:"410328"},{name:"伊川县",code:"410329"},{name:"偃师市",code:"410381"}]},{name:"平顶山市",code:"410400",sub:[{name:"市辖区",code:"410401"},{name:"新华区",code:"410402"},{name:"卫东区",code:"410403"},{name:"石龙区",code:"410404"},{name:"湛河区",code:"410411"},{name:"宝丰县",code:"410421"},{name:"叶县",code:"410422"},{name:"鲁山县",code:"410423"},{name:"郏县",code:"410425"},{name:"舞钢市",code:"410481"},{name:"汝州市",code:"410482"}]},{name:"安阳市",code:"410500",sub:[{name:"市辖区",code:"410501"},{name:"文峰区",code:"410502"},{name:"北关区",code:"410503"},{name:"殷都区",code:"410505"},{name:"龙安区",code:"410506"},{name:"安阳县",code:"410522"},{name:"汤阴县",code:"410523"},{name:"滑县",code:"410526"},{name:"内黄县",code:"410527"},{name:"林州市",code:"410581"}]},{name:"鹤壁市",code:"410600",sub:[{name:"市辖区",code:"410601"},{name:"鹤山区",code:"410602"},{name:"山城区",code:"410603"},{name:"淇滨区",code:"410611"},{name:"浚县",code:"410621"},{name:"淇县",code:"410622"}]},{name:"新乡市",code:"410700",sub:[{name:"市辖区",code:"410701"},{name:"红旗区",code:"410702"},{name:"卫滨区",code:"410703"},{name:"凤泉区",code:"410704"},{name:"牧野区",code:"410711"},{name:"新乡县",code:"410721"},{name:"获嘉县",code:"410724"},{name:"原阳县",code:"410725"},{name:"延津县",code:"410726"},{name:"封丘县",code:"410727"},{name:"长垣县",code:"410728"},{name:"卫辉市",code:"410781"},{name:"辉县市",code:"410782"}]},{name:"焦作市",code:"410800",sub:[{name:"市辖区",code:"410801"},{name:"解放区",code:"410802"},{name:"中站区",code:"410803"},{name:"马村区",code:"410804"},{name:"山阳区",code:"410811"},{name:"修武县",code:"410821"},{name:"博爱县",code:"410822"},{name:"武陟县",code:"410823"},{name:"温县",code:"410825"},{name:"沁阳市",code:"410882"},{name:"孟州市",code:"410883"}]},{name:"濮阳市",code:"410900",sub:[{name:"市辖区",code:"410901"},{name:"华龙区",code:"410902"},{name:"清丰县",code:"410922"},{name:"南乐县",code:"410923"},{name:"范县",code:"410926"},{name:"台前县",code:"410927"},{name:"濮阳县",code:"410928"}]},{name:"许昌市",code:"411000",sub:[{name:"市辖区",code:"411001"},{name:"魏都区",code:"411002"},{name:"许昌县",code:"411023"},{name:"鄢陵县",code:"411024"},{name:"襄城县",code:"411025"},{name:"禹州市",code:"411081"},{name:"长葛市",code:"411082"}]},{name:"漯河市",code:"411100",sub:[{name:"市辖区",code:"411101"},{name:"源汇区",code:"411102"},{name:"郾城区",code:"411103"},{name:"召陵区",code:"411104"},{name:"舞阳县",code:"411121"},{name:"临颍县",code:"411122"}]},{name:"三门峡市",code:"411200",sub:[{name:"市辖区",code:"411201"},{name:"湖滨区",code:"411202"},{name:"渑池县",code:"411221"},{name:"陕县",code:"411222"},{name:"卢氏县",code:"411224"},{name:"义马市",code:"411281"},{name:"灵宝市",code:"411282"}]},{name:"南阳市",code:"411300",sub:[{name:"市辖区",code:"411301"},{name:"宛城区",code:"411302"},{name:"卧龙区",code:"411303"},{name:"南召县",code:"411321"},{name:"方城县",code:"411322"},{name:"西峡县",code:"411323"},{name:"镇平县",code:"411324"},{name:"内乡县",code:"411325"},{name:"淅川县",code:"411326"},{name:"社旗县",code:"411327"},{name:"唐河县",code:"411328"},{name:"新野县",code:"411329"},{name:"桐柏县",code:"411330"},{name:"邓州市",code:"411381"}]},{name:"商丘市",code:"411400",sub:[{name:"市辖区",code:"411401"},{name:"梁园区",code:"411402"},{name:"睢阳区",code:"411403"},{name:"民权县",code:"411421"},{name:"睢县",code:"411422"},{name:"宁陵县",code:"411423"},{name:"柘城县",code:"411424"},{name:"虞城县",code:"411425"},{name:"夏邑县",code:"411426"},{name:"永城市",code:"411481"}]},{name:"信阳市",code:"411500",sub:[{name:"市辖区",code:"411501"},{name:"浉河区",code:"411502"},{name:"平桥区",code:"411503"},{name:"罗山县",code:"411521"},{name:"光山县",code:"411522"},{name:"新县",code:"411523"},{name:"商城县",code:"411524"},{name:"固始县",code:"411525"},{name:"潢川县",code:"411526"},{name:"淮滨县",code:"411527"},{name:"息县",code:"411528"}]},{name:"周口市",code:"411600",sub:[{name:"市辖区",code:"411601"},{name:"川汇区",code:"411602"},{name:"扶沟县",code:"411621"},{name:"西华县",code:"411622"},{name:"商水县",code:"411623"},{name:"沈丘县",code:"411624"},{name:"郸城县",code:"411625"},{name:"淮阳县",code:"411626"},{name:"太康县",code:"411627"},{name:"鹿邑县",code:"411628"},{name:"项城市",code:"411681"}]},{name:"驻马店市",code:"411700",sub:[{name:"市辖区",code:"411701"},{name:"驿城区",code:"411702"},{name:"西平县",code:"411721"},{name:"上蔡县",code:"411722"},{name:"平舆县",code:"411723"},{name:"正阳县",code:"411724"},{name:"确山县",code:"411725"},{name:"泌阳县",code:"411726"},{name:"汝南县",code:"411727"},{name:"遂平县",code:"411728"},{name:"新蔡县",code:"411729"}]},{name:"济源市",code:"419001"}]},{name:"湖北省",code:"420000",sub:[{name:"武汉市",code:"420100",sub:[{name:"市辖区",code:"420101"},{name:"江岸区",code:"420102"},{name:"江汉区",code:"420103"},{name:"硚口区",code:"420104"},{name:"汉阳区",code:"420105"},{name:"武昌区",code:"420106"},{name:"青山区",code:"420107"},{name:"洪山区",code:"420111"},{name:"东西湖区",code:"420112"},{name:"汉南区",code:"420113"},{name:"蔡甸区",code:"420114"},{name:"江夏区",code:"420115"},{name:"黄陂区",code:"420116"},{name:"新洲区",code:"420117"}]},{name:"黄石市",code:"420200",sub:[{name:"市辖区",code:"420201"},{name:"黄石港区",code:"420202"},{name:"西塞山区",code:"420203"},{name:"下陆区",code:"420204"},{name:"铁山区",code:"420205"},{name:"阳新县",code:"420222"},{name:"大冶市",code:"420281"}]},{name:"十堰市",code:"420300",sub:[{name:"市辖区",code:"420301"},{name:"茅箭区",code:"420302"},{name:"张湾区",code:"420303"},{name:"郧阳区",code:"420304"},{name:"郧西县",code:"420322"},{name:"竹山县",code:"420323"},{name:"竹溪县",code:"420324"},{name:"房县",code:"420325"},{name:"丹江口市",code:"420381"}]},{name:"宜昌市",code:"420500",sub:[{name:"市辖区",code:"420501"},{name:"西陵区",code:"420502"},{name:"伍家岗区",code:"420503"},{name:"点军区",code:"420504"},{name:"猇亭区",code:"420505"},{name:"夷陵区",code:"420506"},{name:"远安县",code:"420525"},{name:"兴山县",code:"420526"},{name:"秭归县",code:"420527"},{name:"长阳土家族自治县",code:"420528"},{name:"五峰土家族自治县",code:"420529"},{name:"宜都市",code:"420581"},{name:"当阳市",code:"420582"},{name:"枝江市",code:"420583"}]},{name:"襄阳市",code:"420600",sub:[{name:"市辖区",code:"420601"},{name:"襄城区",code:"420602"},{name:"樊城区",code:"420606"},{name:"襄州区",code:"420607"},{name:"南漳县",code:"420624"},{name:"谷城县",code:"420625"},{name:"保康县",code:"420626"},{name:"老河口市",code:"420682"},{name:"枣阳市",code:"420683"},{name:"宜城市",code:"420684"}]},{name:"鄂州市",code:"420700",sub:[{name:"市辖区",code:"420701"},{name:"梁子湖区",code:"420702"},{name:"华容区",code:"420703"},{name:"鄂城区",code:"420704"}]},{name:"荆门市",code:"420800",sub:[{name:"市辖区",code:"420801"},{name:"东宝区",code:"420802"},{name:"掇刀区",code:"420804"},{name:"京山县",code:"420821"},{name:"沙洋县",code:"420822"},{name:"钟祥市",code:"420881"}]},{name:"孝感市",code:"420900",sub:[{name:"市辖区",code:"420901"},{name:"孝南区",code:"420902"},{name:"孝昌县",code:"420921"},{name:"大悟县",code:"420922"},{name:"云梦县",code:"420923"},{name:"应城市",code:"420981"},{name:"安陆市",code:"420982"},{name:"汉川市",code:"420984"}]},{name:"荆州市",code:"421000",sub:[{name:"市辖区",code:"421001"},{name:"沙市区",code:"421002"},{name:"荆州区",code:"421003"},{name:"公安县",code:"421022"},{name:"监利县",code:"421023"},{name:"江陵县",code:"421024"},{name:"石首市",code:"421081"},{name:"洪湖市",code:"421083"},{name:"松滋市",code:"421087"}]},{name:"黄冈市",code:"421100",sub:[{name:"市辖区",code:"421101"},{name:"黄州区",code:"421102"},{name:"团风县",code:"421121"},{name:"红安县",code:"421122"},{name:"罗田县",code:"421123"},{name:"英山县",code:"421124"},{name:"浠水县",code:"421125"},{name:"蕲春县",code:"421126"},{name:"黄梅县",code:"421127"},{name:"麻城市",code:"421181"},{name:"武穴市",code:"421182"}]},{name:"咸宁市",code:"421200",sub:[{name:"市辖区",code:"421201"},{name:"咸安区",code:"421202"},{name:"嘉鱼县",code:"421221"},{name:"通城县",code:"421222"},{name:"崇阳县",code:"421223"},{name:"通山县",code:"421224"},{name:"赤壁市",code:"421281"}]},{name:"随州市",code:"421300",sub:[{name:"市辖区",code:"421301"},{name:"曾都区",code:"421303"},{name:"随县",code:"421321"},{name:"广水市",code:"421381"}]},{name:"恩施土家族苗族自治州",code:"422800",sub:[{name:"恩施市",code:"422801"},{name:"利川市",code:"422802"},{name:"建始县",code:"422822"},{name:"巴东县",code:"422823"},{name:"宣恩县",code:"422825"},{name:"咸丰县",code:"422826"},{name:"来凤县",code:"422827"},{name:"鹤峰县",code:"422828"}]},{name:"仙桃市",code:"429004"},{name:"潜江市",code:"429005"},{name:"天门市",code:"429006"},{name:"神农架林区",code:"429021"}]},{name:"湖南省",code:"430000",sub:[{name:"长沙市",code:"430100",sub:[{name:"市辖区",code:"430101"},{name:"芙蓉区",code:"430102"},{name:"天心区",code:"430103"},{name:"岳麓区",code:"430104"},{name:"开福区",code:"430105"},{name:"雨花区",code:"430111"},{name:"望城区",code:"430112"},{name:"长沙县",code:"430121"},{name:"宁乡县",code:"430124"},{name:"浏阳市",code:"430181"}]},{name:"株洲市",code:"430200",sub:[{name:"市辖区",code:"430201"},{name:"荷塘区",code:"430202"},{name:"芦淞区",code:"430203"},{name:"石峰区",code:"430204"},{name:"天元区",code:"430211"},{name:"株洲县",code:"430221"},{name:"攸县",code:"430223"},{name:"茶陵县",code:"430224"},{name:"炎陵县",code:"430225"},{name:"醴陵市",code:"430281"}]},{name:"湘潭市",code:"430300",sub:[{name:"市辖区",code:"430301"},{name:"雨湖区",code:"430302"},{name:"岳塘区",code:"430304"},{name:"湘潭县",code:"430321"},{name:"湘乡市",code:"430381"},{name:"韶山市",code:"430382"}]},{name:"衡阳市",code:"430400",sub:[{name:"市辖区",code:"430401"},{name:"珠晖区",code:"430405"},{name:"雁峰区",code:"430406"},{name:"石鼓区",code:"430407"},{name:"蒸湘区",code:"430408"},{name:"南岳区",code:"430412"},{name:"衡阳县",code:"430421"},{name:"衡南县",code:"430422"},{name:"衡山县",code:"430423"},{name:"衡东县",code:"430424"},{name:"祁东县",code:"430426"},{name:"耒阳市",code:"430481"},{name:"常宁市",code:"430482"}]},{name:"邵阳市",code:"430500",sub:[{name:"市辖区",code:"430501"},{name:"双清区",code:"430502"},{name:"大祥区",code:"430503"},{name:"北塔区",code:"430511"},{name:"邵东县",code:"430521"},{name:"新邵县",code:"430522"},{name:"邵阳县",code:"430523"},{name:"隆回县",code:"430524"},{name:"洞口县",code:"430525"},{name:"绥宁县",code:"430527"},{name:"新宁县",code:"430528"},{name:"城步苗族自治县",code:"430529"},{name:"武冈市",code:"430581"}]},{name:"岳阳市",code:"430600",sub:[{name:"市辖区",code:"430601"},{name:"岳阳楼区",code:"430602"},{name:"云溪区",code:"430603"},{name:"君山区",code:"430611"},{name:"岳阳县",code:"430621"},{name:"华容县",code:"430623"},{name:"湘阴县",code:"430624"},{name:"平江县",code:"430626"},{name:"汨罗市",code:"430681"},{name:"临湘市",code:"430682"}]},{name:"常德市",code:"430700",sub:[{name:"市辖区",code:"430701"},{name:"武陵区",code:"430702"},{name:"鼎城区",code:"430703"},{name:"安乡县",code:"430721"},{name:"汉寿县",code:"430722"},{name:"澧县",code:"430723"},{name:"临澧县",code:"430724"},{name:"桃源县",code:"430725"},{name:"石门县",code:"430726"},{name:"津市市",code:"430781"}]},{name:"张家界市",code:"430800",sub:[{name:"市辖区",code:"430801"},{name:"永定区",code:"430802"},{name:"武陵源区",code:"430811"},{name:"慈利县",code:"430821"},{name:"桑植县",code:"430822"}]},{name:"益阳市",code:"430900",sub:[{name:"市辖区",code:"430901"},{name:"资阳区",code:"430902"},{name:"赫山区",code:"430903"},{name:"南县",code:"430921"},{name:"桃江县",code:"430922"},{name:"安化县",code:"430923"},{name:"沅江市",code:"430981"}]},{name:"郴州市",code:"431000",sub:[{name:"市辖区",code:"431001"},{name:"北湖区",code:"431002"},{name:"苏仙区",code:"431003"},{name:"桂阳县",code:"431021"},{name:"宜章县",code:"431022"},{name:"永兴县",code:"431023"},{name:"嘉禾县",code:"431024"},{name:"临武县",code:"431025"},{name:"汝城县",code:"431026"},{name:"桂东县",code:"431027"},{name:"安仁县",code:"431028"},{name:"资兴市",code:"431081"}]},{name:"永州市",code:"431100",sub:[{name:"市辖区",code:"431101"},{name:"零陵区",code:"431102"},{name:"冷水滩区",code:"431103"},{name:"祁阳县",code:"431121"},{name:"东安县",code:"431122"},{name:"双牌县",code:"431123"},{name:"道县",code:"431124"},{name:"江永县",code:"431125"},{name:"宁远县",code:"431126"},{name:"蓝山县",code:"431127"},{name:"新田县",code:"431128"},{name:"江华瑶族自治县",code:"431129"}]},{name:"怀化市",code:"431200",sub:[{name:"市辖区",code:"431201"},{name:"鹤城区",code:"431202"},{name:"中方县",code:"431221"},{name:"沅陵县",code:"431222"},{name:"辰溪县",code:"431223"},{name:"溆浦县",code:"431224"},{name:"会同县",code:"431225"},{name:"麻阳苗族自治县",code:"431226"},{name:"新晃侗族自治县",code:"431227"},{name:"芷江侗族自治县",code:"431228"},{name:"靖州苗族侗族自治县",code:"431229"},{name:"通道侗族自治县",code:"431230"},{name:"洪江市",code:"431281"}]},{name:"娄底市",code:"431300",sub:[{name:"市辖区",code:"431301"},{name:"娄星区",code:"431302"},{name:"双峰县",code:"431321"},{name:"新化县",code:"431322"},{name:"冷水江市",code:"431381"},{name:"涟源市",code:"431382"}]},{name:"湘西土家族苗族自治州",code:"433100",sub:[{name:"吉首市",code:"433101"},{name:"泸溪县",code:"433122"},{name:"凤凰县",code:"433123"},{name:"花垣县",code:"433124"},{name:"保靖县",code:"433125"},{name:"古丈县",code:"433126"},{name:"永顺县",code:"433127"},{name:"龙山县",code:"433130"}]}]},{name:"广东省",code:"440000",sub:[{name:"广州市",code:"440100",sub:[{name:"市辖区",code:"440101"},{name:"荔湾区",code:"440103"},{name:"越秀区",code:"440104"},{name:"海珠区",code:"440105"},{name:"天河区",code:"440106"},{name:"白云区",code:"440111"},{name:"黄埔区",code:"440112"},{name:"番禺区",code:"440113"},{name:"花都区",code:"440114"},{name:"南沙区",code:"440115"},{name:"从化区",code:"440117"},{name:"增城区",code:"440118"}]},{name:"韶关市",code:"440200",sub:[{name:"市辖区",code:"440201"},{name:"武江区",code:"440203"},{name:"浈江区",code:"440204"},{name:"曲江区",code:"440205"},{name:"始兴县",code:"440222"},{name:"仁化县",code:"440224"},{name:"翁源县",code:"440229"},{name:"乳源瑶族自治县",code:"440232"},{name:"新丰县",code:"440233"},{name:"乐昌市",code:"440281"},{name:"南雄市",code:"440282"}]},{name:"深圳市",code:"440300",sub:[{name:"市辖区",code:"440301"},{name:"罗湖区",code:"440303"},{name:"福田区",code:"440304"},{name:"南山区",code:"440305"},{name:"宝安区",code:"440306"},{name:"龙岗区",code:"440307"},{name:"盐田区",code:"440308"}]},{name:"珠海市",code:"440400",sub:[{name:"市辖区",code:"440401"},{name:"香洲区",code:"440402"},{name:"斗门区",code:"440403"},{name:"金湾区",code:"440404"}]},{name:"汕头市",code:"440500",sub:[{name:"市辖区",code:"440501"},{name:"龙湖区",code:"440507"},{name:"金平区",code:"440511"},{name:"濠江区",code:"440512"},{name:"潮阳区",code:"440513"},{name:"潮南区",code:"440514"},{name:"澄海区",code:"440515"},{name:"南澳县",code:"440523"}]},{name:"佛山市",code:"440600",sub:[{name:"市辖区",code:"440601"},{name:"禅城区",code:"440604"},{name:"南海区",code:"440605"},{name:"顺德区",code:"440606"},{name:"三水区",code:"440607"},{name:"高明区",code:"440608"}]},{name:"江门市",code:"440700",sub:[{name:"市辖区",code:"440701"},{name:"蓬江区",code:"440703"},{name:"江海区",code:"440704"},{name:"新会区",code:"440705"},{name:"台山市",code:"440781"},{name:"开平市",code:"440783"},{name:"鹤山市",code:"440784"},{name:"恩平市",code:"440785"}]},{name:"湛江市",code:"440800",sub:[{name:"市辖区",code:"440801"},{name:"赤坎区",code:"440802"},{name:"霞山区",code:"440803"},{name:"坡头区",code:"440804"},{name:"麻章区",code:"440811"},{name:"遂溪县",code:"440823"},{name:"徐闻县",code:"440825"},{name:"廉江市",code:"440881"},{name:"雷州市",code:"440882"},{name:"吴川市",code:"440883"}]},{name:"茂名市",code:"440900",sub:[{name:"市辖区",code:"440901"},{name:"茂南区",code:"440902"},{name:"电白区",code:"440904"},{name:"高州市",code:"440981"},{name:"化州市",code:"440982"},{name:"信宜市",code:"440983"}]},{name:"肇庆市",code:"441200",sub:[{name:"市辖区",code:"441201"},{name:"端州区",code:"441202"},{name:"鼎湖区",code:"441203"},{name:"广宁县",code:"441223"},{name:"怀集县",code:"441224"},{name:"封开县",code:"441225"},{name:"德庆县",code:"441226"},{name:"高要市",code:"441283"},{name:"四会市",code:"441284"}]},{name:"惠州市",code:"441300",sub:[{name:"市辖区",code:"441301"},{name:"惠城区",code:"441302"},{name:"惠阳区",code:"441303"},{name:"博罗县",code:"441322"},{name:"惠东县",code:"441323"},{name:"龙门县",code:"441324"}]},{name:"梅州市",code:"441400",sub:[{name:"市辖区",code:"441401"},{name:"梅江区",code:"441402"},{name:"梅县区",code:"441403"},{name:"大埔县",code:"441422"},{name:"丰顺县",code:"441423"},{name:"五华县",code:"441424"},{name:"平远县",code:"441426"},{name:"蕉岭县",code:"441427"},{name:"兴宁市",code:"441481"}]},{name:"汕尾市",code:"441500",sub:[{name:"市辖区",code:"441501"},{name:"城区",code:"441502"},{name:"海丰县",code:"441521"},{name:"陆河县",code:"441523"},{name:"陆丰市",code:"441581"}]},{name:"河源市",code:"441600",sub:[{name:"市辖区",code:"441601"},{name:"源城区",code:"441602"},{name:"紫金县",code:"441621"},{name:"龙川县",code:"441622"},{name:"连平县",code:"441623"},{name:"和平县",code:"441624"},{name:"东源县",code:"441625"}]},{name:"阳江市",code:"441700",sub:[{name:"市辖区",code:"441701"},{name:"江城区",code:"441702"},{name:"阳东区",code:"441704"},{name:"阳西县",code:"441721"},{name:"阳春市",code:"441781"}]},{name:"清远市",code:"441800",sub:[{name:"市辖区",code:"441801"},{name:"清城区",code:"441802"},{name:"清新区",code:"441803"},{name:"佛冈县",code:"441821"},{name:"阳山县",code:"441823"},{name:"连山壮族瑶族自治县",code:"441825"},{name:"连南瑶族自治县",code:"441826"},{name:"英德市",code:"441881"},{name:"连州市",code:"441882"}]},{name:"东莞市",code:"441900",sub:[]},{name:"中山市",code:"442000",sub:[]},{name:"潮州市",code:"445100",sub:[{name:"市辖区",code:"445101"},{name:"湘桥区",code:"445102"},{name:"潮安区",code:"445103"},{name:"饶平县",code:"445122"}]},{name:"揭阳市",code:"445200",sub:[{name:"市辖区",code:"445201"},{name:"榕城区",code:"445202"},{name:"揭东区",code:"445203"},{name:"揭西县",code:"445222"},{name:"惠来县",code:"445224"},{name:"普宁市",code:"445281"}]},{name:"云浮市",code:"445300",sub:[{name:"市辖区",code:"445301"},{name:"云城区",code:"445302"},{name:"云安区",code:"445303"},{name:"新兴县",code:"445321"},{name:"郁南县",code:"445322"},{name:"罗定市",code:"445381"}]}]},{name:"广西壮族自治区",code:"450000",sub:[{name:"南宁市",code:"450100",sub:[{name:"市辖区",code:"450101"},{name:"兴宁区",code:"450102"},{name:"青秀区",code:"450103"},{name:"江南区",code:"450105"},{name:"西乡塘区",code:"450107"},{name:"良庆区",code:"450108"},{name:"邕宁区",code:"450109"},{name:"武鸣县",code:"450122"},{name:"隆安县",code:"450123"},{name:"马山县",code:"450124"},{name:"上林县",code:"450125"},{name:"宾阳县",code:"450126"},{name:"横县",code:"450127"}]},{name:"柳州市",code:"450200",sub:[{name:"市辖区",code:"450201"},{name:"城中区",code:"450202"},{name:"鱼峰区",code:"450203"},{name:"柳南区",code:"450204"
+},{name:"柳北区",code:"450205"},{name:"柳江县",code:"450221"},{name:"柳城县",code:"450222"},{name:"鹿寨县",code:"450223"},{name:"融安县",code:"450224"},{name:"融水苗族自治县",code:"450225"},{name:"三江侗族自治县",code:"450226"}]},{name:"桂林市",code:"450300",sub:[{name:"市辖区",code:"450301"},{name:"秀峰区",code:"450302"},{name:"叠彩区",code:"450303"},{name:"象山区",code:"450304"},{name:"七星区",code:"450305"},{name:"雁山区",code:"450311"},{name:"临桂区",code:"450312"},{name:"阳朔县",code:"450321"},{name:"灵川县",code:"450323"},{name:"全州县",code:"450324"},{name:"兴安县",code:"450325"},{name:"永福县",code:"450326"},{name:"灌阳县",code:"450327"},{name:"龙胜各族自治县",code:"450328"},{name:"资源县",code:"450329"},{name:"平乐县",code:"450330"},{name:"荔浦县",code:"450331"},{name:"恭城瑶族自治县",code:"450332"}]},{name:"梧州市",code:"450400",sub:[{name:"市辖区",code:"450401"},{name:"万秀区",code:"450403"},{name:"长洲区",code:"450405"},{name:"龙圩区",code:"450406"},{name:"苍梧县",code:"450421"},{name:"藤县",code:"450422"},{name:"蒙山县",code:"450423"},{name:"岑溪市",code:"450481"}]},{name:"北海市",code:"450500",sub:[{name:"市辖区",code:"450501"},{name:"海城区",code:"450502"},{name:"银海区",code:"450503"},{name:"铁山港区",code:"450512"},{name:"合浦县",code:"450521"}]},{name:"防城港市",code:"450600",sub:[{name:"市辖区",code:"450601"},{name:"港口区",code:"450602"},{name:"防城区",code:"450603"},{name:"上思县",code:"450621"},{name:"东兴市",code:"450681"}]},{name:"钦州市",code:"450700",sub:[{name:"市辖区",code:"450701"},{name:"钦南区",code:"450702"},{name:"钦北区",code:"450703"},{name:"灵山县",code:"450721"},{name:"浦北县",code:"450722"}]},{name:"贵港市",code:"450800",sub:[{name:"市辖区",code:"450801"},{name:"港北区",code:"450802"},{name:"港南区",code:"450803"},{name:"覃塘区",code:"450804"},{name:"平南县",code:"450821"},{name:"桂平市",code:"450881"}]},{name:"玉林市",code:"450900",sub:[{name:"市辖区",code:"450901"},{name:"玉州区",code:"450902"},{name:"福绵区",code:"450903"},{name:"容县",code:"450921"},{name:"陆川县",code:"450922"},{name:"博白县",code:"450923"},{name:"兴业县",code:"450924"},{name:"北流市",code:"450981"}]},{name:"百色市",code:"451000",sub:[{name:"市辖区",code:"451001"},{name:"右江区",code:"451002"},{name:"田阳县",code:"451021"},{name:"田东县",code:"451022"},{name:"平果县",code:"451023"},{name:"德保县",code:"451024"},{name:"靖西县",code:"451025"},{name:"那坡县",code:"451026"},{name:"凌云县",code:"451027"},{name:"乐业县",code:"451028"},{name:"田林县",code:"451029"},{name:"西林县",code:"451030"},{name:"隆林各族自治县",code:"451031"}]},{name:"贺州市",code:"451100",sub:[{name:"市辖区",code:"451101"},{name:"八步区",code:"451102"},{name:"平桂管理区",code:"451119"},{name:"昭平县",code:"451121"},{name:"钟山县",code:"451122"},{name:"富川瑶族自治县",code:"451123"}]},{name:"河池市",code:"451200",sub:[{name:"市辖区",code:"451201"},{name:"金城江区",code:"451202"},{name:"南丹县",code:"451221"},{name:"天峨县",code:"451222"},{name:"凤山县",code:"451223"},{name:"东兰县",code:"451224"},{name:"罗城仫佬族自治县",code:"451225"},{name:"环江毛南族自治县",code:"451226"},{name:"巴马瑶族自治县",code:"451227"},{name:"都安瑶族自治县",code:"451228"},{name:"大化瑶族自治县",code:"451229"},{name:"宜州市",code:"451281"}]},{name:"来宾市",code:"451300",sub:[{name:"市辖区",code:"451301"},{name:"兴宾区",code:"451302"},{name:"忻城县",code:"451321"},{name:"象州县",code:"451322"},{name:"武宣县",code:"451323"},{name:"金秀瑶族自治县",code:"451324"},{name:"合山市",code:"451381"}]},{name:"崇左市",code:"451400",sub:[{name:"市辖区",code:"451401"},{name:"江州区",code:"451402"},{name:"扶绥县",code:"451421"},{name:"宁明县",code:"451422"},{name:"龙州县",code:"451423"},{name:"大新县",code:"451424"},{name:"天等县",code:"451425"},{name:"凭祥市",code:"451481"}]}]},{name:"海南省",code:"460000",sub:[{name:"海口市",code:"460100",sub:[{name:"市辖区",code:"460101"},{name:"秀英区",code:"460105"},{name:"龙华区",code:"460106"},{name:"琼山区",code:"460107"},{name:"美兰区",code:"460108"}]},{name:"三亚市",code:"460200",sub:[{name:"市辖区",code:"460201"},{name:"海棠区",code:"460202"},{name:"吉阳区",code:"460203"},{name:"天涯区",code:"460204"},{name:"崖州区",code:"460205"}]},{name:"三沙市",code:"460300",sub:[{name:"西沙群岛",code:"460321"},{name:"南沙群岛",code:"460322"},{name:"中沙群岛的岛礁及其海域",code:"460323"}]},{name:"五指山市",code:"469001"},{name:"琼海市",code:"469002"},{name:"儋州市",code:"469003"},{name:"文昌市",code:"469005"},{name:"万宁市",code:"469006"},{name:"东方市",code:"469007"},{name:"定安县",code:"469021"},{name:"屯昌县",code:"469022"},{name:"澄迈县",code:"469023"},{name:"临高县",code:"469024"},{name:"白沙黎族自治县",code:"469025"},{name:"昌江黎族自治县",code:"469026"},{name:"乐东黎族自治县",code:"469027"},{name:"陵水黎族自治县",code:"469028"},{name:"保亭黎族苗族自治县",code:"469029"},{name:"琼中黎族苗族自治县",code:"469030"}]},{name:"重庆",code:"500000",sub:[{name:"重庆市",code:"500000",sub:[{name:"万州区",code:"500101"},{name:"涪陵区",code:"500102"},{name:"渝中区",code:"500103"},{name:"大渡口区",code:"500104"},{name:"江北区",code:"500105"},{name:"沙坪坝区",code:"500106"},{name:"九龙坡区",code:"500107"},{name:"南岸区",code:"500108"},{name:"北碚区",code:"500109"},{name:"綦江区",code:"500110"},{name:"大足区",code:"500111"},{name:"渝北区",code:"500112"},{name:"巴南区",code:"500113"},{name:"黔江区",code:"500114"},{name:"长寿区",code:"500115"},{name:"江津区",code:"500116"},{name:"合川区",code:"500117"},{name:"永川区",code:"500118"},{name:"南川区",code:"500119"},{name:"璧山区",code:"500120"},{name:"铜梁区",code:"500151"},{name:"潼南县",code:"500223"},{name:"荣昌县",code:"500226"},{name:"梁平县",code:"500228"},{name:"城口县",code:"500229"},{name:"丰都县",code:"500230"},{name:"垫江县",code:"500231"},{name:"武隆县",code:"500232"},{name:"忠县",code:"500233"},{name:"开县",code:"500234"},{name:"云阳县",code:"500235"},{name:"奉节县",code:"500236"},{name:"巫山县",code:"500237"},{name:"巫溪县",code:"500238"},{name:"石柱土家族自治县",code:"500240"},{name:"秀山土家族苗族自治县",code:"500241"},{name:"酉阳土家族苗族自治县",code:"500242"},{name:"彭水苗族土家族自治县",code:"500243"}]}]},{name:"四川省",code:"510000",sub:[{name:"成都市",code:"510100",sub:[{name:"市辖区",code:"510101"},{name:"锦江区",code:"510104"},{name:"青羊区",code:"510105"},{name:"金牛区",code:"510106"},{name:"武侯区",code:"510107"},{name:"成华区",code:"510108"},{name:"龙泉驿区",code:"510112"},{name:"青白江区",code:"510113"},{name:"新都区",code:"510114"},{name:"温江区",code:"510115"},{name:"金堂县",code:"510121"},{name:"双流县",code:"510122"},{name:"郫县",code:"510124"},{name:"大邑县",code:"510129"},{name:"蒲江县",code:"510131"},{name:"新津县",code:"510132"},{name:"都江堰市",code:"510181"},{name:"彭州市",code:"510182"},{name:"邛崃市",code:"510183"},{name:"崇州市",code:"510184"}]},{name:"自贡市",code:"510300",sub:[{name:"市辖区",code:"510301"},{name:"自流井区",code:"510302"},{name:"贡井区",code:"510303"},{name:"大安区",code:"510304"},{name:"沿滩区",code:"510311"},{name:"荣县",code:"510321"},{name:"富顺县",code:"510322"}]},{name:"攀枝花市",code:"510400",sub:[{name:"市辖区",code:"510401"},{name:"东区",code:"510402"},{name:"西区",code:"510403"},{name:"仁和区",code:"510411"},{name:"米易县",code:"510421"},{name:"盐边县",code:"510422"}]},{name:"泸州市",code:"510500",sub:[{name:"市辖区",code:"510501"},{name:"江阳区",code:"510502"},{name:"纳溪区",code:"510503"},{name:"龙马潭区",code:"510504"},{name:"泸县",code:"510521"},{name:"合江县",code:"510522"},{name:"叙永县",code:"510524"},{name:"古蔺县",code:"510525"}]},{name:"德阳市",code:"510600",sub:[{name:"市辖区",code:"510601"},{name:"旌阳区",code:"510603"},{name:"中江县",code:"510623"},{name:"罗江县",code:"510626"},{name:"广汉市",code:"510681"},{name:"什邡市",code:"510682"},{name:"绵竹市",code:"510683"}]},{name:"绵阳市",code:"510700",sub:[{name:"市辖区",code:"510701"},{name:"涪城区",code:"510703"},{name:"游仙区",code:"510704"},{name:"三台县",code:"510722"},{name:"盐亭县",code:"510723"},{name:"安县",code:"510724"},{name:"梓潼县",code:"510725"},{name:"北川羌族自治县",code:"510726"},{name:"平武县",code:"510727"},{name:"江油市",code:"510781"}]},{name:"广元市",code:"510800",sub:[{name:"市辖区",code:"510801"},{name:"利州区",code:"510802"},{name:"昭化区",code:"510811"},{name:"朝天区",code:"510812"},{name:"旺苍县",code:"510821"},{name:"青川县",code:"510822"},{name:"剑阁县",code:"510823"},{name:"苍溪县",code:"510824"}]},{name:"遂宁市",code:"510900",sub:[{name:"市辖区",code:"510901"},{name:"船山区",code:"510903"},{name:"安居区",code:"510904"},{name:"蓬溪县",code:"510921"},{name:"射洪县",code:"510922"},{name:"大英县",code:"510923"}]},{name:"内江市",code:"511000",sub:[{name:"市辖区",code:"511001"},{name:"市中区",code:"511002"},{name:"东兴区",code:"511011"},{name:"威远县",code:"511024"},{name:"资中县",code:"511025"},{name:"隆昌县",code:"511028"}]},{name:"乐山市",code:"511100",sub:[{name:"市辖区",code:"511101"},{name:"市中区",code:"511102"},{name:"沙湾区",code:"511111"},{name:"五通桥区",code:"511112"},{name:"金口河区",code:"511113"},{name:"犍为县",code:"511123"},{name:"井研县",code:"511124"},{name:"夹江县",code:"511126"},{name:"沐川县",code:"511129"},{name:"峨边彝族自治县",code:"511132"},{name:"马边彝族自治县",code:"511133"},{name:"峨眉山市",code:"511181"}]},{name:"南充市",code:"511300",sub:[{name:"市辖区",code:"511301"},{name:"顺庆区",code:"511302"},{name:"高坪区",code:"511303"},{name:"嘉陵区",code:"511304"},{name:"南部县",code:"511321"},{name:"营山县",code:"511322"},{name:"蓬安县",code:"511323"},{name:"仪陇县",code:"511324"},{name:"西充县",code:"511325"},{name:"阆中市",code:"511381"}]},{name:"眉山市",code:"511400",sub:[{name:"市辖区",code:"511401"},{name:"东坡区",code:"511402"},{name:"彭山区",code:"511403"},{name:"仁寿县",code:"511421"},{name:"洪雅县",code:"511423"},{name:"丹棱县",code:"511424"},{name:"青神县",code:"511425"}]},{name:"宜宾市",code:"511500",sub:[{name:"市辖区",code:"511501"},{name:"翠屏区",code:"511502"},{name:"南溪区",code:"511503"},{name:"宜宾县",code:"511521"},{name:"江安县",code:"511523"},{name:"长宁县",code:"511524"},{name:"高县",code:"511525"},{name:"珙县",code:"511526"},{name:"筠连县",code:"511527"},{name:"兴文县",code:"511528"},{name:"屏山县",code:"511529"}]},{name:"广安市",code:"511600",sub:[{name:"市辖区",code:"511601"},{name:"广安区",code:"511602"},{name:"前锋区",code:"511603"},{name:"岳池县",code:"511621"},{name:"武胜县",code:"511622"},{name:"邻水县",code:"511623"},{name:"华蓥市",code:"511681"}]},{name:"达州市",code:"511700",sub:[{name:"市辖区",code:"511701"},{name:"通川区",code:"511702"},{name:"达川区",code:"511703"},{name:"宣汉县",code:"511722"},{name:"开江县",code:"511723"},{name:"大竹县",code:"511724"},{name:"渠县",code:"511725"},{name:"万源市",code:"511781"}]},{name:"雅安市",code:"511800",sub:[{name:"市辖区",code:"511801"},{name:"雨城区",code:"511802"},{name:"名山区",code:"511803"},{name:"荥经县",code:"511822"},{name:"汉源县",code:"511823"},{name:"石棉县",code:"511824"},{name:"天全县",code:"511825"},{name:"芦山县",code:"511826"},{name:"宝兴县",code:"511827"}]},{name:"巴中市",code:"511900",sub:[{name:"市辖区",code:"511901"},{name:"巴州区",code:"511902"},{name:"恩阳区",code:"511903"},{name:"通江县",code:"511921"},{name:"南江县",code:"511922"},{name:"平昌县",code:"511923"}]},{name:"资阳市",code:"512000",sub:[{name:"市辖区",code:"512001"},{name:"雁江区",code:"512002"},{name:"安岳县",code:"512021"},{name:"乐至县",code:"512022"},{name:"简阳市",code:"512081"}]},{name:"阿坝藏族羌族自治州",code:"513200",sub:[{name:"汶川县",code:"513221"},{name:"理县",code:"513222"},{name:"茂县",code:"513223"},{name:"松潘县",code:"513224"},{name:"九寨沟县",code:"513225"},{name:"金川县",code:"513226"},{name:"小金县",code:"513227"},{name:"黑水县",code:"513228"},{name:"马尔康县",code:"513229"},{name:"壤塘县",code:"513230"},{name:"阿坝县",code:"513231"},{name:"若尔盖县",code:"513232"},{name:"红原县",code:"513233"}]},{name:"甘孜藏族自治州",code:"513300",sub:[{name:"康定县",code:"513321"},{name:"泸定县",code:"513322"},{name:"丹巴县",code:"513323"},{name:"九龙县",code:"513324"},{name:"雅江县",code:"513325"},{name:"道孚县",code:"513326"},{name:"炉霍县",code:"513327"},{name:"甘孜县",code:"513328"},{name:"新龙县",code:"513329"},{name:"德格县",code:"513330"},{name:"白玉县",code:"513331"},{name:"石渠县",code:"513332"},{name:"色达县",code:"513333"},{name:"理塘县",code:"513334"},{name:"巴塘县",code:"513335"},{name:"乡城县",code:"513336"},{name:"稻城县",code:"513337"},{name:"得荣县",code:"513338"}]},{name:"凉山彝族自治州",code:"513400",sub:[{name:"西昌市",code:"513401"},{name:"木里藏族自治县",code:"513422"},{name:"盐源县",code:"513423"},{name:"德昌县",code:"513424"},{name:"会理县",code:"513425"},{name:"会东县",code:"513426"},{name:"宁南县",code:"513427"},{name:"普格县",code:"513428"},{name:"布拖县",code:"513429"},{name:"金阳县",code:"513430"},{name:"昭觉县",code:"513431"},{name:"喜德县",code:"513432"},{name:"冕宁县",code:"513433"},{name:"越西县",code:"513434"},{name:"甘洛县",code:"513435"},{name:"美姑县",code:"513436"},{name:"雷波县",code:"513437"}]}]},{name:"贵州省",code:"520000",sub:[{name:"贵阳市",code:"520100",sub:[{name:"市辖区",code:"520101"},{name:"南明区",code:"520102"},{name:"云岩区",code:"520103"},{name:"花溪区",code:"520111"},{name:"乌当区",code:"520112"},{name:"白云区",code:"520113"},{name:"观山湖区",code:"520115"},{name:"开阳县",code:"520121"},{name:"息烽县",code:"520122"},{name:"修文县",code:"520123"},{name:"清镇市",code:"520181"}]},{name:"六盘水市",code:"520200",sub:[{name:"钟山区",code:"520201"},{name:"六枝特区",code:"520203"},{name:"水城县",code:"520221"},{name:"盘县",code:"520222"}]},{name:"遵义市",code:"520300",sub:[{name:"市辖区",code:"520301"},{name:"红花岗区",code:"520302"},{name:"汇川区",code:"520303"},{name:"遵义县",code:"520321"},{name:"桐梓县",code:"520322"},{name:"绥阳县",code:"520323"},{name:"正安县",code:"520324"},{name:"道真仡佬族苗族自治县",code:"520325"},{name:"务川仡佬族苗族自治县",code:"520326"},{name:"凤冈县",code:"520327"},{name:"湄潭县",code:"520328"},{name:"余庆县",code:"520329"},{name:"习水县",code:"520330"},{name:"赤水市",code:"520381"},{name:"仁怀市",code:"520382"}]},{name:"安顺市",code:"520400",sub:[{name:"市辖区",code:"520401"},{name:"西秀区",code:"520402"},{name:"平坝区",code:"520403"},{name:"普定县",code:"520422"},{name:"镇宁布依族苗族自治县",code:"520423"},{name:"关岭布依族苗族自治县",code:"520424"},{name:"紫云苗族布依族自治县",code:"520425"}]},{name:"毕节市",code:"520500",sub:[{name:"市辖区",code:"520501"},{name:"七星关区",code:"520502"},{name:"大方县",code:"520521"},{name:"黔西县",code:"520522"},{name:"金沙县",code:"520523"},{name:"织金县",code:"520524"},{name:"纳雍县",code:"520525"},{name:"威宁彝族回族苗族自治县",code:"520526"},{name:"赫章县",code:"520527"}]},{name:"铜仁市",code:"520600",sub:[{name:"市辖区",code:"520601"},{name:"碧江区",code:"520602"},{name:"万山区",code:"520603"},{name:"江口县",code:"520621"},{name:"玉屏侗族自治县",code:"520622"},{name:"石阡县",code:"520623"},{name:"思南县",code:"520624"},{name:"印江土家族苗族自治县",code:"520625"},{name:"德江县",code:"520626"},{name:"沿河土家族自治县",code:"520627"},{name:"松桃苗族自治县",code:"520628"}]},{name:"黔西南布依族苗族自治州",code:"522300",sub:[{name:"兴义市",code:"522301"},{name:"兴仁县",code:"522322"},{name:"普安县",code:"522323"},{name:"晴隆县",code:"522324"},{name:"贞丰县",code:"522325"},{name:"望谟县",code:"522326"},{name:"册亨县",code:"522327"},{name:"安龙县",code:"522328"}]},{name:"黔东南苗族侗族自治州",code:"522600",sub:[{name:"凯里市",code:"522601"},{name:"黄平县",code:"522622"},{name:"施秉县",code:"522623"},{name:"三穗县",code:"522624"},{name:"镇远县",code:"522625"},{name:"岑巩县",code:"522626"},{name:"天柱县",code:"522627"},{name:"锦屏县",code:"522628"},{name:"剑河县",code:"522629"},{name:"台江县",code:"522630"},{name:"黎平县",code:"522631"},{name:"榕江县",code:"522632"},{name:"从江县",code:"522633"},{name:"雷山县",code:"522634"},{name:"麻江县",code:"522635"},{name:"丹寨县",code:"522636"}]},{name:"黔南布依族苗族自治州",code:"522700",sub:[{name:"都匀市",code:"522701"},{name:"福泉市",code:"522702"},{name:"荔波县",code:"522722"},{name:"贵定县",code:"522723"},{name:"瓮安县",code:"522725"},{name:"独山县",code:"522726"},{name:"平塘县",code:"522727"},{name:"罗甸县",code:"522728"},{name:"长顺县",code:"522729"},{name:"龙里县",code:"522730"},{name:"惠水县",code:"522731"},{name:"三都水族自治县",code:"522732"}]}]},{name:"云南省",code:"530000",sub:[{name:"昆明市",code:"530100",sub:[{name:"市辖区",code:"530101"},{name:"五华区",code:"530102"},{name:"盘龙区",code:"530103"},{name:"官渡区",code:"530111"},{name:"西山区",code:"530112"},{name:"东川区",code:"530113"},{name:"呈贡区",code:"530114"},{name:"晋宁县",code:"530122"},{name:"富民县",code:"530124"},{name:"宜良县",code:"530125"},{name:"石林彝族自治县",code:"530126"},{name:"嵩明县",code:"530127"},{name:"禄劝彝族苗族自治县",code:"530128"},{name:"寻甸回族彝族自治县",code:"530129"},{name:"安宁市",code:"530181"}]},{name:"曲靖市",code:"530300",sub:[{name:"市辖区",code:"530301"},{name:"麒麟区",code:"530302"},{name:"马龙县",code:"530321"},{name:"陆良县",code:"530322"},{name:"师宗县",code:"530323"},{name:"罗平县",code:"530324"},{name:"富源县",code:"530325"},{name:"会泽县",code:"530326"},{name:"沾益县",code:"530328"},{name:"宣威市",code:"530381"}]},{name:"玉溪市",code:"530400",sub:[{name:"市辖区",code:"530401"},{name:"红塔区",code:"530402"},{name:"江川县",code:"530421"},{name:"澄江县",code:"530422"},{name:"通海县",code:"530423"},{name:"华宁县",code:"530424"},{name:"易门县",code:"530425"},{name:"峨山彝族自治县",code:"530426"},{name:"新平彝族傣族自治县",code:"530427"},{name:"元江哈尼族彝族傣族自治县",code:"530428"}]},{name:"保山市",code:"530500",sub:[{name:"市辖区",code:"530501"},{name:"隆阳区",code:"530502"},{name:"施甸县",code:"530521"},{name:"腾冲县",code:"530522"},{name:"龙陵县",code:"530523"},{name:"昌宁县",code:"530524"}]},{name:"昭通市",code:"530600",sub:[{name:"市辖区",code:"530601"},{name:"昭阳区",code:"530602"},{name:"鲁甸县",code:"530621"},{name:"巧家县",code:"530622"},{name:"盐津县",code:"530623"},{name:"大关县",code:"530624"},{name:"永善县",code:"530625"},{name:"绥江县",code:"530626"},{name:"镇雄县",code:"530627"},{name:"彝良县",code:"530628"},{name:"威信县",code:"530629"},{name:"水富县",code:"530630"}]},{name:"丽江市",code:"530700",sub:[{name:"市辖区",code:"530701"},{name:"古城区",code:"530702"},{name:"玉龙纳西族自治县",code:"530721"},{name:"永胜县",code:"530722"},{name:"华坪县",code:"530723"},{name:"宁蒗彝族自治县",code:"530724"}]},{name:"普洱市",code:"530800",sub:[{name:"市辖区",code:"530801"},{name:"思茅区",code:"530802"},{name:"宁洱哈尼族彝族自治县",code:"530821"},{name:"墨江哈尼族自治县",code:"530822"},{name:"景东彝族自治县",code:"530823"},{name:"景谷傣族彝族自治县",code:"530824"},{name:"镇沅彝族哈尼族拉祜族自治县",code:"530825"},{name:"江城哈尼族彝族自治县",code:"530826"},{name:"孟连傣族拉祜族佤族自治县",code:"530827"},{name:"澜沧拉祜族自治县",code:"530828"},{name:"西盟佤族自治县",code:"530829"}]},{name:"临沧市",code:"530900",sub:[{name:"市辖区",code:"530901"},{name:"临翔区",code:"530902"},{name:"凤庆县",code:"530921"},{name:"云县",code:"530922"},{name:"永德县",code:"530923"},{name:"镇康县",code:"530924"},{name:"双江拉祜族佤族布朗族傣族自治县",code:"530925"},{name:"耿马傣族佤族自治县",code:"530926"},{name:"沧源佤族自治县",code:"530927"}]},{name:"楚雄彝族自治州",code:"532300",sub:[{name:"楚雄市",code:"532301"},{name:"双柏县",code:"532322"},{name:"牟定县",code:"532323"},{name:"南华县",code:"532324"},{name:"姚安县",code:"532325"},{name:"大姚县",code:"532326"},{name:"永仁县",code:"532327"},{name:"元谋县",code:"532328"},{name:"武定县",code:"532329"},{name:"禄丰县",code:"532331"}]},{name:"红河哈尼族彝族自治州",code:"532500",sub:[{name:"个旧市",code:"532501"},{name:"开远市",code:"532502"},{name:"蒙自市",code:"532503"},{name:"弥勒市",code:"532504"},{name:"屏边苗族自治县",code:"532523"},{name:"建水县",code:"532524"},{name:"石屏县",code:"532525"},{name:"泸西县",code:"532527"},{name:"元阳县",code:"532528"},{name:"红河县",code:"532529"},{name:"金平苗族瑶族傣族自治县",code:"532530"},{name:"绿春县",code:"532531"},{name:"河口瑶族自治县",code:"532532"}]},{name:"文山壮族苗族自治州",code:"532600",sub:[{name:"文山市",code:"532601"},{name:"砚山县",code:"532622"},{name:"西畴县",code:"532623"},{name:"麻栗坡县",code:"532624"},{name:"马关县",code:"532625"},{name:"丘北县",code:"532626"},{name:"广南县",code:"532627"},{name:"富宁县",code:"532628"}]},{name:"西双版纳傣族自治州",code:"532800",sub:[{name:"景洪市",code:"532801"},{name:"勐海县",code:"532822"},{name:"勐腊县",code:"532823"}]},{name:"大理白族自治州",code:"532900",sub:[{name:"大理市",code:"532901"},{name:"漾濞彝族自治县",code:"532922"},{name:"祥云县",code:"532923"},{name:"宾川县",code:"532924"},{name:"弥渡县",code:"532925"},{name:"南涧彝族自治县",code:"532926"},{name:"巍山彝族回族自治县",code:"532927"},{name:"永平县",code:"532928"},{name:"云龙县",code:"532929"},{name:"洱源县",code:"532930"},{name:"剑川县",code:"532931"},{name:"鹤庆县",code:"532932"}]},{name:"德宏傣族景颇族自治州",code:"533100",sub:[{name:"瑞丽市",code:"533102"},{name:"芒市",code:"533103"},{name:"梁河县",code:"533122"},{name:"盈江县",code:"533123"},{name:"陇川县",code:"533124"}]},{name:"怒江傈僳族自治州",code:"533300",sub:[{name:"泸水县",code:"533321"},{name:"福贡县",code:"533323"},{name:"贡山独龙族怒族自治县",code:"533324"},{name:"兰坪白族普米族自治县",code:"533325"}]},{name:"迪庆藏族自治州",code:"533400",sub:[{name:"香格里拉市",code:"533401"},{name:"德钦县",code:"533422"},{name:"维西傈僳族自治县",code:"533423"}]}]},{name:"西藏自治区",code:"540000",sub:[{name:"拉萨市",code:"540100",sub:[{name:"市辖区",code:"540101"},{name:"城关区",code:"540102"},{name:"林周县",code:"540121"},{name:"当雄县",code:"540122"},{name:"尼木县",code:"540123"},{name:"曲水县",code:"540124"},{name:"堆龙德庆县",code:"540125"},{name:"达孜县",code:"540126"},{name:"墨竹工卡县",code:"540127"}]},{name:"日喀则市",code:"540200",sub:[{name:"市辖区",code:"540201"},{name:"桑珠孜区",code:"540202"},{name:"南木林县",code:"540221"},{name:"江孜县",code:"540222"},{name:"定日县",code:"540223"},{name:"萨迦县",code:"540224"},{name:"拉孜县",code:"540225"},{name:"昂仁县",code:"540226"},{name:"谢通门县",code:"540227"},{name:"白朗县",code:"540228"},{name:"仁布县",code:"540229"},{name:"康马县",code:"540230"},{name:"定结县",code:"540231"},{name:"仲巴县",code:"540232"},{name:"亚东县",code:"540233"},{name:"吉隆县",code:"540234"},{name:"聂拉木县",code:"540235"},{name:"萨嘎县",code:"540236"},{name:"岗巴县",code:"540237"}]},{name:"昌都市",code:"540300",sub:[{name:"市辖区",code:"540301"},{name:"卡若区",code:"540302"},{name:"江达县",code:"540321"},{name:"贡觉县",code:"540322"},{name:"类乌齐县",code:"540323"},{name:"丁青县",code:"540324"},{name:"察雅县",code:"540325"},{name:"八宿县",code:"540326"},{name:"左贡县",code:"540327"},{name:"芒康县",code:"540328"},{name:"洛隆县",code:"540329"},{name:"边坝县",code:"540330"}]},{name:"山南地区",code:"542200",sub:[{name:"乃东县",code:"542221"},{name:"扎囊县",code:"542222"},{name:"贡嘎县",code:"542223"},{name:"桑日县",code:"542224"},{name:"琼结县",code:"542225"},{name:"曲松县",code:"542226"},{name:"措美县",code:"542227"},{name:"洛扎县",code:"542228"},{name:"加查县",code:"542229"},{name:"隆子县",code:"542231"},{name:"错那县",code:"542232"},{name:"浪卡子县",code:"542233"}]},{name:"那曲地区",code:"542400",sub:[{name:"那曲县",code:"542421"},{name:"嘉黎县",code:"542422"},{name:"比如县",code:"542423"},{name:"聂荣县",code:"542424"},{name:"安多县",code:"542425"},{name:"申扎县",code:"542426"},{name:"索县",code:"542427"},{name:"班戈县",code:"542428"},{name:"巴青县",code:"542429"},{name:"尼玛县",code:"542430"},{name:"双湖县",code:"542431"}]},{name:"阿里地区",code:"542500",sub:[{name:"普兰县",code:"542521"},{name:"札达县",code:"542522"},{name:"噶尔县",code:"542523"},{name:"日土县",code:"542524"},{name:"革吉县",code:"542525"},{name:"改则县",code:"542526"},{name:"措勤县",code:"542527"}]},{name:"林芝地区",code:"542600",sub:[{name:"林芝县",code:"542621"},{name:"工布江达县",code:"542622"},{name:"米林县",code:"542623"},{name:"墨脱县",code:"542624"},{name:"波密县",code:"542625"},{name:"察隅县",code:"542626"},{name:"朗县",code:"542627"}]}]},{name:"陕西省",code:"610000",sub:[{name:"西安市",code:"610100",sub:[{name:"市辖区",code:"610101"},{name:"新城区",code:"610102"},{name:"碑林区",code:"610103"},{name:"莲湖区",code:"610104"},{name:"灞桥区",code:"610111"},{name:"未央区",code:"610112"},{name:"雁塔区",code:"610113"},{name:"阎良区",code:"610114"},{name:"临潼区",code:"610115"},{name:"长安区",code:"610116"},{name:"高陵区",code:"610117"},{name:"蓝田县",code:"610122"},{name:"周至县",code:"610124"},{name:"户县",code:"610125"}]},{name:"铜川市",code:"610200",sub:[{name:"市辖区",code:"610201"},{name:"王益区",code:"610202"},{name:"印台区",code:"610203"},{name:"耀州区",code:"610204"},{name:"宜君县",code:"610222"}]},{name:"宝鸡市",code:"610300",sub:[{name:"市辖区",code:"610301"},{name:"渭滨区",code:"610302"},{name:"金台区",code:"610303"},{name:"陈仓区",code:"610304"},{name:"凤翔县",code:"610322"},{name:"岐山县",code:"610323"},{name:"扶风县",code:"610324"},{name:"眉县",code:"610326"},{name:"陇县",code:"610327"},{name:"千阳县",code:"610328"},{name:"麟游县",code:"610329"},{name:"凤县",code:"610330"},{name:"太白县",code:"610331"}]},{name:"咸阳市",code:"610400",sub:[{name:"市辖区",code:"610401"},{name:"秦都区",code:"610402"},{name:"杨陵区",code:"610403"},{name:"渭城区",code:"610404"},{name:"三原县",code:"610422"},{name:"泾阳县",code:"610423"},{name:"乾县",code:"610424"},{name:"礼泉县",code:"610425"},{name:"永寿县",code:"610426"},{name:"彬县",code:"610427"},{name:"长武县",code:"610428"},{name:"旬邑县",code:"610429"},{name:"淳化县",code:"610430"},{name:"武功县",code:"610431"},{name:"兴平市",code:"610481"}]},{name:"渭南市",code:"610500",sub:[{name:"市辖区",code:"610501"},{name:"临渭区",code:"610502"},{name:"华县",code:"610521"},{name:"潼关县",code:"610522"},{name:"大荔县",code:"610523"},{name:"合阳县",code:"610524"},{name:"澄城县",code:"610525"},{name:"蒲城县",code:"610526"},{name:"白水县",code:"610527"},{name:"富平县",code:"610528"},{name:"韩城市",code:"610581"},{name:"华阴市",code:"610582"}]},{name:"延安市",code:"610600",sub:[{name:"市辖区",code:"610601"},{name:"宝塔区",code:"610602"},{name:"延长县",code:"610621"},{name:"延川县",code:"610622"},{name:"子长县",code:"610623"},{name:"安塞县",code:"610624"},{name:"志丹县",code:"610625"},{name:"吴起县",code:"610626"},{name:"甘泉县",code:"610627"},{name:"富县",code:"610628"},{name:"洛川县",code:"610629"},{name:"宜川县",code:"610630"},{name:"黄龙县",code:"610631"},{name:"黄陵县",code:"610632"}]},{name:"汉中市",code:"610700",sub:[{name:"市辖区",code:"610701"},{name:"汉台区",code:"610702"},{name:"南郑县",code:"610721"},{name:"城固县",code:"610722"},{name:"洋县",code:"610723"},{name:"西乡县",code:"610724"},{name:"勉县",code:"610725"},{name:"宁强县",code:"610726"},{name:"略阳县",code:"610727"},{name:"镇巴县",code:"610728"},{name:"留坝县",code:"610729"},{name:"佛坪县",code:"610730"}]},{name:"榆林市",code:"610800",sub:[{name:"市辖区",code:"610801"},{name:"榆阳区",code:"610802"},{name:"神木县",code:"610821"},{name:"府谷县",code:"610822"},{name:"横山县",code:"610823"},{name:"靖边县",code:"610824"},{name:"定边县",code:"610825"},{name:"绥德县",code:"610826"},{name:"米脂县",code:"610827"},{name:"佳县",code:"610828"},{name:"吴堡县",code:"610829"},{name:"清涧县",code:"610830"},{name:"子洲县",code:"610831"}]},{name:"安康市",code:"610900",sub:[{name:"市辖区",code:"610901"},{name:"汉阴县",code:"610921"},{name:"石泉县",code:"610922"},{name:"宁陕县",code:"610923"},{name:"紫阳县",code:"610924"},{name:"岚皋县",code:"610925"},{name:"平利县",code:"610926"},{name:"镇坪县",code:"610927"},{name:"旬阳县",code:"610928"},{name:"白河县",code:"610929"}]},{name:"商洛市",code:"611000",sub:[{name:"市辖区",code:"611001"},{name:"商州区",code:"611002"},{name:"洛南县",code:"611021"},{name:"丹凤县",code:"611022"},{name:"商南县",code:"611023"},{name:"山阳县",code:"611024"},{name:"镇安县",code:"611025"},{name:"柞水县",code:"611026"}]}]},{name:"甘肃省",code:"620000",sub:[{name:"兰州市",code:"620100",sub:[{name:"市辖区",code:"620101"},{name:"城关区",code:"620102"},{name:"七里河区",code:"620103"},{name:"西固区",code:"620104"},{name:"安宁区",code:"620105"},{name:"红古区",code:"620111"},{name:"永登县",code:"620121"},{name:"皋兰县",code:"620122"},{name:"榆中县",code:"620123"}]},{name:"嘉峪关市",code:"620200",sub:[{name:"市辖区",code:"620201"}]},{name:"金昌市",code:"620300",sub:[{name:"市辖区",code:"620301"},{name:"金川区",code:"620302"},{name:"永昌县",code:"620321"}]},{name:"白银市",code:"620400",sub:[{name:"市辖区",code:"620401"},{name:"白银区",code:"620402"},{name:"平川区",code:"620403"},{name:"靖远县",code:"620421"},{name:"会宁县",code:"620422"},{name:"景泰县",code:"620423"}]},{name:"天水市",code:"620500",sub:[{name:"市辖区",code:"620501"},{name:"秦州区",code:"620502"},{name:"麦积区",code:"620503"},{name:"清水县",code:"620521"},{name:"秦安县",code:"620522"},{name:"甘谷县",code:"620523"},{name:"武山县",code:"620524"},{name:"张家川回族自治县",code:"620525"}]},{name:"武威市",code:"620600",sub:[{name:"市辖区",code:"620601"},{name:"凉州区",code:"620602"},{name:"民勤县",code:"620621"},{name:"古浪县",code:"620622"},{name:"天祝藏族自治县",code:"620623"}]},{name:"张掖市",code:"620700",sub:[{name:"市辖区",code:"620701"},{name:"甘州区",code:"620702"},{name:"肃南裕固族自治县",code:"620721"},{name:"民乐县",code:"620722"},{name:"临泽县",code:"620723"},{name:"高台县",code:"620724"},{name:"山丹县",code:"620725"}]},{name:"平凉市",code:"620800",sub:[{name:"市辖区",code:"620801"},{name:"崆峒区",code:"620802"},{name:"泾川县",code:"620821"},{name:"灵台县",code:"620822"},{name:"崇信县",code:"620823"},{name:"华亭县",code:"620824"},{name:"庄浪县",code:"620825"},{name:"静宁县",code:"620826"}]},{name:"酒泉市",code:"620900",sub:[{name:"市辖区",code:"620901"},{name:"肃州区",code:"620902"},{name:"金塔县",code:"620921"},{name:"瓜州县",code:"620922"},{name:"肃北蒙古族自治县",code:"620923"},{name:"阿克塞哈萨克族自治县",code:"620924"},{name:"玉门市",code:"620981"},{name:"敦煌市",code:"620982"}]},{name:"庆阳市",code:"621000",sub:[{name:"市辖区",code:"621001"},{name:"西峰区",code:"621002"},{name:"庆城县",code:"621021"},{name:"环县",code:"621022"},{name:"华池县",code:"621023"},{name:"合水县",code:"621024"},{name:"正宁县",code:"621025"},{name:"宁县",code:"621026"},{name:"镇原县",code:"621027"}]},{name:"定西市",code:"621100",sub:[{name:"市辖区",code:"621101"},{name:"安定区",code:"621102"},{name:"通渭县",code:"621121"},{name:"陇西县",code:"621122"},{name:"渭源县",code:"621123"},{name:"临洮县",code:"621124"},{name:"漳县",code:"621125"},{name:"岷县",code:"621126"}]},{name:"陇南市",code:"621200",sub:[{name:"市辖区",code:"621201"},{name:"武都区",code:"621202"},{name:"成县",code:"621221"},{name:"文县",code:"621222"},{name:"宕昌县",code:"621223"},{name:"康县",code:"621224"},{name:"西和县",code:"621225"},{name:"礼县",code:"621226"},{name:"徽县",code:"621227"},{name:"两当县",code:"621228"}]},{name:"临夏回族自治州",code:"622900",sub:[{name:"临夏市",code:"622901"},{name:"临夏县",code:"622921"},{name:"康乐县",code:"622922"},{name:"永靖县",code:"622923"},{name:"广河县",code:"622924"},{name:"和政县",code:"622925"},{name:"东乡族自治县",code:"622926"},{name:"积石山保安族东乡族撒拉族自治县",code:"622927"}]},{name:"甘南藏族自治州",code:"623000",sub:[{name:"合作市",code:"623001"},{name:"临潭县",code:"623021"},{name:"卓尼县",code:"623022"},{name:"舟曲县",code:"623023"},{name:"迭部县",code:"623024"},{name:"玛曲县",code:"623025"},{name:"碌曲县",code:"623026"},{name:"夏河县",code:"623027"}]}]},{name:"青海省",code:"630000",sub:[{name:"西宁市",code:"630100",sub:[{name:"市辖区",code:"630101"},{name:"城东区",code:"630102"},{name:"城中区",code:"630103"},{name:"城西区",code:"630104"},{name:"城北区",code:"630105"},{name:"大通回族土族自治县",code:"630121"},{name:"湟中县",code:"630122"},{name:"湟源县",code:"630123"}]},{name:"海东市",code:"630200",sub:[{name:"市辖区",code:"630201"},{name:"乐都区",code:"630202"},{name:"平安县",code:"630221"},{name:"民和回族土族自治县",code:"630222"},{name:"互助土族自治县",code:"630223"},{name:"化隆回族自治县",code:"630224"},{name:"循化撒拉族自治县",code:"630225"}]},{name:"海北藏族自治州",code:"632200",sub:[{name:"门源回族自治县",code:"632221"},{name:"祁连县",code:"632222"},{name:"海晏县",code:"632223"},{name:"刚察县",code:"632224"}]},{name:"黄南藏族自治州",code:"632300",sub:[{name:"同仁县",code:"632321"},{name:"尖扎县",code:"632322"},{name:"泽库县",code:"632323"},{name:"河南蒙古族自治县",code:"632324"}]},{name:"海南藏族自治州",code:"632500",sub:[{name:"共和县",code:"632521"},{name:"同德县",code:"632522"},{name:"贵德县",code:"632523"},{name:"兴海县",code:"632524"},{name:"贵南县",code:"632525"}]},{name:"果洛藏族自治州",code:"632600",sub:[{name:"玛沁县",code:"632621"},{name:"班玛县",code:"632622"},{name:"甘德县",code:"632623"},{name:"达日县",code:"632624"},{name:"久治县",code:"632625"},{name:"玛多县",code:"632626"}]},{name:"玉树藏族自治州",code:"632700",sub:[{name:"玉树市",code:"632701"},{name:"杂多县",code:"632722"},{name:"称多县",code:"632723"},{name:"治多县",code:"632724"},{name:"囊谦县",code:"632725"},{name:"曲麻莱县",code:"632726"}]},{name:"海西蒙古族藏族自治州",code:"632800",sub:[{name:"格尔木市",code:"632801"},{name:"德令哈市",code:"632802"},{name:"乌兰县",code:"632821"},{name:"都兰县",code:"632822"},{name:"天峻县",code:"632823"}]}]},{name:"宁夏回族自治区",code:"640000",sub:[{name:"银川市",code:"640100",sub:[{name:"市辖区",code:"640101"},{name:"兴庆区",code:"640104"},{name:"西夏区",code:"640105"},{name:"金凤区",code:"640106"},{name:"永宁县",code:"640121"},{name:"贺兰县",code:"640122"},{name:"灵武市",code:"640181"}]},{name:"石嘴山市",code:"640200",sub:[{name:"市辖区",code:"640201"},{name:"大武口区",code:"640202"},{name:"惠农区",code:"640205"},{name:"平罗县",code:"640221"}]},{name:"吴忠市",code:"640300",sub:[{name:"市辖区",code:"640301"},{name:"利通区",code:"640302"},{name:"红寺堡区",code:"640303"},{name:"盐池县",code:"640323"},{name:"同心县",code:"640324"},{name:"青铜峡市",code:"640381"}]},{name:"固原市",code:"640400",sub:[{name:"市辖区",code:"640401"},{name:"原州区",code:"640402"},{name:"西吉县",code:"640422"},{name:"隆德县",code:"640423"},{name:"泾源县",code:"640424"},{name:"彭阳县",code:"640425"}]},{name:"中卫市",code:"640500",sub:[{name:"市辖区",code:"640501"},{name:"沙坡头区",code:"640502"},{name:"中宁县",code:"640521"},{name:"海原县",code:"640522"}]}]},{name:"新疆维吾尔自治区",code:"650000",sub:[{name:"乌鲁木齐市",code:"650100",sub:[{name:"市辖区",code:"650101"},{name:"天山区",code:"650102"},{name:"沙依巴克区",code:"650103"},{name:"新市区",code:"650104"},{name:"水磨沟区",code:"650105"},{name:"头屯河区",code:"650106"},{name:"达坂城区",code:"650107"},{name:"米东区",code:"650109"},{name:"乌鲁木齐县",code:"650121"}]},{name:"克拉玛依市",code:"650200",sub:[{name:"市辖区",code:"650201"},{name:"独山子区",code:"650202"},{name:"克拉玛依区",code:"650203"},{name:"白碱滩区",code:"650204"},{name:"乌尔禾区",code:"650205"}]},{name:"吐鲁番地区",code:"652100",sub:[{name:"吐鲁番市",code:"652101"},{name:"鄯善县",code:"652122"},{name:"托克逊县",code:"652123"}]},{name:"哈密地区",code:"652200",sub:[{name:"哈密市",code:"652201"},{name:"巴里坤哈萨克自治县",code:"652222"},{name:"伊吾县",code:"652223"}]},{name:"昌吉回族自治州",code:"652300",sub:[{name:"昌吉市",code:"652301"},{name:"阜康市",code:"652302"},{name:"呼图壁县",code:"652323"},{name:"玛纳斯县",code:"652324"},{name:"奇台县",code:"652325"},{name:"吉木萨尔县",code:"652327"},{name:"木垒哈萨克自治县",code:"652328"}]},{name:"博尔塔拉蒙古自治州",code:"652700",sub:[{name:"博乐市",code:"652701"},{name:"阿拉山口市",code:"652702"},{name:"精河县",code:"652722"},{name:"温泉县",code:"652723"}]},{name:"巴音郭楞蒙古自治州",code:"652800",sub:[{name:"库尔勒市",code:"652801"},{name:"轮台县",code:"652822"},{name:"尉犁县",code:"652823"},{name:"若羌县",code:"652824"},{name:"且末县",code:"652825"},{name:"焉耆回族自治县",code:"652826"},{name:"和静县",code:"652827"},{name:"和硕县",code:"652828"},{name:"博湖县",code:"652829"}]},{name:"阿克苏地区",code:"652900",
+sub:[{name:"阿克苏市",code:"652901"},{name:"温宿县",code:"652922"},{name:"库车县",code:"652923"},{name:"沙雅县",code:"652924"},{name:"新和县",code:"652925"},{name:"拜城县",code:"652926"},{name:"乌什县",code:"652927"},{name:"阿瓦提县",code:"652928"},{name:"柯坪县",code:"652929"}]},{name:"克孜勒苏柯尔克孜自治州",code:"653000",sub:[{name:"阿图什市",code:"653001"},{name:"阿克陶县",code:"653022"},{name:"阿合奇县",code:"653023"},{name:"乌恰县",code:"653024"}]},{name:"喀什地区",code:"653100",sub:[{name:"喀什市",code:"653101"},{name:"疏附县",code:"653121"},{name:"疏勒县",code:"653122"},{name:"英吉沙县",code:"653123"},{name:"泽普县",code:"653124"},{name:"莎车县",code:"653125"},{name:"叶城县",code:"653126"},{name:"麦盖提县",code:"653127"},{name:"岳普湖县",code:"653128"},{name:"伽师县",code:"653129"},{name:"巴楚县",code:"653130"},{name:"塔什库尔干塔吉克自治县",code:"653131"}]},{name:"和田地区",code:"653200",sub:[{name:"和田市",code:"653201"},{name:"和田县",code:"653221"},{name:"墨玉县",code:"653222"},{name:"皮山县",code:"653223"},{name:"洛浦县",code:"653224"},{name:"策勒县",code:"653225"},{name:"于田县",code:"653226"},{name:"民丰县",code:"653227"}]},{name:"伊犁哈萨克自治州",code:"654000",sub:[{name:"伊宁市",code:"654002"},{name:"奎屯市",code:"654003"},{name:"霍尔果斯市",code:"654004"},{name:"伊宁县",code:"654021"},{name:"察布查尔锡伯自治县",code:"654022"},{name:"霍城县",code:"654023"},{name:"巩留县",code:"654024"},{name:"新源县",code:"654025"},{name:"昭苏县",code:"654026"},{name:"特克斯县",code:"654027"},{name:"尼勒克县",code:"654028"},{name:"塔城地区",code:"654200"},{name:"塔城市",code:"654201"},{name:"乌苏市",code:"654202"},{name:"额敏县",code:"654221"},{name:"沙湾县",code:"654223"},{name:"托里县",code:"654224"},{name:"裕民县",code:"654225"},{name:"和布克赛尔蒙古自治县",code:"654226"},{name:"阿勒泰地区",code:"654300"},{name:"阿勒泰市",code:"654301"},{name:"布尔津县",code:"654321"},{name:"富蕴县",code:"654322"},{name:"福海县",code:"654323"},{name:"哈巴河县",code:"654324"},{name:"青河县",code:"654325"},{name:"吉木乃县",code:"654326"}]},{name:"自治区直辖县级行政区划",code:"659000",sub:[{name:"石河子市",code:"659001"},{name:"阿拉尔市",code:"659002"},{name:"图木舒克市",code:"659003"},{name:"五家渠市",code:"659004"},{name:"北屯市",code:"659005"},{name:"铁门关市",code:"659006"},{name:"双河市",code:"659007"}]}]},{name:"台湾省",code:"710000",sub:[{name:"台北市",code:"710100",sub:[{name:"松山区",code:"710101"},{name:"信义区",code:"710102"},{name:"大安区",code:"710103"},{name:"中山区",code:"710104"},{name:"中正区",code:"710105"},{name:"大同区",code:"710106"},{name:"万华区",code:"710107"},{name:"文山区",code:"710108"},{name:"南港区",code:"710109"},{name:"内湖区",code:"710110"},{name:"士林区",code:"710111"},{name:"北投区",code:"710112"}]},{name:"高雄市",code:"710200",sub:[{name:"盐埕区",code:"710201"},{name:"鼓山区",code:"710202"},{name:"左营区",code:"710203"},{name:"楠梓区",code:"710204"},{name:"三民区",code:"710205"},{name:"新兴区",code:"710206"},{name:"前金区",code:"710207"},{name:"苓雅区",code:"710208"},{name:"前镇区",code:"710209"},{name:"旗津区",code:"710210"},{name:"小港区",code:"710211"},{name:"凤山区",code:"710212"},{name:"林园区",code:"710213"},{name:"大寮区",code:"710214"},{name:"大树区",code:"710215"},{name:"大社区",code:"710216"},{name:"仁武区",code:"710217"},{name:"鸟松区",code:"710218"},{name:"冈山区",code:"710219"},{name:"桥头区",code:"710220"},{name:"燕巢区",code:"710221"},{name:"田寮区",code:"710222"},{name:"阿莲区",code:"710223"},{name:"路竹区",code:"710224"},{name:"湖内区",code:"710225"},{name:"茄萣区",code:"710226"},{name:"永安区",code:"710227"},{name:"弥陀区",code:"710228"},{name:"梓官区",code:"710229"},{name:"旗山区",code:"710230"},{name:"美浓区",code:"710231"},{name:"六龟区",code:"710232"},{name:"甲仙区",code:"710233"},{name:"杉林区",code:"710234"},{name:"内门区",code:"710235"},{name:"茂林区",code:"710236"},{name:"桃源区",code:"710237"},{name:"那玛夏区",code:"710238"}]},{name:"基隆市",code:"710300",sub:[{name:"中正区",code:"710301"},{name:"七堵区",code:"710302"},{name:"暖暖区",code:"710303"},{name:"仁爱区",code:"710304"},{name:"中山区",code:"710305"},{name:"安乐区",code:"710306"},{name:"信义区",code:"710307"}]},{name:"台中市",code:"710400",sub:[{name:"中区",code:"710401"},{name:"东区",code:"710402"},{name:"南区",code:"710403"},{name:"西区",code:"710404"},{name:"北区",code:"710405"},{name:"西屯区",code:"710406"},{name:"南屯区",code:"710407"},{name:"北屯区",code:"710408"},{name:"丰原区",code:"710409"},{name:"东势区",code:"710410"},{name:"大甲区",code:"710411"},{name:"清水区",code:"710412"},{name:"沙鹿区",code:"710413"},{name:"梧栖区",code:"710414"},{name:"后里区",code:"710415"},{name:"神冈区",code:"710416"},{name:"潭子区",code:"710417"},{name:"大雅区",code:"710418"},{name:"新社区",code:"710419"},{name:"石冈区",code:"710420"},{name:"外埔区",code:"710421"},{name:"大安区",code:"710422"},{name:"乌日区",code:"710423"},{name:"大肚区",code:"710424"},{name:"龙井区",code:"710425"},{name:"雾峰区",code:"710426"},{name:"太平区",code:"710427"},{name:"大里区",code:"710428"},{name:"和平区",code:"710429"}]},{name:"台南市",code:"710500",sub:[{name:"东区",code:"710501"},{name:"南区",code:"710502"},{name:"北区",code:"710504"},{name:"安南区",code:"710506"},{name:"安平区",code:"710507"},{name:"中西区",code:"710508"},{name:"新营区",code:"710509"},{name:"盐水区",code:"710510"},{name:"白河区",code:"710511"},{name:"柳营区",code:"710512"},{name:"后壁区",code:"710513"},{name:"东山区",code:"710514"},{name:"麻豆区",code:"710515"},{name:"下营区",code:"710516"},{name:"六甲区",code:"710517"},{name:"官田区",code:"710518"},{name:"大内区",code:"710519"},{name:"佳里区",code:"710520"},{name:"学甲区",code:"710521"},{name:"西港区",code:"710522"},{name:"七股区",code:"710523"},{name:"将军区",code:"710524"},{name:"北门区",code:"710525"},{name:"新化区",code:"710526"},{name:"善化区",code:"710527"},{name:"新市区",code:"710528"},{name:"安定区",code:"710529"},{name:"山上区",code:"710530"},{name:"玉井区",code:"710531"},{name:"楠西区",code:"710532"},{name:"南化区",code:"710533"},{name:"左镇区",code:"710534"},{name:"仁德区",code:"710535"},{name:"归仁区",code:"710536"},{name:"关庙区",code:"710537"},{name:"龙崎区",code:"710538"},{name:"永康区",code:"710539"}]},{name:"新竹市",code:"710600",sub:[{name:"东区",code:"710601"},{name:"北区",code:"710602"},{name:"香山区",code:"710603"}]},{name:"嘉义市",code:"710700",sub:[{name:"东区",code:"710701"},{name:"西区",code:"710702"}]},{name:"新北市",code:"710800",sub:[{name:"板桥区",code:"710801"},{name:"三重区",code:"710802"},{name:"中和区",code:"710803"},{name:"永和区",code:"710804"},{name:"新庄区",code:"710805"},{name:"新店区",code:"710806"},{name:"树林区",code:"710807"},{name:"莺歌区",code:"710808"},{name:"三峡区",code:"710809"},{name:"淡水区",code:"710810"},{name:"汐止区",code:"710811"},{name:"瑞芳区",code:"710812"},{name:"土城区",code:"710813"},{name:"芦洲区",code:"710814"},{name:"五股区",code:"710815"},{name:"泰山区",code:"710816"},{name:"林口区",code:"710817"},{name:"深坑区",code:"710818"},{name:"石碇区",code:"710819"},{name:"坪林区",code:"710820"},{name:"三芝区",code:"710821"},{name:"石门区",code:"710822"},{name:"八里区",code:"710823"},{name:"平溪区",code:"710824"},{name:"双溪区",code:"710825"},{name:"贡寮区",code:"710826"},{name:"金山区",code:"710827"},{name:"万里区",code:"710828"},{name:"乌来区",code:"710829"}]},{name:"宜兰县",code:"712200",sub:[{name:"宜兰市",code:"712201"},{name:"罗东镇",code:"712221"},{name:"苏澳镇",code:"712222"},{name:"头城镇",code:"712223"},{name:"礁溪乡",code:"712224"},{name:"壮围乡",code:"712225"},{name:"员山乡",code:"712226"},{name:"冬山乡",code:"712227"},{name:"五结乡",code:"712228"},{name:"三星乡",code:"712229"},{name:"大同乡",code:"712230"},{name:"南澳乡",code:"712231"}]},{name:"桃园县",code:"712300",sub:[{name:"桃园市",code:"712301"},{name:"中坜市",code:"712302"},{name:"平镇市",code:"712303"},{name:"八德市",code:"712304"},{name:"杨梅市",code:"712305"},{name:"大溪镇",code:"712321"},{name:"芦竹乡",code:"712323"},{name:"大园乡",code:"712324"},{name:"龟山乡",code:"712325"},{name:"龙潭乡",code:"712327"},{name:"新屋乡",code:"712329"},{name:"观音乡",code:"712330"},{name:"复兴乡",code:"712331"}]},{name:"新竹县",code:"712400",sub:[{name:"竹北市",code:"712401"},{name:"竹东镇",code:"712421"},{name:"新埔镇",code:"712422"},{name:"关西镇",code:"712423"},{name:"湖口乡",code:"712424"},{name:"新丰乡",code:"712425"},{name:"芎林乡",code:"712426"},{name:"橫山乡",code:"712427"},{name:"北埔乡",code:"712428"},{name:"宝山乡",code:"712429"},{name:"峨眉乡",code:"712430"},{name:"尖石乡",code:"712431"},{name:"五峰乡",code:"712432"}]},{name:"苗栗县",code:"712500",sub:[{name:"苗栗市",code:"712501"},{name:"苑里镇",code:"712521"},{name:"通霄镇",code:"712522"},{name:"竹南镇",code:"712523"},{name:"头份镇",code:"712524"},{name:"后龙镇",code:"712525"},{name:"卓兰镇",code:"712526"},{name:"大湖乡",code:"712527"},{name:"公馆乡",code:"712528"},{name:"铜锣乡",code:"712529"},{name:"南庄乡",code:"712530"},{name:"头屋乡",code:"712531"},{name:"三义乡",code:"712532"},{name:"西湖乡",code:"712533"},{name:"造桥乡",code:"712534"},{name:"三湾乡",code:"712535"},{name:"狮潭乡",code:"712536"},{name:"泰安乡",code:"712537"}]},{name:"彰化县",code:"712700",sub:[{name:"彰化市",code:"712701"},{name:"鹿港镇",code:"712721"},{name:"和美镇",code:"712722"},{name:"线西乡",code:"712723"},{name:"伸港乡",code:"712724"},{name:"福兴乡",code:"712725"},{name:"秀水乡",code:"712726"},{name:"花坛乡",code:"712727"},{name:"芬园乡",code:"712728"},{name:"员林镇",code:"712729"},{name:"溪湖镇",code:"712730"},{name:"田中镇",code:"712731"},{name:"大村乡",code:"712732"},{name:"埔盐乡",code:"712733"},{name:"埔心乡",code:"712734"},{name:"永靖乡",code:"712735"},{name:"社头乡",code:"712736"},{name:"二水乡",code:"712737"},{name:"北斗镇",code:"712738"},{name:"二林镇",code:"712739"},{name:"田尾乡",code:"712740"},{name:"埤头乡",code:"712741"},{name:"芳苑乡",code:"712742"},{name:"大城乡",code:"712743"},{name:"竹塘乡",code:"712744"},{name:"溪州乡",code:"712745"}]},{name:"南投县",code:"712800",sub:[{name:"南投市",code:"712801"},{name:"埔里镇",code:"712821"},{name:"草屯镇",code:"712822"},{name:"竹山镇",code:"712823"},{name:"集集镇",code:"712824"},{name:"名间乡",code:"712825"},{name:"鹿谷乡",code:"712826"},{name:"中寮乡",code:"712827"},{name:"鱼池乡",code:"712828"},{name:"国姓乡",code:"712829"},{name:"水里乡",code:"712830"},{name:"信义乡",code:"712831"},{name:"仁爱乡",code:"712832"}]},{name:"云林县",code:"712900",sub:[{name:"斗六市",code:"712901"},{name:"斗南镇",code:"712921"},{name:"虎尾镇",code:"712922"},{name:"西螺镇",code:"712923"},{name:"土库镇",code:"712924"},{name:"北港镇",code:"712925"},{name:"古坑乡",code:"712926"},{name:"大埤乡",code:"712927"},{name:"莿桐乡",code:"712928"},{name:"林内乡",code:"712929"},{name:"二仑乡",code:"712930"},{name:"仑背乡",code:"712931"},{name:"麦寮乡",code:"712932"},{name:"东势乡",code:"712933"},{name:"褒忠乡",code:"712934"},{name:"台西乡",code:"712935"},{name:"元长乡",code:"712936"},{name:"四湖乡",code:"712937"},{name:"口湖乡",code:"712938"},{name:"水林乡",code:"712939"}]},{name:"嘉义县",code:"713000",sub:[{name:"太保市",code:"713001"},{name:"朴子市",code:"713002"},{name:"布袋镇",code:"713023"},{name:"大林镇",code:"713024"},{name:"民雄乡",code:"713025"},{name:"溪口乡",code:"713026"},{name:"新港乡",code:"713027"},{name:"六脚乡",code:"713028"},{name:"东石乡",code:"713029"},{name:"义竹乡",code:"713030"},{name:"鹿草乡",code:"713031"},{name:"水上乡",code:"713032"},{name:"中埔乡",code:"713033"},{name:"竹崎乡",code:"713034"},{name:"梅山乡",code:"713035"},{name:"番路乡",code:"713036"},{name:"大埔乡",code:"713037"},{name:"阿里山乡",code:"713038"}]},{name:"屏东县",code:"713300",sub:[{name:"屏东市",code:"713301"},{name:"潮州镇",code:"713321"},{name:"东港镇",code:"713322"},{name:"恒春镇",code:"713323"},{name:"万丹乡",code:"713324"},{name:"长治乡",code:"713325"},{name:"麟洛乡",code:"713326"},{name:"九如乡",code:"713327"},{name:"里港乡",code:"713328"},{name:"盐埔乡",code:"713329"},{name:"高树乡",code:"713330"},{name:"万峦乡",code:"713331"},{name:"内埔乡",code:"713332"},{name:"竹田乡",code:"713333"},{name:"新埤乡",code:"713334"},{name:"枋寮乡",code:"713335"},{name:"新园乡",code:"713336"},{name:"崁顶乡",code:"713337"},{name:"林边乡",code:"713338"},{name:"南州乡",code:"713339"},{name:"佳冬乡",code:"713340"},{name:"琉球乡",code:"713341"},{name:"车城乡",code:"713342"},{name:"满州乡",code:"713343"},{name:"枋山乡",code:"713344"},{name:"三地门乡",code:"713345"},{name:"雾台乡",code:"713346"},{name:"玛家乡",code:"713347"},{name:"泰武乡",code:"713348"},{name:"来义乡",code:"713349"},{name:"春日乡",code:"713350"},{name:"狮子乡",code:"713351"},{name:"牡丹乡",code:"713352"}]},{name:"台东县",code:"713400",sub:[{name:"台东市",code:"713401"},{name:"成功镇",code:"713421"},{name:"关山镇",code:"713422"},{name:"卑南乡",code:"713423"},{name:"鹿野乡",code:"713424"},{name:"池上乡",code:"713425"},{name:"东河乡",code:"713426"},{name:"长滨乡",code:"713427"},{name:"太麻里乡",code:"713428"},{name:"大武乡",code:"713429"},{name:"绿岛乡",code:"713430"},{name:"海端乡",code:"713431"},{name:"延平乡",code:"713432"},{name:"金峰乡",code:"713433"},{name:"达仁乡",code:"713434"},{name:"兰屿乡",code:"713435"}]},{name:"花莲县",code:"713500",sub:[{name:"花莲市",code:"713501"},{name:"凤林镇",code:"713521"},{name:"玉里镇",code:"713522"},{name:"新城乡",code:"713523"},{name:"吉安乡",code:"713524"},{name:"寿丰乡",code:"713525"},{name:"光复乡",code:"713526"},{name:"丰滨乡",code:"713527"},{name:"瑞穗乡",code:"713528"},{name:"富里乡",code:"713529"},{name:"秀林乡",code:"713530"},{name:"万荣乡",code:"713531"},{name:"卓溪乡",code:"713532"}]},{name:"澎湖县",code:"713600",sub:[{name:"马公市",code:"713601"},{name:"湖西乡",code:"713621"},{name:"白沙乡",code:"713622"},{name:"西屿乡",code:"713623"},{name:"望安乡",code:"713624"},{name:"七美乡",code:"713625"}]}]},{name:"香港特别行政区",code:"810000",sub:[{name:"香港岛",code:"810100",sub:[{name:"中西区",code:"810101"},{name:"湾仔区",code:"810102"},{name:"东区",code:"810103"},{name:"南区",code:"810104"}]},{name:"九龙",code:"810200",sub:[{name:"油尖旺区",code:"810201"},{name:"深水埗区",code:"810202"},{name:"九龙城区",code:"810203"},{name:"黄大仙区",code:"810204"},{name:"观塘区",code:"810205"}]},{name:"新界",code:"810300",sub:[{name:"荃湾区",code:"810301"},{name:"屯门区",code:"810302"},{name:"元朗区",code:"810303"},{name:"北区",code:"810304"},{name:"大埔区",code:"810305"},{name:"西贡区",code:"810306"},{name:"沙田区",code:"810307"},{name:"葵青区",code:"810308"},{name:"离岛区",code:"810309"}]}]},{name:"澳门特别行政区",code:"820000",sub:[{name:"澳门半岛",code:"820100",sub:[{name:"花地玛堂区",code:"820101"},{name:"圣安多尼堂区",code:"820102"},{name:"大堂区",code:"820103"},{name:"望德堂区",code:"820104"},{name:"风顺堂区",code:"820105"}]},{name:"氹仔岛",code:"820200",sub:[{name:"嘉模堂区",code:"820201"}]},{name:"路环岛",code:"820300",sub:[{name:"圣方济各堂区",code:"820301"}]}]}]}($),+function(e){"use strict";var n,a=e.rawCitiesData,c=function(e){for(var n=[],a=0;a<e.length;a++){var c=e[a];/^请选择|市辖区/.test(c.name)||n.push(c)}return n.length?n:[]},o=function(e){return e.sub?c(e.sub):[{name:"",code:e.code}]},m=function(e){for(var n=0;n<a.length;n++)if(a[n].code===e||a[n].name===e)return o(a[n]);return[]},d=function(e,n){for(var c=0;c<a.length;c++)if(a[c].code===e||a[c].name===e)for(var m=0;m<a[c].sub.length;m++)if(a[c].sub[m].code===n||a[c].sub[m].name===n)return o(a[c].sub[m])},u=function(e){var n,c,o=a[0],m=e.split(" ");return a.map(function(e){e.name===m[0]&&(o=e)}),o.sub.map(function(e){e.name===m[1]&&(n=e)}),m[2]&&n.sub.map(function(e){e.name===m[2]&&(c=e)}),c?[o.code,n.code,c.code]:[o.code,n.code]};e.fn.cityPicker=function(c){return c=e.extend({},n,c),this.each(function(){var n=this,s=a.map(function(e){return e.name}),b=a.map(function(e){return e.code}),t=o(a[0]),r=t.map(function(e){return e.name}),i=t.map(function(e){return e.code}),l=o(a[0].sub[0]),f=l.map(function(e){return e.name}),p=l.map(function(e){return e.code}),v=s[0],h=r[0],V=f[0],y=[{displayValues:s,values:b,cssClass:"col-province"},{displayValues:r,values:i,cssClass:"col-city"}];c.showDistrict&&y.push({values:p,displayValues:f,cssClass:"col-district"});var g={cssClass:"city-picker",rotateEffect:!1,formatValue:function(e,n,a){return a.join(" ")},onChange:function(a,o,u){var s,b=a.cols[0].displayValue;if(b!==v){var t=m(b);s=t[0].name;var r=d(b,s);return a.cols[1].replaceValues(t.map(function(e){return e.code}),t.map(function(e){return e.name})),c.showDistrict&&a.cols[2].replaceValues(r.map(function(e){return e.code}),r.map(function(e){return e.name})),v=b,h=s,a.updateValue(),!1}if(c.showDistrict&&(s=a.cols[1].displayValue,s!==h)){var i=d(b,s);return a.cols[2].replaceValues(i.map(function(e){return e.code}),i.map(function(e){return e.name})),h=s,a.updateValue(),!1}var l=o[o.length-1]?o.length-1:o.length-2;e(n).attr("data-code",o[l]),e(n).attr("data-codes",o.join(",")),c.onChange&&c.onChange.call(n,a,o,u)},cols:y};if(this){var C=e.extend({},c,g),w=e(this).val();if(w||(w="北京 北京市 东城区"),v=w.split(" ")[0],h=w.split(" ")[1],V=w.split(" ")[2],w){if(C.value=u(w),C.value[0]){var D=m(C.value[0]);C.cols[1].values=D.map(function(e){return e.code}),C.cols[1].displayValues=D.map(function(e){return e.name})}if(C.value[1]){if(c.showDistrict){var k=d(C.value[0],C.value[1]);C.cols[2].values=k.map(function(e){return e.code}),C.cols[2].displayValues=k.map(function(e){return e.name})}}else if(c.showDistrict){var k=d(C.value[0],C.cols[1].values[0]);C.cols[2].values=k.map(function(e){return e.code}),C.cols[2].displayValues=k.map(function(e){return e.name})}}e(this).picker(C)}})},n=e.fn.cityPicker.prototype.defaults={showDistrict:!0}}($);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/jquery-2.1.4.js b/platforms/android/app/src/main/assets/www/js/lib/jquery-2.1.4.js
new file mode 100644
index 0000000..eed1777
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/jquery-2.1.4.js
@@ -0,0 +1,9210 @@
+/*!
+ * jQuery JavaScript Library v2.1.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:01Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper `window`
+		// is present, execute the factory and get jQuery.
+		// For environments that do not have a `window` with a `document`
+		// (such as Node.js), expose a factory as module.exports.
+		// This accentuates the need for the creation of a real `window`.
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info.
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//
+
+var arr = [];
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	version = "2.1.4",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android<4.1
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return just the one element from the set
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return all the elements in a clean array
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ) );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	eq: function( i ) {
+		var len = this.length,
+			j = +i + ( i < 0 ? len : 0 );
+		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: arr.sort,
+	splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+
+		// Skip the boolean and the target
+		target = arguments[ i ] || {};
+		i++;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// Extend jQuery itself if only one argument is passed
+	if ( i === length ) {
+		target = this;
+		i--;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	// Unique for each copy of jQuery on the page
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+	// Assume jQuery is ready without the ready module
+	isReady: true,
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	noop: function() {},
+
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray,
+
+	isWindow: function( obj ) {
+		return obj != null && obj === obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		// adding 1 corrects loss of precision from parseFloat (#15100)
+		return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
+	},
+
+	isPlainObject: function( obj ) {
+		// Not plain objects:
+		// - Any object or value whose internal [[Class]] property is not "[object Object]"
+		// - DOM nodes
+		// - window
+		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		if ( obj.constructor &&
+				!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
+			return false;
+		}
+
+		// If the function hasn't returned already, we're confident that
+		// |obj| is a plain object, created by {} or constructed with new Object
+		return true;
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+		// Support: Android<4.0, iOS<6 (functionish RegExp)
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	globalEval: function( code ) {
+		var script,
+			indirect = eval;
+
+		code = jQuery.trim( code );
+
+		if ( code ) {
+			// If the code includes a valid, prologue position
+			// strict mode pragma, execute code by injecting a
+			// script tag into the document.
+			if ( code.indexOf("use strict") === 1 ) {
+				script = document.createElement("script");
+				script.text = code;
+				document.head.appendChild( script ).parentNode.removeChild( script );
+			} else {
+			// Otherwise, avoid the DOM node creation, insertion
+			// and removal by using an indirect global eval
+				indirect( code );
+			}
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Support: IE9-11+
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
+
+		if ( args ) {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android<4.1
+	trim: function( text ) {
+		return text == null ?
+			"" :
+			( text + "" ).replace( rtrim, "" );
+	},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var ret = results || [];
+
+		if ( arr != null ) {
+			if ( isArraylike( Object(arr) ) ) {
+				jQuery.merge( ret,
+					typeof arr === "string" ?
+					[ arr ] : arr
+				);
+			} else {
+				push.call( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		return arr == null ? -1 : indexOf.call( arr, elem, i );
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		for ( ; j < len; j++ ) {
+			first[ i++ ] = second[ j ];
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
+			i = 0,
+			length = elems.length,
+			callbackExpect = !invert;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
+			}
+		}
+
+		return matches;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value,
+			i = 0,
+			length = elems.length,
+			isArray = isArraylike( elems ),
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( i in elems ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var tmp, args, proxy;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	now: Date.now,
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+
+	// Support: iOS 8.2 (not reproducible in simulator)
+	// `in` check used to prevent JIT error (gh-2145)
+	// hasOwn isn't used here due to false negatives
+	// regarding Nodelist length in IE
+	var length = "length" in obj && obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	if ( obj.nodeType === 1 && length ) {
+		return true;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+	support,
+	Expr,
+	getText,
+	isXML,
+	tokenize,
+	compile,
+	select,
+	outermostContext,
+	sortInput,
+	hasDuplicate,
+
+	// Local document vars
+	setDocument,
+	document,
+	docElem,
+	documentIsHTML,
+	rbuggyQSA,
+	rbuggyMatches,
+	matches,
+	contains,
+
+	// Instance-specific data
+	expando = "sizzle" + 1 * new Date(),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf as it's faster than native
+	// http://jsperf.com/thor-indexof-vs-for/5
+	indexOf = function( list, elem ) {
+		var i = 0,
+			len = list.length;
+		for ( ; i < len; i++ ) {
+			if ( list[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+	// Regular expressions
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + characterEncoding + ")(?:\\((" +
+		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+		// 1. quoted (capture 3; capture 4 or capture 5)
+		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+		// 2. simple (capture 6)
+		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+		// 3. anything else (capture 2)
+		".*" +
+		")\\)|)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rwhitespace = new RegExp( whitespace + "+", "g" ),
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+	rpseudo = new RegExp( pseudos ),
+	ridentifier = new RegExp( "^" + identifier + "$" ),
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	},
+
+	// Used for iframes
+	// See setDocument()
+	// Removing the function wrapper causes a "Permission Denied"
+	// error in IE
+	unloadHandler = function() {
+		setDocument();
+	};
+
+// Optimize for push.apply( _, NodeList )
+try {
+	push.apply(
+		(arr = slice.call( preferredDoc.childNodes )),
+		preferredDoc.childNodes
+	);
+	// Support: Android<4.0
+	// Detect silently failing push.apply
+	arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+	push = { apply: arr.length ?
+
+		// Leverage slice if possible
+		function( target, els ) {
+			push_native.apply( target, slice.call(els) );
+		} :
+
+		// Support: IE<9
+		// Otherwise append directly
+		function( target, els ) {
+			var j = target.length,
+				i = 0;
+			// Can't trust NodeList.length
+			while ( (target[j++] = els[i++]) ) {}
+			target.length = j - 1;
+		}
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	var match, elem, m, nodeType,
+		// QSA vars
+		i, groups, old, nid, newContext, newSelector;
+
+	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+		setDocument( context );
+	}
+
+	context = context || document;
+	results = results || [];
+	nodeType = context.nodeType;
+
+	if ( typeof selector !== "string" || !selector ||
+		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+		return results;
+	}
+
+	if ( !seed && documentIsHTML ) {
+
+		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document (jQuery #6963)
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, context.getElementsByTagName( selector ) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && support.getElementsByClassName ) {
+				push.apply( results, context.getElementsByClassName( m ) );
+				return results;
+			}
+		}
+
+		// QSA path
+		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+			nid = old = expando;
+			newContext = context;
+			newSelector = nodeType !== 1 && selector;
+
+			// qSA works strangely on Element-rooted queries
+			// We can work around this by specifying an extra ID on the root
+			// and working up from there (Thanks to Andrew Dupont for the technique)
+			// IE 8 doesn't work on object elements
+			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+				groups = tokenize( selector );
+
+				if ( (old = context.getAttribute("id")) ) {
+					nid = old.replace( rescape, "\\$&" );
+				} else {
+					context.setAttribute( "id", nid );
+				}
+				nid = "[id='" + nid + "'] ";
+
+				i = groups.length;
+				while ( i-- ) {
+					groups[i] = nid + toSelector( groups[i] );
+				}
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+				newSelector = groups.join(",");
+			}
+
+			if ( newSelector ) {
+				try {
+					push.apply( results,
+						newContext.querySelectorAll( newSelector )
+					);
+					return results;
+				} catch(qsaError) {
+				} finally {
+					if ( !old ) {
+						context.removeAttribute("id");
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = attrs.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare, parent,
+		doc = node ? node.ownerDocument || node : preferredDoc;
+
+	// If no document and documentElement is available, return
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Set our document
+	document = doc;
+	docElem = doc.documentElement;
+	parent = doc.defaultView;
+
+	// Support: IE>8
+	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
+	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+	// IE6-8 do not support the defaultView property so parent will be undefined
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", unloadHandler, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", unloadHandler );
+		}
+	}
+
+	/* Support tests
+	---------------------------------------------------------------------- */
+	documentIsHTML = !isXML( doc );
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties
+	// (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( doc.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Support: IE<9
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+				var m = context.getElementById( id );
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [ m ] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
+				return context.getElementsByTagName( tag );
+
+			// DocumentFragment nodes don't have gEBTN
+			} else if ( support.qsa ) {
+				return context.querySelectorAll( tag );
+			}
+		} :
+
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+				"<select id='" + expando + "-\f]' msallowcapture=''>" +
+				"<option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+				rbuggyQSA.push("~=");
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+
+			// Support: Safari 8+, iOS 8+
+			// https://bugs.webkit.org/show_bug.cgi?id=136851
+			// In-page `selector#id sibing-combinator selector` fails
+			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+				rbuggyQSA.push(".#.+[+~]");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = doc.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully does not implement inclusive descendent
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === doc ? -1 :
+				b === doc ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch (e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, outerCache, node, diff, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+							// Seek `elem` from a previously-cached index
+							outerCache = parent[ expando ] || (parent[ expando ] = {});
+							cache = outerCache[ type ] || [];
+							nodeIndex = cache[0] === dirruns && cache[1];
+							diff = cache[0] === dirruns && cache[2];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						// Use previously-cached element index if available
+						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+							diff = cache[1];
+
+						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+						} else {
+							// Use the same loop as above to seek `elem` from the start
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+									// Cache the index of each encountered element
+									if ( useCache ) {
+										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+									}
+
+									if ( node === elem ) {
+										break;
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					// Don't keep the element (issue #299)
+					input[0] = null;
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			text = text.replace( runescape, funescape );
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+			// Avoid hanging onto element (issue #299)
+			checkContext = null;
+			return ret;
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !match ) {
+			match = tokenize( selector );
+		}
+		i = match.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( match[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+		// Save selector and tokenization
+		cached.selector = selector;
+	}
+	return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		compiled = typeof selector === "function" && selector,
+		match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+	results = results || [];
+
+	// Try to minimize operations if there is no seed and only one group
+	if ( match.length === 1 ) {
+
+		// Take a shortcut and set the context if the root selector is an ID
+		tokens = match[0] = match[0].slice( 0 );
+		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+				support.getById && context.nodeType === 9 && documentIsHTML &&
+				Expr.relative[ tokens[1].type ] ) {
+
+			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+			if ( !context ) {
+				return results;
+
+			// Precompiled matchers will still verify ancestry, so step up a level
+			} else if ( compiled ) {
+				context = context.parentNode;
+			}
+
+			selector = selector.slice( tokens.shift().value.length );
+		}
+
+		// Fetch a seed set for right-to-left matching
+		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+		while ( i-- ) {
+			token = tokens[i];
+
+			// Abort if we hit a combinator
+			if ( Expr.relative[ (type = token.type) ] ) {
+				break;
+			}
+			if ( (find = Expr.find[ type ]) ) {
+				// Search, expanding context for leading sibling combinators
+				if ( (seed = find(
+					token.matches[0].replace( runescape, funescape ),
+					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+				)) ) {
+
+					// If seed is empty or no tokens remain, we can return early
+					tokens.splice( i, 1 );
+					selector = seed.length && toSelector( tokens );
+					if ( !selector ) {
+						push.apply( results, seed );
+						return results;
+					}
+
+					break;
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function if one is not provided
+	// Provide `match` to avoid retokenization if we modified the selector above
+	( compiled || compile( selector, match ) )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			len = this.length,
+			ret = [],
+			self = this;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// Option to run scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Support: Blackberry 4.6
+					// gEBID returns nodes no longer in the document (#6963)
+					if ( elem && elem.parentNode ) {
+						// Inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// Methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			truncate = until !== undefined;
+
+		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
+			if ( elem.nodeType === 1 ) {
+				if ( truncate && jQuery( elem ).is( until ) ) {
+					break;
+				}
+				matched.push( elem );
+			}
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var matched = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				matched.push( n );
+			}
+		}
+
+		return matched;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var targets = jQuery( target, this ),
+			l = targets.length;
+
+		return this.filter(function() {
+			var i = 0;
+			for ( ; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within the set
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// Index in selector
+		if ( typeof elem === "string" ) {
+			return indexOf.call( jQuery( elem ), this[ 0 ] );
+		}
+
+		// Locate the position of the desired element
+		return indexOf.call( this,
+
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[ 0 ] : elem
+		);
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var matched = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			matched = jQuery.filter( selector, matched );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				jQuery.unique( matched );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				matched.reverse();
+			}
+		}
+
+		return this.pushStack( matched );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// Flag to know if list is currently firing
+		firing,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( list && ( !fired || stack ) ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+					} else if ( !( --remaining ) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// Add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// If we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.triggerHandler ) {
+			jQuery( document ).triggerHandler( "ready" );
+			jQuery( document ).off( "ready" );
+		}
+	}
+});
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	document.removeEventListener( "DOMContentLoaded", completed, false );
+	window.removeEventListener( "load", completed, false );
+	jQuery.ready();
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// We once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		} else {
+
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+		}
+	}
+	return readyList.promise( obj );
+};
+
+// Kick off the DOM ready check even if the user does not
+jQuery.ready.promise();
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		len = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < len; i++ ) {
+				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			len ? fn( elems[0], key ) : emptyGet;
+};
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( owner ) {
+	// Accepts only:
+	//  - Node
+	//    - Node.ELEMENT_NODE
+	//    - Node.DOCUMENT_NODE
+	//  - Object
+	//    - Any
+	/* jshint -W018 */
+	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+function Data() {
+	// Support: Android<4,
+	// Old WebKit does not have Object.preventExtensions/freeze method,
+	// return new empty object instead with no [[set]] accessor
+	Object.defineProperty( this.cache = {}, 0, {
+		get: function() {
+			return {};
+		}
+	});
+
+	this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+Data.accepts = jQuery.acceptData;
+
+Data.prototype = {
+	key: function( owner ) {
+		// We can accept data for non-element nodes in modern browsers,
+		// but we should not, see #8335.
+		// Always return the key for a frozen object.
+		if ( !Data.accepts( owner ) ) {
+			return 0;
+		}
+
+		var descriptor = {},
+			// Check if the owner object already has a cache key
+			unlock = owner[ this.expando ];
+
+		// If not, create one
+		if ( !unlock ) {
+			unlock = Data.uid++;
+
+			// Secure it in a non-enumerable, non-writable property
+			try {
+				descriptor[ this.expando ] = { value: unlock };
+				Object.defineProperties( owner, descriptor );
+
+			// Support: Android<4
+			// Fallback to a less secure definition
+			} catch ( e ) {
+				descriptor[ this.expando ] = unlock;
+				jQuery.extend( owner, descriptor );
+			}
+		}
+
+		// Ensure the cache object
+		if ( !this.cache[ unlock ] ) {
+			this.cache[ unlock ] = {};
+		}
+
+		return unlock;
+	},
+	set: function( owner, data, value ) {
+		var prop,
+			// There may be an unlock assigned to this node,
+			// if there is no entry for this "owner", create one inline
+			// and set the unlock as though an owner entry had always existed
+			unlock = this.key( owner ),
+			cache = this.cache[ unlock ];
+
+		// Handle: [ owner, key, value ] args
+		if ( typeof data === "string" ) {
+			cache[ data ] = value;
+
+		// Handle: [ owner, { properties } ] args
+		} else {
+			// Fresh assignments by object are shallow copied
+			if ( jQuery.isEmptyObject( cache ) ) {
+				jQuery.extend( this.cache[ unlock ], data );
+			// Otherwise, copy the properties one-by-one to the cache object
+			} else {
+				for ( prop in data ) {
+					cache[ prop ] = data[ prop ];
+				}
+			}
+		}
+		return cache;
+	},
+	get: function( owner, key ) {
+		// Either a valid cache is found, or will be created.
+		// New caches will be created and the unlock returned,
+		// allowing direct access to the newly created
+		// empty data object. A valid owner object must be provided.
+		var cache = this.cache[ this.key( owner ) ];
+
+		return key === undefined ?
+			cache : cache[ key ];
+	},
+	access: function( owner, key, value ) {
+		var stored;
+		// In cases where either:
+		//
+		//   1. No key was specified
+		//   2. A string key was specified, but no value provided
+		//
+		// Take the "read" path and allow the get method to determine
+		// which value to return, respectively either:
+		//
+		//   1. The entire cache object
+		//   2. The data stored at the key
+		//
+		if ( key === undefined ||
+				((key && typeof key === "string") && value === undefined) ) {
+
+			stored = this.get( owner, key );
+
+			return stored !== undefined ?
+				stored : this.get( owner, jQuery.camelCase(key) );
+		}
+
+		// [*]When the key is not a string, or both a key and value
+		// are specified, set or extend (existing objects) with either:
+		//
+		//   1. An object of properties
+		//   2. A key and value
+		//
+		this.set( owner, key, value );
+
+		// Since the "set" path can have two possible entry points
+		// return the expected data based on which path was taken[*]
+		return value !== undefined ? value : key;
+	},
+	remove: function( owner, key ) {
+		var i, name, camel,
+			unlock = this.key( owner ),
+			cache = this.cache[ unlock ];
+
+		if ( key === undefined ) {
+			this.cache[ unlock ] = {};
+
+		} else {
+			// Support array or space separated string of keys
+			if ( jQuery.isArray( key ) ) {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = key.concat( key.map( jQuery.camelCase ) );
+			} else {
+				camel = jQuery.camelCase( key );
+				// Try the string as a key before any manipulation
+				if ( key in cache ) {
+					name = [ key, camel ];
+				} else {
+					// If a key with the spaces exists, use it.
+					// Otherwise, create an array by matching non-whitespace
+					name = camel;
+					name = name in cache ?
+						[ name ] : ( name.match( rnotwhite ) || [] );
+				}
+			}
+
+			i = name.length;
+			while ( i-- ) {
+				delete cache[ name[ i ] ];
+			}
+		}
+	},
+	hasData: function( owner ) {
+		return !jQuery.isEmptyObject(
+			this.cache[ owner[ this.expando ] ] || {}
+		);
+	},
+	discard: function( owner ) {
+		if ( owner[ this.expando ] ) {
+			delete this.cache[ owner[ this.expando ] ];
+		}
+	}
+};
+var data_priv = new Data();
+
+var data_user = new Data();
+
+
+
+//	Implementation Summary
+//
+//	1. Enforce API surface and semantic compatibility with 1.9.x branch
+//	2. Improve the module's maintainability by reducing the storage
+//		paths to a single mechanism.
+//	3. Use the same single mechanism to support "private" and "user" data.
+//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+//	5. Avoid exposing implementation details on user objects (eg. expando properties)
+//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+	var name;
+
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			data_user.set( elem, key, data );
+		} else {
+			data = undefined;
+		}
+	}
+	return data;
+}
+
+jQuery.extend({
+	hasData: function( elem ) {
+		return data_user.hasData( elem ) || data_priv.hasData( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return data_user.access( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		data_user.remove( elem, name );
+	},
+
+	// TODO: Now that all calls to _data and _removeData have been replaced
+	// with direct calls to data_priv methods, these can be deprecated.
+	_data: function( elem, name, data ) {
+		return data_priv.access( elem, name, data );
+	},
+
+	_removeData: function( elem, name ) {
+		data_priv.remove( elem, name );
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[ 0 ],
+			attrs = elem && elem.attributes;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = data_user.get( elem );
+
+				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+
+						// Support: IE11+
+						// The attrs elements can be null (#14894)
+						if ( attrs[ i ] ) {
+							name = attrs[ i ].name;
+							if ( name.indexOf( "data-" ) === 0 ) {
+								name = jQuery.camelCase( name.slice(5) );
+								dataAttr( elem, name, data[ name ] );
+							}
+						}
+					}
+					data_priv.set( elem, "hasDataAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				data_user.set( this, key );
+			});
+		}
+
+		return access( this, function( value ) {
+			var data,
+				camelKey = jQuery.camelCase( key );
+
+			// The calling jQuery object (element matches) is not empty
+			// (and therefore has an element appears at this[ 0 ]) and the
+			// `value` parameter was not undefined. An empty jQuery object
+			// will result in `undefined` for elem = this[ 0 ] which will
+			// throw an exception if an attempt to read a data cache is made.
+			if ( elem && value === undefined ) {
+				// Attempt to get data from the cache
+				// with the key as-is
+				data = data_user.get( elem, key );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// Attempt to get data from the cache
+				// with the key camelized
+				data = data_user.get( elem, camelKey );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// Attempt to "discover" the data in
+				// HTML5 custom data-* attrs
+				data = dataAttr( elem, camelKey, undefined );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// We tried really hard, but the data doesn't exist.
+				return;
+			}
+
+			// Set the data...
+			this.each(function() {
+				// First, attempt to store a copy or reference of any
+				// data that might've been store with a camelCased key.
+				var data = data_user.get( this, camelKey );
+
+				// For HTML5 data-* attribute interop, we have to
+				// store property names with dashes in a camelCase form.
+				// This might not apply to all properties...*
+				data_user.set( this, camelKey, value );
+
+				// *... In the case of properties that might _actually_
+				// have dashes, we need to also store a copy of that
+				// unchanged property.
+				if ( key.indexOf("-") !== -1 && data !== undefined ) {
+					data_user.set( this, key, value );
+				}
+			});
+		}, null, value, arguments.length > 1, null, true );
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			data_user.remove( this, key );
+		});
+	}
+});
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = data_priv.get( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray( data ) ) {
+					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// Clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// Not public - generate a queueHooks object, or return the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				data_priv.remove( elem, [ type + "queue", key ] );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// Ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+	};
+
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+	var fragment = document.createDocumentFragment(),
+		div = fragment.appendChild( document.createElement( "div" ) ),
+		input = document.createElement( "input" );
+
+	// Support: Safari<=5.1
+	// Check state lost if the name is set (#11217)
+	// Support: Windows Web Apps (WWA)
+	// `name` and `type` must use .setAttribute for WWA (#14901)
+	input.setAttribute( "type", "radio" );
+	input.setAttribute( "checked", "checked" );
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+
+	// Support: Safari<=5.1, Android<4.2
+	// Older WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<=11+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+})();
+var strundefined = typeof undefined;
+
+
+
+support.focusinBubbles = "onfocusin" in window;
+
+
+var
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var handleObjIn, eventHandle, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = data_priv.get( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !(events = elemData.events) ) {
+			events = elemData.events = {};
+		}
+		if ( !(eventHandle = elemData.handle) ) {
+			eventHandle = elemData.handle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
+					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+			};
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !(handlers = events[ type ]) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var j, origCount, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = data_priv.hasData( elem ) && data_priv.get( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+			data_priv.remove( elem, "events" );
+		}
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+
+		var i, cur, tmp, bubbleType, ontype, handle, special,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf(":") < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === (elem.ownerDocument || document) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+				jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					elem[ type ]();
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, j, ret, matched, handleObj,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
+				// a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( (event.result = ret) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var i, matches, sel, handleObj,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+			for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.disabled !== true || event.type !== "click" ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, handlers: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+		}
+
+		return handlerQueue;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var eventDoc, doc, body,
+				button = original.button;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: Cordova 2.5 (WebKit) (#13255)
+		// All events should have a target; Cordova deviceready doesn't
+		if ( !event.target ) {
+			event.target = document;
+		}
+
+		// Support: Safari 6.0+, Chrome<28
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					this.focus();
+					return false;
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Support: Firefox 20+
+				// Firefox doesn't alert if the returnValue field is not set.
+				if ( event.result !== undefined && event.originalEvent ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+	if ( elem.removeEventListener ) {
+		elem.removeEventListener( type, handle, false );
+	}
+};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined &&
+				// Support: Android<4.0
+				src.returnValue === false ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+
+		if ( e && e.preventDefault ) {
+			e.preventDefault();
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+
+		if ( e && e.stopPropagation ) {
+			e.stopPropagation();
+		}
+	},
+	stopImmediatePropagation: function() {
+		var e = this.originalEvent;
+
+		this.isImmediatePropagationStopped = returnTrue;
+
+		if ( e && e.stopImmediatePropagation ) {
+			e.stopImmediatePropagation();
+		}
+
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// Support: Chrome 15+
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout",
+	pointerenter: "pointerover",
+	pointerleave: "pointerout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// Support: Firefox, Chrome, Safari
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = data_priv.access( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = data_priv.access( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					data_priv.remove( doc, fix );
+
+				} else {
+					data_priv.access( doc, fix, attaches );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var origFn, type;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) {
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[0];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+});
+
+
+var
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /^$|\/(?:java|ecma)script/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+	// We have to close these tags to support XHTML (#13200)
+	wrapMap = {
+
+		// Support: IE9
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+		thead: [ 1, "<table>", "</table>" ],
+		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+		_default: [ 0, "", "" ]
+	};
+
+// Support: IE9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// Support: 1.x compatibility
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName("tbody")[0] ||
+			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+
+	if ( match ) {
+		elem.type = match[ 1 ];
+	} else {
+		elem.removeAttribute("type");
+	}
+
+	return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var i = 0,
+		l = elems.length;
+
+	for ( ; i < l; i++ ) {
+		data_priv.set(
+			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
+		);
+	}
+}
+
+function cloneCopyEvent( src, dest ) {
+	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	// 1. Copy private data: events, handlers, etc.
+	if ( data_priv.hasData( src ) ) {
+		pdataOld = data_priv.access( src );
+		pdataCur = data_priv.set( dest, pdataOld );
+		events = pdataOld.events;
+
+		if ( events ) {
+			delete pdataCur.handle;
+			pdataCur.events = {};
+
+			for ( type in events ) {
+				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+					jQuery.event.add( dest, type, events[ type ][ i ] );
+				}
+			}
+		}
+	}
+
+	// 2. Copy user data
+	if ( data_user.hasData( src ) ) {
+		udataOld = data_user.access( src );
+		udataCur = jQuery.extend( {}, udataOld );
+
+		data_user.set( dest, udataCur );
+	}
+}
+
+function getAll( context, tag ) {
+	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
+			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
+			[];
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], ret ) :
+		ret;
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+	var nodeName = dest.nodeName.toLowerCase();
+
+	// Fails to persist the checked state of a cloned checkbox or radio button.
+	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		dest.checked = src.checked;
+
+	// Fails to return the selected option to the default selected state when cloning options
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var i, l, srcElements, destElements,
+			clone = elem.cloneNode( true ),
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		// Fix IE cloning issues
+		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+				!jQuery.isXMLDoc( elem ) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			for ( i = 0, l = srcElements.length; i < l; i++ ) {
+				fixInput( srcElements[ i ], destElements[ i ] );
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0, l = srcElements.length; i < l; i++ ) {
+					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		// Return the cloned set
+		return clone;
+	},
+
+	buildFragment: function( elems, context, scripts, selection ) {
+		var elem, tmp, tag, wrap, contains, j,
+			fragment = context.createDocumentFragment(),
+			nodes = [],
+			i = 0,
+			l = elems.length;
+
+		for ( ; i < l; i++ ) {
+			elem = elems[ i ];
+
+			if ( elem || elem === 0 ) {
+
+				// Add nodes directly
+				if ( jQuery.type( elem ) === "object" ) {
+					// Support: QtWebKit, PhantomJS
+					// push.apply(_, arraylike) throws on ancient WebKit
+					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+				// Convert non-html into a text node
+				} else if ( !rhtml.test( elem ) ) {
+					nodes.push( context.createTextNode( elem ) );
+
+				// Convert html into DOM nodes
+				} else {
+					tmp = tmp || fragment.appendChild( context.createElement("div") );
+
+					// Deserialize a standard representation
+					tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
+
+					// Descend through wrappers to the right content
+					j = wrap[ 0 ];
+					while ( j-- ) {
+						tmp = tmp.lastChild;
+					}
+
+					// Support: QtWebKit, PhantomJS
+					// push.apply(_, arraylike) throws on ancient WebKit
+					jQuery.merge( nodes, tmp.childNodes );
+
+					// Remember the top-level container
+					tmp = fragment.firstChild;
+
+					// Ensure the created nodes are orphaned (#12392)
+					tmp.textContent = "";
+				}
+			}
+		}
+
+		// Remove wrapper from fragment
+		fragment.textContent = "";
+
+		i = 0;
+		while ( (elem = nodes[ i++ ]) ) {
+
+			// #4087 - If origin and destination elements are the same, and this is
+			// that element, do not do anything
+			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+				continue;
+			}
+
+			contains = jQuery.contains( elem.ownerDocument, elem );
+
+			// Append to fragment
+			tmp = getAll( fragment.appendChild( elem ), "script" );
+
+			// Preserve script evaluation history
+			if ( contains ) {
+				setGlobalEval( tmp );
+			}
+
+			// Capture executables
+			if ( scripts ) {
+				j = 0;
+				while ( (elem = tmp[ j++ ]) ) {
+					if ( rscriptType.test( elem.type || "" ) ) {
+						scripts.push( elem );
+					}
+				}
+			}
+		}
+
+		return fragment;
+	},
+
+	cleanData: function( elems ) {
+		var data, elem, type, key,
+			special = jQuery.event.special,
+			i = 0;
+
+		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
+			if ( jQuery.acceptData( elem ) ) {
+				key = elem[ data_priv.expando ];
+
+				if ( key && (data = data_priv.cache[ key ]) ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+					if ( data_priv.cache[ key ] ) {
+						// Discard any remaining `private` data
+						delete data_priv.cache[ key ];
+					}
+				}
+			}
+			// Discard any remaining `user` data
+			delete data_user.cache[ elem[ data_user.expando ] ];
+		}
+	}
+});
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().each(function() {
+					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+						this.textContent = value;
+					}
+				});
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		});
+	},
+
+	after: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		});
+	},
+
+	remove: function( selector, keepData /* Internal Use Only */ ) {
+		var elem,
+			elems = selector ? jQuery.filter( selector, this ) : this,
+			i = 0;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+			if ( !keepData && elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem ) );
+			}
+
+			if ( elem.parentNode ) {
+				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+					setGlobalEval( getAll( elem, "script" ) );
+				}
+				elem.parentNode.removeChild( elem );
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			if ( elem.nodeType === 1 ) {
+
+				// Prevent memory leaks
+				jQuery.cleanData( getAll( elem, false ) );
+
+				// Remove any remaining nodes
+				elem.textContent = "";
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map(function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined && elem.nodeType === 1 ) {
+				return elem.innerHTML;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for ( ; i < l; i++ ) {
+						elem = this[ i ] || {};
+
+						// Remove element nodes and prevent memory leaks
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch( e ) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var arg = arguments[ 0 ];
+
+		// Make the changes, replacing each context element with the new content
+		this.domManip( arguments, function( elem ) {
+			arg = this.parentNode;
+
+			jQuery.cleanData( getAll( this ) );
+
+			if ( arg ) {
+				arg.replaceChild( elem, this );
+			}
+		});
+
+		// Force removal if there was no new content (e.g., from empty arguments)
+		return arg && (arg.length || arg.nodeType) ? this : this.remove();
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, callback ) {
+
+		// Flatten any nested arrays
+		args = concat.apply( [], args );
+
+		var fragment, first, scripts, hasScripts, node, doc,
+			i = 0,
+			l = this.length,
+			set = this,
+			iNoClone = l - 1,
+			value = args[ 0 ],
+			isFunction = jQuery.isFunction( value );
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( isFunction ||
+				( l > 1 && typeof value === "string" &&
+					!support.checkClone && rchecked.test( value ) ) ) {
+			return this.each(function( index ) {
+				var self = set.eq( index );
+				if ( isFunction ) {
+					args[ 0 ] = value.call( this, index, self.html() );
+				}
+				self.domManip( args, callback );
+			});
+		}
+
+		if ( l ) {
+			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+				hasScripts = scripts.length;
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				for ( ; i < l; i++ ) {
+					node = fragment;
+
+					if ( i !== iNoClone ) {
+						node = jQuery.clone( node, true, true );
+
+						// Keep references to cloned scripts for later restoration
+						if ( hasScripts ) {
+							// Support: QtWebKit
+							// jQuery.merge because push.apply(_, arraylike) throws
+							jQuery.merge( scripts, getAll( node, "script" ) );
+						}
+					}
+
+					callback.call( this[ i ], node, i );
+				}
+
+				if ( hasScripts ) {
+					doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+					// Reenable scripts
+					jQuery.map( scripts, restoreScript );
+
+					// Evaluate executable scripts on first document insertion
+					for ( i = 0; i < hasScripts; i++ ) {
+						node = scripts[ i ];
+						if ( rscriptType.test( node.type || "" ) &&
+							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+							if ( node.src ) {
+								// Optional AJAX dependency, but won't run scripts if not present
+								if ( jQuery._evalUrl ) {
+									jQuery._evalUrl( node.src );
+								}
+							} else {
+								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+							}
+						}
+					}
+				}
+			}
+		}
+
+		return this;
+	}
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1,
+			i = 0;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone( true );
+			jQuery( insert[ i ] )[ original ]( elems );
+
+			// Support: QtWebKit
+			// .get() because push.apply(_, arraylike) throws
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+});
+
+
+var iframe,
+	elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var style,
+		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		// getDefaultComputedStyle might be reliably used only on attached element
+		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+			// Use of this method is a temporary fix (more like optimization) until something better comes along,
+			// since it was removed from specification and supported only in FF
+			style.display : jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = iframe[ 0 ].contentDocument;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+		// IE throws on elements created in popups
+		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+		if ( elem.ownerDocument.defaultView.opener ) {
+			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+		}
+
+		return window.getComputedStyle( elem, null );
+	};
+
+
+
+function curCSS( elem, name, computed ) {
+	var width, minWidth, maxWidth, ret,
+		style = elem.style;
+
+	computed = computed || getStyles( elem );
+
+	// Support: IE9
+	// getPropertyValue is only needed for .css('filter') (#12537)
+	if ( computed ) {
+		ret = computed.getPropertyValue( name ) || computed[ name ];
+	}
+
+	if ( computed ) {
+
+		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+			ret = jQuery.style( elem, name );
+		}
+
+		// Support: iOS < 6
+		// A tribute to the "awesome hack by Dean Edwards"
+		// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+			// Remember the original values
+			width = style.width;
+			minWidth = style.minWidth;
+			maxWidth = style.maxWidth;
+
+			// Put in the new values to get a computed value out
+			style.minWidth = style.maxWidth = style.width = ret;
+			ret = computed.width;
+
+			// Revert the changed values
+			style.width = width;
+			style.minWidth = minWidth;
+			style.maxWidth = maxWidth;
+		}
+	}
+
+	return ret !== undefined ?
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		ret + "" :
+		ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			if ( conditionFn() ) {
+				// Hook not needed (or it's not possible to use it due
+				// to missing dependency), remove it.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+			return (this.get = hookFn).apply( this, arguments );
+		}
+	};
+}
+
+
+(function() {
+	var pixelPositionVal, boxSizingReliableVal,
+		docElem = document.documentElement,
+		container = document.createElement( "div" ),
+		div = document.createElement( "div" );
+
+	if ( !div.style ) {
+		return;
+	}
+
+	// Support: IE9-11+
+	// Style of cloned element affects source element cloned (#8908)
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
+		"position:absolute";
+	container.appendChild( div );
+
+	// Executing both pixelPosition & boxSizingReliable tests require only one layout
+	// so they're executed at the same time to save the second computation.
+	function computePixelPositionAndBoxSizingReliable() {
+		div.style.cssText =
+			// Support: Firefox<29, Android 2.3
+			// Vendor-prefix box-sizing
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+			"border:1px;padding:1px;width:4px;position:absolute";
+		div.innerHTML = "";
+		docElem.appendChild( container );
+
+		var divStyle = window.getComputedStyle( div, null );
+		pixelPositionVal = divStyle.top !== "1%";
+		boxSizingReliableVal = divStyle.width === "4px";
+
+		docElem.removeChild( container );
+	}
+
+	// Support: node.js jsdom
+	// Don't assume that getComputedStyle is a property of the global object
+	if ( window.getComputedStyle ) {
+		jQuery.extend( support, {
+			pixelPosition: function() {
+
+				// This test is executed only once but we still do memoizing
+				// since we can use the boxSizingReliable pre-computing.
+				// No need to check if the test was already performed, though.
+				computePixelPositionAndBoxSizingReliable();
+				return pixelPositionVal;
+			},
+			boxSizingReliable: function() {
+				if ( boxSizingReliableVal == null ) {
+					computePixelPositionAndBoxSizingReliable();
+				}
+				return boxSizingReliableVal;
+			},
+			reliableMarginRight: function() {
+
+				// Support: Android 2.3
+				// Check if div with explicit width and no margin-right incorrectly
+				// gets computed margin-right based on width of container. (#3333)
+				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+				// This support function is only executed once so no memoizing is needed.
+				var ret,
+					marginDiv = div.appendChild( document.createElement( "div" ) );
+
+				// Reset CSS: box-sizing; display; margin; border; padding
+				marginDiv.style.cssText = div.style.cssText =
+					// Support: Firefox<29, Android 2.3
+					// Vendor-prefix box-sizing
+					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+					"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+				marginDiv.style.marginRight = marginDiv.style.width = "0";
+				div.style.width = "1px";
+				docElem.appendChild( container );
+
+				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
+
+				docElem.removeChild( container );
+				div.removeChild( marginDiv );
+
+				return ret;
+			}
+		});
+	}
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var
+	// Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: "0",
+		fontWeight: "400"
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// Shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// Check for vendor prefixed names
+	var capName = name[0].toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// Both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// At this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+			// At this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// At this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// Check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox &&
+			( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// Use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = data_priv.get( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+			}
+		} else {
+			hidden = isHidden( elem );
+
+			if ( display !== "none" || !hidden ) {
+				data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+jQuery.extend({
+
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"columnCount": true,
+		"fillOpacity": true,
+		"flexGrow": true,
+		"flexShrink": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		"float": "cssFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// Gets hook for the prefixed version, then unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// Convert "+=" or "-=" to relative numbers (#7345)
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set (#7116)
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// Support: IE9-11+
+			// background-* props affect original clone's values
+			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+				style[ name ] = value;
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var val, num, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// Try prefixed name followed by the unprefixed name
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		// Convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Make numeric if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+
+				// Certain elements can have dimension info if we invisibly show them
+				// but it must have a current display style that would benefit
+				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+					jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					}) :
+					getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var styles = extra && getStyles( elem );
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				) : 0
+			);
+		}
+	};
+});
+
+// Support: Android 2.3
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			return jQuery.swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// Assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each(function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// Passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails.
+			// Simple values such as "10px" are parsed to Float;
+			// complex values such as "rotate(1rad)" are returned as-is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// Use step hook for back compat.
+			// Use cssHook if its there.
+			// Use .style if available and use plain properties where available.
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE9
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	}
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value ),
+				target = tween.cur(),
+				parts = rfxnum.exec( value ),
+				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+				// Starting value computation is required for potential unit mismatches
+				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+				scale = 1,
+				maxIterations = 20;
+
+			if ( start && start[ 3 ] !== unit ) {
+				// Trust units reported by jQuery.css
+				unit = unit || start[ 3 ];
+
+				// Make sure we update the tween properties later on
+				parts = parts || [];
+
+				// Iteratively approximate from a nonzero starting point
+				start = +target || 1;
+
+				do {
+					// If previous iteration zeroed out, double until we get *something*.
+					// Use string for doubling so we don't accidentally see scale as unchanged below
+					scale = scale || ".5";
+
+					// Adjust and apply
+					start = start / scale;
+					jQuery.style( tween.elem, prop, start + unit );
+
+				// Update scale, tolerating zero or NaN from tween.cur(),
+				// break the loop if scale is unchanged or perfect, or if we've just had enough
+				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+			}
+
+			// Update tween properties
+			if ( parts ) {
+				start = tween.start = +start || +target || 0;
+				tween.unit = unit;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[ 1 ] ?
+					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+					+parts[ 2 ];
+			}
+
+			return tween;
+		} ]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	});
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		i = 0,
+		attrs = { height: type };
+
+	// If we include width, step value is 1 to do all cssExpand values,
+	// otherwise step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+			// We're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = data_priv.get( elem, "fxshow" );
+
+	// Handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// Ensure the complete handler is called before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// Height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE9-10 do not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+
+		// Test default display if display is currently "none"
+		checkDisplay = display === "none" ?
+			data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+			style.display = "inline-block";
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		anim.always(function() {
+			style.overflow = opts.overflow[ 0 ];
+			style.overflowX = opts.overflow[ 1 ];
+			style.overflowY = opts.overflow[ 2 ];
+		});
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+		// Any non-fx value stops us from restoring the original display value
+		} else {
+			display = undefined;
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = data_priv.access( elem, "fxshow", {} );
+		}
+
+		// Store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+
+			data_priv.remove( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+
+	// If this is a noop like .hide().hide(), restore an overwritten display value
+	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+		style.display = display;
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// Not quite $.extend, this won't overwrite existing keys.
+			// Reusing 'index' because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// Don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				// Support: Android 2.3
+				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// If we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// Resolve when we played the last frame; otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// Normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// Show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// Animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || data_priv.get( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = data_priv.get( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Start the next in the queue if the last step wasn't forced.
+			// Timers currently will call their complete callbacks, which
+			// will dequeue but only if they were gotoEnd.
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each(function() {
+			var index,
+				data = data_priv.get( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// Enable finishing flag on private data
+			data.finish = true;
+
+			// Empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// Look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// Turn off finishing flag
+			delete data.finish;
+		});
+	}
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		i = 0,
+		timers = jQuery.timers;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = setTimeout( next, time );
+		hooks.stop = function() {
+			clearTimeout( timeout );
+		};
+	});
+};
+
+
+(function() {
+	var input = document.createElement( "input" ),
+		select = document.createElement( "select" ),
+		opt = select.appendChild( document.createElement( "option" ) );
+
+	input.type = "checkbox";
+
+	// Support: iOS<=5.1, Android<=4.2+
+	// Default value for a checkbox should be "on"
+	support.checkOn = input.value !== "";
+
+	// Support: IE<=11+
+	// Must access selectedIndex to make default options select
+	support.optSelected = opt.selected;
+
+	// Support: Android<=2.3
+	// Options inside disabled selects are incorrectly marked as disabled
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE<=11+
+	// An input loses its value after becoming a radio
+	input = document.createElement( "input" );
+	input.value = "t";
+	input.type = "radio";
+	support.radioValue = input.value === "t";
+})();
+
+
+var nodeHook, boolHook,
+	attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	}
+});
+
+jQuery.extend({
+	attr: function( elem, name, value ) {
+		var hooks, ret,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === strundefined ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+
+			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+			ret = jQuery.find.attr( elem, name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret == null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( (name = attrNames[i++]) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+					// Set corresponding property to false
+					elem[ propName ] = false;
+				}
+
+				elem.removeAttribute( name );
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" &&
+					jQuery.nodeName( elem, "input" ) ) {
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	}
+});
+
+// Hooks for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			elem.setAttribute( name, name );
+		}
+		return name;
+	}
+};
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = function( elem, name, isXML ) {
+		var ret, handle;
+		if ( !isXML ) {
+			// Avoid an infinite loop by temporarily removing this function from the getter
+			handle = attrHandle[ name ];
+			attrHandle[ name ] = ret;
+			ret = getter( elem, name, isXML ) != null ?
+				name.toLowerCase() :
+				null;
+			attrHandle[ name ] = handle;
+		}
+		return ret;
+	};
+});
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i;
+
+jQuery.fn.extend({
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		return this.each(function() {
+			delete this[ jQuery.propFix[ name ] || name ];
+		});
+	}
+});
+
+jQuery.extend({
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// Don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+				ret :
+				( elem[ name ] = value );
+
+		} else {
+			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+				ret :
+				elem[ name ];
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
+					elem.tabIndex :
+					-1;
+			}
+		}
+	}
+});
+
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+			if ( parent && parent.parentNode ) {
+				parent.parentNode.selectedIndex;
+			}
+			return null;
+		}
+	};
+}
+
+jQuery.each([
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+	addClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			proceed = typeof value === "string" && value,
+			i = 0,
+			len = this.length;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call( this, j, this.className ) );
+			});
+		}
+
+		if ( proceed ) {
+			// The disjunction here is for better compressibility (see removeClass)
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					" "
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			proceed = arguments.length === 0 || typeof value === "string" && value,
+			i = 0,
+			len = this.length;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, this.className ) );
+			});
+		}
+		if ( proceed ) {
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					""
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// Only assign if different to avoid unneeded rendering.
+					finalValue = value ? jQuery.trim( cur ) : "";
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// Toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					classNames = value.match( rnotwhite ) || [];
+
+				while ( (className = classNames[ i++ ]) ) {
+					// Check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( type === strundefined || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					data_priv.set( this, "__className__", this.className );
+				}
+
+				// If the element has a class name or if we're passed `false`,
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+});
+
+
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// Handle most common string cases
+					ret.replace(rreturn, "") :
+					// Handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+
+			} else if ( typeof val === "number" ) {
+				val += "";
+
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+					// Support: IE10-11+
+					// option.text throws exceptions (#14686, #14858)
+					jQuery.trim( jQuery.text( elem ) );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// IE6-9 doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
+							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
+						optionSet = true;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	}
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			return elem.getAttribute("value") === null ? "on" : elem.value;
+		};
+	}
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+});
+
+jQuery.fn.extend({
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	}
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+// Support: Android 2.3
+// Workaround failure to string-cast null input
+jQuery.parseJSON = function( data ) {
+	return JSON.parse( data + "" );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml, tmp;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+
+	// Support: IE9
+	try {
+		tmp = new DOMParser();
+		xml = tmp.parseFromString( data, "text/xml" );
+	} catch ( e ) {
+		xml = undefined;
+	}
+
+	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat( "*" ),
+
+	// Document location
+	ajaxLocation = window.location.href,
+
+	// Segment location into parts
+	ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			while ( (dataType = dataTypes[i++]) ) {
+				// Prepend if requested
+				if ( dataType[0] === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+				// Otherwise append
+				} else {
+					(structure[ dataType ] = structure[ dataType ] || []).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		});
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var key, deep,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+	var ct, type, finalDataType, firstDataType,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+		// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s[ "throws" ] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		type: "GET",
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var transport,
+			// URL without anti-cache param
+			cacheURL,
+			// Response headers
+			responseHeadersString,
+			responseHeaders,
+			// timeout handle
+			timeoutTimer,
+			// Cross-domain detection vars
+			parts,
+			// To know if global events are to be dispatched
+			fireGlobals,
+			// Loop variable
+			i,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+				jQuery( callbackContext ) :
+				jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks("once memory"),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( (match = rheaders.exec( responseHeadersString )) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (prefilters might expect it)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
+			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+		fireGlobals = jQuery.event && s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger("ajaxStart");
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// Aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout(function() {
+					jqXHR.abort("timeout");
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("etag");
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+				// Extract error from statusText and normalize for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger("ajaxStop");
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// Shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		});
+	};
+});
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax({
+		url: url,
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	});
+};
+
+
+jQuery.fn.extend({
+	wrapAll: function( html ) {
+		var wrap;
+
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[ 0 ] ) {
+
+			// The elements to wrap the target around
+			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+			if ( this[ 0 ].parentNode ) {
+				wrap.insertBefore( this[ 0 ] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstElementChild ) {
+					elem = elem.firstElementChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function( i ) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	}
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
+};
+jQuery.expr.filters.visible = function( elem ) {
+	return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function() {
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		})
+		.filter(function() {
+			var type = this.type;
+
+			// Use .is( ":disabled" ) so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		})
+		.map(function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+
+jQuery.ajaxSettings.xhr = function() {
+	try {
+		return new XMLHttpRequest();
+	} catch( e ) {}
+};
+
+var xhrId = 0,
+	xhrCallbacks = {},
+	xhrSuccessStatus = {
+		// file protocol always yields status code 0, assume 200
+		0: 200,
+		// Support: IE9
+		// #1450: sometimes IE returns 1223 when it should be 204
+		1223: 204
+	},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE9
+// Open requests must be manually aborted on unload (#5280)
+// See https://support.microsoft.com/kb/2856746 for more info
+if ( window.attachEvent ) {
+	window.attachEvent( "onunload", function() {
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]();
+		}
+	});
+}
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport(function( options ) {
+	var callback;
+
+	// Cross domain only allowed if supported through XMLHttpRequest
+	if ( support.cors || xhrSupported && !options.crossDomain ) {
+		return {
+			send: function( headers, complete ) {
+				var i,
+					xhr = options.xhr(),
+					id = ++xhrId;
+
+				xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+				// Apply custom fields if provided
+				if ( options.xhrFields ) {
+					for ( i in options.xhrFields ) {
+						xhr[ i ] = options.xhrFields[ i ];
+					}
+				}
+
+				// Override mime type if needed
+				if ( options.mimeType && xhr.overrideMimeType ) {
+					xhr.overrideMimeType( options.mimeType );
+				}
+
+				// X-Requested-With header
+				// For cross-domain requests, seeing as conditions for a preflight are
+				// akin to a jigsaw puzzle, we simply never set it to be sure.
+				// (it can always be set on a per-request basis or even using ajaxSetup)
+				// For same-domain requests, won't change header if already provided.
+				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+					headers["X-Requested-With"] = "XMLHttpRequest";
+				}
+
+				// Set headers
+				for ( i in headers ) {
+					xhr.setRequestHeader( i, headers[ i ] );
+				}
+
+				// Callback
+				callback = function( type ) {
+					return function() {
+						if ( callback ) {
+							delete xhrCallbacks[ id ];
+							callback = xhr.onload = xhr.onerror = null;
+
+							if ( type === "abort" ) {
+								xhr.abort();
+							} else if ( type === "error" ) {
+								complete(
+									// file: protocol always yields status 0; see #8605, #14207
+									xhr.status,
+									xhr.statusText
+								);
+							} else {
+								complete(
+									xhrSuccessStatus[ xhr.status ] || xhr.status,
+									xhr.statusText,
+									// Support: IE9
+									// Accessing binary-data responseText throws an exception
+									// (#11426)
+									typeof xhr.responseText === "string" ? {
+										text: xhr.responseText
+									} : undefined,
+									xhr.getAllResponseHeaders()
+								);
+							}
+						}
+					};
+				};
+
+				// Listen to events
+				xhr.onload = callback();
+				xhr.onerror = callback("error");
+
+				// Create the abort callback
+				callback = xhrCallbacks[ id ] = callback("abort");
+
+				try {
+					// Do send the request (this may raise an exception)
+					xhr.send( options.hasContent && options.data || null );
+				} catch ( e ) {
+					// #14683: Only rethrow if this hasn't been notified as an error yet
+					if ( callback ) {
+						throw e;
+					}
+				}
+			},
+
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /(?:java|ecma)script/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+		var script, callback;
+		return {
+			send: function( _, complete ) {
+				script = jQuery("<script>").prop({
+					async: true,
+					charset: s.scriptCharset,
+					src: s.url
+				}).on(
+					"load error",
+					callback = function( evt ) {
+						script.remove();
+						callback = null;
+						if ( evt ) {
+							complete( evt.type === "error" ? 404 : 200, evt.type );
+						}
+					}
+				);
+				document.head.appendChild( script[ 0 ] );
+			},
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[1] ) ];
+	}
+
+	parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, type, response,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = jQuery.trim( url.slice( off ) );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax({
+			url: url,
+
+			// if "type" variable is undefined, then "GET" method will be used
+			type: type,
+			dataType: "html",
+			data: params
+		}).done(function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		}).complete( callback && function( jqXHR, status ) {
+			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+		});
+	}
+
+	return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+});
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep(jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	}).length;
+};
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// Set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
+
+		// Need to be able to calculate position if either
+		// top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend({
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each(function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				});
+		}
+
+		var docElem, win,
+			elem = this[ 0 ],
+			box = { top: 0, left: 0 },
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		// Support: BlackBerry 5, iOS 3 (original iPhone)
+		// If we don't have gBCR, just use 0,0 rather than error
+		if ( typeof elem.getBoundingClientRect !== strundefined ) {
+			box = elem.getBoundingClientRect();
+		}
+		win = getWindow( doc );
+		return {
+			top: box.top + win.pageYOffset - docElem.clientTop,
+			left: box.left + win.pageXOffset - docElem.clientLeft
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			elem = this[ 0 ],
+			parentOffset = { top: 0, left: 0 };
+
+		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+			// Assume getBoundingClientRect is there when computed position is fixed
+			offset = elem.getBoundingClientRect();
+
+		} else {
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		return {
+			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || docElem;
+
+			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+
+			return offsetParent || docElem;
+		});
+	}
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = "pageYOffset" === prop;
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? win[ prop ] : elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : window.pageXOffset,
+					top ? val : window.pageYOffset
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+// Support: Safari<7+, Chrome<37+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+				// If curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// Margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+					// whichever is greatest
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+	return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	});
+}
+
+
+
+
+var
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.js b/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.js
new file mode 100755
index 0000000..c4c1d98
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.js
@@ -0,0 +1,6450 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+/* global $:true */
+/* global WebKitCSSMatrix:true */
+
+(function($) {
+  "use strict";
+
+  $.fn.transitionEnd = function(callback) {
+    var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
+      i, dom = this;
+
+    function fireCallBack(e) {
+      /*jshint validthis:true */
+      if (e.target !== this) return;
+      callback.call(this, e);
+      for (i = 0; i < events.length; i++) {
+        dom.off(events[i], fireCallBack);
+      }
+    }
+    if (callback) {
+      for (i = 0; i < events.length; i++) {
+        dom.on(events[i], fireCallBack);
+      }
+    }
+    return this;
+  };
+
+  $.support = (function() {
+    var support = {
+      touch: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch)
+    };
+    return support;
+  })();
+
+  $.touchEvents = {
+    start: $.support.touch ? 'touchstart' : 'mousedown',
+    move: $.support.touch ? 'touchmove' : 'mousemove',
+    end: $.support.touch ? 'touchend' : 'mouseup'
+  };
+
+  $.getTouchPosition = function(e) {
+    e = e.originalEvent || e; //jquery wrap the originevent
+    if(e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend') {
+      return {
+        x: e.targetTouches[0].pageX,
+        y: e.targetTouches[0].pageY
+      };
+    } else {
+      return {
+        x: e.pageX,
+        y: e.pageY
+      };
+    }
+  };
+
+  $.fn.scrollHeight = function() {
+    return this[0].scrollHeight;
+  };
+
+  $.fn.transform = function(transform) {
+    for (var i = 0; i < this.length; i++) {
+      var elStyle = this[i].style;
+      elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
+    }
+    return this;
+  };
+  $.fn.transition = function(duration) {
+    if (typeof duration !== 'string') {
+      duration = duration + 'ms';
+    }
+    for (var i = 0; i < this.length; i++) {
+      var elStyle = this[i].style;
+      elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
+    }
+    return this;
+  };
+
+  $.getTranslate = function (el, axis) {
+    var matrix, curTransform, curStyle, transformMatrix;
+
+    // automatic axis detection
+    if (typeof axis === 'undefined') {
+      axis = 'x';
+    }
+
+    curStyle = window.getComputedStyle(el, null);
+    if (window.WebKitCSSMatrix) {
+      // Some old versions of Webkit choke when 'none' is passed; pass
+      // empty string instead in this case
+      transformMatrix = new WebKitCSSMatrix(curStyle.webkitTransform === 'none' ? '' : curStyle.webkitTransform);
+    }
+    else {
+      transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
+      matrix = transformMatrix.toString().split(',');
+    }
+
+    if (axis === 'x') {
+      //Latest Chrome and webkits Fix
+      if (window.WebKitCSSMatrix)
+        curTransform = transformMatrix.m41;
+      //Crazy IE10 Matrix
+      else if (matrix.length === 16)
+        curTransform = parseFloat(matrix[12]);
+      //Normal Browsers
+      else
+        curTransform = parseFloat(matrix[4]);
+    }
+    if (axis === 'y') {
+      //Latest Chrome and webkits Fix
+      if (window.WebKitCSSMatrix)
+        curTransform = transformMatrix.m42;
+      //Crazy IE10 Matrix
+      else if (matrix.length === 16)
+        curTransform = parseFloat(matrix[13]);
+      //Normal Browsers
+      else
+        curTransform = parseFloat(matrix[5]);
+    }
+
+    return curTransform || 0;
+  };
+  $.requestAnimationFrame = function (callback) {
+    if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
+    else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
+    else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
+    else {
+      return window.setTimeout(callback, 1000 / 60);
+    }
+  };
+
+  $.cancelAnimationFrame = function (id) {
+    if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
+    else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
+    else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
+    else {
+      return window.clearTimeout(id);
+    }  
+  };
+
+  $.fn.join = function(arg) {
+    return this.toArray().join(arg);
+  }
+})($);
+
+/*===========================
+  Template7 Template engine
+  ===========================*/
+/* global $:true */
+/* jshint unused:false */
+/* jshint forin:false */
++function ($) {
+  "use strict";
+  $.Template7 = $.t7 = (function () {
+    function isArray(arr) {
+      return Object.prototype.toString.apply(arr) === '[object Array]';
+    }
+    function isObject(obj) {
+      return obj instanceof Object;
+    }
+    function isFunction(func) {
+      return typeof func === 'function';
+    }
+    var cache = {};
+    function helperToSlices(string) {
+      var helperParts = string.replace(/[{}#}]/g, '').split(' ');
+      var slices = [];
+      var shiftIndex, i, j;
+      for (i = 0; i < helperParts.length; i++) {
+        var part = helperParts[i];
+        if (i === 0) slices.push(part);
+        else {
+          if (part.indexOf('"') === 0) {
+            // Plain String
+            if (part.match(/"/g).length === 2) {
+              // One word string
+              slices.push(part);
+            }
+            else {
+              // Find closed Index
+              shiftIndex = 0;
+              for (j = i + 1; j < helperParts.length; j++) {
+                part += ' ' + helperParts[j];
+                if (helperParts[j].indexOf('"') >= 0) {
+                  shiftIndex = j;
+                  slices.push(part);
+                  break;
+                }
+              }
+              if (shiftIndex) i = shiftIndex;
+            }
+          }
+          else {
+            if (part.indexOf('=') > 0) {
+              // Hash
+              var hashParts = part.split('=');
+              var hashName = hashParts[0];
+              var hashContent = hashParts[1];
+              if (hashContent.match(/"/g).length !== 2) {
+                shiftIndex = 0;
+                for (j = i + 1; j < helperParts.length; j++) {
+                  hashContent += ' ' + helperParts[j];
+                  if (helperParts[j].indexOf('"') >= 0) {
+                    shiftIndex = j;
+                    break;
+                  }
+                }
+                if (shiftIndex) i = shiftIndex;
+              }
+              var hash = [hashName, hashContent.replace(/"/g,'')];
+              slices.push(hash);
+            }
+            else {
+              // Plain variable
+              slices.push(part);
+            }
+          }
+        }
+      }
+      return slices;
+    }
+    function stringToBlocks(string) {
+      var blocks = [], i, j, k;
+      if (!string) return [];
+      var _blocks = string.split(/({{[^{^}]*}})/);
+      for (i = 0; i < _blocks.length; i++) {
+        var block = _blocks[i];
+        if (block === '') continue;
+        if (block.indexOf('{{') < 0) {
+          blocks.push({
+            type: 'plain',
+            content: block
+          });
+        }
+        else {
+          if (block.indexOf('{/') >= 0) {
+            continue;
+          }
+          if (block.indexOf('{#') < 0 && block.indexOf(' ') < 0 && block.indexOf('else') < 0) {
+            // Simple variable
+            blocks.push({
+              type: 'variable',
+              contextName: block.replace(/[{}]/g, '')
+            });
+            continue;
+          }
+          // Helpers
+          var helperSlices = helperToSlices(block);
+          var helperName = helperSlices[0];
+          var helperContext = [];
+          var helperHash = {};
+          for (j = 1; j < helperSlices.length; j++) {
+            var slice = helperSlices[j];
+            if (isArray(slice)) {
+              // Hash
+              helperHash[slice[0]] = slice[1] === 'false' ? false : slice[1];
+            }
+            else {
+              helperContext.push(slice);
+            }
+          }
+
+          if (block.indexOf('{#') >= 0) {
+            // Condition/Helper
+            var helperStartIndex = i;
+            var helperContent = '';
+            var elseContent = '';
+            var toSkip = 0;
+            var shiftIndex;
+            var foundClosed = false, foundElse = false, foundClosedElse = false, depth = 0;
+            for (j = i + 1; j < _blocks.length; j++) {
+              if (_blocks[j].indexOf('{{#') >= 0) {
+                depth ++;
+              }
+              if (_blocks[j].indexOf('{{/') >= 0) {
+                depth --;
+              }
+              if (_blocks[j].indexOf('{{#' + helperName) >= 0) {
+                helperContent += _blocks[j];
+                if (foundElse) elseContent += _blocks[j];
+                toSkip ++;
+              }
+              else if (_blocks[j].indexOf('{{/' + helperName) >= 0) {
+                if (toSkip > 0) {
+                  toSkip--;
+                  helperContent += _blocks[j];
+                  if (foundElse) elseContent += _blocks[j];
+                }
+                else {
+                  shiftIndex = j;
+                  foundClosed = true;
+                  break;
+                }
+              }
+              else if (_blocks[j].indexOf('else') >= 0 && depth === 0) {
+                foundElse = true;
+              }
+              else {
+                if (!foundElse) helperContent += _blocks[j];
+                if (foundElse) elseContent += _blocks[j];
+              }
+
+            }
+            if (foundClosed) {
+              if (shiftIndex) i = shiftIndex;
+              blocks.push({
+                type: 'helper',
+                helperName: helperName,
+                contextName: helperContext,
+                content: helperContent,
+                inverseContent: elseContent,
+                hash: helperHash
+              });
+            }
+          }
+          else if (block.indexOf(' ') > 0) {
+            blocks.push({
+              type: 'helper',
+              helperName: helperName,
+              contextName: helperContext,
+              hash: helperHash
+            });
+          }
+        }
+      }
+      return blocks;
+    }
+    var Template7 = function (template) {
+      var t = this;
+      t.template = template;
+
+      function getCompileFn(block, depth) {
+        if (block.content) return compile(block.content, depth);
+        else return function () {return ''; };
+      }
+      function getCompileInverse(block, depth) {
+        if (block.inverseContent) return compile(block.inverseContent, depth);
+        else return function () {return ''; };
+      }
+      function getCompileVar(name, ctx) {
+        var variable, parts, levelsUp = 0, initialCtx = ctx;
+        if (name.indexOf('../') === 0) {
+          levelsUp = name.split('../').length - 1;
+          var newDepth = ctx.split('_')[1] - levelsUp;
+          ctx = 'ctx_' + (newDepth >= 1 ? newDepth : 1);
+          parts = name.split('../')[levelsUp].split('.');
+        }
+        else if (name.indexOf('@global') === 0) {
+          ctx = '$.Template7.global';
+          parts = name.split('@global.')[1].split('.');
+        }
+        else if (name.indexOf('@root') === 0) {
+          ctx = 'ctx_1';
+          parts = name.split('@root.')[1].split('.');
+        }
+        else {
+          parts = name.split('.');
+        }
+        variable = ctx;
+        for (var i = 0; i < parts.length; i++) {
+          var part = parts[i];
+          if (part.indexOf('@') === 0) {
+            if (i > 0) {
+              variable += '[(data && data.' + part.replace('@', '') + ')]';
+            }
+            else {
+              variable = '(data && data.' + name.replace('@', '') + ')';
+            }
+          }
+          else {
+            if (isFinite(part)) {
+              variable += '[' + part + ']';
+            }
+            else {
+              if (part.indexOf('this') === 0) {
+                variable = part.replace('this', ctx);
+              }
+              else {
+                variable += '.' + part;       
+              }
+            }
+          }
+        }
+
+        return variable;
+      }
+      function getCompiledArguments(contextArray, ctx) {
+        var arr = [];
+        for (var i = 0; i < contextArray.length; i++) {
+          if (contextArray[i].indexOf('"') === 0) arr.push(contextArray[i]);
+          else {
+            arr.push(getCompileVar(contextArray[i], ctx));
+          }
+        }
+        return arr.join(', ');
+      }
+      function compile(template, depth) {
+        depth = depth || 1;
+        template = template || t.template;
+        if (typeof template !== 'string') {
+          throw new Error('Template7: Template must be a string');
+        }
+        var blocks = stringToBlocks(template);
+        if (blocks.length === 0) {
+          return function () { return ''; };
+        }
+        var ctx = 'ctx_' + depth;
+        var resultString = '(function (' + ctx + ', data) {\n';
+        if (depth === 1) {
+          resultString += 'function isArray(arr){return Object.prototype.toString.apply(arr) === \'[object Array]\';}\n';
+          resultString += 'function isFunction(func){return (typeof func === \'function\');}\n';
+          resultString += 'function c(val, ctx) {if (typeof val !== "undefined") {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n';
+        }
+        resultString += 'var r = \'\';\n';
+        var i, j, context;
+        for (i = 0; i < blocks.length; i++) {
+          var block = blocks[i];
+          // Plain block
+          if (block.type === 'plain') {
+            resultString += 'r +=\'' + (block.content).replace(/\r/g, '\\r').replace(/\n/g, '\\n').replace(/'/g, '\\' + '\'') + '\';';
+            continue;
+          }
+          var variable, compiledArguments;
+          // Variable block
+          if (block.type === 'variable') {
+            variable = getCompileVar(block.contextName, ctx);
+            resultString += 'r += c(' + variable + ', ' + ctx + ');';
+          }
+          // Helpers block
+          if (block.type === 'helper') {
+            if (block.helperName in t.helpers) {
+              compiledArguments = getCompiledArguments(block.contextName, ctx);
+              resultString += 'r += ($.Template7.helpers.' + block.helperName + ').call(' + ctx + ', ' + (compiledArguments && (compiledArguments + ', ')) +'{hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+            }
+            else {
+              if (block.contextName.length > 0) {
+                throw new Error('Template7: Missing helper: "' + block.helperName + '"');
+              }
+              else {
+                variable = getCompileVar(block.helperName, ctx);
+                resultString += 'if (' + variable + ') {';
+                resultString += 'if (isArray(' + variable + ')) {';
+                resultString += 'r += ($.Template7.helpers.each).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+                resultString += '}else {';
+                resultString += 'r += ($.Template7.helpers.with).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+                resultString += '}}';
+              }
+            }
+          }
+        }
+        resultString += '\nreturn r;})';
+        return eval.call(window, resultString);
+      }
+      t.compile = function (template) {
+        if (!t.compiled) {
+          t.compiled = compile(template);
+        }
+        return t.compiled;
+      };
+    };
+    Template7.prototype = {
+      options: {},
+      helpers: {
+        'if': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          if (context) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);
+          }
+        },
+        'unless': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          if (!context) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);
+          }
+        },
+        'each': function (context, options) {
+          var ret = '', i = 0;
+          if (isFunction(context)) { context = context.call(this); }
+          if (isArray(context)) {
+            if (options.hash.reverse) {
+              context = context.reverse();
+            }
+            for (i = 0; i < context.length; i++) {
+              ret += options.fn(context[i], {first: i === 0, last: i === context.length - 1, index: i});
+            }
+            if (options.hash.reverse) {
+              context = context.reverse();
+            }
+          }
+          else {
+            for (var key in context) {
+              i++;
+              ret += options.fn(context[key], {key: key});
+            }
+          }
+          if (i > 0) return ret;
+          else return options.inverse(this);
+        },
+        'with': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          return options.fn(context);
+        },
+        'join': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          return context.join(options.hash.delimiter || options.hash.delimeter);
+        },
+        'js': function (expression, options) {
+          var func;
+          if (expression.indexOf('return')>=0) {
+            func = '(function(){'+expression+'})';
+          }
+          else {
+            func = '(function(){return ('+expression+')})';
+          }
+          return eval.call(this, func).call(this);
+        },
+        'js_compare': function (expression, options) {
+          var func;
+          if (expression.indexOf('return')>=0) {
+            func = '(function(){'+expression+'})';
+          }
+          else {
+            func = '(function(){return ('+expression+')})';
+          }
+          var condition = eval.call(this, func).call(this);
+          if (condition) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);   
+          }
+        }
+      }
+    };
+    var t7 = function (template, data) {
+      if (arguments.length === 2) {
+        var instance = new Template7(template);
+        var rendered = instance.compile()(data);
+        instance = null;
+        return (rendered);
+      }
+      else return new Template7(template);
+    };
+    t7.registerHelper = function (name, fn) {
+      Template7.prototype.helpers[name] = fn;
+    };
+    t7.unregisterHelper = function (name) {
+      Template7.prototype.helpers[name] = undefined;  
+      delete Template7.prototype.helpers[name];
+    };
+
+    t7.compile = function (template, options) {
+      var instance = new Template7(template, options);
+      return instance.compile();
+    };
+
+    t7.options = Template7.prototype.options;
+    t7.helpers = Template7.prototype.helpers;
+    return t7;
+  })();
+}($);
+
+/*! Hammer.JS - v2.0.8 - 2016-04-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the MIT license */
+(function(window, document, exportName, undefined) {
+  'use strict';
+
+var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
+var TEST_ELEMENT = document.createElement('div');
+
+var TYPE_FUNCTION = 'function';
+
+var round = Math.round;
+var abs = Math.abs;
+var now = Date.now;
+
+/**
+ * set a timeout with a given scope
+ * @param {Function} fn
+ * @param {Number} timeout
+ * @param {Object} context
+ * @returns {number}
+ */
+function setTimeoutContext(fn, timeout, context) {
+    return setTimeout(bindFn(fn, context), timeout);
+}
+
+/**
+ * if the argument is an array, we want to execute the fn on each entry
+ * if it aint an array we don't want to do a thing.
+ * this is used by all the methods that accept a single and array argument.
+ * @param {*|Array} arg
+ * @param {String} fn
+ * @param {Object} [context]
+ * @returns {Boolean}
+ */
+function invokeArrayArg(arg, fn, context) {
+    if (Array.isArray(arg)) {
+        each(arg, context[fn], context);
+        return true;
+    }
+    return false;
+}
+
+/**
+ * walk objects and arrays
+ * @param {Object} obj
+ * @param {Function} iterator
+ * @param {Object} context
+ */
+function each(obj, iterator, context) {
+    var i;
+
+    if (!obj) {
+        return;
+    }
+
+    if (obj.forEach) {
+        obj.forEach(iterator, context);
+    } else if (obj.length !== undefined) {
+        i = 0;
+        while (i < obj.length) {
+            iterator.call(context, obj[i], i, obj);
+            i++;
+        }
+    } else {
+        for (i in obj) {
+            obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
+        }
+    }
+}
+
+/**
+ * wrap a method with a deprecation warning and stack trace
+ * @param {Function} method
+ * @param {String} name
+ * @param {String} message
+ * @returns {Function} A new function wrapping the supplied method.
+ */
+function deprecate(method, name, message) {
+    var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
+    return function() {
+        var e = new Error('get-stack-trace');
+        var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
+            .replace(/^\s+at\s+/gm, '')
+            .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
+
+        var log = window.console && (window.console.warn || window.console.log);
+        if (log) {
+            log.call(window.console, deprecationMessage, stack);
+        }
+        return method.apply(this, arguments);
+    };
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} target
+ * @param {...Object} objects_to_assign
+ * @returns {Object} target
+ */
+var assign;
+if (typeof Object.assign !== 'function') {
+    assign = function assign(target) {
+        if (target === undefined || target === null) {
+            throw new TypeError('Cannot convert undefined or null to object');
+        }
+
+        var output = Object(target);
+        for (var index = 1; index < arguments.length; index++) {
+            var source = arguments[index];
+            if (source !== undefined && source !== null) {
+                for (var nextKey in source) {
+                    if (source.hasOwnProperty(nextKey)) {
+                        output[nextKey] = source[nextKey];
+                    }
+                }
+            }
+        }
+        return output;
+    };
+} else {
+    assign = Object.assign;
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} dest
+ * @param {Object} src
+ * @param {Boolean} [merge=false]
+ * @returns {Object} dest
+ */
+var extend = deprecate(function extend(dest, src, merge) {
+    var keys = Object.keys(src);
+    var i = 0;
+    while (i < keys.length) {
+        if (!merge || (merge && dest[keys[i]] === undefined)) {
+            dest[keys[i]] = src[keys[i]];
+        }
+        i++;
+    }
+    return dest;
+}, 'extend', 'Use `assign`.');
+
+/**
+ * merge the values from src in the dest.
+ * means that properties that exist in dest will not be overwritten by src
+ * @param {Object} dest
+ * @param {Object} src
+ * @returns {Object} dest
+ */
+var merge = deprecate(function merge(dest, src) {
+    return extend(dest, src, true);
+}, 'merge', 'Use `assign`.');
+
+/**
+ * simple class inheritance
+ * @param {Function} child
+ * @param {Function} base
+ * @param {Object} [properties]
+ */
+function inherit(child, base, properties) {
+    var baseP = base.prototype,
+        childP;
+
+    childP = child.prototype = Object.create(baseP);
+    childP.constructor = child;
+    childP._super = baseP;
+
+    if (properties) {
+        assign(childP, properties);
+    }
+}
+
+/**
+ * simple function bind
+ * @param {Function} fn
+ * @param {Object} context
+ * @returns {Function}
+ */
+function bindFn(fn, context) {
+    return function boundFn() {
+        return fn.apply(context, arguments);
+    };
+}
+
+/**
+ * let a boolean value also be a function that must return a boolean
+ * this first item in args will be used as the context
+ * @param {Boolean|Function} val
+ * @param {Array} [args]
+ * @returns {Boolean}
+ */
+function boolOrFn(val, args) {
+    if (typeof val == TYPE_FUNCTION) {
+        return val.apply(args ? args[0] || undefined : undefined, args);
+    }
+    return val;
+}
+
+/**
+ * use the val2 when val1 is undefined
+ * @param {*} val1
+ * @param {*} val2
+ * @returns {*}
+ */
+function ifUndefined(val1, val2) {
+    return (val1 === undefined) ? val2 : val1;
+}
+
+/**
+ * addEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function addEventListeners(target, types, handler) {
+    each(splitStr(types), function(type) {
+        target.addEventListener(type, handler, false);
+    });
+}
+
+/**
+ * removeEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function removeEventListeners(target, types, handler) {
+    each(splitStr(types), function(type) {
+        target.removeEventListener(type, handler, false);
+    });
+}
+
+/**
+ * find if a node is in the given parent
+ * @method hasParent
+ * @param {HTMLElement} node
+ * @param {HTMLElement} parent
+ * @return {Boolean} found
+ */
+function hasParent(node, parent) {
+    while (node) {
+        if (node == parent) {
+            return true;
+        }
+        node = node.parentNode;
+    }
+    return false;
+}
+
+/**
+ * small indexOf wrapper
+ * @param {String} str
+ * @param {String} find
+ * @returns {Boolean} found
+ */
+function inStr(str, find) {
+    return str.indexOf(find) > -1;
+}
+
+/**
+ * split string on whitespace
+ * @param {String} str
+ * @returns {Array} words
+ */
+function splitStr(str) {
+    return str.trim().split(/\s+/g);
+}
+
+/**
+ * find if a array contains the object using indexOf or a simple polyFill
+ * @param {Array} src
+ * @param {String} find
+ * @param {String} [findByKey]
+ * @return {Boolean|Number} false when not found, or the index
+ */
+function inArray(src, find, findByKey) {
+    if (src.indexOf && !findByKey) {
+        return src.indexOf(find);
+    } else {
+        var i = 0;
+        while (i < src.length) {
+            if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
+                return i;
+            }
+            i++;
+        }
+        return -1;
+    }
+}
+
+/**
+ * convert array-like objects to real arrays
+ * @param {Object} obj
+ * @returns {Array}
+ */
+function toArray(obj) {
+    return Array.prototype.slice.call(obj, 0);
+}
+
+/**
+ * unique array with objects based on a key (like 'id') or just by the array's value
+ * @param {Array} src [{id:1},{id:2},{id:1}]
+ * @param {String} [key]
+ * @param {Boolean} [sort=False]
+ * @returns {Array} [{id:1},{id:2}]
+ */
+function uniqueArray(src, key, sort) {
+    var results = [];
+    var values = [];
+    var i = 0;
+
+    while (i < src.length) {
+        var val = key ? src[i][key] : src[i];
+        if (inArray(values, val) < 0) {
+            results.push(src[i]);
+        }
+        values[i] = val;
+        i++;
+    }
+
+    if (sort) {
+        if (!key) {
+            results = results.sort();
+        } else {
+            results = results.sort(function sortUniqueArray(a, b) {
+                return a[key] > b[key];
+            });
+        }
+    }
+
+    return results;
+}
+
+/**
+ * get the prefixed property
+ * @param {Object} obj
+ * @param {String} property
+ * @returns {String|Undefined} prefixed
+ */
+function prefixed(obj, property) {
+    var prefix, prop;
+    var camelProp = property[0].toUpperCase() + property.slice(1);
+
+    var i = 0;
+    while (i < VENDOR_PREFIXES.length) {
+        prefix = VENDOR_PREFIXES[i];
+        prop = (prefix) ? prefix + camelProp : property;
+
+        if (prop in obj) {
+            return prop;
+        }
+        i++;
+    }
+    return undefined;
+}
+
+/**
+ * get a unique id
+ * @returns {number} uniqueId
+ */
+var _uniqueId = 1;
+function uniqueId() {
+    return _uniqueId++;
+}
+
+/**
+ * get the window object of an element
+ * @param {HTMLElement} element
+ * @returns {DocumentView|Window}
+ */
+function getWindowForElement(element) {
+    var doc = element.ownerDocument || element;
+    return (doc.defaultView || doc.parentWindow || window);
+}
+
+var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
+
+var SUPPORT_TOUCH = ('ontouchstart' in window);
+var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
+var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
+
+var INPUT_TYPE_TOUCH = 'touch';
+var INPUT_TYPE_PEN = 'pen';
+var INPUT_TYPE_MOUSE = 'mouse';
+var INPUT_TYPE_KINECT = 'kinect';
+
+var COMPUTE_INTERVAL = 25;
+
+var INPUT_START = 1;
+var INPUT_MOVE = 2;
+var INPUT_END = 4;
+var INPUT_CANCEL = 8;
+
+var DIRECTION_NONE = 1;
+var DIRECTION_LEFT = 2;
+var DIRECTION_RIGHT = 4;
+var DIRECTION_UP = 8;
+var DIRECTION_DOWN = 16;
+
+var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
+var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
+var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
+
+var PROPS_XY = ['x', 'y'];
+var PROPS_CLIENT_XY = ['clientX', 'clientY'];
+
+/**
+ * create new input type manager
+ * @param {Manager} manager
+ * @param {Function} callback
+ * @returns {Input}
+ * @constructor
+ */
+function Input(manager, callback) {
+    var self = this;
+    this.manager = manager;
+    this.callback = callback;
+    this.element = manager.element;
+    this.target = manager.options.inputTarget;
+
+    // smaller wrapper around the handler, for the scope and the enabled state of the manager,
+    // so when disabled the input events are completely bypassed.
+    this.domHandler = function(ev) {
+        if (boolOrFn(manager.options.enable, [manager])) {
+            self.handler(ev);
+        }
+    };
+
+    this.init();
+
+}
+
+Input.prototype = {
+    /**
+     * should handle the inputEvent data and trigger the callback
+     * @virtual
+     */
+    handler: function() { },
+
+    /**
+     * bind the events
+     */
+    init: function() {
+        this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
+        this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
+        this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+    },
+
+    /**
+     * unbind the events
+     */
+    destroy: function() {
+        this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
+        this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
+        this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+    }
+};
+
+/**
+ * create new input type manager
+ * called by the Manager constructor
+ * @param {Hammer} manager
+ * @returns {Input}
+ */
+function createInputInstance(manager) {
+    var Type;
+    var inputClass = manager.options.inputClass;
+
+    if (inputClass) {
+        Type = inputClass;
+    } else if (SUPPORT_POINTER_EVENTS) {
+        Type = PointerEventInput;
+    } else if (SUPPORT_ONLY_TOUCH) {
+        Type = TouchInput;
+    } else if (!SUPPORT_TOUCH) {
+        Type = MouseInput;
+    } else {
+        Type = TouchMouseInput;
+    }
+    return new (Type)(manager, inputHandler);
+}
+
+/**
+ * handle input events
+ * @param {Manager} manager
+ * @param {String} eventType
+ * @param {Object} input
+ */
+function inputHandler(manager, eventType, input) {
+    var pointersLen = input.pointers.length;
+    var changedPointersLen = input.changedPointers.length;
+    var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
+    var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
+
+    input.isFirst = !!isFirst;
+    input.isFinal = !!isFinal;
+
+    if (isFirst) {
+        manager.session = {};
+    }
+
+    // source event is the normalized value of the domEvents
+    // like 'touchstart, mouseup, pointerdown'
+    input.eventType = eventType;
+
+    // compute scale, rotation etc
+    computeInputData(manager, input);
+
+    // emit secret event
+    manager.emit('hammer.input', input);
+
+    manager.recognize(input);
+    manager.session.prevInput = input;
+}
+
+/**
+ * extend the data with some usable properties like scale, rotate, velocity etc
+ * @param {Object} manager
+ * @param {Object} input
+ */
+function computeInputData(manager, input) {
+    var session = manager.session;
+    var pointers = input.pointers;
+    var pointersLength = pointers.length;
+
+    // store the first input to calculate the distance and direction
+    if (!session.firstInput) {
+        session.firstInput = simpleCloneInputData(input);
+    }
+
+    // to compute scale and rotation we need to store the multiple touches
+    if (pointersLength > 1 && !session.firstMultiple) {
+        session.firstMultiple = simpleCloneInputData(input);
+    } else if (pointersLength === 1) {
+        session.firstMultiple = false;
+    }
+
+    var firstInput = session.firstInput;
+    var firstMultiple = session.firstMultiple;
+    var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
+
+    var center = input.center = getCenter(pointers);
+    input.timeStamp = now();
+    input.deltaTime = input.timeStamp - firstInput.timeStamp;
+
+    input.angle = getAngle(offsetCenter, center);
+    input.distance = getDistance(offsetCenter, center);
+
+    computeDeltaXY(session, input);
+    input.offsetDirection = getDirection(input.deltaX, input.deltaY);
+
+    var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
+    input.overallVelocityX = overallVelocity.x;
+    input.overallVelocityY = overallVelocity.y;
+    input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
+
+    input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
+    input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
+
+    input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
+        session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
+
+    computeIntervalInputData(session, input);
+
+    // find the correct target
+    var target = manager.element;
+    if (hasParent(input.srcEvent.target, target)) {
+        target = input.srcEvent.target;
+    }
+    input.target = target;
+}
+
+function computeDeltaXY(session, input) {
+    var center = input.center;
+    var offset = session.offsetDelta || {};
+    var prevDelta = session.prevDelta || {};
+    var prevInput = session.prevInput || {};
+
+    if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
+        prevDelta = session.prevDelta = {
+            x: prevInput.deltaX || 0,
+            y: prevInput.deltaY || 0
+        };
+
+        offset = session.offsetDelta = {
+            x: center.x,
+            y: center.y
+        };
+    }
+
+    input.deltaX = prevDelta.x + (center.x - offset.x);
+    input.deltaY = prevDelta.y + (center.y - offset.y);
+}
+
+/**
+ * velocity is calculated every x ms
+ * @param {Object} session
+ * @param {Object} input
+ */
+function computeIntervalInputData(session, input) {
+    var last = session.lastInterval || input,
+        deltaTime = input.timeStamp - last.timeStamp,
+        velocity, velocityX, velocityY, direction;
+
+    if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
+        var deltaX = input.deltaX - last.deltaX;
+        var deltaY = input.deltaY - last.deltaY;
+
+        var v = getVelocity(deltaTime, deltaX, deltaY);
+        velocityX = v.x;
+        velocityY = v.y;
+        velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
+        direction = getDirection(deltaX, deltaY);
+
+        session.lastInterval = input;
+    } else {
+        // use latest velocity info if it doesn't overtake a minimum period
+        velocity = last.velocity;
+        velocityX = last.velocityX;
+        velocityY = last.velocityY;
+        direction = last.direction;
+    }
+
+    input.velocity = velocity;
+    input.velocityX = velocityX;
+    input.velocityY = velocityY;
+    input.direction = direction;
+}
+
+/**
+ * create a simple clone from the input used for storage of firstInput and firstMultiple
+ * @param {Object} input
+ * @returns {Object} clonedInputData
+ */
+function simpleCloneInputData(input) {
+    // make a simple copy of the pointers because we will get a reference if we don't
+    // we only need clientXY for the calculations
+    var pointers = [];
+    var i = 0;
+    while (i < input.pointers.length) {
+        pointers[i] = {
+            clientX: round(input.pointers[i].clientX),
+            clientY: round(input.pointers[i].clientY)
+        };
+        i++;
+    }
+
+    return {
+        timeStamp: now(),
+        pointers: pointers,
+        center: getCenter(pointers),
+        deltaX: input.deltaX,
+        deltaY: input.deltaY
+    };
+}
+
+/**
+ * get the center of all the pointers
+ * @param {Array} pointers
+ * @return {Object} center contains `x` and `y` properties
+ */
+function getCenter(pointers) {
+    var pointersLength = pointers.length;
+
+    // no need to loop when only one touch
+    if (pointersLength === 1) {
+        return {
+            x: round(pointers[0].clientX),
+            y: round(pointers[0].clientY)
+        };
+    }
+
+    var x = 0, y = 0, i = 0;
+    while (i < pointersLength) {
+        x += pointers[i].clientX;
+        y += pointers[i].clientY;
+        i++;
+    }
+
+    return {
+        x: round(x / pointersLength),
+        y: round(y / pointersLength)
+    };
+}
+
+/**
+ * calculate the velocity between two points. unit is in px per ms.
+ * @param {Number} deltaTime
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Object} velocity `x` and `y`
+ */
+function getVelocity(deltaTime, x, y) {
+    return {
+        x: x / deltaTime || 0,
+        y: y / deltaTime || 0
+    };
+}
+
+/**
+ * get the direction between two points
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Number} direction
+ */
+function getDirection(x, y) {
+    if (x === y) {
+        return DIRECTION_NONE;
+    }
+
+    if (abs(x) >= abs(y)) {
+        return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
+    }
+    return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
+}
+
+/**
+ * calculate the absolute distance between two points
+ * @param {Object} p1 {x, y}
+ * @param {Object} p2 {x, y}
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} distance
+ */
+function getDistance(p1, p2, props) {
+    if (!props) {
+        props = PROPS_XY;
+    }
+    var x = p2[props[0]] - p1[props[0]],
+        y = p2[props[1]] - p1[props[1]];
+
+    return Math.sqrt((x * x) + (y * y));
+}
+
+/**
+ * calculate the angle between two coordinates
+ * @param {Object} p1
+ * @param {Object} p2
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} angle
+ */
+function getAngle(p1, p2, props) {
+    if (!props) {
+        props = PROPS_XY;
+    }
+    var x = p2[props[0]] - p1[props[0]],
+        y = p2[props[1]] - p1[props[1]];
+    return Math.atan2(y, x) * 180 / Math.PI;
+}
+
+/**
+ * calculate the rotation degrees between two pointersets
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} rotation
+ */
+function getRotation(start, end) {
+    return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
+}
+
+/**
+ * calculate the scale factor between two pointersets
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} scale
+ */
+function getScale(start, end) {
+    return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
+}
+
+var MOUSE_INPUT_MAP = {
+    mousedown: INPUT_START,
+    mousemove: INPUT_MOVE,
+    mouseup: INPUT_END
+};
+
+var MOUSE_ELEMENT_EVENTS = 'mousedown';
+var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
+
+/**
+ * Mouse events input
+ * @constructor
+ * @extends Input
+ */
+function MouseInput() {
+    this.evEl = MOUSE_ELEMENT_EVENTS;
+    this.evWin = MOUSE_WINDOW_EVENTS;
+
+    this.pressed = false; // mousedown state
+
+    Input.apply(this, arguments);
+}
+
+inherit(MouseInput, Input, {
+    /**
+     * handle mouse events
+     * @param {Object} ev
+     */
+    handler: function MEhandler(ev) {
+        var eventType = MOUSE_INPUT_MAP[ev.type];
+
+        // on start we want to have the left mouse button down
+        if (eventType & INPUT_START && ev.button === 0) {
+            this.pressed = true;
+        }
+
+        if (eventType & INPUT_MOVE && ev.which !== 1) {
+            eventType = INPUT_END;
+        }
+
+        // mouse must be down
+        if (!this.pressed) {
+            return;
+        }
+
+        if (eventType & INPUT_END) {
+            this.pressed = false;
+        }
+
+        this.callback(this.manager, eventType, {
+            pointers: [ev],
+            changedPointers: [ev],
+            pointerType: INPUT_TYPE_MOUSE,
+            srcEvent: ev
+        });
+    }
+});
+
+var POINTER_INPUT_MAP = {
+    pointerdown: INPUT_START,
+    pointermove: INPUT_MOVE,
+    pointerup: INPUT_END,
+    pointercancel: INPUT_CANCEL,
+    pointerout: INPUT_CANCEL
+};
+
+// in IE10 the pointer types is defined as an enum
+var IE10_POINTER_TYPE_ENUM = {
+    2: INPUT_TYPE_TOUCH,
+    3: INPUT_TYPE_PEN,
+    4: INPUT_TYPE_MOUSE,
+    5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
+};
+
+var POINTER_ELEMENT_EVENTS = 'pointerdown';
+var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
+
+// IE10 has prefixed support, and case-sensitive
+if (window.MSPointerEvent && !window.PointerEvent) {
+    POINTER_ELEMENT_EVENTS = 'MSPointerDown';
+    POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
+}
+
+/**
+ * Pointer events input
+ * @constructor
+ * @extends Input
+ */
+function PointerEventInput() {
+    this.evEl = POINTER_ELEMENT_EVENTS;
+    this.evWin = POINTER_WINDOW_EVENTS;
+
+    Input.apply(this, arguments);
+
+    this.store = (this.manager.session.pointerEvents = []);
+}
+
+inherit(PointerEventInput, Input, {
+    /**
+     * handle mouse events
+     * @param {Object} ev
+     */
+    handler: function PEhandler(ev) {
+        var store = this.store;
+        var removePointer = false;
+
+        var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
+        var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
+        var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
+
+        var isTouch = (pointerType == INPUT_TYPE_TOUCH);
+
+        // get index of the event in the store
+        var storeIndex = inArray(store, ev.pointerId, 'pointerId');
+
+        // start and mouse must be down
+        if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
+            if (storeIndex < 0) {
+                store.push(ev);
+                storeIndex = store.length - 1;
+            }
+        } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+            removePointer = true;
+        }
+
+        // it not found, so the pointer hasn't been down (so it's probably a hover)
+        if (storeIndex < 0) {
+            return;
+        }
+
+        // update the event in the store
+        store[storeIndex] = ev;
+
+        this.callback(this.manager, eventType, {
+            pointers: store,
+            changedPointers: [ev],
+            pointerType: pointerType,
+            srcEvent: ev
+        });
+
+        if (removePointer) {
+            // remove from the store
+            store.splice(storeIndex, 1);
+        }
+    }
+});
+
+var SINGLE_TOUCH_INPUT_MAP = {
+    touchstart: INPUT_START,
+    touchmove: INPUT_MOVE,
+    touchend: INPUT_END,
+    touchcancel: INPUT_CANCEL
+};
+
+var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
+var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Touch events input
+ * @constructor
+ * @extends Input
+ */
+function SingleTouchInput() {
+    this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
+    this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
+    this.started = false;
+
+    Input.apply(this, arguments);
+}
+
+inherit(SingleTouchInput, Input, {
+    handler: function TEhandler(ev) {
+        var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
+
+        // should we handle the touch events?
+        if (type === INPUT_START) {
+            this.started = true;
+        }
+
+        if (!this.started) {
+            return;
+        }
+
+        var touches = normalizeSingleTouches.call(this, ev, type);
+
+        // when done, reset the started state
+        if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
+            this.started = false;
+        }
+
+        this.callback(this.manager, type, {
+            pointers: touches[0],
+            changedPointers: touches[1],
+            pointerType: INPUT_TYPE_TOUCH,
+            srcEvent: ev
+        });
+    }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function normalizeSingleTouches(ev, type) {
+    var all = toArray(ev.touches);
+    var changed = toArray(ev.changedTouches);
+
+    if (type & (INPUT_END | INPUT_CANCEL)) {
+        all = uniqueArray(all.concat(changed), 'identifier', true);
+    }
+
+    return [all, changed];
+}
+
+var TOUCH_INPUT_MAP = {
+    touchstart: INPUT_START,
+    touchmove: INPUT_MOVE,
+    touchend: INPUT_END,
+    touchcancel: INPUT_CANCEL
+};
+
+var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Multi-user touch events input
+ * @constructor
+ * @extends Input
+ */
+function TouchInput() {
+    this.evTarget = TOUCH_TARGET_EVENTS;
+    this.targetIds = {};
+
+    Input.apply(this, arguments);
+}
+
+inherit(TouchInput, Input, {
+    handler: function MTEhandler(ev) {
+        var type = TOUCH_INPUT_MAP[ev.type];
+        var touches = getTouches.call(this, ev, type);
+        if (!touches) {
+            return;
+        }
+
+        this.callback(this.manager, type, {
+            pointers: touches[0],
+            changedPointers: touches[1],
+            pointerType: INPUT_TYPE_TOUCH,
+            srcEvent: ev
+        });
+    }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function getTouches(ev, type) {
+    var allTouches = toArray(ev.touches);
+    var targetIds = this.targetIds;
+
+    // when there is only one touch, the process can be simplified
+    if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
+        targetIds[allTouches[0].identifier] = true;
+        return [allTouches, allTouches];
+    }
+
+    var i,
+        targetTouches,
+        changedTouches = toArray(ev.changedTouches),
+        changedTargetTouches = [],
+        target = this.target;
+
+    // get target touches from touches
+    targetTouches = allTouches.filter(function(touch) {
+        return hasParent(touch.target, target);
+    });
+
+    // collect touches
+    if (type === INPUT_START) {
+        i = 0;
+        while (i < targetTouches.length) {
+            targetIds[targetTouches[i].identifier] = true;
+            i++;
+        }
+    }
+
+    // filter changed touches to only contain touches that exist in the collected target ids
+    i = 0;
+    while (i < changedTouches.length) {
+        if (targetIds[changedTouches[i].identifier]) {
+            changedTargetTouches.push(changedTouches[i]);
+        }
+
+        // cleanup removed touches
+        if (type & (INPUT_END | INPUT_CANCEL)) {
+            delete targetIds[changedTouches[i].identifier];
+        }
+        i++;
+    }
+
+    if (!changedTargetTouches.length) {
+        return;
+    }
+
+    return [
+        // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
+        uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
+        changedTargetTouches
+    ];
+}
+
+/**
+ * Combined touch and mouse input
+ *
+ * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
+ * This because touch devices also emit mouse events while doing a touch.
+ *
+ * @constructor
+ * @extends Input
+ */
+
+var DEDUP_TIMEOUT = 2500;
+var DEDUP_DISTANCE = 25;
+
+function TouchMouseInput() {
+    Input.apply(this, arguments);
+
+    var handler = bindFn(this.handler, this);
+    this.touch = new TouchInput(this.manager, handler);
+    this.mouse = new MouseInput(this.manager, handler);
+
+    this.primaryTouch = null;
+    this.lastTouches = [];
+}
+
+inherit(TouchMouseInput, Input, {
+    /**
+     * handle mouse and touch events
+     * @param {Hammer} manager
+     * @param {String} inputEvent
+     * @param {Object} inputData
+     */
+    handler: function TMEhandler(manager, inputEvent, inputData) {
+        var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
+            isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
+
+        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
+            return;
+        }
+
+        // when we're in a touch event, record touches to  de-dupe synthetic mouse event
+        if (isTouch) {
+            recordTouches.call(this, inputEvent, inputData);
+        } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
+            return;
+        }
+
+        this.callback(manager, inputEvent, inputData);
+    },
+
+    /**
+     * remove the event listeners
+     */
+    destroy: function destroy() {
+        this.touch.destroy();
+        this.mouse.destroy();
+    }
+});
+
+function recordTouches(eventType, eventData) {
+    if (eventType & INPUT_START) {
+        this.primaryTouch = eventData.changedPointers[0].identifier;
+        setLastTouch.call(this, eventData);
+    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+        setLastTouch.call(this, eventData);
+    }
+}
+
+function setLastTouch(eventData) {
+    var touch = eventData.changedPointers[0];
+
+    if (touch.identifier === this.primaryTouch) {
+        var lastTouch = {x: touch.clientX, y: touch.clientY};
+        this.lastTouches.push(lastTouch);
+        var lts = this.lastTouches;
+        var removeLastTouch = function() {
+            var i = lts.indexOf(lastTouch);
+            if (i > -1) {
+                lts.splice(i, 1);
+            }
+        };
+        setTimeout(removeLastTouch, DEDUP_TIMEOUT);
+    }
+}
+
+function isSyntheticEvent(eventData) {
+    var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
+    for (var i = 0; i < this.lastTouches.length; i++) {
+        var t = this.lastTouches[i];
+        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
+        if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
+            return true;
+        }
+    }
+    return false;
+}
+
+var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
+var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
+
+// magical touchAction value
+var TOUCH_ACTION_COMPUTE = 'compute';
+var TOUCH_ACTION_AUTO = 'auto';
+var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
+var TOUCH_ACTION_NONE = 'none';
+var TOUCH_ACTION_PAN_X = 'pan-x';
+var TOUCH_ACTION_PAN_Y = 'pan-y';
+var TOUCH_ACTION_MAP = getTouchActionProps();
+
+/**
+ * Touch Action
+ * sets the touchAction property or uses the js alternative
+ * @param {Manager} manager
+ * @param {String} value
+ * @constructor
+ */
+function TouchAction(manager, value) {
+    this.manager = manager;
+    this.set(value);
+}
+
+TouchAction.prototype = {
+    /**
+     * set the touchAction value on the element or enable the polyfill
+     * @param {String} value
+     */
+    set: function(value) {
+        // find out the touch-action by the event handlers
+        if (value == TOUCH_ACTION_COMPUTE) {
+            value = this.compute();
+        }
+
+        if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
+            this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
+        }
+        this.actions = value.toLowerCase().trim();
+    },
+
+    /**
+     * just re-set the touchAction value
+     */
+    update: function() {
+        this.set(this.manager.options.touchAction);
+    },
+
+    /**
+     * compute the value for the touchAction property based on the recognizer's settings
+     * @returns {String} value
+     */
+    compute: function() {
+        var actions = [];
+        each(this.manager.recognizers, function(recognizer) {
+            if (boolOrFn(recognizer.options.enable, [recognizer])) {
+                actions = actions.concat(recognizer.getTouchAction());
+            }
+        });
+        return cleanTouchActions(actions.join(' '));
+    },
+
+    /**
+     * this method is called on each input cycle and provides the preventing of the browser behavior
+     * @param {Object} input
+     */
+    preventDefaults: function(input) {
+        var srcEvent = input.srcEvent;
+        var direction = input.offsetDirection;
+
+        // if the touch action did prevented once this session
+        if (this.manager.session.prevented) {
+            srcEvent.preventDefault();
+            return;
+        }
+
+        var actions = this.actions;
+        var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
+        var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
+        var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
+
+        if (hasNone) {
+            //do not prevent defaults if this is a tap gesture
+
+            var isTapPointer = input.pointers.length === 1;
+            var isTapMovement = input.distance < 2;
+            var isTapTouchTime = input.deltaTime < 250;
+
+            if (isTapPointer && isTapMovement && isTapTouchTime) {
+                return;
+            }
+        }
+
+        if (hasPanX && hasPanY) {
+            // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
+            return;
+        }
+
+        if (hasNone ||
+            (hasPanY && direction & DIRECTION_HORIZONTAL) ||
+            (hasPanX && direction & DIRECTION_VERTICAL)) {
+            return this.preventSrc(srcEvent);
+        }
+    },
+
+    /**
+     * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
+     * @param {Object} srcEvent
+     */
+    preventSrc: function(srcEvent) {
+        this.manager.session.prevented = true;
+        srcEvent.preventDefault();
+    }
+};
+
+/**
+ * when the touchActions are collected they are not a valid value, so we need to clean things up. *
+ * @param {String} actions
+ * @returns {*}
+ */
+function cleanTouchActions(actions) {
+    // none
+    if (inStr(actions, TOUCH_ACTION_NONE)) {
+        return TOUCH_ACTION_NONE;
+    }
+
+    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
+    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
+
+    // if both pan-x and pan-y are set (different recognizers
+    // for different directions, e.g. horizontal pan but vertical swipe?)
+    // we need none (as otherwise with pan-x pan-y combined none of these
+    // recognizers will work, since the browser would handle all panning
+    if (hasPanX && hasPanY) {
+        return TOUCH_ACTION_NONE;
+    }
+
+    // pan-x OR pan-y
+    if (hasPanX || hasPanY) {
+        return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
+    }
+
+    // manipulation
+    if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
+        return TOUCH_ACTION_MANIPULATION;
+    }
+
+    return TOUCH_ACTION_AUTO;
+}
+
+function getTouchActionProps() {
+    if (!NATIVE_TOUCH_ACTION) {
+        return false;
+    }
+    var touchMap = {};
+    var cssSupports = window.CSS && window.CSS.supports;
+    ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
+
+        // If css.supports is not supported but there is native touch-action assume it supports
+        // all values. This is the case for IE 10 and 11.
+        touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
+    });
+    return touchMap;
+}
+
+/**
+ * Recognizer flow explained; *
+ * All recognizers have the initial state of POSSIBLE when a input session starts.
+ * The definition of a input session is from the first input until the last input, with all it's movement in it. *
+ * Example session for mouse-input: mousedown -> mousemove -> mouseup
+ *
+ * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
+ * which determines with state it should be.
+ *
+ * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
+ * POSSIBLE to give it another change on the next cycle.
+ *
+ *               Possible
+ *                  |
+ *            +-----+---------------+
+ *            |                     |
+ *      +-----+-----+               |
+ *      |           |               |
+ *   Failed      Cancelled          |
+ *                          +-------+------+
+ *                          |              |
+ *                      Recognized       Began
+ *                                         |
+ *                                      Changed
+ *                                         |
+ *                                  Ended/Recognized
+ */
+var STATE_POSSIBLE = 1;
+var STATE_BEGAN = 2;
+var STATE_CHANGED = 4;
+var STATE_ENDED = 8;
+var STATE_RECOGNIZED = STATE_ENDED;
+var STATE_CANCELLED = 16;
+var STATE_FAILED = 32;
+
+/**
+ * Recognizer
+ * Every recognizer needs to extend from this class.
+ * @constructor
+ * @param {Object} options
+ */
+function Recognizer(options) {
+    this.options = assign({}, this.defaults, options || {});
+
+    this.id = uniqueId();
+
+    this.manager = null;
+
+    // default is enable true
+    this.options.enable = ifUndefined(this.options.enable, true);
+
+    this.state = STATE_POSSIBLE;
+
+    this.simultaneous = {};
+    this.requireFail = [];
+}
+
+Recognizer.prototype = {
+    /**
+     * @virtual
+     * @type {Object}
+     */
+    defaults: {},
+
+    /**
+     * set options
+     * @param {Object} options
+     * @return {Recognizer}
+     */
+    set: function(options) {
+        assign(this.options, options);
+
+        // also update the touchAction, in case something changed about the directions/enabled state
+        this.manager && this.manager.touchAction.update();
+        return this;
+    },
+
+    /**
+     * recognize simultaneous with an other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    recognizeWith: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
+            return this;
+        }
+
+        var simultaneous = this.simultaneous;
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        if (!simultaneous[otherRecognizer.id]) {
+            simultaneous[otherRecognizer.id] = otherRecognizer;
+            otherRecognizer.recognizeWith(this);
+        }
+        return this;
+    },
+
+    /**
+     * drop the simultaneous link. it doesnt remove the link on the other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    dropRecognizeWith: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
+            return this;
+        }
+
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        delete this.simultaneous[otherRecognizer.id];
+        return this;
+    },
+
+    /**
+     * recognizer can only run when an other is failing
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    requireFailure: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
+            return this;
+        }
+
+        var requireFail = this.requireFail;
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        if (inArray(requireFail, otherRecognizer) === -1) {
+            requireFail.push(otherRecognizer);
+            otherRecognizer.requireFailure(this);
+        }
+        return this;
+    },
+
+    /**
+     * drop the requireFailure link. it does not remove the link on the other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    dropRequireFailure: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
+            return this;
+        }
+
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        var index = inArray(this.requireFail, otherRecognizer);
+        if (index > -1) {
+            this.requireFail.splice(index, 1);
+        }
+        return this;
+    },
+
+    /**
+     * has require failures boolean
+     * @returns {boolean}
+     */
+    hasRequireFailures: function() {
+        return this.requireFail.length > 0;
+    },
+
+    /**
+     * if the recognizer can recognize simultaneous with an other recognizer
+     * @param {Recognizer} otherRecognizer
+     * @returns {Boolean}
+     */
+    canRecognizeWith: function(otherRecognizer) {
+        return !!this.simultaneous[otherRecognizer.id];
+    },
+
+    /**
+     * You should use `tryEmit` instead of `emit` directly to check
+     * that all the needed recognizers has failed before emitting.
+     * @param {Object} input
+     */
+    emit: function(input) {
+        var self = this;
+        var state = this.state;
+
+        function emit(event) {
+            self.manager.emit(event, input);
+        }
+
+        // 'panstart' and 'panmove'
+        if (state < STATE_ENDED) {
+            emit(self.options.event + stateStr(state));
+        }
+
+        emit(self.options.event); // simple 'eventName' events
+
+        if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
+            emit(input.additionalEvent);
+        }
+
+        // panend and pancancel
+        if (state >= STATE_ENDED) {
+            emit(self.options.event + stateStr(state));
+        }
+    },
+
+    /**
+     * Check that all the require failure recognizers has failed,
+     * if true, it emits a gesture event,
+     * otherwise, setup the state to FAILED.
+     * @param {Object} input
+     */
+    tryEmit: function(input) {
+        if (this.canEmit()) {
+            return this.emit(input);
+        }
+        // it's failing anyway
+        this.state = STATE_FAILED;
+    },
+
+    /**
+     * can we emit?
+     * @returns {boolean}
+     */
+    canEmit: function() {
+        var i = 0;
+        while (i < this.requireFail.length) {
+            if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
+                return false;
+            }
+            i++;
+        }
+        return true;
+    },
+
+    /**
+     * update the recognizer
+     * @param {Object} inputData
+     */
+    recognize: function(inputData) {
+        // make a new copy of the inputData
+        // so we can change the inputData without messing up the other recognizers
+        var inputDataClone = assign({}, inputData);
+
+        // is is enabled and allow recognizing?
+        if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
+            this.reset();
+            this.state = STATE_FAILED;
+            return;
+        }
+
+        // reset when we've reached the end
+        if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
+            this.state = STATE_POSSIBLE;
+        }
+
+        this.state = this.process(inputDataClone);
+
+        // the recognizer has recognized a gesture
+        // so trigger an event
+        if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
+            this.tryEmit(inputDataClone);
+        }
+    },
+
+    /**
+     * return the state of the recognizer
+     * the actual recognizing happens in this method
+     * @virtual
+     * @param {Object} inputData
+     * @returns {Const} STATE
+     */
+    process: function(inputData) { }, // jshint ignore:line
+
+    /**
+     * return the preferred touch-action
+     * @virtual
+     * @returns {Array}
+     */
+    getTouchAction: function() { },
+
+    /**
+     * called when the gesture isn't allowed to recognize
+     * like when another is being recognized or it is disabled
+     * @virtual
+     */
+    reset: function() { }
+};
+
+/**
+ * get a usable string, used as event postfix
+ * @param {Const} state
+ * @returns {String} state
+ */
+function stateStr(state) {
+    if (state & STATE_CANCELLED) {
+        return 'cancel';
+    } else if (state & STATE_ENDED) {
+        return 'end';
+    } else if (state & STATE_CHANGED) {
+        return 'move';
+    } else if (state & STATE_BEGAN) {
+        return 'start';
+    }
+    return '';
+}
+
+/**
+ * direction cons to string
+ * @param {Const} direction
+ * @returns {String}
+ */
+function directionStr(direction) {
+    if (direction == DIRECTION_DOWN) {
+        return 'down';
+    } else if (direction == DIRECTION_UP) {
+        return 'up';
+    } else if (direction == DIRECTION_LEFT) {
+        return 'left';
+    } else if (direction == DIRECTION_RIGHT) {
+        return 'right';
+    }
+    return '';
+}
+
+/**
+ * get a recognizer by name if it is bound to a manager
+ * @param {Recognizer|String} otherRecognizer
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer}
+ */
+function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
+    var manager = recognizer.manager;
+    if (manager) {
+        return manager.get(otherRecognizer);
+    }
+    return otherRecognizer;
+}
+
+/**
+ * This recognizer is just used as a base for the simple attribute recognizers.
+ * @constructor
+ * @extends Recognizer
+ */
+function AttrRecognizer() {
+    Recognizer.apply(this, arguments);
+}
+
+inherit(AttrRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof AttrRecognizer
+     */
+    defaults: {
+        /**
+         * @type {Number}
+         * @default 1
+         */
+        pointers: 1
+    },
+
+    /**
+     * Used to check if it the recognizer receives valid input, like input.distance > 10.
+     * @memberof AttrRecognizer
+     * @param {Object} input
+     * @returns {Boolean} recognized
+     */
+    attrTest: function(input) {
+        var optionPointers = this.options.pointers;
+        return optionPointers === 0 || input.pointers.length === optionPointers;
+    },
+
+    /**
+     * Process the input and return the state for the recognizer
+     * @memberof AttrRecognizer
+     * @param {Object} input
+     * @returns {*} State
+     */
+    process: function(input) {
+        var state = this.state;
+        var eventType = input.eventType;
+
+        var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
+        var isValid = this.attrTest(input);
+
+        // on cancel input and we've recognized before, return STATE_CANCELLED
+        if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
+            return state | STATE_CANCELLED;
+        } else if (isRecognized || isValid) {
+            if (eventType & INPUT_END) {
+                return state | STATE_ENDED;
+            } else if (!(state & STATE_BEGAN)) {
+                return STATE_BEGAN;
+            }
+            return state | STATE_CHANGED;
+        }
+        return STATE_FAILED;
+    }
+});
+
+/**
+ * Pan
+ * Recognized when the pointer is down and moved in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PanRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+
+    this.pX = null;
+    this.pY = null;
+}
+
+inherit(PanRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof PanRecognizer
+     */
+    defaults: {
+        event: 'pan',
+        threshold: 10,
+        pointers: 1,
+        direction: DIRECTION_ALL
+    },
+
+    getTouchAction: function() {
+        var direction = this.options.direction;
+        var actions = [];
+        if (direction & DIRECTION_HORIZONTAL) {
+            actions.push(TOUCH_ACTION_PAN_Y);
+        }
+        if (direction & DIRECTION_VERTICAL) {
+            actions.push(TOUCH_ACTION_PAN_X);
+        }
+        return actions;
+    },
+
+    directionTest: function(input) {
+        var options = this.options;
+        var hasMoved = true;
+        var distance = input.distance;
+        var direction = input.direction;
+        var x = input.deltaX;
+        var y = input.deltaY;
+
+        // lock to axis?
+        if (!(direction & options.direction)) {
+            if (options.direction & DIRECTION_HORIZONTAL) {
+                direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
+                hasMoved = x != this.pX;
+                distance = Math.abs(input.deltaX);
+            } else {
+                direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
+                hasMoved = y != this.pY;
+                distance = Math.abs(input.deltaY);
+            }
+        }
+        input.direction = direction;
+        return hasMoved && distance > options.threshold && direction & options.direction;
+    },
+
+    attrTest: function(input) {
+        return AttrRecognizer.prototype.attrTest.call(this, input) &&
+            (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
+    },
+
+    emit: function(input) {
+
+        this.pX = input.deltaX;
+        this.pY = input.deltaY;
+
+        var direction = directionStr(input.direction);
+
+        if (direction) {
+            input.additionalEvent = this.options.event + direction;
+        }
+        this._super.emit.call(this, input);
+    }
+});
+
+/**
+ * Pinch
+ * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PinchRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(PinchRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof PinchRecognizer
+     */
+    defaults: {
+        event: 'pinch',
+        threshold: 0,
+        pointers: 2
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_NONE];
+    },
+
+    attrTest: function(input) {
+        return this._super.attrTest.call(this, input) &&
+            (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
+    },
+
+    emit: function(input) {
+        if (input.scale !== 1) {
+            var inOut = input.scale < 1 ? 'in' : 'out';
+            input.additionalEvent = this.options.event + inOut;
+        }
+        this._super.emit.call(this, input);
+    }
+});
+
+/**
+ * Press
+ * Recognized when the pointer is down for x ms without any movement.
+ * @constructor
+ * @extends Recognizer
+ */
+function PressRecognizer() {
+    Recognizer.apply(this, arguments);
+
+    this._timer = null;
+    this._input = null;
+}
+
+inherit(PressRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof PressRecognizer
+     */
+    defaults: {
+        event: 'press',
+        pointers: 1,
+        time: 251, // minimal time of the pointer to be pressed
+        threshold: 9 // a minimal movement is ok, but keep it low
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_AUTO];
+    },
+
+    process: function(input) {
+        var options = this.options;
+        var validPointers = input.pointers.length === options.pointers;
+        var validMovement = input.distance < options.threshold;
+        var validTime = input.deltaTime > options.time;
+
+        this._input = input;
+
+        // we only allow little movement
+        // and we've reached an end event, so a tap is possible
+        if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
+            this.reset();
+        } else if (input.eventType & INPUT_START) {
+            this.reset();
+            this._timer = setTimeoutContext(function() {
+                this.state = STATE_RECOGNIZED;
+                this.tryEmit();
+            }, options.time, this);
+        } else if (input.eventType & INPUT_END) {
+            return STATE_RECOGNIZED;
+        }
+        return STATE_FAILED;
+    },
+
+    reset: function() {
+        clearTimeout(this._timer);
+    },
+
+    emit: function(input) {
+        if (this.state !== STATE_RECOGNIZED) {
+            return;
+        }
+
+        if (input && (input.eventType & INPUT_END)) {
+            this.manager.emit(this.options.event + 'up', input);
+        } else {
+            this._input.timeStamp = now();
+            this.manager.emit(this.options.event, this._input);
+        }
+    }
+});
+
+/**
+ * Rotate
+ * Recognized when two or more pointer are moving in a circular motion.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function RotateRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(RotateRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof RotateRecognizer
+     */
+    defaults: {
+        event: 'rotate',
+        threshold: 0,
+        pointers: 2
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_NONE];
+    },
+
+    attrTest: function(input) {
+        return this._super.attrTest.call(this, input) &&
+            (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
+    }
+});
+
+/**
+ * Swipe
+ * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function SwipeRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(SwipeRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof SwipeRecognizer
+     */
+    defaults: {
+        event: 'swipe',
+        threshold: 10,
+        velocity: 0.3,
+        direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
+        pointers: 1
+    },
+
+    getTouchAction: function() {
+        return PanRecognizer.prototype.getTouchAction.call(this);
+    },
+
+    attrTest: function(input) {
+        var direction = this.options.direction;
+        var velocity;
+
+        if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
+            velocity = input.overallVelocity;
+        } else if (direction & DIRECTION_HORIZONTAL) {
+            velocity = input.overallVelocityX;
+        } else if (direction & DIRECTION_VERTICAL) {
+            velocity = input.overallVelocityY;
+        }
+
+        return this._super.attrTest.call(this, input) &&
+            direction & input.offsetDirection &&
+            input.distance > this.options.threshold &&
+            input.maxPointers == this.options.pointers &&
+            abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
+    },
+
+    emit: function(input) {
+        var direction = directionStr(input.offsetDirection);
+        if (direction) {
+            this.manager.emit(this.options.event + direction, input);
+        }
+
+        this.manager.emit(this.options.event, input);
+    }
+});
+
+/**
+ * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
+ * between the given interval and position. The delay option can be used to recognize multi-taps without firing
+ * a single tap.
+ *
+ * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
+ * multi-taps being recognized.
+ * @constructor
+ * @extends Recognizer
+ */
+function TapRecognizer() {
+    Recognizer.apply(this, arguments);
+
+    // previous time and center,
+    // used for tap counting
+    this.pTime = false;
+    this.pCenter = false;
+
+    this._timer = null;
+    this._input = null;
+    this.count = 0;
+}
+
+inherit(TapRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof PinchRecognizer
+     */
+    defaults: {
+        event: 'tap',
+        pointers: 1,
+        taps: 1,
+        interval: 300, // max time between the multi-tap taps
+        time: 250, // max time of the pointer to be down (like finger on the screen)
+        threshold: 9, // a minimal movement is ok, but keep it low
+        posThreshold: 10 // a multi-tap can be a bit off the initial position
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_MANIPULATION];
+    },
+
+    process: function(input) {
+        var options = this.options;
+
+        var validPointers = input.pointers.length === options.pointers;
+        var validMovement = input.distance < options.threshold;
+        var validTouchTime = input.deltaTime < options.time;
+
+        this.reset();
+
+        if ((input.eventType & INPUT_START) && (this.count === 0)) {
+            return this.failTimeout();
+        }
+
+        // we only allow little movement
+        // and we've reached an end event, so a tap is possible
+        if (validMovement && validTouchTime && validPointers) {
+            if (input.eventType != INPUT_END) {
+                return this.failTimeout();
+            }
+
+            var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
+            var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
+
+            this.pTime = input.timeStamp;
+            this.pCenter = input.center;
+
+            if (!validMultiTap || !validInterval) {
+                this.count = 1;
+            } else {
+                this.count += 1;
+            }
+
+            this._input = input;
+
+            // if tap count matches we have recognized it,
+            // else it has began recognizing...
+            var tapCount = this.count % options.taps;
+            if (tapCount === 0) {
+                // no failing requirements, immediately trigger the tap event
+                // or wait as long as the multitap interval to trigger
+                if (!this.hasRequireFailures()) {
+                    return STATE_RECOGNIZED;
+                } else {
+                    this._timer = setTimeoutContext(function() {
+                        this.state = STATE_RECOGNIZED;
+                        this.tryEmit();
+                    }, options.interval, this);
+                    return STATE_BEGAN;
+                }
+            }
+        }
+        return STATE_FAILED;
+    },
+
+    failTimeout: function() {
+        this._timer = setTimeoutContext(function() {
+            this.state = STATE_FAILED;
+        }, this.options.interval, this);
+        return STATE_FAILED;
+    },
+
+    reset: function() {
+        clearTimeout(this._timer);
+    },
+
+    emit: function() {
+        if (this.state == STATE_RECOGNIZED) {
+            this._input.tapCount = this.count;
+            this.manager.emit(this.options.event, this._input);
+        }
+    }
+});
+
+/**
+ * Simple way to create a manager with a default set of recognizers.
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Hammer(element, options) {
+    options = options || {};
+    options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
+    return new Manager(element, options);
+}
+
+/**
+ * @const {string}
+ */
+Hammer.VERSION = '2.0.8';
+
+/**
+ * default settings
+ * @namespace
+ */
+Hammer.defaults = {
+    /**
+     * set if DOM events are being triggered.
+     * But this is slower and unused by simple implementations, so disabled by default.
+     * @type {Boolean}
+     * @default false
+     */
+    domEvents: false,
+
+    /**
+     * The value for the touchAction property/fallback.
+     * When set to `compute` it will magically set the correct value based on the added recognizers.
+     * @type {String}
+     * @default compute
+     */
+    touchAction: TOUCH_ACTION_COMPUTE,
+
+    /**
+     * @type {Boolean}
+     * @default true
+     */
+    enable: true,
+
+    /**
+     * EXPERIMENTAL FEATURE -- can be removed/changed
+     * Change the parent input target element.
+     * If Null, then it is being set the to main element.
+     * @type {Null|EventTarget}
+     * @default null
+     */
+    inputTarget: null,
+
+    /**
+     * force an input class
+     * @type {Null|Function}
+     * @default null
+     */
+    inputClass: null,
+
+    /**
+     * Default recognizer setup when calling `Hammer()`
+     * When creating a new Manager these will be skipped.
+     * @type {Array}
+     */
+    preset: [
+        // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
+        [RotateRecognizer, {enable: false}],
+        [PinchRecognizer, {enable: false}, ['rotate']],
+        [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
+        [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
+        [TapRecognizer],
+        [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
+        [PressRecognizer]
+    ],
+
+    /**
+     * Some CSS properties can be used to improve the working of Hammer.
+     * Add them to this method and they will be set when creating a new Manager.
+     * @namespace
+     */
+    cssProps: {
+        /**
+         * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
+         * @type {String}
+         * @default 'none'
+         */
+        userSelect: 'none',
+
+        /**
+         * Disable the Windows Phone grippers when pressing an element.
+         * @type {String}
+         * @default 'none'
+         */
+        touchSelect: 'none',
+
+        /**
+         * Disables the default callout shown when you touch and hold a touch target.
+         * On iOS, when you touch and hold a touch target such as a link, Safari displays
+         * a callout containing information about the link. This property allows you to disable that callout.
+         * @type {String}
+         * @default 'none'
+         */
+        touchCallout: 'none',
+
+        /**
+         * Specifies whether zooming is enabled. Used by IE10>
+         * @type {String}
+         * @default 'none'
+         */
+        contentZooming: 'none',
+
+        /**
+         * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
+         * @type {String}
+         * @default 'none'
+         */
+        userDrag: 'none',
+
+        /**
+         * Overrides the highlight color shown when the user taps a link or a JavaScript
+         * clickable element in iOS. This property obeys the alpha value, if specified.
+         * @type {String}
+         * @default 'rgba(0,0,0,0)'
+         */
+        tapHighlightColor: 'rgba(0,0,0,0)'
+    }
+};
+
+var STOP = 1;
+var FORCED_STOP = 2;
+
+/**
+ * Manager
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Manager(element, options) {
+    this.options = assign({}, Hammer.defaults, options || {});
+
+    this.options.inputTarget = this.options.inputTarget || element;
+
+    this.handlers = {};
+    this.session = {};
+    this.recognizers = [];
+    this.oldCssProps = {};
+
+    this.element = element;
+    this.input = createInputInstance(this);
+    this.touchAction = new TouchAction(this, this.options.touchAction);
+
+    toggleCssProps(this, true);
+
+    each(this.options.recognizers, function(item) {
+        var recognizer = this.add(new (item[0])(item[1]));
+        item[2] && recognizer.recognizeWith(item[2]);
+        item[3] && recognizer.requireFailure(item[3]);
+    }, this);
+}
+
+Manager.prototype = {
+    /**
+     * set options
+     * @param {Object} options
+     * @returns {Manager}
+     */
+    set: function(options) {
+        assign(this.options, options);
+
+        // Options that need a little more setup
+        if (options.touchAction) {
+            this.touchAction.update();
+        }
+        if (options.inputTarget) {
+            // Clean up existing event listeners and reinitialize
+            this.input.destroy();
+            this.input.target = options.inputTarget;
+            this.input.init();
+        }
+        return this;
+    },
+
+    /**
+     * stop recognizing for this session.
+     * This session will be discarded, when a new [input]start event is fired.
+     * When forced, the recognizer cycle is stopped immediately.
+     * @param {Boolean} [force]
+     */
+    stop: function(force) {
+        this.session.stopped = force ? FORCED_STOP : STOP;
+    },
+
+    /**
+     * run the recognizers!
+     * called by the inputHandler function on every movement of the pointers (touches)
+     * it walks through all the recognizers and tries to detect the gesture that is being made
+     * @param {Object} inputData
+     */
+    recognize: function(inputData) {
+        var session = this.session;
+        if (session.stopped) {
+            return;
+        }
+
+        // run the touch-action polyfill
+        this.touchAction.preventDefaults(inputData);
+
+        var recognizer;
+        var recognizers = this.recognizers;
+
+        // this holds the recognizer that is being recognized.
+        // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
+        // if no recognizer is detecting a thing, it is set to `null`
+        var curRecognizer = session.curRecognizer;
+
+        // reset when the last recognizer is recognized
+        // or when we're in a new session
+        if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
+            curRecognizer = session.curRecognizer = null;
+        }
+
+        var i = 0;
+        while (i < recognizers.length) {
+            recognizer = recognizers[i];
+
+            // find out if we are allowed try to recognize the input for this one.
+            // 1.   allow if the session is NOT forced stopped (see the .stop() method)
+            // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
+            //      that is being recognized.
+            // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
+            //      this can be setup with the `recognizeWith()` method on the recognizer.
+            if (session.stopped !== FORCED_STOP && ( // 1
+                    !curRecognizer || recognizer == curRecognizer || // 2
+                    recognizer.canRecognizeWith(curRecognizer))) { // 3
+                recognizer.recognize(inputData);
+            } else {
+                recognizer.reset();
+            }
+
+            // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
+            // current active recognizer. but only if we don't already have an active recognizer
+            if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
+                curRecognizer = session.curRecognizer = recognizer;
+            }
+            i++;
+        }
+    },
+
+    /**
+     * get a recognizer by its event name.
+     * @param {Recognizer|String} recognizer
+     * @returns {Recognizer|Null}
+     */
+    get: function(recognizer) {
+        if (recognizer instanceof Recognizer) {
+            return recognizer;
+        }
+
+        var recognizers = this.recognizers;
+        for (var i = 0; i < recognizers.length; i++) {
+            if (recognizers[i].options.event == recognizer) {
+                return recognizers[i];
+            }
+        }
+        return null;
+    },
+
+    /**
+     * add a recognizer to the manager
+     * existing recognizers with the same event name will be removed
+     * @param {Recognizer} recognizer
+     * @returns {Recognizer|Manager}
+     */
+    add: function(recognizer) {
+        if (invokeArrayArg(recognizer, 'add', this)) {
+            return this;
+        }
+
+        // remove existing
+        var existing = this.get(recognizer.options.event);
+        if (existing) {
+            this.remove(existing);
+        }
+
+        this.recognizers.push(recognizer);
+        recognizer.manager = this;
+
+        this.touchAction.update();
+        return recognizer;
+    },
+
+    /**
+     * remove a recognizer by name or instance
+     * @param {Recognizer|String} recognizer
+     * @returns {Manager}
+     */
+    remove: function(recognizer) {
+        if (invokeArrayArg(recognizer, 'remove', this)) {
+            return this;
+        }
+
+        recognizer = this.get(recognizer);
+
+        // let's make sure this recognizer exists
+        if (recognizer) {
+            var recognizers = this.recognizers;
+            var index = inArray(recognizers, recognizer);
+
+            if (index !== -1) {
+                recognizers.splice(index, 1);
+                this.touchAction.update();
+            }
+        }
+
+        return this;
+    },
+
+    /**
+     * bind event
+     * @param {String} events
+     * @param {Function} handler
+     * @returns {EventEmitter} this
+     */
+    on: function(events, handler) {
+        if (events === undefined) {
+            return;
+        }
+        if (handler === undefined) {
+            return;
+        }
+
+        var handlers = this.handlers;
+        each(splitStr(events), function(event) {
+            handlers[event] = handlers[event] || [];
+            handlers[event].push(handler);
+        });
+        return this;
+    },
+
+    /**
+     * unbind event, leave emit blank to remove all handlers
+     * @param {String} events
+     * @param {Function} [handler]
+     * @returns {EventEmitter} this
+     */
+    off: function(events, handler) {
+        if (events === undefined) {
+            return;
+        }
+
+        var handlers = this.handlers;
+        each(splitStr(events), function(event) {
+            if (!handler) {
+                delete handlers[event];
+            } else {
+                handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
+            }
+        });
+        return this;
+    },
+
+    /**
+     * emit event to the listeners
+     * @param {String} event
+     * @param {Object} data
+     */
+    emit: function(event, data) {
+        // we also want to trigger dom events
+        if (this.options.domEvents) {
+            triggerDomEvent(event, data);
+        }
+
+        // no handlers, so skip it all
+        var handlers = this.handlers[event] && this.handlers[event].slice();
+        if (!handlers || !handlers.length) {
+            return;
+        }
+
+        data.type = event;
+        data.preventDefault = function() {
+            data.srcEvent.preventDefault();
+        };
+
+        var i = 0;
+        while (i < handlers.length) {
+            handlers[i](data);
+            i++;
+        }
+    },
+
+    /**
+     * destroy the manager and unbinds all events
+     * it doesn't unbind dom events, that is the user own responsibility
+     */
+    destroy: function() {
+        this.element && toggleCssProps(this, false);
+
+        this.handlers = {};
+        this.session = {};
+        this.input.destroy();
+        this.element = null;
+    }
+};
+
+/**
+ * add/remove the css properties as defined in manager.options.cssProps
+ * @param {Manager} manager
+ * @param {Boolean} add
+ */
+function toggleCssProps(manager, add) {
+    var element = manager.element;
+    if (!element.style) {
+        return;
+    }
+    var prop;
+    each(manager.options.cssProps, function(value, name) {
+        prop = prefixed(element.style, name);
+        if (add) {
+            manager.oldCssProps[prop] = element.style[prop];
+            element.style[prop] = value;
+        } else {
+            element.style[prop] = manager.oldCssProps[prop] || '';
+        }
+    });
+    if (!add) {
+        manager.oldCssProps = {};
+    }
+}
+
+/**
+ * trigger dom event
+ * @param {String} event
+ * @param {Object} data
+ */
+function triggerDomEvent(event, data) {
+    var gestureEvent = document.createEvent('Event');
+    gestureEvent.initEvent(event, true, true);
+    gestureEvent.gesture = data;
+    data.target.dispatchEvent(gestureEvent);
+}
+
+assign(Hammer, {
+    INPUT_START: INPUT_START,
+    INPUT_MOVE: INPUT_MOVE,
+    INPUT_END: INPUT_END,
+    INPUT_CANCEL: INPUT_CANCEL,
+
+    STATE_POSSIBLE: STATE_POSSIBLE,
+    STATE_BEGAN: STATE_BEGAN,
+    STATE_CHANGED: STATE_CHANGED,
+    STATE_ENDED: STATE_ENDED,
+    STATE_RECOGNIZED: STATE_RECOGNIZED,
+    STATE_CANCELLED: STATE_CANCELLED,
+    STATE_FAILED: STATE_FAILED,
+
+    DIRECTION_NONE: DIRECTION_NONE,
+    DIRECTION_LEFT: DIRECTION_LEFT,
+    DIRECTION_RIGHT: DIRECTION_RIGHT,
+    DIRECTION_UP: DIRECTION_UP,
+    DIRECTION_DOWN: DIRECTION_DOWN,
+    DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
+    DIRECTION_VERTICAL: DIRECTION_VERTICAL,
+    DIRECTION_ALL: DIRECTION_ALL,
+
+    Manager: Manager,
+    Input: Input,
+    TouchAction: TouchAction,
+
+    TouchInput: TouchInput,
+    MouseInput: MouseInput,
+    PointerEventInput: PointerEventInput,
+    TouchMouseInput: TouchMouseInput,
+    SingleTouchInput: SingleTouchInput,
+
+    Recognizer: Recognizer,
+    AttrRecognizer: AttrRecognizer,
+    Tap: TapRecognizer,
+    Pan: PanRecognizer,
+    Swipe: SwipeRecognizer,
+    Pinch: PinchRecognizer,
+    Rotate: RotateRecognizer,
+    Press: PressRecognizer,
+
+    on: addEventListeners,
+    off: removeEventListeners,
+    each: each,
+    merge: merge,
+    extend: extend,
+    assign: assign,
+    inherit: inherit,
+    bindFn: bindFn,
+    prefixed: prefixed
+});
+
+// this prevents errors when Hammer is loaded in the presence of an AMD
+//  style loader but by script tag, not by the loader.
+var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
+freeGlobal.Hammer = Hammer;
+
+if (typeof define === 'function' && define.amd) {
+    define(function() {
+        return Hammer;
+    });
+} else if (typeof module != 'undefined' && module.exports) {
+    module.exports = Hammer;
+} else {
+    window[exportName] = Hammer;
+}
+
+})(window, document, 'Hammer');
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  $.modal = function(params, onOpen) {
+    params = $.extend({}, defaults, params);
+
+
+    var buttons = params.buttons;
+
+    var buttonsHtml = buttons.map(function(d, i) {
+      return '<a href="javascript:;" class="weui-dialog__btn ' + (d.className || "") + '">' + d.text + '</a>';
+    }).join("");
+
+    var tpl = '<div class="weui-dialog">' +
+                '<div class="weui-dialog__hd"><strong class="weui-dialog__title">' + params.title + '</strong></div>' +
+                ( params.text ? '<div class="weui-dialog__bd">'+params.text+'</div>' : '')+
+                '<div class="weui-dialog__ft">' + buttonsHtml + '</div>' +
+              '</div>';
+    
+    var dialog = $.openModal(tpl, onOpen);
+
+    dialog.find(".weui-dialog__btn").each(function(i, e) {
+      var el = $(e);
+      el.click(function() {
+        //先关闭对话框,再调用回调函数
+        if(params.autoClose) $.closeModal();
+
+        if(buttons[i].onClick) {
+          buttons[i].onClick.call(dialog);
+        }
+      });
+    });
+
+    return dialog;
+  };
+
+  $.openModal = function(tpl, onOpen) {
+    var mask = $("<div class='weui-mask'></div>").appendTo(document.body);
+    mask.show();
+
+    var dialog = $(tpl).appendTo(document.body);
+ 
+    if (onOpen) {
+      dialog.transitionEnd(function () {
+        onOpen.call(dialog);
+      });
+    }   
+
+    dialog.show();
+    mask.addClass("weui-mask--visible");
+    dialog.addClass("weui-dialog--visible");
+
+
+    return dialog;
+  }
+
+  $.closeModal = function() {
+    $(".weui-mask--visible").removeClass("weui-mask--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+    $(".weui-dialog--visible").removeClass("weui-dialog--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+  };
+
+  $.alert = function(text, title, onOK) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        onOK = arguments[1];
+        title = undefined;
+      }
+
+      config = {
+        text: text,
+        title: title,
+        onOK: onOK
+      }
+    }
+    return $.modal({
+      text: config.text,
+      title: config.title,
+      buttons: [{
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: config.onOK
+      }]
+    });
+  }
+
+  $.confirm = function(text, title, onOK, onCancel) {
+    var config;
+    if (typeof text === 'object') {
+      config = text
+    } else {
+      if (typeof title === 'function') {
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+
+      config = {
+        text: text,
+        title: title,
+        onOK: onOK,
+        onCancel: onCancel
+      }
+    }
+    return $.modal({
+      text: config.text,
+      title: config.title,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: config.onCancel
+      },
+      {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: config.onOK
+      }]
+    });
+  };
+
+  //如果参数过多,建议通过 config 对象进行配置,而不是传入多个参数。
+  $.prompt = function(text, title, onOK, onCancel, input) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        input = arguments[3];
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+      config = {
+        text: text,
+        title: title,
+        input: input,
+        onOK: onOK,
+        onCancel: onCancel,
+        empty: false  //allow empty
+      }
+    }
+
+    var modal = $.modal({
+      text: '<p class="weui-prompt-text">'+(config.text || '')+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-input" value="' + (config.input || '') + '" />',
+      title: config.title,
+      autoClose: false,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: function () {
+          $.closeModal();
+          config.onCancel && config.onCancel.call(modal);
+        }
+      },
+      {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: function() {
+          var input = $("#weui-prompt-input").val();
+          if (!config.empty && (input === "" || input === null)) {
+            modal.find('.weui-prompt-input').focus()[0].select();
+            return false;
+          }
+          $.closeModal();
+          config.onOK && config.onOK.call(modal, input);
+        }
+      }]
+    }, function () {
+      this.find('.weui-prompt-input').focus()[0].select();
+    });
+
+    return modal;
+  };
+
+  //如果参数过多,建议通过 config 对象进行配置,而不是传入多个参数。
+  $.login = function(text, title, onOK, onCancel, username, password) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        password = arguments[4];
+        username = arguments[3];
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+      config = {
+        text: text,
+        title: title,
+        username: username,
+        password: password,
+        onOK: onOK,
+        onCancel: onCancel
+      }
+    }
+
+    var modal = $.modal({
+      text: '<p class="weui-prompt-text">'+(config.text || '')+'</p>' +
+            '<input type="text" class="weui-input weui-prompt-input" id="weui-prompt-username" value="' + (config.username || '') + '" placeholder="输入用户名" />' +
+            '<input type="password" class="weui-input weui-prompt-input" id="weui-prompt-password" value="' + (config.password || '') + '" placeholder="输入密码" />',
+      title: config.title,
+      autoClose: false,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: function () {
+          $.closeModal();
+          config.onCancel && config.onCancel.call(modal);
+        }
+      }, {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: function() {
+          var username = $("#weui-prompt-username").val();
+          var password = $("#weui-prompt-password").val();
+          if (!config.empty && (username === "" || username === null)) {
+            modal.find('#weui-prompt-username').focus()[0].select();
+            return false;
+          }
+          if (!config.empty && (password === "" || password === null)) {
+            modal.find('#weui-prompt-password').focus()[0].select();
+            return false;
+          }
+          $.closeModal();
+          config.onOK && config.onOK.call(modal, username, password);
+        }
+      }]
+    }, function () {
+      this.find('#weui-prompt-username').focus()[0].select();
+    });
+
+    return modal;
+  };
+
+  defaults = $.modal.prototype.defaults = {
+    title: "提示",
+    text: undefined,
+    buttonOK: "确定",
+    buttonCancel: "取消",
+    buttons: [{
+      text: "确定",
+      className: "primary"
+    }],
+    autoClose: true //点击按钮自动关闭对话框,如果你不希望点击按钮就关闭对话框,可以把这个设置为false
+  };
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  var show = function(html, className) {
+    className = className || "";
+    var mask = $("<div class='weui-mask_transparent'></div>").appendTo(document.body);
+
+    var tpl = '<div class="weui-toast ' + className + '">' + html + '</div>';
+    var dialog = $(tpl).appendTo(document.body);
+
+    dialog.addClass("weui-toast--visible");
+    dialog.show();
+  };
+
+  var hide = function(callback) {
+    $(".weui-mask_transparent").remove();
+    var done = false;
+    var $el = $(".weui-toast--visible").removeClass("weui-toast--visible").transitionEnd(function() {
+      var $this = $(this);
+      $this.remove();
+      callback && callback();
+      done = true
+    });
+
+    setTimeout(function () {
+      if (!done) {
+        $el.remove()
+        callback && callback();
+      }
+    }, 1000)
+  }
+
+  $.toast = function(text, style, callback) {
+    if(typeof style === "function") {
+      callback = style;
+    }
+    var className, iconClassName = 'weui-icon-success-no-circle';
+    var duration = toastDefaults.duration;
+    if(style == "cancel") {
+      className = "weui-toast_cancel";
+      iconClassName = 'weui-icon-cancel'
+    } else if(style == "forbidden") {
+      className = "weui-toast--forbidden";
+      iconClassName = 'weui-icon-warn'
+    } else if(style == "text") {
+      className = "weui-toast--text";
+    } else if(typeof style === typeof 1) {
+      duration = style
+    }
+    show('<i class="' + iconClassName + ' weui-icon_toast"></i><p class="weui-toast_content">' + (text || "已经完成") + '</p>', className);
+
+    setTimeout(function() {
+      hide(callback);
+    }, duration);
+  }
+
+  $.showLoading = function(text) {
+    var html = '<div class="weui_loading">';
+    html += '<i class="weui-loading weui-icon_toast"></i>';
+    html += '</div>';
+    html += '<p class="weui-toast_content">' + (text || "数据加载中") + '</p>';
+    show(html, 'weui_loading_toast');
+  }
+
+  $.hideLoading = function() {
+    hide();
+  }
+
+  var toastDefaults = $.toast.prototype.defaults = {
+    duration: 2500
+  }
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  var show = function(params) {
+
+    var mask = $("<div class='weui-mask weui-actions_mask'></div>").appendTo(document.body);
+
+    var actions = params.actions || [];
+
+    var actionsHtml = actions.map(function(d, i) {
+      return '<div class="weui-actionsheet__cell ' + (d.className || "") + '">' + d.text + '</div>';
+    }).join("");
+
+    var titleHtml = "";
+    
+    if (params.title) {
+      titleHtml = '<div class="weui-actionsheet__title"><p class="weui-actionsheet__title-text">' + params.title + '</p></div>';
+    }
+
+    var tpl = '<div class="weui-actionsheet " id="weui-actionsheet">'+
+                titleHtml +
+                '<div class="weui-actionsheet__menu">'+
+                actionsHtml +
+                '</div>'+
+                '<div class="weui-actionsheet__action">'+
+                  '<div class="weui-actionsheet__cell weui-actionsheet_cancel">取消</div>'+
+                  '</div>'+
+                '</div>';
+    var dialog = $(tpl).appendTo(document.body);
+
+    dialog.find(".weui-actionsheet__menu .weui-actionsheet__cell, .weui-actionsheet__action .weui-actionsheet__cell").each(function(i, e) {
+      $(e).click(function() {
+        $.closeActions();
+        params.onClose && params.onClose();
+        if(actions[i] && actions[i].onClick) {
+          actions[i].onClick();
+        }
+      })
+    });
+
+    mask.show();
+    dialog.show();
+    mask.addClass("weui-mask--visible");
+    dialog.addClass("weui-actionsheet_toggle");
+  };
+
+  var hide = function() {
+    $(".weui-mask").removeClass("weui-mask--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+    $(".weui-actionsheet").removeClass("weui-actionsheet_toggle").transitionEnd(function() {
+      $(this).remove();
+    });
+  }
+
+  $.actions = function(params) {
+    params = $.extend({}, defaults, params);
+    show(params);
+  }
+
+  $.closeActions = function() {
+    hide();
+  }
+
+  $(document).on("click", ".weui-actions_mask", function() {
+    $.closeActions();
+  });
+
+  var defaults = $.actions.prototype.defaults = {
+    title: undefined,
+    onClose: undefined,
+    /*actions: [{
+      text: "菜单",
+      className: "color-danger",
+      onClick: function() {
+        console.log(1);
+      }
+    },{
+      text: "菜单2",
+      className: "color-success",
+      onClick: function() {
+        console.log(2);
+      }
+    }]*/
+  }
+
+}($);
+
+/* ===============================================================================
+************   Pull to refreh ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var PTR = function(el, opt) {
+    if (typeof opt === typeof function () {}) {
+      opt = {
+        onRefresh: opt
+      }
+    }
+    if (typeof opt === typeof 'a') {
+      opt = undefined
+    }
+    this.opt = $.extend(PTR.defaults, opt || {});
+    this.container = $(el);
+    this.attachEvents();
+  }
+
+  PTR.defaults = {
+    distance: 50,
+    onRefresh: undefined,
+    onPull: undefined
+  }
+
+  PTR.prototype.touchStart = function(e) {
+    if(this.container.hasClass("refreshing")) return;
+    var p = $.getTouchPosition(e);
+    this.start = p;
+    this.diffX = this.diffY = 0;
+  };
+
+  PTR.prototype.touchMove= function(e) {
+    if(this.container.hasClass("refreshing")) return;
+    if(!this.start) return false;
+    if(this.container.scrollTop() > 0) return;
+    var p = $.getTouchPosition(e);
+    this.diffX = p.x - this.start.x;
+    this.diffY = p.y - this.start.y;
+    if (Math.abs(this.diffX) > Math.abs(this.diffY)) return true; // 说明是左右方向的拖动
+    if(this.diffY < 0) return;
+    this.container.addClass("touching");
+    e.preventDefault();
+    e.stopPropagation();
+    this.diffY = Math.pow(this.diffY, 0.75);
+    this.container.css("transform", "translate3d(0, "+this.diffY+"px, 0)");
+    this.triggerPull(this.diffY)
+  };
+  PTR.prototype.touchEnd = function() {
+    this.start = false;
+    if(this.diffY <= 0 || this.container.hasClass("refreshing")) return;
+    this.container.removeClass("touching");
+    this.container.removeClass("pull-down pull-up");
+    this.container.css("transform", "");
+    if(Math.abs(this.diffY) <= this.opt.distance) {
+    } else {
+      this.triggerPullToRefresh();
+    }
+  };
+
+  PTR.prototype.triggerPullToRefresh = function() {
+    this.triggerPull(this.opt.distance)
+    this.container.removeClass('pull-up').addClass("refreshing");
+    if (this.opt.onRefresh) {
+      this.opt.onRefresh.call(this)
+    }
+    this.container.trigger("pull-to-refresh");
+  }
+
+  PTR.prototype.triggerPull = function(diffY) {
+
+    if(diffY < this.opt.distance) {
+      this.container.removeClass("pull-up").addClass("pull-down");
+    } else {
+      this.container.removeClass("pull-down").addClass("pull-up");
+    }
+
+    if (this.opt.onPull) {
+      this.opt.onPull.call(this, Math.floor(diffY / this.opt.distance * 100))
+    }
+    this.container.trigger("pull");
+  }
+
+  PTR.prototype.pullToRefreshDone = function() {
+    this.container.removeClass("refreshing");
+  }
+
+  PTR.prototype.attachEvents = function() {
+    var el = this.container;
+    el.addClass("weui-pull-to-refresh");
+    el.on($.touchEvents.start, $.proxy(this.touchStart, this));
+    el.on($.touchEvents.move, $.proxy(this.touchMove, this));
+    el.on($.touchEvents.end, $.proxy(this.touchEnd, this));
+  };
+
+  var pullToRefreshDone = function(el) {
+    $(el).removeClass("refreshing");
+  }
+
+  $.fn.pullToRefresh = function(opt) {
+    return this.each(function() {
+      var $this = $(this)
+      var ptr = $this.data('ptr')
+      if (!ptr) $this.data('ptr', ptr = new PTR(this, opt))
+      if (typeof opt === typeof 'a') {
+        ptr[opt].call(ptr)
+      }
+    });
+  }
+
+  $.fn.pullToRefreshDone = function() {
+    return this.each(function() {
+      pullToRefreshDone(this);
+    });
+  }
+
+}($);
+
+/* ===============================================================================
+************   Infinite ************
+=============================================================================== */
+/* global $:true */
++function ($) {
+  "use strict";
+
+  // fix https://github.com/lihongxun945/jquery-weui/issues/442
+  // chrome will always return 0, when use document.body.scrollTop
+  // https://stackoverflow.com/questions/43717316/google-chrome-document-body-scrolltop-always-returns-0
+  var getOffset = function (container) {
+    var tagName = container[0].tagName.toUpperCase()
+    var scrollTop 
+    if (tagName === 'BODY' || tagName === 'HTML') {
+      scrollTop = container.scrollTop() || $(window).scrollTop()
+    } else {
+      scrollTop = container.scrollTop()
+    }
+    var offset = container.scrollHeight() - ($(window).height() + scrollTop)
+    console.log(offset)
+    return offset
+  }
+
+  var Infinite = function(el, distance) {
+    this.container = $(el);
+    this.container.data("infinite", this);
+    this.distance = distance || 50;
+    this.attachEvents();
+  }
+
+  Infinite.prototype.scroll = function() {
+    var container = this.container;
+    this._check();
+  }
+
+  Infinite.prototype.attachEvents = function(off) {
+    var el = this.container;
+    var scrollContainer = (el[0].tagName.toUpperCase() === "BODY" ? $(document) : el);
+    scrollContainer[off ? "off" : "on"]("scroll", $.proxy(this.scroll, this));
+  };
+  Infinite.prototype.detachEvents = function(off) {
+    this.attachEvents(true);
+  }
+  Infinite.prototype._check = function() {
+    var offset = getOffset(this.container);
+    if(Math.abs(offset) <= this.distance) {
+      this.container.trigger("infinite");
+    }
+  }
+
+  var infinite = function(el) {
+    attachEvents(el);
+  }
+
+  $.fn.infinite = function(distance) {
+    return this.each(function() {
+      new Infinite(this, distance);
+    });
+  }
+  $.fn.destroyInfinite = function() {
+    return this.each(function() {
+      var infinite = $(this).data("infinite");
+      if(infinite && infinite.detachEvents) infinite.detachEvents();
+    });
+  }
+
+}($);
+
+/* global $:true */
++function ($) {
+  "use strict";
+
+  var ITEM_ON = "weui-bar__item--on";
+
+  var showTab = function(a) {
+    var $a = $(a);
+    if($a.hasClass(ITEM_ON)) return;
+    var href = $a.attr("href");
+
+    if(!/^#/.test(href)) return ;
+
+    $a.parent().find("."+ITEM_ON).removeClass(ITEM_ON);
+    $a.addClass(ITEM_ON);
+
+    var bd = $a.parents(".weui-tab").find(".weui-tab__bd");
+
+    bd.find(".weui-tab__bd-item--active").removeClass("weui-tab__bd-item--active");
+
+    $(href).addClass("weui-tab__bd-item--active");
+  }
+
+  $.showTab = showTab;
+
+  $(document).on("click", ".weui-navbar__item, .weui-tabbar__item", function(e) {
+    var $a = $(e.currentTarget);
+    var href = $a.attr("href");
+    if($a.hasClass(ITEM_ON)) return;
+    if(!/^#/.test(href)) return;
+
+    e.preventDefault();
+
+    showTab($a);
+  });
+
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+
+  $(document).on("click touchstart", ".weui-search-bar__label", function(e) {
+    $(e.target).parents(".weui-search-bar").addClass("weui-search-bar_focusing").find('input').focus();
+  }) 
+  /*
+  .on("blur", ".weui-search-bar__input", function(e) {
+    var $input = $(e.target);
+    if(!$input.val()) $input.parents(".weui-search-bar").removeClass("weui-search-bar_focusing");
+  })
+  */
+  .on("click", ".weui-search-bar__cancel-btn", function(e) {
+    var $input = $(e.target).parents(".weui-search-bar").removeClass("weui-search-bar_focusing").find(".weui-search-bar__input").val("").blur();
+  })
+  .on("click", ".weui-icon-clear", function(e) {
+    var $input = $(e.target).parents(".weui-search-bar").find(".weui-search-bar__input").val("").focus();
+  });
+
+}($);
+
+/*===========================
+Device/OS Detection
+===========================*/
+/* global $:true */
+;(function ($) {
+    "use strict";
+    var device = {};
+    var ua = navigator.userAgent;
+
+    var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
+    var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
+    var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
+    var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
+
+    device.ios = device.android = device.iphone = device.ipad = device.androidChrome = false;
+    
+    // Android
+    if (android) {
+        device.os = 'android';
+        device.osVersion = android[2];
+        device.android = true;
+        device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
+    }
+    if (ipad || iphone || ipod) {
+        device.os = 'ios';
+        device.ios = true;
+    }
+    // iOS
+    if (iphone && !ipod) {
+        device.osVersion = iphone[2].replace(/_/g, '.');
+        device.iphone = true;
+    }
+    if (ipad) {
+        device.osVersion = ipad[2].replace(/_/g, '.');
+        device.ipad = true;
+    }
+    if (ipod) {
+        device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
+        device.iphone = true;
+    }
+    // iOS 8+ changed UA
+    if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
+        if (device.osVersion.split('.')[0] === '10') {
+            device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
+        }
+    }
+
+    // Webview
+    device.webView = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);
+        
+    // Minimal UI
+    if (device.os && device.os === 'ios') {
+        var osVersionArr = device.osVersion.split('.');
+        device.minimalUi = !device.webView &&
+                            (ipod || iphone) &&
+                            (osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7) &&
+                            $('meta[name="viewport"]').length > 0 && $('meta[name="viewport"]').attr('content').indexOf('minimal-ui') >= 0;
+    }
+
+    // Check for status bar and fullscreen app mode
+    var windowWidth = $(window).width();
+    var windowHeight = $(window).height();
+    device.statusBar = false;
+    if (device.webView && (windowWidth * windowHeight === screen.width * screen.height)) {
+        device.statusBar = true;
+    }
+    else {
+        device.statusBar = false;
+    }
+
+    // Classes
+    var classNames = [];
+
+    // Pixel Ratio
+    device.pixelRatio = window.devicePixelRatio || 1;
+    classNames.push('pixel-ratio-' + Math.floor(device.pixelRatio));
+    if (device.pixelRatio >= 2) {
+        classNames.push('retina');
+    }
+
+    // OS classes
+    if (device.os) {
+        classNames.push(device.os, device.os + '-' + device.osVersion.split('.')[0], device.os + '-' + device.osVersion.replace(/\./g, '-'));
+        if (device.os === 'ios') {
+            var major = parseInt(device.osVersion.split('.')[0], 10);
+            for (var i = major - 1; i >= 6; i--) {
+                classNames.push('ios-gt-' + i);
+            }
+        }
+        
+    }
+    // Status bar classes
+    if (device.statusBar) {
+        classNames.push('with-statusbar-overlay');
+    }
+    else {
+        $('html').removeClass('with-statusbar-overlay');
+    }
+
+    // Add html classes
+    if (classNames.length > 0) $('html').addClass(classNames.join(' '));
+
+    $.device = device;
+})($);
+
+/*======================================================
+************   Picker   ************
+======================================================*/
+/* global $:true */
+/* jshint unused:false */
+/* jshint multistr:true */
++ function($) {
+  "use strict";
+  var Picker = function (params) {
+      var p = this;
+      var defaults = {
+          updateValuesOnMomentum: false,
+          updateValuesOnTouchmove: true,
+          rotateEffect: false,
+          momentumRatio: 7,
+          freeMode: false,
+          // Common settings
+          scrollToInput: true,
+          inputReadOnly: true,
+          toolbar: true,
+          toolbarCloseText: '完成',
+          title: '请选择',
+          toolbarTemplate: '<div class="toolbar">\
+          <div class="toolbar-inner">\
+          <a href="javascript:;" class="picker-button close-picker">{{closeText}}</a>\
+          <h1 class="title">{{title}}</h1>\
+          </div>\
+          </div>',
+      };
+      params = params || {};
+      for (var def in defaults) {
+          if (typeof params[def] === 'undefined') {
+              params[def] = defaults[def];
+          }
+      }
+      p.params = params;
+      p.cols = [];
+      p.initialized = false;
+      
+      // Inline flag
+      p.inline = p.params.container ? true : false;
+
+      // 3D Transforms origin bug, only on safari
+      var originBug = $.device.ios || (navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !$.device.android;
+
+      // Should be converted to popover
+      function isPopover() {
+          var toPopover = false;
+          if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
+          if (!p.inline && p.params.input) {
+              if (p.params.onlyInPopover) toPopover = true;
+              else {
+                  if ($.device.ios) {
+                      toPopover = $.device.ipad ? true : false;
+                  }
+                  else {
+                      if ($(window).width() >= 768) toPopover = true;
+                  }
+              }
+          } 
+          return toPopover; 
+      }
+      function inPopover() {
+          if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
+          else return false;
+      }
+
+      // Value
+      p.setValue = function (arrValues, transition) {
+          var valueIndex = 0;
+          for (var i = 0; i < p.cols.length; i++) {
+              if (p.cols[i] && !p.cols[i].divider) {
+                  p.cols[i].setValue(arrValues[valueIndex], transition);
+                  valueIndex++;
+              }
+          }
+      };
+      p.updateValue = function () {
+          var newValue = [];
+          var newDisplayValue = [];
+          for (var i = 0; i < p.cols.length; i++) {
+              if (!p.cols[i].divider) {
+                  newValue.push(p.cols[i].value);
+                  newDisplayValue.push(p.cols[i].displayValue);
+              }
+          }
+          if (newValue.indexOf(undefined) >= 0) {
+              return;
+          }
+          p.value = newValue;
+          p.displayValue = newDisplayValue;
+          if (p.params.onChange) {
+              p.params.onChange(p, p.value, p.displayValue);
+          }
+          if (p.input && p.input.length > 0) {
+              $(p.input).val(p.params.formatValue ? p.params.formatValue(p, p.value, p.displayValue) : p.value.join(' '));
+              $(p.input).trigger('change');
+          }
+      };
+
+      // Columns Handlers
+      p.initPickerCol = function (colElement, updateItems) {
+          var colContainer = $(colElement);
+          var colIndex = colContainer.index();
+          var col = p.cols[colIndex];
+          if (col.divider) return;
+          col.container = colContainer;
+          col.wrapper = col.container.find('.picker-items-col-wrapper');
+          col.items = col.wrapper.find('.picker-item');
+          
+          var i, j;
+          var wrapperHeight, itemHeight, itemsHeight, minTranslate, maxTranslate;
+          col.replaceValues = function (values, displayValues) {
+              col.destroyEvents();
+              col.values = values;
+              col.displayValues = displayValues;
+              var newItemsHTML = p.columnHTML(col, true);
+              col.wrapper.html(newItemsHTML);
+              col.items = col.wrapper.find('.picker-item');
+              col.calcSize();
+              col.setValue(col.values[0] || '', 0, true);
+              col.initEvents();
+          };
+          col.calcSize = function () {
+              if (!col.values.length) return;
+              if (p.params.rotateEffect) {
+                  col.container.removeClass('picker-items-col-absolute');
+                  if (!col.width) col.container.css({width:''});
+              }
+              var colWidth, colHeight;
+              colWidth = 0;
+              colHeight = col.container[0].offsetHeight;
+              wrapperHeight = col.wrapper[0].offsetHeight;
+              itemHeight = col.items[0].offsetHeight;
+              itemsHeight = itemHeight * col.items.length;
+              minTranslate = colHeight / 2 - itemsHeight + itemHeight / 2;
+              maxTranslate = colHeight / 2 - itemHeight / 2;    
+              if (col.width) {
+                  colWidth = col.width;
+                  if (parseInt(colWidth, 10) === colWidth) colWidth = colWidth + 'px';
+                  col.container.css({width: colWidth});
+              }
+              if (p.params.rotateEffect) {
+                  if (!col.width) {
+                      col.items.each(function () {
+                          var item = $(this);
+                          item.css({width:'auto'});
+                          colWidth = Math.max(colWidth, item[0].offsetWidth);
+                          item.css({width:''});
+                      });
+                      col.container.css({width: (colWidth + 2) + 'px'});
+                  }
+                  col.container.addClass('picker-items-col-absolute');
+              }
+          };
+          col.calcSize();
+          
+          col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)').transition(0);
+
+
+          var activeIndex = 0;
+          var animationFrameId;
+
+          // Set Value Function
+          col.setValue = function (newValue, transition, valueCallbacks) {
+              if (typeof transition === 'undefined') transition = '';
+              var newActiveIndex = col.wrapper.find('.picker-item[data-picker-value="' + newValue + '"]').index();
+              if(typeof newActiveIndex === 'undefined' || newActiveIndex === -1) {
+                  col.value = col.displayValue = newValue;
+                  return;
+              }
+              var newTranslate = -newActiveIndex * itemHeight + maxTranslate;
+              // Update wrapper
+              col.wrapper.transition(transition);
+              col.wrapper.transform('translate3d(0,' + (newTranslate) + 'px,0)');
+                  
+              // Watch items
+              if (p.params.updateValuesOnMomentum && col.activeIndex && col.activeIndex !== newActiveIndex ) {
+                  $.cancelAnimationFrame(animationFrameId);
+                  col.wrapper.transitionEnd(function(){
+                      $.cancelAnimationFrame(animationFrameId);
+                  });
+                  updateDuringScroll();
+              }
+
+              // Update items
+              col.updateItems(newActiveIndex, newTranslate, transition, valueCallbacks);
+          };
+
+          col.updateItems = function (activeIndex, translate, transition, valueCallbacks) {
+              if (typeof translate === 'undefined') {
+                  translate = $.getTranslate(col.wrapper[0], 'y');
+              }
+              if(typeof activeIndex === 'undefined') activeIndex = -Math.round((translate - maxTranslate)/itemHeight);
+              if (activeIndex < 0) activeIndex = 0;
+              if (activeIndex >= col.items.length) activeIndex = col.items.length - 1;
+              var previousActiveIndex = col.activeIndex;
+              col.activeIndex = activeIndex;
+              /*
+              col.wrapper.find('.picker-selected, .picker-after-selected, .picker-before-selected').removeClass('picker-selected picker-after-selected picker-before-selected');
+
+              col.items.transition(transition);
+              var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
+              var prevItems = selectedItem.prevAll().addClass('picker-before-selected');
+              var nextItems = selectedItem.nextAll().addClass('picker-after-selected');
+              */
+              //去掉 .picker-after-selected, .picker-before-selected 以提高性能
+              col.wrapper.find('.picker-selected').removeClass('picker-selected');
+              if (p.params.rotateEffect) {
+                col.items.transition(transition);
+              }
+              var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
+
+              if (valueCallbacks || typeof valueCallbacks === 'undefined') {
+                  // Update values
+                  col.value = selectedItem.attr('data-picker-value');
+                  col.displayValue = col.displayValues ? col.displayValues[activeIndex] : col.value;
+                  // On change callback
+                  if (previousActiveIndex !== activeIndex) {
+                      if (col.onChange) {
+                          col.onChange(p, col.value, col.displayValue);
+                      }
+                      p.updateValue();
+                  }
+              }
+                  
+              // Set 3D rotate effect
+              if (!p.params.rotateEffect) {
+                  return;
+              }
+              var percentage = (translate - (Math.floor((translate - maxTranslate)/itemHeight) * itemHeight + maxTranslate)) / itemHeight;
+              
+              col.items.each(function () {
+                  var item = $(this);
+                  var itemOffsetTop = item.index() * itemHeight;
+                  var translateOffset = maxTranslate - translate;
+                  var itemOffset = itemOffsetTop - translateOffset;
+                  var percentage = itemOffset / itemHeight;
+
+                  var itemsFit = Math.ceil(col.height / itemHeight / 2) + 1;
+                  
+                  var angle = (-18*percentage);
+                  if (angle > 180) angle = 180;
+                  if (angle < -180) angle = -180;
+                  // Far class
+                  if (Math.abs(percentage) > itemsFit) item.addClass('picker-item-far');
+                  else item.removeClass('picker-item-far');
+                  // Set transform
+                  item.transform('translate3d(0, ' + (-translate + maxTranslate) + 'px, ' + (originBug ? -110 : 0) + 'px) rotateX(' + angle + 'deg)');
+              });
+          };
+
+          function updateDuringScroll() {
+              animationFrameId = $.requestAnimationFrame(function () {
+                  col.updateItems(undefined, undefined, 0);
+                  updateDuringScroll();
+              });
+          }
+
+          // Update items on init
+          if (updateItems) col.updateItems(0, maxTranslate, 0);
+
+          var allowItemClick = true;
+          var isTouched, isMoved, touchStartY, touchCurrentY, touchStartTime, touchEndTime, startTranslate, returnTo, currentTranslate, prevTranslate, velocityTranslate, velocityTime;
+          function handleTouchStart (e) {
+              if (isMoved || isTouched) return;
+              e.preventDefault();
+              isTouched = true;
+              var position = $.getTouchPosition(e);
+              touchStartY = touchCurrentY = position.y;
+              touchStartTime = (new Date()).getTime();
+              
+              allowItemClick = true;
+              startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
+          }
+          function handleTouchMove (e) {
+              if (!isTouched) return;
+              e.preventDefault();
+              allowItemClick = false;
+              var position = $.getTouchPosition(e);
+              touchCurrentY = position.y;
+              if (!isMoved) {
+                  // First move
+                  $.cancelAnimationFrame(animationFrameId);
+                  isMoved = true;
+                  startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
+                  col.wrapper.transition(0);
+              }
+              e.preventDefault();
+
+              var diff = touchCurrentY - touchStartY;
+              currentTranslate = startTranslate + diff;
+              returnTo = undefined;
+
+              // Normalize translate
+              if (currentTranslate < minTranslate) {
+                  currentTranslate = minTranslate - Math.pow(minTranslate - currentTranslate, 0.8);
+                  returnTo = 'min';
+              }
+              if (currentTranslate > maxTranslate) {
+                  currentTranslate = maxTranslate + Math.pow(currentTranslate - maxTranslate, 0.8);
+                  returnTo = 'max';
+              }
+              // Transform wrapper
+              col.wrapper.transform('translate3d(0,' + currentTranslate + 'px,0)');
+
+              // Update items
+              col.updateItems(undefined, currentTranslate, 0, p.params.updateValuesOnTouchmove);
+              
+              // Calc velocity
+              velocityTranslate = currentTranslate - prevTranslate || currentTranslate;
+              velocityTime = (new Date()).getTime();
+              prevTranslate = currentTranslate;
+          }
+          function handleTouchEnd (e) {
+              if (!isTouched || !isMoved) {
+                  isTouched = isMoved = false;
+                  return;
+              }
+              isTouched = isMoved = false;
+              col.wrapper.transition('');
+              if (returnTo) {
+                  if (returnTo === 'min') {
+                      col.wrapper.transform('translate3d(0,' + minTranslate + 'px,0)');
+                  }
+                  else col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)');
+              }
+              touchEndTime = new Date().getTime();
+              var velocity, newTranslate;
+              if (touchEndTime - touchStartTime > 300) {
+                  newTranslate = currentTranslate;
+              }
+              else {
+                  velocity = Math.abs(velocityTranslate / (touchEndTime - velocityTime));
+                  newTranslate = currentTranslate + velocityTranslate * p.params.momentumRatio;
+              }
+
+              newTranslate = Math.max(Math.min(newTranslate, maxTranslate), minTranslate);
+
+              // Active Index
+              var activeIndex = -Math.floor((newTranslate - maxTranslate)/itemHeight);
+
+              // Normalize translate
+              if (!p.params.freeMode) newTranslate = -activeIndex * itemHeight + maxTranslate;
+
+              // Transform wrapper
+              col.wrapper.transform('translate3d(0,' + (parseInt(newTranslate,10)) + 'px,0)');
+
+              // Update items
+              col.updateItems(activeIndex, newTranslate, '', true);
+
+              // Watch items
+              if (p.params.updateValuesOnMomentum) {
+                  updateDuringScroll();
+                  col.wrapper.transitionEnd(function(){
+                      $.cancelAnimationFrame(animationFrameId);
+                  });
+              }
+
+              // Allow click
+              setTimeout(function () {
+                  allowItemClick = true;
+              }, 100);
+          }
+
+          function handleClick(e) {
+              if (!allowItemClick) return;
+              $.cancelAnimationFrame(animationFrameId);
+              /*jshint validthis:true */
+              var value = $(this).attr('data-picker-value');
+              col.setValue(value);
+          }
+
+          col.initEvents = function (detach) {
+              var method = detach ? 'off' : 'on';
+              col.container[method]($.touchEvents.start, handleTouchStart);
+              col.container[method]($.touchEvents.move, handleTouchMove);
+              col.container[method]($.touchEvents.end, handleTouchEnd);
+              col.items[method]('click', handleClick);
+          };
+          col.destroyEvents = function () {
+              col.initEvents(true);
+          };
+
+          col.container[0].f7DestroyPickerCol = function () {
+              col.destroyEvents();
+          };
+
+          col.initEvents();
+
+      };
+      p.destroyPickerCol = function (colContainer) {
+          colContainer = $(colContainer);
+          if ('f7DestroyPickerCol' in colContainer[0]) colContainer[0].f7DestroyPickerCol();
+      };
+      // Resize cols
+      function resizeCols() {
+          if (!p.opened) return;
+          for (var i = 0; i < p.cols.length; i++) {
+              if (!p.cols[i].divider) {
+                  p.cols[i].calcSize();
+                  p.cols[i].setValue(p.cols[i].value, 0, false);
+              }
+          }
+      }
+      $(window).on('resize', resizeCols);
+
+      // HTML Layout
+      p.columnHTML = function (col, onlyItems) {
+          var columnItemsHTML = '';
+          var columnHTML = '';
+          if (col.divider) {
+              columnHTML += '<div class="picker-items-col picker-items-col-divider ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '">' + col.content + '</div>';
+          }
+          else {
+              for (var j = 0; j < col.values.length; j++) {
+                  columnItemsHTML += '<div class="picker-item" data-picker-value="' + col.values[j] + '">' + (col.displayValues ? col.displayValues[j] : col.values[j]) + '</div>';
+              }
+              columnHTML += '<div class="picker-items-col ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '"><div class="picker-items-col-wrapper">' + columnItemsHTML + '</div></div>';
+          }
+          return onlyItems ? columnItemsHTML : columnHTML;
+      };
+      p.layout = function () {
+          var pickerHTML = '';
+          var pickerClass = '';
+          var i;
+          p.cols = [];
+          var colsHTML = '';
+          for (i = 0; i < p.params.cols.length; i++) {
+              var col = p.params.cols[i];
+              colsHTML += p.columnHTML(p.params.cols[i]);
+              p.cols.push(col);
+          }
+          pickerClass = 'weui-picker-modal picker-columns ' + (p.params.cssClass || '') + (p.params.rotateEffect ? ' picker-3d' : '') + (p.params.cols.length === 1 ? ' picker-columns-single' : '');
+          pickerHTML =
+              '<div class="' + (pickerClass) + '">' +
+                  (p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText).replace(/{{title}}/g, p.params.title) : '') +
+                  '<div class="picker-modal-inner picker-items">' +
+                      colsHTML +
+                      '<div class="picker-center-highlight"></div>' +
+                  '</div>' +
+              '</div>';
+              
+          p.pickerHTML = pickerHTML;    
+      };
+
+      // Input Events
+      function openOnInput(e) {
+          e.preventDefault();
+          if (p.opened) return;
+          p.open();
+          if (p.params.scrollToInput && !isPopover()) {
+              var pageContent = p.input.parents('.content');
+              if (pageContent.length === 0) return;
+
+              var paddingTop = parseInt(pageContent.css('padding-top'), 10),
+                  paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
+                  pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
+                  pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
+                  newPaddingBottom;
+              var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
+              if (inputTop > pageHeight) {
+                  var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
+                  if (scrollTop + pageHeight > pageScrollHeight) {
+                      newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
+                      if (pageHeight === pageScrollHeight) {
+                          newPaddingBottom = p.container.height();
+                      }
+                      pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
+                  }
+                  pageContent.scrollTop(scrollTop, 300);
+              }
+          }
+      }
+      function closeOnHTMLClick(e) {
+          if (inPopover()) return;
+          if (p.input && p.input.length > 0) {
+              if (e.target !== p.input[0] && $(e.target).parents('.weui-picker-modal').length === 0) p.close();
+          }
+          else {
+              if ($(e.target).parents('.weui-picker-modal').length === 0) p.close();   
+          }
+      }
+
+      if (p.params.input) {
+          p.input = $(p.params.input);
+          if (p.input.length > 0) {
+              if (p.params.inputReadOnly) p.input.prop('readOnly', true);
+              if (!p.inline) {
+                  p.input.on('click', openOnInput);    
+              }
+              if (p.params.inputReadOnly) {
+                  p.input.on('focus mousedown', function (e) {
+                      e.preventDefault();
+                  });
+              }
+          }
+              
+      }
+      
+      if (!p.inline) $('html').on('click', closeOnHTMLClick);
+
+      // Open
+      function onPickerClose() {
+          p.opened = false;
+          if (p.input && p.input.length > 0) p.input.parents('.page-content').css({'padding-bottom': ''});
+          if (p.params.onClose) p.params.onClose(p);
+
+          // Destroy events
+          p.container.find('.picker-items-col').each(function () {
+              p.destroyPickerCol(this);
+          });
+      }
+
+      p.opened = false;
+      p.open = function () {
+          var toPopover = isPopover();
+
+          if (!p.opened) {
+
+              // Layout
+              p.layout();
+
+              // Append
+              if (toPopover) {
+                  p.pickerHTML = '<div class="popover popover-picker-columns"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
+                  p.popover = $.popover(p.pickerHTML, p.params.input, true);
+                  p.container = $(p.popover).find('.weui-picker-modal');
+                  $(p.popover).on('close', function () {
+                      onPickerClose();
+                  });
+              }
+              else if (p.inline) {
+                  p.container = $(p.pickerHTML);
+                  p.container.addClass('picker-modal-inline');
+                  $(p.params.container).append(p.container);
+              }
+              else {
+                  p.container = $($.openPicker(p.pickerHTML));
+                  $(p.container)
+                  .on('close', function () {
+                      onPickerClose();
+                  });
+              }
+
+              // Store picker instance
+              p.container[0].f7Picker = p;
+
+              // Init Events
+              p.container.find('.picker-items-col').each(function () {
+                  var updateItems = true;
+                  if ((!p.initialized && p.params.value) || (p.initialized && p.value)) updateItems = false;
+                  p.initPickerCol(this, updateItems);
+              });
+              
+              // Set value
+              if (!p.initialized) {
+                  if (p.params.value) {
+                      p.setValue(p.params.value, 0);
+                  }
+              }
+              else {
+                  if (p.value) p.setValue(p.value, 0);
+              }
+          }
+
+          // Set flag
+          p.opened = true;
+          p.initialized = true;
+
+          if (p.params.onOpen) p.params.onOpen(p);
+      };
+
+      // Close
+      p.close = function (force) {
+          if (!p.opened || p.inline) return;
+          if (inPopover()) {
+              $.closePicker(p.popover);
+              return;
+          }
+          else {
+              $.closePicker(p.container);
+              return;
+          }
+      };
+
+      // Destroy
+      p.destroy = function () {
+          p.close();
+          if (p.params.input && p.input.length > 0) {
+              p.input.off('click focus', openOnInput);
+              $(p.input).data('picker', null);
+          }
+          $('html').off('click', closeOnHTMLClick);
+          $(window).off('resize', resizeCols);
+      };
+
+      if (p.inline) {
+          p.open();
+      }
+
+      return p;
+  };
+
+  $(document).on("click", ".close-picker", function() {
+    var pickerToClose = $('.weui-picker-modal.weui-picker-modal-visible');
+    if (pickerToClose.length > 0) {
+      $.closePicker(pickerToClose);
+    }
+  });
+
+  //修复picker会滚动页面的bug
+  $(document).on($.touchEvents.move, ".picker-modal-inner", function(e) {
+    e.preventDefault();
+  });
+
+
+  $.openPicker = function(tpl, className, callback) {
+
+    if(typeof className === "function") {
+      callback = className;
+      className = undefined;
+    }
+
+    $.closePicker();
+
+    var container = $("<div class='weui-picker-container "+ (className || "") + "'></div>").appendTo(document.body);
+    container.show();
+
+    container.addClass("weui-picker-container-visible");
+
+    //关于布局的问题,如果直接放在body上,则做动画的时候会撑开body高度而导致滚动条变化。
+    var dialog = $(tpl).appendTo(container);
+    
+    dialog.width(); //通过取一次CSS值,强制浏览器不能把上下两行代码合并执行,因为合并之后会导致无法出现动画。
+
+    dialog.addClass("weui-picker-modal-visible");
+
+    callback && container.on("close", callback);
+
+    return dialog;
+  }
+
+  $.updatePicker = function(tpl) {
+    var container = $(".weui-picker-container-visible");
+    if(!container[0]) return false;
+
+    container.html("");
+
+    var dialog = $(tpl).appendTo(container);
+
+    dialog.addClass("weui-picker-modal-visible");
+
+    return dialog;
+  }
+
+  $.closePicker = function(container, callback) {
+    if(typeof container === "function") callback = container;
+    $(".weui-picker-modal-visible").removeClass("weui-picker-modal-visible").transitionEnd(function() {
+      $(this).parent().remove();
+      callback && callback();
+    }).trigger("close");
+  };
+
+  $.fn.picker = function(params) {
+    var args = arguments;
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      
+      var picker = $this.data("picker");
+      if(!picker) {
+        params = $.extend({ input: this }, params || {}) // https://github.com/lihongxun945/jquery-weui/issues/432
+        var inputValue = $this.val();
+        if(params.value === undefined && inputValue !== "") {
+          params.value = (params.cols && params.cols.length > 1) ? inputValue.split(" ") : [inputValue];
+        }
+        var p = $.extend({input: this}, params);
+        picker = new Picker(p);
+        $this.data("picker", picker);
+      }
+      if(typeof params === typeof "a") {
+        picker[params].apply(picker, Array.prototype.slice.call(args, 1));
+      }
+    });
+  };
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+
+  var defaults;
+
+  var selects = [];
+
+  var Select = function(input, config) {
+
+    var self = this;
+    this.config = config;
+
+    //init empty data
+    this.data = {
+      values: '',
+      titles: '',
+      origins: [],
+      length: 0
+    };
+
+    this.$input = $(input);
+    this.$input.prop("readOnly", true);
+
+    this.initConfig();
+
+    config = this.config;
+
+    this.$input.click($.proxy(this.open, this));
+    selects.push(this)
+  }
+
+  Select.prototype.initConfig = function() {
+    this.config = $.extend({}, defaults, this.config);
+
+    var config = this.config;
+
+    if(!config.items || !config.items.length) return;
+
+    config.items = config.items.map(function(d, i) {
+      if(typeof d == typeof "a") {
+        return {
+          title: d,
+          value: d
+        };
+      }
+
+      return d;
+    });
+
+
+    this.tpl = $.t7.compile("<div class='weui-picker-modal weui-select-modal'>" + config.toolbarTemplate + (config.multi ? config.checkboxTemplate : config.radioTemplate) + "</div>");
+
+    if(config.input !== undefined) this.$input.val(config.input);
+
+    this.parseInitValue();
+
+    this._init = true;
+  }
+
+  Select.prototype.updateInputValue = function(values, titles) {
+    var v, t;
+    if(this.config.multi) {
+      v = values.join(this.config.split);
+      t = titles.join(this.config.split);
+    } else {
+      v = values[0];
+      t = titles[0];
+    }
+
+    //caculate origin data
+    var origins = [];
+
+    this.config.items.forEach(function(d) {
+      values.each(function(i, dd) {
+        if(d.value == dd) origins.push(d);
+      });
+    });
+
+    this.$input.val(t).data("values", v);
+    this.$input.attr("value", t).attr("data-values", v);
+
+    var data = {
+      values: v,
+      titles: t,
+      valuesArray: values,
+      titlesArray: titles,
+      origins: origins,
+      length: origins.length
+    };
+    this.data = data;
+    this.$input.trigger("change", data);
+    this.config.onChange && this.config.onChange.call(this, data);
+  }
+
+  Select.prototype.parseInitValue = function() {
+    var value = this.$input.val();
+    var items = this.config.items;
+
+    //如果input为空,只有在第一次初始化的时候才保留默认选择。因为后来就是用户自己取消了全部选择,不能再为他选中默认值。
+    if( !this._init && (value === undefined || value == null || value === "")) return;
+
+    var titles = this.config.multi ? value.split(this.config.split) : [value];
+    for(var i=0;i<items.length;i++) {
+      items[i].checked = false;
+      for(var j=0;j<titles.length;j++) {
+        if(items[i].title === titles[j]) {
+          items[i].checked = true;
+        }
+      }
+    }
+  }
+
+  Select.prototype._bind = function(dialog) {
+    var self = this,
+        config = this.config;
+    dialog.on("change", function(e) {
+      var checked = dialog.find("input:checked");
+      var values = checked.map(function() {
+        return $(this).val();
+      });
+      var titles = checked.map(function() {
+        return $(this).data("title");
+      });
+      self.updateInputValue(values, titles);
+
+      if(config.autoClose && !config.multi) self.close();
+    })
+    .trigger('change')
+    .on("click", ".close-select", function() {
+      self.close();
+    });
+  }
+
+  //更新数据
+  Select.prototype.update = function(config) {
+    this.config = $.extend({}, this.config, config);
+    this.initConfig();
+    if(this._open) {
+      this._bind($.updatePicker(this.getHTML()));
+    }
+  }
+  
+  Select.prototype.open = function(values, titles) {
+
+    if(this._open) return;
+
+    // open picker 会默认关掉其他的,但是 onClose 不会被调用,所以这里先关掉其他select
+    for (var i = 0; i < selects.length; i++ ) {
+      var s = selects[i];
+      if (s === this) continue;
+      if (s._open) {
+        if(!s.close()) return false; // 其他的select由于某些条件限制关闭失败。
+      }
+    }
+
+    this.parseInitValue();
+
+    var config = this.config;
+
+    var dialog = this.dialog = $.openPicker(this.getHTML());
+    
+    this._bind(dialog);
+
+    this._open = true;
+    if(config.onOpen) config.onOpen(this);
+  }
+
+  Select.prototype.close = function(callback, force) {
+    if (!this._open) return false;
+    var self = this,
+        beforeClose = this.config.beforeClose;
+
+    if(typeof callback === typeof true) {
+      force === callback;
+    }
+    if(!force) {
+      if(beforeClose && typeof beforeClose === 'function' && beforeClose.call(this, this.data.values, this.data.titles) === false) {
+        return false
+      }
+      if(this.config.multi) {
+        if(this.config.min !== undefined && this.data.length < this.config.min) {
+          $.toast("请至少选择"+this.config.min+"个", "text");
+          return false
+        }
+        if(this.config.max !== undefined && this.data.length > this.config.max) {
+          $.toast("最多只能选择"+this.config.max+"个", "text");
+          return false
+        }
+      }
+    }
+    $.closePicker(function() {
+      self.onClose();
+      callback && callback();
+    });
+
+    return true
+  }
+
+  Select.prototype.onClose = function() {
+    this._open = false;
+    if(this.config.onClose) this.config.onClose(this);
+  }
+
+  Select.prototype.getHTML = function(callback) {
+    var config = this.config;
+    return this.tpl({
+      items: config.items,
+      title: config.title,
+      closeText: config.closeText
+    })
+  }
+
+
+  $.fn.select = function(params, args) {
+
+    return this.each(function() {
+      var $this = $(this);
+      if(!$this.data("weui-select")) $this.data("weui-select", new Select(this, params));
+
+      var select = $this.data("weui-select");
+
+      if(typeof params === typeof "a") select[params].call(select, args);
+
+      return select;
+    });
+  }
+
+  defaults = $.fn.select.prototype.defaults = {
+    items: [],
+    input: undefined, //输入框的初始值
+    title: "请选择",
+    multi: false,
+    closeText: "确定",
+    autoClose: true, //是否选择完成后自动关闭,只有单选模式下才有效
+    onChange: undefined, //function
+    beforeClose: undefined, // function 关闭之前,如果返回false则阻止关闭
+    onClose: undefined, //function
+    onOpen: undefined, //function
+    split: ",",  //多选模式下的分隔符
+    min: undefined, //多选模式下可用,最少选择数
+    max: undefined, //单选模式下可用,最多选择数
+    toolbarTemplate: '<div class="toolbar">\
+      <div class="toolbar-inner">\
+      <a href="javascript:;" class="picker-button close-select">{{closeText}}</a>\
+      <h1 class="title">{{title}}</h1>\
+      </div>\
+      </div>',
+    radioTemplate:
+      '<div class="weui-cells weui-cells_radio">\
+        {{#items}}\
+        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
+          <div class="weui-cell__bd weui-cell_primary">\
+            <p>{{this.title}}</p>\
+          </div>\
+          <div class="weui-cell__ft">\
+            <input type="radio" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}">\
+            <span class="weui-icon-checked"></span>\
+          </div>\
+        </label>\
+        {{/items}}\
+      </div>',
+    checkboxTemplate:
+      '<div class="weui-cells weui-cells_checkbox">\
+        {{#items}}\
+        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
+          <div class="weui-cell__bd weui-cell_primary">\
+            <p>{{this.title}}</p>\
+          </div>\
+          <div class="weui-cell__ft">\
+            <input type="checkbox" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}" >\
+            <span class="weui-icon-checked"></span>\
+          </div>\
+        </label>\
+        {{/items}}\
+      </div>',
+  }
+
+}($);
+
+/*======================================================
+************   Calendar   ************
+======================================================*/
+/* global $:true */
+/*jshint unused: false*/
++function ($) {
+  "use strict";
+  var rtl = false;
+  var defaults;
+  var isSameDate = function (a, b) {
+    var a = new Date(a),
+      b = new Date(b);
+    return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
+  }
+  var Calendar = function (params) {
+      var p = this;
+      params = params || {};
+      for (var def in defaults) {
+          if (typeof params[def] === 'undefined') {
+              params[def] = defaults[def];
+          }
+      }
+      p.params = params;
+      p.initialized = false;
+
+      // Inline flag
+      p.inline = p.params.container ? true : false;
+
+      // Is horizontal
+      p.isH = p.params.direction === 'horizontal';
+
+      // RTL inverter
+      var inverter = p.isH ? (rtl ? -1 : 1) : 1;
+
+      // Animating flag
+      p.animating = false;
+
+      // Should be converted to popover
+      function isPopover() {
+          var toPopover = false;
+          if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
+          if (!p.inline && p.params.input) {
+              if (p.params.onlyInPopover) toPopover = true;
+              else {
+                  if ($.device.ios) {
+                      toPopover = $.device.ipad ? true : false;
+                  }
+                  else {
+                      if ($(window).width() >= 768) toPopover = true;
+                  }
+              }
+          } 
+          return toPopover; 
+      }
+      function inPopover() {
+          if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
+          else return false;
+      }
+
+      // Format date
+      function formatDate(date) {
+          date = new Date(date);
+          var year = date.getFullYear();
+          var month = date.getMonth();
+          var month1 = month + 1;
+          var day = date.getDate();
+          var weekDay = date.getDay();
+          return p.params.dateFormat
+              .replace(/yyyy/g, year)
+              .replace(/yy/g, (year + '').substring(2))
+              .replace(/mm/g, month1 < 10 ? '0' + month1 : month1)
+              .replace(/m/g, month1)
+              .replace(/MM/g, p.params.monthNames[month])
+              .replace(/M/g, p.params.monthNamesShort[month])
+              .replace(/dd/g, day < 10 ? '0' + day : day)
+              .replace(/d/g, day)
+              .replace(/DD/g, p.params.dayNames[weekDay])
+              .replace(/D/g, p.params.dayNamesShort[weekDay]);
+      }
+
+
+      // Value
+      p.addValue = function (value) {
+          if (p.params.multiple) {
+              if (!p.value) p.value = [];
+              var inValuesIndex;
+              for (var i = 0; i < p.value.length; i++) {
+                  if (isSameDate(value, p.value[i])) {
+                      inValuesIndex = i;
+                  }
+              }
+              if (typeof inValuesIndex === 'undefined') {
+                  p.value.push(value);
+              }
+              else {
+                  p.value.splice(inValuesIndex, 1);
+              }
+              p.updateValue();
+          }
+          else {
+              p.value = [value];
+              p.updateValue();
+          }
+      };
+      p.setValue = function (arrValues) {
+        var date = new Date(arrValues[0]);
+        p.setYearMonth(date.getFullYear(), date.getMonth());
+        p.addValue(+ date);
+      };
+      p.updateValue = function () {
+          p.wrapper.find('.picker-calendar-day-selected').removeClass('picker-calendar-day-selected');
+          var i, inputValue;
+          for (i = 0; i < p.value.length; i++) {
+              var valueDate = new Date(p.value[i]);
+              p.wrapper.find('.picker-calendar-day[data-date="' + valueDate.getFullYear() + '-' + valueDate.getMonth() + '-' + valueDate.getDate() + '"]').addClass('picker-calendar-day-selected');
+          }
+          if (p.params.onChange) {
+            p.params.onChange(p, p.value.map(formatDate), p.value.map(function (d) {
+              return + new Date(typeof d === typeof 'a' ? d.split(/\D/).filter(function (a) { return !!a; }).join("-") : d);
+            }));
+          }
+          if (p.input && p.input.length > 0) {
+              if (p.params.formatValue) inputValue = p.params.formatValue(p, p.value);
+              else {
+                  inputValue = [];
+                  for (i = 0; i < p.value.length; i++) {
+                      inputValue.push(formatDate(p.value[i]));
+                  }
+                  inputValue = inputValue.join(', ');
+              } 
+              $(p.input).val(inputValue);
+              $(p.input).trigger('change');
+          }
+      };
+
+      // Columns Handlers
+      p.initCalendarEvents = function () {
+          var col;
+          var allowItemClick = true;
+          var isTouched, isMoved, touchStartX, touchStartY, touchCurrentX, touchCurrentY, touchStartTime, touchEndTime, startTranslate, currentTranslate, wrapperWidth, wrapperHeight, percentage, touchesDiff, isScrolling;
+          function handleTouchStart (e) {
+              if (isMoved || isTouched) return;
+              // e.preventDefault();
+              isTouched = true;
+              var position = $.getTouchPosition(e);
+              touchStartX = touchCurrentY = position.x;
+              touchStartY = touchCurrentY = position.y;
+              touchStartTime = (new Date()).getTime();
+              percentage = 0;
+              allowItemClick = true;
+              isScrolling = undefined;
+              startTranslate = currentTranslate = p.monthsTranslate;
+          }
+          function handleTouchMove (e) {
+              if (!isTouched) return;
+              var position = $.getTouchPosition(e);
+              touchCurrentX = position.x;
+              touchCurrentY = position.y;
+              if (typeof isScrolling === 'undefined') {
+                  isScrolling = !!(isScrolling || Math.abs(touchCurrentY - touchStartY) > Math.abs(touchCurrentX - touchStartX));
+              }
+              if (p.isH && isScrolling) {
+                  isTouched = false;
+                  return;
+              }
+              e.preventDefault();
+              if (p.animating) {
+                  isTouched = false;
+                  return;   
+              }
+              allowItemClick = false;
+              if (!isMoved) {
+                  // First move
+                  isMoved = true;
+                  wrapperWidth = p.wrapper[0].offsetWidth;
+                  wrapperHeight = p.wrapper[0].offsetHeight;
+                  p.wrapper.transition(0);
+              }
+              e.preventDefault();
+
+              touchesDiff = p.isH ? touchCurrentX - touchStartX : touchCurrentY - touchStartY;
+              percentage = touchesDiff/(p.isH ? wrapperWidth : wrapperHeight);
+              currentTranslate = (p.monthsTranslate * inverter + percentage) * 100;
+
+              // Transform wrapper
+              p.wrapper.transform('translate3d(' + (p.isH ? currentTranslate : 0) + '%, ' + (p.isH ? 0 : currentTranslate) + '%, 0)');
+
+          }
+          function handleTouchEnd (e) {
+              if (!isTouched || !isMoved) {
+                  isTouched = isMoved = false;
+                  return;
+              }
+              isTouched = isMoved = false;
+              
+              touchEndTime = new Date().getTime();
+              if (touchEndTime - touchStartTime < 300) {
+                  if (Math.abs(touchesDiff) < 10) {
+                      p.resetMonth();
+                  }
+                  else if (touchesDiff >= 10) {
+                      if (rtl) p.nextMonth();
+                      else p.prevMonth();
+                  }
+                  else {
+                      if (rtl) p.prevMonth();
+                      else p.nextMonth();   
+                  }
+              }
+              else {
+                  if (percentage <= -0.5) {
+                      if (rtl) p.prevMonth();
+                      else p.nextMonth();
+                  }
+                  else if (percentage >= 0.5) {
+                      if (rtl) p.nextMonth();
+                      else p.prevMonth();
+                  }
+                  else {
+                      p.resetMonth();
+                  }
+              }
+
+              // Allow click
+              setTimeout(function () {
+                  allowItemClick = true;
+              }, 100);
+          }
+
+          function handleDayClick(e) {
+              if (!allowItemClick) return;
+              var day = $(e.target).parents('.picker-calendar-day');
+              if (day.length === 0 && $(e.target).hasClass('picker-calendar-day')) {
+                  day = $(e.target);
+              }
+              if (day.length === 0) return;
+              // if (day.hasClass('picker-calendar-day-selected') && !p.params.multiple) return;
+              if (day.hasClass('picker-calendar-day-disabled')) return;
+              if (day.hasClass('picker-calendar-day-next')) p.nextMonth();
+              if (day.hasClass('picker-calendar-day-prev')) p.prevMonth();
+              var dateYear = day.attr('data-year');
+              var dateMonth = day.attr('data-month');
+              var dateDay = day.attr('data-day');
+              if (p.params.onDayClick) {
+                  p.params.onDayClick(p, day[0], dateYear, dateMonth, dateDay);
+              }
+              p.addValue(new Date(dateYear, dateMonth, dateDay).getTime());
+              if (p.params.closeOnSelect && !p.params.multiple) p.close();
+          }
+
+          p.container.find('.picker-calendar-prev-month').on('click', p.prevMonth);
+          p.container.find('.picker-calendar-next-month').on('click', p.nextMonth);
+          p.container.find('.picker-calendar-prev-year').on('click', p.prevYear);
+          p.container.find('.picker-calendar-next-year').on('click', p.nextYear);
+          p.wrapper.on('click', handleDayClick);
+          if (p.params.touchMove) {
+              p.wrapper.on($.touchEvents.start, handleTouchStart);
+              p.wrapper.on($.touchEvents.move, handleTouchMove);
+              p.wrapper.on($.touchEvents.end, handleTouchEnd);
+          }
+              
+          p.container[0].f7DestroyCalendarEvents = function () {
+              p.container.find('.picker-calendar-prev-month').off('click', p.prevMonth);
+              p.container.find('.picker-calendar-next-month').off('click', p.nextMonth);
+              p.container.find('.picker-calendar-prev-year').off('click', p.prevYear);
+              p.container.find('.picker-calendar-next-year').off('click', p.nextYear);
+              p.wrapper.off('click', handleDayClick);
+              if (p.params.touchMove) {
+                  p.wrapper.off($.touchEvents.start, handleTouchStart);
+                  p.wrapper.off($.touchEvents.move, handleTouchMove);
+                  p.wrapper.off($.touchEvents.end, handleTouchEnd);
+              }
+          };
+          
+
+      };
+      p.destroyCalendarEvents = function (colContainer) {
+          if ('f7DestroyCalendarEvents' in p.container[0]) p.container[0].f7DestroyCalendarEvents();
+      };
+
+      // Calendar Methods
+      p.daysInMonth = function (date) {
+          var d = new Date(date);
+          return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
+      };
+      p.monthHTML = function (date, offset) {
+          date = new Date(date);
+          var year = date.getFullYear(),
+              month = date.getMonth(),
+              day = date.getDate();
+          if (offset === 'next') {
+              if (month === 11) date = new Date(year + 1, 0);
+              else date = new Date(year, month + 1, 1);
+          }
+          if (offset === 'prev') {
+              if (month === 0) date = new Date(year - 1, 11);
+              else date = new Date(year, month - 1, 1);
+          }
+          if (offset === 'next' || offset === 'prev') {
+              month = date.getMonth();
+              year = date.getFullYear();
+          }
+          var daysInPrevMonth = p.daysInMonth(new Date(date.getFullYear(), date.getMonth()).getTime() - 10 * 24 * 60 * 60 * 1000),
+              daysInMonth = p.daysInMonth(date),
+              firstDayOfMonthIndex = new Date(date.getFullYear(), date.getMonth()).getDay();
+          if (firstDayOfMonthIndex === 0) firstDayOfMonthIndex = 7;
+          
+          var dayDate, currentValues = [], i, j,
+              rows = 6, cols = 7,
+              monthHTML = '',
+              dayIndex = 0 + (p.params.firstDay - 1),    
+              today = new Date().setHours(0,0,0,0),
+              minDate = p.params.minDate ? new Date(p.params.minDate).getTime() : null,
+              maxDate = p.params.maxDate ? new Date(p.params.maxDate).getTime() : null;
+
+          if (p.value && p.value.length) {
+              for (i = 0; i < p.value.length; i++) {
+                  currentValues.push(new Date(p.value[i]).setHours(0,0,0,0));
+              }
+          }
+              
+          for (i = 1; i <= rows; i++) {
+              var rowHTML = '';
+              var row = i;
+              for (j = 1; j <= cols; j++) {
+                  var col = j;
+                  dayIndex ++;
+                  var dayNumber = dayIndex - firstDayOfMonthIndex;
+                  var addClass = '';
+                  if (dayNumber < 0) {
+                      dayNumber = daysInPrevMonth + dayNumber + 1;
+                      addClass += ' picker-calendar-day-prev';
+                      dayDate = new Date(month - 1 < 0 ? year - 1 : year, month - 1 < 0 ? 11 : month - 1, dayNumber).getTime();
+                  }
+                  else {
+                      dayNumber = dayNumber + 1;
+                      if (dayNumber > daysInMonth) {
+                          dayNumber = dayNumber - daysInMonth;
+                          addClass += ' picker-calendar-day-next';
+                          dayDate = new Date(month + 1 > 11 ? year + 1 : year, month + 1 > 11 ? 0 : month + 1, dayNumber).getTime();
+                      }
+                      else {
+                          dayDate = new Date(year, month, dayNumber).getTime();    
+                      }
+                  }
+                  // Today
+                  if (dayDate === today) addClass += ' picker-calendar-day-today';
+                  // Selected
+                  if (currentValues.indexOf(dayDate) >= 0) addClass += ' picker-calendar-day-selected';
+                  // Weekend
+                  if (p.params.weekendDays.indexOf(col - 1) >= 0) {
+                      addClass += ' picker-calendar-day-weekend';
+                  }
+                  // Disabled
+                  if ((minDate && dayDate < minDate) || (maxDate && dayDate > maxDate)) {
+                      addClass += ' picker-calendar-day-disabled';   
+                  }
+
+                  dayDate = new Date(dayDate);
+                  var dayYear = dayDate.getFullYear();
+                  var dayMonth = dayDate.getMonth();
+                  rowHTML += '<div data-year="' + dayYear + '" data-month="' + dayMonth + '" data-day="' + dayNumber + '" class="picker-calendar-day' + (addClass) + '" data-date="' + (dayYear + '-' + dayMonth + '-' + dayNumber) + '"><span>'+dayNumber+'</span></div>';
+              }
+              monthHTML += '<div class="picker-calendar-row">' + rowHTML + '</div>';
+          }
+          monthHTML = '<div class="picker-calendar-month" data-year="' + year + '" data-month="' + month + '">' + monthHTML + '</div>';
+          return monthHTML;
+      };
+      p.animating = false;
+      p.updateCurrentMonthYear = function (dir) {
+          if (typeof dir === 'undefined') {
+              p.currentMonth = parseInt(p.months.eq(1).attr('data-month'), 10);
+              p.currentYear = parseInt(p.months.eq(1).attr('data-year'), 10);   
+          }
+          else {
+              p.currentMonth = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-month'), 10);
+              p.currentYear = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-year'), 10);
+          }
+          p.container.find('.current-month-value').text(p.params.monthNames[p.currentMonth]);
+          p.container.find('.current-year-value').text(p.currentYear);
+              
+      };
+      p.onMonthChangeStart = function (dir) {
+          p.updateCurrentMonthYear(dir);
+          p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
+          var currentIndex = dir === 'next' ? p.months.length - 1 : 0;
+
+          p.months.eq(currentIndex).addClass('picker-calendar-month-current');
+          p.months.eq(dir === 'next' ? currentIndex - 1 : currentIndex + 1).addClass(dir === 'next' ? 'picker-calendar-month-prev' : 'picker-calendar-month-next');
+
+          if (p.params.onMonthYearChangeStart) {
+              p.params.onMonthYearChangeStart(p, p.currentYear, p.currentMonth);
+          }
+      };
+      p.onMonthChangeEnd = function (dir, rebuildBoth) {
+          p.animating = false;
+          var nextMonthHTML, prevMonthHTML, newMonthHTML;
+          p.wrapper.find('.picker-calendar-month:not(.picker-calendar-month-prev):not(.picker-calendar-month-current):not(.picker-calendar-month-next)').remove();
+          
+          if (typeof dir === 'undefined') {
+              dir = 'next';
+              rebuildBoth = true;
+          }
+          if (!rebuildBoth) {
+              newMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), dir);
+          }
+          else {
+              p.wrapper.find('.picker-calendar-month-next, .picker-calendar-month-prev').remove();
+              prevMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'prev');
+              nextMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'next');
+          }
+          if (dir === 'next' || rebuildBoth) {
+              p.wrapper.append(newMonthHTML || nextMonthHTML);
+          }
+          if (dir === 'prev' || rebuildBoth) {
+              p.wrapper.prepend(newMonthHTML || prevMonthHTML);
+          }
+          p.months = p.wrapper.find('.picker-calendar-month');
+          p.setMonthsTranslate(p.monthsTranslate);
+          if (p.params.onMonthAdd) {
+              p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
+          }
+          if (p.params.onMonthYearChangeEnd) {
+              p.params.onMonthYearChangeEnd(p, p.currentYear, p.currentMonth);
+          }
+      };
+      p.setMonthsTranslate = function (translate) {
+          translate = translate || p.monthsTranslate || 0;
+          if (typeof p.monthsTranslate === 'undefined') p.monthsTranslate = translate;
+          p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
+          var prevMonthTranslate = -(translate + 1) * 100 * inverter;
+          var currentMonthTranslate = -translate * 100 * inverter;
+          var nextMonthTranslate = -(translate - 1) * 100 * inverter;
+          p.months.eq(0).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+          p.months.eq(1).transform('translate3d(' + (p.isH ? currentMonthTranslate : 0) + '%, ' + (p.isH ? 0 : currentMonthTranslate) + '%, 0)').addClass('picker-calendar-month-current');
+          p.months.eq(2).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+      };
+      p.nextMonth = function (transition) {
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var nextMonth = parseInt(p.months.eq(p.months.length - 1).attr('data-month'), 10);
+          var nextYear = parseInt(p.months.eq(p.months.length - 1).attr('data-year'), 10);
+          var nextDate = new Date(nextYear, nextMonth);
+          var nextDateTime = nextDate.getTime();
+          var transitionEndCallback = p.animating ? false : true;
+          if (p.params.maxDate) {
+              if (nextDateTime > new Date(p.params.maxDate).getTime()) {
+                  return p.resetMonth();
+              }
+          }
+          p.monthsTranslate --;
+          if (nextMonth === p.currentMonth) {
+              var nextMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
+              var nextMonthHTML = $(p.monthHTML(nextDateTime, 'next')).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+              p.wrapper.append(nextMonthHTML[0]);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              if (p.params.onMonthAdd) {
+                  p.params.onMonthAdd(p, p.months.eq(p.months.length - 1)[0]);
+              }
+          }
+          p.animating = true;
+          p.onMonthChangeStart('next');
+          var translate = (p.monthsTranslate * 100) * inverter;
+
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+          if (transitionEndCallback) {
+              p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd('next');
+              });
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd('next');
+          }
+      };
+      p.prevMonth = function (transition) {
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var prevMonth = parseInt(p.months.eq(0).attr('data-month'), 10);
+          var prevYear = parseInt(p.months.eq(0).attr('data-year'), 10);
+          var prevDate = new Date(prevYear, prevMonth + 1, -1);
+          var prevDateTime = prevDate.getTime();
+          var transitionEndCallback = p.animating ? false : true;
+          if (p.params.minDate) {
+              if (prevDateTime < new Date(p.params.minDate).getTime()) {
+                  return p.resetMonth();
+              }
+          }
+          p.monthsTranslate ++;
+          if (prevMonth === p.currentMonth) {
+              var prevMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
+              var prevMonthHTML = $(p.monthHTML(prevDateTime, 'prev')).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+              p.wrapper.prepend(prevMonthHTML[0]);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              if (p.params.onMonthAdd) {
+                  p.params.onMonthAdd(p, p.months.eq(0)[0]);
+              }
+          }
+          p.animating = true;
+          p.onMonthChangeStart('prev');
+          var translate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+          if (transitionEndCallback) {
+              p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd('prev');
+              });
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd('prev');
+          }
+      };
+      p.resetMonth = function (transition) {
+          if (typeof transition === 'undefined') transition = '';
+          var translate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+      };
+      p.setYearMonth = function (year, month, transition) {
+          if (typeof year === 'undefined') year = p.currentYear;
+          if (typeof month === 'undefined') month = p.currentMonth;
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var targetDate;
+          if (year < p.currentYear) {
+              targetDate = new Date(year, month + 1, -1).getTime();
+          }
+          else {
+              targetDate = new Date(year, month).getTime();
+          }
+          if (p.params.maxDate && targetDate > new Date(p.params.maxDate).getTime()) {
+              return false;
+          }
+          if (p.params.minDate && targetDate < new Date(p.params.minDate).getTime()) {
+              return false;
+          }
+          var currentDate = new Date(p.currentYear, p.currentMonth).getTime();
+          var dir = targetDate > currentDate ? 'next' : 'prev';
+          var newMonthHTML = p.monthHTML(new Date(year, month));
+          p.monthsTranslate = p.monthsTranslate || 0;
+          var prevTranslate = p.monthsTranslate;
+          var monthTranslate, wrapperTranslate;
+          var transitionEndCallback = p.animating ? false : true;
+          if (targetDate > currentDate) {
+              // To next
+              p.monthsTranslate --;
+              if (!p.animating) p.months.eq(p.months.length - 1).remove();
+              p.wrapper.append(newMonthHTML);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              monthTranslate = -(prevTranslate - 1) * 100 * inverter;
+              p.months.eq(p.months.length - 1).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+          }
+          else {
+              // To prev
+              p.monthsTranslate ++;
+              if (!p.animating) p.months.eq(0).remove();
+              p.wrapper.prepend(newMonthHTML);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              monthTranslate = -(prevTranslate + 1) * 100 * inverter;
+              p.months.eq(0).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+          }
+          if (p.params.onMonthAdd) {
+              p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
+          }
+          p.animating = true;
+          p.onMonthChangeStart(dir);
+          wrapperTranslate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? wrapperTranslate : 0) + '%, ' + (p.isH ? 0 : wrapperTranslate) + '%, 0)');
+          if (transitionEndCallback) {
+             p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd(dir, true);
+              }); 
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd(dir);
+          }
+      };
+      p.nextYear = function () {
+          p.setYearMonth(p.currentYear + 1);
+      };
+      p.prevYear = function () {
+          p.setYearMonth(p.currentYear - 1);
+      };
+      
+
+      // HTML Layout
+      p.layout = function () {
+          var pickerHTML = '';
+          var pickerClass = '';
+          var i;
+          
+          var layoutDate = p.value && p.value.length ? p.value[0] : new Date().setHours(0,0,0,0);
+          var prevMonthHTML = p.monthHTML(layoutDate, 'prev');
+          var currentMonthHTML = p.monthHTML(layoutDate);
+          var nextMonthHTML = p.monthHTML(layoutDate, 'next');
+          var monthsHTML = '<div class="picker-calendar-months"><div class="picker-calendar-months-wrapper">' + (prevMonthHTML + currentMonthHTML + nextMonthHTML) + '</div></div>';
+          // Week days header
+          var weekHeaderHTML = '';
+          if (p.params.weekHeader) {
+              for (i = 0; i < 7; i++) {
+                  var weekDayIndex = (i + p.params.firstDay > 6) ? (i - 7 + p.params.firstDay) : (i + p.params.firstDay);
+                  var dayName = p.params.dayNamesShort[weekDayIndex];
+                  weekHeaderHTML += '<div class="picker-calendar-week-day ' + ((p.params.weekendDays.indexOf(weekDayIndex) >= 0) ? 'picker-calendar-week-day-weekend' : '') + '"> ' + dayName + '</div>';
+                  
+              }
+              weekHeaderHTML = '<div class="picker-calendar-week-days">' + weekHeaderHTML + '</div>';
+          }
+          pickerClass = 'weui-picker-calendar ' + (p.params.cssClass || '');
+          if(!p.inline) pickerClass = 'weui-picker-modal ' + pickerClass;
+          var toolbarHTML = p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '';
+          if (p.params.toolbar) {
+              toolbarHTML = p.params.toolbarTemplate
+                  .replace(/{{closeText}}/g, p.params.toolbarCloseText)
+                  .replace(/{{monthPicker}}/g, (p.params.monthPicker ? p.params.monthPickerTemplate : ''))
+                  .replace(/{{yearPicker}}/g, (p.params.yearPicker ? p.params.yearPickerTemplate : ''));
+          }
+
+          pickerHTML =
+              '<div class="' + (pickerClass) + '">' +
+                  toolbarHTML +
+                  '<div class="picker-modal-inner">' +
+                      weekHeaderHTML +
+                      monthsHTML +
+                  '</div>' +
+              '</div>';
+              
+              
+          p.pickerHTML = pickerHTML;    
+      };
+
+      // Input Events
+      function openOnInput(e) {
+          e.preventDefault();
+          if (p.opened) return;
+          p.open();
+          if (p.params.scrollToInput && !isPopover()) {
+              var pageContent = p.input.parents('.page-content');
+              if (pageContent.length === 0) return;
+
+              var paddingTop = parseInt(pageContent.css('padding-top'), 10),
+                  paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
+                  pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
+                  pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
+                  newPaddingBottom;
+
+              var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
+              if (inputTop > pageHeight) {
+                  var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
+                  if (scrollTop + pageHeight > pageScrollHeight) {
+                      newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
+                      if (pageHeight === pageScrollHeight) {
+                          newPaddingBottom = p.container.height();
+                      }
+                      pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
+                  }
+                  pageContent.scrollTop(scrollTop, 300);
+              }
+          }
+      }
+      function closeOnHTMLClick(e) {
+          if (inPopover()) return;
+          if (p.input && p.input.length > 0) {
+              if (e.target !== p.input[0] && $(e.target).parents('.weui-picker-modal').length === 0) p.close();
+          }
+          else {
+              if ($(e.target).parents('.weui-picker-modal').length === 0) p.close();   
+          }
+      }
+
+      if (p.params.input) {
+          p.input = $(p.params.input);
+          if (p.input.length > 0) {
+              if (p.params.inputReadOnly) p.input.prop('readOnly', true);
+              if (!p.inline) {
+                  p.input.on('click', openOnInput);    
+              }
+              if (p.params.inputReadOnly) {
+                  p.input.on('focus mousedown', function (e) {
+                      e.preventDefault();
+                  });
+              }
+          }
+              
+      }
+      
+      //iphone 上无法正确触发 click,会导致点击外面无法关闭
+      if (!p.inline) $(document).on('click touchend', closeOnHTMLClick);
+
+      // Open
+      function onPickerClose() {
+          p.opened = false;
+          if (p.input && p.input.length > 0) p.input.parents('.page-content').css({'padding-bottom': ''});
+          if (p.params.onClose) p.params.onClose(p);
+
+          // Destroy events
+          p.destroyCalendarEvents();
+      }
+
+      p.opened = false;
+      p.open = function () {
+          var toPopover = isPopover() && false;
+          var updateValue = false;
+          if (!p.opened) {
+              // Set date value
+              if (!p.value) {
+                  if (p.params.value) {
+                      p.value = p.params.value;
+                      updateValue = true;
+                  }
+              }
+
+              // Layout
+              p.layout();
+
+              // Append
+              if (toPopover) {
+                  p.pickerHTML = '<div class="popover popover-picker-calendar"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
+                  p.popover = $.popover(p.pickerHTML, p.params.input, true);
+                  p.container = $(p.popover).find('.weui-picker-modal');
+                  $(p.popover).on('close', function () {
+                      onPickerClose();
+                  });
+              }
+              else if (p.inline) {
+                  p.container = $(p.pickerHTML);
+                  p.container.addClass('picker-modal-inline');
+                  $(p.params.container).append(p.container);
+              }
+              else {
+                  p.container = $($.openPicker(p.pickerHTML));
+                  $(p.container)
+                  .on('close', function () {
+                      onPickerClose();
+                  });
+              }
+
+              // Store calendar instance
+              p.container[0].f7Calendar = p;
+              p.wrapper = p.container.find('.picker-calendar-months-wrapper');
+
+              // Months
+              p.months = p.wrapper.find('.picker-calendar-month');
+
+              // Update current month and year
+              p.updateCurrentMonthYear();
+
+              // Set initial translate
+              p.monthsTranslate = 0;
+              p.setMonthsTranslate();
+
+              // Init events
+              p.initCalendarEvents();
+
+              // Update input value
+              if (updateValue) p.updateValue();
+              
+          }
+
+          // Set flag
+          p.opened = true;
+          p.initialized = true;
+          if (p.params.onMonthAdd) {
+              p.months.each(function () {
+                  p.params.onMonthAdd(p, this);
+              });
+          }
+          if (p.params.onOpen) p.params.onOpen(p);
+      };
+
+      // Close
+      p.close = function () {
+          if (!p.opened || p.inline) return;
+          p.animating = false;  //有可能还有动画没做完,因此animating设置还没改。
+          if (inPopover()) {
+              $.closePicker(p.popover);
+              return;
+          }
+          else {
+              $.closePicker(p.container);
+              return;
+          }
+      };
+
+      // Destroy
+      p.destroy = function () {
+          p.close();
+          if (p.params.input && p.input.length > 0) {
+              p.input.off('click focus', openOnInput);
+              p.input.data("calendar", null);
+          }
+          $('html').off('click', closeOnHTMLClick);
+      };
+
+      if (p.inline) {
+          p.open();
+      }
+
+      return p;
+  };
+
+  var format = function(d) {
+    return d < 10 ? "0"+d : d;
+  }
+
+
+  $.fn.calendar = function (params, args) {
+      params = params || {};
+      return this.each(function() {
+        var $this = $(this);
+        if(!$this[0]) return;
+        var p = {};
+        if($this[0].tagName.toUpperCase() === "INPUT") {
+          p.input = $this;
+        } else {
+          p.container = $this;
+        }
+
+        var calendar = $this.data("calendar");
+
+        if(!calendar) {
+          if(typeof params === typeof "a") {
+          } else {
+            if(!params.value && $this.val()) params.value = [$this.val()];
+            //默认显示今天
+            if(!params.value) {
+              var today = new Date();
+              params.value = [today.getFullYear() + "/" + format(today.getMonth() + 1) + "/" + format(today.getDate())];
+            }
+            calendar = $this.data("calendar", new Calendar($.extend(p, params)));
+          }
+        }
+
+        if(typeof params === typeof "a") {
+          calendar[params].call(calendar, args);
+        }
+      });
+  };
+
+  defaults = $.fn.calendar.prototype.defaults = {
+    value: undefined, // 通过JS赋值,注意是数组
+    monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    dayNames: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    dayNamesShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    firstDay: 1, // First day of the week, Monday
+    weekendDays: [0, 6], // Sunday and Saturday
+    multiple: false,
+    dateFormat: 'yyyy/mm/dd',
+    direction: 'horizontal', // or 'vertical'
+    minDate: null,
+    maxDate: null,
+    touchMove: true,
+    animate: true,
+    closeOnSelect: true,
+    monthPicker: true,
+    monthPickerTemplate: 
+        '<div class="picker-calendar-month-picker">' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-prev-month"><i class="icon icon-prev"></i></a>' +
+            '<div class="current-month-value"></div>' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-next-month"><i class="icon icon-next"></i></a>' +
+        '</div>',
+    yearPicker: true,
+    yearPickerTemplate: 
+        '<div class="picker-calendar-year-picker">' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-prev-year"><i class="icon icon-prev"></i></a>' +
+            '<span class="current-year-value"></span>' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-next-year"><i class="icon icon-next"></i></a>' +
+        '</div>',
+    weekHeader: true,
+    // Common settings
+    scrollToInput: true,
+    inputReadOnly: true,
+    convertToPopover: true,
+    onlyInPopover: false,
+    toolbar: true,
+    toolbarCloseText: 'Done',
+    toolbarTemplate: 
+        '<div class="toolbar">' +
+            '<div class="toolbar-inner">' +
+                '{{yearPicker}}' +
+                '{{monthPicker}}' +
+                // '<a href="#" class="link close-picker">{{closeText}}</a>' +
+            '</div>' +
+        '</div>',
+    /* Callbacks
+    onMonthAdd
+    onChange
+    onOpen
+    onClose
+    onDayClick
+    onMonthYearChangeStart
+    onMonthYearChangeEnd
+    */
+  };
+
+}($);
+
+/* global $:true */
+/* jshint unused:false*/
+
++ function($) {
+  "use strict";
+
+
+  var defaults;
+
+  var formatNumber = function (n) {
+    return n < 10 ? "0" + n : n;
+  }
+
+  var Datetime = function(input, params) {
+    this.input = $(input);
+    this.params = params || {};
+
+    this.initMonthes = params.monthes
+
+    this.initYears = params.years
+
+    var p = $.extend({}, params, this.getConfig());
+    $(this.input).picker(p);
+  }
+
+  Datetime.prototype = {
+    getDays : function(max) {
+      var days = [];
+      for(var i=1; i<= (max||31);i++) {
+        days.push(i < 10 ? "0"+i : i);
+      }
+      return days;
+    },
+
+    getDaysByMonthAndYear : function(month, year) {
+      var int_d = new Date(year, parseInt(month)+1-1, 1);
+      var d = new Date(int_d - 1);
+      return this.getDays(d.getDate());
+    },
+    getConfig: function() {
+      var today = new Date(),
+          params = this.params,
+          self = this,
+          lastValidValues;
+
+      var config = {
+        rotateEffect: false,  //为了性能
+        cssClass: 'datetime-picker',
+
+        value: [today.getFullYear(), formatNumber(today.getMonth()+1), formatNumber(today.getDate()), formatNumber(today.getHours()), (formatNumber(today.getMinutes()))],
+
+        onChange: function (picker, values, displayValues) {
+          var cols = picker.cols;
+          var days = self.getDaysByMonthAndYear(values[1], values[0]);
+          var currentValue = values[2];
+          if(currentValue > days.length) currentValue = days.length;
+          picker.cols[4].setValue(currentValue);
+
+          //check min and max
+          var current = new Date(values[0]+'-'+values[1]+'-'+values[2]);
+          var valid = true;
+          if(params.min) {
+            var min = new Date(typeof params.min === "function" ? params.min() : params.min);
+
+            if(current < +min) {
+              picker.setValue(lastValidValues);
+              valid = false;
+            } 
+          }
+          if(params.max) {
+            var max = new Date(typeof params.max === "function" ? params.max() : params.max);
+            if(current > +max) {
+              picker.setValue(lastValidValues);
+              valid = false;
+            }
+          }
+
+          valid && (lastValidValues = values);
+
+          if (self.params.onChange) {
+            self.params.onChange.apply(this, arguments);
+          }
+        },
+
+        formatValue: function (p, values, displayValues) {
+          return self.params.format(p, values, displayValues);
+        },
+
+        cols: [
+          {
+            values: this.initYears
+          },
+          {
+            divider: true,  // 这是一个分隔符
+            content: params.yearSplit
+          },
+          {
+            values: this.initMonthes
+          },
+          {
+            divider: true,  // 这是一个分隔符
+            content: params.monthSplit
+          },
+          {
+            values: (function () {
+              var dates = [];
+              for (var i=1; i<=31; i++) dates.push(formatNumber(i));
+              return dates;
+            })()
+          },
+          
+        ]
+      }
+
+      if (params.dateSplit) {
+        config.cols.push({
+          divider: true,
+          content: params.dateSplit
+        })
+      }
+
+      config.cols.push({
+        divider: true,
+        content: params.datetimeSplit
+      })
+
+      var times = self.params.times();
+      if (times && times.length) {
+        config.cols = config.cols.concat(times);
+      }
+
+      var inputValue = this.input.val();
+      if(inputValue) config.value = params.parse(inputValue);
+      if(this.params.value) {
+        this.input.val(this.params.value);
+        config.value = params.parse(this.params.value);
+      }
+
+      return config;
+    }
+  }
+
+  $.fn.datetimePicker = function(params) {
+    params = $.extend({}, defaults, params);
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      var datetime = $this.data("datetime");
+      if(!datetime) $this.data("datetime", new Datetime(this, params));
+      return datetime;
+    });
+  };
+
+  defaults = $.fn.datetimePicker.prototype.defaults = {
+    input: undefined, // 默认值
+    min: undefined, // YYYY-MM-DD 最大最小值只比较年月日,不比较时分秒
+    max: undefined,  // YYYY-MM-DD
+    yearSplit: '-',
+    monthSplit: '-',
+    dateSplit: '',  // 默认为空
+    datetimeSplit: ' ',  // 日期和时间之间的分隔符,不可为空
+    monthes: ('01 02 03 04 05 06 07 08 09 10 11 12').split(' '),
+    years: (function () {
+      var arr = [];
+      for (var i = 1950; i <= 2030; i++) { arr.push(i); }
+      return arr;
+    })(),
+    times: function () {
+      return [  // 自定义的时间
+        {
+          values: (function () {
+            var hours = [];
+            for (var i=0; i<24; i++) hours.push(formatNumber(i));
+            return hours;
+          })()
+        },
+        {
+          divider: true,  // 这是一个分隔符
+          content: ':'
+        },
+        {
+          values: (function () {
+            var minutes = [];
+            for (var i=0; i<60; i++) minutes.push(formatNumber(i));
+            return minutes;
+          })()
+        }
+      ];
+    },
+    format: function (p, values) { // 数组转换成字符串
+      return p.cols.map(function (col) {
+        return col.value || col.content;
+      }).join('');
+    },
+    parse: function (str) {
+      // 把字符串转换成数组,用来解析初始值
+      // 如果你的定制的初始值格式无法被这个默认函数解析,请自定义这个函数。比如你的时间是 '子时' 那么默认情况这个'时'会被当做分隔符而导致错误,所以你需要自己定义parse函数
+      // 默认兼容的分隔符
+      var t = str.split(this.datetimeSplit);
+      return t[0].split(/\D/).concat(t[1].split(/:|时|分|秒/)).filter(function (d) {
+        return !!d;
+      })
+    }
+  }
+
+}($);
+
+/*======================================================
+************   Picker   ************
+======================================================*/
+/* global $:true */
+
++ function($) {
+  "use strict";
+
+
+  //Popup 和 picker 之类的不要共用一个弹出方法,因为这样会导致 在 popup 中再弹出 picker 的时候会有问题。
+
+  $.openPopup = function(popup, className) {
+
+    $.closePopup();
+
+    popup = $(popup);
+    popup.show();
+    popup.width();
+    popup.addClass("weui-popup__container--visible");
+    var modal = popup.find(".weui-popup__modal");
+    modal.width();
+    modal.transitionEnd(function() {
+      modal.trigger("open");
+    });
+  }
+
+
+  $.closePopup = function(container, remove) {
+    container = $(container || ".weui-popup__container--visible");
+    container.find('.weui-popup__modal').transitionEnd(function() {
+      var $this = $(this);
+      $this.trigger("close");
+      container.hide();
+      remove && container.remove();
+    })
+    container.removeClass("weui-popup__container--visible")
+  };
+
+
+  $(document).on("click", ".close-popup, .weui-popup__overlay", function() {
+    $.closePopup();
+  })
+  .on("click", ".open-popup", function() {
+    $($(this).data("target")).popup();
+  })
+  .on("click", ".weui-popup__container", function(e) {
+    if($(e.target).hasClass("weui-popup__container")) $.closePopup();
+  })
+
+  $.fn.popup = function() {
+    return this.each(function() {
+      $.openPopup(this);
+    });
+  };
+
+}($);
+
+/* ===============================================================================
+************   Notification ************
+=============================================================================== */
+/* global $:true */
++function ($) {
+  "use strict";
+
+  var noti, defaults, timeout, start, diffX, diffY;
+
+  var touchStart = function(e) {
+    var p = $.getTouchPosition(e);
+    start = p;
+    diffX = diffY = 0;
+    noti.addClass("touching");
+  };
+  var touchMove = function(e) {
+    if(!start) return false;
+    e.preventDefault();
+    e.stopPropagation();
+    var p = $.getTouchPosition(e);
+    diffX = p.x - start.x;
+    diffY = p.y - start.y;
+    if(diffY > 0) {
+      diffY = Math.sqrt(diffY);
+    }
+
+    noti.css("transform", "translate3d(0, "+diffY+"px, 0)");
+  };
+  var touchEnd = function() {
+    noti.removeClass("touching");
+    noti.attr("style", "");
+    if(diffY < 0 && (Math.abs(diffY) > noti.height()*0.38)) {
+      $.closeNotification();
+    }
+
+    if(Math.abs(diffX) <= 1 && Math.abs(diffY) <= 1) {
+      noti.trigger("noti-click");
+    }
+
+    start = false;
+  };
+
+  var attachEvents = function(el) {
+    el.on($.touchEvents.start, touchStart);
+    el.on($.touchEvents.move, touchMove);
+    el.on($.touchEvents.end, touchEnd);
+  };
+
+  $.notification = $.noti = function(params) {
+    params = $.extend({}, defaults, params);
+    noti = $(".weui-notification");
+    if(!noti[0]) { // create a new notification
+      noti = $('<div class="weui-notification"></div>').appendTo(document.body);
+      attachEvents(noti);
+    }
+
+    noti.off("noti-click"); //the click event is not correct sometime: it will trigger when user is draging.
+    if(params.onClick) noti.on("noti-click", function() {
+      params.onClick(params.data);
+    });
+
+    noti.html($.t7.compile(params.tpl)(params));
+
+    noti.show();
+
+    noti.addClass("weui-notification--in");
+    noti.data("params", params);
+
+    var startTimeout = function() {
+      if(timeout) {
+        clearTimeout(timeout);
+        timeout = null;
+      }
+
+      timeout = setTimeout(function() {
+        if(noti.hasClass("weui-notification--touching")) {
+          startTimeout();
+        } else {
+          $.closeNotification();
+        }
+      }, params.time);
+    };
+
+    startTimeout();
+
+  };
+
+  $.closeNotification = function() {
+    timeout && clearTimeout(timeout);
+    timeout = null;
+    var noti = $(".weui-notification").removeClass("weui-notification--in").transitionEnd(function() {
+      $(this).remove();
+    });
+
+    if(noti[0]) {
+      var params = $(".weui-notification").data("params");
+      if(params && params.onClose) {
+        params.onClose(params.data);
+      }
+    }
+  };
+
+  defaults = $.noti.prototype.defaults = {
+    title: undefined,
+    text: undefined,
+    media: undefined,
+    time: 4000,
+    onClick: undefined,
+    onClose: undefined,
+    data: undefined,
+    tpl:  '<div class="weui-notification__inner">' +
+            '{{#if media}}<div class="weui-notification__media">{{media}}</div>{{/if}}' +
+            '<div class="weui-notification__content">' +
+            '{{#if title}}<div class="weui-notification__title">{{title}}</div>{{/if}}' +
+            '{{#if text}}<div class="weui-notification__text">{{text}}</div>{{/if}}' +
+            '</div>' +
+            '<div class="weui-notification__handle-bar"></div>' +
+          '</div>'
+  };
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var timeout;
+
+  $.toptip = function(text, duration, type) {
+    if(!text) return;
+    if(typeof duration === typeof "a") {
+      type = duration;
+      duration = undefined;
+    }
+    duration = duration || 3000;
+    var className = type ? 'bg-' + type : 'bg-danger';
+    var $t = $('.weui-toptips').remove();
+    $t = $('<div class="weui-toptips"></div>').appendTo(document.body);
+    $t.html(text);
+    $t[0].className = 'weui-toptips ' + className
+
+    clearTimeout(timeout);
+
+    if(!$t.hasClass('weui-toptips_visible')) {
+      $t.show().width();
+      $t.addClass('weui-toptips_visible');
+    }
+
+    timeout = setTimeout(function() {
+      $t.removeClass('weui-toptips_visible').transitionEnd(function() {
+        $t.remove();
+      });
+    }, duration);
+  }
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+  var Slider = function (container, arg) {
+    this.container = $(container);
+    this.handler = this.container.find('.weui-slider__handler')
+    this.track = this.container.find('.weui-slider__track')
+    this.value = this.container.find('.weui-slider-box__value')
+    this.bind()
+    if (typeof arg === 'function') {
+      this.callback = arg
+    }
+  }
+
+  Slider.prototype.bind = function () {
+    this.container
+      .on($.touchEvents.start, $.proxy(this.touchStart, this))
+      .on($.touchEvents.end, $.proxy(this.touchEnd, this));
+    $(document.body).on($.touchEvents.move, $.proxy(this.touchMove, this)) // move even outside container
+  }
+
+  Slider.prototype.touchStart = function (e) {
+    e.preventDefault()
+    this.start = $.getTouchPosition(e)
+    this.width = this.container.find('.weui-slider__inner').width()
+    this.left = parseInt(this.container.find('.weui-slider__handler').css('left'))
+    this.touching = true
+  }
+
+  Slider.prototype.touchMove = function (e) {
+    if (!this.touching) return true
+    var p = $.getTouchPosition(e)
+    var distance = p.x - this.start.x
+    var left = distance + this.left
+    var per = parseInt(left / this.width * 100)
+    if (per < 0) per = 0
+    if (per > 100) per = 100
+    this.handler.css('left', per + '%')
+    this.track.css('width', per + '%')
+    this.value.text(per)
+    this.callback && this.callback.call(this, per)
+    this.container.trigger('change', per)
+  }
+
+  Slider.prototype.touchEnd = function (e) {
+    this.touching = false
+  }
+
+  $.fn.slider = function (arg) {
+    this.each(function () {
+      var $this = $(this)
+      var slider = $this.data('slider')
+      if (slider) return slider;
+      else $this.data('slider', new Slider(this, arg))
+    })
+  }
+}($);
+
+/* ===============================================================================
+************   Swipeout ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var cache = [];
+  var TOUCHING = 'swipeout-touching'
+
+  var Swipeout = function(el) {
+    this.container = $(el);
+    this.mover = this.container.find('>.weui-cell__bd')
+    this.attachEvents();
+    cache.push(this)
+  }
+
+  Swipeout.prototype.touchStart = function(e) {
+    var p = $.getTouchPosition(e);
+    this.container.addClass(TOUCHING);
+    this.start = p;
+    this.startX = 0;
+    this.startTime = + new Date;
+    var transform =  this.mover.css('transform').match(/-?[\d\.]+/g)
+    if (transform && transform.length) this.startX = parseInt(transform[4])
+    this.diffX = this.diffY = 0;
+    this._closeOthers()
+    this.limit = this.container.find('>.weui-cell__ft').width() || 68; // 因为有的时候初始化的时候元素是隐藏的(比如在对话框内),所以在touchstart的时候计算宽度而不是初始化的时候
+  };
+
+  Swipeout.prototype.touchMove= function(e) {
+    if(!this.start) return true;
+    var p = $.getTouchPosition(e);
+    this.diffX = p.x - this.start.x;
+    this.diffY = p.y - this.start.y;
+    if (Math.abs(this.diffX) < Math.abs(this.diffY)) { // 说明是上下方向在拖动
+      this.close()
+      this.start = false
+      return true;
+    }
+    e.preventDefault();
+    e.stopPropagation();
+    var x = this.diffX + this.startX
+    if (x > 0) x = 0;
+    if (Math.abs(x) > this.limit) x = - (Math.pow(-(x+this.limit), .7) + this.limit)
+    this.mover.css("transform", "translate3d("+x+"px, 0, 0)");
+  };
+  Swipeout.prototype.touchEnd = function() {
+    if (!this.start) return true;
+    this.start = false;
+    var x = this.diffX + this.startX
+    var t = new Date - this.startTime;
+    if (this.diffX < -5 && t < 200) { // 向左快速滑动,则打开
+      this.open()
+    } else if (this.diffX >= 0 && t < 200) { // 向右快速滑动,或者单击,则关闭
+      this.close()
+    } else if (x > 0 || -x <= this.limit / 2) {
+      this.close()
+    } else {
+      this.open()
+    }
+  };
+
+
+  Swipeout.prototype.close = function() {
+    this.container.removeClass(TOUCHING);
+    this.mover.css("transform", "translate3d(0, 0, 0)");
+    this.container.trigger('swipeout-close');
+  }
+
+  Swipeout.prototype.open = function() {
+    this.container.removeClass(TOUCHING);
+    this._closeOthers()
+    this.mover.css("transform", "translate3d(" + (-this.limit) + "px, 0, 0)");
+    this.container.trigger('swipeout-open');
+  }
+
+  Swipeout.prototype.attachEvents = function() {
+    var el = this.mover;
+    el.on($.touchEvents.start, $.proxy(this.touchStart, this));
+    el.on($.touchEvents.move, $.proxy(this.touchMove, this));
+    el.on($.touchEvents.end, $.proxy(this.touchEnd, this));
+  }
+  Swipeout.prototype._closeOthers = function() {
+    //close others
+    var self = this
+    cache.forEach(function (s) {
+      if (s !== self) s.close()
+    })
+  }
+
+  var swipeout = function(el) {
+    return new Swipeout(el);
+  };
+
+  $.fn.swipeout = function (arg) {
+    return this.each(function() {
+      var $this = $(this)
+      var s = $this.data('swipeout') || swipeout(this);
+      $this.data('swipeout', s);
+
+      if (typeof arg === typeof 'a') {
+        s[arg]()
+      }
+    });
+  }
+
+  $('.weui-cell_swiped').swipeout() // auto init
+}($);
diff --git a/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.min.js b/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.min.js
new file mode 100755
index 0000000..28951e8
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/jquery-weui.min.js
@@ -0,0 +1,13 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+!function(t){"use strict";t.fn.transitionEnd=function(t){function e(r){if(r.target===this)for(t.call(this,r),n=0;n<i.length;n++)a.off(i[n],e)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],a=this;if(t)for(n=0;n<i.length;n++)a.on(i[n],e);return this},t.support=function(){var t={touch:!!("ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch)};return t}(),t.touchEvents={start:t.support.touch?"touchstart":"mousedown",move:t.support.touch?"touchmove":"mousemove",end:t.support.touch?"touchend":"mouseup"},t.getTouchPosition=function(t){return t=t.originalEvent||t,"touchstart"===t.type||"touchmove"===t.type||"touchend"===t.type?{x:t.targetTouches[0].pageX,y:t.targetTouches[0].pageY}:{x:t.pageX,y:t.pageY}},t.fn.scrollHeight=function(){return this[0].scrollHeight},t.fn.transform=function(t){for(var e=0;e<this.length;e++){var n=this[e].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=t}return this},t.fn.transition=function(t){"string"!=typeof t&&(t+="ms");for(var e=0;e<this.length;e++){var n=this[e].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=t}return this},t.getTranslate=function(t,e){var n,i,a,r;return"undefined"==typeof e&&(e="x"),a=window.getComputedStyle(t,null),window.WebKitCSSMatrix?r=new WebKitCSSMatrix("none"===a.webkitTransform?"":a.webkitTransform):(r=a.MozTransform||a.OTransform||a.MsTransform||a.msTransform||a.transform||a.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),n=r.toString().split(",")),"x"===e&&(i=window.WebKitCSSMatrix?r.m41:16===n.length?parseFloat(n[12]):parseFloat(n[4])),"y"===e&&(i=window.WebKitCSSMatrix?r.m42:16===n.length?parseFloat(n[13]):parseFloat(n[5])),i||0},t.requestAnimationFrame=function(t){return window.requestAnimationFrame?window.requestAnimationFrame(t):window.webkitRequestAnimationFrame?window.webkitRequestAnimationFrame(t):window.mozRequestAnimationFrame?window.mozRequestAnimationFrame(t):window.setTimeout(t,1e3/60)},t.cancelAnimationFrame=function(t){return window.cancelAnimationFrame?window.cancelAnimationFrame(t):window.webkitCancelAnimationFrame?window.webkitCancelAnimationFrame(t):window.mozCancelAnimationFrame?window.mozCancelAnimationFrame(t):window.clearTimeout(t)},t.fn.join=function(t){return this.toArray().join(t)}}($),+function(t){"use strict";t.Template7=t.t7=function(){function t(t){return"[object Array]"===Object.prototype.toString.apply(t)}function e(t){return"function"==typeof t}function n(t){var e,n,i,a=t.replace(/[{}#}]/g,"").split(" "),r=[];for(n=0;n<a.length;n++){var o=a[n];if(0===n)r.push(o);else if(0===o.indexOf('"'))if(2===o.match(/"/g).length)r.push(o);else{for(e=0,i=n+1;i<a.length;i++)if(o+=" "+a[i],a[i].indexOf('"')>=0){e=i,r.push(o);break}e&&(n=e)}else if(o.indexOf("=")>0){var s=o.split("="),c=s[0],l=s[1];if(2!==l.match(/"/g).length){for(e=0,i=n+1;i<a.length;i++)if(l+=" "+a[i],a[i].indexOf('"')>=0){e=i;break}e&&(n=e)}var u=[c,l.replace(/"/g,"")];r.push(u)}else r.push(o)}return r}function i(e){var i,a,r=[];if(!e)return[];var o=e.split(/({{[^{^}]*}})/);for(i=0;i<o.length;i++){var s=o[i];if(""!==s)if(s.indexOf("{{")<0)r.push({type:"plain",content:s});else{if(s.indexOf("{/")>=0)continue;if(s.indexOf("{#")<0&&s.indexOf(" ")<0&&s.indexOf("else")<0){r.push({type:"variable",contextName:s.replace(/[{}]/g,"")});continue}var c=n(s),l=c[0],u=[],p={};for(a=1;a<c.length;a++){var h=c[a];t(h)?p[h[0]]="false"!==h[1]&&h[1]:u.push(h)}if(s.indexOf("{#")>=0){var d,f="",m="",v=0,g=!1,w=!1,y=0;for(a=i+1;a<o.length;a++)if(o[a].indexOf("{{#")>=0&&y++,o[a].indexOf("{{/")>=0&&y--,o[a].indexOf("{{#"+l)>=0)f+=o[a],w&&(m+=o[a]),v++;else if(o[a].indexOf("{{/"+l)>=0){if(!(v>0)){d=a,g=!0;break}v--,f+=o[a],w&&(m+=o[a])}else o[a].indexOf("else")>=0&&0===y?w=!0:(w||(f+=o[a]),w&&(m+=o[a]));g&&(d&&(i=d),r.push({type:"helper",helperName:l,contextName:u,content:f,inverseContent:m,hash:p}))}else s.indexOf(" ")>0&&r.push({type:"helper",helperName:l,contextName:u,hash:p})}}return r}var a=function(t){function e(t,e){return t.content?o(t.content,e):function(){return""}}function n(t,e){return t.inverseContent?o(t.inverseContent,e):function(){return""}}function a(t,e){var n,i,a=0;if(0===t.indexOf("../")){a=t.split("../").length-1;var r=e.split("_")[1]-a;e="ctx_"+(r>=1?r:1),i=t.split("../")[a].split(".")}else 0===t.indexOf("@global")?(e="$.Template7.global",i=t.split("@global.")[1].split(".")):0===t.indexOf("@root")?(e="ctx_1",i=t.split("@root.")[1].split(".")):i=t.split(".");n=e;for(var o=0;o<i.length;o++){var s=i[o];0===s.indexOf("@")?o>0?n+="[(data && data."+s.replace("@","")+")]":n="(data && data."+t.replace("@","")+")":isFinite(s)?n+="["+s+"]":0===s.indexOf("this")?n=s.replace("this",e):n+="."+s}return n}function r(t,e){for(var n=[],i=0;i<t.length;i++)0===t[i].indexOf('"')?n.push(t[i]):n.push(a(t[i],e));return n.join(", ")}function o(t,o){if(o=o||1,t=t||s.template,"string"!=typeof t)throw new Error("Template7: Template must be a string");var c=i(t);if(0===c.length)return function(){return""};var l="ctx_"+o,u="(function ("+l+", data) {\n";1===o&&(u+="function isArray(arr){return Object.prototype.toString.apply(arr) === '[object Array]';}\n",u+="function isFunction(func){return (typeof func === 'function');}\n",u+='function c(val, ctx) {if (typeof val !== "undefined") {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n'),u+="var r = '';\n";var p;for(p=0;p<c.length;p++){var h=c[p];if("plain"!==h.type){var d,f;if("variable"===h.type&&(d=a(h.contextName,l),u+="r += c("+d+", "+l+");"),"helper"===h.type)if(h.helperName in s.helpers)f=r(h.contextName,l),u+="r += ($.Template7.helpers."+h.helperName+").call("+l+", "+(f&&f+", ")+"{hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});";else{if(h.contextName.length>0)throw new Error('Template7: Missing helper: "'+h.helperName+'"');d=a(h.helperName,l),u+="if ("+d+") {",u+="if (isArray("+d+")) {",u+="r += ($.Template7.helpers.each).call("+l+", "+d+", {hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});",u+="}else {",u+="r += ($.Template7.helpers.with).call("+l+", "+d+", {hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});",u+="}}"}}else u+="r +='"+h.content.replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/'/g,"\\'")+"';"}return u+="\nreturn r;})",eval.call(window,u)}var s=this;s.template=t,s.compile=function(t){return s.compiled||(s.compiled=o(t)),s.compiled}};a.prototype={options:{},helpers:{"if":function(t,n){return e(t)&&(t=t.call(this)),t?n.fn(this,n.data):n.inverse(this,n.data)},unless:function(t,n){return e(t)&&(t=t.call(this)),t?n.inverse(this,n.data):n.fn(this,n.data)},each:function(n,i){var a="",r=0;if(e(n)&&(n=n.call(this)),t(n)){for(i.hash.reverse&&(n=n.reverse()),r=0;r<n.length;r++)a+=i.fn(n[r],{first:0===r,last:r===n.length-1,index:r});i.hash.reverse&&(n=n.reverse())}else for(var o in n)r++,a+=i.fn(n[o],{key:o});return r>0?a:i.inverse(this)},"with":function(t,n){return e(t)&&(t=t.call(this)),n.fn(t)},join:function(t,n){return e(t)&&(t=t.call(this)),t.join(n.hash.delimiter||n.hash.delimeter)},js:function(t,e){var n;return n=t.indexOf("return")>=0?"(function(){"+t+"})":"(function(){return ("+t+")})",eval.call(this,n).call(this)},js_compare:function(t,e){var n;n=t.indexOf("return")>=0?"(function(){"+t+"})":"(function(){return ("+t+")})";var i=eval.call(this,n).call(this);return i?e.fn(this,e.data):e.inverse(this,e.data)}}};var r=function(t,e){if(2===arguments.length){var n=new a(t),i=n.compile()(e);return n=null,i}return new a(t)};return r.registerHelper=function(t,e){a.prototype.helpers[t]=e},r.unregisterHelper=function(t){a.prototype.helpers[t]=void 0,delete a.prototype.helpers[t]},r.compile=function(t,e){var n=new a(t,e);return n.compile()},r.options=a.prototype.options,r.helpers=a.prototype.helpers,r}()}($),/*! Hammer.JS - v2.0.8 - 2016-04-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the MIT license */
+function(t,e,n,i){"use strict";function a(t,e,n){return setTimeout(l(t,n),e)}function r(t,e,n){return!!Array.isArray(t)&&(o(t,n[e],n),!0)}function o(t,e,n){var a;if(t)if(t.forEach)t.forEach(e,n);else if(t.length!==i)for(a=0;a<t.length;)e.call(n,t[a],a,t),a++;else for(a in t)t.hasOwnProperty(a)&&e.call(n,t[a],a,t)}function s(e,n,i){var a="DEPRECATED METHOD: "+n+"\n"+i+" AT \n";return function(){var n=new Error("get-stack-trace"),i=n&&n.stack?n.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",r=t.console&&(t.console.warn||t.console.log);return r&&r.call(t.console,a,i),e.apply(this,arguments)}}function c(t,e,n){var i,a=e.prototype;i=t.prototype=Object.create(a),i.constructor=t,i._super=a,n&&pt(i,n)}function l(t,e){return function(){return t.apply(e,arguments)}}function u(t,e){return typeof t==ft?t.apply(e?e[0]||i:i,e):t}function p(t,e){return t===i?e:t}function h(t,e,n){o(v(e),function(e){t.addEventListener(e,n,!1)})}function d(t,e,n){o(v(e),function(e){t.removeEventListener(e,n,!1)})}function f(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1}function m(t,e){return t.indexOf(e)>-1}function v(t){return t.trim().split(/\s+/g)}function g(t,e,n){if(t.indexOf&&!n)return t.indexOf(e);for(var i=0;i<t.length;){if(n&&t[i][n]==e||!n&&t[i]===e)return i;i++}return-1}function w(t){return Array.prototype.slice.call(t,0)}function y(t,e,n){for(var i=[],a=[],r=0;r<t.length;){var o=e?t[r][e]:t[r];g(a,o)<0&&i.push(t[r]),a[r]=o,r++}return n&&(i=e?i.sort(function(t,n){return t[e]>n[e]}):i.sort()),i}function T(t,e){for(var n,a,r=e[0].toUpperCase()+e.slice(1),o=0;o<ht.length;){if(n=ht[o],a=n?n+r:e,a in t)return a;o++}return i}function k(){return Tt++}function x(e){var n=e.ownerDocument||e;return n.defaultView||n.parentWindow||t}function C(t,e){var n=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){u(t.options.enable,[t])&&n.handler(e)},this.init()}function b(t){var e,n=t.options.inputClass;return new(e=n?n:Ct?F:bt?z:xt?j:N)(t,M)}function M(t,e,n){var i=n.pointers.length,a=n.changedPointers.length,r=e&Ot&&i-a===0,o=e&(It|Ht)&&i-a===0;n.isFirst=!!r,n.isFinal=!!o,r&&(t.session={}),n.eventType=e,_(t,n),t.emit("hammer.input",n),t.recognize(n),t.session.prevInput=n}function _(t,e){var n=t.session,i=e.pointers,a=i.length;n.firstInput||(n.firstInput=P(e)),a>1&&!n.firstMultiple?n.firstMultiple=P(e):1===a&&(n.firstMultiple=!1);var r=n.firstInput,o=n.firstMultiple,s=o?o.center:r.center,c=e.center=O(i);e.timeStamp=gt(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=S(s,c),e.distance=H(s,c),E(n,e),e.offsetDirection=I(e.deltaX,e.deltaY);var l=A(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=l.x,e.overallVelocityY=l.y,e.overallVelocity=vt(l.x)>vt(l.y)?l.x:l.y,e.scale=o?V(o.pointers,i):1,e.rotation=o?Y(o.pointers,i):0,e.maxPointers=n.prevInput?e.pointers.length>n.prevInput.maxPointers?e.pointers.length:n.prevInput.maxPointers:e.pointers.length,D(n,e);var u=t.element;f(e.srcEvent.target,u)&&(u=e.srcEvent.target),e.target=u}function E(t,e){var n=e.center,i=t.offsetDelta||{},a=t.prevDelta||{},r=t.prevInput||{};e.eventType!==Ot&&r.eventType!==It||(a=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},i=t.offsetDelta={x:n.x,y:n.y}),e.deltaX=a.x+(n.x-i.x),e.deltaY=a.y+(n.y-i.y)}function D(t,e){var n,a,r,o,s=t.lastInterval||e,c=e.timeStamp-s.timeStamp;if(e.eventType!=Ht&&(c>Pt||s.velocity===i)){var l=e.deltaX-s.deltaX,u=e.deltaY-s.deltaY,p=A(c,l,u);a=p.x,r=p.y,n=vt(p.x)>vt(p.y)?p.x:p.y,o=I(l,u),t.lastInterval=e}else n=s.velocity,a=s.velocityX,r=s.velocityY,o=s.direction;e.velocity=n,e.velocityX=a,e.velocityY=r,e.direction=o}function P(t){for(var e=[],n=0;n<t.pointers.length;)e[n]={clientX:mt(t.pointers[n].clientX),clientY:mt(t.pointers[n].clientY)},n++;return{timeStamp:gt(),pointers:e,center:O(e),deltaX:t.deltaX,deltaY:t.deltaY}}function O(t){var e=t.length;if(1===e)return{x:mt(t[0].clientX),y:mt(t[0].clientY)};for(var n=0,i=0,a=0;a<e;)n+=t[a].clientX,i+=t[a].clientY,a++;return{x:mt(n/e),y:mt(i/e)}}function A(t,e,n){return{x:e/t||0,y:n/t||0}}function I(t,e){return t===e?St:vt(t)>=vt(e)?t<0?Yt:Vt:e<0?Nt:Ft}function H(t,e,n){n||(n=Lt);var i=e[n[0]]-t[n[0]],a=e[n[1]]-t[n[1]];return Math.sqrt(i*i+a*a)}function S(t,e,n){n||(n=Lt);var i=e[n[0]]-t[n[0]],a=e[n[1]]-t[n[1]];return 180*Math.atan2(a,i)/Math.PI}function Y(t,e){return S(e[1],e[0],jt)+S(t[1],t[0],jt)}function V(t,e){return H(e[0],e[1],jt)/H(t[0],t[1],jt)}function N(){this.evEl=$t,this.evWin=Wt,this.pressed=!1,C.apply(this,arguments)}function F(){this.evEl=Bt,this.evWin=Gt,C.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function R(){this.evTarget=Zt,this.evWin=Qt,this.started=!1,C.apply(this,arguments)}function q(t,e){var n=w(t.touches),i=w(t.changedTouches);return e&(It|Ht)&&(n=y(n.concat(i),"identifier",!0)),[n,i]}function z(){this.evTarget=ee,this.targetIds={},C.apply(this,arguments)}function L(t,e){var n=w(t.touches),i=this.targetIds;if(e&(Ot|At)&&1===n.length)return i[n[0].identifier]=!0,[n,n];var a,r,o=w(t.changedTouches),s=[],c=this.target;if(r=n.filter(function(t){return f(t.target,c)}),e===Ot)for(a=0;a<r.length;)i[r[a].identifier]=!0,a++;for(a=0;a<o.length;)i[o[a].identifier]&&s.push(o[a]),e&(It|Ht)&&delete i[o[a].identifier],a++;return s.length?[y(r.concat(s),"identifier",!0),s]:void 0}function j(){C.apply(this,arguments);var t=l(this.handler,this);this.touch=new z(this.manager,t),this.mouse=new N(this.manager,t),this.primaryTouch=null,this.lastTouches=[]}function X(t,e){t&Ot?(this.primaryTouch=e.changedPointers[0].identifier,$.call(this,e)):t&(It|Ht)&&$.call(this,e)}function $(t){var e=t.changedPointers[0];if(e.identifier===this.primaryTouch){var n={x:e.clientX,y:e.clientY};this.lastTouches.push(n);var i=this.lastTouches,a=function(){var t=i.indexOf(n);t>-1&&i.splice(t,1)};setTimeout(a,ne)}}function W(t){for(var e=t.srcEvent.clientX,n=t.srcEvent.clientY,i=0;i<this.lastTouches.length;i++){var a=this.lastTouches[i],r=Math.abs(e-a.x),o=Math.abs(n-a.y);if(r<=ie&&o<=ie)return!0}return!1}function K(t,e){this.manager=t,this.set(e)}function U(t){if(m(t,le))return le;var e=m(t,ue),n=m(t,pe);return e&&n?le:e||n?e?ue:pe:m(t,ce)?ce:se}function B(){if(!re)return!1;var e={},n=t.CSS&&t.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(i){e[i]=!n||t.CSS.supports("touch-action",i)}),e}function G(t){this.options=pt({},this.defaults,t||{}),this.id=k(),this.manager=null,this.options.enable=p(this.options.enable,!0),this.state=de,this.simultaneous={},this.requireFail=[]}function J(t){return t&we?"cancel":t&ve?"end":t&me?"move":t&fe?"start":""}function Z(t){return t==Ft?"down":t==Nt?"up":t==Yt?"left":t==Vt?"right":""}function Q(t,e){var n=e.manager;return n?n.get(t):t}function tt(){G.apply(this,arguments)}function et(){tt.apply(this,arguments),this.pX=null,this.pY=null}function nt(){tt.apply(this,arguments)}function it(){G.apply(this,arguments),this._timer=null,this._input=null}function at(){tt.apply(this,arguments)}function rt(){tt.apply(this,arguments)}function ot(){G.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function st(t,e){return e=e||{},e.recognizers=p(e.recognizers,st.defaults.preset),new ct(t,e)}function ct(t,e){this.options=pt({},st.defaults,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=b(this),this.touchAction=new K(this,this.options.touchAction),lt(this,!0),o(this.options.recognizers,function(t){var e=this.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])},this)}function lt(t,e){var n=t.element;if(n.style){var i;o(t.options.cssProps,function(a,r){i=T(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=a):n.style[i]=t.oldCssProps[i]||""}),e||(t.oldCssProps={})}}function ut(t,n){var i=e.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n,n.target.dispatchEvent(i)}var pt,ht=["","webkit","Moz","MS","ms","o"],dt=e.createElement("div"),ft="function",mt=Math.round,vt=Math.abs,gt=Date.now;pt="function"!=typeof Object.assign?function(t){if(t===i||null===t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),n=1;n<arguments.length;n++){var a=arguments[n];if(a!==i&&null!==a)for(var r in a)a.hasOwnProperty(r)&&(e[r]=a[r])}return e}:Object.assign;var wt=s(function(t,e,n){for(var a=Object.keys(e),r=0;r<a.length;)(!n||n&&t[a[r]]===i)&&(t[a[r]]=e[a[r]]),r++;return t},"extend","Use `assign`."),yt=s(function(t,e){return wt(t,e,!0)},"merge","Use `assign`."),Tt=1,kt=/mobile|tablet|ip(ad|hone|od)|android/i,xt="ontouchstart"in t,Ct=T(t,"PointerEvent")!==i,bt=xt&&kt.test(navigator.userAgent),Mt="touch",_t="pen",Et="mouse",Dt="kinect",Pt=25,Ot=1,At=2,It=4,Ht=8,St=1,Yt=2,Vt=4,Nt=8,Ft=16,Rt=Yt|Vt,qt=Nt|Ft,zt=Rt|qt,Lt=["x","y"],jt=["clientX","clientY"];C.prototype={handler:function(){},init:function(){this.evEl&&h(this.element,this.evEl,this.domHandler),this.evTarget&&h(this.target,this.evTarget,this.domHandler),this.evWin&&h(x(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&d(this.element,this.evEl,this.domHandler),this.evTarget&&d(this.target,this.evTarget,this.domHandler),this.evWin&&d(x(this.element),this.evWin,this.domHandler)}};var Xt={mousedown:Ot,mousemove:At,mouseup:It},$t="mousedown",Wt="mousemove mouseup";c(N,C,{handler:function(t){var e=Xt[t.type];e&Ot&&0===t.button&&(this.pressed=!0),e&At&&1!==t.which&&(e=It),this.pressed&&(e&It&&(this.pressed=!1),this.callback(this.manager,e,{pointers:[t],changedPointers:[t],pointerType:Et,srcEvent:t}))}});var Kt={pointerdown:Ot,pointermove:At,pointerup:It,pointercancel:Ht,pointerout:Ht},Ut={2:Mt,3:_t,4:Et,5:Dt},Bt="pointerdown",Gt="pointermove pointerup pointercancel";t.MSPointerEvent&&!t.PointerEvent&&(Bt="MSPointerDown",Gt="MSPointerMove MSPointerUp MSPointerCancel"),c(F,C,{handler:function(t){var e=this.store,n=!1,i=t.type.toLowerCase().replace("ms",""),a=Kt[i],r=Ut[t.pointerType]||t.pointerType,o=r==Mt,s=g(e,t.pointerId,"pointerId");a&Ot&&(0===t.button||o)?s<0&&(e.push(t),s=e.length-1):a&(It|Ht)&&(n=!0),s<0||(e[s]=t,this.callback(this.manager,a,{pointers:e,changedPointers:[t],pointerType:r,srcEvent:t}),n&&e.splice(s,1))}});var Jt={touchstart:Ot,touchmove:At,touchend:It,touchcancel:Ht},Zt="touchstart",Qt="touchstart touchmove touchend touchcancel";c(R,C,{handler:function(t){var e=Jt[t.type];if(e===Ot&&(this.started=!0),this.started){var n=q.call(this,t,e);e&(It|Ht)&&n[0].length-n[1].length===0&&(this.started=!1),this.callback(this.manager,e,{pointers:n[0],changedPointers:n[1],pointerType:Mt,srcEvent:t})}}});var te={touchstart:Ot,touchmove:At,touchend:It,touchcancel:Ht},ee="touchstart touchmove touchend touchcancel";c(z,C,{handler:function(t){var e=te[t.type],n=L.call(this,t,e);n&&this.callback(this.manager,e,{pointers:n[0],changedPointers:n[1],pointerType:Mt,srcEvent:t})}});var ne=2500,ie=25;c(j,C,{handler:function(t,e,n){var i=n.pointerType==Mt,a=n.pointerType==Et;if(!(a&&n.sourceCapabilities&&n.sourceCapabilities.firesTouchEvents)){if(i)X.call(this,e,n);else if(a&&W.call(this,n))return;this.callback(t,e,n)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var ae=T(dt.style,"touchAction"),re=ae!==i,oe="compute",se="auto",ce="manipulation",le="none",ue="pan-x",pe="pan-y",he=B();K.prototype={set:function(t){t==oe&&(t=this.compute()),re&&this.manager.element.style&&he[t]&&(this.manager.element.style[ae]=t),this.actions=t.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var t=[];return o(this.manager.recognizers,function(e){u(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))}),U(t.join(" "))},preventDefaults:function(t){var e=t.srcEvent,n=t.offsetDirection;if(this.manager.session.prevented)return void e.preventDefault();var i=this.actions,a=m(i,le)&&!he[le],r=m(i,pe)&&!he[pe],o=m(i,ue)&&!he[ue];if(a){var s=1===t.pointers.length,c=t.distance<2,l=t.deltaTime<250;if(s&&c&&l)return}return o&&r?void 0:a||r&&n&Rt||o&&n&qt?this.preventSrc(e):void 0},preventSrc:function(t){this.manager.session.prevented=!0,t.preventDefault()}};var de=1,fe=2,me=4,ve=8,ge=ve,we=16,ye=32;G.prototype={defaults:{},set:function(t){return pt(this.options,t),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(t){if(r(t,"recognizeWith",this))return this;var e=this.simultaneous;return t=Q(t,this),e[t.id]||(e[t.id]=t,t.recognizeWith(this)),this},dropRecognizeWith:function(t){return r(t,"dropRecognizeWith",this)?this:(t=Q(t,this),delete this.simultaneous[t.id],this)},requireFailure:function(t){if(r(t,"requireFailure",this))return this;var e=this.requireFail;return t=Q(t,this),g(e,t)===-1&&(e.push(t),t.requireFailure(this)),this},dropRequireFailure:function(t){if(r(t,"dropRequireFailure",this))return this;t=Q(t,this);var e=g(this.requireFail,t);return e>-1&&this.requireFail.splice(e,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(t){return!!this.simultaneous[t.id]},emit:function(t){function e(e){n.manager.emit(e,t)}var n=this,i=this.state;i<ve&&e(n.options.event+J(i)),e(n.options.event),t.additionalEvent&&e(t.additionalEvent),i>=ve&&e(n.options.event+J(i))},tryEmit:function(t){return this.canEmit()?this.emit(t):void(this.state=ye)},canEmit:function(){for(var t=0;t<this.requireFail.length;){if(!(this.requireFail[t].state&(ye|de)))return!1;t++}return!0},recognize:function(t){var e=pt({},t);return u(this.options.enable,[this,e])?(this.state&(ge|we|ye)&&(this.state=de),this.state=this.process(e),void(this.state&(fe|me|ve|we)&&this.tryEmit(e))):(this.reset(),void(this.state=ye))},process:function(t){},getTouchAction:function(){},reset:function(){}},c(tt,G,{defaults:{pointers:1},attrTest:function(t){var e=this.options.pointers;return 0===e||t.pointers.length===e},process:function(t){var e=this.state,n=t.eventType,i=e&(fe|me),a=this.attrTest(t);return i&&(n&Ht||!a)?e|we:i||a?n&It?e|ve:e&fe?e|me:fe:ye}}),c(et,tt,{defaults:{event:"pan",threshold:10,pointers:1,direction:zt},getTouchAction:function(){var t=this.options.direction,e=[];return t&Rt&&e.push(pe),t&qt&&e.push(ue),e},directionTest:function(t){var e=this.options,n=!0,i=t.distance,a=t.direction,r=t.deltaX,o=t.deltaY;return a&e.direction||(e.direction&Rt?(a=0===r?St:r<0?Yt:Vt,n=r!=this.pX,i=Math.abs(t.deltaX)):(a=0===o?St:o<0?Nt:Ft,n=o!=this.pY,i=Math.abs(t.deltaY))),t.direction=a,n&&i>e.threshold&&a&e.direction},attrTest:function(t){return tt.prototype.attrTest.call(this,t)&&(this.state&fe||!(this.state&fe)&&this.directionTest(t))},emit:function(t){this.pX=t.deltaX,this.pY=t.deltaY;var e=Z(t.direction);e&&(t.additionalEvent=this.options.event+e),this._super.emit.call(this,t)}}),c(nt,tt,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[le]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.scale-1)>this.options.threshold||this.state&fe)},emit:function(t){if(1!==t.scale){var e=t.scale<1?"in":"out";t.additionalEvent=this.options.event+e}this._super.emit.call(this,t)}}),c(it,G,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[se]},process:function(t){var e=this.options,n=t.pointers.length===e.pointers,i=t.distance<e.threshold,r=t.deltaTime>e.time;if(this._input=t,!i||!n||t.eventType&(It|Ht)&&!r)this.reset();else if(t.eventType&Ot)this.reset(),this._timer=a(function(){this.state=ge,this.tryEmit()},e.time,this);else if(t.eventType&It)return ge;return ye},reset:function(){clearTimeout(this._timer)},emit:function(t){this.state===ge&&(t&&t.eventType&It?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=gt(),this.manager.emit(this.options.event,this._input)))}}),c(at,tt,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[le]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.rotation)>this.options.threshold||this.state&fe)}}),c(rt,tt,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Rt|qt,pointers:1},getTouchAction:function(){return et.prototype.getTouchAction.call(this)},attrTest:function(t){var e,n=this.options.direction;return n&(Rt|qt)?e=t.overallVelocity:n&Rt?e=t.overallVelocityX:n&qt&&(e=t.overallVelocityY),this._super.attrTest.call(this,t)&&n&t.offsetDirection&&t.distance>this.options.threshold&&t.maxPointers==this.options.pointers&&vt(e)>this.options.velocity&&t.eventType&It},emit:function(t){var e=Z(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)}}),c(ot,G,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ce]},process:function(t){var e=this.options,n=t.pointers.length===e.pointers,i=t.distance<e.threshold,r=t.deltaTime<e.time;if(this.reset(),t.eventType&Ot&&0===this.count)return this.failTimeout();if(i&&r&&n){if(t.eventType!=It)return this.failTimeout();var o=!this.pTime||t.timeStamp-this.pTime<e.interval,s=!this.pCenter||H(this.pCenter,t.center)<e.posThreshold;this.pTime=t.timeStamp,this.pCenter=t.center,s&&o?this.count+=1:this.count=1,this._input=t;var c=this.count%e.taps;if(0===c)return this.hasRequireFailures()?(this._timer=a(function(){this.state=ge,this.tryEmit()},e.interval,this),fe):ge}return ye},failTimeout:function(){return this._timer=a(function(){this.state=ye},this.options.interval,this),ye},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==ge&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),st.VERSION="2.0.8",st.defaults={domEvents:!1,touchAction:oe,enable:!0,inputTarget:null,inputClass:null,preset:[[at,{enable:!1}],[nt,{enable:!1},["rotate"]],[rt,{direction:Rt}],[et,{direction:Rt},["swipe"]],[ot],[ot,{event:"doubletap",taps:2},["tap"]],[it]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var Te=1,ke=2;ct.prototype={set:function(t){return pt(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},stop:function(t){this.session.stopped=t?ke:Te},recognize:function(t){var e=this.session;if(!e.stopped){this.touchAction.preventDefaults(t);var n,i=this.recognizers,a=e.curRecognizer;(!a||a&&a.state&ge)&&(a=e.curRecognizer=null);for(var r=0;r<i.length;)n=i[r],e.stopped===ke||a&&n!=a&&!n.canRecognizeWith(a)?n.reset():n.recognize(t),!a&&n.state&(fe|me|ve)&&(a=e.curRecognizer=n),r++}},get:function(t){if(t instanceof G)return t;for(var e=this.recognizers,n=0;n<e.length;n++)if(e[n].options.event==t)return e[n];return null},add:function(t){if(r(t,"add",this))return this;var e=this.get(t.options.event);return e&&this.remove(e),this.recognizers.push(t),t.manager=this,this.touchAction.update(),t},remove:function(t){if(r(t,"remove",this))return this;if(t=this.get(t)){var e=this.recognizers,n=g(e,t);n!==-1&&(e.splice(n,1),this.touchAction.update())}return this},on:function(t,e){if(t!==i&&e!==i){var n=this.handlers;return o(v(t),function(t){n[t]=n[t]||[],n[t].push(e)}),this}},off:function(t,e){if(t!==i){var n=this.handlers;return o(v(t),function(t){e?n[t]&&n[t].splice(g(n[t],e),1):delete n[t]}),this}},emit:function(t,e){this.options.domEvents&&ut(t,e);var n=this.handlers[t]&&this.handlers[t].slice();if(n&&n.length){e.type=t,e.preventDefault=function(){e.srcEvent.preventDefault()};for(var i=0;i<n.length;)n[i](e),i++}},destroy:function(){this.element&&lt(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},pt(st,{INPUT_START:Ot,INPUT_MOVE:At,INPUT_END:It,INPUT_CANCEL:Ht,STATE_POSSIBLE:de,STATE_BEGAN:fe,STATE_CHANGED:me,STATE_ENDED:ve,STATE_RECOGNIZED:ge,STATE_CANCELLED:we,STATE_FAILED:ye,DIRECTION_NONE:St,DIRECTION_LEFT:Yt,DIRECTION_RIGHT:Vt,DIRECTION_UP:Nt,DIRECTION_DOWN:Ft,DIRECTION_HORIZONTAL:Rt,DIRECTION_VERTICAL:qt,DIRECTION_ALL:zt,Manager:ct,Input:C,TouchAction:K,TouchInput:z,MouseInput:N,PointerEventInput:F,TouchMouseInput:j,SingleTouchInput:R,Recognizer:G,AttrRecognizer:tt,Tap:ot,Pan:et,Swipe:rt,Pinch:nt,Rotate:at,Press:it,on:h,off:d,each:o,merge:yt,extend:wt,assign:pt,inherit:c,bindFn:l,prefixed:T});var xe="undefined"!=typeof t?t:"undefined"!=typeof self?self:{};xe.Hammer=st,"function"==typeof define&&define.amd?define(function(){return st}):"undefined"!=typeof module&&module.exports?module.exports=st:t[n]=st}(window,document,"Hammer"),+function(t){"use strict";var e;t.modal=function(n,i){n=t.extend({},e,n);var a=n.buttons,r=a.map(function(t,e){return'<a href="javascript:;" class="weui-dialog__btn '+(t.className||"")+'">'+t.text+"</a>"}).join(""),o='<div class="weui-dialog"><div class="weui-dialog__hd"><strong class="weui-dialog__title">'+n.title+"</strong></div>"+(n.text?'<div class="weui-dialog__bd">'+n.text+"</div>":"")+'<div class="weui-dialog__ft">'+r+"</div></div>",s=t.openModal(o,i);return s.find(".weui-dialog__btn").each(function(e,i){var r=t(i);r.click(function(){n.autoClose&&t.closeModal(),a[e].onClick&&a[e].onClick.call(s)})}),s},t.openModal=function(e,n){var i=t("<div class='weui-mask'></div>").appendTo(document.body);i.show();var a=t(e).appendTo(document.body);return n&&a.transitionEnd(function(){n.call(a)}),a.show(),i.addClass("weui-mask--visible"),a.addClass("weui-dialog--visible"),a},t.closeModal=function(){t(".weui-mask--visible").removeClass("weui-mask--visible").transitionEnd(function(){t(this).remove()}),t(".weui-dialog--visible").removeClass("weui-dialog--visible").transitionEnd(function(){t(this).remove()})},t.alert=function(n,i,a){var r;return"object"==typeof n?r=n:("function"==typeof i&&(a=arguments[1],i=void 0),r={text:n,title:i,onOK:a}),t.modal({text:r.text,title:r.title,buttons:[{text:e.buttonOK,className:"primary",onClick:r.onOK}]})},t.confirm=function(n,i,a,r){var o;return"object"==typeof n?o=n:("function"==typeof i&&(r=arguments[2],a=arguments[1],i=void 0),o={text:n,title:i,onOK:a,onCancel:r}),t.modal({text:o.text,title:o.title,buttons:[{text:e.buttonCancel,className:"default",onClick:o.onCancel},{text:e.buttonOK,className:"primary",onClick:o.onOK}]})},t.prompt=function(n,i,a,r,o){var s;"object"==typeof n?s=n:("function"==typeof i&&(o=arguments[3],r=arguments[2],a=arguments[1],i=void 0),s={text:n,title:i,input:o,onOK:a,onCancel:r,empty:!1});var c=t.modal({text:'<p class="weui-prompt-text">'+(s.text||"")+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-input" value="'+(s.input||"")+'" />',title:s.title,autoClose:!1,buttons:[{text:e.buttonCancel,className:"default",onClick:function(){t.closeModal(),s.onCancel&&s.onCancel.call(c)}},{text:e.buttonOK,className:"primary",onClick:function(){var e=t("#weui-prompt-input").val();return s.empty||""!==e&&null!==e?(t.closeModal(),void(s.onOK&&s.onOK.call(c,e))):(c.find(".weui-prompt-input").focus()[0].select(),!1)}}]},function(){this.find(".weui-prompt-input").focus()[0].select()});return c},t.login=function(n,i,a,r,o,s){var c;"object"==typeof n?c=n:("function"==typeof i&&(s=arguments[4],o=arguments[3],r=arguments[2],a=arguments[1],i=void 0),c={text:n,title:i,username:o,password:s,onOK:a,onCancel:r});var l=t.modal({text:'<p class="weui-prompt-text">'+(c.text||"")+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-username" value="'+(c.username||"")+'" placeholder="输入用户名" /><input type="password" class="weui-input weui-prompt-input" id="weui-prompt-password" value="'+(c.password||"")+'" placeholder="输入密码" />',title:c.title,autoClose:!1,buttons:[{text:e.buttonCancel,className:"default",onClick:function(){t.closeModal(),c.onCancel&&c.onCancel.call(l)}},{text:e.buttonOK,className:"primary",onClick:function(){var e=t("#weui-prompt-username").val(),n=t("#weui-prompt-password").val();return c.empty||""!==e&&null!==e?c.empty||""!==n&&null!==n?(t.closeModal(),void(c.onOK&&c.onOK.call(l,e,n))):(l.find("#weui-prompt-password").focus()[0].select(),!1):(l.find("#weui-prompt-username").focus()[0].select(),!1)}}]},function(){this.find("#weui-prompt-username").focus()[0].select()});return l},e=t.modal.prototype.defaults={title:"提示",text:void 0,buttonOK:"确定",buttonCancel:"取消",buttons:[{text:"确定",className:"primary"}],autoClose:!0}}($),+function(t){"use strict";var e=function(e,n){n=n||"";var i=(t("<div class='weui-mask_transparent'></div>").appendTo(document.body),'<div class="weui-toast '+n+'">'+e+"</div>"),a=t(i).appendTo(document.body);a.addClass("weui-toast--visible"),a.show()},n=function(e){t(".weui-mask_transparent").remove();var n=!1,i=t(".weui-toast--visible").removeClass("weui-toast--visible").transitionEnd(function(){var i=t(this);i.remove(),e&&e(),n=!0});setTimeout(function(){n||(i.remove(),e&&e())},1e3)};t.toast=function(t,a,r){"function"==typeof a&&(r=a);var o,s="weui-icon-success-no-circle",c=i.duration;"cancel"==a?(o="weui-toast_cancel",s="weui-icon-cancel"):"forbidden"==a?(o="weui-toast--forbidden",s="weui-icon-warn"):"text"==a?o="weui-toast--text":"number"==typeof a&&(c=a),e('<i class="'+s+' weui-icon_toast"></i><p class="weui-toast_content">'+(t||"已经完成")+"</p>",o),setTimeout(function(){n(r)},c)},t.showLoading=function(t){var n='<div class="weui_loading">';n+='<i class="weui-loading weui-icon_toast"></i>',n+="</div>",n+='<p class="weui-toast_content">'+(t||"数据加载中")+"</p>",e(n,"weui_loading_toast")},t.hideLoading=function(){n()};var i=t.toast.prototype.defaults={duration:2500}}($),+function(t){"use strict";var e,n=function(e){var n=t("<div class='weui-mask weui-actions_mask'></div>").appendTo(document.body),i=e.actions||[],a=i.map(function(t,e){return'<div class="weui-actionsheet__cell '+(t.className||"")+'">'+t.text+"</div>"}).join(""),r="";e.title&&(r='<div class="weui-actionsheet__title"><p class="weui-actionsheet__title-text">'+e.title+"</p></div>");var o='<div class="weui-actionsheet " id="weui-actionsheet">'+r+'<div class="weui-actionsheet__menu">'+a+'</div><div class="weui-actionsheet__action"><div class="weui-actionsheet__cell weui-actionsheet_cancel">取消</div></div></div>',s=t(o).appendTo(document.body);s.find(".weui-actionsheet__menu .weui-actionsheet__cell, .weui-actionsheet__action .weui-actionsheet__cell").each(function(n,a){t(a).click(function(){t.closeActions(),e.onClose&&e.onClose(),i[n]&&i[n].onClick&&i[n].onClick()})}),n.show(),s.show(),n.addClass("weui-mask--visible"),s.addClass("weui-actionsheet_toggle")},i=function(){t(".weui-mask").removeClass("weui-mask--visible").transitionEnd(function(){t(this).remove()}),t(".weui-actionsheet").removeClass("weui-actionsheet_toggle").transitionEnd(function(){t(this).remove()})};t.actions=function(i){i=t.extend({},e,i),n(i)},t.closeActions=function(){i()},t(document).on("click",".weui-actions_mask",function(){t.closeActions()});var e=t.actions.prototype.defaults={title:void 0,onClose:void 0}}($),+function(t){"use strict";var e=function(n,i){"function"==typeof i&&(i={onRefresh:i}),"string"==typeof i&&(i=void 0),this.opt=t.extend(e.defaults,i||{}),this.container=t(n),this.attachEvents()};e.defaults={distance:50,onRefresh:void 0,onPull:void 0},e.prototype.touchStart=function(e){if(!this.container.hasClass("refreshing")){var n=t.getTouchPosition(e);this.start=n,this.diffX=this.diffY=0}},e.prototype.touchMove=function(e){if(!this.container.hasClass("refreshing")){if(!this.start)return!1;if(!(this.container.scrollTop()>0)){var n=t.getTouchPosition(e);return this.diffX=n.x-this.start.x,this.diffY=n.y-this.start.y,Math.abs(this.diffX)>Math.abs(this.diffY)||void(this.diffY<0||(this.container.addClass("touching"),e.preventDefault(),e.stopPropagation(),this.diffY=Math.pow(this.diffY,.75),this.container.css("transform","translate3d(0, "+this.diffY+"px, 0)"),this.triggerPull(this.diffY)))}}},e.prototype.touchEnd=function(){this.start=!1,this.diffY<=0||this.container.hasClass("refreshing")||(this.container.removeClass("touching"),this.container.removeClass("pull-down pull-up"),this.container.css("transform",""),Math.abs(this.diffY)<=this.opt.distance||this.triggerPullToRefresh())},e.prototype.triggerPullToRefresh=function(){this.triggerPull(this.opt.distance),this.container.removeClass("pull-up").addClass("refreshing"),this.opt.onRefresh&&this.opt.onRefresh.call(this),this.container.trigger("pull-to-refresh")},e.prototype.triggerPull=function(t){t<this.opt.distance?this.container.removeClass("pull-up").addClass("pull-down"):this.container.removeClass("pull-down").addClass("pull-up"),this.opt.onPull&&this.opt.onPull.call(this,Math.floor(t/this.opt.distance*100)),this.container.trigger("pull")},e.prototype.pullToRefreshDone=function(){this.container.removeClass("refreshing")},e.prototype.attachEvents=function(){var e=this.container;e.addClass("weui-pull-to-refresh"),e.on(t.touchEvents.start,t.proxy(this.touchStart,this)),e.on(t.touchEvents.move,t.proxy(this.touchMove,this)),e.on(t.touchEvents.end,t.proxy(this.touchEnd,this))};var n=function(e){t(e).removeClass("refreshing")};t.fn.pullToRefresh=function(n){return this.each(function(){var i=t(this),a=i.data("ptr");a||i.data("ptr",a=new e(this,n)),"string"==typeof n&&a[n].call(a)})},t.fn.pullToRefreshDone=function(){return this.each(function(){n(this)})}}($),+function(t){"use strict";var e=function(e){var n,i=e[0].tagName.toUpperCase();n="BODY"===i||"HTML"===i?e.scrollTop()||t(window).scrollTop():e.scrollTop();var a=e.scrollHeight()-(t(window).height()+n);return console.log(a),a},n=function(e,n){this.container=t(e),this.container.data("infinite",this),this.distance=n||50,this.attachEvents()};n.prototype.scroll=function(){this.container;this._check()},n.prototype.attachEvents=function(e){var n=this.container,i="BODY"===n[0].tagName.toUpperCase()?t(document):n;i[e?"off":"on"]("scroll",t.proxy(this.scroll,this))},n.prototype.detachEvents=function(t){this.attachEvents(!0)},n.prototype._check=function(){var t=e(this.container);Math.abs(t)<=this.distance&&this.container.trigger("infinite")};t.fn.infinite=function(t){return this.each(function(){new n(this,t)})},t.fn.destroyInfinite=function(){return this.each(function(){var e=t(this).data("infinite");e&&e.detachEvents&&e.detachEvents()})}}($),+function(t){"use strict";var e="weui-bar__item--on",n=function(n){var i=t(n);if(!i.hasClass(e)){var a=i.attr("href");if(/^#/.test(a)){i.parent().find("."+e).removeClass(e),i.addClass(e);var r=i.parents(".weui-tab").find(".weui-tab__bd");r.find(".weui-tab__bd-item--active").removeClass("weui-tab__bd-item--active"),t(a).addClass("weui-tab__bd-item--active")}}};t.showTab=n,t(document).on("click",".weui-navbar__item, .weui-tabbar__item",function(i){var a=t(i.currentTarget),r=a.attr("href");a.hasClass(e)||/^#/.test(r)&&(i.preventDefault(),n(a))})}($),+function(t){"use strict";t(document).on("click touchstart",".weui-search-bar__label",function(e){t(e.target).parents(".weui-search-bar").addClass("weui-search-bar_focusing").find("input").focus()}).on("click",".weui-search-bar__cancel-btn",function(e){t(e.target).parents(".weui-search-bar").removeClass("weui-search-bar_focusing").find(".weui-search-bar__input").val("").blur()}).on("click",".weui-icon-clear",function(e){t(e.target).parents(".weui-search-bar").find(".weui-search-bar__input").val("").focus()})}($),function(t){"use strict";var e={},n=navigator.userAgent,i=n.match(/(Android);?[\s\/]+([\d.]+)?/),a=n.match(/(iPad).*OS\s([\d_]+)/),r=n.match(/(iPod)(.*OS\s([\d_]+))?/),o=!a&&n.match(/(iPhone\sOS)\s([\d_]+)/);if(e.ios=e.android=e.iphone=e.ipad=e.androidChrome=!1,i&&(e.os="android",e.osVersion=i[2],e.android=!0,e.androidChrome=n.toLowerCase().indexOf("chrome")>=0),(a||o||r)&&(e.os="ios",e.ios=!0),o&&!r&&(e.osVersion=o[2].replace(/_/g,"."),e.iphone=!0),a&&(e.osVersion=a[2].replace(/_/g,"."),e.ipad=!0),r&&(e.osVersion=r[3]?r[3].replace(/_/g,"."):null,e.iphone=!0),e.ios&&e.osVersion&&n.indexOf("Version/")>=0&&"10"===e.osVersion.split(".")[0]&&(e.osVersion=n.toLowerCase().split("version/")[1].split(" ")[0]),
+e.webView=(o||a||r)&&n.match(/.*AppleWebKit(?!.*Safari)/i),e.os&&"ios"===e.os){var s=e.osVersion.split(".");e.minimalUi=!e.webView&&(r||o)&&(1*s[0]===7?1*s[1]>=1:1*s[0]>7)&&t('meta[name="viewport"]').length>0&&t('meta[name="viewport"]').attr("content").indexOf("minimal-ui")>=0}var c=t(window).width(),l=t(window).height();e.statusBar=!1,e.webView&&c*l===screen.width*screen.height?e.statusBar=!0:e.statusBar=!1;var u=[];if(e.pixelRatio=window.devicePixelRatio||1,u.push("pixel-ratio-"+Math.floor(e.pixelRatio)),e.pixelRatio>=2&&u.push("retina"),e.os&&(u.push(e.os,e.os+"-"+e.osVersion.split(".")[0],e.os+"-"+e.osVersion.replace(/\./g,"-")),"ios"===e.os))for(var p=parseInt(e.osVersion.split(".")[0],10),h=p-1;h>=6;h--)u.push("ios-gt-"+h);e.statusBar?u.push("with-statusbar-overlay"):t("html").removeClass("with-statusbar-overlay"),u.length>0&&t("html").addClass(u.join(" ")),t.device=e}($),+function(t){"use strict";var e=function(e){function n(){var e=!1;return c.params.convertToPopover||c.params.onlyInPopover?(!c.inline&&c.params.input&&(c.params.onlyInPopover?e=!0:t.device.ios?e=!!t.device.ipad:t(window).width()>=768&&(e=!0)),e):e}function i(){return!!(c.opened&&c.container&&c.container.length>0&&c.container.parents(".popover").length>0)}function a(){if(c.opened)for(var t=0;t<c.cols.length;t++)c.cols[t].divider||(c.cols[t].calcSize(),c.cols[t].setValue(c.cols[t].value,0,!1))}function r(t){if(t.preventDefault(),!c.opened&&(c.open(),c.params.scrollToInput&&!n())){var e=c.input.parents(".content");if(0===e.length)return;var i,a=parseInt(e.css("padding-top"),10),r=parseInt(e.css("padding-bottom"),10),o=e[0].offsetHeight-a-c.container.height(),s=e[0].scrollHeight-a-c.container.height(),l=c.input.offset().top-a+c.input[0].offsetHeight;if(l>o){var u=e.scrollTop()+l-o;u+o>s&&(i=u+o-s+r,o===s&&(i=c.container.height()),e.css({"padding-bottom":i+"px"})),e.scrollTop(u,300)}}}function o(e){i()||(c.input&&c.input.length>0?e.target!==c.input[0]&&0===t(e.target).parents(".weui-picker-modal").length&&c.close():0===t(e.target).parents(".weui-picker-modal").length&&c.close())}function s(){c.opened=!1,c.input&&c.input.length>0&&c.input.parents(".page-content").css({"padding-bottom":""}),c.params.onClose&&c.params.onClose(c),c.container.find(".picker-items-col").each(function(){c.destroyPickerCol(this)})}var c=this,l={updateValuesOnMomentum:!1,updateValuesOnTouchmove:!0,rotateEffect:!1,momentumRatio:7,freeMode:!1,scrollToInput:!0,inputReadOnly:!0,toolbar:!0,toolbarCloseText:"完成",title:"请选择",toolbarTemplate:'<div class="toolbar">          <div class="toolbar-inner">          <a href="javascript:;" class="picker-button close-picker">{{closeText}}</a>          <h1 class="title">{{title}}</h1>          </div>          </div>'};e=e||{};for(var u in l)"undefined"==typeof e[u]&&(e[u]=l[u]);c.params=e,c.cols=[],c.initialized=!1,c.inline=!!c.params.container;var p=t.device.ios||navigator.userAgent.toLowerCase().indexOf("safari")>=0&&navigator.userAgent.toLowerCase().indexOf("chrome")<0&&!t.device.android;return c.setValue=function(t,e){for(var n=0,i=0;i<c.cols.length;i++)c.cols[i]&&!c.cols[i].divider&&(c.cols[i].setValue(t[n],e),n++)},c.updateValue=function(){for(var e=[],n=[],i=0;i<c.cols.length;i++)c.cols[i].divider||(e.push(c.cols[i].value),n.push(c.cols[i].displayValue));e.indexOf(void 0)>=0||(c.value=e,c.displayValue=n,c.params.onChange&&c.params.onChange(c,c.value,c.displayValue),c.input&&c.input.length>0&&(t(c.input).val(c.params.formatValue?c.params.formatValue(c,c.value,c.displayValue):c.value.join(" ")),t(c.input).trigger("change")))},c.initPickerCol=function(e,n){function i(){w=t.requestAnimationFrame(function(){h.updateItems(void 0,void 0,0),i()})}function a(e){if(!T&&!y){e.preventDefault(),y=!0;var n=t.getTouchPosition(e);k=x=n.y,C=(new Date).getTime(),A=!0,M=E=t.getTranslate(h.wrapper[0],"y")}}function r(e){if(y){e.preventDefault(),A=!1;var n=t.getTouchPosition(e);x=n.y,T||(t.cancelAnimationFrame(w),T=!0,M=E=t.getTranslate(h.wrapper[0],"y"),h.wrapper.transition(0)),e.preventDefault();var i=x-k;E=M+i,_=void 0,E<v&&(E=v-Math.pow(v-E,.8),_="min"),E>g&&(E=g+Math.pow(E-g,.8),_="max"),h.wrapper.transform("translate3d(0,"+E+"px,0)"),h.updateItems(void 0,E,0,c.params.updateValuesOnTouchmove),P=E-D||E,O=(new Date).getTime(),D=E}}function o(e){if(!y||!T)return void(y=T=!1);y=T=!1,h.wrapper.transition(""),_&&("min"===_?h.wrapper.transform("translate3d(0,"+v+"px,0)"):h.wrapper.transform("translate3d(0,"+g+"px,0)")),b=(new Date).getTime();var n,a;b-C>300?a=E:(n=Math.abs(P/(b-O)),a=E+P*c.params.momentumRatio),a=Math.max(Math.min(a,g),v);var r=-Math.floor((a-g)/f);c.params.freeMode||(a=-r*f+g),h.wrapper.transform("translate3d(0,"+parseInt(a,10)+"px,0)"),h.updateItems(r,a,"",!0),c.params.updateValuesOnMomentum&&(i(),h.wrapper.transitionEnd(function(){t.cancelAnimationFrame(w)})),setTimeout(function(){A=!0},100)}function s(e){if(A){t.cancelAnimationFrame(w);var n=t(this).attr("data-picker-value");h.setValue(n)}}var l=t(e),u=l.index(),h=c.cols[u];if(!h.divider){h.container=l,h.wrapper=h.container.find(".picker-items-col-wrapper"),h.items=h.wrapper.find(".picker-item");var d,f,m,v,g;h.replaceValues=function(t,e){h.destroyEvents(),h.values=t,h.displayValues=e;var n=c.columnHTML(h,!0);h.wrapper.html(n),h.items=h.wrapper.find(".picker-item"),h.calcSize(),h.setValue(h.values[0]||"",0,!0),h.initEvents()},h.calcSize=function(){if(h.values.length){c.params.rotateEffect&&(h.container.removeClass("picker-items-col-absolute"),h.width||h.container.css({width:""}));var e,n;e=0,n=h.container[0].offsetHeight,d=h.wrapper[0].offsetHeight,f=h.items[0].offsetHeight,m=f*h.items.length,v=n/2-m+f/2,g=n/2-f/2,h.width&&(e=h.width,parseInt(e,10)===e&&(e+="px"),h.container.css({width:e})),c.params.rotateEffect&&(h.width||(h.items.each(function(){var n=t(this);n.css({width:"auto"}),e=Math.max(e,n[0].offsetWidth),n.css({width:""})}),h.container.css({width:e+2+"px"})),h.container.addClass("picker-items-col-absolute"))}},h.calcSize(),h.wrapper.transform("translate3d(0,"+g+"px,0)").transition(0);var w;h.setValue=function(e,n,a){"undefined"==typeof n&&(n="");var r=h.wrapper.find('.picker-item[data-picker-value="'+e+'"]').index();if("undefined"==typeof r||r===-1)return void(h.value=h.displayValue=e);var o=-r*f+g;h.wrapper.transition(n),h.wrapper.transform("translate3d(0,"+o+"px,0)"),c.params.updateValuesOnMomentum&&h.activeIndex&&h.activeIndex!==r&&(t.cancelAnimationFrame(w),h.wrapper.transitionEnd(function(){t.cancelAnimationFrame(w)}),i()),h.updateItems(r,o,n,a)},h.updateItems=function(e,n,i,a){"undefined"==typeof n&&(n=t.getTranslate(h.wrapper[0],"y")),"undefined"==typeof e&&(e=-Math.round((n-g)/f)),e<0&&(e=0),e>=h.items.length&&(e=h.items.length-1);var r=h.activeIndex;h.activeIndex=e,h.wrapper.find(".picker-selected").removeClass("picker-selected"),c.params.rotateEffect&&h.items.transition(i);var o=h.items.eq(e).addClass("picker-selected").transform("");if((a||"undefined"==typeof a)&&(h.value=o.attr("data-picker-value"),h.displayValue=h.displayValues?h.displayValues[e]:h.value,r!==e&&(h.onChange&&h.onChange(c,h.value,h.displayValue),c.updateValue())),c.params.rotateEffect){(n-(Math.floor((n-g)/f)*f+g))/f;h.items.each(function(){var e=t(this),i=e.index()*f,a=g-n,r=i-a,o=r/f,s=Math.ceil(h.height/f/2)+1,c=-18*o;c>180&&(c=180),c<-180&&(c=-180),Math.abs(o)>s?e.addClass("picker-item-far"):e.removeClass("picker-item-far"),e.transform("translate3d(0, "+(-n+g)+"px, "+(p?-110:0)+"px) rotateX("+c+"deg)")})}},n&&h.updateItems(0,g,0);var y,T,k,x,C,b,M,_,E,D,P,O,A=!0;h.initEvents=function(e){var n=e?"off":"on";h.container[n](t.touchEvents.start,a),h.container[n](t.touchEvents.move,r),h.container[n](t.touchEvents.end,o),h.items[n]("click",s)},h.destroyEvents=function(){h.initEvents(!0)},h.container[0].f7DestroyPickerCol=function(){h.destroyEvents()},h.initEvents()}},c.destroyPickerCol=function(e){e=t(e),"f7DestroyPickerCol"in e[0]&&e[0].f7DestroyPickerCol()},t(window).on("resize",a),c.columnHTML=function(t,e){var n="",i="";if(t.divider)i+='<div class="picker-items-col picker-items-col-divider '+(t.textAlign?"picker-items-col-"+t.textAlign:"")+" "+(t.cssClass||"")+'">'+t.content+"</div>";else{for(var a=0;a<t.values.length;a++)n+='<div class="picker-item" data-picker-value="'+t.values[a]+'">'+(t.displayValues?t.displayValues[a]:t.values[a])+"</div>";i+='<div class="picker-items-col '+(t.textAlign?"picker-items-col-"+t.textAlign:"")+" "+(t.cssClass||"")+'"><div class="picker-items-col-wrapper">'+n+"</div></div>"}return e?n:i},c.layout=function(){var t,e="",n="";c.cols=[];var i="";for(t=0;t<c.params.cols.length;t++){var a=c.params.cols[t];i+=c.columnHTML(c.params.cols[t]),c.cols.push(a)}n="weui-picker-modal picker-columns "+(c.params.cssClass||"")+(c.params.rotateEffect?" picker-3d":"")+(1===c.params.cols.length?" picker-columns-single":""),e='<div class="'+n+'">'+(c.params.toolbar?c.params.toolbarTemplate.replace(/{{closeText}}/g,c.params.toolbarCloseText).replace(/{{title}}/g,c.params.title):"")+'<div class="picker-modal-inner picker-items">'+i+'<div class="picker-center-highlight"></div></div></div>',c.pickerHTML=e},c.params.input&&(c.input=t(c.params.input),c.input.length>0&&(c.params.inputReadOnly&&c.input.prop("readOnly",!0),c.inline||c.input.on("click",r),c.params.inputReadOnly&&c.input.on("focus mousedown",function(t){t.preventDefault()}))),c.inline||t("html").on("click",o),c.opened=!1,c.open=function(){var e=n();c.opened||(c.layout(),e?(c.pickerHTML='<div class="popover popover-picker-columns"><div class="popover-inner">'+c.pickerHTML+"</div></div>",c.popover=t.popover(c.pickerHTML,c.params.input,!0),c.container=t(c.popover).find(".weui-picker-modal"),t(c.popover).on("close",function(){s()})):c.inline?(c.container=t(c.pickerHTML),c.container.addClass("picker-modal-inline"),t(c.params.container).append(c.container)):(c.container=t(t.openPicker(c.pickerHTML)),t(c.container).on("close",function(){s()})),c.container[0].f7Picker=c,c.container.find(".picker-items-col").each(function(){var t=!0;(!c.initialized&&c.params.value||c.initialized&&c.value)&&(t=!1),c.initPickerCol(this,t)}),c.initialized?c.value&&c.setValue(c.value,0):c.params.value&&c.setValue(c.params.value,0)),c.opened=!0,c.initialized=!0,c.params.onOpen&&c.params.onOpen(c)},c.close=function(e){if(c.opened&&!c.inline)return i()?void t.closePicker(c.popover):void t.closePicker(c.container)},c.destroy=function(){c.close(),c.params.input&&c.input.length>0&&(c.input.off("click focus",r),t(c.input).data("picker",null)),t("html").off("click",o),t(window).off("resize",a)},c.inline&&c.open(),c};t(document).on("click",".close-picker",function(){var e=t(".weui-picker-modal.weui-picker-modal-visible");e.length>0&&t.closePicker(e)}),t(document).on(t.touchEvents.move,".picker-modal-inner",function(t){t.preventDefault()}),t.openPicker=function(e,n,i){"function"==typeof n&&(i=n,n=void 0),t.closePicker();var a=t("<div class='weui-picker-container "+(n||"")+"'></div>").appendTo(document.body);a.show(),a.addClass("weui-picker-container-visible");var r=t(e).appendTo(a);return r.width(),r.addClass("weui-picker-modal-visible"),i&&a.on("close",i),r},t.updatePicker=function(e){var n=t(".weui-picker-container-visible");if(!n[0])return!1;n.html("");var i=t(e).appendTo(n);return i.addClass("weui-picker-modal-visible"),i},t.closePicker=function(e,n){"function"==typeof e&&(n=e),t(".weui-picker-modal-visible").removeClass("weui-picker-modal-visible").transitionEnd(function(){t(this).parent().remove(),n&&n()}).trigger("close")},t.fn.picker=function(n){var i=arguments;return this.each(function(){if(this){var a=t(this),r=a.data("picker");if(!r){n=t.extend({input:this},n||{});var o=a.val();void 0===n.value&&""!==o&&(n.value=n.cols&&n.cols.length>1?o.split(" "):[o]);var s=t.extend({input:this},n);r=new e(s),a.data("picker",r)}"string"==typeof n&&r[n].apply(r,Array.prototype.slice.call(i,1))}})}}($),+function(t){"use strict";var e,n=[],i=function(e,i){this.config=i,this.data={values:"",titles:"",origins:[],length:0},this.$input=t(e),this.$input.prop("readOnly",!0),this.initConfig(),i=this.config,this.$input.click(t.proxy(this.open,this)),n.push(this)};i.prototype.initConfig=function(){this.config=t.extend({},e,this.config);var n=this.config;n.items&&n.items.length&&(n.items=n.items.map(function(t,e){return"string"==typeof t?{title:t,value:t}:t}),this.tpl=t.t7.compile("<div class='weui-picker-modal weui-select-modal'>"+n.toolbarTemplate+(n.multi?n.checkboxTemplate:n.radioTemplate)+"</div>"),void 0!==n.input&&this.$input.val(n.input),this.parseInitValue(),this._init=!0)},i.prototype.updateInputValue=function(t,e){var n,i;this.config.multi?(n=t.join(this.config.split),i=e.join(this.config.split)):(n=t[0],i=e[0]);var a=[];this.config.items.forEach(function(e){t.each(function(t,n){e.value==n&&a.push(e)})}),this.$input.val(i).data("values",n),this.$input.attr("value",i).attr("data-values",n);var r={values:n,titles:i,valuesArray:t,titlesArray:e,origins:a,length:a.length};this.data=r,this.$input.trigger("change",r),this.config.onChange&&this.config.onChange.call(this,r)},i.prototype.parseInitValue=function(){var t=this.$input.val(),e=this.config.items;if(this._init||void 0!==t&&null!=t&&""!==t)for(var n=this.config.multi?t.split(this.config.split):[t],i=0;i<e.length;i++){e[i].checked=!1;for(var a=0;a<n.length;a++)e[i].title===n[a]&&(e[i].checked=!0)}},i.prototype._bind=function(e){var n=this,i=this.config;e.on("change",function(a){var r=e.find("input:checked"),o=r.map(function(){return t(this).val()}),s=r.map(function(){return t(this).data("title")});n.updateInputValue(o,s),i.autoClose&&!i.multi&&n.close()}).trigger("change").on("click",".close-select",function(){n.close()})},i.prototype.update=function(e){this.config=t.extend({},this.config,e),this.initConfig(),this._open&&this._bind(t.updatePicker(this.getHTML()))},i.prototype.open=function(e,i){if(!this._open){for(var a=0;a<n.length;a++){var r=n[a];if(r!==this&&r._open&&!r.close())return!1}this.parseInitValue();var o=this.config,s=this.dialog=t.openPicker(this.getHTML());this._bind(s),this._open=!0,o.onOpen&&o.onOpen(this)}},i.prototype.close=function(e,n){if(!this._open)return!1;var i=this,a=this.config.beforeClose;if(!n){if(a&&"function"==typeof a&&a.call(this,this.data.values,this.data.titles)===!1)return!1;if(this.config.multi){if(void 0!==this.config.min&&this.data.length<this.config.min)return t.toast("请至少选择"+this.config.min+"个","text"),!1;if(void 0!==this.config.max&&this.data.length>this.config.max)return t.toast("最多只能选择"+this.config.max+"个","text"),!1}}return t.closePicker(function(){i.onClose(),e&&e()}),!0},i.prototype.onClose=function(){this._open=!1,this.config.onClose&&this.config.onClose(this)},i.prototype.getHTML=function(t){var e=this.config;return this.tpl({items:e.items,title:e.title,closeText:e.closeText})},t.fn.select=function(e,n){return this.each(function(){var a=t(this);a.data("weui-select")||a.data("weui-select",new i(this,e));var r=a.data("weui-select");return"string"==typeof e&&r[e].call(r,n),r})},e=t.fn.select.prototype.defaults={items:[],input:void 0,title:"请选择",multi:!1,closeText:"确定",autoClose:!0,onChange:void 0,beforeClose:void 0,onClose:void 0,onOpen:void 0,split:",",min:void 0,max:void 0,toolbarTemplate:'<div class="toolbar">      <div class="toolbar-inner">      <a href="javascript:;" class="picker-button close-select">{{closeText}}</a>      <h1 class="title">{{title}}</h1>      </div>      </div>',radioTemplate:'<div class="weui-cells weui-cells_radio">        {{#items}}        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">          <div class="weui-cell__bd weui-cell_primary">            <p>{{this.title}}</p>          </div>          <div class="weui-cell__ft">            <input type="radio" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}">            <span class="weui-icon-checked"></span>          </div>        </label>        {{/items}}      </div>',checkboxTemplate:'<div class="weui-cells weui-cells_checkbox">        {{#items}}        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">          <div class="weui-cell__bd weui-cell_primary">            <p>{{this.title}}</p>          </div>          <div class="weui-cell__ft">            <input type="checkbox" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}" >            <span class="weui-icon-checked"></span>          </div>        </label>        {{/items}}      </div>'}}($),+function(t){"use strict";var e,n=!1,i=function(t,e){var t=new Date(t),e=new Date(e);return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()},a=function(a){function r(){var e=!1;return p.params.convertToPopover||p.params.onlyInPopover?(!p.inline&&p.params.input&&(p.params.onlyInPopover?e=!0:t.device.ios?e=!!t.device.ipad:t(window).width()>=768&&(e=!0)),e):e}function o(){return!!(p.opened&&p.container&&p.container.length>0&&p.container.parents(".popover").length>0)}function s(t){t=new Date(t);var e=t.getFullYear(),n=t.getMonth(),i=n+1,a=t.getDate(),r=t.getDay();return p.params.dateFormat.replace(/yyyy/g,e).replace(/yy/g,(e+"").substring(2)).replace(/mm/g,i<10?"0"+i:i).replace(/m/g,i).replace(/MM/g,p.params.monthNames[n]).replace(/M/g,p.params.monthNamesShort[n]).replace(/dd/g,a<10?"0"+a:a).replace(/d/g,a).replace(/DD/g,p.params.dayNames[r]).replace(/D/g,p.params.dayNamesShort[r])}function c(t){if(t.preventDefault(),!p.opened&&(p.open(),p.params.scrollToInput&&!r())){var e=p.input.parents(".page-content");if(0===e.length)return;var n,i=parseInt(e.css("padding-top"),10),a=parseInt(e.css("padding-bottom"),10),o=e[0].offsetHeight-i-p.container.height(),s=e[0].scrollHeight-i-p.container.height(),c=p.input.offset().top-i+p.input[0].offsetHeight;if(c>o){var l=e.scrollTop()+c-o;l+o>s&&(n=l+o-s+a,o===s&&(n=p.container.height()),e.css({"padding-bottom":n+"px"})),e.scrollTop(l,300)}}}function l(e){o()||(p.input&&p.input.length>0?e.target!==p.input[0]&&0===t(e.target).parents(".weui-picker-modal").length&&p.close():0===t(e.target).parents(".weui-picker-modal").length&&p.close())}function u(){p.opened=!1,p.input&&p.input.length>0&&p.input.parents(".page-content").css({"padding-bottom":""}),p.params.onClose&&p.params.onClose(p),p.destroyCalendarEvents()}var p=this;a=a||{};for(var h in e)"undefined"==typeof a[h]&&(a[h]=e[h]);p.params=a,p.initialized=!1,p.inline=!!p.params.container,p.isH="horizontal"===p.params.direction;var d=p.isH&&n?-1:1;return p.animating=!1,p.addValue=function(t){if(p.params.multiple){p.value||(p.value=[]);for(var e,n=0;n<p.value.length;n++)i(t,p.value[n])&&(e=n);"undefined"==typeof e?p.value.push(t):p.value.splice(e,1),p.updateValue()}else p.value=[t],p.updateValue()},p.setValue=function(t){var e=new Date(t[0]);p.setYearMonth(e.getFullYear(),e.getMonth()),p.addValue(+e)},p.updateValue=function(){p.wrapper.find(".picker-calendar-day-selected").removeClass("picker-calendar-day-selected");var e,n;for(e=0;e<p.value.length;e++){var i=new Date(p.value[e]);p.wrapper.find('.picker-calendar-day[data-date="'+i.getFullYear()+"-"+i.getMonth()+"-"+i.getDate()+'"]').addClass("picker-calendar-day-selected")}if(p.params.onChange&&p.params.onChange(p,p.value.map(s),p.value.map(function(t){return+new Date("string"==typeof t?t.split(/\D/).filter(function(t){return!!t}).join("-"):t)})),p.input&&p.input.length>0){if(p.params.formatValue)n=p.params.formatValue(p,p.value);else{for(n=[],e=0;e<p.value.length;e++)n.push(s(p.value[e]));n=n.join(", ")}t(p.input).val(n),t(p.input).trigger("change")}},p.initCalendarEvents=function(){function e(e){if(!s&&!o){o=!0;var n=t.getTouchPosition(e);c=h=n.x,l=h=n.y,f=(new Date).getTime(),T=0,C=!0,x=void 0,v=g=p.monthsTranslate}}function i(e){if(o){var n=t.getTouchPosition(e);if(u=n.x,h=n.y,"undefined"==typeof x&&(x=!!(x||Math.abs(h-l)>Math.abs(u-c))),p.isH&&x)return void(o=!1);if(e.preventDefault(),p.animating)return void(o=!1);C=!1,s||(s=!0,w=p.wrapper[0].offsetWidth,y=p.wrapper[0].offsetHeight,p.wrapper.transition(0)),e.preventDefault(),k=p.isH?u-c:h-l,T=k/(p.isH?w:y),g=100*(p.monthsTranslate*d+T),p.wrapper.transform("translate3d("+(p.isH?g:0)+"%, "+(p.isH?0:g)+"%, 0)")}}function a(t){return o&&s?(o=s=!1,m=(new Date).getTime(),m-f<300?Math.abs(k)<10?p.resetMonth():k>=10?n?p.nextMonth():p.prevMonth():n?p.prevMonth():p.nextMonth():T<=-.5?n?p.prevMonth():p.nextMonth():T>=.5?n?p.nextMonth():p.prevMonth():p.resetMonth(),void setTimeout(function(){C=!0},100)):void(o=s=!1)}function r(e){if(C){var n=t(e.target).parents(".picker-calendar-day");if(0===n.length&&t(e.target).hasClass("picker-calendar-day")&&(n=t(e.target)),0!==n.length&&!n.hasClass("picker-calendar-day-disabled")){n.hasClass("picker-calendar-day-next")&&p.nextMonth(),n.hasClass("picker-calendar-day-prev")&&p.prevMonth();var i=n.attr("data-year"),a=n.attr("data-month"),r=n.attr("data-day");p.params.onDayClick&&p.params.onDayClick(p,n[0],i,a,r),p.addValue(new Date(i,a,r).getTime()),p.params.closeOnSelect&&!p.params.multiple&&p.close()}}}var o,s,c,l,u,h,f,m,v,g,w,y,T,k,x,C=!0;p.container.find(".picker-calendar-prev-month").on("click",p.prevMonth),p.container.find(".picker-calendar-next-month").on("click",p.nextMonth),p.container.find(".picker-calendar-prev-year").on("click",p.prevYear),p.container.find(".picker-calendar-next-year").on("click",p.nextYear),p.wrapper.on("click",r),p.params.touchMove&&(p.wrapper.on(t.touchEvents.start,e),p.wrapper.on(t.touchEvents.move,i),p.wrapper.on(t.touchEvents.end,a)),p.container[0].f7DestroyCalendarEvents=function(){p.container.find(".picker-calendar-prev-month").off("click",p.prevMonth),p.container.find(".picker-calendar-next-month").off("click",p.nextMonth),p.container.find(".picker-calendar-prev-year").off("click",p.prevYear),p.container.find(".picker-calendar-next-year").off("click",p.nextYear),p.wrapper.off("click",r),p.params.touchMove&&(p.wrapper.off(t.touchEvents.start,e),p.wrapper.off(t.touchEvents.move,i),p.wrapper.off(t.touchEvents.end,a))}},p.destroyCalendarEvents=function(t){"f7DestroyCalendarEvents"in p.container[0]&&p.container[0].f7DestroyCalendarEvents()},p.daysInMonth=function(t){var e=new Date(t);return new Date(e.getFullYear(),e.getMonth()+1,0).getDate()},p.monthHTML=function(t,e){t=new Date(t);var n=t.getFullYear(),i=t.getMonth();t.getDate();"next"===e&&(t=11===i?new Date(n+1,0):new Date(n,i+1,1)),"prev"===e&&(t=0===i?new Date(n-1,11):new Date(n,i-1,1)),"next"!==e&&"prev"!==e||(i=t.getMonth(),n=t.getFullYear());var a=p.daysInMonth(new Date(t.getFullYear(),t.getMonth()).getTime()-864e6),r=p.daysInMonth(t),o=new Date(t.getFullYear(),t.getMonth()).getDay();0===o&&(o=7);var s,c,l,u=[],h=6,d=7,f="",m=0+(p.params.firstDay-1),v=(new Date).setHours(0,0,0,0),g=p.params.minDate?new Date(p.params.minDate).getTime():null,w=p.params.maxDate?new Date(p.params.maxDate).getTime():null;if(p.value&&p.value.length)for(c=0;c<p.value.length;c++)u.push(new Date(p.value[c]).setHours(0,0,0,0));for(c=1;c<=h;c++){var y="";for(l=1;l<=d;l++){var T=l;m++;var k=m-o,x="";k<0?(k=a+k+1,x+=" picker-calendar-day-prev",s=new Date(i-1<0?n-1:n,i-1<0?11:i-1,k).getTime()):(k+=1,k>r?(k-=r,x+=" picker-calendar-day-next",s=new Date(i+1>11?n+1:n,i+1>11?0:i+1,k).getTime()):s=new Date(n,i,k).getTime()),s===v&&(x+=" picker-calendar-day-today"),u.indexOf(s)>=0&&(x+=" picker-calendar-day-selected"),p.params.weekendDays.indexOf(T-1)>=0&&(x+=" picker-calendar-day-weekend"),(g&&s<g||w&&s>w)&&(x+=" picker-calendar-day-disabled"),s=new Date(s);var C=s.getFullYear(),b=s.getMonth();y+='<div data-year="'+C+'" data-month="'+b+'" data-day="'+k+'" class="picker-calendar-day'+x+'" data-date="'+(C+"-"+b+"-"+k)+'"><span>'+k+"</span></div>"}f+='<div class="picker-calendar-row">'+y+"</div>"}return f='<div class="picker-calendar-month" data-year="'+n+'" data-month="'+i+'">'+f+"</div>"},p.animating=!1,p.updateCurrentMonthYear=function(t){"undefined"==typeof t?(p.currentMonth=parseInt(p.months.eq(1).attr("data-month"),10),p.currentYear=parseInt(p.months.eq(1).attr("data-year"),10)):(p.currentMonth=parseInt(p.months.eq("next"===t?p.months.length-1:0).attr("data-month"),10),p.currentYear=parseInt(p.months.eq("next"===t?p.months.length-1:0).attr("data-year"),10)),p.container.find(".current-month-value").text(p.params.monthNames[p.currentMonth]),p.container.find(".current-year-value").text(p.currentYear)},p.onMonthChangeStart=function(t){p.updateCurrentMonthYear(t),p.months.removeClass("picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next");var e="next"===t?p.months.length-1:0;p.months.eq(e).addClass("picker-calendar-month-current"),p.months.eq("next"===t?e-1:e+1).addClass("next"===t?"picker-calendar-month-prev":"picker-calendar-month-next"),p.params.onMonthYearChangeStart&&p.params.onMonthYearChangeStart(p,p.currentYear,p.currentMonth)},p.onMonthChangeEnd=function(t,e){p.animating=!1;var n,i,a;p.wrapper.find(".picker-calendar-month:not(.picker-calendar-month-prev):not(.picker-calendar-month-current):not(.picker-calendar-month-next)").remove(),"undefined"==typeof t&&(t="next",e=!0),e?(p.wrapper.find(".picker-calendar-month-next, .picker-calendar-month-prev").remove(),i=p.monthHTML(new Date(p.currentYear,p.currentMonth),"prev"),n=p.monthHTML(new Date(p.currentYear,p.currentMonth),"next")):a=p.monthHTML(new Date(p.currentYear,p.currentMonth),t),("next"===t||e)&&p.wrapper.append(a||n),("prev"===t||e)&&p.wrapper.prepend(a||i),p.months=p.wrapper.find(".picker-calendar-month"),p.setMonthsTranslate(p.monthsTranslate),p.params.onMonthAdd&&p.params.onMonthAdd(p,"next"===t?p.months.eq(p.months.length-1)[0]:p.months.eq(0)[0]),p.params.onMonthYearChangeEnd&&p.params.onMonthYearChangeEnd(p,p.currentYear,p.currentMonth)},p.setMonthsTranslate=function(t){t=t||p.monthsTranslate||0,"undefined"==typeof p.monthsTranslate&&(p.monthsTranslate=t),p.months.removeClass("picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next");var e=100*-(t+1)*d,n=100*-t*d,i=100*-(t-1)*d;p.months.eq(0).transform("translate3d("+(p.isH?e:0)+"%, "+(p.isH?0:e)+"%, 0)").addClass("picker-calendar-month-prev"),p.months.eq(1).transform("translate3d("+(p.isH?n:0)+"%, "+(p.isH?0:n)+"%, 0)").addClass("picker-calendar-month-current"),p.months.eq(2).transform("translate3d("+(p.isH?i:0)+"%, "+(p.isH?0:i)+"%, 0)").addClass("picker-calendar-month-next")},p.nextMonth=function(e){"undefined"!=typeof e&&"object"!=typeof e||(e="",p.params.animate||(e=0));var n=parseInt(p.months.eq(p.months.length-1).attr("data-month"),10),i=parseInt(p.months.eq(p.months.length-1).attr("data-year"),10),a=new Date(i,n),r=a.getTime(),o=!p.animating;if(p.params.maxDate&&r>new Date(p.params.maxDate).getTime())return p.resetMonth();if(p.monthsTranslate--,n===p.currentMonth){var s=100*-p.monthsTranslate*d,c=t(p.monthHTML(r,"next")).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-next");p.wrapper.append(c[0]),p.months=p.wrapper.find(".picker-calendar-month"),p.params.onMonthAdd&&p.params.onMonthAdd(p,p.months.eq(p.months.length-1)[0])}p.animating=!0,p.onMonthChangeStart("next");var l=100*p.monthsTranslate*d;p.wrapper.transition(e).transform("translate3d("+(p.isH?l:0)+"%, "+(p.isH?0:l)+"%, 0)"),o&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd("next")}),p.params.animate||p.onMonthChangeEnd("next")},p.prevMonth=function(e){"undefined"!=typeof e&&"object"!=typeof e||(e="",p.params.animate||(e=0));var n=parseInt(p.months.eq(0).attr("data-month"),10),i=parseInt(p.months.eq(0).attr("data-year"),10),a=new Date(i,n+1,(-1)),r=a.getTime(),o=!p.animating;if(p.params.minDate&&r<new Date(p.params.minDate).getTime())return p.resetMonth();if(p.monthsTranslate++,n===p.currentMonth){var s=100*-p.monthsTranslate*d,c=t(p.monthHTML(r,"prev")).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-prev");p.wrapper.prepend(c[0]),p.months=p.wrapper.find(".picker-calendar-month"),p.params.onMonthAdd&&p.params.onMonthAdd(p,p.months.eq(0)[0])}p.animating=!0,p.onMonthChangeStart("prev");var l=100*p.monthsTranslate*d;p.wrapper.transition(e).transform("translate3d("+(p.isH?l:0)+"%, "+(p.isH?0:l)+"%, 0)"),o&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd("prev")}),p.params.animate||p.onMonthChangeEnd("prev")},p.resetMonth=function(t){"undefined"==typeof t&&(t="");var e=100*p.monthsTranslate*d;p.wrapper.transition(t).transform("translate3d("+(p.isH?e:0)+"%, "+(p.isH?0:e)+"%, 0)")},p.setYearMonth=function(t,e,n){"undefined"==typeof t&&(t=p.currentYear),"undefined"==typeof e&&(e=p.currentMonth),"undefined"!=typeof n&&"object"!=typeof n||(n="",p.params.animate||(n=0));var i;if(i=t<p.currentYear?new Date(t,e+1,(-1)).getTime():new Date(t,e).getTime(),p.params.maxDate&&i>new Date(p.params.maxDate).getTime())return!1;if(p.params.minDate&&i<new Date(p.params.minDate).getTime())return!1;var a=new Date(p.currentYear,p.currentMonth).getTime(),r=i>a?"next":"prev",o=p.monthHTML(new Date(t,e));p.monthsTranslate=p.monthsTranslate||0;var s,c,l=p.monthsTranslate,u=!p.animating;i>a?(p.monthsTranslate--,p.animating||p.months.eq(p.months.length-1).remove(),p.wrapper.append(o),p.months=p.wrapper.find(".picker-calendar-month"),s=100*-(l-1)*d,p.months.eq(p.months.length-1).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-next")):(p.monthsTranslate++,p.animating||p.months.eq(0).remove(),p.wrapper.prepend(o),p.months=p.wrapper.find(".picker-calendar-month"),s=100*-(l+1)*d,p.months.eq(0).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-prev")),p.params.onMonthAdd&&p.params.onMonthAdd(p,"next"===r?p.months.eq(p.months.length-1)[0]:p.months.eq(0)[0]),p.animating=!0,p.onMonthChangeStart(r),c=100*p.monthsTranslate*d,p.wrapper.transition(n).transform("translate3d("+(p.isH?c:0)+"%, "+(p.isH?0:c)+"%, 0)"),u&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd(r,!0)}),p.params.animate||p.onMonthChangeEnd(r)},p.nextYear=function(){p.setYearMonth(p.currentYear+1)},p.prevYear=function(){p.setYearMonth(p.currentYear-1)},p.layout=function(){var t,e="",n="",i=p.value&&p.value.length?p.value[0]:(new Date).setHours(0,0,0,0),a=p.monthHTML(i,"prev"),r=p.monthHTML(i),o=p.monthHTML(i,"next"),s='<div class="picker-calendar-months"><div class="picker-calendar-months-wrapper">'+(a+r+o)+"</div></div>",c="";if(p.params.weekHeader){for(t=0;t<7;t++){var l=t+p.params.firstDay>6?t-7+p.params.firstDay:t+p.params.firstDay,u=p.params.dayNamesShort[l];c+='<div class="picker-calendar-week-day '+(p.params.weekendDays.indexOf(l)>=0?"picker-calendar-week-day-weekend":"")+'"> '+u+"</div>"}c='<div class="picker-calendar-week-days">'+c+"</div>"}n="weui-picker-calendar "+(p.params.cssClass||""),p.inline||(n="weui-picker-modal "+n);var h=p.params.toolbar?p.params.toolbarTemplate.replace(/{{closeText}}/g,p.params.toolbarCloseText):"";p.params.toolbar&&(h=p.params.toolbarTemplate.replace(/{{closeText}}/g,p.params.toolbarCloseText).replace(/{{monthPicker}}/g,p.params.monthPicker?p.params.monthPickerTemplate:"").replace(/{{yearPicker}}/g,p.params.yearPicker?p.params.yearPickerTemplate:"")),e='<div class="'+n+'">'+h+'<div class="picker-modal-inner">'+c+s+"</div></div>",p.pickerHTML=e},p.params.input&&(p.input=t(p.params.input),p.input.length>0&&(p.params.inputReadOnly&&p.input.prop("readOnly",!0),p.inline||p.input.on("click",c),p.params.inputReadOnly&&p.input.on("focus mousedown",function(t){t.preventDefault()}))),p.inline||t(document).on("click touchend",l),p.opened=!1,p.open=function(){var e=r()&&!1,n=!1;p.opened||(p.value||p.params.value&&(p.value=p.params.value,n=!0),p.layout(),e?(p.pickerHTML='<div class="popover popover-picker-calendar"><div class="popover-inner">'+p.pickerHTML+"</div></div>",p.popover=t.popover(p.pickerHTML,p.params.input,!0),p.container=t(p.popover).find(".weui-picker-modal"),
+t(p.popover).on("close",function(){u()})):p.inline?(p.container=t(p.pickerHTML),p.container.addClass("picker-modal-inline"),t(p.params.container).append(p.container)):(p.container=t(t.openPicker(p.pickerHTML)),t(p.container).on("close",function(){u()})),p.container[0].f7Calendar=p,p.wrapper=p.container.find(".picker-calendar-months-wrapper"),p.months=p.wrapper.find(".picker-calendar-month"),p.updateCurrentMonthYear(),p.monthsTranslate=0,p.setMonthsTranslate(),p.initCalendarEvents(),n&&p.updateValue()),p.opened=!0,p.initialized=!0,p.params.onMonthAdd&&p.months.each(function(){p.params.onMonthAdd(p,this)}),p.params.onOpen&&p.params.onOpen(p)},p.close=function(){if(p.opened&&!p.inline)return p.animating=!1,o()?void t.closePicker(p.popover):void t.closePicker(p.container)},p.destroy=function(){p.close(),p.params.input&&p.input.length>0&&(p.input.off("click focus",c),p.input.data("calendar",null)),t("html").off("click",l)},p.inline&&p.open(),p},r=function(t){return t<10?"0"+t:t};t.fn.calendar=function(e,n){return e=e||{},this.each(function(){var i=t(this);if(i[0]){var o={};"INPUT"===i[0].tagName.toUpperCase()?o.input=i:o.container=i;var s=i.data("calendar");if(!s)if("string"==typeof e);else{if(!e.value&&i.val()&&(e.value=[i.val()]),!e.value){var c=new Date;e.value=[c.getFullYear()+"/"+r(c.getMonth()+1)+"/"+r(c.getDate())]}s=i.data("calendar",new a(t.extend(o,e)))}"string"==typeof e&&s[e].call(s,n)}})},e=t.fn.calendar.prototype.defaults={value:void 0,monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["周日","周一","周二","周三","周四","周五","周六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],firstDay:1,weekendDays:[0,6],multiple:!1,dateFormat:"yyyy/mm/dd",direction:"horizontal",minDate:null,maxDate:null,touchMove:!0,animate:!0,closeOnSelect:!0,monthPicker:!0,monthPickerTemplate:'<div class="picker-calendar-month-picker"><a href="javascript:;" class="link icon-only picker-calendar-prev-month"><i class="icon icon-prev"></i></a><div class="current-month-value"></div><a href="javascript:;" class="link icon-only picker-calendar-next-month"><i class="icon icon-next"></i></a></div>',yearPicker:!0,yearPickerTemplate:'<div class="picker-calendar-year-picker"><a href="javascript:;" class="link icon-only picker-calendar-prev-year"><i class="icon icon-prev"></i></a><span class="current-year-value"></span><a href="javascript:;" class="link icon-only picker-calendar-next-year"><i class="icon icon-next"></i></a></div>',weekHeader:!0,scrollToInput:!0,inputReadOnly:!0,convertToPopover:!0,onlyInPopover:!1,toolbar:!0,toolbarCloseText:"Done",toolbarTemplate:'<div class="toolbar"><div class="toolbar-inner">{{yearPicker}}{{monthPicker}}</div></div>'}}($),+function(t){"use strict";var e,n=function(t){return t<10?"0"+t:t},i=function(e,n){this.input=t(e),this.params=n||{},this.initMonthes=n.monthes,this.initYears=n.years;var i=t.extend({},n,this.getConfig());t(this.input).picker(i)};i.prototype={getDays:function(t){for(var e=[],n=1;n<=(t||31);n++)e.push(n<10?"0"+n:n);return e},getDaysByMonthAndYear:function(t,e){var n=new Date(e,parseInt(t)+1-1,1),i=new Date(n-1);return this.getDays(i.getDate())},getConfig:function(){var t,e=new Date,i=this.params,a=this,r={rotateEffect:!1,cssClass:"datetime-picker",value:[e.getFullYear(),n(e.getMonth()+1),n(e.getDate()),n(e.getHours()),n(e.getMinutes())],onChange:function(e,n,r){var o=(e.cols,a.getDaysByMonthAndYear(n[1],n[0])),s=n[2];s>o.length&&(s=o.length),e.cols[4].setValue(s);var c=new Date(n[0]+"-"+n[1]+"-"+n[2]),l=!0;if(i.min){var u=new Date("function"==typeof i.min?i.min():i.min);c<+u&&(e.setValue(t),l=!1)}if(i.max){var p=new Date("function"==typeof i.max?i.max():i.max);c>+p&&(e.setValue(t),l=!1)}l&&(t=n),a.params.onChange&&a.params.onChange.apply(this,arguments)},formatValue:function(t,e,n){return a.params.format(t,e,n)},cols:[{values:this.initYears},{divider:!0,content:i.yearSplit},{values:this.initMonthes},{divider:!0,content:i.monthSplit},{values:function(){for(var t=[],e=1;e<=31;e++)t.push(n(e));return t}()}]};i.dateSplit&&r.cols.push({divider:!0,content:i.dateSplit}),r.cols.push({divider:!0,content:i.datetimeSplit});var o=a.params.times();o&&o.length&&(r.cols=r.cols.concat(o));var s=this.input.val();return s&&(r.value=i.parse(s)),this.params.value&&(this.input.val(this.params.value),r.value=i.parse(this.params.value)),r}},t.fn.datetimePicker=function(n){return n=t.extend({},e,n),this.each(function(){if(this){var e=t(this),a=e.data("datetime");return a||e.data("datetime",new i(this,n)),a}})},e=t.fn.datetimePicker.prototype.defaults={input:void 0,min:void 0,max:void 0,yearSplit:"-",monthSplit:"-",dateSplit:"",datetimeSplit:" ",monthes:"01 02 03 04 05 06 07 08 09 10 11 12".split(" "),years:function(){for(var t=[],e=1950;e<=2030;e++)t.push(e);return t}(),times:function(){return[{values:function(){for(var t=[],e=0;e<24;e++)t.push(n(e));return t}()},{divider:!0,content:":"},{values:function(){for(var t=[],e=0;e<60;e++)t.push(n(e));return t}()}]},format:function(t,e){return t.cols.map(function(t){return t.value||t.content}).join("")},parse:function(t){var e=t.split(this.datetimeSplit);return e[0].split(/\D/).concat(e[1].split(/:|时|分|秒/)).filter(function(t){return!!t})}}}($),+function(t){"use strict";t.openPopup=function(e,n){t.closePopup(),e=t(e),e.show(),e.width(),e.addClass("weui-popup__container--visible");var i=e.find(".weui-popup__modal");i.width(),i.transitionEnd(function(){i.trigger("open")})},t.closePopup=function(e,n){e=t(e||".weui-popup__container--visible"),e.find(".weui-popup__modal").transitionEnd(function(){var i=t(this);i.trigger("close"),e.hide(),n&&e.remove()}),e.removeClass("weui-popup__container--visible")},t(document).on("click",".close-popup, .weui-popup__overlay",function(){t.closePopup()}).on("click",".open-popup",function(){t(t(this).data("target")).popup()}).on("click",".weui-popup__container",function(e){t(e.target).hasClass("weui-popup__container")&&t.closePopup()}),t.fn.popup=function(){return this.each(function(){t.openPopup(this)})}}($),+function(t){"use strict";var e,n,i,a,r,o,s=function(n){var i=t.getTouchPosition(n);a=i,r=o=0,e.addClass("touching")},c=function(n){if(!a)return!1;n.preventDefault(),n.stopPropagation();var i=t.getTouchPosition(n);r=i.x-a.x,o=i.y-a.y,o>0&&(o=Math.sqrt(o)),e.css("transform","translate3d(0, "+o+"px, 0)")},l=function(){e.removeClass("touching"),e.attr("style",""),o<0&&Math.abs(o)>.38*e.height()&&t.closeNotification(),Math.abs(r)<=1&&Math.abs(o)<=1&&e.trigger("noti-click"),a=!1},u=function(e){e.on(t.touchEvents.start,s),e.on(t.touchEvents.move,c),e.on(t.touchEvents.end,l)};t.notification=t.noti=function(a){a=t.extend({},n,a),e=t(".weui-notification"),e[0]||(e=t('<div class="weui-notification"></div>').appendTo(document.body),u(e)),e.off("noti-click"),a.onClick&&e.on("noti-click",function(){a.onClick(a.data)}),e.html(t.t7.compile(a.tpl)(a)),e.show(),e.addClass("weui-notification--in"),e.data("params",a);var r=function(){i&&(clearTimeout(i),i=null),i=setTimeout(function(){e.hasClass("weui-notification--touching")?r():t.closeNotification()},a.time)};r()},t.closeNotification=function(){i&&clearTimeout(i),i=null;var e=t(".weui-notification").removeClass("weui-notification--in").transitionEnd(function(){t(this).remove()});if(e[0]){var n=t(".weui-notification").data("params");n&&n.onClose&&n.onClose(n.data)}},n=t.noti.prototype.defaults={title:void 0,text:void 0,media:void 0,time:4e3,onClick:void 0,onClose:void 0,data:void 0,tpl:'<div class="weui-notification__inner">{{#if media}}<div class="weui-notification__media">{{media}}</div>{{/if}}<div class="weui-notification__content">{{#if title}}<div class="weui-notification__title">{{title}}</div>{{/if}}{{#if text}}<div class="weui-notification__text">{{text}}</div>{{/if}}</div><div class="weui-notification__handle-bar"></div></div>'}}($),+function(t){"use strict";var e;t.toptip=function(n,i,a){if(n){"string"==typeof i&&(a=i,i=void 0),i=i||3e3;var r=a?"bg-"+a:"bg-danger",o=t(".weui-toptips").remove();o=t('<div class="weui-toptips"></div>').appendTo(document.body),o.html(n),o[0].className="weui-toptips "+r,clearTimeout(e),o.hasClass("weui-toptips_visible")||(o.show().width(),o.addClass("weui-toptips_visible")),e=setTimeout(function(){o.removeClass("weui-toptips_visible").transitionEnd(function(){o.remove()})},i)}}}($),+function(t){"use strict";var e=function(e,n){this.container=t(e),this.handler=this.container.find(".weui-slider__handler"),this.track=this.container.find(".weui-slider__track"),this.value=this.container.find(".weui-slider-box__value"),this.bind(),"function"==typeof n&&(this.callback=n)};e.prototype.bind=function(){this.container.on(t.touchEvents.start,t.proxy(this.touchStart,this)).on(t.touchEvents.end,t.proxy(this.touchEnd,this)),t(document.body).on(t.touchEvents.move,t.proxy(this.touchMove,this))},e.prototype.touchStart=function(e){e.preventDefault(),this.start=t.getTouchPosition(e),this.width=this.container.find(".weui-slider__inner").width(),this.left=parseInt(this.container.find(".weui-slider__handler").css("left")),this.touching=!0},e.prototype.touchMove=function(e){if(!this.touching)return!0;var n=t.getTouchPosition(e),i=n.x-this.start.x,a=i+this.left,r=parseInt(a/this.width*100);r<0&&(r=0),r>100&&(r=100),this.handler.css("left",r+"%"),this.track.css("width",r+"%"),this.value.text(r),this.callback&&this.callback.call(this,r),this.container.trigger("change",r)},e.prototype.touchEnd=function(t){this.touching=!1},t.fn.slider=function(n){this.each(function(){var i=t(this),a=i.data("slider");return a?a:void i.data("slider",new e(this,n))})}}($),+function(t){"use strict";var e=[],n="swipeout-touching",i=function(n){this.container=t(n),this.mover=this.container.find(">.weui-cell__bd"),this.attachEvents(),e.push(this)};i.prototype.touchStart=function(e){var i=t.getTouchPosition(e);this.container.addClass(n),this.start=i,this.startX=0,this.startTime=+new Date;var a=this.mover.css("transform").match(/-?[\d\.]+/g);a&&a.length&&(this.startX=parseInt(a[4])),this.diffX=this.diffY=0,this._closeOthers(),this.limit=this.container.find(">.weui-cell__ft").width()||68},i.prototype.touchMove=function(e){if(!this.start)return!0;var n=t.getTouchPosition(e);if(this.diffX=n.x-this.start.x,this.diffY=n.y-this.start.y,Math.abs(this.diffX)<Math.abs(this.diffY))return this.close(),this.start=!1,!0;e.preventDefault(),e.stopPropagation();var i=this.diffX+this.startX;i>0&&(i=0),Math.abs(i)>this.limit&&(i=-(Math.pow(-(i+this.limit),.7)+this.limit)),this.mover.css("transform","translate3d("+i+"px, 0, 0)")},i.prototype.touchEnd=function(){if(!this.start)return!0;this.start=!1;var t=this.diffX+this.startX,e=new Date-this.startTime;this.diffX<-5&&e<200?this.open():this.diffX>=0&&e<200?this.close():t>0||-t<=this.limit/2?this.close():this.open()},i.prototype.close=function(){this.container.removeClass(n),this.mover.css("transform","translate3d(0, 0, 0)"),this.container.trigger("swipeout-close")},i.prototype.open=function(){this.container.removeClass(n),this._closeOthers(),this.mover.css("transform","translate3d("+-this.limit+"px, 0, 0)"),this.container.trigger("swipeout-open")},i.prototype.attachEvents=function(){var e=this.mover;e.on(t.touchEvents.start,t.proxy(this.touchStart,this)),e.on(t.touchEvents.move,t.proxy(this.touchMove,this)),e.on(t.touchEvents.end,t.proxy(this.touchEnd,this))},i.prototype._closeOthers=function(){var t=this;e.forEach(function(e){e!==t&&e.close()})};var a=function(t){return new i(t)};t.fn.swipeout=function(e){return this.each(function(){var n=t(this),i=n.data("swipeout")||a(this);n.data("swipeout",i),"string"==typeof e&&i[e]()})},t(".weui-cell_swiped").swipeout()}($);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/jquery.mobile-1.4.5.min.js b/platforms/android/app/src/main/assets/www/js/lib/jquery.mobile-1.4.5.min.js
new file mode 100755
index 0000000..5b1a9a1
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/jquery.mobile-1.4.5.min.js
@@ -0,0 +1,10 @@
+/*! jQuery Mobile 1.4.5 | Git HEADhash: 68e55e7 <> 2014-10-31T17:33:30Z | (c) 2010, 2014 jQuery Foundation, Inc. | jquery.org/license */
+
+!function(a,b,c){"function"==typeof define&&define.amd?define(["jquery"],function(d){return c(d,a,b),d.mobile}):c(a.jQuery,a,b)}(this,document,function(a,b,c){!function(a){a.mobile={}}(a),function(a,b){function d(b,c){var d,f,g,h=b.nodeName.toLowerCase();return"area"===h?(d=b.parentNode,f=d.name,b.href&&f&&"map"===d.nodeName.toLowerCase()?(g=a("img[usemap=#"+f+"]")[0],!!g&&e(g)):!1):(/input|select|textarea|button|object/.test(h)?!b.disabled:"a"===h?b.href||c:c)&&e(b)}function e(b){return a.expr.filters.visible(b)&&!a(b).parents().addBack().filter(function(){return"hidden"===a.css(this,"visibility")}).length}var f=0,g=/^ui-id-\d+$/;a.ui=a.ui||{},a.extend(a.ui,{version:"c0ab71056b936627e8a7821f03c044aec6280a40",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),a.fn.extend({focus:function(b){return function(c,d){return"number"==typeof c?this.each(function(){var b=this;setTimeout(function(){a(b).focus(),d&&d.call(b)},c)}):b.apply(this,arguments)}}(a.fn.focus),scrollParent:function(){var b;return b=a.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.css(this,"position"))&&/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(this[0].ownerDocument||c):b},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++f)})},removeUniqueId:function(){return this.each(function(){g.test(this.id)&&a(this).removeAttr("id")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return d(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var c=a.attr(b,"tabindex"),e=isNaN(c);return(e||c>=0)&&d(b,!e)}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function e(b,c,d,e){return a.each(f,function(){c-=parseFloat(a.css(b,"padding"+this))||0,d&&(c-=parseFloat(a.css(b,"border"+this+"Width"))||0),e&&(c-=parseFloat(a.css(b,"margin"+this))||0)}),c}var f="Width"===d?["Left","Right"]:["Top","Bottom"],g=d.toLowerCase(),h={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?h["inner"+d].call(this):this.each(function(){a(this).css(g,e(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return"number"!=typeof b?h["outer"+d].call(this,b):this.each(function(){a(this).css(g,e(this,b,!0,c)+"px")})}}),a.fn.addBack||(a.fn.addBack=function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}),a("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(a.fn.removeData=function(b){return function(c){return arguments.length?b.call(this,a.camelCase(c)):b.call(this)}}(a.fn.removeData)),a.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),a.support.selectstart="onselectstart"in c.createElement("div"),a.fn.extend({disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(d){if(d!==b)return this.css("zIndex",d);if(this.length)for(var e,f,g=a(this[0]);g.length&&g[0]!==c;){if(e=g.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(f=parseInt(g.css("zIndex"),10),!isNaN(f)&&0!==f))return f;g=g.parent()}return 0}}),a.ui.plugin={add:function(b,c,d){var e,f=a.ui[b].prototype;for(e in d)f.plugins[e]=f.plugins[e]||[],f.plugins[e].push([c,d[e]])},call:function(a,b,c,d){var e,f=a.plugins[b];if(f&&(d||a.element[0].parentNode&&11!==a.element[0].parentNode.nodeType))for(e=0;e<f.length;e++)a.options[f[e][0]]&&f[e][1].apply(a.element,c)}}}(a),function(a,b){var d=function(b,c){var d=b.parent(),e=[],f=function(){var b=a(this),c=a.mobile.toolbar&&b.data("mobile-toolbar")?b.toolbar("option"):{position:b.attr("data-"+a.mobile.ns+"position"),updatePagePadding:b.attr("data-"+a.mobile.ns+"update-page-padding")!==!1};return!("fixed"===c.position&&c.updatePagePadding===!0)},g=d.children(":jqmData(role='header')").filter(f),h=b.children(":jqmData(role='header')"),i=d.children(":jqmData(role='footer')").filter(f),j=b.children(":jqmData(role='footer')");return 0===h.length&&g.length>0&&(e=e.concat(g.toArray())),0===j.length&&i.length>0&&(e=e.concat(i.toArray())),a.each(e,function(b,d){c-=a(d).outerHeight()}),Math.max(0,c)};a.extend(a.mobile,{window:a(b),document:a(c),keyCode:a.ui.keyCode,behaviors:{},silentScroll:function(c){"number"!==a.type(c)&&(c=a.mobile.defaultHomeScroll),a.event.special.scrollstart.enabled=!1,setTimeout(function(){b.scrollTo(0,c),a.mobile.document.trigger("silentscroll",{x:0,y:c})},20),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},getClosestBaseUrl:function(b){var c=a(b).closest(".ui-page").jqmData("url"),d=a.mobile.path.documentBase.hrefNoHash;return a.mobile.dynamicBaseEnabled&&c&&a.mobile.path.isPath(c)||(c=d),a.mobile.path.makeUrlAbsolute(c,d)},removeActiveLinkClass:function(b){!a.mobile.activeClickedLink||a.mobile.activeClickedLink.closest("."+a.mobile.activePageClass).length&&!b||a.mobile.activeClickedLink.removeClass(a.mobile.activeBtnClass),a.mobile.activeClickedLink=null},getInheritedTheme:function(a,b){for(var c,d,e=a[0],f="",g=/ui-(bar|body|overlay)-([a-z])\b/;e&&(c=e.className||"",!(c&&(d=g.exec(c))&&(f=d[2])));)e=e.parentNode;return f||b||"a"},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;var d,e,f,g,h,i=b.length,j=a();for(g=0;i>g;g++){for(e=b.eq(g),f=!1,d=b[g];d;){if(h=d.getAttribute?d.getAttribute("data-"+a.mobile.ns+c):"","false"===h){f=!0;break}d=d.parentNode}f||(j=j.add(e))}return j},getScreenHeight:function(){return b.innerHeight||a.mobile.window.height()},resetActivePageHeight:function(b){var c=a("."+a.mobile.activePageClass),e=c.height(),f=c.outerHeight(!0);b=d(c,"number"==typeof b?b:a.mobile.getScreenHeight()),c.css("min-height",""),c.height()<b&&c.css("min-height",b-(f-e))},loading:function(){var b=this.loading._widget||a(a.mobile.loader.prototype.defaultHtml).loader(),c=b.loader.apply(b,arguments);return this.loading._widget=b,c}}),a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.fn.extend({removeWithDependents:function(){a.removeWithDependents(this)},enhanceWithin:function(){var b,c={},d=a.mobile.page.prototype.keepNativeSelector(),e=this;a.mobile.nojs&&a.mobile.nojs(this),a.mobile.links&&a.mobile.links(this),a.mobile.degradeInputsWithin&&a.mobile.degradeInputsWithin(this),a.fn.buttonMarkup&&this.find(a.fn.buttonMarkup.initSelector).not(d).jqmEnhanceable().buttonMarkup(),a.fn.fieldcontain&&this.find(":jqmData(role='fieldcontain')").not(d).jqmEnhanceable().fieldcontain(),a.each(a.mobile.widgets,function(b,f){if(f.initSelector){var g=a.mobile.enhanceable(e.find(f.initSelector));g.length>0&&(g=g.not(d)),g.length>0&&(c[f.prototype.widgetName]=g)}});for(b in c)c[b][b]();return this},addDependents:function(b){a.addDependents(this,b)},getEncodedText:function(){return a("<a>").text(this.text()).html()},jqmEnhanceable:function(){return a.mobile.enhanceable(this)},jqmHijackable:function(){return a.mobile.hijackable(this)}}),a.removeWithDependents=function(b){var c=a(b);(c.jqmData("dependents")||a()).remove(),c.remove()},a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.find.matches=function(b,c){return a.find(b,null,null,c)},a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}}(a,this),function(a){a.extend(a.mobile,{version:"1.4.5",subPageUrlKey:"ui-page",hideUrlBar:!0,keepNative:":jqmData(role='none'), :jqmData(role='nojs')",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:!0,hashListeningEnabled:!0,linkBindingEnabled:!0,defaultPageTransition:"fade",maxTransitionWidth:!1,minScrollBack:0,defaultDialogTransition:"pop",pageLoadErrorMessage:"Error Loading Page",pageLoadErrorMessageTheme:"a",phonegapNavigationEnabled:!1,autoInitializePage:!0,pushStateEnabled:!0,ignoreContentEnabled:!1,buttonMarkup:{hoverDelay:200},dynamicBaseEnabled:!0,pageContainer:a(),allowCrossDomainPages:!1,dialogHashKey:"&ui-state=dialog"})}(a,this),function(a,b){var c=0,d=Array.prototype.slice,e=a.cleanData;a.cleanData=function(b){for(var c,d=0;null!=(c=b[d]);d++)try{a(c).triggerHandler("remove")}catch(f){}e(b)},a.widget=function(b,c,d){var e,f,g,h,i={},j=b.split(".")[0];return b=b.split(".")[1],e=j+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][e.toLowerCase()]=function(b){return!!a.data(b,e)},a[j]=a[j]||{},f=a[j][b],g=a[j][b]=function(a,b){return this._createWidget?void(arguments.length&&this._createWidget(a,b)):new g(a,b)},a.extend(g,f,{version:d.version,_proto:a.extend({},d),_childConstructors:[]}),h=new c,h.options=a.widget.extend({},h.options),a.each(d,function(b,d){return a.isFunction(d)?void(i[b]=function(){var a=function(){return c.prototype[b].apply(this,arguments)},e=function(a){return c.prototype[b].apply(this,a)};return function(){var b,c=this._super,f=this._superApply;return this._super=a,this._superApply=e,b=d.apply(this,arguments),this._super=c,this._superApply=f,b}}()):void(i[b]=d)}),g.prototype=a.widget.extend(h,{widgetEventPrefix:f?h.widgetEventPrefix||b:b},i,{constructor:g,namespace:j,widgetName:b,widgetFullName:e}),f?(a.each(f._childConstructors,function(b,c){var d=c.prototype;a.widget(d.namespace+"."+d.widgetName,g,c._proto)}),delete f._childConstructors):c._childConstructors.push(g),a.widget.bridge(b,g),g},a.widget.extend=function(c){for(var e,f,g=d.call(arguments,1),h=0,i=g.length;i>h;h++)for(e in g[h])f=g[h][e],g[h].hasOwnProperty(e)&&f!==b&&(c[e]=a.isPlainObject(f)?a.isPlainObject(c[e])?a.widget.extend({},c[e],f):a.widget.extend({},f):f);return c},a.widget.bridge=function(c,e){var f=e.prototype.widgetFullName||c;a.fn[c]=function(g){var h="string"==typeof g,i=d.call(arguments,1),j=this;return g=!h&&i.length?a.widget.extend.apply(null,[g].concat(i)):g,this.each(h?function(){var d,e=a.data(this,f);return"instance"===g?(j=e,!1):e?a.isFunction(e[g])&&"_"!==g.charAt(0)?(d=e[g].apply(e,i),d!==e&&d!==b?(j=d&&d.jquery?j.pushStack(d.get()):d,!1):void 0):a.error("no such method '"+g+"' for "+c+" widget instance"):a.error("cannot call methods on "+c+" prior to initialization; attempted to call method '"+g+"'")}:function(){var b=a.data(this,f);b?b.option(g||{})._init():a.data(this,f,new e(g,this))}),j}},a.Widget=function(){},a.Widget._childConstructors=[],a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(b,d){d=a(d||this.defaultElement||this)[0],this.element=a(d),this.uuid=c++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=a.widget.extend({},this.options,this._getCreateOptions(),b),this.bindings=a(),this.hoverable=a(),this.focusable=a(),d!==this&&(a.data(d,this.widgetFullName,this),this._on(!0,this.element,{remove:function(a){a.target===d&&this.destroy()}}),this.document=a(d.style?d.ownerDocument:d.document||d),this.window=a(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:a.noop,_getCreateEventData:a.noop,_create:a.noop,_init:a.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(a.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:a.noop,widget:function(){return this.element},option:function(c,d){var e,f,g,h=c;if(0===arguments.length)return a.widget.extend({},this.options);if("string"==typeof c)if(h={},e=c.split("."),c=e.shift(),e.length){for(f=h[c]=a.widget.extend({},this.options[c]),g=0;g<e.length-1;g++)f[e[g]]=f[e[g]]||{},f=f[e[g]];if(c=e.pop(),d===b)return f[c]===b?null:f[c];f[c]=d}else{if(d===b)return this.options[c]===b?null:this.options[c];h[c]=d}return this._setOptions(h),this},_setOptions:function(a){var b;for(b in a)this._setOption(b,a[b]);return this},_setOption:function(a,b){return this.options[a]=b,"disabled"===a&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!b),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(b,c,d){var e,f=this;"boolean"!=typeof b&&(d=c,c=b,b=!1),d?(c=e=a(c),this.bindings=this.bindings.add(c)):(d=c,c=this.element,e=this.widget()),a.each(d,function(d,g){function h(){return b||f.options.disabled!==!0&&!a(this).hasClass("ui-state-disabled")?("string"==typeof g?f[g]:g).apply(f,arguments):void 0}"string"!=typeof g&&(h.guid=g.guid=g.guid||h.guid||a.guid++);var i=d.match(/^(\w+)\s*(.*)$/),j=i[1]+f.eventNamespace,k=i[2];k?e.delegate(k,j,h):c.bind(j,h)})},_off:function(a,b){b=(b||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,a.unbind(b).undelegate(b)},_delay:function(a,b){function c(){return("string"==typeof a?d[a]:a).apply(d,arguments)}var d=this;return setTimeout(c,b||0)},_hoverable:function(b){this.hoverable=this.hoverable.add(b),this._on(b,{mouseenter:function(b){a(b.currentTarget).addClass("ui-state-hover")},mouseleave:function(b){a(b.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(b){this.focusable=this.focusable.add(b),this._on(b,{focusin:function(b){a(b.currentTarget).addClass("ui-state-focus")},focusout:function(b){a(b.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(b,c,d){var e,f,g=this.options[b];if(d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.apply(this.element[0],[c].concat(d))===!1||c.isDefaultPrevented())}},a.each({show:"fadeIn",hide:"fadeOut"},function(b,c){a.Widget.prototype["_"+b]=function(d,e,f){"string"==typeof e&&(e={effect:e});var g,h=e?e===!0||"number"==typeof e?c:e.effect||c:b;e=e||{},"number"==typeof e&&(e={duration:e}),g=!a.isEmptyObject(e),e.complete=f,e.delay&&d.delay(e.delay),g&&a.effects&&a.effects.effect[h]?d[b](e):h!==b&&d[h]?d[h](e.duration,e.easing,f):d.queue(function(c){a(this)[b](),f&&f.call(d[0]),c()})}})}(a),function(a,b,c){var d={},e=a.find,f=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,g=/:jqmData\(([^)]*)\)/g;a.extend(a.mobile,{ns:"",getAttribute:function(b,c){var d;b=b.jquery?b[0]:b,b&&b.getAttribute&&(d=b.getAttribute("data-"+a.mobile.ns+c));try{d="true"===d?!0:"false"===d?!1:"null"===d?null:+d+""===d?+d:f.test(d)?JSON.parse(d):d}catch(e){}return d},nsNormalizeDict:d,nsNormalize:function(b){return d[b]||(d[b]=a.camelCase(a.mobile.ns+b))},closestPageData:function(a){return a.closest(":jqmData(role='page'), :jqmData(role='dialog')").data("mobile-page")}}),a.fn.jqmData=function(b,d){var e;return"undefined"!=typeof b&&(b&&(b=a.mobile.nsNormalize(b)),e=arguments.length<2||d===c?this.data(b):this.data(b,d)),e},a.jqmData=function(b,c,d){var e;return"undefined"!=typeof c&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,d)),e},a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))},a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))},a.find=function(b,c,d,f){return b.indexOf(":jqmData")>-1&&(b=b.replace(g,"[data-"+(a.mobile.ns||"")+"$1]")),e.call(this,b,c,d,f)},a.extend(a.find,e)}(a,this),function(a){var b=/[A-Z]/g,c=function(a){return"-"+a.toLowerCase()};a.extend(a.Widget.prototype,{_getCreateOptions:function(){var d,e,f=this.element[0],g={};if(!a.mobile.getAttribute(f,"defaults"))for(d in this.options)e=a.mobile.getAttribute(f,d.replace(b,c)),null!=e&&(g[d]=e);return g}}),a.mobile.widget=a.Widget}(a),function(a){var b="ui-loader",c=a("html");a.widget("mobile.loader",{options:{theme:"a",textVisible:!1,html:"",text:"loading"},defaultHtml:"<div class='"+b+"'><span class='ui-icon-loading'></span><h1></h1></div>",fakeFixLoader:function(){var b=a("."+a.mobile.activeBtnClass).first();this.element.css({top:a.support.scrollTop&&this.window.scrollTop()+this.window.height()/2||b.length&&b.offset().top||100})},checkLoaderPosition:function(){var b=this.element.offset(),c=this.window.scrollTop(),d=a.mobile.getScreenHeight();(b.top<c||b.top-c>d)&&(this.element.addClass("ui-loader-fakefix"),this.fakeFixLoader(),this.window.unbind("scroll",this.checkLoaderPosition).bind("scroll",a.proxy(this.fakeFixLoader,this)))},resetHtml:function(){this.element.html(a(this.defaultHtml).html())},show:function(d,e,f){var g,h,i;this.resetHtml(),"object"===a.type(d)?(i=a.extend({},this.options,d),d=i.theme):(i=this.options,d=d||i.theme),h=e||(i.text===!1?"":i.text),c.addClass("ui-loading"),g=i.textVisible,this.element.attr("class",b+" ui-corner-all ui-body-"+d+" ui-loader-"+(g||e||d.text?"verbose":"default")+(i.textonly||f?" ui-loader-textonly":"")),i.html?this.element.html(i.html):this.element.find("h1").text(h),this.element.appendTo(a(a.mobile.pagecontainer?":mobile-pagecontainer":"body")),this.checkLoaderPosition(),this.window.bind("scroll",a.proxy(this.checkLoaderPosition,this))},hide:function(){c.removeClass("ui-loading"),this.options.text&&this.element.removeClass("ui-loader-fakefix"),this.window.unbind("scroll",this.fakeFixLoader),this.window.unbind("scroll",this.checkLoaderPosition)}})}(a,this),function(a,b,d){"$:nomunge";function e(a){return a=a||location.href,"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var f,g="hashchange",h=c,i=a.event.special,j=h.documentMode,k="on"+g in b&&(j===d||j>7);a.fn[g]=function(a){return a?this.bind(g,a):this.trigger(g)},a.fn[g].delay=50,i[g]=a.extend(i[g],{setup:function(){return k?!1:void a(f.start)},teardown:function(){return k?!1:void a(f.stop)}}),f=function(){function c(){var d=e(),h=n(j);d!==j?(m(j=d,h),a(b).trigger(g)):h!==j&&(location.href=location.href.replace(/#.*/,"")+h),f=setTimeout(c,a.fn[g].delay)}var f,i={},j=e(),l=function(a){return a},m=l,n=l;return i.start=function(){f||c()},i.stop=function(){f&&clearTimeout(f),f=d},b.attachEvent&&!b.addEventListener&&!k&&function(){var b,d;i.start=function(){b||(d=a.fn[g].src,d=d&&d+e(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||m(e()),c()}).attr("src",d||"javascript:0").insertAfter("body")[0].contentWindow,h.onpropertychange=function(){try{"title"===event.propertyName&&(b.document.title=h.title)}catch(a){}})},i.stop=l,n=function(){return e(b.location.href)},m=function(c,d){var e=b.document,f=a.fn[g].domain;c!==d&&(e.title=h.title,e.open(),f&&e.write('<script>document.domain="'+f+'"</script>'),e.close(),b.location.hash=c)}}(),i}()}(a,this),function(a){b.matchMedia=b.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(c),a.mobile.media=function(a){return b.matchMedia(a).matches}}(a),function(a){var b={touch:"ontouchend"in c};a.mobile.support=a.mobile.support||{},a.extend(a.support,b),a.extend(a.mobile.support,b)}(a),function(a){a.extend(a.support,{orientation:"orientation"in b&&"onorientationchange"in b})}(a),function(a,d){function e(a){var b,c=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(c+" ")+c).split(" ");for(b in e)if(n[e[b]]!==d)return!0}function f(){var c=b,d=!(!c.document.createElementNS||!c.document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||c.opera&&-1===navigator.userAgent.indexOf("Chrome")),e=function(b){b&&d||a("html").addClass("ui-nosvg")},f=new c.Image;f.onerror=function(){e(!1)},f.onload=function(){e(1===f.width&&1===f.height)},f.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="}function g(){var e,f,g,h="transform-3d",i=a.mobile.media("(-"+o.join("-"+h+"),(-")+"-"+h+"),("+h+")");if(i)return!!i;e=c.createElement("div"),f={MozTransform:"-moz-transform",transform:"transform"},m.append(e);for(g in f)e.style[g]!==d&&(e.style[g]="translate3d( 100px, 1px, 1px )",i=b.getComputedStyle(e).getPropertyValue(f[g]));return!!i&&"none"!==i}function h(){var b,c,d=location.protocol+"//"+location.host+location.pathname+"ui-dir/",e=a("head base"),f=null,g="";return e.length?g=e.attr("href"):e=f=a("<base>",{href:d}).appendTo("head"),b=a("<a href='testurl' />").prependTo(m),c=b[0].href,e[0].href=g||location.pathname,f&&f.remove(),0===c.indexOf(d)}function i(){var a,d=c.createElement("x"),e=c.documentElement,f=b.getComputedStyle;return"pointerEvents"in d.style?(d.style.pointerEvents="auto",d.style.pointerEvents="x",e.appendChild(d),a=f&&"auto"===f(d,"").pointerEvents,e.removeChild(d),!!a):!1}function j(){var a=c.createElement("div");return"undefined"!=typeof a.getBoundingClientRect}function k(){var a=b,c=navigator.userAgent,d=navigator.platform,e=c.match(/AppleWebKit\/([0-9]+)/),f=!!e&&e[1],g=c.match(/Fennec\/([0-9]+)/),h=!!g&&g[1],i=c.match(/Opera Mobi\/([0-9]+)/),j=!!i&&i[1];return(d.indexOf("iPhone")>-1||d.indexOf("iPad")>-1||d.indexOf("iPod")>-1)&&f&&534>f||a.operamini&&"[object OperaMini]"==={}.toString.call(a.operamini)||i&&7458>j||c.indexOf("Android")>-1&&f&&533>f||h&&6>h||"palmGetResource"in b&&f&&534>f||c.indexOf("MeeGo")>-1&&c.indexOf("NokiaBrowser/8.5.0")>-1?!1:!0}var l,m=a("<body>").prependTo("html"),n=m[0].style,o=["Webkit","Moz","O"],p="palmGetResource"in b,q=b.operamini&&"[object OperaMini]"==={}.toString.call(b.operamini),r=b.blackberry&&!e("-webkit-transform");a.extend(a.mobile,{browser:{}}),a.mobile.browser.oldIE=function(){var a=3,b=c.createElement("div"),d=b.all||[];do b.innerHTML="<!--[if gt IE "+ ++a+"]><br><![endif]-->";while(d[0]);return a>4?a:!a}(),a.extend(a.support,{pushState:"pushState"in history&&"replaceState"in history&&!(b.navigator.userAgent.indexOf("Firefox")>=0&&b.top!==b)&&-1===b.navigator.userAgent.search(/CriOS/),mediaquery:a.mobile.media("only all"),cssPseudoElement:!!e("content"),touchOverflow:!!e("overflowScrolling"),cssTransform3d:g(),boxShadow:!!e("boxShadow")&&!r,fixedPosition:k(),scrollTop:("pageXOffset"in b||"scrollTop"in c.documentElement||"scrollTop"in m[0])&&!p&&!q,dynamicBaseTag:h(),cssPointerEvents:i(),boundingRect:j(),inlineSVG:f}),m.remove(),l=function(){var a=b.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")>-1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}(),a.mobile.gradeA=function(){return(a.support.mediaquery&&a.support.cssPseudoElement||a.mobile.browser.oldIE&&a.mobile.browser.oldIE>=8)&&(a.support.boundingRect||null!==a.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/))},a.mobile.ajaxBlacklist=b.blackberry&&!b.WebKitPoint||q||l,l&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")}),a.support.boxShadow||a("html").addClass("ui-noboxshadow")}(a),function(a,b){var c,d=a.mobile.window,e=function(){};a.event.special.beforenavigate={setup:function(){d.on("navigate",e)},teardown:function(){d.off("navigate",e)}},a.event.special.navigate=c={bound:!1,pushStateEnabled:!0,originalEventName:b,isPushStateEnabled:function(){return a.support.pushState&&a.mobile.pushStateEnabled===!0&&this.isHashChangeEnabled()},isHashChangeEnabled:function(){return a.mobile.hashListeningEnabled===!0},popstate:function(b){var c=new a.Event("navigate"),e=new a.Event("beforenavigate"),f=b.originalEvent.state||{};e.originalEvent=b,d.trigger(e),e.isDefaultPrevented()||(b.historyState&&a.extend(f,b.historyState),c.originalEvent=b,setTimeout(function(){d.trigger(c,{state:f})},0))},hashchange:function(b){var c=new a.Event("navigate"),e=new a.Event("beforenavigate");e.originalEvent=b,d.trigger(e),e.isDefaultPrevented()||(c.originalEvent=b,d.trigger(c,{state:b.hashchangeState||{}}))},setup:function(){c.bound||(c.bound=!0,c.isPushStateEnabled()?(c.originalEventName="popstate",d.bind("popstate.navigate",c.popstate)):c.isHashChangeEnabled()&&(c.originalEventName="hashchange",d.bind("hashchange.navigate",c.hashchange)))}}}(a),function(a,c){var d,e,f="&ui-state=dialog";a.mobile.path=d={uiStateKey:"&ui-state",urlParseRE:/^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,getLocation:function(a){var b=this.parseUrl(a||location.href),c=a?b:location,d=b.hash;return d="#"===d?"":d,c.protocol+b.doubleSlash+c.host+(""!==c.protocol&&"/"!==c.pathname.substring(0,1)?"/":"")+c.pathname+c.search+d},getDocumentUrl:function(b){return b?a.extend({},d.documentUrl):d.documentUrl.href},parseLocation:function(){return this.parseUrl(this.getLocation())},parseUrl:function(b){if("object"===a.type(b))return b;var c=d.urlParseRE.exec(b||"")||[];return{href:c[0]||"",hrefNoHash:c[1]||"",hrefNoSearch:c[2]||"",domain:c[3]||"",protocol:c[4]||"",doubleSlash:c[5]||"",authority:c[6]||"",username:c[8]||"",password:c[9]||"",host:c[10]||"",hostname:c[11]||"",port:c[12]||"",pathname:c[13]||"",directory:c[14]||"",filename:c[15]||"",search:c[16]||"",hash:c[17]||""}},makePathAbsolute:function(a,b){var c,d,e,f;if(a&&"/"===a.charAt(0))return a;for(a=a||"",b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"",c=b?b.split("/"):[],d=a.split("/"),e=0;e<d.length;e++)switch(f=d[e]){case".":break;case"..":c.length&&c.pop();break;default:c.push(f)}return"/"+c.join("/")},isSameDomain:function(a,b){return d.parseUrl(a).domain.toLowerCase()===d.parseUrl(b).domain.toLowerCase()},isRelativeUrl:function(a){return""===d.parseUrl(a).protocol},isAbsoluteUrl:function(a){return""!==d.parseUrl(a).protocol},makeUrlAbsolute:function(a,b){if(!d.isRelativeUrl(a))return a;b===c&&(b=this.documentBase);var e=d.parseUrl(a),f=d.parseUrl(b),g=e.protocol||f.protocol,h=e.protocol?e.doubleSlash:e.doubleSlash||f.doubleSlash,i=e.authority||f.authority,j=""!==e.pathname,k=d.makePathAbsolute(e.pathname||f.filename,f.pathname),l=e.search||!j&&f.search||"",m=e.hash;return g+h+i+k+l+m},addSearchParams:function(b,c){var e=d.parseUrl(b),f="object"==typeof c?a.param(c):c,g=e.search||"?";return e.hrefNoSearch+g+("?"!==g.charAt(g.length-1)?"&":"")+f+(e.hash||"")},convertUrlToDataUrl:function(a){var c=a,e=d.parseUrl(a);return d.isEmbeddedPage(e)?c=e.hash.split(f)[0].replace(/^#/,"").replace(/\?.*$/,""):d.isSameDomain(e,this.documentBase)&&(c=e.hrefNoHash.replace(this.documentBase.domain,"").split(f)[0]),b.decodeURIComponent(c)},get:function(a){return a===c&&(a=d.parseLocation().hash),d.stripHash(a).replace(/[^\/]*\.[^\/*]+$/,"")},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(this.documentBase.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},stripQueryParams:function(a){return a.replace(/\?.*$/,"")},cleanHash:function(a){return d.stripHash(a.replace(/\?.*$/,"").replace(f,""))},isHashValid:function(a){return/^#[^#]+$/.test(a)},isExternal:function(a){var b=d.parseUrl(a);return!(!b.protocol||b.domain.toLowerCase()===this.documentUrl.domain.toLowerCase())},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isEmbeddedPage:function(a){var b=d.parseUrl(a);return""!==b.protocol?!this.isPath(b.hash)&&b.hash&&(b.hrefNoHash===this.documentUrl.hrefNoHash||this.documentBaseDiffers&&b.hrefNoHash===this.documentBase.hrefNoHash):/^#/.test(b.href)},squash:function(a,b){var c,e,f,g,h,i=this.isPath(a),j=this.parseUrl(a),k=j.hash,l="";return b||(i?b=d.getLocation():(h=d.getDocumentUrl(!0),b=d.isPath(h.hash)?d.squash(h.href):h.href)),e=i?d.stripHash(a):a,e=d.isPath(j.hash)?d.stripHash(j.hash):e,g=e.indexOf(this.uiStateKey),g>-1&&(l=e.slice(g),e=e.slice(0,g)),c=d.makeUrlAbsolute(e,b),f=this.parseUrl(c).search,i?((d.isPath(k)||0===k.replace("#","").indexOf(this.uiStateKey))&&(k=""),l&&-1===k.indexOf(this.uiStateKey)&&(k+=l),-1===k.indexOf("#")&&""!==k&&(k="#"+k),c=d.parseUrl(c),c=c.protocol+c.doubleSlash+c.host+c.pathname+f+k):c+=c.indexOf("#")>-1?l:"#"+l,c},isPreservableHash:function(a){return 0===a.replace("#","").indexOf(this.uiStateKey)},hashToSelector:function(a){var b="#"===a.substring(0,1);return b&&(a=a.substring(1)),(b?"#":"")+a.replace(/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,"\\$1")},getFilePath:function(a){return a&&a.split(f)[0]},isFirstPageUrl:function(b){var e=d.parseUrl(d.makeUrlAbsolute(b,this.documentBase)),f=e.hrefNoHash===this.documentUrl.hrefNoHash||this.documentBaseDiffers&&e.hrefNoHash===this.documentBase.hrefNoHash,g=a.mobile.firstPage,h=g&&g[0]?g[0].id:c;return f&&(!e.hash||"#"===e.hash||h&&e.hash.replace(/^#/,"")===h)},isPermittedCrossDomainRequest:function(b,c){return a.mobile.allowCrossDomainPages&&("file:"===b.protocol||"content:"===b.protocol)&&-1!==c.search(/^https?:/)}},d.documentUrl=d.parseLocation(),e=a("head").find("base"),d.documentBase=e.length?d.parseUrl(d.makeUrlAbsolute(e.attr("href"),d.documentUrl.href)):d.documentUrl,d.documentBaseDiffers=d.documentUrl.hrefNoHash!==d.documentBase.hrefNoHash,d.getDocumentBase=function(b){return b?a.extend({},d.documentBase):d.documentBase.href},a.extend(a.mobile,{getDocumentUrl:d.getDocumentUrl,getDocumentBase:d.getDocumentBase})}(a),function(a,b){a.mobile.History=function(a,b){this.stack=a||[],this.activeIndex=b||0},a.extend(a.mobile.History.prototype,{getActive:function(){return this.stack[this.activeIndex]},getLast:function(){return this.stack[this.previousIndex]},getNext:function(){return this.stack[this.activeIndex+1]},getPrev:function(){return this.stack[this.activeIndex-1]},add:function(a,b){b=b||{},this.getNext()&&this.clearForward(),b.hash&&-1===b.hash.indexOf("#")&&(b.hash="#"+b.hash),b.url=a,this.stack.push(b),this.activeIndex=this.stack.length-1},clearForward:function(){this.stack=this.stack.slice(0,this.activeIndex+1)},find:function(a,b,c){b=b||this.stack;var d,e,f,g=b.length;for(e=0;g>e;e++)if(d=b[e],(decodeURIComponent(a)===decodeURIComponent(d.url)||decodeURIComponent(a)===decodeURIComponent(d.hash))&&(f=e,c))return f;return f},closest:function(a){var c,d=this.activeIndex;return c=this.find(a,this.stack.slice(0,d)),c===b&&(c=this.find(a,this.stack.slice(d),!0),c=c===b?c:c+d),c},direct:function(c){var d=this.closest(c.url),e=this.activeIndex;d!==b&&(this.activeIndex=d,this.previousIndex=e),e>d?(c.present||c.back||a.noop)(this.getActive(),"back"):d>e?(c.present||c.forward||a.noop)(this.getActive(),"forward"):d===b&&c.missing&&c.missing(this.getActive())}})}(a),function(a){var d=a.mobile.path,e=location.href;a.mobile.Navigator=function(b){this.history=b,this.ignoreInitialHashChange=!0,a.mobile.window.bind({"popstate.history":a.proxy(this.popstate,this),"hashchange.history":a.proxy(this.hashchange,this)})},a.extend(a.mobile.Navigator.prototype,{squash:function(e,f){var g,h,i=d.isPath(e)?d.stripHash(e):e;return h=d.squash(e),g=a.extend({hash:i,url:h},f),b.history.replaceState(g,g.title||c.title,h),g},hash:function(a,b){var c,e,f,g;return c=d.parseUrl(a),e=d.parseLocation(),e.pathname+e.search===c.pathname+c.search?f=c.hash?c.hash:c.pathname+c.search:d.isPath(a)?(g=d.parseUrl(b),f=g.pathname+g.search+(d.isPreservableHash(g.hash)?g.hash.replace("#",""):"")):f=a,f},go:function(e,f,g){var h,i,j,k,l=a.event.special.navigate.isPushStateEnabled();
+i=d.squash(e),j=this.hash(e,i),g&&j!==d.stripHash(d.parseLocation().hash)&&(this.preventNextHashChange=g),this.preventHashAssignPopState=!0,b.location.hash=j,this.preventHashAssignPopState=!1,h=a.extend({url:i,hash:j,title:c.title},f),l&&(k=new a.Event("popstate"),k.originalEvent={type:"popstate",state:null},this.squash(e,h),g||(this.ignorePopState=!0,a.mobile.window.trigger(k))),this.history.add(h.url,h)},popstate:function(b){var c,f;if(a.event.special.navigate.isPushStateEnabled())return this.preventHashAssignPopState?(this.preventHashAssignPopState=!1,void b.stopImmediatePropagation()):this.ignorePopState?void(this.ignorePopState=!1):!b.originalEvent.state&&1===this.history.stack.length&&this.ignoreInitialHashChange&&(this.ignoreInitialHashChange=!1,location.href===e)?void b.preventDefault():(c=d.parseLocation().hash,!b.originalEvent.state&&c?(f=this.squash(c),this.history.add(f.url,f),void(b.historyState=f)):void this.history.direct({url:(b.originalEvent.state||{}).url||c,present:function(c,d){b.historyState=a.extend({},c),b.historyState.direction=d}}))},hashchange:function(b){var e,f;if(a.event.special.navigate.isHashChangeEnabled()&&!a.event.special.navigate.isPushStateEnabled()){if(this.preventNextHashChange)return this.preventNextHashChange=!1,void b.stopImmediatePropagation();e=this.history,f=d.parseLocation().hash,this.history.direct({url:f,present:function(c,d){b.hashchangeState=a.extend({},c),b.hashchangeState.direction=d},missing:function(){e.add(f,{hash:f,title:c.title})}})}}})}(a),function(a){a.mobile.navigate=function(b,c,d){a.mobile.navigate.navigator.go(b,c,d)},a.mobile.navigate.history=new a.mobile.History,a.mobile.navigate.navigator=new a.mobile.Navigator(a.mobile.navigate.history);var b=a.mobile.path.parseLocation();a.mobile.navigate.history.add(b.href,{hash:b.hash})}(a),function(a,b){var d={animation:{},transition:{}},e=c.createElement("a"),f=["","webkit-","moz-","o-"];a.each(["animation","transition"],function(c,g){var h=0===c?g+"-name":g;a.each(f,function(c,f){return e.style[a.camelCase(f+h)]!==b?(d[g].prefix=f,!1):void 0}),d[g].duration=a.camelCase(d[g].prefix+g+"-duration"),d[g].event=a.camelCase(d[g].prefix+g+"-end"),""===d[g].prefix&&(d[g].event=d[g].event.toLowerCase())}),a.support.cssTransitions=d.transition.prefix!==b,a.support.cssAnimations=d.animation.prefix!==b,a(e).remove(),a.fn.animationComplete=function(e,f,g){var h,i,j=this,k=function(){clearTimeout(h),e.apply(this,arguments)},l=f&&"animation"!==f?"transition":"animation";return a.support.cssTransitions&&"transition"===l||a.support.cssAnimations&&"animation"===l?(g===b&&(a(this).context!==c&&(i=3e3*parseFloat(a(this).css(d[l].duration))),(0===i||i===b||isNaN(i))&&(i=a.fn.animationComplete.defaultDuration)),h=setTimeout(function(){a(j).off(d[l].event,k),e.apply(j)},i),a(this).one(d[l].event,k)):(setTimeout(a.proxy(e,this),0),a(this))},a.fn.animationComplete.defaultDuration=1e3}(a),function(a,b,c,d){function e(a){for(;a&&"undefined"!=typeof a.originalEvent;)a=a.originalEvent;return a}function f(b,c){var f,g,h,i,j,k,l,m,n,o=b.type;if(b=a.Event(b),b.type=c,f=b.originalEvent,g=a.event.props,o.search(/^(mouse|click)/)>-1&&(g=E),f)for(l=g.length,i;l;)i=g[--l],b[i]=f[i];if(o.search(/mouse(down|up)|click/)>-1&&!b.which&&(b.which=1),-1!==o.search(/^touch/)&&(h=e(f),o=h.touches,j=h.changedTouches,k=o&&o.length?o[0]:j&&j.length?j[0]:d))for(m=0,n=C.length;n>m;m++)i=C[m],b[i]=k[i];return b}function g(b){for(var c,d,e={};b;){c=a.data(b,z);for(d in c)c[d]&&(e[d]=e.hasVirtualBinding=!0);b=b.parentNode}return e}function h(b,c){for(var d;b;){if(d=a.data(b,z),d&&(!c||d[c]))return b;b=b.parentNode}return null}function i(){M=!1}function j(){M=!0}function k(){Q=0,K.length=0,L=!1,j()}function l(){i()}function m(){n(),G=setTimeout(function(){G=0,k()},a.vmouse.resetTimerDuration)}function n(){G&&(clearTimeout(G),G=0)}function o(b,c,d){var e;return(d&&d[b]||!d&&h(c.target,b))&&(e=f(c,b),a(c.target).trigger(e)),e}function p(b){var c,d=a.data(b.target,A);L||Q&&Q===d||(c=o("v"+b.type,b),c&&(c.isDefaultPrevented()&&b.preventDefault(),c.isPropagationStopped()&&b.stopPropagation(),c.isImmediatePropagationStopped()&&b.stopImmediatePropagation()))}function q(b){var c,d,f,h=e(b).touches;h&&1===h.length&&(c=b.target,d=g(c),d.hasVirtualBinding&&(Q=P++,a.data(c,A,Q),n(),l(),J=!1,f=e(b).touches[0],H=f.pageX,I=f.pageY,o("vmouseover",b,d),o("vmousedown",b,d)))}function r(a){M||(J||o("vmousecancel",a,g(a.target)),J=!0,m())}function s(b){if(!M){var c=e(b).touches[0],d=J,f=a.vmouse.moveDistanceThreshold,h=g(b.target);J=J||Math.abs(c.pageX-H)>f||Math.abs(c.pageY-I)>f,J&&!d&&o("vmousecancel",b,h),o("vmousemove",b,h),m()}}function t(a){if(!M){j();var b,c,d=g(a.target);o("vmouseup",a,d),J||(b=o("vclick",a,d),b&&b.isDefaultPrevented()&&(c=e(a).changedTouches[0],K.push({touchID:Q,x:c.clientX,y:c.clientY}),L=!0)),o("vmouseout",a,d),J=!1,m()}}function u(b){var c,d=a.data(b,z);if(d)for(c in d)if(d[c])return!0;return!1}function v(){}function w(b){var c=b.substr(1);return{setup:function(){u(this)||a.data(this,z,{});var d=a.data(this,z);d[b]=!0,F[b]=(F[b]||0)+1,1===F[b]&&O.bind(c,p),a(this).bind(c,v),N&&(F.touchstart=(F.touchstart||0)+1,1===F.touchstart&&O.bind("touchstart",q).bind("touchend",t).bind("touchmove",s).bind("scroll",r))},teardown:function(){--F[b],F[b]||O.unbind(c,p),N&&(--F.touchstart,F.touchstart||O.unbind("touchstart",q).unbind("touchmove",s).unbind("touchend",t).unbind("scroll",r));var d=a(this),e=a.data(this,z);e&&(e[b]=!1),d.unbind(c,v),u(this)||d.removeData(z)}}}var x,y,z="virtualMouseBindings",A="virtualTouchID",B="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),C="clientX clientY pageX pageY screenX screenY".split(" "),D=a.event.mouseHooks?a.event.mouseHooks.props:[],E=a.event.props.concat(D),F={},G=0,H=0,I=0,J=!1,K=[],L=!1,M=!1,N="addEventListener"in c,O=a(c),P=1,Q=0;for(a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500},y=0;y<B.length;y++)a.event.special[B[y]]=w(B[y]);N&&c.addEventListener("click",function(b){var c,d,e,f,g,h,i=K.length,j=b.target;if(i)for(c=b.clientX,d=b.clientY,x=a.vmouse.clickDistanceThreshold,e=j;e;){for(f=0;i>f;f++)if(g=K[f],h=0,e===j&&Math.abs(g.x-c)<x&&Math.abs(g.y-d)<x||a.data(e,A)===g.touchID)return b.preventDefault(),void b.stopPropagation();e=e.parentNode}},!0)}(a,b,c),function(a,b,d){function e(b,c,e,f){var g=e.type;e.type=c,f?a.event.trigger(e,d,b):a.event.dispatch.call(b,e),e.type=g}var f=a(c),g=a.mobile.support.touch,h="touchmove scroll",i=g?"touchstart":"mousedown",j=g?"touchend":"mouseup",k=g?"touchmove":"mousemove";a.each("touchstart touchmove touchend tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(b,c){a.fn[c]=function(a){return a?this.bind(c,a):this.trigger(c)},a.attrFn&&(a.attrFn[c]=!0)}),a.event.special.scrollstart={enabled:!0,setup:function(){function b(a,b){c=b,e(f,c?"scrollstart":"scrollstop",a)}var c,d,f=this,g=a(f);g.bind(h,function(e){a.event.special.scrollstart.enabled&&(c||b(e,!0),clearTimeout(d),d=setTimeout(function(){b(e,!1)},50))})},teardown:function(){a(this).unbind(h)}},a.event.special.tap={tapholdThreshold:750,emitTapOnTaphold:!0,setup:function(){var b=this,c=a(b),d=!1;c.bind("vmousedown",function(g){function h(){clearTimeout(k)}function i(){h(),c.unbind("vclick",j).unbind("vmouseup",h),f.unbind("vmousecancel",i)}function j(a){i(),d||l!==a.target?d&&a.preventDefault():e(b,"tap",a)}if(d=!1,g.which&&1!==g.which)return!1;var k,l=g.target;c.bind("vmouseup",h).bind("vclick",j),f.bind("vmousecancel",i),k=setTimeout(function(){a.event.special.tap.emitTapOnTaphold||(d=!0),e(b,"taphold",a.Event("taphold",{target:l}))},a.event.special.tap.tapholdThreshold)})},teardown:function(){a(this).unbind("vmousedown").unbind("vclick").unbind("vmouseup"),f.unbind("vmousecancel")}},a.event.special.swipe={scrollSupressionThreshold:30,durationThreshold:1e3,horizontalDistanceThreshold:30,verticalDistanceThreshold:30,getLocation:function(a){var c=b.pageXOffset,d=b.pageYOffset,e=a.clientX,f=a.clientY;return 0===a.pageY&&Math.floor(f)>Math.floor(a.pageY)||0===a.pageX&&Math.floor(e)>Math.floor(a.pageX)?(e-=c,f-=d):(f<a.pageY-d||e<a.pageX-c)&&(e=a.pageX-c,f=a.pageY-d),{x:e,y:f}},start:function(b){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b,d=a.event.special.swipe.getLocation(c);return{time:(new Date).getTime(),coords:[d.x,d.y],origin:a(b.target)}},stop:function(b){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b,d=a.event.special.swipe.getLocation(c);return{time:(new Date).getTime(),coords:[d.x,d.y]}},handleSwipe:function(b,c,d,f){if(c.time-b.time<a.event.special.swipe.durationThreshold&&Math.abs(b.coords[0]-c.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(b.coords[1]-c.coords[1])<a.event.special.swipe.verticalDistanceThreshold){var g=b.coords[0]>c.coords[0]?"swipeleft":"swiperight";return e(d,"swipe",a.Event("swipe",{target:f,swipestart:b,swipestop:c}),!0),e(d,g,a.Event(g,{target:f,swipestart:b,swipestop:c}),!0),!0}return!1},eventInProgress:!1,setup:function(){var b,c=this,d=a(c),e={};b=a.data(this,"mobile-events"),b||(b={length:0},a.data(this,"mobile-events",b)),b.length++,b.swipe=e,e.start=function(b){if(!a.event.special.swipe.eventInProgress){a.event.special.swipe.eventInProgress=!0;var d,g=a.event.special.swipe.start(b),h=b.target,i=!1;e.move=function(b){g&&!b.isDefaultPrevented()&&(d=a.event.special.swipe.stop(b),i||(i=a.event.special.swipe.handleSwipe(g,d,c,h),i&&(a.event.special.swipe.eventInProgress=!1)),Math.abs(g.coords[0]-d.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault())},e.stop=function(){i=!0,a.event.special.swipe.eventInProgress=!1,f.off(k,e.move),e.move=null},f.on(k,e.move).one(j,e.stop)}},d.on(i,e.start)},teardown:function(){var b,c;b=a.data(this,"mobile-events"),b&&(c=b.swipe,delete b.swipe,b.length--,0===b.length&&a.removeData(this,"mobile-events")),c&&(c.start&&a(this).off(i,c.start),c.move&&f.off(k,c.move),c.stop&&f.off(j,c.stop))}},a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe.left",swiperight:"swipe.right"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)},teardown:function(){a(this).unbind(c)}}})}(a,this),function(a){a.event.special.throttledresize={setup:function(){a(this).bind("resize",f)},teardown:function(){a(this).unbind("resize",f)}};var b,c,d,e=250,f=function(){c=(new Date).getTime(),d=c-g,d>=e?(g=c,a(this).trigger("throttledresize")):(b&&clearTimeout(b),b=setTimeout(f,e-d))},g=0}(a),function(a,b){function d(){var a=e();a!==f&&(f=a,l.trigger(m))}var e,f,g,h,i,j,k,l=a(b),m="orientationchange",n={0:!0,180:!0};a.support.orientation&&(i=b.innerWidth||l.width(),j=b.innerHeight||l.height(),k=50,g=i>j&&i-j>k,h=n[b.orientation],(g&&h||!g&&!h)&&(n={"-90":!0,90:!0})),a.event.special.orientationchange=a.extend({},a.event.special.orientationchange,{setup:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:(f=e(),void l.bind("throttledresize",d))},teardown:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:void l.unbind("throttledresize",d)},add:function(a){var b=a.handler;a.handler=function(a){return a.orientation=e(),b.apply(this,arguments)}}}),a.event.special.orientationchange.orientation=e=function(){var d=!0,e=c.documentElement;return d=a.support.orientation?n[b.orientation]:e&&e.clientWidth/e.clientHeight<1.1,d?"portrait":"landscape"},a.fn[m]=function(a){return a?this.bind(m,a):this.trigger(m)},a.attrFn&&(a.attrFn[m]=!0)}(a,this),function(a){var b=a("head").children("base"),c={element:b.length?b:a("<base>",{href:a.mobile.path.documentBase.hrefNoHash}).prependTo(a("head")),linkSelector:"[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]",set:function(b){a.mobile.dynamicBaseEnabled&&a.support.dynamicBaseTag&&c.element.attr("href",a.mobile.path.makeUrlAbsolute(b,a.mobile.path.documentBase))},rewrite:function(b,d){var e=a.mobile.path.get(b);d.find(c.linkSelector).each(function(b,c){var d=a(c).is("[href]")?"href":a(c).is("[src]")?"src":"action",f=a.mobile.path.parseLocation(),g=a(c).attr(d);g=g.replace(f.protocol+f.doubleSlash+f.host+f.pathname,""),/^(\w+:|#|\/)/.test(g)||a(c).attr(d,e+g)})},reset:function(){c.element.attr("href",a.mobile.path.documentBase.hrefNoSearch)}};a.mobile.base=c}(a),function(a,b){a.mobile.widgets={};var c=a.widget,d=a.mobile.keepNative;a.widget=function(c){return function(){var d=c.apply(this,arguments),e=d.prototype.widgetName;return d.initSelector=d.prototype.initSelector!==b?d.prototype.initSelector:":jqmData(role='"+e+"')",a.mobile.widgets[e]=d,d}}(a.widget),a.extend(a.widget,c),a.mobile.document.on("create",function(b){a(b.target).enhanceWithin()}),a.widget("mobile.page",{options:{theme:"a",domCache:!1,keepNativeDefault:a.mobile.keepNative,contentTheme:null,enhanced:!1},_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments),this._trigger("init")},_create:function(){return this._trigger("beforecreate")===!1?!1:(this.options.enhanced||this._enhance(),this._on(this.element,{pagebeforehide:"removeContainerBackground",pagebeforeshow:"_handlePageBeforeShow"}),this.element.enhanceWithin(),void("dialog"===a.mobile.getAttribute(this.element[0],"role")&&a.mobile.dialog&&this.element.dialog()))},_enhance:function(){var c="data-"+a.mobile.ns,d=this;this.options.role&&this.element.attr("data-"+a.mobile.ns+"role",this.options.role),this.element.attr("tabindex","0").addClass("ui-page ui-page-theme-"+this.options.theme),this.element.find("["+c+"role='content']").each(function(){var e=a(this),f=this.getAttribute(c+"theme")||b;d.options.contentTheme=f||d.options.contentTheme||d.options.dialog&&d.options.theme||"dialog"===d.element.jqmData("role")&&d.options.theme,e.addClass("ui-content"),d.options.contentTheme&&e.addClass("ui-body-"+d.options.contentTheme),e.attr("role","main").addClass("ui-content")})},bindRemove:function(b){var c=this.element;!c.data("mobile-page").options.domCache&&c.is(":jqmData(external-page='true')")&&c.bind("pagehide.remove",b||function(b,c){if(!c.samePage){var d=a(this),e=new a.Event("pageremove");d.trigger(e),e.isDefaultPrevented()||d.removeWithDependents()}})},_setOptions:function(c){c.theme!==b&&this.element.removeClass("ui-page-theme-"+this.options.theme).addClass("ui-page-theme-"+c.theme),c.contentTheme!==b&&this.element.find("[data-"+a.mobile.ns+"='content']").removeClass("ui-body-"+this.options.contentTheme).addClass("ui-body-"+c.contentTheme)},_handlePageBeforeShow:function(){this.setContainerBackground()},removeContainerBackground:function(){this.element.closest(":mobile-pagecontainer").pagecontainer({theme:"none"})},setContainerBackground:function(a){this.element.parent().pagecontainer({theme:a||this.options.theme})},keepNativeSelector:function(){var b=this.options,c=a.trim(b.keepNative||""),e=a.trim(a.mobile.keepNative),f=a.trim(b.keepNativeDefault),g=d===e?"":e,h=""===g?f:"";return(c?[c]:[]).concat(g?[g]:[]).concat(h?[h]:[]).join(", ")}})}(a),function(a,d){a.widget("mobile.pagecontainer",{options:{theme:"a"},initSelector:!1,_create:function(){this._trigger("beforecreate"),this.setLastScrollEnabled=!0,this._on(this.window,{navigate:"_disableRecordScroll",scrollstop:"_delayedRecordScroll"}),this._on(this.window,{navigate:"_filterNavigateEvents"}),this._on({pagechange:"_afterContentChange"}),this.window.one("navigate",a.proxy(function(){this.setLastScrollEnabled=!0},this))},_setOptions:function(a){a.theme!==d&&"none"!==a.theme?this.element.removeClass("ui-overlay-"+this.options.theme).addClass("ui-overlay-"+a.theme):a.theme!==d&&this.element.removeClass("ui-overlay-"+this.options.theme),this._super(a)},_disableRecordScroll:function(){this.setLastScrollEnabled=!1},_enableRecordScroll:function(){this.setLastScrollEnabled=!0},_afterContentChange:function(){this.setLastScrollEnabled=!0,this._off(this.window,"scrollstop"),this._on(this.window,{scrollstop:"_delayedRecordScroll"})},_recordScroll:function(){if(this.setLastScrollEnabled){var a,b,c,d=this._getActiveHistory();d&&(a=this._getScroll(),b=this._getMinScroll(),c=this._getDefaultScroll(),d.lastScroll=b>a?c:a)}},_delayedRecordScroll:function(){setTimeout(a.proxy(this,"_recordScroll"),100)},_getScroll:function(){return this.window.scrollTop()},_getMinScroll:function(){return a.mobile.minScrollBack},_getDefaultScroll:function(){return a.mobile.defaultHomeScroll},_filterNavigateEvents:function(b,c){var d;b.originalEvent&&b.originalEvent.isDefaultPrevented()||(d=b.originalEvent.type.indexOf("hashchange")>-1?c.state.hash:c.state.url,d||(d=this._getHash()),d&&"#"!==d&&0!==d.indexOf("#"+a.mobile.path.uiStateKey)||(d=location.href),this._handleNavigate(d,c.state))},_getHash:function(){return a.mobile.path.parseLocation().hash},getActivePage:function(){return this.activePage},_getInitialContent:function(){return a.mobile.firstPage},_getHistory:function(){return a.mobile.navigate.history},_getActiveHistory:function(){return this._getHistory().getActive()},_getDocumentBase:function(){return a.mobile.path.documentBase},back:function(){this.go(-1)},forward:function(){this.go(1)},go:function(c){if(a.mobile.hashListeningEnabled)b.history.go(c);else{var d=a.mobile.navigate.history.activeIndex,e=d+parseInt(c,10),f=a.mobile.navigate.history.stack[e].url,g=c>=1?"forward":"back";a.mobile.navigate.history.activeIndex=e,a.mobile.navigate.history.previousIndex=d,this.change(f,{direction:g,changeHash:!1,fromHashChange:!0})}},_handleDestination:function(b){var c;return"string"===a.type(b)&&(b=a.mobile.path.stripHash(b)),b&&(c=this._getHistory(),b=a.mobile.path.isPath(b)?b:a.mobile.path.makeUrlAbsolute("#"+b,this._getDocumentBase())),b||this._getInitialContent()},_transitionFromHistory:function(a,b){var c=this._getHistory(),d="back"===a?c.getLast():c.getActive();return d&&d.transition||b},_handleDialog:function(b,c){var d,e,f=this.getActivePage();return f&&!f.data("mobile-dialog")?("back"===c.direction?this.back():this.forward(),!1):(d=c.pageUrl,e=this._getActiveHistory(),a.extend(b,{role:e.role,transition:this._transitionFromHistory(c.direction,b.transition),reverse:"back"===c.direction}),d)},_handleNavigate:function(b,c){var d=a.mobile.path.stripHash(b),e=this._getHistory(),f=0===e.stack.length?"none":this._transitionFromHistory(c.direction),g={changeHash:!1,fromHashChange:!0,reverse:"back"===c.direction};a.extend(g,c,{transition:f}),e.activeIndex>0&&d.indexOf(a.mobile.dialogHashKey)>-1&&(d=this._handleDialog(g,c),d===!1)||this._changeContent(this._handleDestination(d),g)},_changeContent:function(b,c){a.mobile.changePage(b,c)},_getBase:function(){return a.mobile.base},_getNs:function(){return a.mobile.ns},_enhance:function(a,b){return a.page({role:b})},_include:function(a,b){a.appendTo(this.element),this._enhance(a,b.role),a.page("bindRemove")},_find:function(b){var c,d=this._createFileUrl(b),e=this._createDataUrl(b),f=this._getInitialContent();return c=this.element.children("[data-"+this._getNs()+"url='"+a.mobile.path.hashToSelector(e)+"']"),0===c.length&&e&&!a.mobile.path.isPath(e)&&(c=this.element.children(a.mobile.path.hashToSelector("#"+e)).attr("data-"+this._getNs()+"url",e).jqmData("url",e)),0===c.length&&a.mobile.path.isFirstPageUrl(d)&&f&&f.parent().length&&(c=a(f)),c},_getLoader:function(){return a.mobile.loading()},_showLoading:function(b,c,d,e){this._loadMsg||(this._loadMsg=setTimeout(a.proxy(function(){this._getLoader().loader("show",c,d,e),this._loadMsg=0},this),b))},_hideLoading:function(){clearTimeout(this._loadMsg),this._loadMsg=0,this._getLoader().loader("hide")},_showError:function(){this._hideLoading(),this._showLoading(0,a.mobile.pageLoadErrorMessageTheme,a.mobile.pageLoadErrorMessage,!0),setTimeout(a.proxy(this,"_hideLoading"),1500)},_parse:function(b,c){var d,e=a("<div></div>");return e.get(0).innerHTML=b,d=e.find(":jqmData(role='page'), :jqmData(role='dialog')").first(),d.length||(d=a("<div data-"+this._getNs()+"role='page'>"+(b.split(/<\/?body[^>]*>/gim)[1]||"")+"</div>")),d.attr("data-"+this._getNs()+"url",this._createDataUrl(c)).attr("data-"+this._getNs()+"external-page",!0),d},_setLoadedTitle:function(b,c){var d=c.match(/<title[^>]*>([^<]*)/)&&RegExp.$1;d&&!b.jqmData("title")&&(d=a("<div>"+d+"</div>").text(),b.jqmData("title",d))},_isRewritableBaseTag:function(){return a.mobile.dynamicBaseEnabled&&!a.support.dynamicBaseTag},_createDataUrl:function(b){return a.mobile.path.convertUrlToDataUrl(b)},_createFileUrl:function(b){return a.mobile.path.getFilePath(b)},_triggerWithDeprecated:function(b,c,d){var e=a.Event("page"+b),f=a.Event(this.widgetName+b);return(d||this.element).trigger(e,c),this._trigger(b,f,c),{deprecatedEvent:e,event:f}},_loadSuccess:function(b,c,e,f){var g=this._createFileUrl(b);return a.proxy(function(h,i,j){var k,l=new RegExp("(<[^>]+\\bdata-"+this._getNs()+"role=[\"']?page[\"']?[^>]*>)"),m=new RegExp("\\bdata-"+this._getNs()+"url=[\"']?([^\"'>]*)[\"']?");l.test(h)&&RegExp.$1&&m.test(RegExp.$1)&&RegExp.$1&&(g=a.mobile.path.getFilePath(a("<div>"+RegExp.$1+"</div>").text()),g=this.window[0].encodeURIComponent(g)),e.prefetch===d&&this._getBase().set(g),k=this._parse(h,g),this._setLoadedTitle(k,h),c.xhr=j,c.textStatus=i,c.page=k,c.content=k,c.toPage=k,this._triggerWithDeprecated("load",c).event.isDefaultPrevented()||(this._isRewritableBaseTag()&&k&&this._getBase().rewrite(g,k),this._include(k,e),e.showLoadMsg&&this._hideLoading(),f.resolve(b,e,k))},this)},_loadDefaults:{type:"get",data:d,reloadPage:!1,reload:!1,role:d,showLoadMsg:!1,loadMsgDelay:50},load:function(b,c){var e,f,g,h,i=c&&c.deferred||a.Deferred(),j=c&&c.reload===d&&c.reloadPage!==d?{reload:c.reloadPage}:{},k=a.extend({},this._loadDefaults,c,j),l=null,m=a.mobile.path.makeUrlAbsolute(b,this._findBaseWithDefault());return k.data&&"get"===k.type&&(m=a.mobile.path.addSearchParams(m,k.data),k.data=d),k.data&&"post"===k.type&&(k.reload=!0),e=this._createFileUrl(m),f=this._createDataUrl(m),l=this._find(m),0===l.length&&a.mobile.path.isEmbeddedPage(e)&&!a.mobile.path.isFirstPageUrl(e)?(i.reject(m,k),i.promise()):(this._getBase().reset(),l.length&&!k.reload?(this._enhance(l,k.role),i.resolve(m,k,l),k.prefetch||this._getBase().set(b),i.promise()):(h={url:b,absUrl:m,toPage:b,prevPage:c?c.fromPage:d,dataUrl:f,deferred:i,options:k},g=this._triggerWithDeprecated("beforeload",h),g.deprecatedEvent.isDefaultPrevented()||g.event.isDefaultPrevented()?i.promise():(k.showLoadMsg&&this._showLoading(k.loadMsgDelay),k.prefetch===d&&this._getBase().reset(),a.mobile.allowCrossDomainPages||a.mobile.path.isSameDomain(a.mobile.path.documentUrl,m)?(a.ajax({url:e,type:k.type,data:k.data,contentType:k.contentType,dataType:"html",success:this._loadSuccess(m,h,k,i),error:this._loadError(m,h,k,i)}),i.promise()):(i.reject(m,k),i.promise()))))},_loadError:function(b,c,d,e){return a.proxy(function(f,g,h){this._getBase().set(a.mobile.path.get()),c.xhr=f,c.textStatus=g,c.errorThrown=h;var i=this._triggerWithDeprecated("loadfailed",c);i.deprecatedEvent.isDefaultPrevented()||i.event.isDefaultPrevented()||(d.showLoadMsg&&this._showError(),e.reject(b,d))},this)},_getTransitionHandler:function(b){return b=a.mobile._maybeDegradeTransition(b),a.mobile.transitionHandlers[b]||a.mobile.defaultTransitionHandler},_triggerCssTransitionEvents:function(b,c,d){var e=!1;d=d||"",c&&(b[0]===c[0]&&(e=!0),this._triggerWithDeprecated(d+"hide",{nextPage:b,toPage:b,prevPage:c,samePage:e},c)),this._triggerWithDeprecated(d+"show",{prevPage:c||a(""),toPage:b},b)},_cssTransition:function(b,c,d){var e,f,g=d.transition,h=d.reverse,i=d.deferred;this._triggerCssTransitionEvents(b,c,"before"),this._hideLoading(),e=this._getTransitionHandler(g),f=new e(g,h,b,c).transition(),f.done(a.proxy(function(){this._triggerCssTransitionEvents(b,c)},this)),f.done(function(){i.resolve.apply(i,arguments)})},_releaseTransitionLock:function(){f=!1,e.length>0&&a.mobile.changePage.apply(null,e.pop())},_removeActiveLinkClass:function(b){a.mobile.removeActiveLinkClass(b)},_loadUrl:function(b,c,d){d.target=b,d.deferred=a.Deferred(),this.load(b,d),d.deferred.done(a.proxy(function(a,b,d){f=!1,b.absUrl=c.absUrl,this.transition(d,c,b)},this)),d.deferred.fail(a.proxy(function(){this._removeActiveLinkClass(!0),this._releaseTransitionLock(),this._triggerWithDeprecated("changefailed",c)},this))},_triggerPageBeforeChange:function(b,c,d){var e;return c.prevPage=this.activePage,a.extend(c,{toPage:b,options:d}),c.absUrl="string"===a.type(b)?a.mobile.path.makeUrlAbsolute(b,this._findBaseWithDefault()):d.absUrl,e=this._triggerWithDeprecated("beforechange",c),e.event.isDefaultPrevented()||e.deprecatedEvent.isDefaultPrevented()?!1:!0},change:function(b,c){if(f)return void e.unshift(arguments);var d=a.extend({},a.mobile.changePage.defaults,c),g={};d.fromPage=d.fromPage||this.activePage,this._triggerPageBeforeChange(b,g,d)&&(b=g.toPage,"string"===a.type(b)?(f=!0,this._loadUrl(b,g,d)):this.transition(b,g,d))},transition:function(b,g,h){var i,j,k,l,m,n,o,p,q,r,s,t,u,v;if(f)return void e.unshift([b,h]);if(this._triggerPageBeforeChange(b,g,h)&&(g.prevPage=h.fromPage,v=this._triggerWithDeprecated("beforetransition",g),!v.deprecatedEvent.isDefaultPrevented()&&!v.event.isDefaultPrevented())){if(f=!0,b[0]!==a.mobile.firstPage[0]||h.dataUrl||(h.dataUrl=a.mobile.path.documentUrl.hrefNoHash),i=h.fromPage,j=h.dataUrl&&a.mobile.path.convertUrlToDataUrl(h.dataUrl)||b.jqmData("url"),k=j,l=a.mobile.path.getFilePath(j),m=a.mobile.navigate.history.getActive(),n=0===a.mobile.navigate.history.activeIndex,o=0,p=c.title,q=("dialog"===h.role||"dialog"===b.jqmData("role"))&&b.jqmData("dialog")!==!0,i&&i[0]===b[0]&&!h.allowSamePageTransition)return f=!1,this._triggerWithDeprecated("transition",g),this._triggerWithDeprecated("change",g),void(h.fromHashChange&&a.mobile.navigate.history.direct({url:j}));b.page({role:h.role}),h.fromHashChange&&(o="back"===h.direction?-1:1);try{c.activeElement&&"body"!==c.activeElement.nodeName.toLowerCase()?a(c.activeElement).blur():a("input:focus, textarea:focus, select:focus").blur()}catch(w){}r=!1,q&&m&&(m.url&&m.url.indexOf(a.mobile.dialogHashKey)>-1&&this.activePage&&!this.activePage.hasClass("ui-dialog")&&a.mobile.navigate.history.activeIndex>0&&(h.changeHash=!1,r=!0),j=m.url||"",j+=!r&&j.indexOf("#")>-1?a.mobile.dialogHashKey:"#"+a.mobile.dialogHashKey),s=m?b.jqmData("title")||b.children(":jqmData(role='header')").find(".ui-title").text():p,s&&p===c.title&&(p=s),b.jqmData("title")||b.jqmData("title",p),h.transition=h.transition||(o&&!n?m.transition:d)||(q?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition),!o&&r&&(a.mobile.navigate.history.getActive().pageUrl=k),j&&!h.fromHashChange&&(!a.mobile.path.isPath(j)&&j.indexOf("#")<0&&(j="#"+j),t={transition:h.transition,title:p,pageUrl:k,role:h.role},h.changeHash!==!1&&a.mobile.hashListeningEnabled?a.mobile.navigate(this.window[0].encodeURI(j),t,!0):b[0]!==a.mobile.firstPage[0]&&a.mobile.navigate.history.add(j,t)),c.title=p,a.mobile.activePage=b,this.activePage=b,h.reverse=h.reverse||0>o,u=a.Deferred(),this._cssTransition(b,i,{transition:h.transition,reverse:h.reverse,deferred:u}),u.done(a.proxy(function(c,d,e,f,i){a.mobile.removeActiveLinkClass(),h.duplicateCachedPage&&h.duplicateCachedPage.remove(),i||a.mobile.focusPage(b),this._releaseTransitionLock(),this._triggerWithDeprecated("transition",g),this._triggerWithDeprecated("change",g)},this))}},_findBaseWithDefault:function(){var b=this.activePage&&a.mobile.getClosestBaseUrl(this.activePage);return b||a.mobile.path.documentBase.hrefNoHash}}),a.mobile.navreadyDeferred=a.Deferred();var e=[],f=!1}(a),function(a,d){function e(a){for(;a&&("string"!=typeof a.nodeName||"a"!==a.nodeName.toLowerCase());)a=a.parentNode;return a}var f=a.Deferred(),g=a.Deferred(),h=function(){g.resolve(),g=null},i=a.mobile.path.documentUrl,j=null;a.mobile.loadPage=function(b,c){var d;return c=c||{},d=c.pageContainer||a.mobile.pageContainer,c.deferred=a.Deferred(),d.pagecontainer("load",b,c),c.deferred.promise()},a.mobile.back=function(){var c=b.navigator;this.phonegapNavigationEnabled&&c&&c.app&&c.app.backHistory?c.app.backHistory():a.mobile.pageContainer.pagecontainer("back")},a.mobile.focusPage=function(a){var b=a.find("[autofocus]"),c=a.find(".ui-title:eq(0)");return b.length?void b.focus():void(c.length?c.focus():a.focus())},a.mobile._maybeDegradeTransition=a.mobile._maybeDegradeTransition||function(a){return a},a.mobile.changePage=function(b,c){a.mobile.pageContainer.pagecontainer("change",b,c)},a.mobile.changePage.defaults={transition:d,reverse:!1,changeHash:!0,fromHashChange:!1,role:d,duplicateCachedPage:d,pageContainer:d,showLoadMsg:!0,dataUrl:d,fromPage:d,allowSamePageTransition:!1},a.mobile._registerInternalEvents=function(){var c=function(b,c){var d,e,f,g,h=!0;return!a.mobile.ajaxEnabled||b.is(":jqmData(ajax='false')")||!b.jqmHijackable().length||b.attr("target")?!1:(d=j&&j.attr("formaction")||b.attr("action"),g=(b.attr("method")||"get").toLowerCase(),d||(d=a.mobile.getClosestBaseUrl(b),"get"===g&&(d=a.mobile.path.parseUrl(d).hrefNoSearch),d===a.mobile.path.documentBase.hrefNoHash&&(d=i.hrefNoSearch)),d=a.mobile.path.makeUrlAbsolute(d,a.mobile.getClosestBaseUrl(b)),a.mobile.path.isExternal(d)&&!a.mobile.path.isPermittedCrossDomainRequest(i,d)?!1:(c||(e=b.serializeArray(),j&&j[0].form===b[0]&&(f=j.attr("name"),f&&(a.each(e,function(a,b){return b.name===f?(f="",!1):void 0}),f&&e.push({name:f,value:j.attr("value")}))),h={url:d,options:{type:g,data:a.param(e),transition:b.jqmData("transition"),reverse:"reverse"===b.jqmData("direction"),reloadPage:!0}}),h))};a.mobile.document.delegate("form","submit",function(b){var d;b.isDefaultPrevented()||(d=c(a(this)),d&&(a.mobile.changePage(d.url,d.options),b.preventDefault()))}),a.mobile.document.bind("vclick",function(b){var d,f,g=b.target,h=!1;if(!(b.which>1)&&a.mobile.linkBindingEnabled){if(j=a(g),a.data(g,"mobile-button")){if(!c(a(g).closest("form"),!0))return;g.parentNode&&(g=g.parentNode)}else{if(g=e(g),!g||"#"===a.mobile.path.parseUrl(g.getAttribute("href")||"#").hash)return;if(!a(g).jqmHijackable().length)return}~g.className.indexOf("ui-link-inherit")?g.parentNode&&(f=a.data(g.parentNode,"buttonElements")):f=a.data(g,"buttonElements"),f?g=f.outer:h=!0,d=a(g),h&&(d=d.closest(".ui-btn")),d.length>0&&!d.hasClass("ui-state-disabled")&&(a.mobile.removeActiveLinkClass(!0),a.mobile.activeClickedLink=d,a.mobile.activeClickedLink.addClass(a.mobile.activeBtnClass))}}),a.mobile.document.bind("click",function(c){if(a.mobile.linkBindingEnabled&&!c.isDefaultPrevented()){var f,g,h,j,k,l,m,n=e(c.target),o=a(n),p=function(){b.setTimeout(function(){a.mobile.removeActiveLinkClass(!0)},200)};if(a.mobile.activeClickedLink&&a.mobile.activeClickedLink[0]===c.target.parentNode&&p(),n&&!(c.which>1)&&o.jqmHijackable().length){if(o.is(":jqmData(rel='back')"))return a.mobile.back(),!1;if(f=a.mobile.getClosestBaseUrl(o),g=a.mobile.path.makeUrlAbsolute(o.attr("href")||"#",f),!a.mobile.ajaxEnabled&&!a.mobile.path.isEmbeddedPage(g))return void p();if(!(-1===g.search("#")||a.mobile.path.isExternal(g)&&a.mobile.path.isAbsoluteUrl(g))){if(g=g.replace(/[^#]*#/,""),!g)return void c.preventDefault();g=a.mobile.path.isPath(g)?a.mobile.path.makeUrlAbsolute(g,f):a.mobile.path.makeUrlAbsolute("#"+g,i.hrefNoHash)}if(h=o.is("[rel='external']")||o.is(":jqmData(ajax='false')")||o.is("[target]"),j=h||a.mobile.path.isExternal(g)&&!a.mobile.path.isPermittedCrossDomainRequest(i,g))return void p();k=o.jqmData("transition"),l="reverse"===o.jqmData("direction")||o.jqmData("back"),m=o.attr("data-"+a.mobile.ns+"rel")||d,a.mobile.changePage(g,{transition:k,reverse:l,role:m,link:o}),c.preventDefault()}}}),a.mobile.document.delegate(".ui-page","pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),d=c.attr("href");d&&-1===a.inArray(d,b)&&(b.push(d),a.mobile.loadPage(d,{role:c.attr("data-"+a.mobile.ns+"rel"),prefetch:!0}))})}),a.mobile.pageContainer.pagecontainer(),a.mobile.document.bind("pageshow",function(){g?g.done(a.mobile.resetActivePageHeight):a.mobile.resetActivePageHeight()
+}),a.mobile.window.bind("throttledresize",a.mobile.resetActivePageHeight)},a(function(){f.resolve()}),"complete"===c.readyState?h():a.mobile.window.load(h),a.when(f,a.mobile.navreadyDeferred).done(function(){a.mobile._registerInternalEvents()})}(a),function(a,b){a.mobile.Transition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.Transition.prototype,{toPreClass:" ui-page-pre-in",init:function(b,c,d,e){a.extend(this,{name:b,reverse:c,$to:d,$from:e,deferred:new a.Deferred})},cleanFrom:function(){this.$from.removeClass(a.mobile.activePageClass+" out in reverse "+this.name).height("")},beforeDoneIn:function(){},beforeDoneOut:function(){},beforeStartOut:function(){},doneIn:function(){this.beforeDoneIn(),this.$to.removeClass("out in reverse "+this.name).height(""),this.toggleViewportClass(),a.mobile.window.scrollTop()!==this.toScroll&&this.scrollPage(),this.sequential||this.$to.addClass(a.mobile.activePageClass),this.deferred.resolve(this.name,this.reverse,this.$to,this.$from,!0)},doneOut:function(a,b,c,d){this.beforeDoneOut(),this.startIn(a,b,c,d)},hideIn:function(a){this.$to.css("z-index",-10),a.call(this),this.$to.css("z-index","")},scrollPage:function(){a.event.special.scrollstart.enabled=!1,(a.mobile.hideUrlBar||this.toScroll!==a.mobile.defaultHomeScroll)&&b.scrollTo(0,this.toScroll),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},startIn:function(b,c,d,e){this.hideIn(function(){this.$to.addClass(a.mobile.activePageClass+this.toPreClass),e||a.mobile.focusPage(this.$to),this.$to.height(b+this.toScroll),d||this.scrollPage()}),this.$to.removeClass(this.toPreClass).addClass(this.name+" in "+c),d?this.doneIn():this.$to.animationComplete(a.proxy(function(){this.doneIn()},this))},startOut:function(b,c,d){this.beforeStartOut(b,c,d),this.$from.height(b+a.mobile.window.scrollTop()).addClass(this.name+" out"+c)},toggleViewportClass:function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+this.name)},transition:function(){var b,c=this.reverse?" reverse":"",d=a.mobile.getScreenHeight(),e=a.mobile.maxTransitionWidth!==!1&&a.mobile.window.width()>a.mobile.maxTransitionWidth;return this.toScroll=a.mobile.navigate.history.getActive().lastScroll||a.mobile.defaultHomeScroll,b=!a.support.cssTransitions||!a.support.cssAnimations||e||!this.name||"none"===this.name||Math.max(a.mobile.window.scrollTop(),this.toScroll)>a.mobile.getMaxScrollForTransition(),this.toggleViewportClass(),this.$from&&!b?this.startOut(d,c,b):this.doneOut(d,c,b,!0),this.deferred.promise()}})}(a,this),function(a){a.mobile.SerialTransition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.SerialTransition.prototype,a.mobile.Transition.prototype,{sequential:!0,beforeDoneOut:function(){this.$from&&this.cleanFrom()},beforeStartOut:function(b,c,d){this.$from.animationComplete(a.proxy(function(){this.doneOut(b,c,d)},this))}})}(a),function(a){a.mobile.ConcurrentTransition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.ConcurrentTransition.prototype,a.mobile.Transition.prototype,{sequential:!1,beforeDoneIn:function(){this.$from&&this.cleanFrom()},beforeStartOut:function(a,b,c){this.doneOut(a,b,c)}})}(a),function(a){var b=function(){return 3*a.mobile.getScreenHeight()};a.mobile.transitionHandlers={sequential:a.mobile.SerialTransition,simultaneous:a.mobile.ConcurrentTransition},a.mobile.defaultTransitionHandler=a.mobile.transitionHandlers.sequential,a.mobile.transitionFallbacks={},a.mobile._maybeDegradeTransition=function(b){return b&&!a.support.cssTransform3d&&a.mobile.transitionFallbacks[b]&&(b=a.mobile.transitionFallbacks[b]),b},a.mobile.getMaxScrollForTransition=a.mobile.getMaxScrollForTransition||b}(a),function(a){a.mobile.transitionFallbacks.flip="fade"}(a,this),function(a){a.mobile.transitionFallbacks.flow="fade"}(a,this),function(a){a.mobile.transitionFallbacks.pop="fade"}(a,this),function(a){a.mobile.transitionHandlers.slide=a.mobile.transitionHandlers.simultaneous,a.mobile.transitionFallbacks.slide="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slidedown="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slidefade="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slideup="fade"}(a,this),function(a){a.mobile.transitionFallbacks.turn="fade"}(a,this),function(a){a.mobile.degradeInputs={color:!1,date:!1,datetime:!1,"datetime-local":!1,email:!1,month:!1,number:!1,range:"number",search:"text",tel:!1,time:!1,url:!1,week:!1},a.mobile.page.prototype.options.degradeInputs=a.mobile.degradeInputs,a.mobile.degradeInputsWithin=function(b){b=a(b),b.find("input").not(a.mobile.page.prototype.keepNativeSelector()).each(function(){var b,c,d,e,f=a(this),g=this.getAttribute("type"),h=a.mobile.degradeInputs[g]||"text";a.mobile.degradeInputs[g]&&(b=a("<div>").html(f.clone()).html(),c=b.indexOf(" type=")>-1,d=c?/\s+type=["']?\w+['"]?/:/\/?>/,e=' type="'+h+'" data-'+a.mobile.ns+'type="'+g+'"'+(c?"":">"),f.replaceWith(b.replace(d,e)))})}}(a),function(a,b,c){a.widget("mobile.page",a.mobile.page,{options:{closeBtn:"left",closeBtnText:"Close",overlayTheme:"a",corners:!0,dialog:!1},_create:function(){this._super(),this.options.dialog&&(a.extend(this,{_inner:this.element.children(),_headerCloseButton:null}),this.options.enhanced||this._setCloseBtn(this.options.closeBtn))},_enhance:function(){this._super(),this.options.dialog&&this.element.addClass("ui-dialog").wrapInner(a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-overlay-shadow"+(this.options.corners?" ui-corner-all":"")}))},_setOptions:function(b){var d,e,f=this.options;b.corners!==c&&this._inner.toggleClass("ui-corner-all",!!b.corners),b.overlayTheme!==c&&a.mobile.activePage[0]===this.element[0]&&(f.overlayTheme=b.overlayTheme,this._handlePageBeforeShow()),b.closeBtnText!==c&&(d=f.closeBtn,e=b.closeBtnText),b.closeBtn!==c&&(d=b.closeBtn),d&&this._setCloseBtn(d,e),this._super(b)},_handlePageBeforeShow:function(){this.options.overlayTheme&&this.options.dialog?(this.removeContainerBackground(),this.setContainerBackground(this.options.overlayTheme)):this._super()},_setCloseBtn:function(b,c){var d,e=this._headerCloseButton;b="left"===b?"left":"right"===b?"right":"none","none"===b?e&&(e.remove(),e=null):e?(e.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-"+b),c&&e.text(c)):(d=this._inner.find(":jqmData(role='header')").first(),e=a("<a></a>",{href:"#","class":"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-"+b}).attr("data-"+a.mobile.ns+"rel","back").text(c||this.options.closeBtnText||"").prependTo(d)),this._headerCloseButton=e}})}(a,this),function(a,b,c){a.widget("mobile.dialog",{options:{closeBtn:"left",closeBtnText:"Close",overlayTheme:"a",corners:!0},_handlePageBeforeShow:function(){this._isCloseable=!0,this.options.overlayTheme&&this.element.page("removeContainerBackground").page("setContainerBackground",this.options.overlayTheme)},_handlePageBeforeHide:function(){this._isCloseable=!1},_handleVClickSubmit:function(b){var c,d=a(b.target).closest("vclick"===b.type?"a":"form");d.length&&!d.jqmData("transition")&&(c={},c["data-"+a.mobile.ns+"transition"]=(a.mobile.navigate.history.getActive()||{}).transition||a.mobile.defaultDialogTransition,c["data-"+a.mobile.ns+"direction"]="reverse",d.attr(c))},_create:function(){var b=this.element,c=this.options;b.addClass("ui-dialog").wrapInner(a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-overlay-shadow"+(c.corners?" ui-corner-all":"")})),a.extend(this,{_isCloseable:!1,_inner:b.children(),_headerCloseButton:null}),this._on(b,{vclick:"_handleVClickSubmit",submit:"_handleVClickSubmit",pagebeforeshow:"_handlePageBeforeShow",pagebeforehide:"_handlePageBeforeHide"}),this._setCloseBtn(c.closeBtn)},_setOptions:function(b){var d,e,f=this.options;b.corners!==c&&this._inner.toggleClass("ui-corner-all",!!b.corners),b.overlayTheme!==c&&a.mobile.activePage[0]===this.element[0]&&(f.overlayTheme=b.overlayTheme,this._handlePageBeforeShow()),b.closeBtnText!==c&&(d=f.closeBtn,e=b.closeBtnText),b.closeBtn!==c&&(d=b.closeBtn),d&&this._setCloseBtn(d,e),this._super(b)},_setCloseBtn:function(b,c){var d,e=this._headerCloseButton;b="left"===b?"left":"right"===b?"right":"none","none"===b?e&&(e.remove(),e=null):e?(e.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-"+b),c&&e.text(c)):(d=this._inner.find(":jqmData(role='header')").first(),e=a("<a></a>",{role:"button",href:"#","class":"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-"+b}).text(c||this.options.closeBtnText||"").prependTo(d),this._on(e,{click:"close"})),this._headerCloseButton=e},close:function(){var b=a.mobile.navigate.history;this._isCloseable&&(this._isCloseable=!1,a.mobile.hashListeningEnabled&&b.activeIndex>0?a.mobile.back():a.mobile.pageContainer.pagecontainer("back"))}})}(a,this),function(a,b){var c=/([A-Z])/g,d=function(a){return"ui-btn-icon-"+(null===a?"left":a)};a.widget("mobile.collapsible",{options:{enhanced:!1,expandCueText:null,collapseCueText:null,collapsed:!0,heading:"h1,h2,h3,h4,h5,h6,legend",collapsedIcon:null,expandedIcon:null,iconpos:null,theme:null,contentTheme:null,inset:null,corners:null,mini:null},_create:function(){var b=this.element,c={accordion:b.closest(":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')"+(a.mobile.collapsibleset?", :mobile-collapsibleset":"")).addClass("ui-collapsible-set")};this._ui=c,this._renderedOptions=this._getOptions(this.options),this.options.enhanced?(c.heading=this.element.children(".ui-collapsible-heading"),c.content=c.heading.next(),c.anchor=c.heading.children(),c.status=c.anchor.children(".ui-collapsible-heading-status")):this._enhance(b,c),this._on(c.heading,{tap:function(){c.heading.find("a").first().addClass(a.mobile.activeBtnClass)},click:function(a){this._handleExpandCollapse(!c.heading.hasClass("ui-collapsible-heading-collapsed")),a.preventDefault(),a.stopPropagation()}})},_getOptions:function(b){var d,e=this._ui.accordion,f=this._ui.accordionWidget;b=a.extend({},b),e.length&&!f&&(this._ui.accordionWidget=f=e.data("mobile-collapsibleset"));for(d in b)b[d]=null!=b[d]?b[d]:f?f.options[d]:e.length?a.mobile.getAttribute(e[0],d.replace(c,"-$1").toLowerCase()):null,null==b[d]&&(b[d]=a.mobile.collapsible.defaults[d]);return b},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:""},_enhance:function(b,c){var e,f=this._renderedOptions,g=this._themeClassFromOption("ui-body-",f.contentTheme);return b.addClass("ui-collapsible "+(f.inset?"ui-collapsible-inset ":"")+(f.inset&&f.corners?"ui-corner-all ":"")+(g?"ui-collapsible-themed-content ":"")),c.originalHeading=b.children(this.options.heading).first(),c.content=b.wrapInner("<div class='ui-collapsible-content "+g+"'></div>").children(".ui-collapsible-content"),c.heading=c.originalHeading,c.heading.is("legend")&&(c.heading=a("<div role='heading'>"+c.heading.html()+"</div>"),c.placeholder=a("<div><!-- placeholder for legend --></div>").insertBefore(c.originalHeading),c.originalHeading.remove()),e=f.collapsed?f.collapsedIcon?"ui-icon-"+f.collapsedIcon:"":f.expandedIcon?"ui-icon-"+f.expandedIcon:"",c.status=a("<span class='ui-collapsible-heading-status'></span>"),c.anchor=c.heading.detach().addClass("ui-collapsible-heading").append(c.status).wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().addClass("ui-btn "+(e?e+" ":"")+(e?d(f.iconpos)+" ":"")+this._themeClassFromOption("ui-btn-",f.theme)+" "+(f.mini?"ui-mini ":"")),c.heading.insertBefore(c.content),this._handleExpandCollapse(this.options.collapsed),c},refresh:function(){this._applyOptions(this.options),this._renderedOptions=this._getOptions(this.options)},_applyOptions:function(a){var c,e,f,g,h,i=this.element,j=this._renderedOptions,k=this._ui,l=k.anchor,m=k.status,n=this._getOptions(a);a.collapsed!==b&&this._handleExpandCollapse(a.collapsed),c=i.hasClass("ui-collapsible-collapsed"),c?n.expandCueText!==b&&m.text(n.expandCueText):n.collapseCueText!==b&&m.text(n.collapseCueText),h=n.collapsedIcon!==b?n.collapsedIcon!==!1:j.collapsedIcon!==!1,(n.iconpos!==b||n.collapsedIcon!==b||n.expandedIcon!==b)&&(l.removeClass([d(j.iconpos)].concat(j.expandedIcon?["ui-icon-"+j.expandedIcon]:[]).concat(j.collapsedIcon?["ui-icon-"+j.collapsedIcon]:[]).join(" ")),h&&l.addClass([d(n.iconpos!==b?n.iconpos:j.iconpos)].concat(c?["ui-icon-"+(n.collapsedIcon!==b?n.collapsedIcon:j.collapsedIcon)]:["ui-icon-"+(n.expandedIcon!==b?n.expandedIcon:j.expandedIcon)]).join(" "))),n.theme!==b&&(f=this._themeClassFromOption("ui-btn-",j.theme),e=this._themeClassFromOption("ui-btn-",n.theme),l.removeClass(f).addClass(e)),n.contentTheme!==b&&(f=this._themeClassFromOption("ui-body-",j.contentTheme),e=this._themeClassFromOption("ui-body-",n.contentTheme),k.content.removeClass(f).addClass(e)),n.inset!==b&&(i.toggleClass("ui-collapsible-inset",n.inset),g=!(!n.inset||!n.corners&&!j.corners)),n.corners!==b&&(g=!(!n.corners||!n.inset&&!j.inset)),g!==b&&i.toggleClass("ui-corner-all",g),n.mini!==b&&l.toggleClass("ui-mini",n.mini)},_setOptions:function(a){this._applyOptions(a),this._super(a),this._renderedOptions=this._getOptions(this.options)},_handleExpandCollapse:function(b){var c=this._renderedOptions,d=this._ui;d.status.text(b?c.expandCueText:c.collapseCueText),d.heading.toggleClass("ui-collapsible-heading-collapsed",b).find("a").first().toggleClass("ui-icon-"+c.expandedIcon,!b).toggleClass("ui-icon-"+c.collapsedIcon,b||c.expandedIcon===c.collapsedIcon).removeClass(a.mobile.activeBtnClass),this.element.toggleClass("ui-collapsible-collapsed",b),d.content.toggleClass("ui-collapsible-content-collapsed",b).attr("aria-hidden",b).trigger("updatelayout"),this.options.collapsed=b,this._trigger(b?"collapse":"expand")},expand:function(){this._handleExpandCollapse(!1)},collapse:function(){this._handleExpandCollapse(!0)},_destroy:function(){var a=this._ui,b=this.options;b.enhanced||(a.placeholder?(a.originalHeading.insertBefore(a.placeholder),a.placeholder.remove(),a.heading.remove()):(a.status.remove(),a.heading.removeClass("ui-collapsible-heading ui-collapsible-heading-collapsed").children().contents().unwrap()),a.anchor.contents().unwrap(),a.content.contents().unwrap(),this.element.removeClass("ui-collapsible ui-collapsible-collapsed ui-collapsible-themed-content ui-collapsible-inset ui-corner-all"))}}),a.mobile.collapsible.defaults={expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsedIcon:"plus",contentTheme:"inherit",expandedIcon:"minus",iconpos:"left",inset:!0,corners:!0,theme:"inherit",mini:!1}}(a),function(a){function b(b){var d,e=b.length,f=[];for(d=0;e>d;d++)b[d].className.match(c)||f.push(b[d]);return a(f)}var c=/\bui-screen-hidden\b/;a.mobile.behaviors.addFirstLastClasses={_getVisibles:function(a,c){var d;return c?d=b(a):(d=a.filter(":visible"),0===d.length&&(d=b(a))),d},_addFirstLastClasses:function(a,b,c){a.removeClass("ui-first-child ui-last-child"),b.eq(0).addClass("ui-first-child").end().last().addClass("ui-last-child"),c||this.element.trigger("updatelayout")},_removeFirstLastClasses:function(a){a.removeClass("ui-first-child ui-last-child")}}}(a),function(a,b){var c=":mobile-collapsible, "+a.mobile.collapsible.initSelector;a.widget("mobile.collapsibleset",a.extend({initSelector:":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')",options:a.extend({enhanced:!1},a.mobile.collapsible.defaults),_handleCollapsibleExpand:function(b){var c=a(b.target).closest(".ui-collapsible");c.parent().is(":mobile-collapsibleset, :jqmData(role='collapsible-set')")&&c.siblings(".ui-collapsible:not(.ui-collapsible-collapsed)").collapsible("collapse")},_create:function(){var b=this.element,c=this.options;a.extend(this,{_classes:""}),c.enhanced||(b.addClass("ui-collapsible-set "+this._themeClassFromOption("ui-group-theme-",c.theme)+" "+(c.corners&&c.inset?"ui-corner-all ":"")),this.element.find(a.mobile.collapsible.initSelector).collapsible()),this._on(b,{collapsibleexpand:"_handleCollapsibleExpand"})},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:""},_init:function(){this._refresh(!0),this.element.children(c).filter(":jqmData(collapsed='false')").collapsible("expand")},_setOptions:function(a){var c,d,e=this.element,f=this._themeClassFromOption("ui-group-theme-",a.theme);return f&&e.removeClass(this._themeClassFromOption("ui-group-theme-",this.options.theme)).addClass(f),a.inset!==b&&(d=!(!a.inset||!a.corners&&!this.options.corners)),a.corners!==b&&(d=!(!a.corners||!a.inset&&!this.options.inset)),d!==b&&e.toggleClass("ui-corner-all",d),c=this._super(a),this.element.children(":mobile-collapsible").collapsible("refresh"),c},_destroy:function(){var a=this.element;this._removeFirstLastClasses(a.children(c)),a.removeClass("ui-collapsible-set ui-corner-all "+this._themeClassFromOption("ui-group-theme-",this.options.theme)).children(":mobile-collapsible").collapsible("destroy")},_refresh:function(b){var d=this.element.children(c);this.element.find(a.mobile.collapsible.initSelector).not(".ui-collapsible").collapsible(),this._addFirstLastClasses(d,this._getVisibles(d,b),b)},refresh:function(){this._refresh(!1)}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain")}}(a),function(a){a.fn.grid=function(b){return this.each(function(){var c,d,e=a(this),f=a.extend({grid:null},b),g=e.children(),h={solo:1,a:2,b:3,c:4,d:5},i=f.grid;if(!i)if(g.length<=5)for(d in h)h[d]===g.length&&(i=d);else i="a",e.addClass("ui-grid-duo");c=h[i],e.addClass("ui-grid-"+i),g.filter(":nth-child("+c+"n+1)").addClass("ui-block-a"),c>1&&g.filter(":nth-child("+c+"n+2)").addClass("ui-block-b"),c>2&&g.filter(":nth-child("+c+"n+3)").addClass("ui-block-c"),c>3&&g.filter(":nth-child("+c+"n+4)").addClass("ui-block-d"),c>4&&g.filter(":nth-child("+c+"n+5)").addClass("ui-block-e")})}}(a),function(a,b){a.widget("mobile.navbar",{options:{iconpos:"top",grid:null},_create:function(){var d=this.element,e=d.find("a, button"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:b;d.addClass("ui-navbar").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid}),e.each(function(){var b=a.mobile.getAttribute(this,"icon"),c=a.mobile.getAttribute(this,"theme"),d="ui-btn";c&&(d+=" ui-btn-"+c),b&&(d+=" ui-icon-"+b+" ui-btn-icon-"+f),a(this).addClass(d)}),d.delegate("a","vclick",function(){var b=a(this);b.hasClass("ui-state-disabled")||b.hasClass("ui-disabled")||b.hasClass(a.mobile.activeBtnClass)||(e.removeClass(a.mobile.activeBtnClass),b.addClass(a.mobile.activeBtnClass),a(c).one("pagehide",function(){b.removeClass(a.mobile.activeBtnClass)}))}),d.closest(".ui-page").bind("pagebeforeshow",function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}})}(a),function(a){var b=a.mobile.getAttribute;a.widget("mobile.listview",a.extend({options:{theme:null,countTheme:null,dividerTheme:null,icon:"carat-r",splitIcon:"carat-r",splitTheme:null,corners:!0,shadow:!0,inset:!1},_create:function(){var a=this,b="";b+=a.options.inset?" ui-listview-inset":"",a.options.inset&&(b+=a.options.corners?" ui-corner-all":"",b+=a.options.shadow?" ui-shadow":""),a.element.addClass(" ui-listview"+b),a.refresh(!0)},_findFirstElementByTagName:function(a,b,c,d){var e={};for(e[c]=e[d]=!0;a;){if(e[a.nodeName])return a;a=a[b]}return null},_addThumbClasses:function(b){var c,d,e=b.length;for(c=0;e>c;c++)d=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),d.length&&a(this._findFirstElementByTagName(d[0].parentNode,"parentNode","li","LI")).addClass(d.hasClass("ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb")},_getChildrenByTagName:function(b,c,d){var e=[],f={};for(f[c]=f[d]=!0,b=b.firstChild;b;)f[b.nodeName]&&e.push(b),b=b.nextSibling;return a(e)},_beforeListviewRefresh:a.noop,_afterListviewRefresh:a.noop,refresh:function(c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=this.options,y=this.element,z=!!a.nodeName(y[0],"ol"),A=y.attr("start"),B={},C=y.find(".ui-li-count"),D=b(y[0],"counttheme")||this.options.countTheme,E=D?"ui-body-"+D:"ui-body-inherit";for(x.theme&&y.addClass("ui-group-theme-"+x.theme),z&&(A||0===A)&&(n=parseInt(A,10)-1,y.css("counter-reset","listnumbering "+n)),this._beforeListviewRefresh(),w=this._getChildrenByTagName(y[0],"li","LI"),e=0,f=w.length;f>e;e++)g=w.eq(e),h="",(c||g[0].className.search(/\bui-li-static\b|\bui-li-divider\b/)<0)&&(l=this._getChildrenByTagName(g[0],"a","A"),m="list-divider"===b(g[0],"role"),p=g.attr("value"),i=b(g[0],"theme"),l.length&&l[0].className.search(/\bui-btn\b/)<0&&!m?(j=b(g[0],"icon"),k=j===!1?!1:j||x.icon,l.removeClass("ui-link"),d="ui-btn",i&&(d+=" ui-btn-"+i),l.length>1?(h="ui-li-has-alt",q=l.last(),r=b(q[0],"theme")||x.splitTheme||b(g[0],"theme",!0),s=r?" ui-btn-"+r:"",t=b(q[0],"icon")||b(g[0],"icon")||x.splitIcon,u="ui-btn ui-btn-icon-notext ui-icon-"+t+s,q.attr("title",a.trim(q.getEncodedText())).addClass(u).empty(),l=l.first()):k&&(d+=" ui-btn-icon-right ui-icon-"+k),l.addClass(d)):m?(v=b(g[0],"theme")||x.dividerTheme||x.theme,h="ui-li-divider ui-bar-"+(v?v:"inherit"),g.attr("role","heading")):l.length<=0&&(h="ui-li-static ui-body-"+(i?i:"inherit")),z&&p&&(o=parseInt(p,10)-1,g.css("counter-reset","listnumbering "+o))),B[h]||(B[h]=[]),B[h].push(g[0]);for(h in B)a(B[h]).addClass(h);C.each(function(){a(this).closest("li").addClass("ui-li-has-count")}),E&&C.not("[class*='ui-body-']").addClass(E),this._addThumbClasses(w),this._addThumbClasses(w.find(".ui-btn")),this._afterListviewRefresh(),this._addFirstLastClasses(w,this._getVisibles(w,c),c)}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a){function b(b){var c=a.trim(b.text())||null;return c?c=c.slice(0,1).toUpperCase():null}a.widget("mobile.listview",a.mobile.listview,{options:{autodividers:!1,autodividersSelector:b},_beforeListviewRefresh:function(){this.options.autodividers&&(this._replaceDividers(),this._superApply(arguments))},_replaceDividers:function(){var b,d,e,f,g,h=null,i=this.element;for(i.children("li:jqmData(role='list-divider')").remove(),d=i.children("li"),b=0;b<d.length;b++)e=d[b],f=this.options.autodividersSelector(a(e)),f&&h!==f&&(g=c.createElement("li"),g.appendChild(c.createTextNode(f)),g.setAttribute("data-"+a.mobile.ns+"role","list-divider"),e.parentNode.insertBefore(g,e)),h=f}})}(a),function(a){var b=/(^|\s)ui-li-divider($|\s)/,c=/(^|\s)ui-screen-hidden($|\s)/;a.widget("mobile.listview",a.mobile.listview,{options:{hideDividers:!1},_afterListviewRefresh:function(){var a,d,e,f=!0;if(this._superApply(arguments),this.options.hideDividers)for(a=this._getChildrenByTagName(this.element[0],"li","LI"),d=a.length-1;d>-1;d--)e=a[d],e.className.match(b)?(f&&(e.className=e.className+" ui-screen-hidden"),f=!0):e.className.match(c)||(f=!1)}})}(a),function(a){a.mobile.nojs=function(b){a(":jqmData(role='nojs')",b).addClass("ui-nojs")}}(a),function(a){a.mobile.behaviors.formReset={_handleFormReset:function(){this._on(this.element.closest("form"),{reset:function(){this._delay("_reset")}})}}}(a),function(a,b){var c=a.mobile.path.hashToSelector;a.widget("mobile.checkboxradio",a.extend({initSelector:"input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",options:{theme:"inherit",mini:!1,wrapperClass:null,enhanced:!1,iconpos:"left"},_create:function(){var b=this.element,c=this.options,d=function(a,b){return a.jqmData(b)||a.closest("form, fieldset").jqmData(b)},e=this.options.enhanced?{element:this.element.siblings("label"),isParent:!1}:this._findLabel(),f=b[0].type,g="ui-"+f+"-on",h="ui-"+f+"-off";("checkbox"===f||"radio"===f)&&(this.element[0].disabled&&(this.options.disabled=!0),c.iconpos=d(b,"iconpos")||e.element.attr("data-"+a.mobile.ns+"iconpos")||c.iconpos,c.mini=d(b,"mini")||c.mini,a.extend(this,{input:b,label:e.element,labelIsParent:e.isParent,inputtype:f,checkedClass:g,uncheckedClass:h}),this.options.enhanced||this._enhance(),this._on(e.element,{vmouseover:"_handleLabelVMouseOver",vclick:"_handleLabelVClick"}),this._on(b,{vmousedown:"_cacheVals",vclick:"_handleInputVClick",focus:"_handleInputFocus",blur:"_handleInputBlur"}),this._handleFormReset(),this.refresh())},_findLabel:function(){var b,d,e,f=this.element,g=f[0].labels;return g&&g.length>0?(d=a(g[0]),e=a.contains(d[0],f[0])):(b=f.closest("label"),e=b.length>0,d=e?b:a(this.document[0].getElementsByTagName("label")).filter("[for='"+c(f[0].id)+"']").first()),{element:d,isParent:e}},_enhance:function(){this.label.addClass("ui-btn ui-corner-all"),this.labelIsParent?this.input.add(this.label).wrapAll(this._wrapper()):(this.element.wrap(this._wrapper()),this.element.parent().prepend(this.label)),this._setOptions({theme:this.options.theme,iconpos:this.options.iconpos,mini:this.options.mini})},_wrapper:function(){return a("<div class='"+(this.options.wrapperClass?this.options.wrapperClass:"")+" ui-"+this.inputtype+(this.options.disabled?" ui-state-disabled":"")+"' ></div>")},_handleInputFocus:function(){this.label.addClass(a.mobile.focusClass)},_handleInputBlur:function(){this.label.removeClass(a.mobile.focusClass)},_handleInputVClick:function(){this.element.prop("checked",this.element.is(":checked")),this._getInputSet().not(this.element).prop("checked",!1),this._updateAll(!0)},_handleLabelVMouseOver:function(a){this.label.parent().hasClass("ui-state-disabled")&&a.stopPropagation()},_handleLabelVClick:function(a){var b=this.element;return b.is(":disabled")?void a.preventDefault():(this._cacheVals(),b.prop("checked","radio"===this.inputtype&&!0||!b.prop("checked")),b.triggerHandler("click"),this._getInputSet().not(b).prop("checked",!1),this._updateAll(),!1)},_cacheVals:function(){this._getInputSet().each(function(){a(this).attr("data-"+a.mobile.ns+"cacheVal",this.checked)})},_getInputSet:function(){var b,d,e=this.element[0],f=e.name,g=e.form,h=this.element.parents().last().get(0),i=this.element;return f&&"radio"===this.inputtype&&h&&(b="input[type='radio'][name='"+c(f)+"']",g?(d=g.getAttribute("id"),d&&(i=a(b+"[form='"+c(d)+"']",h)),i=a(g).find(b).filter(function(){return this.form===g}).add(i)):i=a(b,h).filter(function(){return!this.form})),i},_updateAll:function(b){var c=this;this._getInputSet().each(function(){var d=a(this);!this.checked&&"checkbox"!==c.inputtype||b||d.trigger("change")}).checkboxradio("refresh")},_reset:function(){this.refresh()},_hasIcon:function(){var b,c,d=a.mobile.controlgroup;return d&&(b=this.element.closest(":mobile-controlgroup,"+d.prototype.initSelector),b.length>0)?(c=a.data(b[0],"mobile-controlgroup"),"horizontal"!==(c?c.options.type:b.attr("data-"+a.mobile.ns+"type"))):!0},refresh:function(){var b=this.element[0].checked,c=a.mobile.activeBtnClass,d="ui-btn-icon-"+this.options.iconpos,e=[],f=[];this._hasIcon()?(f.push(c),e.push(d)):(f.push(d),(b?e:f).push(c)),b?(e.push(this.checkedClass),f.push(this.uncheckedClass)):(e.push(this.uncheckedClass),f.push(this.checkedClass)),this.widget().toggleClass("ui-state-disabled",this.element.prop("disabled")),this.label.addClass(e.join(" ")).removeClass(f.join(" "))},widget:function(){return this.label.parent()},_setOptions:function(a){var c=this.label,d=this.options,e=this.widget(),f=this._hasIcon();a.disabled!==b&&(this.input.prop("disabled",!!a.disabled),e.toggleClass("ui-state-disabled",!!a.disabled)),a.mini!==b&&e.toggleClass("ui-mini",!!a.mini),a.theme!==b&&c.removeClass("ui-btn-"+d.theme).addClass("ui-btn-"+a.theme),a.wrapperClass!==b&&e.removeClass(d.wrapperClass).addClass(a.wrapperClass),a.iconpos!==b&&f?c.removeClass("ui-btn-icon-"+d.iconpos).addClass("ui-btn-icon-"+a.iconpos):f||c.removeClass("ui-btn-icon-"+d.iconpos),this._super(a)}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.button",{initSelector:"input[type='button'], input[type='submit'], input[type='reset']",options:{theme:null,icon:null,iconpos:"left",iconshadow:!1,corners:!0,shadow:!0,inline:null,mini:null,wrapperClass:null,enhanced:!1},_create:function(){this.element.is(":disabled")&&(this.options.disabled=!0),this.options.enhanced||this._enhance(),a.extend(this,{wrapper:this.element.parent()}),this._on({focus:function(){this.widget().addClass(a.mobile.focusClass)},blur:function(){this.widget().removeClass(a.mobile.focusClass)}}),this.refresh(!0)},_enhance:function(){this.element.wrap(this._button())},_button:function(){var b=this.options,c=this._getIconClasses(this.options);return a("<div class='ui-btn ui-input-btn"+(b.wrapperClass?" "+b.wrapperClass:"")+(b.theme?" ui-btn-"+b.theme:"")+(b.corners?" ui-corner-all":"")+(b.shadow?" ui-shadow":"")+(b.inline?" ui-btn-inline":"")+(b.mini?" ui-mini":"")+(b.disabled?" ui-state-disabled":"")+(c?" "+c:"")+"' >"+this.element.val()+"</div>")},widget:function(){return this.wrapper},_destroy:function(){this.element.insertBefore(this.wrapper),this.wrapper.remove()},_getIconClasses:function(a){return a.icon?"ui-icon-"+a.icon+(a.iconshadow?" ui-shadow-icon":"")+" ui-btn-icon-"+a.iconpos:""},_setOptions:function(c){var d=this.widget();c.theme!==b&&d.removeClass(this.options.theme).addClass("ui-btn-"+c.theme),c.corners!==b&&d.toggleClass("ui-corner-all",c.corners),c.shadow!==b&&d.toggleClass("ui-shadow",c.shadow),c.inline!==b&&d.toggleClass("ui-btn-inline",c.inline),c.mini!==b&&d.toggleClass("ui-mini",c.mini),c.disabled!==b&&(this.element.prop("disabled",c.disabled),d.toggleClass("ui-state-disabled",c.disabled)),(c.icon!==b||c.iconshadow!==b||c.iconpos!==b)&&d.removeClass(this._getIconClasses(this.options)).addClass(this._getIconClasses(a.extend({},this.options,c))),this._super(c)},refresh:function(b){var c,d=this.element.prop("disabled");this.options.icon&&"notext"===this.options.iconpos&&this.element.attr("title")&&this.element.attr("title",this.element.val()),b||(c=this.element.detach(),a(this.wrapper).text(this.element.val()).append(c)),this.options.disabled!==d&&this._setOptions({disabled:d})}})}(a),function(a){var b=a("meta[name=viewport]"),c=b.attr("content"),d=c+",maximum-scale=1, user-scalable=no",e=c+",maximum-scale=10, user-scalable=yes",f=/(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(c);a.mobile.zoom=a.extend({},{enabled:!f,locked:!1,disable:function(c){f||a.mobile.zoom.locked||(b.attr("content",d),a.mobile.zoom.enabled=!1,a.mobile.zoom.locked=c||!1)},enable:function(c){f||a.mobile.zoom.locked&&c!==!0||(b.attr("content",e),a.mobile.zoom.enabled=!0,a.mobile.zoom.locked=!1)},restore:function(){f||(b.attr("content",c),a.mobile.zoom.enabled=!0)}})}(a),function(a,b){a.widget("mobile.textinput",{initSelector:"input[type='text'],input[type='search'],:jqmData(type='search'),input[type='number'],:jqmData(type='number'),input[type='password'],input[type='email'],input[type='url'],input[type='tel'],textarea,input[type='time'],input[type='date'],input[type='month'],input[type='week'],input[type='datetime'],input[type='datetime-local'],input[type='color'],input:not([type]),input[type='file']",options:{theme:null,corners:!0,mini:!1,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,wrapperClass:"",enhanced:!1},_create:function(){var b=this.options,c=this.element.is("[type='search'], :jqmData(type='search')"),d="TEXTAREA"===this.element[0].tagName,e=this.element.is("[data-"+(a.mobile.ns||"")+"type='range']"),f=(this.element.is("input")||this.element.is("[data-"+(a.mobile.ns||"")+"type='search']"))&&!e;this.element.prop("disabled")&&(b.disabled=!0),a.extend(this,{classes:this._classesFromOptions(),isSearch:c,isTextarea:d,isRange:e,inputNeedsWrap:f}),this._autoCorrect(),b.enhanced||this._enhance(),this._on({focus:"_handleFocus",blur:"_handleBlur"})},refresh:function(){this.setOptions({disabled:this.element.is(":disabled")})},_enhance:function(){var a=[];this.isTextarea&&a.push("ui-input-text"),(this.isTextarea||this.isRange)&&a.push("ui-shadow-inset"),this.inputNeedsWrap?this.element.wrap(this._wrap()):a=a.concat(this.classes),this.element.addClass(a.join(" "))},widget:function(){return this.inputNeedsWrap?this.element.parent():this.element},_classesFromOptions:function(){var a=this.options,b=[];return b.push("ui-body-"+(null===a.theme?"inherit":a.theme)),a.corners&&b.push("ui-corner-all"),a.mini&&b.push("ui-mini"),a.disabled&&b.push("ui-state-disabled"),a.wrapperClass&&b.push(a.wrapperClass),b
+},_wrap:function(){return a("<div class='"+(this.isSearch?"ui-input-search ":"ui-input-text ")+this.classes.join(" ")+" ui-shadow-inset'></div>")},_autoCorrect:function(){"undefined"==typeof this.element[0].autocorrect||a.support.touchOverflow||(this.element[0].setAttribute("autocorrect","off"),this.element[0].setAttribute("autocomplete","off"))},_handleBlur:function(){this.widget().removeClass(a.mobile.focusClass),this.options.preventFocusZoom&&a.mobile.zoom.enable(!0)},_handleFocus:function(){this.options.preventFocusZoom&&a.mobile.zoom.disable(!0),this.widget().addClass(a.mobile.focusClass)},_setOptions:function(a){var c=this.widget();this._super(a),(a.disabled!==b||a.mini!==b||a.corners!==b||a.theme!==b||a.wrapperClass!==b)&&(c.removeClass(this.classes.join(" ")),this.classes=this._classesFromOptions(),c.addClass(this.classes.join(" "))),a.disabled!==b&&this.element.prop("disabled",!!a.disabled)},_destroy:function(){this.options.enhanced||(this.inputNeedsWrap&&this.element.unwrap(),this.element.removeClass("ui-input-text "+this.classes.join(" ")))}})}(a),function(a,d){a.widget("mobile.slider",a.extend({initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",widgetEventPrefix:"slide",options:{theme:null,trackTheme:null,corners:!0,mini:!1,highlight:!1},_create:function(){var e,f,g,h,i,j,k,l,m,n,o=this,p=this.element,q=this.options.trackTheme||a.mobile.getAttribute(p[0],"theme"),r=q?" ui-bar-"+q:" ui-bar-inherit",s=this.options.corners||p.jqmData("corners")?" ui-corner-all":"",t=this.options.mini||p.jqmData("mini")?" ui-mini":"",u=p[0].nodeName.toLowerCase(),v="select"===u,w=p.parent().is(":jqmData(role='rangeslider')"),x=v?"ui-slider-switch":"",y=p.attr("id"),z=a("[for='"+y+"']"),A=z.attr("id")||y+"-label",B=v?0:parseFloat(p.attr("min")),C=v?p.find("option").length-1:parseFloat(p.attr("max")),D=b.parseFloat(p.attr("step")||1),E=c.createElement("a"),F=a(E),G=c.createElement("div"),H=a(G),I=this.options.highlight&&!v?function(){var b=c.createElement("div");return b.className="ui-slider-bg "+a.mobile.activeBtnClass,a(b).prependTo(H)}():!1;if(z.attr("id",A),this.isToggleSwitch=v,E.setAttribute("href","#"),G.setAttribute("role","application"),G.className=[this.isToggleSwitch?"ui-slider ui-slider-track ui-shadow-inset ":"ui-slider-track ui-shadow-inset ",x,r,s,t].join(""),E.className="ui-slider-handle",G.appendChild(E),F.attr({role:"slider","aria-valuemin":B,"aria-valuemax":C,"aria-valuenow":this._value(),"aria-valuetext":this._value(),title:this._value(),"aria-labelledby":A}),a.extend(this,{slider:H,handle:F,control:p,type:u,step:D,max:C,min:B,valuebg:I,isRangeslider:w,dragging:!1,beforeStart:null,userModified:!1,mouseMoved:!1}),v){for(k=p.attr("tabindex"),k&&F.attr("tabindex",k),p.attr("tabindex","-1").focus(function(){a(this).blur(),F.focus()}),f=c.createElement("div"),f.className="ui-slider-inneroffset",g=0,h=G.childNodes.length;h>g;g++)f.appendChild(G.childNodes[g]);for(G.appendChild(f),F.addClass("ui-slider-handle-snapping"),e=p.find("option"),i=0,j=e.length;j>i;i++)l=i?"a":"b",m=i?" "+a.mobile.activeBtnClass:"",n=c.createElement("span"),n.className=["ui-slider-label ui-slider-label-",l,m].join(""),n.setAttribute("role","img"),n.appendChild(c.createTextNode(e[i].innerHTML)),a(n).prependTo(H);o._labels=a(".ui-slider-label",H)}p.addClass(v?"ui-slider-switch":"ui-slider-input"),this._on(p,{change:"_controlChange",keyup:"_controlKeyup",blur:"_controlBlur",vmouseup:"_controlVMouseUp"}),H.bind("vmousedown",a.proxy(this._sliderVMouseDown,this)).bind("vclick",!1),this._on(c,{vmousemove:"_preventDocumentDrag"}),this._on(H.add(c),{vmouseup:"_sliderVMouseUp"}),H.insertAfter(p),v||w||(f=this.options.mini?"<div class='ui-slider ui-mini'>":"<div class='ui-slider'>",p.add(H).wrapAll(f)),this._on(this.handle,{vmousedown:"_handleVMouseDown",keydown:"_handleKeydown",keyup:"_handleKeyup"}),this.handle.bind("vclick",!1),this._handleFormReset(),this.refresh(d,d,!0)},_setOptions:function(a){a.theme!==d&&this._setTheme(a.theme),a.trackTheme!==d&&this._setTrackTheme(a.trackTheme),a.corners!==d&&this._setCorners(a.corners),a.mini!==d&&this._setMini(a.mini),a.highlight!==d&&this._setHighlight(a.highlight),a.disabled!==d&&this._setDisabled(a.disabled),this._super(a)},_controlChange:function(a){return this._trigger("controlchange",a)===!1?!1:void(this.mouseMoved||this.refresh(this._value(),!0))},_controlKeyup:function(){this.refresh(this._value(),!0,!0)},_controlBlur:function(){this.refresh(this._value(),!0)},_controlVMouseUp:function(){this._checkedRefresh()},_handleVMouseDown:function(){this.handle.focus()},_handleKeydown:function(b){var c=this._value();if(!this.options.disabled){switch(b.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.preventDefault(),this._keySliding||(this._keySliding=!0,this.handle.addClass("ui-state-active"))}switch(b.keyCode){case a.mobile.keyCode.HOME:this.refresh(this.min);break;case a.mobile.keyCode.END:this.refresh(this.max);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:this.refresh(c+this.step);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:this.refresh(c-this.step)}}},_handleKeyup:function(){this._keySliding&&(this._keySliding=!1,this.handle.removeClass("ui-state-active"))},_sliderVMouseDown:function(a){return this.options.disabled||1!==a.which&&0!==a.which&&a.which!==d?!1:this._trigger("beforestart",a)===!1?!1:(this.dragging=!0,this.userModified=!1,this.mouseMoved=!1,this.isToggleSwitch&&(this.beforeStart=this.element[0].selectedIndex),this.refresh(a),this._trigger("start"),!1)},_sliderVMouseUp:function(){return this.dragging?(this.dragging=!1,this.isToggleSwitch&&(this.handle.addClass("ui-slider-handle-snapping"),this.refresh(this.mouseMoved?this.userModified?0===this.beforeStart?1:0:this.beforeStart:0===this.beforeStart?1:0)),this.mouseMoved=!1,this._trigger("stop"),!1):void 0},_preventDocumentDrag:function(a){return this._trigger("drag",a)===!1?!1:this.dragging&&!this.options.disabled?(this.mouseMoved=!0,this.isToggleSwitch&&this.handle.removeClass("ui-slider-handle-snapping"),this.refresh(a),this.userModified=this.beforeStart!==this.element[0].selectedIndex,!1):void 0},_checkedRefresh:function(){this.value!==this._value()&&this.refresh(this._value())},_value:function(){return this.isToggleSwitch?this.element[0].selectedIndex:parseFloat(this.element.val())},_reset:function(){this.refresh(d,!1,!0)},refresh:function(b,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z=this,A=a.mobile.getAttribute(this.element[0],"theme"),B=this.options.theme||A,C=B?" ui-btn-"+B:"",D=this.options.trackTheme||A,E=D?" ui-bar-"+D:" ui-bar-inherit",F=this.options.corners?" ui-corner-all":"",G=this.options.mini?" ui-mini":"";if(z.slider[0].className=[this.isToggleSwitch?"ui-slider ui-slider-switch ui-slider-track ui-shadow-inset":"ui-slider-track ui-shadow-inset",E,F,G].join(""),(this.options.disabled||this.element.prop("disabled"))&&this.disable(),this.value=this._value(),this.options.highlight&&!this.isToggleSwitch&&0===this.slider.find(".ui-slider-bg").length&&(this.valuebg=function(){var b=c.createElement("div");return b.className="ui-slider-bg "+a.mobile.activeBtnClass,a(b).prependTo(z.slider)}()),this.handle.addClass("ui-btn"+C+" ui-shadow"),l=this.element,m=!this.isToggleSwitch,n=m?[]:l.find("option"),o=m?parseFloat(l.attr("min")):0,p=m?parseFloat(l.attr("max")):n.length-1,q=m&&parseFloat(l.attr("step"))>0?parseFloat(l.attr("step")):1,"object"==typeof b){if(h=b,i=8,f=this.slider.offset().left,g=this.slider.width(),j=g/((p-o)/q),!this.dragging||h.pageX<f-i||h.pageX>f+g+i)return;k=j>1?(h.pageX-f)/g*100:Math.round((h.pageX-f)/g*100)}else null==b&&(b=m?parseFloat(l.val()||0):l[0].selectedIndex),k=(parseFloat(b)-o)/(p-o)*100;if(!isNaN(k)&&(r=k/100*(p-o)+o,s=(r-o)%q,t=r-s,2*Math.abs(s)>=q&&(t+=s>0?q:-q),u=100/((p-o)/q),r=parseFloat(t.toFixed(5)),"undefined"==typeof j&&(j=g/((p-o)/q)),j>1&&m&&(k=(r-o)*u*(1/q)),0>k&&(k=0),k>100&&(k=100),o>r&&(r=o),r>p&&(r=p),this.handle.css("left",k+"%"),this.handle[0].setAttribute("aria-valuenow",m?r:n.eq(r).attr("value")),this.handle[0].setAttribute("aria-valuetext",m?r:n.eq(r).getEncodedText()),this.handle[0].setAttribute("title",m?r:n.eq(r).getEncodedText()),this.valuebg&&this.valuebg.css("width",k+"%"),this._labels&&(v=this.handle.width()/this.slider.width()*100,w=k&&v+(100-v)*k/100,x=100===k?0:Math.min(v+100-w,100),this._labels.each(function(){var b=a(this).hasClass("ui-slider-label-a");a(this).width((b?w:x)+"%")})),!e)){if(y=!1,m?(y=parseFloat(l.val())!==r,l.val(r)):(y=l[0].selectedIndex!==r,l[0].selectedIndex=r),this._trigger("beforechange",b)===!1)return!1;!d&&y&&l.trigger("change")}},_setHighlight:function(a){a=!!a,a?(this.options.highlight=!!a,this.refresh()):this.valuebg&&(this.valuebg.remove(),this.valuebg=!1)},_setTheme:function(a){this.handle.removeClass("ui-btn-"+this.options.theme).addClass("ui-btn-"+a);var b=this.options.theme?this.options.theme:"inherit",c=a?a:"inherit";this.control.removeClass("ui-body-"+b).addClass("ui-body-"+c)},_setTrackTheme:function(a){var b=this.options.trackTheme?this.options.trackTheme:"inherit",c=a?a:"inherit";this.slider.removeClass("ui-body-"+b).addClass("ui-body-"+c)},_setMini:function(a){a=!!a,this.isToggleSwitch||this.isRangeslider||(this.slider.parent().toggleClass("ui-mini",a),this.element.toggleClass("ui-mini",a)),this.slider.toggleClass("ui-mini",a)},_setCorners:function(a){this.slider.toggleClass("ui-corner-all",a),this.isToggleSwitch||this.control.toggleClass("ui-corner-all",a)},_setDisabled:function(a){a=!!a,this.element.prop("disabled",a),this.slider.toggleClass("ui-state-disabled",a).attr("aria-disabled",a),this.element.toggleClass("ui-state-disabled",a)}},a.mobile.behaviors.formReset))}(a),function(a){function b(){return c||(c=a("<div></div>",{"class":"ui-slider-popup ui-shadow ui-corner-all"})),c.clone()}var c;a.widget("mobile.slider",a.mobile.slider,{options:{popupEnabled:!1,showValue:!1},_create:function(){this._super(),a.extend(this,{_currentValue:null,_popup:null,_popupVisible:!1}),this._setOption("popupEnabled",this.options.popupEnabled),this._on(this.handle,{vmousedown:"_showPopup"}),this._on(this.slider.add(this.document),{vmouseup:"_hidePopup"}),this._refresh()},_positionPopup:function(){var a=this.handle.offset();this._popup.offset({left:a.left+(this.handle.width()-this._popup.width())/2,top:a.top-this._popup.outerHeight()-5})},_setOption:function(a,c){this._super(a,c),"showValue"===a?this.handle.html(c&&!this.options.mini?this._value():""):"popupEnabled"===a&&c&&!this._popup&&(this._popup=b().addClass("ui-body-"+(this.options.theme||"a")).hide().insertBefore(this.element))},refresh:function(){this._super.apply(this,arguments),this._refresh()},_refresh:function(){var a,b=this.options;b.popupEnabled&&this.handle.removeAttr("title"),a=this._value(),a!==this._currentValue&&(this._currentValue=a,b.popupEnabled&&this._popup&&(this._positionPopup(),this._popup.html(a)),b.showValue&&!this.options.mini&&this.handle.html(a))},_showPopup:function(){this.options.popupEnabled&&!this._popupVisible&&(this.handle.html(""),this._popup.show(),this._positionPopup(),this._popupVisible=!0)},_hidePopup:function(){var a=this.options;a.popupEnabled&&this._popupVisible&&(a.showValue&&!a.mini&&this.handle.html(this._value()),this._popup.hide(),this._popupVisible=!1)}})}(a),function(a,b){a.widget("mobile.flipswitch",a.extend({options:{onText:"On",offText:"Off",theme:null,enhanced:!1,wrapperClass:null,corners:!0,mini:!1},_create:function(){this.options.enhanced?a.extend(this,{flipswitch:this.element.parent(),on:this.element.find(".ui-flipswitch-on").eq(0),off:this.element.find(".ui-flipswitch-off").eq(0),type:this.element.get(0).tagName}):this._enhance(),this._handleFormReset(),this._originalTabIndex=this.element.attr("tabindex"),null!=this._originalTabIndex&&this.on.attr("tabindex",this._originalTabIndex),this.element.attr("tabindex","-1"),this._on({focus:"_handleInputFocus"}),this.element.is(":disabled")&&this._setOptions({disabled:!0}),this._on(this.flipswitch,{click:"_toggle",swipeleft:"_left",swiperight:"_right"}),this._on(this.on,{keydown:"_keydown"}),this._on({change:"refresh"})},_handleInputFocus:function(){this.on.focus()},widget:function(){return this.flipswitch},_left:function(){this.flipswitch.removeClass("ui-flipswitch-active"),"SELECT"===this.type?this.element.get(0).selectedIndex=0:this.element.prop("checked",!1),this.element.trigger("change")},_right:function(){this.flipswitch.addClass("ui-flipswitch-active"),"SELECT"===this.type?this.element.get(0).selectedIndex=1:this.element.prop("checked",!0),this.element.trigger("change")},_enhance:function(){var b=a("<div>"),c=this.options,d=this.element,e=c.theme?c.theme:"inherit",f=a("<a></a>",{href:"#"}),g=a("<span></span>"),h=d.get(0).tagName,i="INPUT"===h?c.onText:d.find("option").eq(1).text(),j="INPUT"===h?c.offText:d.find("option").eq(0).text();f.addClass("ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit").text(i),g.addClass("ui-flipswitch-off").text(j),b.addClass("ui-flipswitch ui-shadow-inset ui-bar-"+e+" "+(c.wrapperClass?c.wrapperClass:"")+" "+(d.is(":checked")||d.find("option").eq(1).is(":selected")?"ui-flipswitch-active":"")+(d.is(":disabled")?" ui-state-disabled":"")+(c.corners?" ui-corner-all":"")+(c.mini?" ui-mini":"")).append(f,g),d.addClass("ui-flipswitch-input").after(b).appendTo(b),a.extend(this,{flipswitch:b,on:f,off:g,type:h})},_reset:function(){this.refresh()},refresh:function(){var a,b=this.flipswitch.hasClass("ui-flipswitch-active")?"_right":"_left";a="SELECT"===this.type?this.element.get(0).selectedIndex>0?"_right":"_left":this.element.prop("checked")?"_right":"_left",a!==b&&this[a]()},_toggle:function(){var a=this.flipswitch.hasClass("ui-flipswitch-active")?"_left":"_right";this[a]()},_keydown:function(b){b.which===a.mobile.keyCode.LEFT?this._left():b.which===a.mobile.keyCode.RIGHT?this._right():b.which===a.mobile.keyCode.SPACE&&(this._toggle(),b.preventDefault())},_setOptions:function(a){if(a.theme!==b){var c=a.theme?a.theme:"inherit",d=a.theme?a.theme:"inherit";this.widget().removeClass("ui-bar-"+c).addClass("ui-bar-"+d)}a.onText!==b&&this.on.text(a.onText),a.offText!==b&&this.off.text(a.offText),a.disabled!==b&&this.widget().toggleClass("ui-state-disabled",a.disabled),a.mini!==b&&this.widget().toggleClass("ui-mini",a.mini),a.corners!==b&&this.widget().toggleClass("ui-corner-all",a.corners),this._super(a)},_destroy:function(){this.options.enhanced||(null!=this._originalTabIndex?this.element.attr("tabindex",this._originalTabIndex):this.element.removeAttr("tabindex"),this.on.remove(),this.off.remove(),this.element.unwrap(),this.flipswitch.remove(),this.removeClass("ui-flipswitch-input"))}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.rangeslider",a.extend({options:{theme:null,trackTheme:null,corners:!0,mini:!1,highlight:!0},_create:function(){var b=this.element,c=this.options.mini?"ui-rangeslider ui-mini":"ui-rangeslider",d=b.find("input").first(),e=b.find("input").last(),f=b.find("label").first(),g=a.data(d.get(0),"mobile-slider")||a.data(d.slider().get(0),"mobile-slider"),h=a.data(e.get(0),"mobile-slider")||a.data(e.slider().get(0),"mobile-slider"),i=g.slider,j=h.slider,k=g.handle,l=a("<div class='ui-rangeslider-sliders' />").appendTo(b);d.addClass("ui-rangeslider-first"),e.addClass("ui-rangeslider-last"),b.addClass(c),i.appendTo(l),j.appendTo(l),f.insertBefore(b),k.prependTo(j),a.extend(this,{_inputFirst:d,_inputLast:e,_sliderFirst:i,_sliderLast:j,_label:f,_targetVal:null,_sliderTarget:!1,_sliders:l,_proxy:!1}),this.refresh(),this._on(this.element.find("input.ui-slider-input"),{slidebeforestart:"_slidebeforestart",slidestop:"_slidestop",slidedrag:"_slidedrag",slidebeforechange:"_change",blur:"_change",keyup:"_change"}),this._on({mousedown:"_change"}),this._on(this.element.closest("form"),{reset:"_handleReset"}),this._on(k,{vmousedown:"_dragFirstHandle"})},_handleReset:function(){var a=this;setTimeout(function(){a._updateHighlight()},0)},_dragFirstHandle:function(b){return a.data(this._inputFirst.get(0),"mobile-slider").dragging=!0,a.data(this._inputFirst.get(0),"mobile-slider").refresh(b),a.data(this._inputFirst.get(0),"mobile-slider")._trigger("start"),!1},_slidedrag:function(b){var c=a(b.target).is(this._inputFirst),d=c?this._inputLast:this._inputFirst;return this._sliderTarget=!1,"first"===this._proxy&&c||"last"===this._proxy&&!c?(a.data(d.get(0),"mobile-slider").dragging=!0,a.data(d.get(0),"mobile-slider").refresh(b),!1):void 0},_slidestop:function(b){var c=a(b.target).is(this._inputFirst);this._proxy=!1,this.element.find("input").trigger("vmouseup"),this._sliderFirst.css("z-index",c?1:"")},_slidebeforestart:function(b){this._sliderTarget=!1,a(b.originalEvent.target).hasClass("ui-slider-track")&&(this._sliderTarget=!0,this._targetVal=a(b.target).val())},_setOptions:function(a){a.theme!==b&&this._setTheme(a.theme),a.trackTheme!==b&&this._setTrackTheme(a.trackTheme),a.mini!==b&&this._setMini(a.mini),a.highlight!==b&&this._setHighlight(a.highlight),a.disabled!==b&&this._setDisabled(a.disabled),this._super(a),this.refresh()},refresh:function(){var a=this.element,b=this.options;(this._inputFirst.is(":disabled")||this._inputLast.is(":disabled"))&&(this.options.disabled=!0),a.find("input").slider({theme:b.theme,trackTheme:b.trackTheme,disabled:b.disabled,corners:b.corners,mini:b.mini,highlight:b.highlight}).slider("refresh"),this._updateHighlight()},_change:function(b){if("keyup"===b.type)return this._updateHighlight(),!1;var c=this,d=parseFloat(this._inputFirst.val(),10),e=parseFloat(this._inputLast.val(),10),f=a(b.target).hasClass("ui-rangeslider-first"),g=f?this._inputFirst:this._inputLast,h=f?this._inputLast:this._inputFirst;if(this._inputFirst.val()>this._inputLast.val()&&"mousedown"===b.type&&!a(b.target).hasClass("ui-slider-handle"))g.blur();else if("mousedown"===b.type)return;return d>e&&!this._sliderTarget?(g.val(f?e:d).slider("refresh"),this._trigger("normalize")):d>e&&(g.val(this._targetVal).slider("refresh"),setTimeout(function(){h.val(f?d:e).slider("refresh"),a.data(h.get(0),"mobile-slider").handle.focus(),c._sliderFirst.css("z-index",f?"":1),c._trigger("normalize")},0),this._proxy=f?"first":"last"),d===e?(a.data(g.get(0),"mobile-slider").handle.css("z-index",1),a.data(h.get(0),"mobile-slider").handle.css("z-index",0)):(a.data(h.get(0),"mobile-slider").handle.css("z-index",""),a.data(g.get(0),"mobile-slider").handle.css("z-index","")),this._updateHighlight(),d>=e?!1:void 0},_updateHighlight:function(){var b=parseInt(a.data(this._inputFirst.get(0),"mobile-slider").handle.get(0).style.left,10),c=parseInt(a.data(this._inputLast.get(0),"mobile-slider").handle.get(0).style.left,10),d=c-b;this.element.find(".ui-slider-bg").css({"margin-left":b+"%",width:d+"%"})},_setTheme:function(a){this._inputFirst.slider("option","theme",a),this._inputLast.slider("option","theme",a)},_setTrackTheme:function(a){this._inputFirst.slider("option","trackTheme",a),this._inputLast.slider("option","trackTheme",a)},_setMini:function(a){this._inputFirst.slider("option","mini",a),this._inputLast.slider("option","mini",a),this.element.toggleClass("ui-mini",!!a)},_setHighlight:function(a){this._inputFirst.slider("option","highlight",a),this._inputLast.slider("option","highlight",a)},_setDisabled:function(a){this._inputFirst.prop("disabled",a),this._inputLast.prop("disabled",a)},_destroy:function(){this._label.prependTo(this.element),this.element.removeClass("ui-rangeslider ui-mini"),this._inputFirst.after(this._sliderFirst),this._inputLast.after(this._sliderLast),this._sliders.remove(),this.element.find("input").removeClass("ui-rangeslider-first ui-rangeslider-last").slider("destroy")}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.textinput",a.mobile.textinput,{options:{clearBtn:!1,clearBtnText:"Clear text"},_create:function(){this._super(),this.isSearch&&(this.options.clearBtn=!0),this.options.clearBtn&&this.inputNeedsWrap&&this._addClearBtn()},clearButton:function(){return a("<a href='#' tabindex='-1' aria-hidden='true' class='ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all'></a>").attr("title",this.options.clearBtnText).text(this.options.clearBtnText)},_clearBtnClick:function(a){this.element.val("").focus().trigger("change"),this._clearBtn.addClass("ui-input-clear-hidden"),a.preventDefault()},_addClearBtn:function(){this.options.enhanced||this._enhanceClear(),a.extend(this,{_clearBtn:this.widget().find("a.ui-input-clear")}),this._bindClearEvents(),this._toggleClear()},_enhanceClear:function(){this.clearButton().appendTo(this.widget()),this.widget().addClass("ui-input-has-clear")},_bindClearEvents:function(){this._on(this._clearBtn,{click:"_clearBtnClick"}),this._on({keyup:"_toggleClear",change:"_toggleClear",input:"_toggleClear",focus:"_toggleClear",blur:"_toggleClear",cut:"_toggleClear",paste:"_toggleClear"})},_unbindClear:function(){this._off(this._clearBtn,"click"),this._off(this.element,"keyup change input focus blur cut paste")},_setOptions:function(a){this._super(a),a.clearBtn===b||this.element.is("textarea, :jqmData(type='range')")||(a.clearBtn?this._addClearBtn():this._destroyClear()),a.clearBtnText!==b&&this._clearBtn!==b&&this._clearBtn.text(a.clearBtnText).attr("title",a.clearBtnText)},_toggleClear:function(){this._delay("_toggleClearClass",0)},_toggleClearClass:function(){this._clearBtn.toggleClass("ui-input-clear-hidden",!this.element.val())},_destroyClear:function(){this.widget().removeClass("ui-input-has-clear"),this._unbindClear(),this._clearBtn.remove()},_destroy:function(){this._super(),this.options.clearBtn&&this._destroyClear()}})}(a),function(a,b){a.widget("mobile.textinput",a.mobile.textinput,{options:{autogrow:!0,keyupTimeoutBuffer:100},_create:function(){this._super(),this.options.autogrow&&this.isTextarea&&this._autogrow()},_autogrow:function(){this.element.addClass("ui-textinput-autogrow"),this._on({keyup:"_timeout",change:"_timeout",input:"_timeout",paste:"_timeout"}),this._on(!0,this.document,{pageshow:"_handleShow",popupbeforeposition:"_handleShow",updatelayout:"_handleShow",panelopen:"_handleShow"})},_handleShow:function(b){a.contains(b.target,this.element[0])&&this.element.is(":visible")&&("popupbeforeposition"!==b.type&&this.element.addClass("ui-textinput-autogrow-resize").animationComplete(a.proxy(function(){this.element.removeClass("ui-textinput-autogrow-resize")},this),"transition"),this._prepareHeightUpdate())},_unbindAutogrow:function(){this.element.removeClass("ui-textinput-autogrow"),this._off(this.element,"keyup change input paste"),this._off(this.document,"pageshow popupbeforeposition updatelayout panelopen")},keyupTimeout:null,_prepareHeightUpdate:function(a){this.keyupTimeout&&clearTimeout(this.keyupTimeout),a===b?this._updateHeight():this.keyupTimeout=this._delay("_updateHeight",a)},_timeout:function(){this._prepareHeightUpdate(this.options.keyupTimeoutBuffer)},_updateHeight:function(){var a,b,c,d,e,f,g,h,i,j=this.window.scrollTop();this.keyupTimeout=0,"onpage"in this.element[0]||this.element.css({height:0,"min-height":0,"max-height":0}),d=this.element[0].scrollHeight,e=this.element[0].clientHeight,f=parseFloat(this.element.css("border-top-width")),g=parseFloat(this.element.css("border-bottom-width")),h=f+g,i=d+h+15,0===e&&(a=parseFloat(this.element.css("padding-top")),b=parseFloat(this.element.css("padding-bottom")),c=a+b,i+=c),this.element.css({height:i,"min-height":"","max-height":""}),this.window.scrollTop(j)},refresh:function(){this.options.autogrow&&this.isTextarea&&this._updateHeight()},_setOptions:function(a){this._super(a),a.autogrow!==b&&this.isTextarea&&(a.autogrow?this._autogrow():this._unbindAutogrow())}})}(a),function(a){a.widget("mobile.selectmenu",a.extend({initSelector:"select:not( :jqmData(role='slider')):not( :jqmData(role='flipswitch') )",options:{theme:null,icon:"carat-d",iconpos:"right",inline:!1,corners:!0,shadow:!0,iconshadow:!1,overlayTheme:null,dividerTheme:null,hidePlaceholderMenuItems:!0,closeText:"Close",nativeMenu:!0,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,mini:!1},_button:function(){return a("<div/>")},_setDisabled:function(a){return this.element.attr("disabled",a),this.button.attr("aria-disabled",a),this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var b=this.options.inline||this.element.jqmData("inline"),c=this.options.mini||this.element.jqmData("mini"),d="";~this.element[0].className.indexOf("ui-btn-left")&&(d=" ui-btn-left"),~this.element[0].className.indexOf("ui-btn-right")&&(d=" ui-btn-right"),b&&(d+=" ui-btn-inline"),c&&(d+=" ui-mini"),this.select=this.element.removeClass("ui-btn-left ui-btn-right").wrap("<div class='ui-select"+d+"'>"),this.selectId=this.select.attr("id")||"select-"+this.uuid,this.buttonId=this.selectId+"-button",this.label=a("label[for='"+this.selectId+"']"),this.isMultiple=this.select[0].multiple},_destroy:function(){var a=this.element.parents(".ui-select");a.length>0&&(a.is(".ui-btn-left, .ui-btn-right")&&this.element.addClass(a.hasClass("ui-btn-left")?"ui-btn-left":"ui-btn-right"),this.element.insertAfter(a),a.remove())},_create:function(){this._preExtension(),this.button=this._button();var c=this,d=this.options,e=d.icon?d.iconpos||this.select.jqmData("iconpos"):!1,f=this.button.insertBefore(this.select).attr("id",this.buttonId).addClass("ui-btn"+(d.icon?" ui-icon-"+d.icon+" ui-btn-icon-"+e+(d.iconshadow?" ui-shadow-icon":""):"")+(d.theme?" ui-btn-"+d.theme:"")+(d.corners?" ui-corner-all":"")+(d.shadow?" ui-shadow":""));this.setButtonText(),d.nativeMenu&&b.opera&&b.opera.version&&f.addClass("ui-select-nativeonly"),this.isMultiple&&(this.buttonCount=a("<span>").addClass("ui-li-count ui-body-inherit").hide().appendTo(f.addClass("ui-li-has-count"))),(d.disabled||this.element.attr("disabled"))&&this.disable(),this.select.change(function(){c.refresh(),d.nativeMenu&&c._delay(function(){c.select.blur()})}),this._handleFormReset(),this._on(this.button,{keydown:"_handleKeydown"}),this.build()},build:function(){var b=this;this.select.appendTo(b.button).bind("vmousedown",function(){b.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){b.button.addClass(a.mobile.focusClass)}).bind("blur",function(){b.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){b.button.trigger("vmouseover")}).bind("vmousemove",function(){b.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){b.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}),b.button.bind("vmousedown",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.label.bind("click focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.select.bind("focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.button.bind("mouseup",function(){b.options.preventFocusZoom&&setTimeout(function(){a.mobile.zoom.enable(!0)},0)}),b.select.bind("blur",function(){b.options.preventFocusZoom&&a.mobile.zoom.enable(!0)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var b=this,d=this.selected(),e=this.placeholder,f=a(c.createElement("span"));this.button.children("span").not(".ui-li-count").remove().end().end().prepend(function(){return e=d.length?d.map(function(){return a(this).text()}).get().join(", "):b.placeholder,e?f.text(e):f.html("&#160;"),f.addClass(b.select.attr("class")).addClass(d.attr("class")).removeClass("ui-screen-hidden")}())},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},_handleKeydown:function(){this._delay("_refreshButton")},_reset:function(){this.refresh()},_refreshButton:function(){this.setButtonText(),this.setButtonCount()},refresh:function(){this._refreshButton()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(!0),this.button.addClass("ui-state-disabled")},enable:function(){this._setDisabled(!1),this.button.removeClass("ui-state-disabled")}},a.mobile.behaviors.formReset))}(a),function(a){a.mobile.links=function(b){a(b).find("a").jqmEnhanceable().filter(":jqmData(rel='popup')[href][href!='']").each(function(){var a=this,b=a.getAttribute("href").substring(1);b&&(a.setAttribute("aria-haspopup",!0),a.setAttribute("aria-owns",b),a.setAttribute("aria-expanded",!1))}).end().not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")}}(a),function(a,c){function d(a,b,c,d){var e=d;return e=b>a?c+(a-b)/2:Math.min(Math.max(c,d-b/2),c+a-b)}function e(a){return{x:a.scrollLeft(),y:a.scrollTop(),cx:a[0].innerWidth||a.width(),cy:a[0].innerHeight||a.height()}}a.widget("mobile.popup",{options:{wrapperClass:null,theme:null,overlayTheme:null,shadow:!0,corners:!0,transition:"none",positionTo:"origin",tolerance:null,closeLinkSelector:"a:jqmData(rel='back')",closeLinkEvents:"click.popup",navigateEvents:"navigate.popup",closeEvents:"navigate.popup pagebeforechange.popup",dismissible:!0,enhanced:!1,history:!a.mobile.browser.oldIE},_handleDocumentVmousedown:function(b){this._isOpen&&a.contains(this._ui.container[0],b.target)&&this._ignoreResizeEvents()},_create:function(){var b=this.element,c=b.attr("id"),d=this.options;d.history=d.history&&a.mobile.ajaxEnabled&&a.mobile.hashListeningEnabled,this._on(this.document,{vmousedown:"_handleDocumentVmousedown"}),a.extend(this,{_scrollTop:0,_page:b.closest(".ui-page"),_ui:null,_fallbackTransition:"",_currentTransition:!1,_prerequisites:null,_isOpen:!1,_tolerance:null,_resizeData:null,_ignoreResizeTo:0,_orientationchangeInProgress:!1}),0===this._page.length&&(this._page=a("body")),d.enhanced?this._ui={container:b.parent(),screen:b.parent().prev(),placeholder:a(this.document[0].getElementById(c+"-placeholder"))}:(this._ui=this._enhance(b,c),this._applyTransition(d.transition)),this._setTolerance(d.tolerance)._ui.focusElement=this._ui.container,this._on(this._ui.screen,{vclick:"_eatEventAndClose"}),this._on(this.window,{orientationchange:a.proxy(this,"_handleWindowOrientationchange"),resize:a.proxy(this,"_handleWindowResize"),keyup:a.proxy(this,"_handleWindowKeyUp")}),this._on(this.document,{focusin:"_handleDocumentFocusIn"})},_enhance:function(b,c){var d=this.options,e=d.wrapperClass,f={screen:a("<div class='ui-screen-hidden ui-popup-screen "+this._themeClassFromOption("ui-overlay-",d.overlayTheme)+"'></div>"),placeholder:a("<div style='display: none;'><!-- placeholder --></div>"),container:a("<div class='ui-popup-container ui-popup-hidden ui-popup-truncate"+(e?" "+e:"")+"'></div>")},g=this.document[0].createDocumentFragment();return g.appendChild(f.screen[0]),g.appendChild(f.container[0]),c&&(f.screen.attr("id",c+"-screen"),f.container.attr("id",c+"-popup"),f.placeholder.attr("id",c+"-placeholder").html("<!-- placeholder for "+c+" -->")),this._page[0].appendChild(g),f.placeholder.insertAfter(b),b.detach().addClass("ui-popup "+this._themeClassFromOption("ui-body-",d.theme)+" "+(d.shadow?"ui-overlay-shadow ":"")+(d.corners?"ui-corner-all ":"")).appendTo(f.container),f},_eatEventAndClose:function(a){return a.preventDefault(),a.stopImmediatePropagation(),this.options.dismissible&&this.close(),!1},_resizeScreen:function(){var a=this._ui.screen,b=this._ui.container.outerHeight(!0),c=a.removeAttr("style").height(),d=this.document.height()-1;d>c?a.height(d):b>c&&a.height(b)},_handleWindowKeyUp:function(b){return this._isOpen&&b.keyCode===a.mobile.keyCode.ESCAPE?this._eatEventAndClose(b):void 0},_expectResizeEvent:function(){var a=e(this.window);
+if(this._resizeData){if(a.x===this._resizeData.windowCoordinates.x&&a.y===this._resizeData.windowCoordinates.y&&a.cx===this._resizeData.windowCoordinates.cx&&a.cy===this._resizeData.windowCoordinates.cy)return!1;clearTimeout(this._resizeData.timeoutId)}return this._resizeData={timeoutId:this._delay("_resizeTimeout",200),windowCoordinates:a},!0},_resizeTimeout:function(){this._isOpen?this._expectResizeEvent()||(this._ui.container.hasClass("ui-popup-hidden")&&(this._ui.container.removeClass("ui-popup-hidden ui-popup-truncate"),this.reposition({positionTo:"window"}),this._ignoreResizeEvents()),this._resizeScreen(),this._resizeData=null,this._orientationchangeInProgress=!1):(this._resizeData=null,this._orientationchangeInProgress=!1)},_stopIgnoringResizeEvents:function(){this._ignoreResizeTo=0},_ignoreResizeEvents:function(){this._ignoreResizeTo&&clearTimeout(this._ignoreResizeTo),this._ignoreResizeTo=this._delay("_stopIgnoringResizeEvents",1e3)},_handleWindowResize:function(){this._isOpen&&0===this._ignoreResizeTo&&(!this._expectResizeEvent()&&!this._orientationchangeInProgress||this._ui.container.hasClass("ui-popup-hidden")||this._ui.container.addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style"))},_handleWindowOrientationchange:function(){!this._orientationchangeInProgress&&this._isOpen&&0===this._ignoreResizeTo&&(this._expectResizeEvent(),this._orientationchangeInProgress=!0)},_handleDocumentFocusIn:function(b){var c,d=b.target,e=this._ui;if(this._isOpen){if(d!==e.container[0]){if(c=a(d),!a.contains(e.container[0],d))return a(this.document[0].activeElement).one("focus",a.proxy(function(){this._safelyBlur(d)},this)),e.focusElement.focus(),b.preventDefault(),b.stopImmediatePropagation(),!1;e.focusElement[0]===e.container[0]&&(e.focusElement=c)}this._ignoreResizeEvents()}},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:a+"inherit"},_applyTransition:function(b){return b&&(this._ui.container.removeClass(this._fallbackTransition),"none"!==b&&(this._fallbackTransition=a.mobile._maybeDegradeTransition(b),"none"===this._fallbackTransition&&(this._fallbackTransition=""),this._ui.container.addClass(this._fallbackTransition))),this},_setOptions:function(a){var b=this.options,d=this.element,e=this._ui.screen;return a.wrapperClass!==c&&this._ui.container.removeClass(b.wrapperClass).addClass(a.wrapperClass),a.theme!==c&&d.removeClass(this._themeClassFromOption("ui-body-",b.theme)).addClass(this._themeClassFromOption("ui-body-",a.theme)),a.overlayTheme!==c&&(e.removeClass(this._themeClassFromOption("ui-overlay-",b.overlayTheme)).addClass(this._themeClassFromOption("ui-overlay-",a.overlayTheme)),this._isOpen&&e.addClass("in")),a.shadow!==c&&d.toggleClass("ui-overlay-shadow",a.shadow),a.corners!==c&&d.toggleClass("ui-corner-all",a.corners),a.transition!==c&&(this._currentTransition||this._applyTransition(a.transition)),a.tolerance!==c&&this._setTolerance(a.tolerance),a.disabled!==c&&a.disabled&&this.close(),this._super(a)},_setTolerance:function(b){var d,e={t:30,r:15,b:30,l:15};if(b!==c)switch(d=String(b).split(","),a.each(d,function(a,b){d[a]=parseInt(b,10)}),d.length){case 1:isNaN(d[0])||(e.t=e.r=e.b=e.l=d[0]);break;case 2:isNaN(d[0])||(e.t=e.b=d[0]),isNaN(d[1])||(e.l=e.r=d[1]);break;case 4:isNaN(d[0])||(e.t=d[0]),isNaN(d[1])||(e.r=d[1]),isNaN(d[2])||(e.b=d[2]),isNaN(d[3])||(e.l=d[3])}return this._tolerance=e,this},_clampPopupWidth:function(a){var b,c=e(this.window),d={x:this._tolerance.l,y:c.y+this._tolerance.t,cx:c.cx-this._tolerance.l-this._tolerance.r,cy:c.cy-this._tolerance.t-this._tolerance.b};return a||this._ui.container.css("max-width",d.cx),b={cx:this._ui.container.outerWidth(!0),cy:this._ui.container.outerHeight(!0)},{rc:d,menuSize:b}},_calculateFinalLocation:function(a,b){var c,e=b.rc,f=b.menuSize;return c={left:d(e.cx,f.cx,e.x,a.x),top:d(e.cy,f.cy,e.y,a.y)},c.top=Math.max(0,c.top),c.top-=Math.min(c.top,Math.max(0,c.top+f.cy-this.document.height())),c},_placementCoords:function(a){return this._calculateFinalLocation(a,this._clampPopupWidth())},_createPrerequisites:function(b,c,d){var e,f=this;e={screen:a.Deferred(),container:a.Deferred()},e.screen.then(function(){e===f._prerequisites&&b()}),e.container.then(function(){e===f._prerequisites&&c()}),a.when(e.screen,e.container).done(function(){e===f._prerequisites&&(f._prerequisites=null,d())}),f._prerequisites=e},_animate:function(b){return this._ui.screen.removeClass(b.classToRemove).addClass(b.screenClassToAdd),b.prerequisites.screen.resolve(),b.transition&&"none"!==b.transition&&(b.applyTransition&&this._applyTransition(b.transition),this._fallbackTransition)?void this._ui.container.addClass(b.containerClassToAdd).removeClass(b.classToRemove).animationComplete(a.proxy(b.prerequisites.container,"resolve")):(this._ui.container.removeClass(b.classToRemove),void b.prerequisites.container.resolve())},_desiredCoords:function(b){var c,d=null,f=e(this.window),g=b.x,h=b.y,i=b.positionTo;if(i&&"origin"!==i)if("window"===i)g=f.cx/2+f.x,h=f.cy/2+f.y;else{try{d=a(i)}catch(j){d=null}d&&(d.filter(":visible"),0===d.length&&(d=null))}return d&&(c=d.offset(),g=c.left+d.outerWidth()/2,h=c.top+d.outerHeight()/2),("number"!==a.type(g)||isNaN(g))&&(g=f.cx/2+f.x),("number"!==a.type(h)||isNaN(h))&&(h=f.cy/2+f.y),{x:g,y:h}},_reposition:function(a){a={x:a.x,y:a.y,positionTo:a.positionTo},this._trigger("beforeposition",c,a),this._ui.container.offset(this._placementCoords(this._desiredCoords(a)))},reposition:function(a){this._isOpen&&this._reposition(a)},_safelyBlur:function(b){b!==this.window[0]&&"body"!==b.nodeName.toLowerCase()&&a(b).blur()},_openPrerequisitesComplete:function(){var b=this.element.attr("id"),c=this._ui.container.find(":focusable").first();this._ui.container.addClass("ui-popup-active"),this._isOpen=!0,this._resizeScreen(),a.contains(this._ui.container[0],this.document[0].activeElement)||this._safelyBlur(this.document[0].activeElement),c.length>0&&(this._ui.focusElement=c),this._ignoreResizeEvents(),b&&this.document.find("[aria-haspopup='true'][aria-owns='"+b+"']").attr("aria-expanded",!0),this._trigger("afteropen")},_open:function(b){var c=a.extend({},this.options,b),d=function(){var a=navigator.userAgent,b=a.match(/AppleWebKit\/([0-9\.]+)/),c=!!b&&b[1],d=a.match(/Android (\d+(?:\.\d+))/),e=!!d&&d[1],f=a.indexOf("Chrome")>-1;return null!==d&&"4.0"===e&&c&&c>534.13&&!f?!0:!1}();this._createPrerequisites(a.noop,a.noop,a.proxy(this,"_openPrerequisitesComplete")),this._currentTransition=c.transition,this._applyTransition(c.transition),this._ui.screen.removeClass("ui-screen-hidden"),this._ui.container.removeClass("ui-popup-truncate"),this._reposition(c),this._ui.container.removeClass("ui-popup-hidden"),this.options.overlayTheme&&d&&this.element.closest(".ui-page").addClass("ui-popup-open"),this._animate({additionalCondition:!0,transition:c.transition,classToRemove:"",screenClassToAdd:"in",containerClassToAdd:"in",applyTransition:!1,prerequisites:this._prerequisites})},_closePrerequisiteScreen:function(){this._ui.screen.removeClass("out").addClass("ui-screen-hidden")},_closePrerequisiteContainer:function(){this._ui.container.removeClass("reverse out").addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style")},_closePrerequisitesDone:function(){var b=this._ui.container,d=this.element.attr("id");a.mobile.popup.active=c,a(":focus",b[0]).add(b[0]).blur(),d&&this.document.find("[aria-haspopup='true'][aria-owns='"+d+"']").attr("aria-expanded",!1),this._trigger("afterclose")},_close:function(b){this._ui.container.removeClass("ui-popup-active"),this._page.removeClass("ui-popup-open"),this._isOpen=!1,this._createPrerequisites(a.proxy(this,"_closePrerequisiteScreen"),a.proxy(this,"_closePrerequisiteContainer"),a.proxy(this,"_closePrerequisitesDone")),this._animate({additionalCondition:this._ui.screen.hasClass("in"),transition:b?"none":this._currentTransition,classToRemove:"in",screenClassToAdd:"out",containerClassToAdd:"reverse out",applyTransition:!0,prerequisites:this._prerequisites})},_unenhance:function(){this.options.enhanced||(this._setOptions({theme:a.mobile.popup.prototype.options.theme}),this.element.detach().insertAfter(this._ui.placeholder).removeClass("ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit"),this._ui.screen.remove(),this._ui.container.remove(),this._ui.placeholder.remove())},_destroy:function(){return a.mobile.popup.active===this?(this.element.one("popupafterclose",a.proxy(this,"_unenhance")),this.close()):this._unenhance(),this},_closePopup:function(c,d){var e,f,g=this.options,h=!1;c&&c.isDefaultPrevented()||a.mobile.popup.active!==this||(b.scrollTo(0,this._scrollTop),c&&"pagebeforechange"===c.type&&d&&(e="string"==typeof d.toPage?d.toPage:d.toPage.jqmData("url"),e=a.mobile.path.parseUrl(e),f=e.pathname+e.search+e.hash,this._myUrl!==a.mobile.path.makeUrlAbsolute(f)?h=!0:c.preventDefault()),this.window.off(g.closeEvents),this.element.undelegate(g.closeLinkSelector,g.closeLinkEvents),this._close(h))},_bindContainerClose:function(){this.window.on(this.options.closeEvents,a.proxy(this,"_closePopup"))},widget:function(){return this._ui.container},open:function(b){var c,d,e,f,g,h,i=this,j=this.options;return a.mobile.popup.active||j.disabled?this:(a.mobile.popup.active=this,this._scrollTop=this.window.scrollTop(),j.history?(h=a.mobile.navigate.history,d=a.mobile.dialogHashKey,e=a.mobile.activePage,f=e?e.hasClass("ui-dialog"):!1,this._myUrl=c=h.getActive().url,(g=c.indexOf(d)>-1&&!f&&h.activeIndex>0)?(i._open(b),i._bindContainerClose(),this):(-1!==c.indexOf(d)||f?c=a.mobile.path.parseLocation().hash+d:c+=c.indexOf("#")>-1?d:"#"+d,this.window.one("beforenavigate",function(a){a.preventDefault(),i._open(b),i._bindContainerClose()}),this.urlAltered=!0,a.mobile.navigate(c,{role:"dialog"}),this)):(i._open(b),i._bindContainerClose(),i.element.delegate(j.closeLinkSelector,j.closeLinkEvents,function(a){i.close(),a.preventDefault()}),this))},close:function(){return a.mobile.popup.active!==this?this:(this._scrollTop=this.window.scrollTop(),this.options.history&&this.urlAltered?(a.mobile.back(),this.urlAltered=!1):this._closePopup(),this)}}),a.mobile.popup.handleLink=function(b){var c,d=a.mobile.path,e=a(d.hashToSelector(d.parseUrl(b.attr("href")).hash)).first();e.length>0&&e.data("mobile-popup")&&(c=b.offset(),e.popup("open",{x:c.left+b.outerWidth()/2,y:c.top+b.outerHeight()/2,transition:b.jqmData("transition"),positionTo:b.jqmData("position-to")})),setTimeout(function(){b.removeClass(a.mobile.activeBtnClass)},300)},a.mobile.document.on("pagebeforechange",function(b,c){"popup"===c.options.role&&(a.mobile.popup.handleLink(c.options.link),b.preventDefault())})}(a),function(a,b){var d=".ui-disabled,.ui-state-disabled,.ui-li-divider,.ui-screen-hidden,:jqmData(role='placeholder')",e=function(a,b,c){var e=a[c+"All"]().not(d).first();e.length&&(b.blur().attr("tabindex","-1"),e.find("a").first().focus())};a.widget("mobile.selectmenu",a.mobile.selectmenu,{_create:function(){var a=this.options;return a.nativeMenu=a.nativeMenu||this.element.parents(":jqmData(role='popup'),:mobile-popup").length>0,this._super()},_handleSelectFocus:function(){this.element.blur(),this.button.focus()},_handleKeydown:function(a){this._super(a),this._handleButtonVclickKeydown(a)},_handleButtonVclickKeydown:function(b){this.options.disabled||this.isOpen||this.options.nativeMenu||("vclick"===b.type||b.keyCode&&(b.keyCode===a.mobile.keyCode.ENTER||b.keyCode===a.mobile.keyCode.SPACE))&&(this._decideFormat(),"overlay"===this.menuType?this.button.attr("href","#"+this.popupId).attr("data-"+(a.mobile.ns||"")+"rel","popup"):this.button.attr("href","#"+this.dialogId).attr("data-"+(a.mobile.ns||"")+"rel","dialog"),this.isOpen=!0)},_handleListFocus:function(b){var c="focusin"===b.type?{tabindex:"0",event:"vmouseover"}:{tabindex:"-1",event:"vmouseout"};a(b.target).attr("tabindex",c.tabindex).trigger(c.event)},_handleListKeydown:function(b){var c=a(b.target),d=c.closest("li");switch(b.keyCode){case 38:return e(d,c,"prev"),!1;case 40:return e(d,c,"next"),!1;case 13:case 32:return c.trigger("click"),!1}},_handleMenuPageHide:function(){this._delayedTrigger(),this.thisPage.page("bindRemove")},_handleHeaderCloseClick:function(){return"overlay"===this.menuType?(this.close(),!1):void 0},_handleListItemClick:function(b){var c=a(b.target).closest("li"),d=this.select[0].selectedIndex,e=a.mobile.getAttribute(c,"option-index"),f=this._selectOptions().eq(e)[0];f.selected=this.isMultiple?!f.selected:!0,this.isMultiple&&c.find("a").toggleClass("ui-checkbox-on",f.selected).toggleClass("ui-checkbox-off",!f.selected),this.isMultiple||d===e||(this._triggerChange=!0),this.isMultiple?(this.select.trigger("change"),this.list.find("li:not(.ui-li-divider)").eq(e).find("a").first().focus()):this.close(),b.preventDefault()},build:function(){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=this.options;return v.nativeMenu?this._super():(c=this.selectId,d=c+"-listbox",e=c+"-dialog",f=this.label,g=this.element.closest(".ui-page"),h=this.element[0].multiple,i=c+"-menu",j=v.theme?" data-"+a.mobile.ns+"theme='"+v.theme+"'":"",k=v.overlayTheme||v.theme||null,l=k?" data-"+a.mobile.ns+"overlay-theme='"+k+"'":"",m=v.dividerTheme&&h?" data-"+a.mobile.ns+"divider-theme='"+v.dividerTheme+"'":"",n=a("<div data-"+a.mobile.ns+"role='dialog' class='ui-selectmenu' id='"+e+"'"+j+l+"><div data-"+a.mobile.ns+"role='header'><div class='ui-title'></div></div><div data-"+a.mobile.ns+"role='content'></div></div>"),o=a("<div"+j+l+" id='"+d+"' class='ui-selectmenu'></div>").insertAfter(this.select).popup(),p=a("<ul class='ui-selectmenu-list' id='"+i+"' role='listbox' aria-labelledby='"+this.buttonId+"'"+j+m+"></ul>").appendTo(o),q=a("<div class='ui-header ui-bar-"+(v.theme?v.theme:"inherit")+"'></div>").prependTo(o),r=a("<h1 class='ui-title'></h1>").appendTo(q),this.isMultiple&&(u=a("<a>",{role:"button",text:v.closeText,href:"#","class":"ui-btn ui-corner-all ui-btn-left ui-btn-icon-notext ui-icon-delete"}).appendTo(q)),a.extend(this,{selectId:c,menuId:i,popupId:d,dialogId:e,thisPage:g,menuPage:n,label:f,isMultiple:h,theme:v.theme,listbox:o,list:p,header:q,headerTitle:r,headerClose:u,menuPageContent:s,menuPageClose:t,placeholder:""}),this.refresh(),this._origTabIndex===b&&(this._origTabIndex=null===this.select[0].getAttribute("tabindex")?!1:this.select.attr("tabindex")),this.select.attr("tabindex","-1"),this._on(this.select,{focus:"_handleSelectFocus"}),this._on(this.button,{vclick:"_handleButtonVclickKeydown"}),this.list.attr("role","listbox"),this._on(this.list,{focusin:"_handleListFocus",focusout:"_handleListFocus",keydown:"_handleListKeydown","click li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)":"_handleListItemClick"}),this._on(this.menuPage,{pagehide:"_handleMenuPageHide"}),this._on(this.listbox,{popupafterclose:"_popupClosed"}),this.isMultiple&&this._on(this.headerClose,{click:"_handleHeaderCloseClick"}),this)},_popupClosed:function(){this.close(),this._delayedTrigger()},_delayedTrigger:function(){this._triggerChange&&this.element.trigger("change"),this._triggerChange=!1},_isRebuildRequired:function(){var a=this.list.find("li"),b=this._selectOptions().not(".ui-screen-hidden");return b.text()!==a.text()},selected:function(){return this._selectOptions().filter(":selected:not( :jqmData(placeholder='true') )")},refresh:function(b){var c,d;return this.options.nativeMenu?this._super(b):(c=this,(b||this._isRebuildRequired())&&c._buildList(),d=this.selectedIndices(),c.setButtonText(),c.setButtonCount(),void c.list.find("li:not(.ui-li-divider)").find("a").removeClass(a.mobile.activeBtnClass).end().attr("aria-selected",!1).each(function(b){var e=a(this);a.inArray(b,d)>-1?(e.attr("aria-selected",!0),c.isMultiple?e.find("a").removeClass("ui-checkbox-off").addClass("ui-checkbox-on"):e.hasClass("ui-screen-hidden")?e.next().find("a").addClass(a.mobile.activeBtnClass):e.find("a").addClass(a.mobile.activeBtnClass)):c.isMultiple&&e.find("a").removeClass("ui-checkbox-on").addClass("ui-checkbox-off")}))},close:function(){if(!this.options.disabled&&this.isOpen){var a=this;"page"===a.menuType?(a.menuPage.dialog("close"),a.list.appendTo(a.listbox)):a.listbox.popup("close"),a._focusButton(),a.isOpen=!1}},open:function(){this.button.click()},_focusMenuItem:function(){var b=this.list.find("a."+a.mobile.activeBtnClass);0===b.length&&(b=this.list.find("li:not("+d+") a.ui-btn")),b.first().focus()},_decideFormat:function(){var b=this,c=this.window,d=b.list.parent(),e=d.outerHeight(),f=c.scrollTop(),g=b.button.offset().top,h=c.height();e>h-80||!a.support.scrollTop?(b.menuPage.appendTo(a.mobile.pageContainer).page(),b.menuPageContent=b.menuPage.find(".ui-content"),b.menuPageClose=b.menuPage.find(".ui-header a"),b.thisPage.unbind("pagehide.remove"),0===f&&g>h&&b.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",g)}),b.menuPage.one({pageshow:a.proxy(this,"_focusMenuItem"),pagehide:a.proxy(this,"close")}),b.menuType="page",b.menuPageContent.append(b.list),b.menuPage.find("div .ui-title").text(b.label.getEncodedText()||b.placeholder)):(b.menuType="overlay",b.listbox.one({popupafteropen:a.proxy(this,"_focusMenuItem")}))},_buildList:function(){var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q=this,r=this.options,s=this.placeholder,t=!0,u="false",v="data-"+a.mobile.ns,w=v+"option-index",x=v+"icon",y=v+"role",z=v+"placeholder",A=c.createDocumentFragment(),B=!1;for(q.list.empty().filter(".ui-listview").listview("destroy"),b=this._selectOptions(),d=b.length,e=this.select[0],g=0;d>g;g++,B=!1)h=b[g],i=a(h),i.hasClass("ui-screen-hidden")||(j=h.parentNode,m=[],k=i.text(),l=c.createElement("a"),l.setAttribute("href","#"),l.appendChild(c.createTextNode(k)),j!==e&&"optgroup"===j.nodeName.toLowerCase()&&(n=j.getAttribute("label"),n!==f&&(o=c.createElement("li"),o.setAttribute(y,"list-divider"),o.setAttribute("role","option"),o.setAttribute("tabindex","-1"),o.appendChild(c.createTextNode(n)),A.appendChild(o),f=n)),!t||h.getAttribute("value")&&0!==k.length&&!i.jqmData("placeholder")||(t=!1,B=!0,null===h.getAttribute(z)&&(this._removePlaceholderAttr=!0),h.setAttribute(z,!0),r.hidePlaceholderMenuItems&&m.push("ui-screen-hidden"),s!==k&&(s=q.placeholder=k)),p=c.createElement("li"),h.disabled&&(m.push("ui-state-disabled"),p.setAttribute("aria-disabled",!0)),p.setAttribute(w,g),p.setAttribute(x,u),B&&p.setAttribute(z,!0),p.className=m.join(" "),p.setAttribute("role","option"),l.setAttribute("tabindex","-1"),this.isMultiple&&a(l).addClass("ui-btn ui-checkbox-off ui-btn-icon-right"),p.appendChild(l),A.appendChild(p));q.list[0].appendChild(A),this.isMultiple||s.length?this.headerTitle.text(this.placeholder):this.header.addClass("ui-screen-hidden"),q.list.listview()},_button:function(){return this.options.nativeMenu?this._super():a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})},_destroy:function(){this.options.nativeMenu||(this.close(),this._origTabIndex!==b&&(this._origTabIndex!==!1?this.select.attr("tabindex",this._origTabIndex):this.select.removeAttr("tabindex")),this._removePlaceholderAttr&&this._selectOptions().removeAttr("data-"+a.mobile.ns+"placeholder"),this.listbox.remove(),this.menuPage.remove()),this._super()}})}(a),function(a,b){function c(a,b){var c=b?b:[];return c.push("ui-btn"),a.theme&&c.push("ui-btn-"+a.theme),a.icon&&(c=c.concat(["ui-icon-"+a.icon,"ui-btn-icon-"+a.iconpos]),a.iconshadow&&c.push("ui-shadow-icon")),a.inline&&c.push("ui-btn-inline"),a.shadow&&c.push("ui-shadow"),a.corners&&c.push("ui-corner-all"),a.mini&&c.push("ui-mini"),c}function d(a){var c,d,e,g=!1,h=!0,i={icon:"",inline:!1,shadow:!1,corners:!1,iconshadow:!1,mini:!1},j=[];for(a=a.split(" "),c=0;c<a.length;c++)e=!0,d=f[a[c]],d!==b?(e=!1,i[d]=!0):0===a[c].indexOf("ui-btn-icon-")?(e=!1,h=!1,i.iconpos=a[c].substring(12)):0===a[c].indexOf("ui-icon-")?(e=!1,i.icon=a[c].substring(8)):0===a[c].indexOf("ui-btn-")&&8===a[c].length?(e=!1,i.theme=a[c].substring(7)):"ui-btn"===a[c]&&(e=!1,g=!0),e&&j.push(a[c]);return h&&(i.icon=""),{options:i,unknownClasses:j,alreadyEnhanced:g}}function e(a){return"-"+a.toLowerCase()}var f={"ui-shadow":"shadow","ui-corner-all":"corners","ui-btn-inline":"inline","ui-shadow-icon":"iconshadow","ui-mini":"mini"},g=function(){var c=a.mobile.getAttribute.apply(this,arguments);return null==c?b:c},h=/[A-Z]/g;a.fn.buttonMarkup=function(f,i){var j,k,l,m,n,o=a.fn.buttonMarkup.defaults;for(j=0;j<this.length;j++){if(l=this[j],k=i?{alreadyEnhanced:!1,unknownClasses:[]}:d(l.className),m=a.extend({},k.alreadyEnhanced?k.options:{},f),!k.alreadyEnhanced)for(n in o)m[n]===b&&(m[n]=g(l,n.replace(h,e)));l.className=c(a.extend({},o,m),k.unknownClasses).join(" "),"button"!==l.tagName.toLowerCase()&&l.setAttribute("role","button")}return this},a.fn.buttonMarkup.defaults={icon:"",iconpos:"left",theme:null,inline:!1,shadow:!0,corners:!0,iconshadow:!1,mini:!1},a.extend(a.fn.buttonMarkup,{initSelector:"a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button:not(:jqmData(role='navbar') button)"})}(a),function(a,b){a.widget("mobile.controlgroup",a.extend({options:{enhanced:!1,theme:null,shadow:!1,corners:!0,excludeInvisible:!0,type:"vertical",mini:!1},_create:function(){var b=this.element,c=this.options,d=a.mobile.page.prototype.keepNativeSelector();a.fn.buttonMarkup&&this.element.find(a.fn.buttonMarkup.initSelector).not(d).buttonMarkup(),a.each(this._childWidgets,a.proxy(function(b,c){a.mobile[c]&&this.element.find(a.mobile[c].initSelector).not(d)[c]()},this)),a.extend(this,{_ui:null,_initialRefresh:!0}),this._ui=c.enhanced?{groupLegend:b.children(".ui-controlgroup-label").children(),childWrapper:b.children(".ui-controlgroup-controls")}:this._enhance()},_childWidgets:["checkboxradio","selectmenu","button"],_themeClassFromOption:function(a){return a?"none"===a?"":"ui-group-theme-"+a:""},_enhance:function(){var b=this.element,c=this.options,d={groupLegend:b.children("legend"),childWrapper:b.addClass("ui-controlgroup ui-controlgroup-"+("horizontal"===c.type?"horizontal":"vertical")+" "+this._themeClassFromOption(c.theme)+" "+(c.corners?"ui-corner-all ":"")+(c.mini?"ui-mini ":"")).wrapInner("<div class='ui-controlgroup-controls "+(c.shadow===!0?"ui-shadow":"")+"'></div>").children()};return d.groupLegend.length>0&&a("<div role='heading' class='ui-controlgroup-label'></div>").append(d.groupLegend).prependTo(b),d},_init:function(){this.refresh()},_setOptions:function(a){var c,d,e=this.element;return a.type!==b&&(e.removeClass("ui-controlgroup-horizontal ui-controlgroup-vertical").addClass("ui-controlgroup-"+("horizontal"===a.type?"horizontal":"vertical")),c=!0),a.theme!==b&&e.removeClass(this._themeClassFromOption(this.options.theme)).addClass(this._themeClassFromOption(a.theme)),a.corners!==b&&e.toggleClass("ui-corner-all",a.corners),a.mini!==b&&e.toggleClass("ui-mini",a.mini),a.shadow!==b&&this._ui.childWrapper.toggleClass("ui-shadow",a.shadow),a.excludeInvisible!==b&&(this.options.excludeInvisible=a.excludeInvisible,c=!0),d=this._super(a),c&&this.refresh(),d},container:function(){return this._ui.childWrapper},refresh:function(){var b=this.container(),c=b.find(".ui-btn").not(".ui-slider-handle"),d=this._initialRefresh;a.mobile.checkboxradio&&b.find(":mobile-checkboxradio").checkboxradio("refresh"),this._addFirstLastClasses(c,this.options.excludeInvisible?this._getVisibles(c,d):c,d),this._initialRefresh=!1},_destroy:function(){var a,b,c=this.options;return c.enhanced?this:(a=this._ui,b=this.element.removeClass("ui-controlgroup ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini "+this._themeClassFromOption(c.theme)).find(".ui-btn").not(".ui-slider-handle"),this._removeFirstLastClasses(b),a.groupLegend.unwrap(),void a.childWrapper.children().unwrap())}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a,b){a.widget("mobile.toolbar",{initSelector:":jqmData(role='footer'), :jqmData(role='header')",options:{theme:null,addBackBtn:!1,backBtnTheme:null,backBtnText:"Back"},_create:function(){var b,c,d=this.element.is(":jqmData(role='header')")?"header":"footer",e=this.element.closest(".ui-page");0===e.length&&(e=!1,this._on(this.document,{pageshow:"refresh"})),a.extend(this,{role:d,page:e,leftbtn:b,rightbtn:c}),this.element.attr("role","header"===d?"banner":"contentinfo").addClass("ui-"+d),this.refresh(),this._setOptions(this.options)},_setOptions:function(a){if(a.addBackBtn!==b&&this._updateBackButton(),null!=a.backBtnTheme&&this.element.find(".ui-toolbar-back-btn").addClass("ui-btn ui-btn-"+a.backBtnTheme),a.backBtnText!==b&&this.element.find(".ui-toolbar-back-btn .ui-btn-text").text(a.backBtnText),a.theme!==b){var c=this.options.theme?this.options.theme:"inherit",d=a.theme?a.theme:"inherit";this.element.removeClass("ui-bar-"+c).addClass("ui-bar-"+d)}this._super(a)},refresh:function(){"header"===this.role&&this._addHeaderButtonClasses(),this.page||(this._setRelative(),"footer"===this.role?this.element.appendTo("body"):"header"===this.role&&this._updateBackButton()),this._addHeadingClasses(),this._btnMarkup()},_setRelative:function(){a("[data-"+a.mobile.ns+"role='page']").css({position:"relative"})},_btnMarkup:function(){this.element.children("a").filter(":not([data-"+a.mobile.ns+"role='none'])").attr("data-"+a.mobile.ns+"role","button"),this.element.trigger("create")},_addHeaderButtonClasses:function(){var a=this.element.children("a, button");this.leftbtn=a.hasClass("ui-btn-left")&&!a.hasClass("ui-toolbar-back-btn"),this.rightbtn=a.hasClass("ui-btn-right"),this.leftbtn=this.leftbtn||a.eq(0).not(".ui-btn-right,.ui-toolbar-back-btn").addClass("ui-btn-left").length,this.rightbtn=this.rightbtn||a.eq(1).addClass("ui-btn-right").length},_updateBackButton:function(){var b,c=this.options,d=c.backBtnTheme||c.theme;b=this._backButton=this._backButton||{},this.options.addBackBtn&&"header"===this.role&&a(".ui-page").length>1&&(this.page?this.page[0].getAttribute("data-"+a.mobile.ns+"url")!==a.mobile.path.stripHash(location.hash):a.mobile.navigate&&a.mobile.navigate.history&&a.mobile.navigate.history.activeIndex>0)&&!this.leftbtn?b.attached||(this.backButton=b.element=(b.element||a("<a role='button' href='javascript:void(0);' class='ui-btn ui-corner-all ui-shadow ui-btn-left "+(d?"ui-btn-"+d+" ":"")+"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' data-"+a.mobile.ns+"rel='back'>"+c.backBtnText+"</a>")).prependTo(this.element),b.attached=!0):b.element&&(b.element.detach(),b.attached=!1)},_addHeadingClasses:function(){this.element.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({role:"heading","aria-level":"1"})},_destroy:function(){var a;this.element.children("h1, h2, h3, h4, h5, h6").removeClass("ui-title").removeAttr("role").removeAttr("aria-level"),"header"===this.role&&(this.element.children("a, button").removeClass("ui-btn-left ui-btn-right ui-btn ui-shadow ui-corner-all"),this.backButton&&this.backButton.remove()),a=this.options.theme?this.options.theme:"inherit",this.element.removeClass("ui-bar-"+a),this.element.removeClass("ui-"+this.role).removeAttr("role")}})}(a),function(a,b){a.widget("mobile.toolbar",a.mobile.toolbar,{options:{position:null,visibleOnPageShow:!0,disablePageZoom:!0,transition:"slide",fullscreen:!1,tapToggle:!0,tapToggleBlacklist:"a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open",hideDuringFocus:"input, textarea, select",updatePagePadding:!0,trackPersistentToolbars:!0,supportBlacklist:function(){return!a.support.fixedPosition}},_create:function(){this._super(),this.pagecontainer=a(":mobile-pagecontainer"),"fixed"!==this.options.position||this.options.supportBlacklist()||this._makeFixed()},_makeFixed:function(){this.element.addClass("ui-"+this.role+"-fixed"),this.updatePagePadding(),this._addTransitionClass(),this._bindPageEvents(),this._bindToggleHandlers()},_setOptions:function(c){if("fixed"===c.position&&"fixed"!==this.options.position&&this._makeFixed(),"fixed"===this.options.position&&!this.options.supportBlacklist()){var d=this.page?this.page:a(".ui-page-active").length>0?a(".ui-page-active"):a(".ui-page").eq(0);c.fullscreen!==b&&(c.fullscreen?(this.element.addClass("ui-"+this.role+"-fullscreen"),d.addClass("ui-page-"+this.role+"-fullscreen")):(this.element.removeClass("ui-"+this.role+"-fullscreen"),d.removeClass("ui-page-"+this.role+"-fullscreen").addClass("ui-page-"+this.role+"-fixed")))}this._super(c)},_addTransitionClass:function(){var a=this.options.transition;a&&"none"!==a&&("slide"===a&&(a=this.element.hasClass("ui-header")?"slidedown":"slideup"),this.element.addClass(a))},_bindPageEvents:function(){var a=this.page?this.element.closest(".ui-page"):this.document;this._on(a,{pagebeforeshow:"_handlePageBeforeShow",webkitAnimationStart:"_handleAnimationStart",animationstart:"_handleAnimationStart",updatelayout:"_handleAnimationStart",pageshow:"_handlePageShow",pagebeforehide:"_handlePageBeforeHide"})},_handlePageBeforeShow:function(){var b=this.options;b.disablePageZoom&&a.mobile.zoom.disable(!0),b.visibleOnPageShow||this.hide(!0)},_handleAnimationStart:function(){this.options.updatePagePadding&&this.updatePagePadding(this.page?this.page:".ui-page-active")},_handlePageShow:function(){this.updatePagePadding(this.page?this.page:".ui-page-active"),this.options.updatePagePadding&&this._on(this.window,{throttledresize:"updatePagePadding"})},_handlePageBeforeHide:function(b,c){var d,e,f,g,h=this.options;h.disablePageZoom&&a.mobile.zoom.enable(!0),h.updatePagePadding&&this._off(this.window,"throttledresize"),h.trackPersistentToolbars&&(d=a(".ui-footer-fixed:jqmData(id)",this.page),e=a(".ui-header-fixed:jqmData(id)",this.page),f=d.length&&c.nextPage&&a(".ui-footer-fixed:jqmData(id='"+d.jqmData("id")+"')",c.nextPage)||a(),g=e.length&&c.nextPage&&a(".ui-header-fixed:jqmData(id='"+e.jqmData("id")+"')",c.nextPage)||a(),(f.length||g.length)&&(f.add(g).appendTo(a.mobile.pageContainer),c.nextPage.one("pageshow",function(){g.prependTo(this),f.appendTo(this)})))},_visible:!0,updatePagePadding:function(c){var d=this.element,e="header"===this.role,f=parseFloat(d.css(e?"top":"bottom"));this.options.fullscreen||(c=c&&c.type===b&&c||this.page||d.closest(".ui-page"),c=this.page?this.page:".ui-page-active",a(c).css("padding-"+(e?"top":"bottom"),d.outerHeight()+f))},_useTransition:function(b){var c=this.window,d=this.element,e=c.scrollTop(),f=d.height(),g=this.page?d.closest(".ui-page").height():a(".ui-page-active").height(),h=a.mobile.getScreenHeight();return!b&&(this.options.transition&&"none"!==this.options.transition&&("header"===this.role&&!this.options.fullscreen&&e>f||"footer"===this.role&&!this.options.fullscreen&&g-f>e+h)||this.options.fullscreen)},show:function(a){var b="ui-fixed-hidden",c=this.element;this._useTransition(a)?c.removeClass("out "+b).addClass("in").animationComplete(function(){c.removeClass("in")}):c.removeClass(b),this._visible=!0},hide:function(a){var b="ui-fixed-hidden",c=this.element,d="out"+("slide"===this.options.transition?" reverse":"");this._useTransition(a)?c.addClass(d).removeClass("in").animationComplete(function(){c.addClass(b).removeClass(d)}):c.addClass(b).removeClass(d),this._visible=!1},toggle:function(){this[this._visible?"hide":"show"]()},_bindToggleHandlers:function(){var b,c,d=this,e=d.options,f=!0,g=this.page?this.page:a(".ui-page");g.bind("vclick",function(b){e.tapToggle&&!a(b.target).closest(e.tapToggleBlacklist).length&&d.toggle()}).bind("focusin focusout",function(g){screen.width<1025&&a(g.target).is(e.hideDuringFocus)&&!a(g.target).closest(".ui-header-fixed, .ui-footer-fixed").length&&("focusout"!==g.type||f?"focusin"===g.type&&f&&(clearTimeout(b),f=!1,c=setTimeout(function(){d.hide()},0)):(f=!0,clearTimeout(c),b=setTimeout(function(){d.show()},0)))})},_setRelative:function(){"fixed"!==this.options.position&&a("[data-"+a.mobile.ns+"role='page']").css({position:"relative"})},_destroy:function(){var b,c,d,e,f,g=this.pagecontainer.pagecontainer("getActivePage");this._super(),"fixed"===this.options.position&&(d=a("body>.ui-"+this.role+"-fixed").add(g.find(".ui-"+this.options.role+"-fixed")).not(this.element).length>0,f=a("body>.ui-"+this.role+"-fixed").add(g.find(".ui-"+this.options.role+"-fullscreen")).not(this.element).length>0,c="ui-header-fixed ui-footer-fixed ui-header-fullscreen in out ui-footer-fullscreen fade slidedown slideup ui-fixed-hidden",this.element.removeClass(c),f||(b="ui-page-"+this.role+"-fullscreen"),d||(e="header"===this.role,b+=" ui-page-"+this.role+"-fixed",g.css("padding-"+(e?"top":"bottom"),"")),g.removeClass(b))
+}})}(a),function(a){a.widget("mobile.toolbar",a.mobile.toolbar,{_makeFixed:function(){this._super(),this._workarounds()},_workarounds:function(){var a=navigator.userAgent,b=navigator.platform,c=a.match(/AppleWebKit\/([0-9]+)/),d=!!c&&c[1],e=null,f=this;if(b.indexOf("iPhone")>-1||b.indexOf("iPad")>-1||b.indexOf("iPod")>-1)e="ios";else{if(!(a.indexOf("Android")>-1))return;e="android"}if("ios"===e)f._bindScrollWorkaround();else{if(!("android"===e&&d&&534>d))return;f._bindScrollWorkaround(),f._bindListThumbWorkaround()}},_viewportOffset:function(){var a=this.element,b=a.hasClass("ui-header"),c=Math.abs(a.offset().top-this.window.scrollTop());return b||(c=Math.round(c-this.window.height()+a.outerHeight())-60),c},_bindScrollWorkaround:function(){var a=this;this._on(this.window,{scrollstop:function(){var b=a._viewportOffset();b>2&&a._visible&&a._triggerRedraw()}})},_bindListThumbWorkaround:function(){this.element.closest(".ui-page").addClass("ui-android-2x-fixed")},_triggerRedraw:function(){var b=parseFloat(a(".ui-page-active").css("padding-bottom"));a(".ui-page-active").css("padding-bottom",b+1+"px"),setTimeout(function(){a(".ui-page-active").css("padding-bottom",b+"px")},0)},destroy:function(){this._super(),this.element.closest(".ui-page-active").removeClass("ui-android-2x-fix")}})}(a),function(a,b){function c(){var a=e.clone(),b=a.eq(0),c=a.eq(1),d=c.children();return{arEls:c.add(b),gd:b,ct:c,ar:d}}var d=a.mobile.browser.oldIE&&a.mobile.browser.oldIE<=8,e=a("<div class='ui-popup-arrow-guide'></div><div class='ui-popup-arrow-container"+(d?" ie":"")+"'><div class='ui-popup-arrow'></div></div>");a.widget("mobile.popup",a.mobile.popup,{options:{arrow:""},_create:function(){var a,b=this._super();return this.options.arrow&&(this._ui.arrow=a=this._addArrow()),b},_addArrow:function(){var a,b=this.options,d=c();return a=this._themeClassFromOption("ui-body-",b.theme),d.ar.addClass(a+(b.shadow?" ui-overlay-shadow":"")),d.arEls.hide().appendTo(this.element),d},_unenhance:function(){var a=this._ui.arrow;return a&&a.arEls.remove(),this._super()},_tryAnArrow:function(a,b,c,d,e){var f,g,h,i={},j={};return d.arFull[a.dimKey]>d.guideDims[a.dimKey]?e:(i[a.fst]=c[a.fst]+(d.arHalf[a.oDimKey]+d.menuHalf[a.oDimKey])*a.offsetFactor-d.contentBox[a.fst]+(d.clampInfo.menuSize[a.oDimKey]-d.contentBox[a.oDimKey])*a.arrowOffsetFactor,i[a.snd]=c[a.snd],f=d.result||this._calculateFinalLocation(i,d.clampInfo),g={x:f.left,y:f.top},j[a.fst]=g[a.fst]+d.contentBox[a.fst]+a.tipOffset,j[a.snd]=Math.max(f[a.prop]+d.guideOffset[a.prop]+d.arHalf[a.dimKey],Math.min(f[a.prop]+d.guideOffset[a.prop]+d.guideDims[a.dimKey]-d.arHalf[a.dimKey],c[a.snd])),h=Math.abs(c.x-j.x)+Math.abs(c.y-j.y),(!e||h<e.diff)&&(j[a.snd]-=d.arHalf[a.dimKey]+f[a.prop]+d.contentBox[a.snd],e={dir:b,diff:h,result:f,posProp:a.prop,posVal:j[a.snd]}),e)},_getPlacementState:function(a){var b,c,d=this._ui.arrow,e={clampInfo:this._clampPopupWidth(!a),arFull:{cx:d.ct.width(),cy:d.ct.height()},guideDims:{cx:d.gd.width(),cy:d.gd.height()},guideOffset:d.gd.offset()};return b=this.element.offset(),d.gd.css({left:0,top:0,right:0,bottom:0}),c=d.gd.offset(),e.contentBox={x:c.left-b.left,y:c.top-b.top,cx:d.gd.width(),cy:d.gd.height()},d.gd.removeAttr("style"),e.guideOffset={left:e.guideOffset.left-b.left,top:e.guideOffset.top-b.top},e.arHalf={cx:e.arFull.cx/2,cy:e.arFull.cy/2},e.menuHalf={cx:e.clampInfo.menuSize.cx/2,cy:e.clampInfo.menuSize.cy/2},e},_placementCoords:function(b){var c,e,f,g,h,i=this.options.arrow,j=this._ui.arrow;return j?(j.arEls.show(),h={},c=this._getPlacementState(!0),f={l:{fst:"x",snd:"y",prop:"top",dimKey:"cy",oDimKey:"cx",offsetFactor:1,tipOffset:-c.arHalf.cx,arrowOffsetFactor:0},r:{fst:"x",snd:"y",prop:"top",dimKey:"cy",oDimKey:"cx",offsetFactor:-1,tipOffset:c.arHalf.cx+c.contentBox.cx,arrowOffsetFactor:1},b:{fst:"y",snd:"x",prop:"left",dimKey:"cx",oDimKey:"cy",offsetFactor:-1,tipOffset:c.arHalf.cy+c.contentBox.cy,arrowOffsetFactor:1},t:{fst:"y",snd:"x",prop:"left",dimKey:"cx",oDimKey:"cy",offsetFactor:1,tipOffset:-c.arHalf.cy,arrowOffsetFactor:0}},a.each((i===!0?"l,t,r,b":i).split(","),a.proxy(function(a,d){e=this._tryAnArrow(f[d],d,b,c,e)},this)),e?(j.ct.removeClass("ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b").addClass("ui-popup-arrow-"+e.dir).removeAttr("style").css(e.posProp,e.posVal).show(),d||(g=this.element.offset(),h[f[e.dir].fst]=j.ct.offset(),h[f[e.dir].snd]={left:g.left+c.contentBox.x,top:g.top+c.contentBox.y}),e.result):(j.arEls.hide(),this._super(b))):this._super(b)},_setOptions:function(a){var c,d=this.options.theme,e=this._ui.arrow,f=this._super(a);if(a.arrow!==b){if(!e&&a.arrow)return void(this._ui.arrow=this._addArrow());e&&!a.arrow&&(e.arEls.remove(),this._ui.arrow=null)}return e=this._ui.arrow,e&&(a.theme!==b&&(d=this._themeClassFromOption("ui-body-",d),c=this._themeClassFromOption("ui-body-",a.theme),e.ar.removeClass(d).addClass(c)),a.shadow!==b&&e.ar.toggleClass("ui-overlay-shadow",a.shadow)),f},_destroy:function(){var a=this._ui.arrow;return a&&a.arEls.remove(),this._super()}})}(a),function(a,c){a.widget("mobile.panel",{options:{classes:{panel:"ui-panel",panelOpen:"ui-panel-open",panelClosed:"ui-panel-closed",panelFixed:"ui-panel-fixed",panelInner:"ui-panel-inner",modal:"ui-panel-dismiss",modalOpen:"ui-panel-dismiss-open",pageContainer:"ui-panel-page-container",pageWrapper:"ui-panel-wrapper",pageFixedToolbar:"ui-panel-fixed-toolbar",pageContentPrefix:"ui-panel-page-content",animate:"ui-panel-animate"},animate:!0,theme:null,position:"left",dismissible:!0,display:"reveal",swipeClose:!0,positionFixed:!1},_closeLink:null,_parentPage:null,_page:null,_modal:null,_panelInner:null,_wrapper:null,_fixedToolbars:null,_create:function(){var b=this.element,c=b.closest(".ui-page, :jqmData(role='page')");a.extend(this,{_closeLink:b.find(":jqmData(rel='close')"),_parentPage:c.length>0?c:!1,_openedPage:null,_page:this._getPage,_panelInner:this._getPanelInner(),_fixedToolbars:this._getFixedToolbars}),"overlay"!==this.options.display&&this._getWrapper(),this._addPanelClasses(),a.support.cssTransform3d&&this.options.animate&&this.element.addClass(this.options.classes.animate),this._bindUpdateLayout(),this._bindCloseEvents(),this._bindLinkListeners(),this._bindPageEvents(),this.options.dismissible&&this._createModal(),this._bindSwipeEvents()},_getPanelInner:function(){var a=this.element.find("."+this.options.classes.panelInner);return 0===a.length&&(a=this.element.children().wrapAll("<div class='"+this.options.classes.panelInner+"' />").parent()),a},_createModal:function(){var b=this,c=b._parentPage?b._parentPage.parent():b.element.parent();b._modal=a("<div class='"+b.options.classes.modal+"'></div>").on("mousedown",function(){b.close()}).appendTo(c)},_getPage:function(){var b=this._openedPage||this._parentPage||a("."+a.mobile.activePageClass);return b},_getWrapper:function(){var a=this._page().find("."+this.options.classes.pageWrapper);0===a.length&&(a=this._page().children(".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)").wrapAll("<div class='"+this.options.classes.pageWrapper+"'></div>").parent()),this._wrapper=a},_getFixedToolbars:function(){var b=a("body").children(".ui-header-fixed, .ui-footer-fixed"),c=this._page().find(".ui-header-fixed, .ui-footer-fixed"),d=b.add(c).addClass(this.options.classes.pageFixedToolbar);return d},_getPosDisplayClasses:function(a){return a+"-position-"+this.options.position+" "+a+"-display-"+this.options.display},_getPanelClasses:function(){var a=this.options.classes.panel+" "+this._getPosDisplayClasses(this.options.classes.panel)+" "+this.options.classes.panelClosed+" ui-body-"+(this.options.theme?this.options.theme:"inherit");return this.options.positionFixed&&(a+=" "+this.options.classes.panelFixed),a},_addPanelClasses:function(){this.element.addClass(this._getPanelClasses())},_handleCloseClick:function(a){a.isDefaultPrevented()||this.close()},_bindCloseEvents:function(){this._on(this._closeLink,{click:"_handleCloseClick"}),this._on({"click a:jqmData(ajax='false')":"_handleCloseClick"})},_positionPanel:function(b){var c=this,d=c._panelInner.outerHeight(),e=d>a.mobile.getScreenHeight();e||!c.options.positionFixed?(e&&(c._unfixPanel(),a.mobile.resetActivePageHeight(d)),b&&this.window[0].scrollTo(0,a.mobile.defaultHomeScroll)):c._fixPanel()},_bindFixListener:function(){this._on(a(b),{throttledresize:"_positionPanel"})},_unbindFixListener:function(){this._off(a(b),"throttledresize")},_unfixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.removeClass(this.options.classes.panelFixed)},_fixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.addClass(this.options.classes.panelFixed)},_bindUpdateLayout:function(){var a=this;a.element.on("updatelayout",function(){a._open&&a._positionPanel()})},_bindLinkListeners:function(){this._on("body",{"click a":"_handleClick"})},_handleClick:function(b){var d,e=this.element.attr("id");b.currentTarget.href.split("#")[1]===e&&e!==c&&(b.preventDefault(),d=a(b.target),d.hasClass("ui-btn")&&(d.addClass(a.mobile.activeBtnClass),this.element.one("panelopen panelclose",function(){d.removeClass(a.mobile.activeBtnClass)})),this.toggle())},_bindSwipeEvents:function(){var a=this,b=a._modal?a.element.add(a._modal):a.element;a.options.swipeClose&&("left"===a.options.position?b.on("swipeleft.panel",function(){a.close()}):b.on("swiperight.panel",function(){a.close()}))},_bindPageEvents:function(){var a=this;this.document.on("panelbeforeopen",function(b){a._open&&b.target!==a.element[0]&&a.close()}).on("keyup.panel",function(b){27===b.keyCode&&a._open&&a.close()}),this._parentPage||"overlay"===this.options.display||this._on(this.document,{pageshow:function(){this._openedPage=null,this._getWrapper()}}),a._parentPage?this.document.on("pagehide",":jqmData(role='page')",function(){a._open&&a.close(!0)}):this.document.on("pagebeforehide",function(){a._open&&a.close(!0)})},_open:!1,_pageContentOpenClasses:null,_modalOpenClasses:null,open:function(b){if(!this._open){var c=this,d=c.options,e=function(){c._off(c.document,"panelclose"),c._page().jqmData("panel","open"),a.support.cssTransform3d&&d.animate&&"overlay"!==d.display&&(c._wrapper.addClass(d.classes.animate),c._fixedToolbars().addClass(d.classes.animate)),!b&&a.support.cssTransform3d&&d.animate?(c._wrapper||c.element).animationComplete(f,"transition"):setTimeout(f,0),d.theme&&"overlay"!==d.display&&c._page().parent().addClass(d.classes.pageContainer+"-themed "+d.classes.pageContainer+"-"+d.theme),c.element.removeClass(d.classes.panelClosed).addClass(d.classes.panelOpen),c._positionPanel(!0),c._pageContentOpenClasses=c._getPosDisplayClasses(d.classes.pageContentPrefix),"overlay"!==d.display&&(c._page().parent().addClass(d.classes.pageContainer),c._wrapper.addClass(c._pageContentOpenClasses),c._fixedToolbars().addClass(c._pageContentOpenClasses)),c._modalOpenClasses=c._getPosDisplayClasses(d.classes.modal)+" "+d.classes.modalOpen,c._modal&&c._modal.addClass(c._modalOpenClasses).height(Math.max(c._modal.height(),c.document.height()))},f=function(){c._open&&("overlay"!==d.display&&(c._wrapper.addClass(d.classes.pageContentPrefix+"-open"),c._fixedToolbars().addClass(d.classes.pageContentPrefix+"-open")),c._bindFixListener(),c._trigger("open"),c._openedPage=c._page())};c._trigger("beforeopen"),"open"===c._page().jqmData("panel")?c._on(c.document,{panelclose:e}):e(),c._open=!0}},close:function(b){if(this._open){var c=this,d=this.options,e=function(){c.element.removeClass(d.classes.panelOpen),"overlay"!==d.display&&(c._wrapper.removeClass(c._pageContentOpenClasses),c._fixedToolbars().removeClass(c._pageContentOpenClasses)),!b&&a.support.cssTransform3d&&d.animate?(c._wrapper||c.element).animationComplete(f,"transition"):setTimeout(f,0),c._modal&&c._modal.removeClass(c._modalOpenClasses).height("")},f=function(){d.theme&&"overlay"!==d.display&&c._page().parent().removeClass(d.classes.pageContainer+"-themed "+d.classes.pageContainer+"-"+d.theme),c.element.addClass(d.classes.panelClosed),"overlay"!==d.display&&(c._page().parent().removeClass(d.classes.pageContainer),c._wrapper.removeClass(d.classes.pageContentPrefix+"-open"),c._fixedToolbars().removeClass(d.classes.pageContentPrefix+"-open")),a.support.cssTransform3d&&d.animate&&"overlay"!==d.display&&(c._wrapper.removeClass(d.classes.animate),c._fixedToolbars().removeClass(d.classes.animate)),c._fixPanel(),c._unbindFixListener(),a.mobile.resetActivePageHeight(),c._page().jqmRemoveData("panel"),c._trigger("close"),c._openedPage=null};c._trigger("beforeclose"),e(),c._open=!1}},toggle:function(){this[this._open?"close":"open"]()},_destroy:function(){var b,c=this.options,d=a("body > :mobile-panel").length+a.mobile.activePage.find(":mobile-panel").length>1;"overlay"!==c.display&&(b=a("body > :mobile-panel").add(a.mobile.activePage.find(":mobile-panel")),0===b.not(".ui-panel-display-overlay").not(this.element).length&&this._wrapper.children().unwrap(),this._open&&(this._fixedToolbars().removeClass(c.classes.pageContentPrefix+"-open"),a.support.cssTransform3d&&c.animate&&this._fixedToolbars().removeClass(c.classes.animate),this._page().parent().removeClass(c.classes.pageContainer),c.theme&&this._page().parent().removeClass(c.classes.pageContainer+"-themed "+c.classes.pageContainer+"-"+c.theme))),d||this.document.off("panelopen panelclose"),this._open&&this._page().jqmRemoveData("panel"),this._panelInner.children().unwrap(),this.element.removeClass([this._getPanelClasses(),c.classes.panelOpen,c.classes.animate].join(" ")).off("swipeleft.panel swiperight.panel").off("panelbeforeopen").off("panelhide").off("keyup.panel").off("updatelayout"),this._modal&&this._modal.remove()}})}(a),function(a,b){a.widget("mobile.table",{options:{classes:{table:"ui-table"},enhanced:!1},_create:function(){this.options.enhanced||this.element.addClass(this.options.classes.table),a.extend(this,{headers:b,allHeaders:b}),this._refresh(!0)},_setHeaders:function(){var a=this.element.find("thead tr");this.headers=this.element.find("tr:eq(0)").children(),this.allHeaders=this.headers.add(a.children())},refresh:function(){this._refresh()},rebuild:a.noop,_refresh:function(){var b=this.element,c=b.find("thead tr");this._setHeaders(),c.each(function(){var d=0;a(this).children().each(function(){var e,f=parseInt(this.getAttribute("colspan"),10),g=":nth-child("+(d+1)+")";if(this.setAttribute("data-"+a.mobile.ns+"colstart",d+1),f)for(e=0;f-1>e;e++)d++,g+=", :nth-child("+(d+1)+")";a(this).jqmData("cells",b.find("tr").not(c.eq(0)).not(this).children(g)),d++})})}})}(a),function(a){a.widget("mobile.table",a.mobile.table,{options:{mode:"columntoggle",columnBtnTheme:null,columnPopupTheme:null,columnBtnText:"Columns...",classes:a.extend(a.mobile.table.prototype.options.classes,{popup:"ui-table-columntoggle-popup",columnBtn:"ui-table-columntoggle-btn",priorityPrefix:"ui-table-priority-",columnToggleTable:"ui-table-columntoggle"})},_create:function(){this._super(),"columntoggle"===this.options.mode&&(a.extend(this,{_menu:null}),this.options.enhanced?(this._menu=a(this.document[0].getElementById(this._id()+"-popup")).children().first(),this._addToggles(this._menu,!0)):(this._menu=this._enhanceColToggle(),this.element.addClass(this.options.classes.columnToggleTable)),this._setupEvents(),this._setToggleState())},_id:function(){return this.element.attr("id")||this.widgetName+this.uuid},_setupEvents:function(){this._on(this.window,{throttledresize:"_setToggleState"}),this._on(this._menu,{"change input":"_menuInputChange"})},_addToggles:function(b,c){var d,e=0,f=this.options,g=b.controlgroup("container");c?d=b.find("input"):g.empty(),this.headers.not("td").each(function(){var b,h,i=a(this),j=a.mobile.getAttribute(this,"priority");j&&(h=i.add(i.jqmData("cells")),h.addClass(f.classes.priorityPrefix+j),b=(c?d.eq(e++):a("<label><input type='checkbox' checked />"+(i.children("abbr").first().attr("title")||i.text())+"</label>").appendTo(g).children(0).checkboxradio({theme:f.columnPopupTheme})).jqmData("header",i).jqmData("cells",h),i.jqmData("input",b))}),c||b.controlgroup("refresh")},_menuInputChange:function(b){var c=a(b.target),d=c[0].checked;c.jqmData("cells").toggleClass("ui-table-cell-hidden",!d).toggleClass("ui-table-cell-visible",d)},_unlockCells:function(a){a.removeClass("ui-table-cell-hidden ui-table-cell-visible")},_enhanceColToggle:function(){var b,c,d,e,f=this.element,g=this.options,h=a.mobile.ns,i=this.document[0].createDocumentFragment();return b=this._id()+"-popup",c=a("<a href='#"+b+"' class='"+g.classes.columnBtn+" ui-btn ui-btn-"+(g.columnBtnTheme||"a")+" ui-corner-all ui-shadow ui-mini' data-"+h+"rel='popup'>"+g.columnBtnText+"</a>"),d=a("<div class='"+g.classes.popup+"' id='"+b+"'></div>"),e=a("<fieldset></fieldset>").controlgroup(),this._addToggles(e,!1),e.appendTo(d),i.appendChild(d[0]),i.appendChild(c[0]),f.before(i),d.popup(),e},rebuild:function(){this._super(),"columntoggle"===this.options.mode&&this._refresh(!1)},_refresh:function(b){var c,d,e;if(this._super(b),!b&&"columntoggle"===this.options.mode)for(c=this.headers,d=[],this._menu.find("input").each(function(){var b=a(this),e=b.jqmData("header"),f=c.index(e[0]);f>-1&&!b.prop("checked")&&d.push(f)}),this._unlockCells(this.element.find(".ui-table-cell-hidden, .ui-table-cell-visible")),this._addToggles(this._menu,b),e=d.length-1;e>-1;e--)c.eq(d[e]).jqmData("input").prop("checked",!1).checkboxradio("refresh").trigger("change")},_setToggleState:function(){this._menu.find("input").each(function(){var b=a(this);this.checked="table-cell"===b.jqmData("cells").eq(0).css("display"),b.checkboxradio("refresh")})},_destroy:function(){this._super()}})}(a),function(a){a.widget("mobile.table",a.mobile.table,{options:{mode:"reflow",classes:a.extend(a.mobile.table.prototype.options.classes,{reflowTable:"ui-table-reflow",cellLabels:"ui-table-cell-label"})},_create:function(){this._super(),"reflow"===this.options.mode&&(this.options.enhanced||(this.element.addClass(this.options.classes.reflowTable),this._updateReflow()))},rebuild:function(){this._super(),"reflow"===this.options.mode&&this._refresh(!1)},_refresh:function(a){this._super(a),a||"reflow"!==this.options.mode||this._updateReflow()},_updateReflow:function(){var b=this,c=this.options;a(b.allHeaders.get().reverse()).each(function(){var d,e,f=a(this).jqmData("cells"),g=a.mobile.getAttribute(this,"colstart"),h=f.not(this).filter("thead th").length&&" ui-table-cell-label-top",i=a(this).clone().contents();i.length>0&&(h?(d=parseInt(this.getAttribute("colspan"),10),e="",d&&(e="td:nth-child("+d+"n + "+g+")"),b._addLabels(f.filter(e),c.classes.cellLabels+h,i)):b._addLabels(f,c.classes.cellLabels,i))})},_addLabels:function(b,c,d){1===d.length&&"abbr"===d[0].nodeName.toLowerCase()&&(d=d.eq(0).attr("title")),b.not(":has(b."+c+")").prepend(a("<b class='"+c+"'></b>").append(d))}})}(a),function(a,c){var d=function(b,c){return-1===(""+(a.mobile.getAttribute(this,"filtertext")||a(this).text())).toLowerCase().indexOf(c)};a.widget("mobile.filterable",{initSelector:":jqmData(filter='true')",options:{filterReveal:!1,filterCallback:d,enhanced:!1,input:null,children:"> li, > option, > optgroup option, > tbody tr, > .ui-controlgroup-controls > .ui-btn, > .ui-controlgroup-controls > .ui-checkbox, > .ui-controlgroup-controls > .ui-radio"},_create:function(){var b=this.options;a.extend(this,{_search:null,_timer:0}),this._setInput(b.input),b.enhanced||this._filterItems((this._search&&this._search.val()||"").toLowerCase())},_onKeyUp:function(){var c,d,e=this._search;if(e){if(c=e.val().toLowerCase(),d=a.mobile.getAttribute(e[0],"lastval")+"",d&&d===c)return;this._timer&&(b.clearTimeout(this._timer),this._timer=0),this._timer=this._delay(function(){return this._trigger("beforefilter",null,{input:e})===!1?!1:(e[0].setAttribute("data-"+a.mobile.ns+"lastval",c),this._filterItems(c),void(this._timer=0))},250)}},_getFilterableItems:function(){var b=this.element,c=this.options.children,d=c?a.isFunction(c)?c():c.nodeName?a(c):c.jquery?c:this.element.find(c):{length:0};return 0===d.length&&(d=b.children()),d},_filterItems:function(b){var c,e,f,g,h=[],i=[],j=this.options,k=this._getFilterableItems();if(null!=b)for(e=j.filterCallback||d,f=k.length,c=0;f>c;c++)g=e.call(k[c],c,b)?i:h,g.push(k[c]);0===i.length?k[j.filterReveal&&0===b.length?"addClass":"removeClass"]("ui-screen-hidden"):(a(i).addClass("ui-screen-hidden"),a(h).removeClass("ui-screen-hidden")),this._refreshChildWidget(),this._trigger("filter",null,{items:k})},_refreshChildWidget:function(){var b,c,d=["collapsibleset","selectmenu","controlgroup","listview"];for(c=d.length-1;c>-1;c--)b=d[c],a.mobile[b]&&(b=this.element.data("mobile-"+b),b&&a.isFunction(b.refresh)&&b.refresh())},_setInput:function(c){var d=this._search;this._timer&&(b.clearTimeout(this._timer),this._timer=0),d&&(this._off(d,"keyup change input"),d=null),c&&(d=c.jquery?c:c.nodeName?a(c):this.document.find(c),this._on(d,{keydown:"_onKeyDown",keypress:"_onKeyPress",keyup:"_onKeyUp",change:"_onKeyUp",input:"_onKeyUp"})),this._search=d},_onKeyDown:function(b){b.keyCode===a.ui.keyCode.ENTER&&(b.preventDefault(),this._preventKeyPress=!0)},_onKeyPress:function(a){this._preventKeyPress&&(a.preventDefault(),this._preventKeyPress=!1)},_setOptions:function(a){var b=!(a.filterReveal===c&&a.filterCallback===c&&a.children===c);this._super(a),a.input!==c&&(this._setInput(a.input),b=!0),b&&this.refresh()},_destroy:function(){var a=this.options,b=this._getFilterableItems();a.enhanced?b.toggleClass("ui-screen-hidden",a.filterReveal):b.removeClass("ui-screen-hidden")},refresh:function(){this._timer&&(b.clearTimeout(this._timer),this._timer=0),this._filterItems((this._search&&this._search.val()||"").toLowerCase())}})}(a),function(a,b){var c=function(a,b){return function(c){b.call(this,c),a._syncTextInputOptions(c)}},d=/(^|\s)ui-li-divider(\s|$)/,e=a.mobile.filterable.prototype.options.filterCallback;a.mobile.filterable.prototype.options.filterCallback=function(a,b){return!this.className.match(d)&&e.call(this,a,b)},a.widget("mobile.filterable",a.mobile.filterable,{options:{filterPlaceholder:"Filter items...",filterTheme:null},_create:function(){var b,c,d=this.element,e=["collapsibleset","selectmenu","controlgroup","listview"],f={};for(this._super(),a.extend(this,{_widget:null}),b=e.length-1;b>-1;b--)if(c=e[b],a.mobile[c]){if(this._setWidget(d.data("mobile-"+c)))break;f[c+"create"]="_handleCreate"}this._widget||this._on(d,f)},_handleCreate:function(a){this._setWidget(this.element.data("mobile-"+a.type.substring(0,a.type.length-6)))},_trigger:function(a,b,c){return this._widget&&"mobile-listview"===this._widget.widgetFullName&&"beforefilter"===a&&this._widget._trigger("beforefilter",b,c),this._super(a,b,c)},_setWidget:function(a){return!this._widget&&a&&(this._widget=a,this._widget._setOptions=c(this,this._widget._setOptions)),this._widget&&(this._syncTextInputOptions(this._widget.options),"listview"===this._widget.widgetName&&(this._widget.options.hideDividers=!0,this._widget.element.listview("refresh"))),!!this._widget},_isSearchInternal:function(){return this._search&&this._search.jqmData("ui-filterable-"+this.uuid+"-internal")},_setInput:function(b){var c=this.options,d=!0,e={};if(!b){if(this._isSearchInternal())return;d=!1,b=a("<input data-"+a.mobile.ns+"type='search' placeholder='"+c.filterPlaceholder+"'></input>").jqmData("ui-filterable-"+this.uuid+"-internal",!0),a("<form class='ui-filterable'></form>").append(b).submit(function(a){a.preventDefault(),b.blur()}).insertBefore(this.element),a.mobile.textinput&&(null!=this.options.filterTheme&&(e.theme=c.filterTheme),b.textinput(e))}this._super(b),this._isSearchInternal()&&d&&this._search.attr("placeholder",this.options.filterPlaceholder)},_setOptions:function(c){var d=this._super(c);return c.filterPlaceholder!==b&&this._isSearchInternal()&&this._search.attr("placeholder",c.filterPlaceholder),c.filterTheme!==b&&this._search&&a.mobile.textinput&&this._search.textinput("option","theme",c.filterTheme),d},_refreshChildWidget:function(){this._refreshingChildWidget=!0,this._superApply(arguments),this._refreshingChildWidget=!1},refresh:function(){this._refreshingChildWidget||this._superApply(arguments)},_destroy:function(){this._isSearchInternal()&&this._search.remove(),this._super()},_syncTextInputOptions:function(c){var d,e={};if(this._isSearchInternal()&&a.mobile.textinput){for(d in a.mobile.textinput.prototype.options)c[d]!==b&&(e[d]="theme"===d&&null!=this.options.filterTheme?this.options.filterTheme:c[d]);this._search.textinput("option",e)}}}),a.widget("mobile.listview",a.mobile.listview,{options:{filter:!1},_create:function(){return this.options.filter!==!0||this.element.data("mobile-filterable")||this.element.filterable(),this._super()},refresh:function(){var a;this._superApply(arguments),this.options.filter===!0&&(a=this.element.data("mobile-filterable"),a&&a.refresh())}})}(a),function(a,b){function c(){return++e}function d(a){return a.hash.length>1&&decodeURIComponent(a.href.replace(f,""))===decodeURIComponent(location.href.replace(f,""))}var e=0,f=/#.*$/;a.widget("ui.tabs",{version:"fadf2b312a05040436451c64bbfaf4814bc62c56",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var b=this,c=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",c.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(b){a(this).is(".ui-state-disabled")&&b.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){a(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),c.active=this._initialActive(),a.isArray(c.disabled)&&(c.disabled=a.unique(c.disabled.concat(a.map(this.tabs.filter(".ui-state-disabled"),function(a){return b.tabs.index(a)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(c.active):a(),this._refresh(),this.active.length&&this.load(c.active)},_initialActive:function(){var b=this.options.active,c=this.options.collapsible,d=location.hash.substring(1);return null===b&&(d&&this.tabs.each(function(c,e){return a(e).attr("aria-controls")===d?(b=c,!1):void 0}),null===b&&(b=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===b||-1===b)&&(b=this.tabs.length?0:!1)),b!==!1&&(b=this.tabs.index(this.tabs.eq(b)),-1===b&&(b=c?!1:0)),!c&&b===!1&&this.anchors.length&&(b=0),b},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):a()}},_tabKeydown:function(b){var c=a(this.document[0].activeElement).closest("li"),d=this.tabs.index(c),e=!0;if(!this._handlePageNav(b)){switch(b.keyCode){case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:d++;break;case a.ui.keyCode.UP:case a.ui.keyCode.LEFT:e=!1,d--;break;case a.ui.keyCode.END:d=this.anchors.length-1;break;case a.ui.keyCode.HOME:d=0;break;case a.ui.keyCode.SPACE:return b.preventDefault(),clearTimeout(this.activating),void this._activate(d);case a.ui.keyCode.ENTER:return b.preventDefault(),clearTimeout(this.activating),void this._activate(d===this.options.active?!1:d);default:return}b.preventDefault(),clearTimeout(this.activating),d=this._focusNextTab(d,e),b.ctrlKey||(c.attr("aria-selected","false"),this.tabs.eq(d).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",d)},this.delay))}},_panelKeydown:function(b){this._handlePageNav(b)||b.ctrlKey&&b.keyCode===a.ui.keyCode.UP&&(b.preventDefault(),this.active.focus())},_handlePageNav:function(b){return b.altKey&&b.keyCode===a.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):b.altKey&&b.keyCode===a.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(b,c){function d(){return b>e&&(b=0),0>b&&(b=e),b}for(var e=this.tabs.length-1;-1!==a.inArray(d(),this.options.disabled);)b=c?b+1:b-1;return b},_focusNextTab:function(a,b){return a=this._findNextTab(a,b),this.tabs.eq(a).focus(),a},_setOption:function(a,b){return"active"===a?void this._activate(b):"disabled"===a?void this._setupDisabled(b):(this._super(a,b),"collapsible"===a&&(this.element.toggleClass("ui-tabs-collapsible",b),b||this.options.active!==!1||this._activate(0)),"event"===a&&this._setupEvents(b),void("heightStyle"===a&&this._setupHeightStyle(b)))},_tabId:function(a){return a.attr("aria-controls")||"ui-tabs-"+c()},_sanitizeSelector:function(a){return a?a.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var b=this.options,c=this.tablist.children(":has(a[href])");b.disabled=a.map(c.filter(".ui-state-disabled"),function(a){return c.index(a)}),this._processTabs(),b.active!==!1&&this.anchors.length?this.active.length&&!a.contains(this.tablist[0],this.active[0])?this.tabs.length===b.disabled.length?(b.active=!1,this.active=a()):this._activate(this._findNextTab(Math.max(0,b.active-1),!1)):b.active=this.tabs.index(this.active):(b.active=!1,this.active=a()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var b=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return a("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=a(),this.anchors.each(function(c,e){var f,g,h,i=a(e).uniqueId().attr("id"),j=a(e).closest("li"),k=j.attr("aria-controls");d(e)?(f=e.hash,g=b.element.find(b._sanitizeSelector(f))):(h=b._tabId(j),f="#"+h,g=b.element.find(f),g.length||(g=b._createPanel(h),g.insertAfter(b.panels[c-1]||b.tablist)),g.attr("aria-live","polite")),g.length&&(b.panels=b.panels.add(g)),k&&j.data("ui-tabs-aria-controls",k),j.attr({"aria-controls":f.substring(1),"aria-labelledby":i}),g.attr("aria-labelledby",i)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(b){return a("<div>").attr("id",b).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(b){a.isArray(b)&&(b.length?b.length===this.anchors.length&&(b=!0):b=!1);for(var c,d=0;c=this.tabs[d];d++)b===!0||-1!==a.inArray(d,b)?a(c).addClass("ui-state-disabled").attr("aria-disabled","true"):a(c).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=b},_setupEvents:function(b){var c={click:function(a){a.preventDefault()}};b&&a.each(b.split(" "),function(a,b){c[b]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,c),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(b){var c,d=this.element.parent();"fill"===b?(c=d.height(),c-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var b=a(this),d=b.css("position");"absolute"!==d&&"fixed"!==d&&(c-=b.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){c-=a(this).outerHeight(!0)
+}),this.panels.each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")):"auto"===b&&(c=0,this.panels.each(function(){c=Math.max(c,a(this).height("").height())}).height(c))},_eventHandler:function(b){var c=this.options,d=this.active,e=a(b.currentTarget),f=e.closest("li"),g=f[0]===d[0],h=g&&c.collapsible,i=h?a():this._getPanelForTab(f),j=d.length?this._getPanelForTab(d):a(),k={oldTab:d,oldPanel:j,newTab:h?a():f,newPanel:i};b.preventDefault(),f.hasClass("ui-state-disabled")||f.hasClass("ui-tabs-loading")||this.running||g&&!c.collapsible||this._trigger("beforeActivate",b,k)===!1||(c.active=h?!1:this.tabs.index(f),this.active=g?a():f,this.xhr&&this.xhr.abort(),j.length||i.length||a.error("jQuery UI Tabs: Mismatching fragment identifier."),i.length&&this.load(this.tabs.index(f),b),this._toggle(b,k))},_toggle:function(b,c){function d(){f.running=!1,f._trigger("activate",b,c)}function e(){c.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),g.length&&f.options.show?f._show(g,f.options.show,d):(g.show(),d())}var f=this,g=c.newPanel,h=c.oldPanel;this.running=!0,h.length&&this.options.hide?this._hide(h,this.options.hide,function(){c.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),e()}):(c.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),h.hide(),e()),h.attr({"aria-expanded":"false","aria-hidden":"true"}),c.oldTab.attr("aria-selected","false"),g.length&&h.length?c.oldTab.attr("tabIndex",-1):g.length&&this.tabs.filter(function(){return 0===a(this).attr("tabIndex")}).attr("tabIndex",-1),g.attr({"aria-expanded":"true","aria-hidden":"false"}),c.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(b){var c,d=this._findActive(b);d[0]!==this.active[0]&&(d.length||(d=this.active),c=d.find(".ui-tabs-anchor")[0],this._eventHandler({target:c,currentTarget:c,preventDefault:a.noop}))},_findActive:function(b){return b===!1?a():this.tabs.eq(b)},_getIndex:function(a){return"string"==typeof a&&(a=this.anchors.index(this.anchors.filter("[href$='"+a+"']"))),a},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){a.data(this,"ui-tabs-destroy")?a(this).remove():a(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var b=a(this),c=b.data("ui-tabs-aria-controls");c?b.attr("aria-controls",c).removeData("ui-tabs-aria-controls"):b.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(c){var d=this.options.disabled;d!==!1&&(c===b?d=!1:(c=this._getIndex(c),d=a.isArray(d)?a.map(d,function(a){return a!==c?a:null}):a.map(this.tabs,function(a,b){return b!==c?b:null})),this._setupDisabled(d))},disable:function(c){var d=this.options.disabled;if(d!==!0){if(c===b)d=!0;else{if(c=this._getIndex(c),-1!==a.inArray(c,d))return;d=a.isArray(d)?a.merge([c],d).sort():[c]}this._setupDisabled(d)}},load:function(b,c){b=this._getIndex(b);var e=this,f=this.tabs.eq(b),g=f.find(".ui-tabs-anchor"),h=this._getPanelForTab(f),i={tab:f,panel:h};d(g[0])||(this.xhr=a.ajax(this._ajaxSettings(g,c,i)),this.xhr&&"canceled"!==this.xhr.statusText&&(f.addClass("ui-tabs-loading"),h.attr("aria-busy","true"),this.xhr.success(function(a){setTimeout(function(){h.html(a),e._trigger("load",c,i)},1)}).complete(function(a,b){setTimeout(function(){"abort"===b&&e.panels.stop(!1,!0),f.removeClass("ui-tabs-loading"),h.removeAttr("aria-busy"),a===e.xhr&&delete e.xhr},1)})))},_ajaxSettings:function(b,c,d){var e=this;return{url:b.attr("href"),beforeSend:function(b,f){return e._trigger("beforeLoad",c,a.extend({jqXHR:b,ajaxSettings:f},d))}}},_getPanelForTab:function(b){var c=a(b).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+c))}})}(a),function(){}(a),function(a,b){function c(a){e=a.originalEvent,i=e.accelerationIncludingGravity,f=Math.abs(i.x),g=Math.abs(i.y),h=Math.abs(i.z),!b.orientation&&(f>7||(h>6&&8>g||8>h&&g>6)&&f>5)?d.enabled&&d.disable():d.enabled||d.enable()}a.mobile.iosorientationfixEnabled=!0;var d,e,f,g,h,i,j=navigator.userAgent;return/iPhone|iPad|iPod/.test(navigator.platform)&&/OS [1-5]_[0-9_]* like Mac OS X/i.test(j)&&j.indexOf("AppleWebKit")>-1?(d=a.mobile.zoom,void a.mobile.document.on("mobileinit",function(){a.mobile.iosorientationfixEnabled&&a.mobile.window.bind("orientationchange.iosorientationfix",d.enable).bind("devicemotion.iosorientationfix",c)})):void(a.mobile.iosorientationfixEnabled=!1)}(a,this),function(a,b,d){function e(){f.removeClass("ui-mobile-rendering")}var f=a("html"),g=a.mobile.window;a(b.document).trigger("mobileinit"),a.mobile.gradeA()&&(a.mobile.ajaxBlacklist&&(a.mobile.ajaxEnabled=!1),f.addClass("ui-mobile ui-mobile-rendering"),setTimeout(e,5e3),a.extend(a.mobile,{initializePage:function(){var b=a.mobile.path,f=a(":jqmData(role='page'), :jqmData(role='dialog')"),h=b.stripHash(b.stripQueryParams(b.parseLocation().hash)),i=a.mobile.path.parseLocation(),j=h?c.getElementById(h):d;f.length||(f=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0)),f.each(function(){var c=a(this);c[0].getAttribute("data-"+a.mobile.ns+"url")||c.attr("data-"+a.mobile.ns+"url",c.attr("id")||b.convertUrlToDataUrl(i.pathname+i.search))}),a.mobile.firstPage=f.first(),a.mobile.pageContainer=a.mobile.firstPage.parent().addClass("ui-mobile-viewport").pagecontainer(),a.mobile.navreadyDeferred.resolve(),g.trigger("pagecontainercreate"),a.mobile.loading("show"),e(),a.mobile.hashListeningEnabled&&a.mobile.path.isHashValid(location.hash)&&(a(j).is(":jqmData(role='page')")||a.mobile.path.isPath(h)||h===a.mobile.dialogHashKey)?a.event.special.navigate.isPushStateEnabled()?(a.mobile.navigate.history.stack=[],a.mobile.navigate(a.mobile.path.isPath(location.hash)?location.hash:location.href)):g.trigger("hashchange",[!0]):(a.event.special.navigate.isPushStateEnabled()&&a.mobile.navigate.navigator.squash(b.parseLocation().href),a.mobile.changePage(a.mobile.firstPage,{transition:"none",reverse:!0,changeHash:!1,fromHashChange:!0}))}}),a(function(){a.support.inlineSVG(),a.mobile.hideUrlBar&&b.scrollTo(0,1),a.mobile.defaultHomeScroll=a.support.scrollTop&&1!==a.mobile.window.scrollTop()?1:0,a.mobile.autoInitializePage&&a.mobile.initializePage(),a.mobile.hideUrlBar&&g.load(a.mobile.silentScroll),a.support.cssPointerEvents||a.mobile.document.delegate(".ui-state-disabled,.ui-disabled","vclick",function(a){a.preventDefault(),a.stopImmediatePropagation()})}))}(a,this)});
+//# sourceMappingURL=jquery.mobile-1.4.5.min.map
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/lib/qrcode.min.js b/platforms/android/app/src/main/assets/www/js/lib/qrcode.min.js
new file mode 100755
index 0000000..993e88f
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/qrcode.min.js
@@ -0,0 +1 @@
+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/platforms/android/app/src/main/assets/www/js/lib/swiper.js b/platforms/android/app/src/main/assets/www/js/lib/swiper.js
new file mode 100755
index 0000000..a83b981
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/swiper.js
@@ -0,0 +1,4161 @@
+/**
+ * Swiper 3.3.1
+ * Most modern mobile touch slider and framework with hardware accelerated transitions
+ * 
+ * http://www.idangero.us/swiper/
+ * 
+ * Copyright 2016, Vladimir Kharlampidi
+ * The iDangero.us
+ * http://www.idangero.us/
+ * 
+ * Licensed under MIT
+ * 
+ * Released on: February 7, 2016
+ */
+(function () {
+    'use strict';
+    var $;
+    /*===========================
+    Swiper
+    ===========================*/
+    var Swiper = function (container, params) {
+        if (!(this instanceof Swiper)) return new Swiper(container, params);
+
+        var defaults = {
+            direction: 'horizontal',
+            touchEventsTarget: 'container',
+            initialSlide: 0,
+            speed: 300,
+            // autoplay
+            autoplay: false,
+            autoplayDisableOnInteraction: true,
+            autoplayStopOnLast: false,
+            // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
+            iOSEdgeSwipeDetection: false,
+            iOSEdgeSwipeThreshold: 20,
+            // Free mode
+            freeMode: false,
+            freeModeMomentum: true,
+            freeModeMomentumRatio: 1,
+            freeModeMomentumBounce: true,
+            freeModeMomentumBounceRatio: 1,
+            freeModeSticky: false,
+            freeModeMinimumVelocity: 0.02,
+            // Autoheight
+            autoHeight: false,
+            // Set wrapper width
+            setWrapperSize: false,
+            // Virtual Translate
+            virtualTranslate: false,
+            // Effects
+            effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
+            coverflow: {
+                rotate: 50,
+                stretch: 0,
+                depth: 100,
+                modifier: 1,
+                slideShadows : true
+            },
+            flip: {
+                slideShadows : true,
+                limitRotation: true
+            },
+            cube: {
+                slideShadows: true,
+                shadow: true,
+                shadowOffset: 20,
+                shadowScale: 0.94
+            },
+            fade: {
+                crossFade: false
+            },
+            // Parallax
+            parallax: false,
+            // Scrollbar
+            scrollbar: null,
+            scrollbarHide: true,
+            scrollbarDraggable: false,
+            scrollbarSnapOnRelease: false,
+            // Keyboard Mousewheel
+            keyboardControl: false,
+            mousewheelControl: false,
+            mousewheelReleaseOnEdges: false,
+            mousewheelInvert: false,
+            mousewheelForceToAxis: false,
+            mousewheelSensitivity: 1,
+            // Hash Navigation
+            hashnav: false,
+            // Breakpoints
+            breakpoints: undefined,
+            // Slides grid
+            spaceBetween: 0,
+            slidesPerView: 1,
+            slidesPerColumn: 1,
+            slidesPerColumnFill: 'column',
+            slidesPerGroup: 1,
+            centeredSlides: false,
+            slidesOffsetBefore: 0, // in px
+            slidesOffsetAfter: 0, // in px
+            // Round length
+            roundLengths: false,
+            // Touches
+            touchRatio: 1,
+            touchAngle: 45,
+            simulateTouch: true,
+            shortSwipes: true,
+            longSwipes: true,
+            longSwipesRatio: 0.5,
+            longSwipesMs: 300,
+            followFinger: true,
+            onlyExternal: false,
+            threshold: 0,
+            touchMoveStopPropagation: true,
+            // Unique Navigation Elements
+            uniqueNavElements: true,
+            // Pagination
+            pagination: null,
+            paginationElement: 'span',
+            paginationClickable: false,
+            paginationHide: false,
+            paginationBulletRender: null,
+            paginationProgressRender: null,
+            paginationFractionRender: null,
+            paginationCustomRender: null,
+            paginationType: 'bullets', // 'bullets' or 'progress' or 'fraction' or 'custom'
+            // Resistance
+            resistance: true,
+            resistanceRatio: 0.85,
+            // Next/prev buttons
+            nextButton: null,
+            prevButton: null,
+            // Progress
+            watchSlidesProgress: false,
+            watchSlidesVisibility: false,
+            // Cursor
+            grabCursor: false,
+            // Clicks
+            preventClicks: true,
+            preventClicksPropagation: true,
+            slideToClickedSlide: false,
+            // Lazy Loading
+            lazyLoading: false,
+            lazyLoadingInPrevNext: false,
+            lazyLoadingInPrevNextAmount: 1,
+            lazyLoadingOnTransitionStart: false,
+            // Images
+            preloadImages: true,
+            updateOnImagesReady: true,
+            // loop
+            loop: false,
+            loopAdditionalSlides: 0,
+            loopedSlides: null,
+            // Control
+            control: undefined,
+            controlInverse: false,
+            controlBy: 'slide', //or 'container'
+            // Swiping/no swiping
+            allowSwipeToPrev: true,
+            allowSwipeToNext: true,
+            swipeHandler: null, //'.swipe-handler',
+            noSwiping: true,
+            noSwipingClass: 'swiper-no-swiping',
+            // NS
+            slideClass: 'swiper-slide',
+            slideActiveClass: 'swiper-slide-active',
+            slideVisibleClass: 'swiper-slide-visible',
+            slideDuplicateClass: 'swiper-slide-duplicate',
+            slideNextClass: 'swiper-slide-next',
+            slidePrevClass: 'swiper-slide-prev',
+            wrapperClass: 'swiper-wrapper',
+            bulletClass: 'swiper-pagination-bullet',
+            bulletActiveClass: 'swiper-pagination-bullet-active',
+            buttonDisabledClass: 'swiper-button-disabled',
+            paginationCurrentClass: 'swiper-pagination-current',
+            paginationTotalClass: 'swiper-pagination-total',
+            paginationHiddenClass: 'swiper-pagination-hidden',
+            paginationProgressbarClass: 'swiper-pagination-progressbar',
+            // Observer
+            observer: false,
+            observeParents: false,
+            // Accessibility
+            a11y: false,
+            prevSlideMessage: 'Previous slide',
+            nextSlideMessage: 'Next slide',
+            firstSlideMessage: 'This is the first slide',
+            lastSlideMessage: 'This is the last slide',
+            paginationBulletMessage: 'Go to slide {{index}}',
+            // Callbacks
+            runCallbacksOnInit: true
+            /*
+            Callbacks:
+            onInit: function (swiper)
+            onDestroy: function (swiper)
+            onClick: function (swiper, e)
+            onTap: function (swiper, e)
+            onDoubleTap: function (swiper, e)
+            onSliderMove: function (swiper, e)
+            onSlideChangeStart: function (swiper)
+            onSlideChangeEnd: function (swiper)
+            onTransitionStart: function (swiper)
+            onTransitionEnd: function (swiper)
+            onImagesReady: function (swiper)
+            onProgress: function (swiper, progress)
+            onTouchStart: function (swiper, e)
+            onTouchMove: function (swiper, e)
+            onTouchMoveOpposite: function (swiper, e)
+            onTouchEnd: function (swiper, e)
+            onReachBeginning: function (swiper)
+            onReachEnd: function (swiper)
+            onSetTransition: function (swiper, duration)
+            onSetTranslate: function (swiper, translate)
+            onAutoplayStart: function (swiper)
+            onAutoplayStop: function (swiper),
+            onLazyImageLoad: function (swiper, slide, image)
+            onLazyImageReady: function (swiper, slide, image)
+            */
+        
+        };
+        var initialVirtualTranslate = params && params.virtualTranslate;
+        
+        params = params || {};
+        var originalParams = {};
+        for (var param in params) {
+            if (typeof params[param] === 'object' && params[param] !== null && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) {
+                originalParams[param] = {};
+                for (var deepParam in params[param]) {
+                    originalParams[param][deepParam] = params[param][deepParam];
+                }
+            }
+            else {
+                originalParams[param] = params[param];
+            }
+        }
+        for (var def in defaults) {
+            if (typeof params[def] === 'undefined') {
+                params[def] = defaults[def];
+            }
+            else if (typeof params[def] === 'object') {
+                for (var deepDef in defaults[def]) {
+                    if (typeof params[def][deepDef] === 'undefined') {
+                        params[def][deepDef] = defaults[def][deepDef];
+                    }
+                }
+            }
+        }
+        
+        // Swiper
+        var s = this;
+        
+        // Params
+        s.params = params;
+        s.originalParams = originalParams;
+        
+        // Classname
+        s.classNames = [];
+        /*=========================
+          Dom Library and plugins
+          ===========================*/
+        if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){
+            $ = Dom7;
+        }
+        if (typeof $ === 'undefined') {
+            if (typeof Dom7 === 'undefined') {
+                $ = window.Dom7 || window.Zepto || window.jQuery;
+            }
+            else {
+                $ = Dom7;
+            }
+            if (!$) return;
+        }
+        // Export it to Swiper instance
+        s.$ = $;
+        
+        /*=========================
+          Breakpoints
+          ===========================*/
+        s.currentBreakpoint = undefined;
+        s.getActiveBreakpoint = function () {
+            //Get breakpoint for window width
+            if (!s.params.breakpoints) return false;
+            var breakpoint = false;
+            var points = [], point;
+            for ( point in s.params.breakpoints ) {
+                if (s.params.breakpoints.hasOwnProperty(point)) {
+                    points.push(point);
+                }
+            }
+            points.sort(function (a, b) {
+                return parseInt(a, 10) > parseInt(b, 10);
+            });
+            for (var i = 0; i < points.length; i++) {
+                point = points[i];
+                if (point >= window.innerWidth && !breakpoint) {
+                    breakpoint = point;
+                }
+            }
+            return breakpoint || 'max';
+        };
+        s.setBreakpoint = function () {
+            //Set breakpoint for window width and update parameters
+            var breakpoint = s.getActiveBreakpoint();
+            if (breakpoint && s.currentBreakpoint !== breakpoint) {
+                var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams;
+                var needsReLoop = s.params.loop && (breakPointsParams.slidesPerView !== s.params.slidesPerView);
+                for ( var param in breakPointsParams ) {
+                    s.params[param] = breakPointsParams[param];
+                }
+                s.currentBreakpoint = breakpoint;
+                if(needsReLoop && s.destroyLoop) {
+                    s.reLoop(true);
+                }
+            }
+        };
+        // Set breakpoint on load
+        if (s.params.breakpoints) {
+            s.setBreakpoint();
+        }
+        
+        /*=========================
+          Preparation - Define Container, Wrapper and Pagination
+          ===========================*/
+        s.container = $(container);
+        if (s.container.length === 0) return;
+        if (s.container.length > 1) {
+            var swipers = [];
+            s.container.each(function () {
+                var container = this;
+                swipers.push(new Swiper(this, params));
+            });
+            return swipers;
+        }
+        
+        // Save instance in container HTML Element and in data
+        s.container[0].swiper = s;
+        s.container.data('swiper', s);
+        
+        s.classNames.push('swiper-container-' + s.params.direction);
+        
+        if (s.params.freeMode) {
+            s.classNames.push('swiper-container-free-mode');
+        }
+        if (!s.support.flexbox) {
+            s.classNames.push('swiper-container-no-flexbox');
+            s.params.slidesPerColumn = 1;
+        }
+        if (s.params.autoHeight) {
+            s.classNames.push('swiper-container-autoheight');
+        }
+        // Enable slides progress when required
+        if (s.params.parallax || s.params.watchSlidesVisibility) {
+            s.params.watchSlidesProgress = true;
+        }
+        // Coverflow / 3D
+        if (['cube', 'coverflow', 'flip'].indexOf(s.params.effect) >= 0) {
+            if (s.support.transforms3d) {
+                s.params.watchSlidesProgress = true;
+                s.classNames.push('swiper-container-3d');
+            }
+            else {
+                s.params.effect = 'slide';
+            }
+        }
+        if (s.params.effect !== 'slide') {
+            s.classNames.push('swiper-container-' + s.params.effect);
+        }
+        if (s.params.effect === 'cube') {
+            s.params.resistanceRatio = 0;
+            s.params.slidesPerView = 1;
+            s.params.slidesPerColumn = 1;
+            s.params.slidesPerGroup = 1;
+            s.params.centeredSlides = false;
+            s.params.spaceBetween = 0;
+            s.params.virtualTranslate = true;
+            s.params.setWrapperSize = false;
+        }
+        if (s.params.effect === 'fade' || s.params.effect === 'flip') {
+            s.params.slidesPerView = 1;
+            s.params.slidesPerColumn = 1;
+            s.params.slidesPerGroup = 1;
+            s.params.watchSlidesProgress = true;
+            s.params.spaceBetween = 0;
+            s.params.setWrapperSize = false;
+            if (typeof initialVirtualTranslate === 'undefined') {
+                s.params.virtualTranslate = true;
+            }
+        }
+        
+        // Grab Cursor
+        if (s.params.grabCursor && s.support.touch) {
+            s.params.grabCursor = false;
+        }
+        
+        // Wrapper
+        s.wrapper = s.container.children('.' + s.params.wrapperClass);
+        
+        // Pagination
+        if (s.params.pagination) {
+            s.paginationContainer = $(s.params.pagination);
+            if (s.params.uniqueNavElements && typeof s.params.pagination === 'string' && s.paginationContainer.length > 1 && s.container.find(s.params.pagination).length === 1) {
+                s.paginationContainer = s.container.find(s.params.pagination);
+            }
+        
+            if (s.params.paginationType === 'bullets' && s.params.paginationClickable) {
+                s.paginationContainer.addClass('swiper-pagination-clickable');
+            }
+            else {
+                s.params.paginationClickable = false;
+            }
+            s.paginationContainer.addClass('swiper-pagination-' + s.params.paginationType);
+        }
+        // Next/Prev Buttons
+        if (s.params.nextButton || s.params.prevButton) {
+            if (s.params.nextButton) {
+                s.nextButton = $(s.params.nextButton);
+                if (s.params.uniqueNavElements && typeof s.params.nextButton === 'string' && s.nextButton.length > 1 && s.container.find(s.params.nextButton).length === 1) {
+                    s.nextButton = s.container.find(s.params.nextButton);
+                }
+            }
+            if (s.params.prevButton) {
+                s.prevButton = $(s.params.prevButton);
+                if (s.params.uniqueNavElements && typeof s.params.prevButton === 'string' && s.prevButton.length > 1 && s.container.find(s.params.prevButton).length === 1) {
+                    s.prevButton = s.container.find(s.params.prevButton);
+                }
+            }
+        }
+        
+        // Is Horizontal
+        s.isHorizontal = function () {
+            return s.params.direction === 'horizontal';
+        };
+        // s.isH = isH;
+        
+        // RTL
+        s.rtl = s.isHorizontal() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl');
+        if (s.rtl) {
+            s.classNames.push('swiper-container-rtl');
+        }
+        
+        // Wrong RTL support
+        if (s.rtl) {
+            s.wrongRTL = s.wrapper.css('display') === '-webkit-box';
+        }
+        
+        // Columns
+        if (s.params.slidesPerColumn > 1) {
+            s.classNames.push('swiper-container-multirow');
+        }
+        
+        // Check for Android
+        if (s.device.android) {
+            s.classNames.push('swiper-container-android');
+        }
+        
+        // Add classes
+        s.container.addClass(s.classNames.join(' '));
+        
+        // Translate
+        s.translate = 0;
+        
+        // Progress
+        s.progress = 0;
+        
+        // Velocity
+        s.velocity = 0;
+        
+        /*=========================
+          Locks, unlocks
+          ===========================*/
+        s.lockSwipeToNext = function () {
+            s.params.allowSwipeToNext = false;
+        };
+        s.lockSwipeToPrev = function () {
+            s.params.allowSwipeToPrev = false;
+        };
+        s.lockSwipes = function () {
+            s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false;
+        };
+        s.unlockSwipeToNext = function () {
+            s.params.allowSwipeToNext = true;
+        };
+        s.unlockSwipeToPrev = function () {
+            s.params.allowSwipeToPrev = true;
+        };
+        s.unlockSwipes = function () {
+            s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true;
+        };
+        
+        /*=========================
+          Round helper
+          ===========================*/
+        function round(a) {
+            return Math.floor(a);
+        }
+        /*=========================
+          Set grab cursor
+          ===========================*/
+        if (s.params.grabCursor) {
+            s.container[0].style.cursor = 'move';
+            s.container[0].style.cursor = '-webkit-grab';
+            s.container[0].style.cursor = '-moz-grab';
+            s.container[0].style.cursor = 'grab';
+        }
+        /*=========================
+          Update on Images Ready
+          ===========================*/
+        s.imagesToLoad = [];
+        s.imagesLoaded = 0;
+        
+        s.loadImage = function (imgElement, src, srcset, checkForComplete, callback) {
+            var image;
+            function onReady () {
+                if (callback) callback();
+            }
+            if (!imgElement.complete || !checkForComplete) {
+                if (src) {
+                    image = new window.Image();
+                    image.onload = onReady;
+                    image.onerror = onReady;
+                    if (srcset) {
+                        image.srcset = srcset;
+                    }
+                    if (src) {
+                        image.src = src;
+                    }
+                } else {
+                    onReady();
+                }
+        
+            } else {//image already loaded...
+                onReady();
+            }
+        };
+        s.preloadImages = function () {
+            s.imagesToLoad = s.container.find('img');
+            function _onReady() {
+                if (typeof s === 'undefined' || s === null) return;
+                if (s.imagesLoaded !== undefined) s.imagesLoaded++;
+                if (s.imagesLoaded === s.imagesToLoad.length) {
+                    if (s.params.updateOnImagesReady) s.update();
+                    s.emit('onImagesReady', s);
+                }
+            }
+            for (var i = 0; i < s.imagesToLoad.length; i++) {
+                s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), true, _onReady);
+            }
+        };
+        
+        /*=========================
+          Autoplay
+          ===========================*/
+        s.autoplayTimeoutId = undefined;
+        s.autoplaying = false;
+        s.autoplayPaused = false;
+        function autoplay() {
+            s.autoplayTimeoutId = setTimeout(function () {
+                if (s.params.loop) {
+                    s.fixLoop();
+                    s._slideNext();
+                    s.emit('onAutoplay', s);
+                }
+                else {
+                    if (!s.isEnd) {
+                        s._slideNext();
+                        s.emit('onAutoplay', s);
+                    }
+                    else {
+                        if (!params.autoplayStopOnLast) {
+                            s._slideTo(0);
+                            s.emit('onAutoplay', s);
+                        }
+                        else {
+                            s.stopAutoplay();
+                        }
+                    }
+                }
+            }, s.params.autoplay);
+        }
+        s.startAutoplay = function () {
+            if (typeof s.autoplayTimeoutId !== 'undefined') return false;
+            if (!s.params.autoplay) return false;
+            if (s.autoplaying) return false;
+            s.autoplaying = true;
+            s.emit('onAutoplayStart', s);
+            autoplay();
+        };
+        s.stopAutoplay = function (internal) {
+            if (!s.autoplayTimeoutId) return;
+            if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
+            s.autoplaying = false;
+            s.autoplayTimeoutId = undefined;
+            s.emit('onAutoplayStop', s);
+        };
+        s.pauseAutoplay = function (speed) {
+            if (s.autoplayPaused) return;
+            if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
+            s.autoplayPaused = true;
+            if (speed === 0) {
+                s.autoplayPaused = false;
+                autoplay();
+            }
+            else {
+                s.wrapper.transitionEnd(function () {
+                    if (!s) return;
+                    s.autoplayPaused = false;
+                    if (!s.autoplaying) {
+                        s.stopAutoplay();
+                    }
+                    else {
+                        autoplay();
+                    }
+                });
+            }
+        };
+        /*=========================
+          Min/Max Translate
+          ===========================*/
+        s.minTranslate = function () {
+            return (-s.snapGrid[0]);
+        };
+        s.maxTranslate = function () {
+            return (-s.snapGrid[s.snapGrid.length - 1]);
+        };
+        /*=========================
+          Slider/slides sizes
+          ===========================*/
+        s.updateAutoHeight = function () {
+            // Update Height
+            var slide = s.slides.eq(s.activeIndex)[0];
+            if (typeof slide !== 'undefined') {
+                var newHeight = slide.offsetHeight;
+                if (newHeight) s.wrapper.css('height', newHeight + 'px');
+            }
+        };
+        s.updateContainerSize = function () {
+            var width, height;
+            if (typeof s.params.width !== 'undefined') {
+                width = s.params.width;
+            }
+            else {
+                width = s.container[0].clientWidth;
+            }
+            if (typeof s.params.height !== 'undefined') {
+                height = s.params.height;
+            }
+            else {
+                height = s.container[0].clientHeight;
+            }
+            if (width === 0 && s.isHorizontal() || height === 0 && !s.isHorizontal()) {
+                return;
+            }
+        
+            //Subtract paddings
+            width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10);
+            height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10);
+        
+            // Store values
+            s.width = width;
+            s.height = height;
+            s.size = s.isHorizontal() ? s.width : s.height;
+        };
+        
+        s.updateSlidesSize = function () {
+            s.slides = s.wrapper.children('.' + s.params.slideClass);
+            s.snapGrid = [];
+            s.slidesGrid = [];
+            s.slidesSizesGrid = [];
+        
+            var spaceBetween = s.params.spaceBetween,
+                slidePosition = -s.params.slidesOffsetBefore,
+                i,
+                prevSlideSize = 0,
+                index = 0;
+            if (typeof s.size === 'undefined') return;
+            if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
+                spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size;
+            }
+        
+            s.virtualSize = -spaceBetween;
+            // reset margins
+            if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''});
+            else s.slides.css({marginRight: '', marginBottom: ''});
+        
+            var slidesNumberEvenToRows;
+            if (s.params.slidesPerColumn > 1) {
+                if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) {
+                    slidesNumberEvenToRows = s.slides.length;
+                }
+                else {
+                    slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn;
+                }
+                if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') {
+                    slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn);
+                }
+            }
+        
+            // Calc slides
+            var slideSize;
+            var slidesPerColumn = s.params.slidesPerColumn;
+            var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
+            var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length);
+            for (i = 0; i < s.slides.length; i++) {
+                slideSize = 0;
+                var slide = s.slides.eq(i);
+                if (s.params.slidesPerColumn > 1) {
+                    // Set slides order
+                    var newSlideOrderIndex;
+                    var column, row;
+                    if (s.params.slidesPerColumnFill === 'column') {
+                        column = Math.floor(i / slidesPerColumn);
+                        row = i - column * slidesPerColumn;
+                        if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) {
+                            if (++row >= slidesPerColumn) {
+                                row = 0;
+                                column++;
+                            }
+                        }
+                        newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn;
+                        slide
+                            .css({
+                                '-webkit-box-ordinal-group': newSlideOrderIndex,
+                                '-moz-box-ordinal-group': newSlideOrderIndex,
+                                '-ms-flex-order': newSlideOrderIndex,
+                                '-webkit-order': newSlideOrderIndex,
+                                'order': newSlideOrderIndex
+                            });
+                    }
+                    else {
+                        row = Math.floor(i / slidesPerRow);
+                        column = i - row * slidesPerRow;
+                    }
+                    slide
+                        .css({
+                            'margin-top': (row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px')
+                        })
+                        .attr('data-swiper-column', column)
+                        .attr('data-swiper-row', row);
+        
+                }
+                if (slide.css('display') === 'none') continue;
+                if (s.params.slidesPerView === 'auto') {
+                    slideSize = s.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);
+                    if (s.params.roundLengths) slideSize = round(slideSize);
+                }
+                else {
+                    slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView;
+                    if (s.params.roundLengths) slideSize = round(slideSize);
+        
+                    if (s.isHorizontal()) {
+                        s.slides[i].style.width = slideSize + 'px';
+                    }
+                    else {
+                        s.slides[i].style.height = slideSize + 'px';
+                    }
+                }
+                s.slides[i].swiperSlideSize = slideSize;
+                s.slidesSizesGrid.push(slideSize);
+        
+        
+                if (s.params.centeredSlides) {
+                    slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
+                    if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween;
+                    if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
+                    if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
+                    s.slidesGrid.push(slidePosition);
+                }
+                else {
+                    if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
+                    s.slidesGrid.push(slidePosition);
+                    slidePosition = slidePosition + slideSize + spaceBetween;
+                }
+        
+                s.virtualSize += slideSize + spaceBetween;
+        
+                prevSlideSize = slideSize;
+        
+                index ++;
+            }
+            s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter;
+            var newSlidesGrid;
+        
+            if (
+                s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) {
+                s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+            }
+            if (!s.support.flexbox || s.params.setWrapperSize) {
+                if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+                else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'});
+            }
+        
+            if (s.params.slidesPerColumn > 1) {
+                s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows;
+                s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween;
+                s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+                if (s.params.centeredSlides) {
+                    newSlidesGrid = [];
+                    for (i = 0; i < s.snapGrid.length; i++) {
+                        if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]);
+                    }
+                    s.snapGrid = newSlidesGrid;
+                }
+            }
+        
+            // Remove last grid elements depending on width
+            if (!s.params.centeredSlides) {
+                newSlidesGrid = [];
+                for (i = 0; i < s.snapGrid.length; i++) {
+                    if (s.snapGrid[i] <= s.virtualSize - s.size) {
+                        newSlidesGrid.push(s.snapGrid[i]);
+                    }
+                }
+                s.snapGrid = newSlidesGrid;
+                if (Math.floor(s.virtualSize - s.size) - Math.floor(s.snapGrid[s.snapGrid.length - 1]) > 1) {
+                    s.snapGrid.push(s.virtualSize - s.size);
+                }
+            }
+            if (s.snapGrid.length === 0) s.snapGrid = [0];
+        
+            if (s.params.spaceBetween !== 0) {
+                if (s.isHorizontal()) {
+                    if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'});
+                    else s.slides.css({marginRight: spaceBetween + 'px'});
+                }
+                else s.slides.css({marginBottom: spaceBetween + 'px'});
+            }
+            if (s.params.watchSlidesProgress) {
+                s.updateSlidesOffset();
+            }
+        };
+        s.updateSlidesOffset = function () {
+            for (var i = 0; i < s.slides.length; i++) {
+                s.slides[i].swiperSlideOffset = s.isHorizontal() ? s.slides[i].offsetLeft : s.slides[i].offsetTop;
+            }
+        };
+        
+        /*=========================
+          Slider/slides progress
+          ===========================*/
+        s.updateSlidesProgress = function (translate) {
+            if (typeof translate === 'undefined') {
+                translate = s.translate || 0;
+            }
+            if (s.slides.length === 0) return;
+            if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset();
+        
+            var offsetCenter = -translate;
+            if (s.rtl) offsetCenter = translate;
+        
+            // Visible Slides
+            s.slides.removeClass(s.params.slideVisibleClass);
+            for (var i = 0; i < s.slides.length; i++) {
+                var slide = s.slides[i];
+                var slideProgress = (offsetCenter - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween);
+                if (s.params.watchSlidesVisibility) {
+                    var slideBefore = -(offsetCenter - slide.swiperSlideOffset);
+                    var slideAfter = slideBefore + s.slidesSizesGrid[i];
+                    var isVisible =
+                        (slideBefore >= 0 && slideBefore < s.size) ||
+                        (slideAfter > 0 && slideAfter <= s.size) ||
+                        (slideBefore <= 0 && slideAfter >= s.size);
+                    if (isVisible) {
+                        s.slides.eq(i).addClass(s.params.slideVisibleClass);
+                    }
+                }
+                slide.progress = s.rtl ? -slideProgress : slideProgress;
+            }
+        };
+        s.updateProgress = function (translate) {
+            if (typeof translate === 'undefined') {
+                translate = s.translate || 0;
+            }
+            var translatesDiff = s.maxTranslate() - s.minTranslate();
+            var wasBeginning = s.isBeginning;
+            var wasEnd = s.isEnd;
+            if (translatesDiff === 0) {
+                s.progress = 0;
+                s.isBeginning = s.isEnd = true;
+            }
+            else {
+                s.progress = (translate - s.minTranslate()) / (translatesDiff);
+                s.isBeginning = s.progress <= 0;
+                s.isEnd = s.progress >= 1;
+            }
+            if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s);
+            if (s.isEnd && !wasEnd) s.emit('onReachEnd', s);
+        
+            if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate);
+            s.emit('onProgress', s, s.progress);
+        };
+        s.updateActiveIndex = function () {
+            var translate = s.rtl ? s.translate : -s.translate;
+            var newActiveIndex, i, snapIndex;
+            for (i = 0; i < s.slidesGrid.length; i ++) {
+                if (typeof s.slidesGrid[i + 1] !== 'undefined') {
+                    if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) {
+                        newActiveIndex = i;
+                    }
+                    else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) {
+                        newActiveIndex = i + 1;
+                    }
+                }
+                else {
+                    if (translate >= s.slidesGrid[i]) {
+                        newActiveIndex = i;
+                    }
+                }
+            }
+            // Normalize slideIndex
+            if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0;
+            // for (i = 0; i < s.slidesGrid.length; i++) {
+                // if (- translate >= s.slidesGrid[i]) {
+                    // newActiveIndex = i;
+                // }
+            // }
+            snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup);
+            if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1;
+        
+            if (newActiveIndex === s.activeIndex) {
+                return;
+            }
+            s.snapIndex = snapIndex;
+            s.previousIndex = s.activeIndex;
+            s.activeIndex = newActiveIndex;
+            s.updateClasses();
+        };
+        
+        /*=========================
+          Classes
+          ===========================*/
+        s.updateClasses = function () {
+            s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass);
+            var activeSlide = s.slides.eq(s.activeIndex);
+            // Active classes
+            activeSlide.addClass(s.params.slideActiveClass);
+            // Next Slide
+            var nextSlide = activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass);
+            if (s.params.loop && nextSlide.length === 0) {
+                s.slides.eq(0).addClass(s.params.slideNextClass);
+            }
+            // Prev Slide
+            var prevSlide = activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass);
+            if (s.params.loop && prevSlide.length === 0) {
+                s.slides.eq(-1).addClass(s.params.slidePrevClass);
+            }
+        
+            // Pagination
+            if (s.paginationContainer && s.paginationContainer.length > 0) {
+                // Current/Total
+                var current,
+                    total = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
+                if (s.params.loop) {
+                    current = Math.ceil((s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup);
+                    if (current > s.slides.length - 1 - s.loopedSlides * 2) {
+                        current = current - (s.slides.length - s.loopedSlides * 2);
+                    }
+                    if (current > total - 1) current = current - total;
+                    if (current < 0 && s.params.paginationType !== 'bullets') current = total + current;
+                }
+                else {
+                    if (typeof s.snapIndex !== 'undefined') {
+                        current = s.snapIndex;
+                    }
+                    else {
+                        current = s.activeIndex || 0;
+                    }
+                }
+                // Types
+                if (s.params.paginationType === 'bullets' && s.bullets && s.bullets.length > 0) {
+                    s.bullets.removeClass(s.params.bulletActiveClass);
+                    if (s.paginationContainer.length > 1) {
+                        s.bullets.each(function () {
+                            if ($(this).index() === current) $(this).addClass(s.params.bulletActiveClass);
+                        });
+                    }
+                    else {
+                        s.bullets.eq(current).addClass(s.params.bulletActiveClass);
+                    }
+                }
+                if (s.params.paginationType === 'fraction') {
+                    s.paginationContainer.find('.' + s.params.paginationCurrentClass).text(current + 1);
+                    s.paginationContainer.find('.' + s.params.paginationTotalClass).text(total);
+                }
+                if (s.params.paginationType === 'progress') {
+                    var scale = (current + 1) / total,
+                        scaleX = scale,
+                        scaleY = 1;
+                    if (!s.isHorizontal()) {
+                        scaleY = scale;
+                        scaleX = 1;
+                    }
+                    s.paginationContainer.find('.' + s.params.paginationProgressbarClass).transform('translate3d(0,0,0) scaleX(' + scaleX + ') scaleY(' + scaleY + ')').transition(s.params.speed);
+                }
+                if (s.params.paginationType === 'custom' && s.params.paginationCustomRender) {
+                    s.paginationContainer.html(s.params.paginationCustomRender(s, current + 1, total));
+                    s.emit('onPaginationRendered', s, s.paginationContainer[0]);
+                }
+            }
+        
+            // Next/active buttons
+            if (!s.params.loop) {
+                if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                    if (s.isBeginning) {
+                        s.prevButton.addClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.disable(s.prevButton);
+                    }
+                    else {
+                        s.prevButton.removeClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.enable(s.prevButton);
+                    }
+                }
+                if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                    if (s.isEnd) {
+                        s.nextButton.addClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.disable(s.nextButton);
+                    }
+                    else {
+                        s.nextButton.removeClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.enable(s.nextButton);
+                    }
+                }
+            }
+        };
+        
+        /*=========================
+          Pagination
+          ===========================*/
+        s.updatePagination = function () {
+            if (!s.params.pagination) return;
+            if (s.paginationContainer && s.paginationContainer.length > 0) {
+                var paginationHTML = '';
+                if (s.params.paginationType === 'bullets') {
+                    var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
+                    for (var i = 0; i < numberOfBullets; i++) {
+                        if (s.params.paginationBulletRender) {
+                            paginationHTML += s.params.paginationBulletRender(i, s.params.bulletClass);
+                        }
+                        else {
+                            paginationHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>';
+                        }
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                    s.bullets = s.paginationContainer.find('.' + s.params.bulletClass);
+                    if (s.params.paginationClickable && s.params.a11y && s.a11y) {
+                        s.a11y.initPagination();
+                    }
+                }
+                if (s.params.paginationType === 'fraction') {
+                    if (s.params.paginationFractionRender) {
+                        paginationHTML = s.params.paginationFractionRender(s, s.params.paginationCurrentClass, s.params.paginationTotalClass);
+                    }
+                    else {
+                        paginationHTML =
+                            '<span class="' + s.params.paginationCurrentClass + '"></span>' +
+                            ' / ' +
+                            '<span class="' + s.params.paginationTotalClass+'"></span>';
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                }
+                if (s.params.paginationType === 'progress') {
+                    if (s.params.paginationProgressRender) {
+                        paginationHTML = s.params.paginationProgressRender(s, s.params.paginationProgressbarClass);
+                    }
+                    else {
+                        paginationHTML = '<span class="' + s.params.paginationProgressbarClass + '"></span>';
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                }
+                if (s.params.paginationType !== 'custom') {
+                    s.emit('onPaginationRendered', s, s.paginationContainer[0]);
+                }
+            }
+        };
+        /*=========================
+          Common update method
+          ===========================*/
+        s.update = function (updateTranslate) {
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            s.updateProgress();
+            s.updatePagination();
+            s.updateClasses();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+            }
+            function forceSetTranslate() {
+                newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
+                s.setWrapperTranslate(newTranslate);
+                s.updateActiveIndex();
+                s.updateClasses();
+            }
+            if (updateTranslate) {
+                var translated, newTranslate;
+                if (s.controller && s.controller.spline) {
+                    s.controller.spline = undefined;
+                }
+                if (s.params.freeMode) {
+                    forceSetTranslate();
+                    if (s.params.autoHeight) {
+                        s.updateAutoHeight();
+                    }
+                }
+                else {
+                    if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
+                        translated = s.slideTo(s.slides.length - 1, 0, false, true);
+                    }
+                    else {
+                        translated = s.slideTo(s.activeIndex, 0, false, true);
+                    }
+                    if (!translated) {
+                        forceSetTranslate();
+                    }
+                }
+            }
+            else if (s.params.autoHeight) {
+                s.updateAutoHeight();
+            }
+        };
+        
+        /*=========================
+          Resize Handler
+          ===========================*/
+        s.onResize = function (forceUpdatePagination) {
+            //Breakpoints
+            if (s.params.breakpoints) {
+                s.setBreakpoint();
+            }
+        
+            // Disable locks on resize
+            var allowSwipeToPrev = s.params.allowSwipeToPrev;
+            var allowSwipeToNext = s.params.allowSwipeToNext;
+            s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true;
+        
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+            }
+            if (s.controller && s.controller.spline) {
+                s.controller.spline = undefined;
+            }
+            var slideChangedBySlideTo = false;
+            if (s.params.freeMode) {
+                var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
+                s.setWrapperTranslate(newTranslate);
+                s.updateActiveIndex();
+                s.updateClasses();
+        
+                if (s.params.autoHeight) {
+                    s.updateAutoHeight();
+                }
+            }
+            else {
+                s.updateClasses();
+                if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
+                    slideChangedBySlideTo = s.slideTo(s.slides.length - 1, 0, false, true);
+                }
+                else {
+                    slideChangedBySlideTo = s.slideTo(s.activeIndex, 0, false, true);
+                }
+            }
+            if (s.params.lazyLoading && !slideChangedBySlideTo && s.lazy) {
+                s.lazy.load();
+            }
+            // Return locks after resize
+            s.params.allowSwipeToPrev = allowSwipeToPrev;
+            s.params.allowSwipeToNext = allowSwipeToNext;
+        };
+        
+        /*=========================
+          Events
+          ===========================*/
+        
+        //Define Touch Events
+        var desktopEvents = ['mousedown', 'mousemove', 'mouseup'];
+        if (window.navigator.pointerEnabled) desktopEvents = ['pointerdown', 'pointermove', 'pointerup'];
+        else if (window.navigator.msPointerEnabled) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp'];
+        s.touchEvents = {
+            start : s.support.touch || !s.params.simulateTouch  ? 'touchstart' : desktopEvents[0],
+            move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : desktopEvents[1],
+            end : s.support.touch || !s.params.simulateTouch ? 'touchend' : desktopEvents[2]
+        };
+        
+        
+        // WP8 Touch Events Fix
+        if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) {
+            (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction);
+        }
+        
+        // Attach/detach events
+        s.initEvents = function (detach) {
+            var actionDom = detach ? 'off' : 'on';
+            var action = detach ? 'removeEventListener' : 'addEventListener';
+            var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0];
+            var target = s.support.touch ? touchEventsTarget : document;
+        
+            var moveCapture = s.params.nested ? true : false;
+        
+            //Touch Events
+            if (s.browser.ie) {
+                touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
+                target[action](s.touchEvents.move, s.onTouchMove, moveCapture);
+                target[action](s.touchEvents.end, s.onTouchEnd, false);
+            }
+            else {
+                if (s.support.touch) {
+                    touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
+                    touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture);
+                    touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, false);
+                }
+                if (params.simulateTouch && !s.device.ios && !s.device.android) {
+                    touchEventsTarget[action]('mousedown', s.onTouchStart, false);
+                    document[action]('mousemove', s.onTouchMove, moveCapture);
+                    document[action]('mouseup', s.onTouchEnd, false);
+                }
+            }
+            window[action]('resize', s.onResize);
+        
+            // Next, Prev, Index
+            if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                s.nextButton[actionDom]('click', s.onClickNext);
+                if (s.params.a11y && s.a11y) s.nextButton[actionDom]('keydown', s.a11y.onEnterKey);
+            }
+            if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                s.prevButton[actionDom]('click', s.onClickPrev);
+                if (s.params.a11y && s.a11y) s.prevButton[actionDom]('keydown', s.a11y.onEnterKey);
+            }
+            if (s.params.pagination && s.params.paginationClickable) {
+                s.paginationContainer[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex);
+                if (s.params.a11y && s.a11y) s.paginationContainer[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey);
+            }
+        
+            // Prevent Links Clicks
+            if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true);
+        };
+        s.attachEvents = function () {
+            s.initEvents();
+        };
+        s.detachEvents = function () {
+            s.initEvents(true);
+        };
+        
+        /*=========================
+          Handle Clicks
+          ===========================*/
+        // Prevent Clicks
+        s.allowClick = true;
+        s.preventClicks = function (e) {
+            if (!s.allowClick) {
+                if (s.params.preventClicks) e.preventDefault();
+                if (s.params.preventClicksPropagation && s.animating) {
+                    e.stopPropagation();
+                    e.stopImmediatePropagation();
+                }
+            }
+        };
+        // Clicks
+        s.onClickNext = function (e) {
+            e.preventDefault();
+            if (s.isEnd && !s.params.loop) return;
+            s.slideNext();
+        };
+        s.onClickPrev = function (e) {
+            e.preventDefault();
+            if (s.isBeginning && !s.params.loop) return;
+            s.slidePrev();
+        };
+        s.onClickIndex = function (e) {
+            e.preventDefault();
+            var index = $(this).index() * s.params.slidesPerGroup;
+            if (s.params.loop) index = index + s.loopedSlides;
+            s.slideTo(index);
+        };
+        
+        /*=========================
+          Handle Touches
+          ===========================*/
+        function findElementInEvent(e, selector) {
+            var el = $(e.target);
+            if (!el.is(selector)) {
+                if (typeof selector === 'string') {
+                    el = el.parents(selector);
+                }
+                else if (selector.nodeType) {
+                    var found;
+                    el.parents().each(function (index, _el) {
+                        if (_el === selector) found = selector;
+                    });
+                    if (!found) return undefined;
+                    else return selector;
+                }
+            }
+            if (el.length === 0) {
+                return undefined;
+            }
+            return el[0];
+        }
+        s.updateClickedSlide = function (e) {
+            var slide = findElementInEvent(e, '.' + s.params.slideClass);
+            var slideFound = false;
+            if (slide) {
+                for (var i = 0; i < s.slides.length; i++) {
+                    if (s.slides[i] === slide) slideFound = true;
+                }
+            }
+        
+            if (slide && slideFound) {
+                s.clickedSlide = slide;
+                s.clickedIndex = $(slide).index();
+            }
+            else {
+                s.clickedSlide = undefined;
+                s.clickedIndex = undefined;
+                return;
+            }
+            if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) {
+                var slideToIndex = s.clickedIndex,
+                    realIndex,
+                    duplicatedSlides;
+                if (s.params.loop) {
+                    if (s.animating) return;
+                    realIndex = $(s.clickedSlide).attr('data-swiper-slide-index');
+                    if (s.params.centeredSlides) {
+                        if ((slideToIndex < s.loopedSlides - s.params.slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + s.params.slidesPerView/2)) {
+                            s.fixLoop();
+                            slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index();
+                            setTimeout(function () {
+                                s.slideTo(slideToIndex);
+                            }, 0);
+                        }
+                        else {
+                            s.slideTo(slideToIndex);
+                        }
+                    }
+                    else {
+                        if (slideToIndex > s.slides.length - s.params.slidesPerView) {
+                            s.fixLoop();
+                            slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index();
+                            setTimeout(function () {
+                                s.slideTo(slideToIndex);
+                            }, 0);
+                        }
+                        else {
+                            s.slideTo(slideToIndex);
+                        }
+                    }
+                }
+                else {
+                    s.slideTo(slideToIndex);
+                }
+            }
+        };
+        
+        var isTouched,
+            isMoved,
+            allowTouchCallbacks,
+            touchStartTime,
+            isScrolling,
+            currentTranslate,
+            startTranslate,
+            allowThresholdMove,
+            // Form elements to match
+            formElements = 'input, select, textarea, button',
+            // Last click time
+            lastClickTime = Date.now(), clickTimeout,
+            //Velocities
+            velocities = [],
+            allowMomentumBounce;
+        
+        // Animating Flag
+        s.animating = false;
+        
+        // Touches information
+        s.touches = {
+            startX: 0,
+            startY: 0,
+            currentX: 0,
+            currentY: 0,
+            diff: 0
+        };
+        
+        // Touch handlers
+        var isTouchEvent, startMoving;
+        s.onTouchStart = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            isTouchEvent = e.type === 'touchstart';
+            if (!isTouchEvent && 'which' in e && e.which === 3) return;
+            if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) {
+                s.allowClick = true;
+                return;
+            }
+            if (s.params.swipeHandler) {
+                if (!findElementInEvent(e, s.params.swipeHandler)) return;
+            }
+        
+            var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
+            var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
+        
+            // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
+            if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) {
+                return;
+            }
+        
+            isTouched = true;
+            isMoved = false;
+            allowTouchCallbacks = true;
+            isScrolling = undefined;
+            startMoving = undefined;
+            s.touches.startX = startX;
+            s.touches.startY = startY;
+            touchStartTime = Date.now();
+            s.allowClick = true;
+            s.updateContainerSize();
+            s.swipeDirection = undefined;
+            if (s.params.threshold > 0) allowThresholdMove = false;
+            if (e.type !== 'touchstart') {
+                var preventDefault = true;
+                if ($(e.target).is(formElements)) preventDefault = false;
+                if (document.activeElement && $(document.activeElement).is(formElements)) {
+                    document.activeElement.blur();
+                }
+                if (preventDefault) {
+                    e.preventDefault();
+                }
+            }
+            s.emit('onTouchStart', s, e);
+        };
+        
+        s.onTouchMove = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            if (isTouchEvent && e.type === 'mousemove') return;
+            if (e.preventedByNestedSwiper) {
+                s.touches.startX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+                s.touches.startY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+                return;
+            }
+            if (s.params.onlyExternal) {
+                // isMoved = true;
+                s.allowClick = false;
+                if (isTouched) {
+                    s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+                    s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+                    touchStartTime = Date.now();
+                }
+                return;
+            }
+            if (isTouchEvent && document.activeElement) {
+                if (e.target === document.activeElement && $(e.target).is(formElements)) {
+                    isMoved = true;
+                    s.allowClick = false;
+                    return;
+                }
+            }
+            if (allowTouchCallbacks) {
+                s.emit('onTouchMove', s, e);
+            }
+            if (e.targetTouches && e.targetTouches.length > 1) return;
+        
+            s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+            s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+        
+            if (typeof isScrolling === 'undefined') {
+                var touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI;
+                isScrolling = s.isHorizontal() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle);
+            }
+            if (isScrolling) {
+                s.emit('onTouchMoveOpposite', s, e);
+            }
+            if (typeof startMoving === 'undefined' && s.browser.ieTouch) {
+                if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) {
+                    startMoving = true;
+                }
+            }
+            if (!isTouched) return;
+            if (isScrolling)  {
+                isTouched = false;
+                return;
+            }
+            if (!startMoving && s.browser.ieTouch) {
+                return;
+            }
+            s.allowClick = false;
+            s.emit('onSliderMove', s, e);
+            e.preventDefault();
+            if (s.params.touchMoveStopPropagation && !s.params.nested) {
+                e.stopPropagation();
+            }
+        
+            if (!isMoved) {
+                if (params.loop) {
+                    s.fixLoop();
+                }
+                startTranslate = s.getWrapperTranslate();
+                s.setWrapperTransition(0);
+                if (s.animating) {
+                    s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd');
+                }
+                if (s.params.autoplay && s.autoplaying) {
+                    if (s.params.autoplayDisableOnInteraction) {
+                        s.stopAutoplay();
+                    }
+                    else {
+                        s.pauseAutoplay();
+                    }
+                }
+                allowMomentumBounce = false;
+                //Grab Cursor
+                if (s.params.grabCursor) {
+                    s.container[0].style.cursor = 'move';
+                    s.container[0].style.cursor = '-webkit-grabbing';
+                    s.container[0].style.cursor = '-moz-grabbin';
+                    s.container[0].style.cursor = 'grabbing';
+                }
+            }
+            isMoved = true;
+        
+            var diff = s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
+        
+            diff = diff * s.params.touchRatio;
+            if (s.rtl) diff = -diff;
+        
+            s.swipeDirection = diff > 0 ? 'prev' : 'next';
+            currentTranslate = diff + startTranslate;
+        
+            var disableParentSwiper = true;
+            if ((diff > 0 && currentTranslate > s.minTranslate())) {
+                disableParentSwiper = false;
+                if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio);
+            }
+            else if (diff < 0 && currentTranslate < s.maxTranslate()) {
+                disableParentSwiper = false;
+                if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio);
+            }
+        
+            if (disableParentSwiper) {
+                e.preventedByNestedSwiper = true;
+            }
+        
+            // Directions locks
+            if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) {
+                currentTranslate = startTranslate;
+            }
+            if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) {
+                currentTranslate = startTranslate;
+            }
+        
+            if (!s.params.followFinger) return;
+        
+            // Threshold
+            if (s.params.threshold > 0) {
+                if (Math.abs(diff) > s.params.threshold || allowThresholdMove) {
+                    if (!allowThresholdMove) {
+                        allowThresholdMove = true;
+                        s.touches.startX = s.touches.currentX;
+                        s.touches.startY = s.touches.currentY;
+                        currentTranslate = startTranslate;
+                        s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
+                        return;
+                    }
+                }
+                else {
+                    currentTranslate = startTranslate;
+                    return;
+                }
+            }
+            // Update active index in free mode
+            if (s.params.freeMode || s.params.watchSlidesProgress) {
+                s.updateActiveIndex();
+            }
+            if (s.params.freeMode) {
+                //Velocity
+                if (velocities.length === 0) {
+                    velocities.push({
+                        position: s.touches[s.isHorizontal() ? 'startX' : 'startY'],
+                        time: touchStartTime
+                    });
+                }
+                velocities.push({
+                    position: s.touches[s.isHorizontal() ? 'currentX' : 'currentY'],
+                    time: (new window.Date()).getTime()
+                });
+            }
+            // Update progress
+            s.updateProgress(currentTranslate);
+            // Update translate
+            s.setWrapperTranslate(currentTranslate);
+        };
+        s.onTouchEnd = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            if (allowTouchCallbacks) {
+                s.emit('onTouchEnd', s, e);
+            }
+            allowTouchCallbacks = false;
+            if (!isTouched) return;
+            //Return Grab Cursor
+            if (s.params.grabCursor && isMoved && isTouched) {
+                s.container[0].style.cursor = 'move';
+                s.container[0].style.cursor = '-webkit-grab';
+                s.container[0].style.cursor = '-moz-grab';
+                s.container[0].style.cursor = 'grab';
+            }
+        
+            // Time diff
+            var touchEndTime = Date.now();
+            var timeDiff = touchEndTime - touchStartTime;
+        
+            // Tap, doubleTap, Click
+            if (s.allowClick) {
+                s.updateClickedSlide(e);
+                s.emit('onTap', s, e);
+                if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) {
+                    if (clickTimeout) clearTimeout(clickTimeout);
+                    clickTimeout = setTimeout(function () {
+                        if (!s) return;
+                        if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) {
+                            s.paginationContainer.toggleClass(s.params.paginationHiddenClass);
+                        }
+                        s.emit('onClick', s, e);
+                    }, 300);
+        
+                }
+                if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) {
+                    if (clickTimeout) clearTimeout(clickTimeout);
+                    s.emit('onDoubleTap', s, e);
+                }
+            }
+        
+            lastClickTime = Date.now();
+            setTimeout(function () {
+                if (s) s.allowClick = true;
+            }, 0);
+        
+            if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) {
+                isTouched = isMoved = false;
+                return;
+            }
+            isTouched = isMoved = false;
+        
+            var currentPos;
+            if (s.params.followFinger) {
+                currentPos = s.rtl ? s.translate : -s.translate;
+            }
+            else {
+                currentPos = -currentTranslate;
+            }
+            if (s.params.freeMode) {
+                if (currentPos < -s.minTranslate()) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                else if (currentPos > -s.maxTranslate()) {
+                    if (s.slides.length < s.snapGrid.length) {
+                        s.slideTo(s.snapGrid.length - 1);
+                    }
+                    else {
+                        s.slideTo(s.slides.length - 1);
+                    }
+                    return;
+                }
+        
+                if (s.params.freeModeMomentum) {
+                    if (velocities.length > 1) {
+                        var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop();
+        
+                        var distance = lastMoveEvent.position - velocityEvent.position;
+                        var time = lastMoveEvent.time - velocityEvent.time;
+                        s.velocity = distance / time;
+                        s.velocity = s.velocity / 2;
+                        if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) {
+                            s.velocity = 0;
+                        }
+                        // this implies that the user stopped moving a finger then released.
+                        // There would be no events with distance zero, so the last event is stale.
+                        if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) {
+                            s.velocity = 0;
+                        }
+                    } else {
+                        s.velocity = 0;
+                    }
+        
+                    velocities.length = 0;
+                    var momentumDuration = 1000 * s.params.freeModeMomentumRatio;
+                    var momentumDistance = s.velocity * momentumDuration;
+        
+                    var newPosition = s.translate + momentumDistance;
+                    if (s.rtl) newPosition = - newPosition;
+                    var doBounce = false;
+                    var afterBouncePosition;
+                    var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio;
+                    if (newPosition < s.maxTranslate()) {
+                        if (s.params.freeModeMomentumBounce) {
+                            if (newPosition + s.maxTranslate() < -bounceAmount) {
+                                newPosition = s.maxTranslate() - bounceAmount;
+                            }
+                            afterBouncePosition = s.maxTranslate();
+                            doBounce = true;
+                            allowMomentumBounce = true;
+                        }
+                        else {
+                            newPosition = s.maxTranslate();
+                        }
+                    }
+                    else if (newPosition > s.minTranslate()) {
+                        if (s.params.freeModeMomentumBounce) {
+                            if (newPosition - s.minTranslate() > bounceAmount) {
+                                newPosition = s.minTranslate() + bounceAmount;
+                            }
+                            afterBouncePosition = s.minTranslate();
+                            doBounce = true;
+                            allowMomentumBounce = true;
+                        }
+                        else {
+                            newPosition = s.minTranslate();
+                        }
+                    }
+                    else if (s.params.freeModeSticky) {
+                        var j = 0,
+                            nextSlide;
+                        for (j = 0; j < s.snapGrid.length; j += 1) {
+                            if (s.snapGrid[j] > -newPosition) {
+                                nextSlide = j;
+                                break;
+                            }
+        
+                        }
+                        if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') {
+                            newPosition = s.snapGrid[nextSlide];
+                        } else {
+                            newPosition = s.snapGrid[nextSlide - 1];
+                        }
+                        if (!s.rtl) newPosition = - newPosition;
+                    }
+                    //Fix duration
+                    if (s.velocity !== 0) {
+                        if (s.rtl) {
+                            momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity);
+                        }
+                        else {
+                            momentumDuration = Math.abs((newPosition - s.translate) / s.velocity);
+                        }
+                    }
+                    else if (s.params.freeModeSticky) {
+                        s.slideReset();
+                        return;
+                    }
+        
+                    if (s.params.freeModeMomentumBounce && doBounce) {
+                        s.updateProgress(afterBouncePosition);
+                        s.setWrapperTransition(momentumDuration);
+                        s.setWrapperTranslate(newPosition);
+                        s.onTransitionStart();
+                        s.animating = true;
+                        s.wrapper.transitionEnd(function () {
+                            if (!s || !allowMomentumBounce) return;
+                            s.emit('onMomentumBounce', s);
+        
+                            s.setWrapperTransition(s.params.speed);
+                            s.setWrapperTranslate(afterBouncePosition);
+                            s.wrapper.transitionEnd(function () {
+                                if (!s) return;
+                                s.onTransitionEnd();
+                            });
+                        });
+                    } else if (s.velocity) {
+                        s.updateProgress(newPosition);
+                        s.setWrapperTransition(momentumDuration);
+                        s.setWrapperTranslate(newPosition);
+                        s.onTransitionStart();
+                        if (!s.animating) {
+                            s.animating = true;
+                            s.wrapper.transitionEnd(function () {
+                                if (!s) return;
+                                s.onTransitionEnd();
+                            });
+                        }
+        
+                    } else {
+                        s.updateProgress(newPosition);
+                    }
+        
+                    s.updateActiveIndex();
+                }
+                if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) {
+                    s.updateProgress();
+                    s.updateActiveIndex();
+                }
+                return;
+            }
+        
+            // Find current slide
+            var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0];
+            for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) {
+                if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') {
+                    if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) {
+                        stopIndex = i;
+                        groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i];
+                    }
+                }
+                else {
+                    if (currentPos >= s.slidesGrid[i]) {
+                        stopIndex = i;
+                        groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2];
+                    }
+                }
+            }
+        
+            // Find current slide size
+            var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize;
+        
+            if (timeDiff > s.params.longSwipesMs) {
+                // Long touches
+                if (!s.params.longSwipes) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                if (s.swipeDirection === 'next') {
+                    if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup);
+                    else s.slideTo(stopIndex);
+        
+                }
+                if (s.swipeDirection === 'prev') {
+                    if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup);
+                    else s.slideTo(stopIndex);
+                }
+            }
+            else {
+                // Short swipes
+                if (!s.params.shortSwipes) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                if (s.swipeDirection === 'next') {
+                    s.slideTo(stopIndex + s.params.slidesPerGroup);
+        
+                }
+                if (s.swipeDirection === 'prev') {
+                    s.slideTo(stopIndex);
+                }
+            }
+        };
+        /*=========================
+          Transitions
+          ===========================*/
+        s._slideTo = function (slideIndex, speed) {
+            return s.slideTo(slideIndex, speed, true, true);
+        };
+        s.slideTo = function (slideIndex, speed, runCallbacks, internal) {
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (typeof slideIndex === 'undefined') slideIndex = 0;
+            if (slideIndex < 0) slideIndex = 0;
+            s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup);
+            if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1;
+        
+            var translate = - s.snapGrid[s.snapIndex];
+            // Stop autoplay
+            if (s.params.autoplay && s.autoplaying) {
+                if (internal || !s.params.autoplayDisableOnInteraction) {
+                    s.pauseAutoplay(speed);
+                }
+                else {
+                    s.stopAutoplay();
+                }
+            }
+            // Update progress
+            s.updateProgress(translate);
+        
+            // Normalize slideIndex
+            for (var i = 0; i < s.slidesGrid.length; i++) {
+                if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) {
+                    slideIndex = i;
+                }
+            }
+        
+            // Directions locks
+            if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) {
+                return false;
+            }
+            if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) {
+                if ((s.activeIndex || 0) !== slideIndex ) return false;
+            }
+        
+            // Update Index
+            if (typeof speed === 'undefined') speed = s.params.speed;
+            s.previousIndex = s.activeIndex || 0;
+            s.activeIndex = slideIndex;
+        
+            if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) {
+                // Update Height
+                if (s.params.autoHeight) {
+                    s.updateAutoHeight();
+                }
+                s.updateClasses();
+                if (s.params.effect !== 'slide') {
+                    s.setWrapperTranslate(translate);
+                }
+                return false;
+            }
+            s.updateClasses();
+            s.onTransitionStart(runCallbacks);
+        
+            if (speed === 0) {
+                s.setWrapperTranslate(translate);
+                s.setWrapperTransition(0);
+                s.onTransitionEnd(runCallbacks);
+            }
+            else {
+                s.setWrapperTranslate(translate);
+                s.setWrapperTransition(speed);
+                if (!s.animating) {
+                    s.animating = true;
+                    s.wrapper.transitionEnd(function () {
+                        if (!s) return;
+                        s.onTransitionEnd(runCallbacks);
+                    });
+                }
+        
+            }
+        
+            return true;
+        };
+        
+        s.onTransitionStart = function (runCallbacks) {
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (s.params.autoHeight) {
+                s.updateAutoHeight();
+            }
+            if (s.lazy) s.lazy.onTransitionStart();
+            if (runCallbacks) {
+                s.emit('onTransitionStart', s);
+                if (s.activeIndex !== s.previousIndex) {
+                    s.emit('onSlideChangeStart', s);
+                    if (s.activeIndex > s.previousIndex) {
+                        s.emit('onSlideNextStart', s);
+                    }
+                    else {
+                        s.emit('onSlidePrevStart', s);
+                    }
+                }
+        
+            }
+        };
+        s.onTransitionEnd = function (runCallbacks) {
+            s.animating = false;
+            s.setWrapperTransition(0);
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (s.lazy) s.lazy.onTransitionEnd();
+            if (runCallbacks) {
+                s.emit('onTransitionEnd', s);
+                if (s.activeIndex !== s.previousIndex) {
+                    s.emit('onSlideChangeEnd', s);
+                    if (s.activeIndex > s.previousIndex) {
+                        s.emit('onSlideNextEnd', s);
+                    }
+                    else {
+                        s.emit('onSlidePrevEnd', s);
+                    }
+                }
+            }
+            if (s.params.hashnav && s.hashnav) {
+                s.hashnav.setHash();
+            }
+        
+        };
+        s.slideNext = function (runCallbacks, speed, internal) {
+            if (s.params.loop) {
+                if (s.animating) return false;
+                s.fixLoop();
+                var clientLeft = s.container[0].clientLeft;
+                return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
+            }
+            else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
+        };
+        s._slideNext = function (speed) {
+            return s.slideNext(true, speed, true);
+        };
+        s.slidePrev = function (runCallbacks, speed, internal) {
+            if (s.params.loop) {
+                if (s.animating) return false;
+                s.fixLoop();
+                var clientLeft = s.container[0].clientLeft;
+                return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
+            }
+            else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
+        };
+        s._slidePrev = function (speed) {
+            return s.slidePrev(true, speed, true);
+        };
+        s.slideReset = function (runCallbacks, speed, internal) {
+            return s.slideTo(s.activeIndex, speed, runCallbacks);
+        };
+        
+        /*=========================
+          Translate/transition helpers
+          ===========================*/
+        s.setWrapperTransition = function (duration, byController) {
+            s.wrapper.transition(duration);
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                s.effects[s.params.effect].setTransition(duration);
+            }
+            if (s.params.parallax && s.parallax) {
+                s.parallax.setTransition(duration);
+            }
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.setTransition(duration);
+            }
+            if (s.params.control && s.controller) {
+                s.controller.setTransition(duration, byController);
+            }
+            s.emit('onSetTransition', s, duration);
+        };
+        s.setWrapperTranslate = function (translate, updateActiveIndex, byController) {
+            var x = 0, y = 0, z = 0;
+            if (s.isHorizontal()) {
+                x = s.rtl ? -translate : translate;
+            }
+            else {
+                y = translate;
+            }
+        
+            if (s.params.roundLengths) {
+                x = round(x);
+                y = round(y);
+            }
+        
+            if (!s.params.virtualTranslate) {
+                if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)');
+                else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)');
+            }
+        
+            s.translate = s.isHorizontal() ? x : y;
+        
+            // Check if we need to update progress
+            var progress;
+            var translatesDiff = s.maxTranslate() - s.minTranslate();
+            if (translatesDiff === 0) {
+                progress = 0;
+            }
+            else {
+                progress = (translate - s.minTranslate()) / (translatesDiff);
+            }
+            if (progress !== s.progress) {
+                s.updateProgress(translate);
+            }
+        
+            if (updateActiveIndex) s.updateActiveIndex();
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                s.effects[s.params.effect].setTranslate(s.translate);
+            }
+            if (s.params.parallax && s.parallax) {
+                s.parallax.setTranslate(s.translate);
+            }
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.setTranslate(s.translate);
+            }
+            if (s.params.control && s.controller) {
+                s.controller.setTranslate(s.translate, byController);
+            }
+            s.emit('onSetTranslate', s, s.translate);
+        };
+        
+        s.getTranslate = function (el, axis) {
+            var matrix, curTransform, curStyle, transformMatrix;
+        
+            // automatic axis detection
+            if (typeof axis === 'undefined') {
+                axis = 'x';
+            }
+        
+            if (s.params.virtualTranslate) {
+                return s.rtl ? -s.translate : s.translate;
+            }
+        
+            curStyle = window.getComputedStyle(el, null);
+            if (window.WebKitCSSMatrix) {
+                curTransform = curStyle.transform || curStyle.webkitTransform;
+                if (curTransform.split(',').length > 6) {
+                    curTransform = curTransform.split(', ').map(function(a){
+                        return a.replace(',','.');
+                    }).join(', ');
+                }
+                // Some old versions of Webkit choke when 'none' is passed; pass
+                // empty string instead in this case
+                transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
+            }
+            else {
+                transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
+                matrix = transformMatrix.toString().split(',');
+            }
+        
+            if (axis === 'x') {
+                //Latest Chrome and webkits Fix
+                if (window.WebKitCSSMatrix)
+                    curTransform = transformMatrix.m41;
+                //Crazy IE10 Matrix
+                else if (matrix.length === 16)
+                    curTransform = parseFloat(matrix[12]);
+                //Normal Browsers
+                else
+                    curTransform = parseFloat(matrix[4]);
+            }
+            if (axis === 'y') {
+                //Latest Chrome and webkits Fix
+                if (window.WebKitCSSMatrix)
+                    curTransform = transformMatrix.m42;
+                //Crazy IE10 Matrix
+                else if (matrix.length === 16)
+                    curTransform = parseFloat(matrix[13]);
+                //Normal Browsers
+                else
+                    curTransform = parseFloat(matrix[5]);
+            }
+            if (s.rtl && curTransform) curTransform = -curTransform;
+            return curTransform || 0;
+        };
+        s.getWrapperTranslate = function (axis) {
+            if (typeof axis === 'undefined') {
+                axis = s.isHorizontal() ? 'x' : 'y';
+            }
+            return s.getTranslate(s.wrapper[0], axis);
+        };
+        
+        /*=========================
+          Observer
+          ===========================*/
+        s.observers = [];
+        function initObserver(target, options) {
+            options = options || {};
+            // create an observer instance
+            var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
+            var observer = new ObserverFunc(function (mutations) {
+                mutations.forEach(function (mutation) {
+                    s.onResize(true);
+                    s.emit('onObserverUpdate', s, mutation);
+                });
+            });
+        
+            observer.observe(target, {
+                attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
+                childList: typeof options.childList === 'undefined' ? true : options.childList,
+                characterData: typeof options.characterData === 'undefined' ? true : options.characterData
+            });
+        
+            s.observers.push(observer);
+        }
+        s.initObservers = function () {
+            if (s.params.observeParents) {
+                var containerParents = s.container.parents();
+                for (var i = 0; i < containerParents.length; i++) {
+                    initObserver(containerParents[i]);
+                }
+            }
+        
+            // Observe container
+            initObserver(s.container[0], {childList: false});
+        
+            // Observe wrapper
+            initObserver(s.wrapper[0], {attributes: false});
+        };
+        s.disconnectObservers = function () {
+            for (var i = 0; i < s.observers.length; i++) {
+                s.observers[i].disconnect();
+            }
+            s.observers = [];
+        };
+        /*=========================
+          Loop
+          ===========================*/
+        // Create looped slides
+        s.createLoop = function () {
+            // Remove duplicated slides
+            s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
+        
+            var slides = s.wrapper.children('.' + s.params.slideClass);
+        
+            if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length;
+        
+            s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10);
+            s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides;
+            if (s.loopedSlides > slides.length) {
+                s.loopedSlides = slides.length;
+            }
+        
+            var prependSlides = [], appendSlides = [], i;
+            slides.each(function (index, el) {
+                var slide = $(this);
+                if (index < s.loopedSlides) appendSlides.push(el);
+                if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el);
+                slide.attr('data-swiper-slide-index', index);
+            });
+            for (i = 0; i < appendSlides.length; i++) {
+                s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
+            }
+            for (i = prependSlides.length - 1; i >= 0; i--) {
+                s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
+            }
+        };
+        s.destroyLoop = function () {
+            s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
+            s.slides.removeAttr('data-swiper-slide-index');
+        };
+        s.reLoop = function (updatePosition) {
+            var oldIndex = s.activeIndex - s.loopedSlides;
+            s.destroyLoop();
+            s.createLoop();
+            s.updateSlidesSize();
+            if (updatePosition) {
+                s.slideTo(oldIndex + s.loopedSlides, 0, false);
+            }
+        
+        };
+        s.fixLoop = function () {
+            var newIndex;
+            //Fix For Negative Oversliding
+            if (s.activeIndex < s.loopedSlides) {
+                newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex;
+                newIndex = newIndex + s.loopedSlides;
+                s.slideTo(newIndex, 0, false, true);
+            }
+            //Fix For Positive Oversliding
+            else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) {
+                newIndex = -s.slides.length + s.activeIndex + s.loopedSlides;
+                newIndex = newIndex + s.loopedSlides;
+                s.slideTo(newIndex, 0, false, true);
+            }
+        };
+        /*=========================
+          Append/Prepend/Remove Slides
+          ===========================*/
+        s.appendSlide = function (slides) {
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            if (typeof slides === 'object' && slides.length) {
+                for (var i = 0; i < slides.length; i++) {
+                    if (slides[i]) s.wrapper.append(slides[i]);
+                }
+            }
+            else {
+                s.wrapper.append(slides);
+            }
+            if (s.params.loop) {
+                s.createLoop();
+            }
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+        };
+        s.prependSlide = function (slides) {
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            var newActiveIndex = s.activeIndex + 1;
+            if (typeof slides === 'object' && slides.length) {
+                for (var i = 0; i < slides.length; i++) {
+                    if (slides[i]) s.wrapper.prepend(slides[i]);
+                }
+                newActiveIndex = s.activeIndex + slides.length;
+            }
+            else {
+                s.wrapper.prepend(slides);
+            }
+            if (s.params.loop) {
+                s.createLoop();
+            }
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+            s.slideTo(newActiveIndex, 0, false);
+        };
+        s.removeSlide = function (slidesIndexes) {
+            if (s.params.loop) {
+                s.destroyLoop();
+                s.slides = s.wrapper.children('.' + s.params.slideClass);
+            }
+            var newActiveIndex = s.activeIndex,
+                indexToRemove;
+            if (typeof slidesIndexes === 'object' && slidesIndexes.length) {
+                for (var i = 0; i < slidesIndexes.length; i++) {
+                    indexToRemove = slidesIndexes[i];
+                    if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
+                    if (indexToRemove < newActiveIndex) newActiveIndex--;
+                }
+                newActiveIndex = Math.max(newActiveIndex, 0);
+            }
+            else {
+                indexToRemove = slidesIndexes;
+                if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
+                if (indexToRemove < newActiveIndex) newActiveIndex--;
+                newActiveIndex = Math.max(newActiveIndex, 0);
+            }
+        
+            if (s.params.loop) {
+                s.createLoop();
+            }
+        
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+            if (s.params.loop) {
+                s.slideTo(newActiveIndex + s.loopedSlides, 0, false);
+            }
+            else {
+                s.slideTo(newActiveIndex, 0, false);
+            }
+        
+        };
+        s.removeAllSlides = function () {
+            var slidesIndexes = [];
+            for (var i = 0; i < s.slides.length; i++) {
+                slidesIndexes.push(i);
+            }
+            s.removeSlide(slidesIndexes);
+        };
+        
+
+        /*=========================
+          Effects
+          ===========================*/
+        s.effects = {
+            fade: {
+                setTranslate: function () {
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var offset = slide[0].swiperSlideOffset;
+                        var tx = -offset;
+                        if (!s.params.virtualTranslate) tx = tx - s.translate;
+                        var ty = 0;
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                        }
+                        var slideOpacity = s.params.fade.crossFade ?
+                                Math.max(1 - Math.abs(slide[0].progress), 0) :
+                                1 + Math.min(Math.max(slide[0].progress, -1), 0);
+                        slide
+                            .css({
+                                opacity: slideOpacity
+                            })
+                            .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)');
+        
+                    }
+        
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration);
+                    if (s.params.virtualTranslate && duration !== 0) {
+                        var eventTriggered = false;
+                        s.slides.transitionEnd(function () {
+                            if (eventTriggered) return;
+                            if (!s) return;
+                            eventTriggered = true;
+                            s.animating = false;
+                            var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
+                            for (var i = 0; i < triggerEvents.length; i++) {
+                                s.wrapper.trigger(triggerEvents[i]);
+                            }
+                        });
+                    }
+                }
+            },
+            flip: {
+                setTranslate: function () {
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var progress = slide[0].progress;
+                        if (s.params.flip.limitRotation) {
+                            progress = Math.max(Math.min(slide[0].progress, 1), -1);
+                        }
+                        var offset = slide[0].swiperSlideOffset;
+                        var rotate = -180 * progress,
+                            rotateY = rotate,
+                            rotateX = 0,
+                            tx = -offset,
+                            ty = 0;
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                            rotateX = -rotateY;
+                            rotateY = 0;
+                        }
+                        else if (s.rtl) {
+                            rotateY = -rotateY;
+                        }
+        
+                        slide[0].style.zIndex = -Math.abs(Math.round(progress)) + s.slides.length;
+        
+                        if (s.params.flip.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
+                        }
+        
+                        slide
+                            .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)');
+                    }
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                    if (s.params.virtualTranslate && duration !== 0) {
+                        var eventTriggered = false;
+                        s.slides.eq(s.activeIndex).transitionEnd(function () {
+                            if (eventTriggered) return;
+                            if (!s) return;
+                            if (!$(this).hasClass(s.params.slideActiveClass)) return;
+                            eventTriggered = true;
+                            s.animating = false;
+                            var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
+                            for (var i = 0; i < triggerEvents.length; i++) {
+                                s.wrapper.trigger(triggerEvents[i]);
+                            }
+                        });
+                    }
+                }
+            },
+            cube: {
+                setTranslate: function () {
+                    var wrapperRotate = 0, cubeShadow;
+                    if (s.params.cube.shadow) {
+                        if (s.isHorizontal()) {
+                            cubeShadow = s.wrapper.find('.swiper-cube-shadow');
+                            if (cubeShadow.length === 0) {
+                                cubeShadow = $('<div class="swiper-cube-shadow"></div>');
+                                s.wrapper.append(cubeShadow);
+                            }
+                            cubeShadow.css({height: s.width + 'px'});
+                        }
+                        else {
+                            cubeShadow = s.container.find('.swiper-cube-shadow');
+                            if (cubeShadow.length === 0) {
+                                cubeShadow = $('<div class="swiper-cube-shadow"></div>');
+                                s.container.append(cubeShadow);
+                            }
+                        }
+                    }
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var slideAngle = i * 90;
+                        var round = Math.floor(slideAngle / 360);
+                        if (s.rtl) {
+                            slideAngle = -slideAngle;
+                            round = Math.floor(-slideAngle / 360);
+                        }
+                        var progress = Math.max(Math.min(slide[0].progress, 1), -1);
+                        var tx = 0, ty = 0, tz = 0;
+                        if (i % 4 === 0) {
+                            tx = - round * 4 * s.size;
+                            tz = 0;
+                        }
+                        else if ((i - 1) % 4 === 0) {
+                            tx = 0;
+                            tz = - round * 4 * s.size;
+                        }
+                        else if ((i - 2) % 4 === 0) {
+                            tx = s.size + round * 4 * s.size;
+                            tz = s.size;
+                        }
+                        else if ((i - 3) % 4 === 0) {
+                            tx = - s.size;
+                            tz = 3 * s.size + s.size * 4 * round;
+                        }
+                        if (s.rtl) {
+                            tx = -tx;
+                        }
+        
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                        }
+        
+                        var transform = 'rotateX(' + (s.isHorizontal() ? 0 : -slideAngle) + 'deg) rotateY(' + (s.isHorizontal() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)';
+                        if (progress <= 1 && progress > -1) {
+                            wrapperRotate = i * 90 + progress * 90;
+                            if (s.rtl) wrapperRotate = -i * 90 - progress * 90;
+                        }
+                        slide.transform(transform);
+                        if (s.params.cube.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
+                        }
+                    }
+                    s.wrapper.css({
+                        '-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        '-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        '-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        'transform-origin': '50% 50% -' + (s.size / 2) + 'px'
+                    });
+        
+                    if (s.params.cube.shadow) {
+                        if (s.isHorizontal()) {
+                            cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')');
+                        }
+                        else {
+                            var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
+                            var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
+                            var scale1 = s.params.cube.shadowScale,
+                                scale2 = s.params.cube.shadowScale / multiplier,
+                                offset = s.params.cube.shadowOffset;
+                            cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)');
+                        }
+                    }
+                    var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0;
+                    s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (s.isHorizontal() ? 0 : wrapperRotate) + 'deg) rotateY(' + (s.isHorizontal() ? -wrapperRotate : 0) + 'deg)');
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                    if (s.params.cube.shadow && !s.isHorizontal()) {
+                        s.container.find('.swiper-cube-shadow').transition(duration);
+                    }
+                }
+            },
+            coverflow: {
+                setTranslate: function () {
+                    var transform = s.translate;
+                    var center = s.isHorizontal() ? -transform + s.width / 2 : -transform + s.height / 2;
+                    var rotate = s.isHorizontal() ? s.params.coverflow.rotate: -s.params.coverflow.rotate;
+                    var translate = s.params.coverflow.depth;
+                    //Each slide offset from center
+                    for (var i = 0, length = s.slides.length; i < length; i++) {
+                        var slide = s.slides.eq(i);
+                        var slideSize = s.slidesSizesGrid[i];
+                        var slideOffset = slide[0].swiperSlideOffset;
+                        var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier;
+        
+                        var rotateY = s.isHorizontal() ? rotate * offsetMultiplier : 0;
+                        var rotateX = s.isHorizontal() ? 0 : rotate * offsetMultiplier;
+                        // var rotateZ = 0
+                        var translateZ = -translate * Math.abs(offsetMultiplier);
+        
+                        var translateY = s.isHorizontal() ? 0 : s.params.coverflow.stretch * (offsetMultiplier);
+                        var translateX = s.isHorizontal() ? s.params.coverflow.stretch * (offsetMultiplier) : 0;
+        
+                        //Fix for ultra small values
+                        if (Math.abs(translateX) < 0.001) translateX = 0;
+                        if (Math.abs(translateY) < 0.001) translateY = 0;
+                        if (Math.abs(translateZ) < 0.001) translateZ = 0;
+                        if (Math.abs(rotateY) < 0.001) rotateY = 0;
+                        if (Math.abs(rotateX) < 0.001) rotateX = 0;
+        
+                        var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px)  rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)';
+        
+                        slide.transform(slideTransform);
+                        slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
+                        if (s.params.coverflow.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0;
+                        }
+                    }
+        
+                    //Set correct perspective for IE10
+                    if (s.browser.ie) {
+                        var ws = s.wrapper[0].style;
+                        ws.perspectiveOrigin = center + 'px 50%';
+                    }
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                }
+            }
+        };
+
+        /*=========================
+          Images Lazy Loading
+          ===========================*/
+        s.lazy = {
+            initialImageLoaded: false,
+            loadImageInSlide: function (index, loadInDuplicate) {
+                if (typeof index === 'undefined') return;
+                if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true;
+                if (s.slides.length === 0) return;
+        
+                var slide = s.slides.eq(index);
+                var img = slide.find('.swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)');
+                if (slide.hasClass('swiper-lazy') && !slide.hasClass('swiper-lazy-loaded') && !slide.hasClass('swiper-lazy-loading')) {
+                    img = img.add(slide[0]);
+                }
+                if (img.length === 0) return;
+        
+                img.each(function () {
+                    var _img = $(this);
+                    _img.addClass('swiper-lazy-loading');
+                    var background = _img.attr('data-background');
+                    var src = _img.attr('data-src'),
+                        srcset = _img.attr('data-srcset');
+                    s.loadImage(_img[0], (src || background), srcset, false, function () {
+                        if (background) {
+                            _img.css('background-image', 'url("' + background + '")');
+                            _img.removeAttr('data-background');
+                        }
+                        else {
+                            if (srcset) {
+                                _img.attr('srcset', srcset);
+                                _img.removeAttr('data-srcset');
+                            }
+                            if (src) {
+                                _img.attr('src', src);
+                                _img.removeAttr('data-src');
+                            }
+        
+                        }
+        
+                        _img.addClass('swiper-lazy-loaded').removeClass('swiper-lazy-loading');
+                        slide.find('.swiper-lazy-preloader, .preloader').remove();
+                        if (s.params.loop && loadInDuplicate) {
+                            var slideOriginalIndex = slide.attr('data-swiper-slide-index');
+                            if (slide.hasClass(s.params.slideDuplicateClass)) {
+                                var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')');
+                                s.lazy.loadImageInSlide(originalSlide.index(), false);
+                            }
+                            else {
+                                var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]');
+                                s.lazy.loadImageInSlide(duplicatedSlide.index(), false);
+                            }
+                        }
+                        s.emit('onLazyImageReady', s, slide[0], _img[0]);
+                    });
+        
+                    s.emit('onLazyImageLoad', s, slide[0], _img[0]);
+                });
+        
+            },
+            load: function () {
+                var i;
+                if (s.params.watchSlidesVisibility) {
+                    s.wrapper.children('.' + s.params.slideVisibleClass).each(function () {
+                        s.lazy.loadImageInSlide($(this).index());
+                    });
+                }
+                else {
+                    if (s.params.slidesPerView > 1) {
+                        for (i = s.activeIndex; i < s.activeIndex + s.params.slidesPerView ; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                    }
+                    else {
+                        s.lazy.loadImageInSlide(s.activeIndex);
+                    }
+                }
+                if (s.params.lazyLoadingInPrevNext) {
+                    if (s.params.slidesPerView > 1 || (s.params.lazyLoadingInPrevNextAmount && s.params.lazyLoadingInPrevNextAmount > 1)) {
+                        var amount = s.params.lazyLoadingInPrevNextAmount;
+                        var spv = s.params.slidesPerView;
+                        var maxIndex = Math.min(s.activeIndex + spv + Math.max(amount, spv), s.slides.length);
+                        var minIndex = Math.max(s.activeIndex - Math.max(spv, amount), 0);
+                        // Next Slides
+                        for (i = s.activeIndex + s.params.slidesPerView; i < maxIndex; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                        // Prev Slides
+                        for (i = minIndex; i < s.activeIndex ; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                    }
+                    else {
+                        var nextSlide = s.wrapper.children('.' + s.params.slideNextClass);
+                        if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index());
+        
+                        var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass);
+                        if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index());
+                    }
+                }
+            },
+            onTransitionStart: function () {
+                if (s.params.lazyLoading) {
+                    if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) {
+                        s.lazy.load();
+                    }
+                }
+            },
+            onTransitionEnd: function () {
+                if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) {
+                    s.lazy.load();
+                }
+            }
+        };
+        
+
+        /*=========================
+          Scrollbar
+          ===========================*/
+        s.scrollbar = {
+            isTouched: false,
+            setDragPosition: function (e) {
+                var sb = s.scrollbar;
+                var x = 0, y = 0;
+                var translate;
+                var pointerPosition = s.isHorizontal() ?
+                    ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) :
+                    ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ;
+                var position = (pointerPosition) - sb.track.offset()[s.isHorizontal() ? 'left' : 'top'] - sb.dragSize / 2;
+                var positionMin = -s.minTranslate() * sb.moveDivider;
+                var positionMax = -s.maxTranslate() * sb.moveDivider;
+                if (position < positionMin) {
+                    position = positionMin;
+                }
+                else if (position > positionMax) {
+                    position = positionMax;
+                }
+                position = -position / sb.moveDivider;
+                s.updateProgress(position);
+                s.setWrapperTranslate(position, true);
+            },
+            dragStart: function (e) {
+                var sb = s.scrollbar;
+                sb.isTouched = true;
+                e.preventDefault();
+                e.stopPropagation();
+        
+                sb.setDragPosition(e);
+                clearTimeout(sb.dragTimeout);
+        
+                sb.track.transition(0);
+                if (s.params.scrollbarHide) {
+                    sb.track.css('opacity', 1);
+                }
+                s.wrapper.transition(100);
+                sb.drag.transition(100);
+                s.emit('onScrollbarDragStart', s);
+            },
+            dragMove: function (e) {
+                var sb = s.scrollbar;
+                if (!sb.isTouched) return;
+                if (e.preventDefault) e.preventDefault();
+                else e.returnValue = false;
+                sb.setDragPosition(e);
+                s.wrapper.transition(0);
+                sb.track.transition(0);
+                sb.drag.transition(0);
+                s.emit('onScrollbarDragMove', s);
+            },
+            dragEnd: function (e) {
+                var sb = s.scrollbar;
+                if (!sb.isTouched) return;
+                sb.isTouched = false;
+                if (s.params.scrollbarHide) {
+                    clearTimeout(sb.dragTimeout);
+                    sb.dragTimeout = setTimeout(function () {
+                        sb.track.css('opacity', 0);
+                        sb.track.transition(400);
+                    }, 1000);
+        
+                }
+                s.emit('onScrollbarDragEnd', s);
+                if (s.params.scrollbarSnapOnRelease) {
+                    s.slideReset();
+                }
+            },
+            enableDraggable: function () {
+                var sb = s.scrollbar;
+                var target = s.support.touch ? sb.track : document;
+                $(sb.track).on(s.touchEvents.start, sb.dragStart);
+                $(target).on(s.touchEvents.move, sb.dragMove);
+                $(target).on(s.touchEvents.end, sb.dragEnd);
+            },
+            disableDraggable: function () {
+                var sb = s.scrollbar;
+                var target = s.support.touch ? sb.track : document;
+                $(sb.track).off(s.touchEvents.start, sb.dragStart);
+                $(target).off(s.touchEvents.move, sb.dragMove);
+                $(target).off(s.touchEvents.end, sb.dragEnd);
+            },
+            set: function () {
+                if (!s.params.scrollbar) return;
+                var sb = s.scrollbar;
+                sb.track = $(s.params.scrollbar);
+                if (s.params.uniqueNavElements && typeof s.params.scrollbar === 'string' && sb.track.length > 1 && s.container.find(s.params.scrollbar).length === 1) {
+                    sb.track = s.container.find(s.params.scrollbar);
+                }
+                sb.drag = sb.track.find('.swiper-scrollbar-drag');
+                if (sb.drag.length === 0) {
+                    sb.drag = $('<div class="swiper-scrollbar-drag"></div>');
+                    sb.track.append(sb.drag);
+                }
+                sb.drag[0].style.width = '';
+                sb.drag[0].style.height = '';
+                sb.trackSize = s.isHorizontal() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight;
+        
+                sb.divider = s.size / s.virtualSize;
+                sb.moveDivider = sb.divider * (sb.trackSize / s.size);
+                sb.dragSize = sb.trackSize * sb.divider;
+        
+                if (s.isHorizontal()) {
+                    sb.drag[0].style.width = sb.dragSize + 'px';
+                }
+                else {
+                    sb.drag[0].style.height = sb.dragSize + 'px';
+                }
+        
+                if (sb.divider >= 1) {
+                    sb.track[0].style.display = 'none';
+                }
+                else {
+                    sb.track[0].style.display = '';
+                }
+                if (s.params.scrollbarHide) {
+                    sb.track[0].style.opacity = 0;
+                }
+            },
+            setTranslate: function () {
+                if (!s.params.scrollbar) return;
+                var diff;
+                var sb = s.scrollbar;
+                var translate = s.translate || 0;
+                var newPos;
+        
+                var newSize = sb.dragSize;
+                newPos = (sb.trackSize - sb.dragSize) * s.progress;
+                if (s.rtl && s.isHorizontal()) {
+                    newPos = -newPos;
+                    if (newPos > 0) {
+                        newSize = sb.dragSize - newPos;
+                        newPos = 0;
+                    }
+                    else if (-newPos + sb.dragSize > sb.trackSize) {
+                        newSize = sb.trackSize + newPos;
+                    }
+                }
+                else {
+                    if (newPos < 0) {
+                        newSize = sb.dragSize + newPos;
+                        newPos = 0;
+                    }
+                    else if (newPos + sb.dragSize > sb.trackSize) {
+                        newSize = sb.trackSize - newPos;
+                    }
+                }
+                if (s.isHorizontal()) {
+                    if (s.support.transforms3d) {
+                        sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)');
+                    }
+                    else {
+                        sb.drag.transform('translateX(' + (newPos) + 'px)');
+                    }
+                    sb.drag[0].style.width = newSize + 'px';
+                }
+                else {
+                    if (s.support.transforms3d) {
+                        sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)');
+                    }
+                    else {
+                        sb.drag.transform('translateY(' + (newPos) + 'px)');
+                    }
+                    sb.drag[0].style.height = newSize + 'px';
+                }
+                if (s.params.scrollbarHide) {
+                    clearTimeout(sb.timeout);
+                    sb.track[0].style.opacity = 1;
+                    sb.timeout = setTimeout(function () {
+                        sb.track[0].style.opacity = 0;
+                        sb.track.transition(400);
+                    }, 1000);
+                }
+            },
+            setTransition: function (duration) {
+                if (!s.params.scrollbar) return;
+                s.scrollbar.drag.transition(duration);
+            }
+        };
+
+        /*=========================
+          Controller
+          ===========================*/
+        s.controller = {
+            LinearSpline: function (x, y) {
+                this.x = x;
+                this.y = y;
+                this.lastIndex = x.length - 1;
+                // Given an x value (x2), return the expected y2 value:
+                // (x1,y1) is the known point before given value,
+                // (x3,y3) is the known point after given value.
+                var i1, i3;
+                var l = this.x.length;
+        
+                this.interpolate = function (x2) {
+                    if (!x2) return 0;
+        
+                    // Get the indexes of x1 and x3 (the array indexes before and after given x2):
+                    i3 = binarySearch(this.x, x2);
+                    i1 = i3 - 1;
+        
+                    // We have our indexes i1 & i3, so we can calculate already:
+                    // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
+                    return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1];
+                };
+        
+                var binarySearch = (function() {
+                    var maxIndex, minIndex, guess;
+                    return function(array, val) {
+                        minIndex = -1;
+                        maxIndex = array.length;
+                        while (maxIndex - minIndex > 1)
+                            if (array[guess = maxIndex + minIndex >> 1] <= val) {
+                                minIndex = guess;
+                            } else {
+                                maxIndex = guess;
+                            }
+                        return maxIndex;
+                    };
+                })();
+            },
+            //xxx: for now i will just save one spline function to to
+            getInterpolateFunction: function(c){
+                if(!s.controller.spline) s.controller.spline = s.params.loop ?
+                    new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) :
+                    new s.controller.LinearSpline(s.snapGrid, c.snapGrid);
+            },
+            setTranslate: function (translate, byController) {
+               var controlled = s.params.control;
+               var multiplier, controlledTranslate;
+               function setControlledTranslate(c) {
+                    // this will create an Interpolate function based on the snapGrids
+                    // x is the Grid of the scrolled scroller and y will be the controlled scroller
+                    // it makes sense to create this only once and recall it for the interpolation
+                    // the function does a lot of value caching for performance
+                    translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate;
+                    if (s.params.controlBy === 'slide') {
+                        s.controller.getInterpolateFunction(c);
+                        // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
+                        // but it did not work out
+                        controlledTranslate = -s.controller.spline.interpolate(-translate);
+                    }
+        
+                    if(!controlledTranslate || s.params.controlBy === 'container'){
+                        multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate());
+                        controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate();
+                    }
+        
+                    if (s.params.controlInverse) {
+                        controlledTranslate = c.maxTranslate() - controlledTranslate;
+                    }
+                    c.updateProgress(controlledTranslate);
+                    c.setWrapperTranslate(controlledTranslate, false, s);
+                    c.updateActiveIndex();
+               }
+               if (s.isArray(controlled)) {
+                   for (var i = 0; i < controlled.length; i++) {
+                       if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
+                           setControlledTranslate(controlled[i]);
+                       }
+                   }
+               }
+               else if (controlled instanceof Swiper && byController !== controlled) {
+        
+                   setControlledTranslate(controlled);
+               }
+            },
+            setTransition: function (duration, byController) {
+                var controlled = s.params.control;
+                var i;
+                function setControlledTransition(c) {
+                    c.setWrapperTransition(duration, s);
+                    if (duration !== 0) {
+                        c.onTransitionStart();
+                        c.wrapper.transitionEnd(function(){
+                            if (!controlled) return;
+                            if (c.params.loop && s.params.controlBy === 'slide') {
+                                c.fixLoop();
+                            }
+                            c.onTransitionEnd();
+        
+                        });
+                    }
+                }
+                if (s.isArray(controlled)) {
+                    for (i = 0; i < controlled.length; i++) {
+                        if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
+                            setControlledTransition(controlled[i]);
+                        }
+                    }
+                }
+                else if (controlled instanceof Swiper && byController !== controlled) {
+                    setControlledTransition(controlled);
+                }
+            }
+        };
+
+        /*=========================
+          Hash Navigation
+          ===========================*/
+        s.hashnav = {
+            init: function () {
+                if (!s.params.hashnav) return;
+                s.hashnav.initialized = true;
+                var hash = document.location.hash.replace('#', '');
+                if (!hash) return;
+                var speed = 0;
+                for (var i = 0, length = s.slides.length; i < length; i++) {
+                    var slide = s.slides.eq(i);
+                    var slideHash = slide.attr('data-hash');
+                    if (slideHash === hash && !slide.hasClass(s.params.slideDuplicateClass)) {
+                        var index = slide.index();
+                        s.slideTo(index, speed, s.params.runCallbacksOnInit, true);
+                    }
+                }
+            },
+            setHash: function () {
+                if (!s.hashnav.initialized || !s.params.hashnav) return;
+                document.location.hash = s.slides.eq(s.activeIndex).attr('data-hash') || '';
+            }
+        };
+
+        /*=========================
+          Keyboard Control
+          ===========================*/
+        function handleKeyboard(e) {
+            if (e.originalEvent) e = e.originalEvent; //jquery fix
+            var kc = e.keyCode || e.charCode;
+            // Directions locks
+            if (!s.params.allowSwipeToNext && (s.isHorizontal() && kc === 39 || !s.isHorizontal() && kc === 40)) {
+                return false;
+            }
+            if (!s.params.allowSwipeToPrev && (s.isHorizontal() && kc === 37 || !s.isHorizontal() && kc === 38)) {
+                return false;
+            }
+            if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
+                return;
+            }
+            if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) {
+                return;
+            }
+            if (kc === 37 || kc === 39 || kc === 38 || kc === 40) {
+                var inView = false;
+                //Check that swiper should be inside of visible area of window
+                if (s.container.parents('.swiper-slide').length > 0 && s.container.parents('.swiper-slide-active').length === 0) {
+                    return;
+                }
+                var windowScroll = {
+                    left: window.pageXOffset,
+                    top: window.pageYOffset
+                };
+                var windowWidth = window.innerWidth;
+                var windowHeight = window.innerHeight;
+                var swiperOffset = s.container.offset();
+                if (s.rtl) swiperOffset.left = swiperOffset.left - s.container[0].scrollLeft;
+                var swiperCoord = [
+                    [swiperOffset.left, swiperOffset.top],
+                    [swiperOffset.left + s.width, swiperOffset.top],
+                    [swiperOffset.left, swiperOffset.top + s.height],
+                    [swiperOffset.left + s.width, swiperOffset.top + s.height]
+                ];
+                for (var i = 0; i < swiperCoord.length; i++) {
+                    var point = swiperCoord[i];
+                    if (
+                        point[0] >= windowScroll.left && point[0] <= windowScroll.left + windowWidth &&
+                        point[1] >= windowScroll.top && point[1] <= windowScroll.top + windowHeight
+                    ) {
+                        inView = true;
+                    }
+        
+                }
+                if (!inView) return;
+            }
+            if (s.isHorizontal()) {
+                if (kc === 37 || kc === 39) {
+                    if (e.preventDefault) e.preventDefault();
+                    else e.returnValue = false;
+                }
+                if ((kc === 39 && !s.rtl) || (kc === 37 && s.rtl)) s.slideNext();
+                if ((kc === 37 && !s.rtl) || (kc === 39 && s.rtl)) s.slidePrev();
+            }
+            else {
+                if (kc === 38 || kc === 40) {
+                    if (e.preventDefault) e.preventDefault();
+                    else e.returnValue = false;
+                }
+                if (kc === 40) s.slideNext();
+                if (kc === 38) s.slidePrev();
+            }
+        }
+        s.disableKeyboardControl = function () {
+            s.params.keyboardControl = false;
+            $(document).off('keydown', handleKeyboard);
+        };
+        s.enableKeyboardControl = function () {
+            s.params.keyboardControl = true;
+            $(document).on('keydown', handleKeyboard);
+        };
+        
+
+        /*=========================
+          Mousewheel Control
+          ===========================*/
+        s.mousewheel = {
+            event: false,
+            lastScrollTime: (new window.Date()).getTime()
+        };
+        if (s.params.mousewheelControl) {
+            try {
+                new window.WheelEvent('wheel');
+                s.mousewheel.event = 'wheel';
+            } catch (e) {
+                if (window.WheelEvent || (s.container[0] && 'wheel' in s.container[0])) {
+                    s.mousewheel.event = 'wheel';
+                }
+            }
+            if (!s.mousewheel.event && window.WheelEvent) {
+        
+            }
+            if (!s.mousewheel.event && document.onmousewheel !== undefined) {
+                s.mousewheel.event = 'mousewheel';
+            }
+            if (!s.mousewheel.event) {
+                s.mousewheel.event = 'DOMMouseScroll';
+            }
+        }
+        function handleMousewheel(e) {
+            if (e.originalEvent) e = e.originalEvent; //jquery fix
+            var we = s.mousewheel.event;
+            var delta = 0;
+            var rtlFactor = s.rtl ? -1 : 1;
+        
+            //WebKits
+            if (we === 'mousewheel') {
+                if (s.params.mousewheelForceToAxis) {
+                    if (s.isHorizontal()) {
+                        if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX * rtlFactor;
+                        else return;
+                    }
+                    else {
+                        if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY;
+                        else return;
+                    }
+                }
+                else {
+                    delta = Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY) ? - e.wheelDeltaX * rtlFactor : - e.wheelDeltaY;
+                }
+            }
+            //Old FireFox
+            else if (we === 'DOMMouseScroll') delta = -e.detail;
+            //New FireFox
+            else if (we === 'wheel') {
+                if (s.params.mousewheelForceToAxis) {
+                    if (s.isHorizontal()) {
+                        if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX * rtlFactor;
+                        else return;
+                    }
+                    else {
+                        if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY;
+                        else return;
+                    }
+                }
+                else {
+                    delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX * rtlFactor : - e.deltaY;
+                }
+            }
+            if (delta === 0) return;
+        
+            if (s.params.mousewheelInvert) delta = -delta;
+        
+            if (!s.params.freeMode) {
+                if ((new window.Date()).getTime() - s.mousewheel.lastScrollTime > 60) {
+                    if (delta < 0) {
+                        if ((!s.isEnd || s.params.loop) && !s.animating) s.slideNext();
+                        else if (s.params.mousewheelReleaseOnEdges) return true;
+                    }
+                    else {
+                        if ((!s.isBeginning || s.params.loop) && !s.animating) s.slidePrev();
+                        else if (s.params.mousewheelReleaseOnEdges) return true;
+                    }
+                }
+                s.mousewheel.lastScrollTime = (new window.Date()).getTime();
+        
+            }
+            else {
+                //Freemode or scrollContainer:
+                var position = s.getWrapperTranslate() + delta * s.params.mousewheelSensitivity;
+                var wasBeginning = s.isBeginning,
+                    wasEnd = s.isEnd;
+        
+                if (position >= s.minTranslate()) position = s.minTranslate();
+                if (position <= s.maxTranslate()) position = s.maxTranslate();
+        
+                s.setWrapperTransition(0);
+                s.setWrapperTranslate(position);
+                s.updateProgress();
+                s.updateActiveIndex();
+        
+                if (!wasBeginning && s.isBeginning || !wasEnd && s.isEnd) {
+                    s.updateClasses();
+                }
+        
+                if (s.params.freeModeSticky) {
+                    clearTimeout(s.mousewheel.timeout);
+                    s.mousewheel.timeout = setTimeout(function () {
+                        s.slideReset();
+                    }, 300);
+                }
+                else {
+                    if (s.params.lazyLoading && s.lazy) {
+                        s.lazy.load();
+                    }
+                }
+        
+                // Return page scroll on edge positions
+                if (position === 0 || position === s.maxTranslate()) return;
+            }
+            if (s.params.autoplay) s.stopAutoplay();
+        
+            if (e.preventDefault) e.preventDefault();
+            else e.returnValue = false;
+            return false;
+        }
+        s.disableMousewheelControl = function () {
+            if (!s.mousewheel.event) return false;
+            s.container.off(s.mousewheel.event, handleMousewheel);
+            return true;
+        };
+        
+        s.enableMousewheelControl = function () {
+            if (!s.mousewheel.event) return false;
+            s.container.on(s.mousewheel.event, handleMousewheel);
+            return true;
+        };
+        
+
+        /*=========================
+          Parallax
+          ===========================*/
+        function setParallaxTransform(el, progress) {
+            el = $(el);
+            var p, pX, pY;
+            var rtlFactor = s.rtl ? -1 : 1;
+        
+            p = el.attr('data-swiper-parallax') || '0';
+            pX = el.attr('data-swiper-parallax-x');
+            pY = el.attr('data-swiper-parallax-y');
+            if (pX || pY) {
+                pX = pX || '0';
+                pY = pY || '0';
+            }
+            else {
+                if (s.isHorizontal()) {
+                    pX = p;
+                    pY = '0';
+                }
+                else {
+                    pY = p;
+                    pX = '0';
+                }
+            }
+        
+            if ((pX).indexOf('%') >= 0) {
+                pX = parseInt(pX, 10) * progress * rtlFactor + '%';
+            }
+            else {
+                pX = pX * progress * rtlFactor + 'px' ;
+            }
+            if ((pY).indexOf('%') >= 0) {
+                pY = parseInt(pY, 10) * progress + '%';
+            }
+            else {
+                pY = pY * progress + 'px' ;
+            }
+        
+            el.transform('translate3d(' + pX + ', ' + pY + ',0px)');
+        }
+        s.parallax = {
+            setTranslate: function () {
+                s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
+                    setParallaxTransform(this, s.progress);
+        
+                });
+                s.slides.each(function () {
+                    var slide = $(this);
+                    slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () {
+                        var progress = Math.min(Math.max(slide[0].progress, -1), 1);
+                        setParallaxTransform(this, progress);
+                    });
+                });
+            },
+            setTransition: function (duration) {
+                if (typeof duration === 'undefined') duration = s.params.speed;
+                s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
+                    var el = $(this);
+                    var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration;
+                    if (duration === 0) parallaxDuration = 0;
+                    el.transition(parallaxDuration);
+                });
+            }
+        };
+        
+
+        /*=========================
+          Plugins API. Collect all and init all plugins
+          ===========================*/
+        s._plugins = [];
+        for (var plugin in s.plugins) {
+            var p = s.plugins[plugin](s, s.params[plugin]);
+            if (p) s._plugins.push(p);
+        }
+        // Method to call all plugins event/method
+        s.callPlugins = function (eventName) {
+            for (var i = 0; i < s._plugins.length; i++) {
+                if (eventName in s._plugins[i]) {
+                    s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+                }
+            }
+        };
+
+        /*=========================
+          Events/Callbacks/Plugins Emitter
+          ===========================*/
+        function normalizeEventName (eventName) {
+            if (eventName.indexOf('on') !== 0) {
+                if (eventName[0] !== eventName[0].toUpperCase()) {
+                    eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1);
+                }
+                else {
+                    eventName = 'on' + eventName;
+                }
+            }
+            return eventName;
+        }
+        s.emitterEventListeners = {
+        
+        };
+        s.emit = function (eventName) {
+            // Trigger callbacks
+            if (s.params[eventName]) {
+                s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+            }
+            var i;
+            // Trigger events
+            if (s.emitterEventListeners[eventName]) {
+                for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
+                    s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+                }
+            }
+            // Trigger plugins
+            if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+        };
+        s.on = function (eventName, handler) {
+            eventName = normalizeEventName(eventName);
+            if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = [];
+            s.emitterEventListeners[eventName].push(handler);
+            return s;
+        };
+        s.off = function (eventName, handler) {
+            var i;
+            eventName = normalizeEventName(eventName);
+            if (typeof handler === 'undefined') {
+                // Remove all handlers for such event
+                s.emitterEventListeners[eventName] = [];
+                return s;
+            }
+            if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return;
+            for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
+                if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1);
+            }
+            return s;
+        };
+        s.once = function (eventName, handler) {
+            eventName = normalizeEventName(eventName);
+            var _handler = function () {
+                handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+                s.off(eventName, _handler);
+            };
+            s.on(eventName, _handler);
+            return s;
+        };
+
+        // Accessibility tools
+        s.a11y = {
+            makeFocusable: function ($el) {
+                $el.attr('tabIndex', '0');
+                return $el;
+            },
+            addRole: function ($el, role) {
+                $el.attr('role', role);
+                return $el;
+            },
+        
+            addLabel: function ($el, label) {
+                $el.attr('aria-label', label);
+                return $el;
+            },
+        
+            disable: function ($el) {
+                $el.attr('aria-disabled', true);
+                return $el;
+            },
+        
+            enable: function ($el) {
+                $el.attr('aria-disabled', false);
+                return $el;
+            },
+        
+            onEnterKey: function (event) {
+                if (event.keyCode !== 13) return;
+                if ($(event.target).is(s.params.nextButton)) {
+                    s.onClickNext(event);
+                    if (s.isEnd) {
+                        s.a11y.notify(s.params.lastSlideMessage);
+                    }
+                    else {
+                        s.a11y.notify(s.params.nextSlideMessage);
+                    }
+                }
+                else if ($(event.target).is(s.params.prevButton)) {
+                    s.onClickPrev(event);
+                    if (s.isBeginning) {
+                        s.a11y.notify(s.params.firstSlideMessage);
+                    }
+                    else {
+                        s.a11y.notify(s.params.prevSlideMessage);
+                    }
+                }
+                if ($(event.target).is('.' + s.params.bulletClass)) {
+                    $(event.target)[0].click();
+                }
+            },
+        
+            liveRegion: $('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),
+        
+            notify: function (message) {
+                var notification = s.a11y.liveRegion;
+                if (notification.length === 0) return;
+                notification.html('');
+                notification.html(message);
+            },
+            init: function () {
+                // Setup accessibility
+                if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                    s.a11y.makeFocusable(s.nextButton);
+                    s.a11y.addRole(s.nextButton, 'button');
+                    s.a11y.addLabel(s.nextButton, s.params.nextSlideMessage);
+                }
+                if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                    s.a11y.makeFocusable(s.prevButton);
+                    s.a11y.addRole(s.prevButton, 'button');
+                    s.a11y.addLabel(s.prevButton, s.params.prevSlideMessage);
+                }
+        
+                $(s.container).append(s.a11y.liveRegion);
+            },
+            initPagination: function () {
+                if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) {
+                    s.bullets.each(function () {
+                        var bullet = $(this);
+                        s.a11y.makeFocusable(bullet);
+                        s.a11y.addRole(bullet, 'button');
+                        s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1));
+                    });
+                }
+            },
+            destroy: function () {
+                if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove();
+            }
+        };
+        
+
+        /*=========================
+          Init/Destroy
+          ===========================*/
+        s.init = function () {
+            if (s.params.loop) s.createLoop();
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            s.updatePagination();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+                if (s.params.scrollbarDraggable) {
+                    s.scrollbar.enableDraggable();
+                }
+            }
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                if (!s.params.loop) s.updateProgress();
+                s.effects[s.params.effect].setTranslate();
+            }
+            if (s.params.loop) {
+                s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit);
+            }
+            else {
+                s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit);
+                if (s.params.initialSlide === 0) {
+                    if (s.parallax && s.params.parallax) s.parallax.setTranslate();
+                    if (s.lazy && s.params.lazyLoading) {
+                        s.lazy.load();
+                        s.lazy.initialImageLoaded = true;
+                    }
+                }
+            }
+            s.attachEvents();
+            if (s.params.observer && s.support.observer) {
+                s.initObservers();
+            }
+            if (s.params.preloadImages && !s.params.lazyLoading) {
+                s.preloadImages();
+            }
+            if (s.params.autoplay) {
+                s.startAutoplay();
+            }
+            if (s.params.keyboardControl) {
+                if (s.enableKeyboardControl) s.enableKeyboardControl();
+            }
+            if (s.params.mousewheelControl) {
+                if (s.enableMousewheelControl) s.enableMousewheelControl();
+            }
+            if (s.params.hashnav) {
+                if (s.hashnav) s.hashnav.init();
+            }
+            if (s.params.a11y && s.a11y) s.a11y.init();
+            s.emit('onInit', s);
+        };
+        
+        // Cleanup dynamic styles
+        s.cleanupStyles = function () {
+            // Container
+            s.container.removeClass(s.classNames.join(' ')).removeAttr('style');
+        
+            // Wrapper
+            s.wrapper.removeAttr('style');
+        
+            // Slides
+            if (s.slides && s.slides.length) {
+                s.slides
+                    .removeClass([
+                      s.params.slideVisibleClass,
+                      s.params.slideActiveClass,
+                      s.params.slideNextClass,
+                      s.params.slidePrevClass
+                    ].join(' '))
+                    .removeAttr('style')
+                    .removeAttr('data-swiper-column')
+                    .removeAttr('data-swiper-row');
+            }
+        
+            // Pagination/Bullets
+            if (s.paginationContainer && s.paginationContainer.length) {
+                s.paginationContainer.removeClass(s.params.paginationHiddenClass);
+            }
+            if (s.bullets && s.bullets.length) {
+                s.bullets.removeClass(s.params.bulletActiveClass);
+            }
+        
+            // Buttons
+            if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
+            if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
+        
+            // Scrollbar
+            if (s.params.scrollbar && s.scrollbar) {
+                if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style');
+                if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style');
+            }
+        };
+        
+        // Destroy
+        s.destroy = function (deleteInstance, cleanupStyles) {
+            // Detach evebts
+            s.detachEvents();
+            // Stop autoplay
+            s.stopAutoplay();
+            // Disable draggable
+            if (s.params.scrollbar && s.scrollbar) {
+                if (s.params.scrollbarDraggable) {
+                    s.scrollbar.disableDraggable();
+                }
+            }
+            // Destroy loop
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            // Cleanup styles
+            if (cleanupStyles) {
+                s.cleanupStyles();
+            }
+            // Disconnect observer
+            s.disconnectObservers();
+            // Disable keyboard/mousewheel
+            if (s.params.keyboardControl) {
+                if (s.disableKeyboardControl) s.disableKeyboardControl();
+            }
+            if (s.params.mousewheelControl) {
+                if (s.disableMousewheelControl) s.disableMousewheelControl();
+            }
+            // Disable a11y
+            if (s.params.a11y && s.a11y) s.a11y.destroy();
+            // Destroy callback
+            s.emit('onDestroy');
+            // Delete instance
+            if (deleteInstance !== false) s = null;
+        };
+        
+        s.init();
+        
+
+    
+        // Return swiper instance
+        return s;
+    };
+    
+
+    /*==================================================
+        Prototype
+    ====================================================*/
+    Swiper.prototype = {
+        isSafari: (function () {
+            var ua = navigator.userAgent.toLowerCase();
+            return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
+        })(),
+        isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),
+        isArray: function (arr) {
+            return Object.prototype.toString.apply(arr) === '[object Array]';
+        },
+        /*==================================================
+        Browser
+        ====================================================*/
+        browser: {
+            ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
+            ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1)
+        },
+        /*==================================================
+        Devices
+        ====================================================*/
+        device: (function () {
+            var ua = navigator.userAgent;
+            var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
+            var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
+            var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
+            var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
+            return {
+                ios: ipad || iphone || ipod,
+                android: android
+            };
+        })(),
+        /*==================================================
+        Feature Detection
+        ====================================================*/
+        support: {
+            touch : (window.Modernizr && Modernizr.touch === true) || (function () {
+                return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
+            })(),
+    
+            transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () {
+                var div = document.createElement('div').style;
+                return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div);
+            })(),
+    
+            flexbox: (function () {
+                var div = document.createElement('div').style;
+                var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' ');
+                for (var i = 0; i < styles.length; i++) {
+                    if (styles[i] in div) return true;
+                }
+            })(),
+    
+            observer: (function () {
+                return ('MutationObserver' in window || 'WebkitMutationObserver' in window);
+            })()
+        },
+        /*==================================================
+        Plugins
+        ====================================================*/
+        plugins: {}
+    };
+    
+
+    /*===========================
+     Get Dom libraries
+     ===========================*/
+    var swiperDomPlugins = ['jQuery', 'Zepto', 'Dom7'];
+    for (var i = 0; i < swiperDomPlugins.length; i++) {
+    	if (window[swiperDomPlugins[i]]) {
+    		addLibraryPlugin(window[swiperDomPlugins[i]]);
+    	}
+    }
+    // Required DOM Plugins
+    var domLib;
+    if (typeof Dom7 === 'undefined') {
+    	domLib = window.Dom7 || window.Zepto || window.jQuery;
+    }
+    else {
+    	domLib = Dom7;
+    }
+
+    /*===========================
+    Add .swiper plugin from Dom libraries
+    ===========================*/
+    function addLibraryPlugin(lib) {
+        lib.fn.swiper = function (params) {
+            var firstInstance;
+            lib(this).each(function () {
+                var s = new Swiper(this, params);
+                if (!firstInstance) firstInstance = s;
+            });
+            return firstInstance;
+        };
+    }
+    
+    if (domLib) {
+        if (!('transitionEnd' in domLib.fn)) {
+            domLib.fn.transitionEnd = function (callback) {
+                var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
+                    i, j, dom = this;
+                function fireCallBack(e) {
+                    /*jshint validthis:true */
+                    if (e.target !== this) return;
+                    callback.call(this, e);
+                    for (i = 0; i < events.length; i++) {
+                        dom.off(events[i], fireCallBack);
+                    }
+                }
+                if (callback) {
+                    for (i = 0; i < events.length; i++) {
+                        dom.on(events[i], fireCallBack);
+                    }
+                }
+                return this;
+            };
+        }
+        if (!('transform' in domLib.fn)) {
+            domLib.fn.transform = function (transform) {
+                for (var i = 0; i < this.length; i++) {
+                    var elStyle = this[i].style;
+                    elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
+                }
+                return this;
+            };
+        }
+        if (!('transition' in domLib.fn)) {
+            domLib.fn.transition = function (duration) {
+                if (typeof duration !== 'string') {
+                    duration = duration + 'ms';
+                }
+                for (var i = 0; i < this.length; i++) {
+                    var elStyle = this[i].style;
+                    elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
+                }
+                return this;
+            };
+        }
+    }
+
+    window.Swiper = Swiper;
+})();
+/*===========================
+Swiper AMD Export
+===========================*/
+if (typeof(module) !== 'undefined')
+{
+    module.exports = window.Swiper;
+}
+else if (typeof define === 'function' && define.amd) {
+    define([], function () {
+        'use strict';
+        return window.Swiper;
+    });
+}
+//# sourceMappingURL=maps/swiper.jquery.js.map
+
+/* ===============================================================================
+************ Swiper ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var defaults;
+
+  $.fn.swiper = function(params) {
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      var swiper = $this.data("swiper");
+      if(!swiper) $this.data("swiper", new Swiper(this, $.extend({}, defaults, params))); 
+      return swiper;
+    });
+  }
+
+  defaults = $.fn.swiper.prototype.defaults = {
+    pagination: ".swiper-pagination"
+  };
+
+}($);
+
+/* global $:true */
++ function($) {
+
+  var defaults;
+
+  var Photos = function(config) {
+    this.initConfig(config);
+    this.index = 0;
+  }
+
+  Photos.prototype = {
+    initConfig: function (config) {
+      this.config = $.extend({}, defaults, config);
+      this.activeIndex = this.lastActiveIndex = this.config.initIndex;
+
+      this.config.items = this.config.items.map(function(d, i) {
+        if(typeof d === typeof 'a') {
+          return {
+            image: d,
+            caption: ''
+          }
+        }
+        return d;
+      });
+
+      this.tpl = $.t7.compile(this.config.tpl);
+      if(this.config.autoOpen) this.open();
+    },
+
+    open: function (index) {
+      if (this._open) return false;
+      if (!this.modal) {
+        this.modal = $(this.tpl(this.config)).appendTo(document.body);
+        this.container = this.modal.find('.swiper-container');
+        this.wrapper = this.modal.find('.swiper-wrapper');
+
+        var hammer = new Hammer(this.container[0]);
+        hammer.get('pinch').set({ enable: true });
+        hammer.on('pinchstart', $.proxy(this.onGestureStart, this));
+        hammer.on('pinchmove', $.proxy(this.onGestureChange, this));
+        hammer.on('pinchend', $.proxy(this.onGestureEnd, this));
+        this.modal.on($.touchEvents.start, $.proxy(this.onTouchStart, this));
+        this.modal.on($.touchEvents.move, $.proxy(this.onTouchMove, this));
+        this.modal.on($.touchEvents.end, $.proxy(this.onTouchEnd, this));
+
+        //init index
+        this.wrapper.transition(0);
+        this.wrapper.transform('translate3d(-' + $(window).width()*this.config.initIndex + 'px,0,0)');
+        this.container.find('.caption-item').eq(this.config.initIndex).addClass('active');
+        this.container.find('.swiper-pagination-bullet').eq(this.config.initIndex).addClass('swiper-pagination-bullet-active');
+      }
+
+      var self = this;
+      this.modal.show().height();
+      this.modal.addClass('weui-photo-browser-modal-visible');
+      this.container.addClass('swiper-container-visible').transitionEnd(function() {
+        self.initParams();
+        if(index !== undefined) {
+          self.slideTo(index);
+        }
+        if(self.config.onOpen) {
+          self.config.onOpen.call(self);
+        }
+      });
+
+      this._open = true;
+    },
+
+    close: function() {
+      this.container.transitionEnd($.proxy(function() {
+        this.modal.hide();
+        this._open = false;
+        if(this.config.onClose) this.config.onClose.call(this);
+      }, this));
+      this.container.removeClass('swiper-container-visible');
+      this.modal.removeClass('weui-photo-browser-modal-visible');
+    },
+
+    initParams: function () {
+      if(this.containerHeight) return false;
+
+      this.windowWidth = $(window).width();
+      this.containerHeight = this.container.height();
+      this.containerWidth = this.container.width();
+
+      this.touchStart = {};
+
+      this.wrapperTransform = 0;
+      this.wrapperLastTransform = - $(window).width()*this.config.initIndex;
+      this.wrapperDiff = 0;
+
+      this.lastScale = 1;
+      this.currentScale = 1;
+
+      this.imageLastTransform = { x: 0, y: 0 };
+      this.imageTransform = { x: 0, y: 0 };
+      this.imageDiff = { x: 0, y: 0 };
+      this.imageLastDiff = { x: 0, y: 0 };
+    },
+
+    onTouchStart: function (e) {
+      if(this.scaling) return false;
+      this.touching = true;
+      this.touchStart = $.getTouchPosition(e);
+      this.touchMove = null;
+      this.touchStartTime = + new Date;
+      this.wrapperDiff = 0;
+      this.breakpointPosition = null;
+    },
+
+    onTouchMove: function (e) {
+      if(!this.touching || this.scaling) return false;
+
+      e.preventDefault();
+
+      if(this.gestureImage) {
+        var rect = this.gestureImage[0].getBoundingClientRect();
+        if (rect.left >= 0 || rect.right <= this.windowWidth) {
+          this.overflow = true;
+        } else {
+          this.overflow = false;
+        }
+      } else {
+        this.oveflow = false;
+      }
+      var p = this.touchMove = $.getTouchPosition(e);
+      if(this.currentScale === 1 || this.overflow) {
+        if(this.breakpointPosition) {
+          this.wrapperDiff = p.x - this.breakpointPosition.x;
+        } else {
+          this.wrapperDiff = p.x - this.touchStart.x;
+        }
+        if(this.activeIndex === 0 && this.wrapperDiff > 0) this.wrapperDiff = Math.pow(this.wrapperDiff, .8);
+        if(this.activeIndex === this.config.items.length - 1 && this.wrapperDiff < 0) this.wrapperDiff = - Math.pow(-this.wrapperDiff, .8);
+        this.wrapperTransform = this.wrapperLastTransform + this.wrapperDiff;
+        this.doWrapperTransform();
+      } else {
+        var img = this.gestureImage;
+        this.imageDiff = {
+          x: p.x - this.touchStart.x,
+          y: p.y - this.touchStart.y
+        }
+
+        this.imageTransform = {
+          x: this.imageDiff.x + this.imageLastTransform.x,
+          y: this.imageDiff.y + this.imageLastTransform.y
+        };
+        this.doImageTransform();
+
+        this.breakpointPosition = p;
+
+        this.imageLastDiff = this.imageDiff;
+      }
+    },
+
+    onTouchEnd: function (e) {
+      if(!this.touching) return false;
+      this.touching = false;
+      if(this.scaling) return false;
+      var duration = (+ new Date) - this.touchStartTime;
+
+      if(duration < 200 && (!this.touchMove || Math.abs(this.touchStart.x - this.touchMove.x) <= 2 && Math.abs(this.touchStart.y - this.touchMove.y) <= 2)) {
+        this.onClick();
+        return;
+      }
+      if(this.wrapperDiff > 0) {
+        if(this.wrapperDiff > this.containerWidth/2 || (this.wrapperDiff > 20 && duration < 300)) {
+          this.slidePrev();
+        } else {
+          this.slideTo(this.activeIndex, 200);
+        }
+      } else {
+        if(- this.wrapperDiff > this.containerWidth/2 || (-this.wrapperDiff > 20 && duration < 300)) {
+          this.slideNext();
+        } else {
+          this.slideTo(this.activeIndex, 200);
+        }
+      }
+
+      this.imageLastTransform = this.imageTransform;
+
+      this.adjust();
+    },
+
+    onClick: function () {
+      var self = this;
+      if (this._lastClickTime && ( + new Date - this._lastClickTime < 300)) {
+        this.onDoubleClick();
+        clearTimeout(this._clickTimeout);
+      } else {
+        this._clickTimeout = setTimeout(function () {
+          self.close();
+        }, 300);
+      }
+      this._lastClickTime = + new Date;
+    },
+
+    onDoubleClick: function () {
+      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
+      this.currentScale = this.currentScale > 1 ? 1 : 2;
+      this.doImageTransform(200); 
+      this.adjust();
+    },
+
+    onGestureStart: function (e) {
+      this.scaling = true;
+      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
+    },
+
+    onGestureChange: function (e) {
+      var s = this.lastScale * e.scale;
+      if (s > this.config.maxScale) {
+        s = this.config.maxScale + Math.pow((s - this.config.maxScale), 0.5);
+      } else if (s < 1) {
+        s = Math.pow(s, .5);
+      }
+      this.currentScale = s;
+      this.doImageTransform();
+    },
+
+    onGestureEnd: function (e) {
+      if (this.currentScale > this.config.maxScale) {
+        this.currentScale = this.config.maxScale;
+        this.doImageTransform(200);
+      } else if (this.currentScale < 1) {
+        this.currentScale = 1;
+        this.doImageTransform(200);
+      }
+      this.lastScale = this.currentScale;
+      this.scaling = false;
+      this.adjust();
+    },
+
+    doWrapperTransform: function(duration, callback) {
+      if (duration === 0) {
+        var origin = this.wrapper.css('transition-property')
+        this.wrapper.css('transition-property', 'none').transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
+        this.wrapper.css('transition-property', origin);
+        callback()
+      } else {
+        this.wrapper.transitionEnd(function() {
+          callback && callback();
+        });
+        this.wrapper.transition(duration || defaults.duration).transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
+      }
+    },
+
+    doImageTransform: function(duration, callback) {
+      if(!this.gestureImage) return;
+      this.gestureImage.transition(duration || 0).transform('translate3d(' + this.imageTransform.x + 'px,' + this.imageTransform.y + 'px, 0) scale(' + this.currentScale + ')');
+      this._needAdjust = true;
+    },
+
+    adjust: function() {
+      if(!this._needAdjust) return false;
+      var img = this.gestureImage;
+      if(!img) return false;
+      if(this.currentScale === 1) {
+        this.imageTransform = this.imageLastDiff =  {x:0,y:0};
+        this.doImageTransform(200);
+        return;
+      }
+
+      var rect = img[0].getBoundingClientRect();
+
+      //调整上下
+      if(rect.height < this.containerHeight) {  // 如果高度没容器高,则自动居中
+        this.imageTransform.y = this.imageLastTransform.y = 0;
+      } else {  //如果比容器高,那么要保证上下不能有空隙
+        if(rect.top > 0) this.imageTransform.y = this.imageTransform.y - rect.top;
+        else if(rect.bottom < this.containerHeight) this.imageTransform.y = this.imageTransform.y + this.containerHeight - rect.bottom;
+      }
+
+      this.doImageTransform(200);
+      this._needAdjust = false; // must at last line, because doImageTransform will set this._needAdjust true
+    },
+
+    slideTo: function(index, duration) {
+      if(index < 0) index = 0;
+      if(index > this.config.items.length-1) index = this.config.items.length - 1;
+      this.lastActiveIndex = this.activeIndex;
+      this.activeIndex = index;
+      this.wrapperTransform = - (index * this.containerWidth);
+      this.wrapperLastTransform = this.wrapperTransform;
+      this.doWrapperTransform(duration, $.proxy(function() {
+        if(this.lastActiveIndex === this.activeIndex) return false; // active index not change
+        this.container.find('.caption-item.active').removeClass('active');
+        this.container.find('.swiper-slide-active').removeClass('swiper-slide-active');
+        this.container.find('.swiper-pagination-bullet-active').removeClass('swiper-pagination-bullet-active');
+        this.container.find('.caption-item').eq(this.activeIndex).addClass('active');
+        this.container.find('.swiper-slide').eq(this.activeIndex).addClass('swiper-slide-active');
+        this.container.find('.swiper-pagination-bullet').eq(this.activeIndex).addClass('swiper-pagination-bullet-active');
+
+        //reset image transform
+        this.container.find('.swiper-slide img[style]').transition(0).transform('translate3d(0,0,0) scale(1)');
+
+        this.lastScale = 1;
+        this.currentScale = 1;
+
+        this.imageLastTransform = { x: 0, y: 0 };
+        this.imageTransform = { x: 0, y: 0 };
+        this.imageDiff = { x: 0, y: 0 };
+        this.imageLastDiff = { x: 0, y: 0 };
+
+        if(this.config.onSlideChange) {
+          this.config.onSlideChange.call(this, this.activeIndex);
+        }
+
+      }, this));
+    },
+    slideNext: function() {
+      return this.slideTo(this.activeIndex+1, 200);
+    },
+    slidePrev: function() {
+      return this.slideTo(this.activeIndex-1, 200);
+    }
+  }
+
+  defaults = Photos.prototype.defaults = {
+    items: [],
+    autoOpen: false, //初始化完成之后立刻打开
+    onOpen: undefined,
+    onClose: undefined,
+    initIndex: 0, //打开时默认显示第几张
+    maxScale: 3,
+    onSlideChange: undefined,
+    duration: 200, // 默认动画时间,如果没有在调用函数的时候指定,则使用这个值
+    tpl: '<div class="weui-photo-browser-modal">\
+            <div class="swiper-container">\
+              <div class="swiper-wrapper">\
+                {{#items}}\
+                <div class="swiper-slide">\
+                  <div class="photo-container">\
+                    <img src="{{image}}" />\
+                  </div>\
+                </div>\
+                {{/items}}\
+              </div>\
+              <div class="caption">\
+                {{#items}}\
+                <div class="caption-item caption-item-{{@index}}">{{caption}}</div>\
+                {{/items}}\
+              </div>\
+              <div class="swiper-pagination swiper-pagination-bullets">\
+                {{#items}}\
+                <span class="swiper-pagination-bullet"></span>\
+                {{/items}}\
+              </div>\
+            </div>\
+          </div>'
+  }
+
+  $.photoBrowser = function(params) {
+    return new Photos(params);
+  }
+}($);
diff --git a/platforms/android/app/src/main/assets/www/js/lib/swiper.min.js b/platforms/android/app/src/main/assets/www/js/lib/swiper.min.js
new file mode 100755
index 0000000..69f968b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/lib/swiper.min.js
@@ -0,0 +1,17 @@
+/**
+ * Swiper 3.3.1
+ * Most modern mobile touch slider and framework with hardware accelerated transitions
+ * 
+ * http://www.idangero.us/swiper/
+ * 
+ * Copyright 2016, Vladimir Kharlampidi
+ * The iDangero.us
+ * http://www.idangero.us/
+ * 
+ * Licensed under MIT
+ * 
+ * Released on: February 7, 2016
+ */
+!function(){"use strict";function e(e){e.fn.swiper=function(a){var i;return e(this).each(function(){var e=new t(this,a);i||(i=e)}),i}}var a,t=function(e,i){function s(e){return Math.floor(e)}function r(){y.autoplayTimeoutId=setTimeout(function(){y.params.loop?(y.fixLoop(),y._slideNext(),y.emit("onAutoplay",y)):y.isEnd?i.autoplayStopOnLast?y.stopAutoplay():(y._slideTo(0),y.emit("onAutoplay",y)):(y._slideNext(),y.emit("onAutoplay",y))},y.params.autoplay)}function n(e,t){var i=a(e.target);if(!i.is(t))if("string"==typeof t)i=i.parents(t);else if(t.nodeType){var s;return i.parents().each(function(e,a){a===t&&(s=t)}),s?t:void 0}if(0!==i.length)return i[0]}function o(e,a){a=a||{};var t=window.MutationObserver||window.WebkitMutationObserver,i=new t(function(e){e.forEach(function(e){y.onResize(!0),y.emit("onObserverUpdate",y,e)})});i.observe(e,{attributes:"undefined"==typeof a.attributes||a.attributes,childList:"undefined"==typeof a.childList||a.childList,characterData:"undefined"==typeof a.characterData||a.characterData}),y.observers.push(i)}function l(e){e.originalEvent&&(e=e.originalEvent);var a=e.keyCode||e.charCode;if(!y.params.allowSwipeToNext&&(y.isHorizontal()&&39===a||!y.isHorizontal()&&40===a))return!1;if(!y.params.allowSwipeToPrev&&(y.isHorizontal()&&37===a||!y.isHorizontal()&&38===a))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===a||39===a||38===a||40===a){var t=!1;if(y.container.parents(".swiper-slide").length>0&&0===y.container.parents(".swiper-slide-active").length)return;var i={left:window.pageXOffset,top:window.pageYOffset},s=window.innerWidth,r=window.innerHeight,n=y.container.offset();y.rtl&&(n.left=n.left-y.container[0].scrollLeft);for(var o=[[n.left,n.top],[n.left+y.width,n.top],[n.left,n.top+y.height],[n.left+y.width,n.top+y.height]],l=0;l<o.length;l++){var p=o[l];p[0]>=i.left&&p[0]<=i.left+s&&p[1]>=i.top&&p[1]<=i.top+r&&(t=!0)}if(!t)return}y.isHorizontal()?(37!==a&&39!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===a&&!y.rtl||37===a&&y.rtl)&&y.slideNext(),(37===a&&!y.rtl||39===a&&y.rtl)&&y.slidePrev()):(38!==a&&40!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),40===a&&y.slideNext(),38===a&&y.slidePrev())}}function p(e){e.originalEvent&&(e=e.originalEvent);var a=y.mousewheel.event,t=0,i=y.rtl?-1:1;if("mousewheel"===a)if(y.params.mousewheelForceToAxis)if(y.isHorizontal()){if(!(Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)))return;t=e.wheelDeltaX*i}else{if(!(Math.abs(e.wheelDeltaY)>Math.abs(e.wheelDeltaX)))return;t=e.wheelDeltaY}else t=Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)?-e.wheelDeltaX*i:-e.wheelDeltaY;else if("DOMMouseScroll"===a)t=-e.detail;else if("wheel"===a)if(y.params.mousewheelForceToAxis)if(y.isHorizontal()){if(!(Math.abs(e.deltaX)>Math.abs(e.deltaY)))return;t=-e.deltaX*i}else{if(!(Math.abs(e.deltaY)>Math.abs(e.deltaX)))return;t=-e.deltaY}else t=Math.abs(e.deltaX)>Math.abs(e.deltaY)?-e.deltaX*i:-e.deltaY;if(0!==t){if(y.params.mousewheelInvert&&(t=-t),y.params.freeMode){var s=y.getWrapperTranslate()+t*y.params.mousewheelSensitivity,r=y.isBeginning,n=y.isEnd;if(s>=y.minTranslate()&&(s=y.minTranslate()),s<=y.maxTranslate()&&(s=y.maxTranslate()),y.setWrapperTransition(0),y.setWrapperTranslate(s),y.updateProgress(),y.updateActiveIndex(),(!r&&y.isBeginning||!n&&y.isEnd)&&y.updateClasses(),y.params.freeModeSticky?(clearTimeout(y.mousewheel.timeout),y.mousewheel.timeout=setTimeout(function(){y.slideReset()},300)):y.params.lazyLoading&&y.lazy&&y.lazy.load(),0===s||s===y.maxTranslate())return}else{if((new window.Date).getTime()-y.mousewheel.lastScrollTime>60)if(t<0)if(y.isEnd&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slideNext();else if(y.isBeginning&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slidePrev();y.mousewheel.lastScrollTime=(new window.Date).getTime()}return y.params.autoplay&&y.stopAutoplay(),e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function d(e,t){e=a(e);var i,s,r,n=y.rtl?-1:1;i=e.attr("data-swiper-parallax")||"0",s=e.attr("data-swiper-parallax-x"),r=e.attr("data-swiper-parallax-y"),s||r?(s=s||"0",r=r||"0"):y.isHorizontal()?(s=i,r="0"):(r=i,s="0"),s=s.indexOf("%")>=0?parseInt(s,10)*t*n+"%":s*t*n+"px",r=r.indexOf("%")>=0?parseInt(r,10)*t+"%":r*t+"px",e.transform("translate3d("+s+", "+r+",0px)")}function c(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof t))return new t(e,i);var u={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,autoplayStopOnLast:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flip:{slideShadows:!0,limitRotation:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,hashnav:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,uniqueNavElements:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,paginationProgressRender:null,paginationFractionRender:null,paginationCustomRender:null,paginationType:"bullets",resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingInPrevNextAmount:1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slidePrevClass:"swiper-slide-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationCurrentClass:"swiper-pagination-current",paginationTotalClass:"swiper-pagination-total",paginationHiddenClass:"swiper-pagination-hidden",paginationProgressbarClass:"swiper-pagination-progressbar",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},m=i&&i.virtualTranslate;i=i||{};var h={};for(var f in i)if("object"!=typeof i[f]||null===i[f]||(i[f].nodeType||i[f]===window||i[f]===document||"undefined"!=typeof Dom7&&i[f]instanceof Dom7||"undefined"!=typeof jQuery&&i[f]instanceof jQuery))h[f]=i[f];else{h[f]={};for(var g in i[f])h[f][g]=i[f][g]}for(var v in u)if("undefined"==typeof i[v])i[v]=u[v];else if("object"==typeof i[v])for(var w in u[v])"undefined"==typeof i[v][w]&&(i[v][w]=u[v][w]);var y=this;if(y.params=i,y.originalParams=h,y.classNames=[],"undefined"!=typeof a&&"undefined"!=typeof Dom7&&(a=Dom7),("undefined"!=typeof a||(a="undefined"==typeof Dom7?window.Dom7||window.Zepto||window.jQuery:Dom7))&&(y.$=a,y.currentBreakpoint=void 0,y.getActiveBreakpoint=function(){if(!y.params.breakpoints)return!1;var e,a=!1,t=[];for(e in y.params.breakpoints)y.params.breakpoints.hasOwnProperty(e)&&t.push(e);t.sort(function(e,a){return parseInt(e,10)>parseInt(a,10)});for(var i=0;i<t.length;i++)e=t[i],e>=window.innerWidth&&!a&&(a=e);return a||"max"},y.setBreakpoint=function(){var e=y.getActiveBreakpoint();if(e&&y.currentBreakpoint!==e){var a=e in y.params.breakpoints?y.params.breakpoints[e]:y.originalParams,t=y.params.loop&&a.slidesPerView!==y.params.slidesPerView;for(var i in a)y.params[i]=a[i];y.currentBreakpoint=e,t&&y.destroyLoop&&y.reLoop(!0)}},y.params.breakpoints&&y.setBreakpoint(),y.container=a(e),0!==y.container.length)){if(y.container.length>1){var x=[];return y.container.each(function(){x.push(new t(this,i))}),x}y.container[0].swiper=y,y.container.data("swiper",y),y.classNames.push("swiper-container-"+y.params.direction),y.params.freeMode&&y.classNames.push("swiper-container-free-mode"),y.support.flexbox||(y.classNames.push("swiper-container-no-flexbox"),y.params.slidesPerColumn=1),y.params.autoHeight&&y.classNames.push("swiper-container-autoheight"),(y.params.parallax||y.params.watchSlidesVisibility)&&(y.params.watchSlidesProgress=!0),["cube","coverflow","flip"].indexOf(y.params.effect)>=0&&(y.support.transforms3d?(y.params.watchSlidesProgress=!0,y.classNames.push("swiper-container-3d")):y.params.effect="slide"),"slide"!==y.params.effect&&y.classNames.push("swiper-container-"+y.params.effect),"cube"===y.params.effect&&(y.params.resistanceRatio=0,y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.centeredSlides=!1,y.params.spaceBetween=0,y.params.virtualTranslate=!0,y.params.setWrapperSize=!1),"fade"!==y.params.effect&&"flip"!==y.params.effect||(y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.watchSlidesProgress=!0,y.params.spaceBetween=0,y.params.setWrapperSize=!1,"undefined"==typeof m&&(y.params.virtualTranslate=!0)),y.params.grabCursor&&y.support.touch&&(y.params.grabCursor=!1),y.wrapper=y.container.children("."+y.params.wrapperClass),y.params.pagination&&(y.paginationContainer=a(y.params.pagination),y.params.uniqueNavElements&&"string"==typeof y.params.pagination&&y.paginationContainer.length>1&&1===y.container.find(y.params.pagination).length&&(y.paginationContainer=y.container.find(y.params.pagination)),"bullets"===y.params.paginationType&&y.params.paginationClickable?y.paginationContainer.addClass("swiper-pagination-clickable"):y.params.paginationClickable=!1,y.paginationContainer.addClass("swiper-pagination-"+y.params.paginationType)),(y.params.nextButton||y.params.prevButton)&&(y.params.nextButton&&(y.nextButton=a(y.params.nextButton),y.params.uniqueNavElements&&"string"==typeof y.params.nextButton&&y.nextButton.length>1&&1===y.container.find(y.params.nextButton).length&&(y.nextButton=y.container.find(y.params.nextButton))),y.params.prevButton&&(y.prevButton=a(y.params.prevButton),y.params.uniqueNavElements&&"string"==typeof y.params.prevButton&&y.prevButton.length>1&&1===y.container.find(y.params.prevButton).length&&(y.prevButton=y.container.find(y.params.prevButton)))),y.isHorizontal=function(){return"horizontal"===y.params.direction},y.rtl=y.isHorizontal()&&("rtl"===y.container[0].dir.toLowerCase()||"rtl"===y.container.css("direction")),y.rtl&&y.classNames.push("swiper-container-rtl"),y.rtl&&(y.wrongRTL="-webkit-box"===y.wrapper.css("display")),y.params.slidesPerColumn>1&&y.classNames.push("swiper-container-multirow"),y.device.android&&y.classNames.push("swiper-container-android"),y.container.addClass(y.classNames.join(" ")),y.translate=0,y.progress=0,y.velocity=0,y.lockSwipeToNext=function(){y.params.allowSwipeToNext=!1},y.lockSwipeToPrev=function(){y.params.allowSwipeToPrev=!1},y.lockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!1},y.unlockSwipeToNext=function(){y.params.allowSwipeToNext=!0},y.unlockSwipeToPrev=function(){y.params.allowSwipeToPrev=!0},y.unlockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!0},y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab"),y.imagesToLoad=[],y.imagesLoaded=0,y.loadImage=function(e,a,t,i,s){function r(){s&&s()}var n;e.complete&&i?r():a?(n=new window.Image,n.onload=r,n.onerror=r,t&&(n.srcset=t),a&&(n.src=a)):r()},y.preloadImages=function(){function e(){"undefined"!=typeof y&&null!==y&&(void 0!==y.imagesLoaded&&y.imagesLoaded++,y.imagesLoaded===y.imagesToLoad.length&&(y.params.updateOnImagesReady&&y.update(),y.emit("onImagesReady",y)))}y.imagesToLoad=y.container.find("img");for(var a=0;a<y.imagesToLoad.length;a++)y.loadImage(y.imagesToLoad[a],y.imagesToLoad[a].currentSrc||y.imagesToLoad[a].getAttribute("src"),y.imagesToLoad[a].srcset||y.imagesToLoad[a].getAttribute("srcset"),!0,e)},y.autoplayTimeoutId=void 0,y.autoplaying=!1,y.autoplayPaused=!1,y.startAutoplay=function(){return"undefined"==typeof y.autoplayTimeoutId&&(!!y.params.autoplay&&(!y.autoplaying&&(y.autoplaying=!0,y.emit("onAutoplayStart",y),void r())))},y.stopAutoplay=function(e){y.autoplayTimeoutId&&(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplaying=!1,y.autoplayTimeoutId=void 0,y.emit("onAutoplayStop",y))},y.pauseAutoplay=function(e){y.autoplayPaused||(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplayPaused=!0,0===e?(y.autoplayPaused=!1,r()):y.wrapper.transitionEnd(function(){y&&(y.autoplayPaused=!1,y.autoplaying?r():y.stopAutoplay())}))},y.minTranslate=function(){return-y.snapGrid[0]},y.maxTranslate=function(){return-y.snapGrid[y.snapGrid.length-1]},y.updateAutoHeight=function(){var e=y.slides.eq(y.activeIndex)[0];if("undefined"!=typeof e){var a=e.offsetHeight;a&&y.wrapper.css("height",a+"px")}},y.updateContainerSize=function(){var e,a;e="undefined"!=typeof y.params.width?y.params.width:y.container[0].clientWidth,a="undefined"!=typeof y.params.height?y.params.height:y.container[0].clientHeight,0===e&&y.isHorizontal()||0===a&&!y.isHorizontal()||(e=e-parseInt(y.container.css("padding-left"),10)-parseInt(y.container.css("padding-right"),10),a=a-parseInt(y.container.css("padding-top"),10)-parseInt(y.container.css("padding-bottom"),10),y.width=e,y.height=a,y.size=y.isHorizontal()?y.width:y.height)},y.updateSlidesSize=function(){y.slides=y.wrapper.children("."+y.params.slideClass),y.snapGrid=[],y.slidesGrid=[],y.slidesSizesGrid=[];var e,a=y.params.spaceBetween,t=-y.params.slidesOffsetBefore,i=0,r=0;if("undefined"!=typeof y.size){"string"==typeof a&&a.indexOf("%")>=0&&(a=parseFloat(a.replace("%",""))/100*y.size),y.virtualSize=-a,y.rtl?y.slides.css({marginLeft:"",marginTop:""}):y.slides.css({marginRight:"",marginBottom:""});var n;y.params.slidesPerColumn>1&&(n=Math.floor(y.slides.length/y.params.slidesPerColumn)===y.slides.length/y.params.slidesPerColumn?y.slides.length:Math.ceil(y.slides.length/y.params.slidesPerColumn)*y.params.slidesPerColumn,"auto"!==y.params.slidesPerView&&"row"===y.params.slidesPerColumnFill&&(n=Math.max(n,y.params.slidesPerView*y.params.slidesPerColumn)));var o,l=y.params.slidesPerColumn,p=n/l,d=p-(y.params.slidesPerColumn*p-y.slides.length);for(e=0;e<y.slides.length;e++){o=0;var c=y.slides.eq(e);if(y.params.slidesPerColumn>1){var u,m,h;"column"===y.params.slidesPerColumnFill?(m=Math.floor(e/l),h=e-m*l,(m>d||m===d&&h===l-1)&&++h>=l&&(h=0,m++),u=m+h*n/l,c.css({"-webkit-box-ordinal-group":u,"-moz-box-ordinal-group":u,"-ms-flex-order":u,"-webkit-order":u,order:u})):(h=Math.floor(e/p),m=e-h*p),c.css({"margin-top":0!==h&&y.params.spaceBetween&&y.params.spaceBetween+"px"}).attr("data-swiper-column",m).attr("data-swiper-row",h)}"none"!==c.css("display")&&("auto"===y.params.slidesPerView?(o=y.isHorizontal()?c.outerWidth(!0):c.outerHeight(!0),y.params.roundLengths&&(o=s(o))):(o=(y.size-(y.params.slidesPerView-1)*a)/y.params.slidesPerView,y.params.roundLengths&&(o=s(o)),y.isHorizontal()?y.slides[e].style.width=o+"px":y.slides[e].style.height=o+"px"),y.slides[e].swiperSlideSize=o,y.slidesSizesGrid.push(o),y.params.centeredSlides?(t=t+o/2+i/2+a,0===e&&(t=t-y.size/2-a),Math.abs(t)<.001&&(t=0),r%y.params.slidesPerGroup===0&&y.snapGrid.push(t),y.slidesGrid.push(t)):(r%y.params.slidesPerGroup===0&&y.snapGrid.push(t),y.slidesGrid.push(t),t=t+o+a),y.virtualSize+=o+a,i=o,r++)}y.virtualSize=Math.max(y.virtualSize,y.size)+y.params.slidesOffsetAfter;var f;if(y.rtl&&y.wrongRTL&&("slide"===y.params.effect||"coverflow"===y.params.effect)&&y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.support.flexbox&&!y.params.setWrapperSize||(y.isHorizontal()?y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}):y.wrapper.css({height:y.virtualSize+y.params.spaceBetween+"px"})),y.params.slidesPerColumn>1&&(y.virtualSize=(o+y.params.spaceBetween)*n,y.virtualSize=Math.ceil(y.virtualSize/y.params.slidesPerColumn)-y.params.spaceBetween,y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.params.centeredSlides)){for(f=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<y.virtualSize+y.snapGrid[0]&&f.push(y.snapGrid[e]);y.snapGrid=f}if(!y.params.centeredSlides){for(f=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<=y.virtualSize-y.size&&f.push(y.snapGrid[e]);y.snapGrid=f,Math.floor(y.virtualSize-y.size)-Math.floor(y.snapGrid[y.snapGrid.length-1])>1&&y.snapGrid.push(y.virtualSize-y.size)}0===y.snapGrid.length&&(y.snapGrid=[0]),0!==y.params.spaceBetween&&(y.isHorizontal()?y.rtl?y.slides.css({marginLeft:a+"px"}):y.slides.css({marginRight:a+"px"}):y.slides.css({marginBottom:a+"px"})),y.params.watchSlidesProgress&&y.updateSlidesOffset()}},y.updateSlidesOffset=function(){for(var e=0;e<y.slides.length;e++)y.slides[e].swiperSlideOffset=y.isHorizontal()?y.slides[e].offsetLeft:y.slides[e].offsetTop},y.updateSlidesProgress=function(e){if("undefined"==typeof e&&(e=y.translate||0),0!==y.slides.length){"undefined"==typeof y.slides[0].swiperSlideOffset&&y.updateSlidesOffset();var a=-e;y.rtl&&(a=e),y.slides.removeClass(y.params.slideVisibleClass);for(var t=0;t<y.slides.length;t++){var i=y.slides[t],s=(a-i.swiperSlideOffset)/(i.swiperSlideSize+y.params.spaceBetween);if(y.params.watchSlidesVisibility){var r=-(a-i.swiperSlideOffset),n=r+y.slidesSizesGrid[t],o=r>=0&&r<y.size||n>0&&n<=y.size||r<=0&&n>=y.size;o&&y.slides.eq(t).addClass(y.params.slideVisibleClass)}i.progress=y.rtl?-s:s}}},y.updateProgress=function(e){"undefined"==typeof e&&(e=y.translate||0);var a=y.maxTranslate()-y.minTranslate(),t=y.isBeginning,i=y.isEnd;0===a?(y.progress=0,y.isBeginning=y.isEnd=!0):(y.progress=(e-y.minTranslate())/a,y.isBeginning=y.progress<=0,y.isEnd=y.progress>=1),y.isBeginning&&!t&&y.emit("onReachBeginning",y),y.isEnd&&!i&&y.emit("onReachEnd",y),y.params.watchSlidesProgress&&y.updateSlidesProgress(e),y.emit("onProgress",y,y.progress)},y.updateActiveIndex=function(){var e,a,t,i=y.rtl?y.translate:-y.translate;for(a=0;a<y.slidesGrid.length;a++)"undefined"!=typeof y.slidesGrid[a+1]?i>=y.slidesGrid[a]&&i<y.slidesGrid[a+1]-(y.slidesGrid[a+1]-y.slidesGrid[a])/2?e=a:i>=y.slidesGrid[a]&&i<y.slidesGrid[a+1]&&(e=a+1):i>=y.slidesGrid[a]&&(e=a);(e<0||"undefined"==typeof e)&&(e=0),t=Math.floor(e/y.params.slidesPerGroup),t>=y.snapGrid.length&&(t=y.snapGrid.length-1),e!==y.activeIndex&&(y.snapIndex=t,y.previousIndex=y.activeIndex,y.activeIndex=e,y.updateClasses())},y.updateClasses=function(){y.slides.removeClass(y.params.slideActiveClass+" "+y.params.slideNextClass+" "+y.params.slidePrevClass);var e=y.slides.eq(y.activeIndex);e.addClass(y.params.slideActiveClass);var t=e.next("."+y.params.slideClass).addClass(y.params.slideNextClass);y.params.loop&&0===t.length&&y.slides.eq(0).addClass(y.params.slideNextClass);var i=e.prev("."+y.params.slideClass).addClass(y.params.slidePrevClass);if(y.params.loop&&0===i.length&&y.slides.eq(-1).addClass(y.params.slidePrevClass),y.paginationContainer&&y.paginationContainer.length>0){var s,r=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length;if(y.params.loop?(s=Math.ceil((y.activeIndex-y.loopedSlides)/y.params.slidesPerGroup),s>y.slides.length-1-2*y.loopedSlides&&(s-=y.slides.length-2*y.loopedSlides),s>r-1&&(s-=r),s<0&&"bullets"!==y.params.paginationType&&(s=r+s)):s="undefined"!=typeof y.snapIndex?y.snapIndex:y.activeIndex||0,"bullets"===y.params.paginationType&&y.bullets&&y.bullets.length>0&&(y.bullets.removeClass(y.params.bulletActiveClass),y.paginationContainer.length>1?y.bullets.each(function(){a(this).index()===s&&a(this).addClass(y.params.bulletActiveClass)}):y.bullets.eq(s).addClass(y.params.bulletActiveClass)),"fraction"===y.params.paginationType&&(y.paginationContainer.find("."+y.params.paginationCurrentClass).text(s+1),y.paginationContainer.find("."+y.params.paginationTotalClass).text(r)),"progress"===y.params.paginationType){var n=(s+1)/r,o=n,l=1;y.isHorizontal()||(l=n,o=1),y.paginationContainer.find("."+y.params.paginationProgressbarClass).transform("translate3d(0,0,0) scaleX("+o+") scaleY("+l+")").transition(y.params.speed)}"custom"===y.params.paginationType&&y.params.paginationCustomRender&&(y.paginationContainer.html(y.params.paginationCustomRender(y,s+1,r)),y.emit("onPaginationRendered",y,y.paginationContainer[0]))}y.params.loop||(y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.isBeginning?(y.prevButton.addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(y.prevButton)):(y.prevButton.removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(y.prevButton))),y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.isEnd?(y.nextButton.addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(y.nextButton)):(y.nextButton.removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(y.nextButton))))},y.updatePagination=function(){if(y.params.pagination&&y.paginationContainer&&y.paginationContainer.length>0){var e="";if("bullets"===y.params.paginationType){for(var a=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length,t=0;t<a;t++)e+=y.params.paginationBulletRender?y.params.paginationBulletRender(t,y.params.bulletClass):"<"+y.params.paginationElement+' class="'+y.params.bulletClass+'"></'+y.params.paginationElement+">";y.paginationContainer.html(e),y.bullets=y.paginationContainer.find("."+y.params.bulletClass),y.params.paginationClickable&&y.params.a11y&&y.a11y&&y.a11y.initPagination()}"fraction"===y.params.paginationType&&(e=y.params.paginationFractionRender?y.params.paginationFractionRender(y,y.params.paginationCurrentClass,y.params.paginationTotalClass):'<span class="'+y.params.paginationCurrentClass+'"></span> / <span class="'+y.params.paginationTotalClass+'"></span>',y.paginationContainer.html(e)),"progress"===y.params.paginationType&&(e=y.params.paginationProgressRender?y.params.paginationProgressRender(y,y.params.paginationProgressbarClass):'<span class="'+y.params.paginationProgressbarClass+'"></span>',y.paginationContainer.html(e)),"custom"!==y.params.paginationType&&y.emit("onPaginationRendered",y,y.paginationContainer[0])}},y.update=function(e){function a(){i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate()),y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses()}if(y.updateContainerSize(),y.updateSlidesSize(),y.updateProgress(),y.updatePagination(),y.updateClasses(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),e){var t,i;y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode?(a(),y.params.autoHeight&&y.updateAutoHeight()):(t=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0),t||a())}else y.params.autoHeight&&y.updateAutoHeight()},y.onResize=function(e){y.params.breakpoints&&y.setBreakpoint();var a=y.params.allowSwipeToPrev,t=y.params.allowSwipeToNext;y.params.allowSwipeToPrev=y.params.allowSwipeToNext=!0,y.updateContainerSize(),y.updateSlidesSize(),("auto"===y.params.slidesPerView||y.params.freeMode||e)&&y.updatePagination(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),y.controller&&y.controller.spline&&(y.controller.spline=void 0);var i=!1;if(y.params.freeMode){var s=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate());y.setWrapperTranslate(s),y.updateActiveIndex(),y.updateClasses(),y.params.autoHeight&&y.updateAutoHeight()}else y.updateClasses(),i=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0);y.params.lazyLoading&&!i&&y.lazy&&y.lazy.load(),y.params.allowSwipeToPrev=a,y.params.allowSwipeToNext=t};var T=["mousedown","mousemove","mouseup"];window.navigator.pointerEnabled?T=["pointerdown","pointermove","pointerup"]:window.navigator.msPointerEnabled&&(T=["MSPointerDown","MSPointerMove","MSPointerUp"]),y.touchEvents={start:y.support.touch||!y.params.simulateTouch?"touchstart":T[0],move:y.support.touch||!y.params.simulateTouch?"touchmove":T[1],end:y.support.touch||!y.params.simulateTouch?"touchend":T[2]},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===y.params.touchEventsTarget?y.container:y.wrapper).addClass("swiper-wp8-"+y.params.direction),y.initEvents=function(e){var a=e?"off":"on",t=e?"removeEventListener":"addEventListener",s="container"===y.params.touchEventsTarget?y.container[0]:y.wrapper[0],r=y.support.touch?s:document,n=!!y.params.nested;y.browser.ie?(s[t](y.touchEvents.start,y.onTouchStart,!1),r[t](y.touchEvents.move,y.onTouchMove,n),r[t](y.touchEvents.end,y.onTouchEnd,!1)):(y.support.touch&&(s[t](y.touchEvents.start,y.onTouchStart,!1),s[t](y.touchEvents.move,y.onTouchMove,n),s[t](y.touchEvents.end,y.onTouchEnd,!1)),!i.simulateTouch||y.device.ios||y.device.android||(s[t]("mousedown",y.onTouchStart,!1),document[t]("mousemove",y.onTouchMove,n),document[t]("mouseup",y.onTouchEnd,!1))),window[t]("resize",y.onResize),y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.nextButton[a]("click",y.onClickNext),y.params.a11y&&y.a11y&&y.nextButton[a]("keydown",y.a11y.onEnterKey)),y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.prevButton[a]("click",y.onClickPrev),y.params.a11y&&y.a11y&&y.prevButton[a]("keydown",y.a11y.onEnterKey)),y.params.pagination&&y.params.paginationClickable&&(y.paginationContainer[a]("click","."+y.params.bulletClass,y.onClickIndex),y.params.a11y&&y.a11y&&y.paginationContainer[a]("keydown","."+y.params.bulletClass,y.a11y.onEnterKey)),(y.params.preventClicks||y.params.preventClicksPropagation)&&s[t]("click",y.preventClicks,!0)},y.attachEvents=function(){y.initEvents()},y.detachEvents=function(){y.initEvents(!0)},y.allowClick=!0,y.preventClicks=function(e){y.allowClick||(y.params.preventClicks&&e.preventDefault(),y.params.preventClicksPropagation&&y.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},y.onClickNext=function(e){e.preventDefault(),y.isEnd&&!y.params.loop||y.slideNext()},y.onClickPrev=function(e){e.preventDefault(),y.isBeginning&&!y.params.loop||y.slidePrev()},y.onClickIndex=function(e){e.preventDefault();var t=a(this).index()*y.params.slidesPerGroup;y.params.loop&&(t+=y.loopedSlides),y.slideTo(t)},y.updateClickedSlide=function(e){var t=n(e,"."+y.params.slideClass),i=!1;if(t)for(var s=0;s<y.slides.length;s++)y.slides[s]===t&&(i=!0);if(!t||!i)return y.clickedSlide=void 0,void(y.clickedIndex=void 0);if(y.clickedSlide=t,y.clickedIndex=a(t).index(),y.params.slideToClickedSlide&&void 0!==y.clickedIndex&&y.clickedIndex!==y.activeIndex){var r,o=y.clickedIndex;if(y.params.loop){if(y.animating)return;r=a(y.clickedSlide).attr("data-swiper-slide-index"),y.params.centeredSlides?o<y.loopedSlides-y.params.slidesPerView/2||o>y.slides.length-y.loopedSlides+y.params.slidesPerView/2?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o):o>y.slides.length-y.params.slidesPerView?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o)}else y.slideTo(o)}};var b,S,C,z,M,P,I,k,E,D,B="input, select, textarea, button",L=Date.now(),H=[];y.animating=!1,y.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var G,A;if(y.onTouchStart=function(e){if(e.originalEvent&&(e=e.originalEvent),G="touchstart"===e.type,G||!("which"in e)||3!==e.which){if(y.params.noSwiping&&n(e,"."+y.params.noSwipingClass))return void(y.allowClick=!0);if(!y.params.swipeHandler||n(e,y.params.swipeHandler)){var t=y.touches.currentX="touchstart"===e.type?e.targetTouches[0].pageX:e.pageX,i=y.touches.currentY="touchstart"===e.type?e.targetTouches[0].pageY:e.pageY;if(!(y.device.ios&&y.params.iOSEdgeSwipeDetection&&t<=y.params.iOSEdgeSwipeThreshold)){if(b=!0,S=!1,C=!0,M=void 0,A=void 0,y.touches.startX=t,y.touches.startY=i,z=Date.now(),y.allowClick=!0,y.updateContainerSize(),y.swipeDirection=void 0,y.params.threshold>0&&(k=!1),"touchstart"!==e.type){var s=!0;a(e.target).is(B)&&(s=!1),document.activeElement&&a(document.activeElement).is(B)&&document.activeElement.blur(),s&&e.preventDefault()}y.emit("onTouchStart",y,e)}}}},y.onTouchMove=function(e){if(e.originalEvent&&(e=e.originalEvent),!G||"mousemove"!==e.type){if(e.preventedByNestedSwiper)return y.touches.startX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,void(y.touches.startY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY);if(y.params.onlyExternal)return y.allowClick=!1,void(b&&(y.touches.startX=y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.startY=y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,z=Date.now()));if(G&&document.activeElement&&e.target===document.activeElement&&a(e.target).is(B))return S=!0,void(y.allowClick=!1);if(C&&y.emit("onTouchMove",y,e),!(e.targetTouches&&e.targetTouches.length>1)){if(y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,"undefined"==typeof M){var t=180*Math.atan2(Math.abs(y.touches.currentY-y.touches.startY),Math.abs(y.touches.currentX-y.touches.startX))/Math.PI;M=y.isHorizontal()?t>y.params.touchAngle:90-t>y.params.touchAngle}if(M&&y.emit("onTouchMoveOpposite",y,e),"undefined"==typeof A&&y.browser.ieTouch&&(y.touches.currentX===y.touches.startX&&y.touches.currentY===y.touches.startY||(A=!0)),b){if(M)return void(b=!1);if(A||!y.browser.ieTouch){y.allowClick=!1,y.emit("onSliderMove",y,e),e.preventDefault(),y.params.touchMoveStopPropagation&&!y.params.nested&&e.stopPropagation(),S||(i.loop&&y.fixLoop(),I=y.getWrapperTranslate(),y.setWrapperTransition(0),y.animating&&y.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),y.params.autoplay&&y.autoplaying&&(y.params.autoplayDisableOnInteraction?y.stopAutoplay():y.pauseAutoplay()),D=!1,y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grabbing",y.container[0].style.cursor="-moz-grabbin",y.container[0].style.cursor="grabbing")),S=!0;var s=y.touches.diff=y.isHorizontal()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY;s*=y.params.touchRatio,y.rtl&&(s=-s),y.swipeDirection=s>0?"prev":"next",P=s+I;var r=!0;if(s>0&&P>y.minTranslate()?(r=!1,y.params.resistance&&(P=y.minTranslate()-1+Math.pow(-y.minTranslate()+I+s,y.params.resistanceRatio))):s<0&&P<y.maxTranslate()&&(r=!1,y.params.resistance&&(P=y.maxTranslate()+1-Math.pow(y.maxTranslate()-I-s,y.params.resistanceRatio))),
+r&&(e.preventedByNestedSwiper=!0),!y.params.allowSwipeToNext&&"next"===y.swipeDirection&&P<I&&(P=I),!y.params.allowSwipeToPrev&&"prev"===y.swipeDirection&&P>I&&(P=I),y.params.followFinger){if(y.params.threshold>0){if(!(Math.abs(s)>y.params.threshold||k))return void(P=I);if(!k)return k=!0,y.touches.startX=y.touches.currentX,y.touches.startY=y.touches.currentY,P=I,void(y.touches.diff=y.isHorizontal()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY)}(y.params.freeMode||y.params.watchSlidesProgress)&&y.updateActiveIndex(),y.params.freeMode&&(0===H.length&&H.push({position:y.touches[y.isHorizontal()?"startX":"startY"],time:z}),H.push({position:y.touches[y.isHorizontal()?"currentX":"currentY"],time:(new window.Date).getTime()})),y.updateProgress(P),y.setWrapperTranslate(P)}}}}}},y.onTouchEnd=function(e){if(e.originalEvent&&(e=e.originalEvent),C&&y.emit("onTouchEnd",y,e),C=!1,b){y.params.grabCursor&&S&&b&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab");var t=Date.now(),i=t-z;if(y.allowClick&&(y.updateClickedSlide(e),y.emit("onTap",y,e),i<300&&t-L>300&&(E&&clearTimeout(E),E=setTimeout(function(){y&&(y.params.paginationHide&&y.paginationContainer.length>0&&!a(e.target).hasClass(y.params.bulletClass)&&y.paginationContainer.toggleClass(y.params.paginationHiddenClass),y.emit("onClick",y,e))},300)),i<300&&t-L<300&&(E&&clearTimeout(E),y.emit("onDoubleTap",y,e))),L=Date.now(),setTimeout(function(){y&&(y.allowClick=!0)},0),!b||!S||!y.swipeDirection||0===y.touches.diff||P===I)return void(b=S=!1);b=S=!1;var s;if(s=y.params.followFinger?y.rtl?y.translate:-y.translate:-P,y.params.freeMode){if(s<-y.minTranslate())return void y.slideTo(y.activeIndex);if(s>-y.maxTranslate())return void(y.slides.length<y.snapGrid.length?y.slideTo(y.snapGrid.length-1):y.slideTo(y.slides.length-1));if(y.params.freeModeMomentum){if(H.length>1){var r=H.pop(),n=H.pop(),o=r.position-n.position,l=r.time-n.time;y.velocity=o/l,y.velocity=y.velocity/2,Math.abs(y.velocity)<y.params.freeModeMinimumVelocity&&(y.velocity=0),(l>150||(new window.Date).getTime()-r.time>300)&&(y.velocity=0)}else y.velocity=0;H.length=0;var p=1e3*y.params.freeModeMomentumRatio,d=y.velocity*p,c=y.translate+d;y.rtl&&(c=-c);var u,m=!1,h=20*Math.abs(y.velocity)*y.params.freeModeMomentumBounceRatio;if(c<y.maxTranslate())y.params.freeModeMomentumBounce?(c+y.maxTranslate()<-h&&(c=y.maxTranslate()-h),u=y.maxTranslate(),m=!0,D=!0):c=y.maxTranslate();else if(c>y.minTranslate())y.params.freeModeMomentumBounce?(c-y.minTranslate()>h&&(c=y.minTranslate()+h),u=y.minTranslate(),m=!0,D=!0):c=y.minTranslate();else if(y.params.freeModeSticky){var f,g=0;for(g=0;g<y.snapGrid.length;g+=1)if(y.snapGrid[g]>-c){f=g;break}c=Math.abs(y.snapGrid[f]-c)<Math.abs(y.snapGrid[f-1]-c)||"next"===y.swipeDirection?y.snapGrid[f]:y.snapGrid[f-1],y.rtl||(c=-c)}if(0!==y.velocity)p=y.rtl?Math.abs((-c-y.translate)/y.velocity):Math.abs((c-y.translate)/y.velocity);else if(y.params.freeModeSticky)return void y.slideReset();y.params.freeModeMomentumBounce&&m?(y.updateProgress(u),y.setWrapperTransition(p),y.setWrapperTranslate(c),y.onTransitionStart(),y.animating=!0,y.wrapper.transitionEnd(function(){y&&D&&(y.emit("onMomentumBounce",y),y.setWrapperTransition(y.params.speed),y.setWrapperTranslate(u),y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))})):y.velocity?(y.updateProgress(c),y.setWrapperTransition(p),y.setWrapperTranslate(c),y.onTransitionStart(),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))):y.updateProgress(c),y.updateActiveIndex()}return void((!y.params.freeModeMomentum||i>=y.params.longSwipesMs)&&(y.updateProgress(),y.updateActiveIndex()))}var v,w=0,x=y.slidesSizesGrid[0];for(v=0;v<y.slidesGrid.length;v+=y.params.slidesPerGroup)"undefined"!=typeof y.slidesGrid[v+y.params.slidesPerGroup]?s>=y.slidesGrid[v]&&s<y.slidesGrid[v+y.params.slidesPerGroup]&&(w=v,x=y.slidesGrid[v+y.params.slidesPerGroup]-y.slidesGrid[v]):s>=y.slidesGrid[v]&&(w=v,x=y.slidesGrid[y.slidesGrid.length-1]-y.slidesGrid[y.slidesGrid.length-2]);var T=(s-y.slidesGrid[w])/x;if(i>y.params.longSwipesMs){if(!y.params.longSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&(T>=y.params.longSwipesRatio?y.slideTo(w+y.params.slidesPerGroup):y.slideTo(w)),"prev"===y.swipeDirection&&(T>1-y.params.longSwipesRatio?y.slideTo(w+y.params.slidesPerGroup):y.slideTo(w))}else{if(!y.params.shortSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&y.slideTo(w+y.params.slidesPerGroup),"prev"===y.swipeDirection&&y.slideTo(w)}}},y._slideTo=function(e,a){return y.slideTo(e,a,!0,!0)},y.slideTo=function(e,a,t,i){"undefined"==typeof t&&(t=!0),"undefined"==typeof e&&(e=0),e<0&&(e=0),y.snapIndex=Math.floor(e/y.params.slidesPerGroup),y.snapIndex>=y.snapGrid.length&&(y.snapIndex=y.snapGrid.length-1);var s=-y.snapGrid[y.snapIndex];y.params.autoplay&&y.autoplaying&&(i||!y.params.autoplayDisableOnInteraction?y.pauseAutoplay(a):y.stopAutoplay()),y.updateProgress(s);for(var r=0;r<y.slidesGrid.length;r++)-Math.floor(100*s)>=Math.floor(100*y.slidesGrid[r])&&(e=r);return!(!y.params.allowSwipeToNext&&s<y.translate&&s<y.minTranslate())&&(!(!y.params.allowSwipeToPrev&&s>y.translate&&s>y.maxTranslate()&&(y.activeIndex||0)!==e)&&("undefined"==typeof a&&(a=y.params.speed),y.previousIndex=y.activeIndex||0,y.activeIndex=e,y.rtl&&-s===y.translate||!y.rtl&&s===y.translate?(y.params.autoHeight&&y.updateAutoHeight(),y.updateClasses(),"slide"!==y.params.effect&&y.setWrapperTranslate(s),!1):(y.updateClasses(),y.onTransitionStart(t),0===a?(y.setWrapperTranslate(s),y.setWrapperTransition(0),y.onTransitionEnd(t)):(y.setWrapperTranslate(s),y.setWrapperTransition(a),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd(t)}))),!0)))},y.onTransitionStart=function(e){"undefined"==typeof e&&(e=!0),y.params.autoHeight&&y.updateAutoHeight(),y.lazy&&y.lazy.onTransitionStart(),e&&(y.emit("onTransitionStart",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeStart",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextStart",y):y.emit("onSlidePrevStart",y)))},y.onTransitionEnd=function(e){y.animating=!1,y.setWrapperTransition(0),"undefined"==typeof e&&(e=!0),y.lazy&&y.lazy.onTransitionEnd(),e&&(y.emit("onTransitionEnd",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeEnd",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextEnd",y):y.emit("onSlidePrevEnd",y))),y.params.hashnav&&y.hashnav&&y.hashnav.setHash()},y.slideNext=function(e,a,t){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex+y.params.slidesPerGroup,a,e,t)}return y.slideTo(y.activeIndex+y.params.slidesPerGroup,a,e,t)},y._slideNext=function(e){return y.slideNext(!0,e,!0)},y.slidePrev=function(e,a,t){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex-1,a,e,t)}return y.slideTo(y.activeIndex-1,a,e,t)},y._slidePrev=function(e){return y.slidePrev(!0,e,!0)},y.slideReset=function(e,a,t){return y.slideTo(y.activeIndex,a,e)},y.setWrapperTransition=function(e,a){y.wrapper.transition(e),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTransition(e),y.params.parallax&&y.parallax&&y.parallax.setTransition(e),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTransition(e),y.params.control&&y.controller&&y.controller.setTransition(e,a),y.emit("onSetTransition",y,e)},y.setWrapperTranslate=function(e,a,t){var i=0,r=0,n=0;y.isHorizontal()?i=y.rtl?-e:e:r=e,y.params.roundLengths&&(i=s(i),r=s(r)),y.params.virtualTranslate||(y.support.transforms3d?y.wrapper.transform("translate3d("+i+"px, "+r+"px, "+n+"px)"):y.wrapper.transform("translate("+i+"px, "+r+"px)")),y.translate=y.isHorizontal()?i:r;var o,l=y.maxTranslate()-y.minTranslate();o=0===l?0:(e-y.minTranslate())/l,o!==y.progress&&y.updateProgress(e),a&&y.updateActiveIndex(),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTranslate(y.translate),y.params.parallax&&y.parallax&&y.parallax.setTranslate(y.translate),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTranslate(y.translate),y.params.control&&y.controller&&y.controller.setTranslate(y.translate,t),y.emit("onSetTranslate",y,y.translate)},y.getTranslate=function(e,a){var t,i,s,r;return"undefined"==typeof a&&(a="x"),y.params.virtualTranslate?y.rtl?-y.translate:y.translate:(s=window.getComputedStyle(e,null),window.WebKitCSSMatrix?(i=s.transform||s.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),r=new window.WebKitCSSMatrix("none"===i?"":i)):(r=s.MozTransform||s.OTransform||s.MsTransform||s.msTransform||s.transform||s.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),t=r.toString().split(",")),"x"===a&&(i=window.WebKitCSSMatrix?r.m41:16===t.length?parseFloat(t[12]):parseFloat(t[4])),"y"===a&&(i=window.WebKitCSSMatrix?r.m42:16===t.length?parseFloat(t[13]):parseFloat(t[5])),y.rtl&&i&&(i=-i),i||0)},y.getWrapperTranslate=function(e){return"undefined"==typeof e&&(e=y.isHorizontal()?"x":"y"),y.getTranslate(y.wrapper[0],e)},y.observers=[],y.initObservers=function(){if(y.params.observeParents)for(var e=y.container.parents(),a=0;a<e.length;a++)o(e[a]);o(y.container[0],{childList:!1}),o(y.wrapper[0],{attributes:!1})},y.disconnectObservers=function(){for(var e=0;e<y.observers.length;e++)y.observers[e].disconnect();y.observers=[]},y.createLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove();var e=y.wrapper.children("."+y.params.slideClass);"auto"!==y.params.slidesPerView||y.params.loopedSlides||(y.params.loopedSlides=e.length),y.loopedSlides=parseInt(y.params.loopedSlides||y.params.slidesPerView,10),y.loopedSlides=y.loopedSlides+y.params.loopAdditionalSlides,y.loopedSlides>e.length&&(y.loopedSlides=e.length);var t,i=[],s=[];for(e.each(function(t,r){var n=a(this);t<y.loopedSlides&&s.push(r),t<e.length&&t>=e.length-y.loopedSlides&&i.push(r),n.attr("data-swiper-slide-index",t)}),t=0;t<s.length;t++)y.wrapper.append(a(s[t].cloneNode(!0)).addClass(y.params.slideDuplicateClass));for(t=i.length-1;t>=0;t--)y.wrapper.prepend(a(i[t].cloneNode(!0)).addClass(y.params.slideDuplicateClass))},y.destroyLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove(),y.slides.removeAttr("data-swiper-slide-index")},y.reLoop=function(e){var a=y.activeIndex-y.loopedSlides;y.destroyLoop(),y.createLoop(),y.updateSlidesSize(),e&&y.slideTo(a+y.loopedSlides,0,!1)},y.fixLoop=function(){var e;y.activeIndex<y.loopedSlides?(e=y.slides.length-3*y.loopedSlides+y.activeIndex,e+=y.loopedSlides,y.slideTo(e,0,!1,!0)):("auto"===y.params.slidesPerView&&y.activeIndex>=2*y.loopedSlides||y.activeIndex>y.slides.length-2*y.params.slidesPerView)&&(e=-y.slides.length+y.activeIndex+y.loopedSlides,e+=y.loopedSlides,y.slideTo(e,0,!1,!0))},y.appendSlide=function(e){if(y.params.loop&&y.destroyLoop(),"object"==typeof e&&e.length)for(var a=0;a<e.length;a++)e[a]&&y.wrapper.append(e[a]);else y.wrapper.append(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0)},y.prependSlide=function(e){y.params.loop&&y.destroyLoop();var a=y.activeIndex+1;if("object"==typeof e&&e.length){for(var t=0;t<e.length;t++)e[t]&&y.wrapper.prepend(e[t]);a=y.activeIndex+e.length}else y.wrapper.prepend(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.slideTo(a,0,!1)},y.removeSlide=function(e){y.params.loop&&(y.destroyLoop(),y.slides=y.wrapper.children("."+y.params.slideClass));var a,t=y.activeIndex;if("object"==typeof e&&e.length){for(var i=0;i<e.length;i++)a=e[i],y.slides[a]&&y.slides.eq(a).remove(),a<t&&t--;t=Math.max(t,0)}else a=e,y.slides[a]&&y.slides.eq(a).remove(),a<t&&t--,t=Math.max(t,0);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.params.loop?y.slideTo(t+y.loopedSlides,0,!1):y.slideTo(t,0,!1)},y.removeAllSlides=function(){for(var e=[],a=0;a<y.slides.length;a++)e.push(a);y.removeSlide(e)},y.effects={fade:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var a=y.slides.eq(e),t=a[0].swiperSlideOffset,i=-t;y.params.virtualTranslate||(i-=y.translate);var s=0;y.isHorizontal()||(s=i,i=0);var r=y.params.fade.crossFade?Math.max(1-Math.abs(a[0].progress),0):1+Math.min(Math.max(a[0].progress,-1),0);a.css({opacity:r}).transform("translate3d("+i+"px, "+s+"px, 0px)")}},setTransition:function(e){if(y.slides.transition(e),y.params.virtualTranslate&&0!==e){var a=!1;y.slides.transitionEnd(function(){if(!a&&y){a=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],t=0;t<e.length;t++)y.wrapper.trigger(e[t])}})}}},flip:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var t=y.slides.eq(e),i=t[0].progress;y.params.flip.limitRotation&&(i=Math.max(Math.min(t[0].progress,1),-1));var s=t[0].swiperSlideOffset,r=-180*i,n=r,o=0,l=-s,p=0;if(y.isHorizontal()?y.rtl&&(n=-n):(p=l,l=0,o=-n,n=0),t[0].style.zIndex=-Math.abs(Math.round(i))+y.slides.length,y.params.flip.slideShadows){var d=y.isHorizontal()?t.find(".swiper-slide-shadow-left"):t.find(".swiper-slide-shadow-top"),c=y.isHorizontal()?t.find(".swiper-slide-shadow-right"):t.find(".swiper-slide-shadow-bottom");0===d.length&&(d=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),t.append(d)),0===c.length&&(c=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),t.append(c)),d.length&&(d[0].style.opacity=Math.max(-i,0)),c.length&&(c[0].style.opacity=Math.max(i,0))}t.transform("translate3d("+l+"px, "+p+"px, 0px) rotateX("+o+"deg) rotateY("+n+"deg)")}},setTransition:function(e){if(y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.virtualTranslate&&0!==e){var t=!1;y.slides.eq(y.activeIndex).transitionEnd(function(){if(!t&&y&&a(this).hasClass(y.params.slideActiveClass)){t=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=0;i<e.length;i++)y.wrapper.trigger(e[i])}})}}},cube:{setTranslate:function(){var e,t=0;y.params.cube.shadow&&(y.isHorizontal()?(e=y.wrapper.find(".swiper-cube-shadow"),0===e.length&&(e=a('<div class="swiper-cube-shadow"></div>'),y.wrapper.append(e)),e.css({height:y.width+"px"})):(e=y.container.find(".swiper-cube-shadow"),0===e.length&&(e=a('<div class="swiper-cube-shadow"></div>'),y.container.append(e))));for(var i=0;i<y.slides.length;i++){var s=y.slides.eq(i),r=90*i,n=Math.floor(r/360);y.rtl&&(r=-r,n=Math.floor(-r/360));var o=Math.max(Math.min(s[0].progress,1),-1),l=0,p=0,d=0;i%4===0?(l=4*-n*y.size,d=0):(i-1)%4===0?(l=0,d=4*-n*y.size):(i-2)%4===0?(l=y.size+4*n*y.size,d=y.size):(i-3)%4===0&&(l=-y.size,d=3*y.size+4*y.size*n),y.rtl&&(l=-l),y.isHorizontal()||(p=l,l=0);var c="rotateX("+(y.isHorizontal()?0:-r)+"deg) rotateY("+(y.isHorizontal()?r:0)+"deg) translate3d("+l+"px, "+p+"px, "+d+"px)";if(o<=1&&o>-1&&(t=90*i+90*o,y.rtl&&(t=90*-i-90*o)),s.transform(c),y.params.cube.slideShadows){var u=y.isHorizontal()?s.find(".swiper-slide-shadow-left"):s.find(".swiper-slide-shadow-top"),m=y.isHorizontal()?s.find(".swiper-slide-shadow-right"):s.find(".swiper-slide-shadow-bottom");0===u.length&&(u=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),s.append(u)),0===m.length&&(m=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),s.append(m)),u.length&&(u[0].style.opacity=Math.max(-o,0)),m.length&&(m[0].style.opacity=Math.max(o,0))}}if(y.wrapper.css({"-webkit-transform-origin":"50% 50% -"+y.size/2+"px","-moz-transform-origin":"50% 50% -"+y.size/2+"px","-ms-transform-origin":"50% 50% -"+y.size/2+"px","transform-origin":"50% 50% -"+y.size/2+"px"}),y.params.cube.shadow)if(y.isHorizontal())e.transform("translate3d(0px, "+(y.width/2+y.params.cube.shadowOffset)+"px, "+-y.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+y.params.cube.shadowScale+")");else{var h=Math.abs(t)-90*Math.floor(Math.abs(t)/90),f=1.5-(Math.sin(2*h*Math.PI/360)/2+Math.cos(2*h*Math.PI/360)/2),g=y.params.cube.shadowScale,v=y.params.cube.shadowScale/f,w=y.params.cube.shadowOffset;e.transform("scale3d("+g+", 1, "+v+") translate3d(0px, "+(y.height/2+w)+"px, "+-y.height/2/v+"px) rotateX(-90deg)")}var x=y.isSafari||y.isUiWebView?-y.size/2:0;y.wrapper.transform("translate3d(0px,0,"+x+"px) rotateX("+(y.isHorizontal()?0:t)+"deg) rotateY("+(y.isHorizontal()?-t:0)+"deg)")},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.cube.shadow&&!y.isHorizontal()&&y.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var e=y.translate,t=y.isHorizontal()?-e+y.width/2:-e+y.height/2,i=y.isHorizontal()?y.params.coverflow.rotate:-y.params.coverflow.rotate,s=y.params.coverflow.depth,r=0,n=y.slides.length;r<n;r++){var o=y.slides.eq(r),l=y.slidesSizesGrid[r],p=o[0].swiperSlideOffset,d=(t-p-l/2)/l*y.params.coverflow.modifier,c=y.isHorizontal()?i*d:0,u=y.isHorizontal()?0:i*d,m=-s*Math.abs(d),h=y.isHorizontal()?0:y.params.coverflow.stretch*d,f=y.isHorizontal()?y.params.coverflow.stretch*d:0;Math.abs(f)<.001&&(f=0),Math.abs(h)<.001&&(h=0),Math.abs(m)<.001&&(m=0),Math.abs(c)<.001&&(c=0),Math.abs(u)<.001&&(u=0);var g="translate3d("+f+"px,"+h+"px,"+m+"px)  rotateX("+u+"deg) rotateY("+c+"deg)";if(o.transform(g),o[0].style.zIndex=-Math.abs(Math.round(d))+1,y.params.coverflow.slideShadows){var v=y.isHorizontal()?o.find(".swiper-slide-shadow-left"):o.find(".swiper-slide-shadow-top"),w=y.isHorizontal()?o.find(".swiper-slide-shadow-right"):o.find(".swiper-slide-shadow-bottom");0===v.length&&(v=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),o.append(v)),0===w.length&&(w=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),o.append(w)),v.length&&(v[0].style.opacity=d>0?d:0),w.length&&(w[0].style.opacity=-d>0?-d:0)}}if(y.browser.ie){var x=y.wrapper[0].style;x.perspectiveOrigin=t+"px 50%"}},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},y.lazy={initialImageLoaded:!1,loadImageInSlide:function(e,t){if("undefined"!=typeof e&&("undefined"==typeof t&&(t=!0),0!==y.slides.length)){var i=y.slides.eq(e),s=i.find(".swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)");!i.hasClass("swiper-lazy")||i.hasClass("swiper-lazy-loaded")||i.hasClass("swiper-lazy-loading")||(s=s.add(i[0])),0!==s.length&&s.each(function(){var e=a(this);e.addClass("swiper-lazy-loading");var s=e.attr("data-background"),r=e.attr("data-src"),n=e.attr("data-srcset");y.loadImage(e[0],r||s,n,!1,function(){if(s?(e.css("background-image",'url("'+s+'")'),e.removeAttr("data-background")):(n&&(e.attr("srcset",n),e.removeAttr("data-srcset")),r&&(e.attr("src",r),e.removeAttr("data-src"))),e.addClass("swiper-lazy-loaded").removeClass("swiper-lazy-loading"),i.find(".swiper-lazy-preloader, .preloader").remove(),y.params.loop&&t){var a=i.attr("data-swiper-slide-index");if(i.hasClass(y.params.slideDuplicateClass)){var o=y.wrapper.children('[data-swiper-slide-index="'+a+'"]:not(.'+y.params.slideDuplicateClass+")");y.lazy.loadImageInSlide(o.index(),!1)}else{var l=y.wrapper.children("."+y.params.slideDuplicateClass+'[data-swiper-slide-index="'+a+'"]');y.lazy.loadImageInSlide(l.index(),!1)}}y.emit("onLazyImageReady",y,i[0],e[0])}),y.emit("onLazyImageLoad",y,i[0],e[0])})}},load:function(){var e;if(y.params.watchSlidesVisibility)y.wrapper.children("."+y.params.slideVisibleClass).each(function(){y.lazy.loadImageInSlide(a(this).index())});else if(y.params.slidesPerView>1)for(e=y.activeIndex;e<y.activeIndex+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);else y.lazy.loadImageInSlide(y.activeIndex);if(y.params.lazyLoadingInPrevNext)if(y.params.slidesPerView>1||y.params.lazyLoadingInPrevNextAmount&&y.params.lazyLoadingInPrevNextAmount>1){var t=y.params.lazyLoadingInPrevNextAmount,i=y.params.slidesPerView,s=Math.min(y.activeIndex+i+Math.max(t,i),y.slides.length),r=Math.max(y.activeIndex-Math.max(i,t),0);for(e=y.activeIndex+y.params.slidesPerView;e<s;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);for(e=r;e<y.activeIndex;e++)y.slides[e]&&y.lazy.loadImageInSlide(e)}else{var n=y.wrapper.children("."+y.params.slideNextClass);n.length>0&&y.lazy.loadImageInSlide(n.index());var o=y.wrapper.children("."+y.params.slidePrevClass);o.length>0&&y.lazy.loadImageInSlide(o.index())}},onTransitionStart:function(){y.params.lazyLoading&&(y.params.lazyLoadingOnTransitionStart||!y.params.lazyLoadingOnTransitionStart&&!y.lazy.initialImageLoaded)&&y.lazy.load()},onTransitionEnd:function(){y.params.lazyLoading&&!y.params.lazyLoadingOnTransitionStart&&y.lazy.load()}},y.scrollbar={isTouched:!1,setDragPosition:function(e){var a=y.scrollbar,t=y.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY,i=t-a.track.offset()[y.isHorizontal()?"left":"top"]-a.dragSize/2,s=-y.minTranslate()*a.moveDivider,r=-y.maxTranslate()*a.moveDivider;i<s?i=s:i>r&&(i=r),i=-i/a.moveDivider,y.updateProgress(i),y.setWrapperTranslate(i,!0)},dragStart:function(e){var a=y.scrollbar;a.isTouched=!0,e.preventDefault(),e.stopPropagation(),a.setDragPosition(e),clearTimeout(a.dragTimeout),a.track.transition(0),y.params.scrollbarHide&&a.track.css("opacity",1),y.wrapper.transition(100),a.drag.transition(100),y.emit("onScrollbarDragStart",y)},dragMove:function(e){var a=y.scrollbar;a.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,a.setDragPosition(e),y.wrapper.transition(0),a.track.transition(0),a.drag.transition(0),y.emit("onScrollbarDragMove",y))},dragEnd:function(e){var a=y.scrollbar;a.isTouched&&(a.isTouched=!1,y.params.scrollbarHide&&(clearTimeout(a.dragTimeout),a.dragTimeout=setTimeout(function(){a.track.css("opacity",0),a.track.transition(400)},1e3)),y.emit("onScrollbarDragEnd",y),y.params.scrollbarSnapOnRelease&&y.slideReset())},enableDraggable:function(){var e=y.scrollbar,t=y.support.touch?e.track:document;a(e.track).on(y.touchEvents.start,e.dragStart),a(t).on(y.touchEvents.move,e.dragMove),a(t).on(y.touchEvents.end,e.dragEnd)},disableDraggable:function(){var e=y.scrollbar,t=y.support.touch?e.track:document;a(e.track).off(y.touchEvents.start,e.dragStart),a(t).off(y.touchEvents.move,e.dragMove),a(t).off(y.touchEvents.end,e.dragEnd)},set:function(){if(y.params.scrollbar){var e=y.scrollbar;e.track=a(y.params.scrollbar),y.params.uniqueNavElements&&"string"==typeof y.params.scrollbar&&e.track.length>1&&1===y.container.find(y.params.scrollbar).length&&(e.track=y.container.find(y.params.scrollbar)),e.drag=e.track.find(".swiper-scrollbar-drag"),0===e.drag.length&&(e.drag=a('<div class="swiper-scrollbar-drag"></div>'),e.track.append(e.drag)),e.drag[0].style.width="",e.drag[0].style.height="",e.trackSize=y.isHorizontal()?e.track[0].offsetWidth:e.track[0].offsetHeight,e.divider=y.size/y.virtualSize,e.moveDivider=e.divider*(e.trackSize/y.size),e.dragSize=e.trackSize*e.divider,y.isHorizontal()?e.drag[0].style.width=e.dragSize+"px":e.drag[0].style.height=e.dragSize+"px",e.divider>=1?e.track[0].style.display="none":e.track[0].style.display="",y.params.scrollbarHide&&(e.track[0].style.opacity=0)}},setTranslate:function(){if(y.params.scrollbar){var e,a=y.scrollbar,t=(y.translate||0,a.dragSize);e=(a.trackSize-a.dragSize)*y.progress,y.rtl&&y.isHorizontal()?(e=-e,e>0?(t=a.dragSize-e,e=0):-e+a.dragSize>a.trackSize&&(t=a.trackSize+e)):e<0?(t=a.dragSize+e,e=0):e+a.dragSize>a.trackSize&&(t=a.trackSize-e),y.isHorizontal()?(y.support.transforms3d?a.drag.transform("translate3d("+e+"px, 0, 0)"):a.drag.transform("translateX("+e+"px)"),a.drag[0].style.width=t+"px"):(y.support.transforms3d?a.drag.transform("translate3d(0px, "+e+"px, 0)"):a.drag.transform("translateY("+e+"px)"),a.drag[0].style.height=t+"px"),y.params.scrollbarHide&&(clearTimeout(a.timeout),a.track[0].style.opacity=1,a.timeout=setTimeout(function(){a.track[0].style.opacity=0,a.track.transition(400)},1e3))}},setTransition:function(e){y.params.scrollbar&&y.scrollbar.drag.transition(e)}},y.controller={LinearSpline:function(e,a){this.x=e,this.y=a,this.lastIndex=e.length-1;var t,i;this.x.length;this.interpolate=function(e){return e?(i=s(this.x,e),t=i-1,(e-this.x[t])*(this.y[i]-this.y[t])/(this.x[i]-this.x[t])+this.y[t]):0};var s=function(){var e,a,t;return function(i,s){for(a=-1,e=i.length;e-a>1;)i[t=e+a>>1]<=s?a=t:e=t;return e}}()},getInterpolateFunction:function(e){y.controller.spline||(y.controller.spline=y.params.loop?new y.controller.LinearSpline(y.slidesGrid,e.slidesGrid):new y.controller.LinearSpline(y.snapGrid,e.snapGrid))},setTranslate:function(e,a){function i(a){e=a.rtl&&"horizontal"===a.params.direction?-y.translate:y.translate,"slide"===y.params.controlBy&&(y.controller.getInterpolateFunction(a),r=-y.controller.spline.interpolate(-e)),r&&"container"!==y.params.controlBy||(s=(a.maxTranslate()-a.minTranslate())/(y.maxTranslate()-y.minTranslate()),r=(e-y.minTranslate())*s+a.minTranslate()),y.params.controlInverse&&(r=a.maxTranslate()-r),a.updateProgress(r),a.setWrapperTranslate(r,!1,y),a.updateActiveIndex()}var s,r,n=y.params.control;if(y.isArray(n))for(var o=0;o<n.length;o++)n[o]!==a&&n[o]instanceof t&&i(n[o]);else n instanceof t&&a!==n&&i(n)},setTransition:function(e,a){function i(a){a.setWrapperTransition(e,y),0!==e&&(a.onTransitionStart(),a.wrapper.transitionEnd(function(){r&&(a.params.loop&&"slide"===y.params.controlBy&&a.fixLoop(),a.onTransitionEnd())}))}var s,r=y.params.control;if(y.isArray(r))for(s=0;s<r.length;s++)r[s]!==a&&r[s]instanceof t&&i(r[s]);else r instanceof t&&a!==r&&i(r)}},y.hashnav={init:function(){if(y.params.hashnav){y.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var a=0,t=0,i=y.slides.length;t<i;t++){var s=y.slides.eq(t),r=s.attr("data-hash");if(r===e&&!s.hasClass(y.params.slideDuplicateClass)){var n=s.index();y.slideTo(n,a,y.params.runCallbacksOnInit,!0)}}}},setHash:function(){y.hashnav.initialized&&y.params.hashnav&&(document.location.hash=y.slides.eq(y.activeIndex).attr("data-hash")||"")}},y.disableKeyboardControl=function(){y.params.keyboardControl=!1,a(document).off("keydown",l)},y.enableKeyboardControl=function(){y.params.keyboardControl=!0,a(document).on("keydown",l)},y.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},y.params.mousewheelControl){try{new window.WheelEvent("wheel"),y.mousewheel.event="wheel"}catch(O){(window.WheelEvent||y.container[0]&&"wheel"in y.container[0])&&(y.mousewheel.event="wheel")}!y.mousewheel.event&&window.WheelEvent,y.mousewheel.event||void 0===document.onmousewheel||(y.mousewheel.event="mousewheel"),y.mousewheel.event||(y.mousewheel.event="DOMMouseScroll")}y.disableMousewheelControl=function(){return!!y.mousewheel.event&&(y.container.off(y.mousewheel.event,p),!0)},y.enableMousewheelControl=function(){return!!y.mousewheel.event&&(y.container.on(y.mousewheel.event,p),!0)},y.parallax={setTranslate:function(){y.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){d(this,y.progress)}),y.slides.each(function(){var e=a(this);e.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var a=Math.min(Math.max(e[0].progress,-1),1);d(this,a)})})},setTransition:function(e){"undefined"==typeof e&&(e=y.params.speed),y.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=a(this),i=parseInt(t.attr("data-swiper-parallax-duration"),10)||e;0===e&&(i=0),t.transition(i)})}},y._plugins=[];for(var N in y.plugins){var R=y.plugins[N](y,y.params[N]);R&&y._plugins.push(R)}return y.callPlugins=function(e){for(var a=0;a<y._plugins.length;a++)e in y._plugins[a]&&y._plugins[a][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.emitterEventListeners={},y.emit=function(e){y.params[e]&&y.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var a;if(y.emitterEventListeners[e])for(a=0;a<y.emitterEventListeners[e].length;a++)y.emitterEventListeners[e][a](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);y.callPlugins&&y.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.on=function(e,a){return e=c(e),y.emitterEventListeners[e]||(y.emitterEventListeners[e]=[]),y.emitterEventListeners[e].push(a),y},y.off=function(e,a){var t;if(e=c(e),"undefined"==typeof a)return y.emitterEventListeners[e]=[],y;if(y.emitterEventListeners[e]&&0!==y.emitterEventListeners[e].length){for(t=0;t<y.emitterEventListeners[e].length;t++)y.emitterEventListeners[e][t]===a&&y.emitterEventListeners[e].splice(t,1);return y}},y.once=function(e,a){e=c(e);var t=function(){a(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),y.off(e,t)};return y.on(e,t),y},y.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,a){return e.attr("role",a),e},addLabel:function(e,a){return e.attr("aria-label",a),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(e){13===e.keyCode&&(a(e.target).is(y.params.nextButton)?(y.onClickNext(e),y.isEnd?y.a11y.notify(y.params.lastSlideMessage):y.a11y.notify(y.params.nextSlideMessage)):a(e.target).is(y.params.prevButton)&&(y.onClickPrev(e),y.isBeginning?y.a11y.notify(y.params.firstSlideMessage):y.a11y.notify(y.params.prevSlideMessage)),a(e.target).is("."+y.params.bulletClass)&&a(e.target)[0].click())},liveRegion:a('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var a=y.a11y.liveRegion;0!==a.length&&(a.html(""),a.html(e))},init:function(){y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.a11y.makeFocusable(y.nextButton),y.a11y.addRole(y.nextButton,"button"),y.a11y.addLabel(y.nextButton,y.params.nextSlideMessage)),y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.a11y.makeFocusable(y.prevButton),y.a11y.addRole(y.prevButton,"button"),y.a11y.addLabel(y.prevButton,y.params.prevSlideMessage)),a(y.container).append(y.a11y.liveRegion)},initPagination:function(){y.params.pagination&&y.params.paginationClickable&&y.bullets&&y.bullets.length&&y.bullets.each(function(){var e=a(this);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.paginationBulletMessage.replace(/{{index}}/,e.index()+1))})},destroy:function(){y.a11y.liveRegion&&y.a11y.liveRegion.length>0&&y.a11y.liveRegion.remove()}},y.init=function(){y.params.loop&&y.createLoop(),y.updateContainerSize(),y.updateSlidesSize(),y.updatePagination(),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.set(),y.params.scrollbarDraggable&&y.scrollbar.enableDraggable()),"slide"!==y.params.effect&&y.effects[y.params.effect]&&(y.params.loop||y.updateProgress(),y.effects[y.params.effect].setTranslate()),y.params.loop?y.slideTo(y.params.initialSlide+y.loopedSlides,0,y.params.runCallbacksOnInit):(y.slideTo(y.params.initialSlide,0,y.params.runCallbacksOnInit),0===y.params.initialSlide&&(y.parallax&&y.params.parallax&&y.parallax.setTranslate(),y.lazy&&y.params.lazyLoading&&(y.lazy.load(),y.lazy.initialImageLoaded=!0))),y.attachEvents(),y.params.observer&&y.support.observer&&y.initObservers(),y.params.preloadImages&&!y.params.lazyLoading&&y.preloadImages(),y.params.autoplay&&y.startAutoplay(),y.params.keyboardControl&&y.enableKeyboardControl&&y.enableKeyboardControl(),y.params.mousewheelControl&&y.enableMousewheelControl&&y.enableMousewheelControl(),
+y.params.hashnav&&y.hashnav&&y.hashnav.init(),y.params.a11y&&y.a11y&&y.a11y.init(),y.emit("onInit",y)},y.cleanupStyles=function(){y.container.removeClass(y.classNames.join(" ")).removeAttr("style"),y.wrapper.removeAttr("style"),y.slides&&y.slides.length&&y.slides.removeClass([y.params.slideVisibleClass,y.params.slideActiveClass,y.params.slideNextClass,y.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),y.paginationContainer&&y.paginationContainer.length&&y.paginationContainer.removeClass(y.params.paginationHiddenClass),y.bullets&&y.bullets.length&&y.bullets.removeClass(y.params.bulletActiveClass),y.params.prevButton&&a(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.nextButton&&a(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.track&&y.scrollbar.track.length&&y.scrollbar.track.removeAttr("style"),y.scrollbar.drag&&y.scrollbar.drag.length&&y.scrollbar.drag.removeAttr("style"))},y.destroy=function(e,a){y.detachEvents(),y.stopAutoplay(),y.params.scrollbar&&y.scrollbar&&y.params.scrollbarDraggable&&y.scrollbar.disableDraggable(),y.params.loop&&y.destroyLoop(),a&&y.cleanupStyles(),y.disconnectObservers(),y.params.keyboardControl&&y.disableKeyboardControl&&y.disableKeyboardControl(),y.params.mousewheelControl&&y.disableMousewheelControl&&y.disableMousewheelControl(),y.params.a11y&&y.a11y&&y.a11y.destroy(),y.emit("onDestroy"),e!==!1&&(y=null)},y.init(),y}};t.prototype={isSafari:function(){var e=navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1},device:function(){var e=navigator.userAgent,a=e.match(/(Android);?[\s\/]+([\d.]+)?/),t=e.match(/(iPad).*OS\s([\d_]+)/),i=e.match(/(iPod)(.*OS\s([\d_]+))?/),s=!t&&e.match(/(iPhone\sOS)\s([\d_]+)/);return{ios:t||s||i,android:a}}(),support:{touch:window.Modernizr&&Modernizr.touch===!0||function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)}(),transforms3d:window.Modernizr&&Modernizr.csstransforms3d===!0||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,a="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),t=0;t<a.length;t++)if(a[t]in e)return!0}(),observer:function(){return"MutationObserver"in window||"WebkitMutationObserver"in window}()},plugins:{}};for(var i=["jQuery","Zepto","Dom7"],s=0;s<i.length;s++)window[i[s]]&&e(window[i[s]]);var r;r="undefined"==typeof Dom7?window.Dom7||window.Zepto||window.jQuery:Dom7,r&&("transitionEnd"in r.fn||(r.fn.transitionEnd=function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<i.length;t++)s.off(i[t],a)}var t,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],s=this;if(e)for(t=0;t<i.length;t++)s.on(i[t],a);return this}),"transform"in r.fn||(r.fn.transform=function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this}),"transition"in r.fn||(r.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this})),window.Swiper=t}(),"undefined"!=typeof module?module.exports=window.Swiper:"function"==typeof define&&define.amd&&define([],function(){"use strict";return window.Swiper}),+function(e){"use strict";var a;e.fn.swiper=function(t){return this.each(function(){if(this){var i=e(this),s=i.data("swiper");return s||i.data("swiper",new Swiper(this,e.extend({},a,t))),s}})},a=e.fn.swiper.prototype.defaults={pagination:".swiper-pagination"}}($),+function(e){var a,t=function(e){this.initConfig(e),this.index=0};t.prototype={initConfig:function(t){this.config=e.extend({},a,t),this.activeIndex=this.lastActiveIndex=this.config.initIndex,this.config.items=this.config.items.map(function(e,a){return"string"==typeof e?{image:e,caption:""}:e}),this.tpl=e.t7.compile(this.config.tpl),this.config.autoOpen&&this.open()},open:function(a){if(this._open)return!1;if(!this.modal){this.modal=e(this.tpl(this.config)).appendTo(document.body),this.container=this.modal.find(".swiper-container"),this.wrapper=this.modal.find(".swiper-wrapper");var t=new Hammer(this.container[0]);t.get("pinch").set({enable:!0}),t.on("pinchstart",e.proxy(this.onGestureStart,this)),t.on("pinchmove",e.proxy(this.onGestureChange,this)),t.on("pinchend",e.proxy(this.onGestureEnd,this)),this.modal.on(e.touchEvents.start,e.proxy(this.onTouchStart,this)),this.modal.on(e.touchEvents.move,e.proxy(this.onTouchMove,this)),this.modal.on(e.touchEvents.end,e.proxy(this.onTouchEnd,this)),this.wrapper.transition(0),this.wrapper.transform("translate3d(-"+e(window).width()*this.config.initIndex+"px,0,0)"),this.container.find(".caption-item").eq(this.config.initIndex).addClass("active"),this.container.find(".swiper-pagination-bullet").eq(this.config.initIndex).addClass("swiper-pagination-bullet-active")}var i=this;this.modal.show().height(),this.modal.addClass("weui-photo-browser-modal-visible"),this.container.addClass("swiper-container-visible").transitionEnd(function(){i.initParams(),void 0!==a&&i.slideTo(a),i.config.onOpen&&i.config.onOpen.call(i)}),this._open=!0},close:function(){this.container.transitionEnd(e.proxy(function(){this.modal.hide(),this._open=!1,this.config.onClose&&this.config.onClose.call(this)},this)),this.container.removeClass("swiper-container-visible"),this.modal.removeClass("weui-photo-browser-modal-visible")},initParams:function(){return!this.containerHeight&&(this.windowWidth=e(window).width(),this.containerHeight=this.container.height(),this.containerWidth=this.container.width(),this.touchStart={},this.wrapperTransform=0,this.wrapperLastTransform=-e(window).width()*this.config.initIndex,this.wrapperDiff=0,this.lastScale=1,this.currentScale=1,this.imageLastTransform={x:0,y:0},this.imageTransform={x:0,y:0},this.imageDiff={x:0,y:0},void(this.imageLastDiff={x:0,y:0}))},onTouchStart:function(a){return!this.scaling&&(this.touching=!0,this.touchStart=e.getTouchPosition(a),this.touchMove=null,this.touchStartTime=+new Date,this.wrapperDiff=0,void(this.breakpointPosition=null))},onTouchMove:function(a){if(!this.touching||this.scaling)return!1;if(a.preventDefault(),this.gestureImage){var t=this.gestureImage[0].getBoundingClientRect();t.left>=0||t.right<=this.windowWidth?this.overflow=!0:this.overflow=!1}else this.oveflow=!1;var i=this.touchMove=e.getTouchPosition(a);if(1===this.currentScale||this.overflow)this.breakpointPosition?this.wrapperDiff=i.x-this.breakpointPosition.x:this.wrapperDiff=i.x-this.touchStart.x,0===this.activeIndex&&this.wrapperDiff>0&&(this.wrapperDiff=Math.pow(this.wrapperDiff,.8)),this.activeIndex===this.config.items.length-1&&this.wrapperDiff<0&&(this.wrapperDiff=-Math.pow(-this.wrapperDiff,.8)),this.wrapperTransform=this.wrapperLastTransform+this.wrapperDiff,this.doWrapperTransform();else{this.gestureImage;this.imageDiff={x:i.x-this.touchStart.x,y:i.y-this.touchStart.y},this.imageTransform={x:this.imageDiff.x+this.imageLastTransform.x,y:this.imageDiff.y+this.imageLastTransform.y},this.doImageTransform(),this.breakpointPosition=i,this.imageLastDiff=this.imageDiff}},onTouchEnd:function(e){if(!this.touching)return!1;if(this.touching=!1,this.scaling)return!1;var a=+new Date-this.touchStartTime;return a<200&&(!this.touchMove||Math.abs(this.touchStart.x-this.touchMove.x)<=2&&Math.abs(this.touchStart.y-this.touchMove.y)<=2)?void this.onClick():(this.wrapperDiff>0?this.wrapperDiff>this.containerWidth/2||this.wrapperDiff>20&&a<300?this.slidePrev():this.slideTo(this.activeIndex,200):-this.wrapperDiff>this.containerWidth/2||-this.wrapperDiff>20&&a<300?this.slideNext():this.slideTo(this.activeIndex,200),this.imageLastTransform=this.imageTransform,void this.adjust())},onClick:function(){var e=this;this._lastClickTime&&+new Date-this._lastClickTime<300?(this.onDoubleClick(),clearTimeout(this._clickTimeout)):this._clickTimeout=setTimeout(function(){e.close()},300),this._lastClickTime=+new Date},onDoubleClick:function(){this.gestureImage=this.container.find(".swiper-slide").eq(this.activeIndex).find("img"),this.currentScale=this.currentScale>1?1:2,this.doImageTransform(200),this.adjust()},onGestureStart:function(e){this.scaling=!0,this.gestureImage=this.container.find(".swiper-slide").eq(this.activeIndex).find("img")},onGestureChange:function(e){var a=this.lastScale*e.scale;a>this.config.maxScale?a=this.config.maxScale+Math.pow(a-this.config.maxScale,.5):a<1&&(a=Math.pow(a,.5)),this.currentScale=a,this.doImageTransform()},onGestureEnd:function(e){this.currentScale>this.config.maxScale?(this.currentScale=this.config.maxScale,this.doImageTransform(200)):this.currentScale<1&&(this.currentScale=1,this.doImageTransform(200)),this.lastScale=this.currentScale,this.scaling=!1,this.adjust()},doWrapperTransform:function(e,t){if(0===e){var i=this.wrapper.css("transition-property");this.wrapper.css("transition-property","none").transform("translate3d("+this.wrapperTransform+"px, 0, 0)"),this.wrapper.css("transition-property",i),t()}else this.wrapper.transitionEnd(function(){t&&t()}),this.wrapper.transition(e||a.duration).transform("translate3d("+this.wrapperTransform+"px, 0, 0)")},doImageTransform:function(e,a){this.gestureImage&&(this.gestureImage.transition(e||0).transform("translate3d("+this.imageTransform.x+"px,"+this.imageTransform.y+"px, 0) scale("+this.currentScale+")"),this._needAdjust=!0)},adjust:function(){if(!this._needAdjust)return!1;var e=this.gestureImage;if(!e)return!1;if(1===this.currentScale)return this.imageTransform=this.imageLastDiff={x:0,y:0},void this.doImageTransform(200);var a=e[0].getBoundingClientRect();a.height<this.containerHeight?this.imageTransform.y=this.imageLastTransform.y=0:a.top>0?this.imageTransform.y=this.imageTransform.y-a.top:a.bottom<this.containerHeight&&(this.imageTransform.y=this.imageTransform.y+this.containerHeight-a.bottom),this.doImageTransform(200),this._needAdjust=!1},slideTo:function(a,t){a<0&&(a=0),a>this.config.items.length-1&&(a=this.config.items.length-1),this.lastActiveIndex=this.activeIndex,this.activeIndex=a,this.wrapperTransform=-(a*this.containerWidth),this.wrapperLastTransform=this.wrapperTransform,this.doWrapperTransform(t,e.proxy(function(){return this.lastActiveIndex!==this.activeIndex&&(this.container.find(".caption-item.active").removeClass("active"),this.container.find(".swiper-slide-active").removeClass("swiper-slide-active"),this.container.find(".swiper-pagination-bullet-active").removeClass("swiper-pagination-bullet-active"),this.container.find(".caption-item").eq(this.activeIndex).addClass("active"),this.container.find(".swiper-slide").eq(this.activeIndex).addClass("swiper-slide-active"),this.container.find(".swiper-pagination-bullet").eq(this.activeIndex).addClass("swiper-pagination-bullet-active"),this.container.find(".swiper-slide img[style]").transition(0).transform("translate3d(0,0,0) scale(1)"),this.lastScale=1,this.currentScale=1,this.imageLastTransform={x:0,y:0},this.imageTransform={x:0,y:0},this.imageDiff={x:0,y:0},this.imageLastDiff={x:0,y:0},void(this.config.onSlideChange&&this.config.onSlideChange.call(this,this.activeIndex)))},this))},slideNext:function(){return this.slideTo(this.activeIndex+1,200)},slidePrev:function(){return this.slideTo(this.activeIndex-1,200)}},a=t.prototype.defaults={items:[],autoOpen:!1,onOpen:void 0,onClose:void 0,initIndex:0,maxScale:3,onSlideChange:void 0,duration:200,tpl:'<div class="weui-photo-browser-modal">            <div class="swiper-container">              <div class="swiper-wrapper">                {{#items}}                <div class="swiper-slide">                  <div class="photo-container">                    <img src="{{image}}" />                  </div>                </div>                {{/items}}              </div>              <div class="caption">                {{#items}}                <div class="caption-item caption-item-{{@index}}">{{caption}}</div>                {{/items}}              </div>              <div class="swiper-pagination swiper-pagination-bullets">                {{#items}}                <span class="swiper-pagination-bullet"></span>                {{/items}}              </div>            </div>          </div>'},e.photoBrowser=function(e){return new t(e)}}($);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/login.js b/platforms/android/app/src/main/assets/www/js/login.js
new file mode 100644
index 0000000..77b8b2a
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/login.js
@@ -0,0 +1,69 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        this.receivedEvent('deviceready');
+    },
+
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        var phone =  window.localStorage.getItem("phone");
+        if(!isEmpty(phone)){
+            $("#phone").val(phone)
+        }
+    },
+    toRegister :function(){
+        window.location = "register.html";
+    },
+    toForget :function(){
+        window.location = "findpwd.html";
+    },
+    login: function(){
+        //loading("正在处理");
+        var phone = $("#phone").val()
+        var pwd = $("#pwd").val()
+        if(isEmpty(phone)||isEmpty(pwd)){
+            return;
+        }
+        //loadingElement('loginBtn', '登录中...')
+        $.showLoading("登录中");
+        var param={
+            "username":phone,
+            "password":pwd
+        }
+        Login(param,function(ok,ret){
+            console.log(ret)
+            if(ok){
+               if(ret.code!=200){
+                 $.alert(ret.msg, "错误");
+                 //closeLoading('loginBtn')
+                 //showOk(ret.msg)
+                 $.hideLoading();
+               }else{
+                 window.localStorage.setItem("phone",phone); 
+                 window.localStorage.setItem("phoneX",ret.phone);
+                 window.localStorage.setItem("token",ret.token); 
+                 window.localStorage.setItem("tenantid",ret.tenantid); 
+                 window.localStorage.setItem("tokenexpire",ret.expire); 
+                 window.localStorage.setItem("tokentime",ret.now); 
+                 window.localStorage.setItem("userid",ret.userid);
+                 window.localStorage.setItem("signed",ret.signed); 
+                 window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                 window.localStorage.setItem("name",ret.name);  
+                 window.location = "main.html";  
+               }     
+            }else{
+               //$.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+               //closeLoading('loginBtn')
+               //showOk("请求失败了"+ret.status+",请稍后再试")
+               $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+               $.hideLoading();
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/main.js b/platforms/android/app/src/main/assets/www/js/main.js
new file mode 100644
index 0000000..a5b788d
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/main.js
@@ -0,0 +1,204 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        $('#scanBtn').click(function() {
+             window.location = "scan.html";
+            /*app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "scan.html";
+                })
+            })*/
+        });
+        $('#qrcodeBtn').click(function() {
+            app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "qrcode.html";
+                })
+            })
+        });
+        $('#cardBtn').click(function() {
+            app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "card.html";
+                })
+            })
+        });
+        $('#billBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "bill.html";
+            })
+        });
+        $('#moreBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "bill.html";
+            })
+        });
+        $('#secBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "security.html";
+            })
+        });
+        $('#usersec').click(function() {
+            app.checkBefore(function() {
+                window.location = "security.html";
+            })
+        });
+        this.initData();
+    },
+    initData: function() {
+        this.loadBill()
+        this.initView();
+    },
+    loadBill:function(){
+        $("#loaddata").show()
+        $("#nodata").hide();
+        var param={
+            "pageno":1
+        }
+        V1Bills(param,function(ok,ret){
+            if(ok){
+                console.log(ret)
+                if(ret.code==200){
+                    $("#maingt").text(ret.t+"!")
+                    $("#user-amount").text(ret.amount)
+                    $("#user-point").text(ret.point)
+                    if(ret.page&&ret.page.count>0){
+                        GLOBAL_TODAY = ret.today;
+                        GLOBAL_YESTERDAY = ret.yesterday;
+                        app.initBillView(ret.page)
+                    }else{
+                        $("#loaddata").hide()
+                        $("#nodatahint").text("暂无数据")
+                        $("#nodata").show(); 
+                    }    
+                }else{
+                    $("#loaddata").hide()
+                    $("#nodatahint").text("数据加载异常")
+                    $("#nodata").show(); 
+                }
+            }else{
+                $("#loaddata").hide()
+                $("#nodatahint").text("请求数据失败")
+                $("#nodata").show();
+            }            
+        })
+    },
+
+    initBillView:function(page){
+        var html ='';
+        for(var i=0;i<page.data.length;i++){
+            var bean=page.data[i]
+            html +='<div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail(\''+bean.refno+'\')">';
+            html +='<div class="aui-card-list-user-avatar"><img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />';
+            html +='</div><div class="aui-card-list-user-name">';
+            html +='<div>'+bean.transdesc+'</div>';
+            if(bean.tradeflag=='in'){
+                html +='<div class="aui-list-item-right">+'+bean.amount+'</div>';
+            }else{
+                html +='<div class="aui-list-item-right">'+bean.amount+'</div>';
+            }
+            html +='</div><div class="aui-card-list-user-info">'+formatDateNoYear(bean.transdate,bean.transtime)+'</div></div>';
+        }
+        $("#billcontent").html(html);
+        $("#loaddata").hide()
+        $("#nodata").hide(); 
+        $("#billcontent").show(); 
+    },
+    initView: function() {
+        var userid = window.localStorage.getItem("userid");
+        var signed = window.localStorage.getItem("signed");
+        if (isEmpty(userid)) {
+            $("#userbank").text("未绑定");
+            $("#userbank").css("color", "red")
+        } else {
+            $("#userbank").text("已绑定");
+            $("userbank").css("color", "#757575");
+        }
+        if (isEmpty(signed) || signed != 'yes') {
+            $("#usersign").text("未签约");
+            $("#usersign").css("color", "red")
+        } else {
+            $("#usersign").text("已签约");
+            $("usersign").css("color", "#757575");
+        }
+        var phone =  window.localStorage.getItem("phoneX");
+        if(!isEmpty(phone)){
+            $("#userphone").text(phone)
+        }
+        var name =  window.localStorage.getItem("name");
+        if(isEmpty(name)){
+            $("#username").text("匿名")
+        }else{
+            $("#username").text(name)
+            $("#homename").text(name)
+        }
+    },
+    checkBefore: function(callback) {
+        var uid = window.localStorage.getItem("token");
+        if (isEmpty(uid)) {
+            window.location = "login.html";
+        } else {
+            var userid = window.localStorage.getItem("userid");
+            if (isEmpty(userid)) {
+                var cum = new auiDialog({});
+                var confirm = cum.alert({
+                    title: "提示",
+                    msg: '为了不影响您正常使用相关功能,请先绑定银行卡',
+                    buttons: ['取消', '去绑卡']
+                }, function(ret) {
+                    if (ret.buttonIndex == 2) {
+                        window.location = 'bindcard.html'
+                    }
+                })
+            } else {
+                if (callback) {
+                    callback()
+                }
+            }
+        }
+    },
+    checkOther: function(callback) {
+        var payseted = window.localStorage.getItem("paypwdset");
+        var signed = window.localStorage.getItem("signed");
+        var cum = new auiDialog({});
+        console.log(payseted, signed)
+        if (isEmpty(payseted) || !payseted || payseted != 'true') {
+            var confirm = cum.alert({
+                title: "提示",
+                msg: '您还没有设置支付密码,无法使用该功能',
+                buttons: ['取消', '去设置']
+            }, function(ret) {
+                if (ret.buttonIndex == 2) {
+                    window.location = 'paypwdset.html'
+                }
+            })
+        } else {
+            if (isEmpty(signed) || signed != 'yes') {
+                var confirm = cum.alert({
+                    title: "提示",
+                    msg: '您尚未签约代扣免密付协议,无法使用该功能',
+                    buttons: ['取消', '去签约']
+                }, function(ret) {
+                    if (ret.buttonIndex == 2) {
+                        window.location = 'signxy.html'
+                    }
+                })
+            } else {
+                if (callback) {
+                    callback()
+                }
+            }
+        }
+    },
+    toBillDetail: function(refno) {
+        window.localStorage.setItem("currentrefno",refno);
+        window.location='billdetail.html';
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/mobile.js b/platforms/android/app/src/main/assets/www/js/mobile.js
new file mode 100644
index 0000000..e5abfb7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/mobile.js
@@ -0,0 +1,19 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        this.receivedEvent('deviceready');
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/paypwdset.js b/platforms/android/app/src/main/assets/www/js/paypwdset.js
new file mode 100644
index 0000000..0fc1c95
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/paypwdset.js
@@ -0,0 +1,63 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doNext: function() {
+        var pwd =  $("#pwd").val();
+        var repwd =  $("#repwd").val();
+        if(isEmpty(pwd)||isEmpty(repwd)){
+            return;
+        }
+        if(pwd.length!=6){
+            $.alert("支付密码为6位数字", "提示");
+            return;
+        }
+        if(pwd!=repwd){
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        var paypwdtype = window.localStorage.getItem("paypwdtype"); 
+        if(isEmpty(paypwdtype)){
+            paypwdtype = "new"
+        }
+        var randomcode = window.localStorage.getItem("randomcode"); 
+        if(isEmpty(randomcode)){
+            randomcode = ""
+        }
+        $.showLoading("正在保存");
+        var param={
+            "pwd":pwd,
+            "repwd":repwd,
+            "type":paypwdtype,
+            "randcode":randomcode
+        }
+        V1Paypwd(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                     window.localStorage.removeItem("randomcode"); 
+                     var signed = window.localStorage.getItem("signed"); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     if(isEmpty(signed)||signed!='yes'){
+                        window.location='signxy.html'   
+                     }else{
+                        window.location='main.html'   
+                     }
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/pwdset.js b/platforms/android/app/src/main/assets/www/js/pwdset.js
new file mode 100644
index 0000000..e8086a5
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/pwdset.js
@@ -0,0 +1,62 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doRegister: function() {
+        var pwd =  $("#pwd").val();
+        var repwd =  $("#repwd").val();
+        if(isEmpty(pwd)||isEmpty(repwd)){
+            return;
+        }
+        if(pwd.length<6){
+            $.alert("密码至少6位以上字符", "提示");
+            return;
+        }
+        if(pwd!=repwd){
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        var uid = window.localStorage.getItem("uid"); 
+        var code = window.localStorage.getItem("code"); 
+        $.showLoading("正在保存");
+        var param={
+            "pwd":pwd,
+            "repwd":repwd,
+            "id":uid,
+            "random":code
+        }
+        console.log(param)
+        IRegister(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                     window.localStorage.removeItem("code"); 
+                     window.localStorage.setItem("phoneX",ret.phone);
+                     window.localStorage.setItem("token",ret.token); 
+                     window.localStorage.setItem("userid",ret.userid); 
+                     window.localStorage.setItem("tenantid",ret.tenantid); 
+                     window.localStorage.setItem("tokenexpire",ret.expire); 
+                     window.localStorage.setItem("tokentime",ret.now);   
+                     window.localStorage.setItem("signed",ret.signed); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     $.alert("密码设置成功,您可以登录系统了", "提示", function() {
+                         window.location = "main.html"; 
+                      });
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/qrcode.js b/platforms/android/app/src/main/assets/www/js/qrcode.js
new file mode 100644
index 0000000..35fe7a3
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/qrcode.js
@@ -0,0 +1,23 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        var qrcode = new QRCode(document.getElementById("qrcode"), {
+          text: uid,
+          width: 150,
+          height: 150,
+          colorDark : "#000000",
+          colorLight : "#ffffff",
+          correctLevel : QRCode.CorrectLevel.L
+      });
+    },
+    toBillDetail :function(refno){
+        
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/register.js b/platforms/android/app/src/main/assets/www/js/register.js
new file mode 100644
index 0000000..e0214ab
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/register.js
@@ -0,0 +1,77 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doRegister: function() {
+        var phone =  $("#phone").val();
+        var code =  $("#code").val();
+        if(isEmpty(phone)||isEmpty(code)){
+            return;
+        }
+        var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意用户协议与隐私条款", "提示");
+            return;
+        }
+        $.showLoading("正在处理");
+        var param={
+            "phone":phone,
+            "code":code,
+            "platform":device.name+","+device.platform+","+device.version,
+            "uuid":device.uuid
+        }
+        console.log(param)
+        ICheckCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                console.log(ret)
+                if(ret.code==200){
+                     
+                     window.localStorage.setItem("phone",phone); 
+                     window.localStorage.setItem("uid",ret.uid); 
+                     window.localStorage.setItem("code",ret.randcode); 
+                     window.localStorage.removeItem("name"); 
+                     window.location="pwdset.html";
+                }else{
+                     $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        var phone =  $("#phone").val();
+        if(isEmpty(phone)){
+            return;            
+        }
+        $.showLoading("请求中");
+        var param={
+            "phone":phone
+        }
+        IGetCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/scan.js b/platforms/android/app/src/main/assets/www/js/scan.js
new file mode 100644
index 0000000..07a89fc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/scan.js
@@ -0,0 +1,159 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        console.log(2);
+        if (typeof(QRScanner) != 'undefined') {
+            //初始化检测,申请摄像头等权限
+            console.log(1);
+            QRScanner.destroy();
+            QRScanner.prepare(onDone); // show the prompt
+        } else {
+            $.alert('插件加载失败');
+        }
+        function onDone(err, status) {
+            if (err) {
+                console.log(err);
+                $.alert('启动扫描出错:' + JSON.stringify(err), '提示');
+            }
+            if (status.authorized) {
+                //绑定扫描监听
+                // `QRScanner.cancelScan()` is called.
+                QRScanner.scan(displayContents);
+                function displayContents(err, text) {
+                    if (err) {
+                        // an error occurred, or the scan was canceled (error code `6`)
+                        $.alert('扫描出错,请稍后再试:' + JSON.stringify(err), '提示');
+                    } else {
+                        // The scan completed, display the contents of the QR code:
+                        //$.alert(text, '提示');
+                        showRet(text)
+                    }
+                }
+                //开始扫描,需要将页面的背景设置成透明
+                QRScanner.show();
+                console.log("QRScanner.scan");   
+            } else if (status.denied) {
+                // The video preview will remain black, and scanning is disabled. We can
+                // try to ask the user to change their mind, but we'll have to send them
+                // to their device settings with `QRScanner.openSettings()`.
+               $.alert('无法请求道相机权限,请在设置中开启', '提示');
+            } else {
+                // we didn't get permission, but we didn't get permanently denied. (On
+                // Android, a denial isn't permanent unless the user checks the "Don't
+                // ask again" box.) We can ask again at the next relevant opportunity.
+                $.alert('无法请求道相机权限,请在设置中开启', '提示');
+            }
+        }
+        this.receivedEvent()
+    },
+    receivedEvent: function() {
+        var light = false;
+        $('#lightBtn').click(function () {
+            if (light) {
+                QRScanner.enableLight();
+            } else {
+                QRScanner.disableLight();
+            }
+            light = !light;
+        });
+    },
+    goPage:function(){
+        QRScanner.destroy();
+        window.location="main.html"
+    }
+};
+app.initialize();
+var inAppBrowserRef;
+
+function showRet(url) {
+
+    var target = "_blank";
+
+    var options = "location=yes,hidden=yes,beforeload=yes";
+
+    inAppBrowserRef = cordova.InAppBrowser.open(url, target, options);
+
+    inAppBrowserRef.addEventListener('loadstart', loadStartCallBack);
+
+    inAppBrowserRef.addEventListener('loadstop', loadStopCallBack);
+
+    inAppBrowserRef.addEventListener('loaderror', loadErrorCallBack);
+
+    inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
+
+    inAppBrowserRef.addEventListener('message', messageCallBack);
+}
+function loadStartCallBack() {
+
+    $('#status-message').text("loading please wait ...");
+
+}
+
+function loadStopCallBack() {
+
+    if (inAppBrowserRef != undefined) {
+
+        inAppBrowserRef.insertCSS({ code: "body{font-size: 25px;" });
+
+        inAppBrowserRef.executeScript({ code: "\
+            var message = 'this is the message';\
+            var messageObj = {my_message: message};\
+            var stringifiedMessageObj = JSON.stringify(messageObj);\
+            webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj);"
+        });
+
+        $('#status-message').text("");
+
+        inAppBrowserRef.show();
+    }
+
+}
+
+function loadErrorCallBack(params) {
+
+    $('#status-message').text("");
+
+    var scriptErrorMesssage =
+       "alert('Sorry we cannot open that page. Message from the server is : "
+       + params.message + "');"
+
+    inAppBrowserRef.executeScript({ code: scriptErrorMesssage }, executeScriptCallBack);
+
+    inAppBrowserRef.close();
+
+    inAppBrowserRef = undefined;
+
+}
+
+function executeScriptCallBack(params) {
+
+    if (params[0] == null) {
+
+        $('#status-message').text(
+           "Sorry we couldn't open that page. Message from the server is : '"
+           + params.message + "'");
+    }
+
+}
+
+function beforeloadCallBack(params, callback) {
+
+    if (params.url.startsWith("http://www.example.com/")) {
+
+        // Load this URL in the inAppBrowser.
+        callback(params.url);
+    } else {
+
+        // The callback is not invoked, so the page will not be loaded.
+        $('#status-message').text("This browser only opens pages on http://www.example.com/");
+    }
+}
+
+function messageCallBack(params){
+    $('#status-message').text("message received: "+params.data.my_message);
+}
diff --git a/platforms/android/app/src/main/assets/www/js/security.js b/platforms/android/app/src/main/assets/www/js/security.js
new file mode 100644
index 0000000..441d577
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/security.js
@@ -0,0 +1,17 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        var phone =  window.localStorage.getItem("phoneX");
+        
+    },
+    doNext: function() {
+       
+    }
+};
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/server.js b/platforms/android/app/src/main/assets/www/js/server.js
new file mode 100644
index 0000000..96d5023
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/server.js
@@ -0,0 +1,290 @@
+var dev = true;
+var SERVER = "";
+var GLOBAL_TODAY="";
+var GLOBAL_YESTERDAY="";
+if (dev) {
+    SERVER = "http://172.28.43.3:8099/payapi/mobileapi";
+}
+
+function V1Billdetail(param,callback) {
+    ajaxPost("/v1/billdetail", param, callback)
+}
+
+function V1Bills(param,callback) {
+    ajaxPost("/v1/bills", param, callback)
+}
+
+function V1CardLost(param,callback) {
+    ajaxPost("/v1/cardlost", param, callback)
+}
+
+function V1Signbxy(param,callback) {
+    ajaxPost("/v1/signbxy", param, callback)
+}
+
+function V1Bxy(callback) {
+    ajaxPost("/v1/bxy", {}, callback)
+}
+
+function V1Paypwd(param,callback) {
+    ajaxPost("/v1/paypwd", param, callback)
+}
+function V1Code(callback) {
+    ajaxPost("/v1/code", {}, callback)
+}
+function V1Checkcode(param,callback) {
+    ajaxPost("/v1/checkcode", param, callback)
+}
+
+function V1Bindcard(param,callback) {
+    ajaxPost("/v1/bindcard", param, callback)
+}
+
+function V1Infor(callback) {
+    ajaxPost("/v1/infor", {}, callback)
+}
+
+function IRegister(param,callback) {
+    ajaxPost("/i/register", param, callback)
+}
+
+function ICheckCode(param,callback) {
+    ajaxPost("/i/checkcode", param, callback)
+}
+
+function IGetPage(callback) {
+    ajaxPost("/i/uxy", {}, callback)
+}
+
+function IGetCode(param,callback) {
+    ajaxPost("/i/code", param, callback)
+}
+
+
+function IServeTime(callback) {
+    ajaxPost("/i/time", {}, callback)
+}
+
+function Login(param, callback) {
+    ajaxPost("/login", param, callback)
+}
+
+function ajaxGet(url, callback) {
+    var token = window.localStorage.getItem("token");
+    var tenantid = window.localStorage.getItem("tenantid");
+    $.ajax({
+        url: SERVER + url,
+        type: "GET",
+        dataType: "json",
+        headers: hd,
+        crossDomain: true,
+        success: function(result) {
+            if (callback) {
+                callback(true, result)
+            }
+        },
+        error: function(status, err) {
+            if (callback) {
+                callback(false, status)
+            }
+        }
+    });
+}
+
+function ajaxPost(url, param, callback) {
+    var token = window.localStorage.getItem("token");
+    var tenantid = window.localStorage.getItem("tenantid");
+    var hd = {};
+    hd["Authorization"] = "Bearer " + token;
+    hd["X-TENANT-ID"] = tenantid;
+    console.log(param)
+    $.ajax({
+        url: SERVER + url,
+        type: "POST",
+        contentType: "application/x-www-form-urlencoded",
+        dataType: "json",
+        data: param,
+        crossDomain: true,
+        timeout: 5000,
+        headers: hd,
+        success: function(result) {
+            if (callback) {
+                callback(true, result)
+            }
+        },
+        error: function(status, err) {
+            console.log(status,err)
+            if (status && status.status == 401) {
+                window.location = "login.html";
+            } else {
+                if (callback) {
+                    callback(false, status, err)
+                }
+            }
+        }
+    });
+}
+
+
+function formatDateShort(date) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
+}
+
+function formatDate(date, flag) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6);
+    }
+    if (date.length < 12) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
+    }
+    if (flag || date.length < 14) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12) + ":" + date.substring(12, 14);
+}
+function formatDateNoYear(date,time) {
+    if (isEmpty(date)) {
+        return date;
+    }
+    if(isEmpty(time)){
+        return date;
+    }
+    if (date.length < 8||time.length<4) {
+        return date;
+    }
+    if(!isEmpty(GLOBAL_TODAY)){
+        if(date==GLOBAL_TODAY){
+            return "今天 "+time.substring(0,2)+":"+time.substring(2,4)
+        }
+    }else if(!isEmpty(GLOBAL_YESTERDAY)){
+        if(date==GLOBAL_YESTERDAY){
+            return "昨天 "+time.substring(0,2)+":"+time.substring(2,4)
+        }
+    }
+    return date.substring(4, 6) + "-" + date.substring(6, 8) + " " +time.substring(0,2)+":"+time.substring(2,4)
+}
+
+function formateDateZH(date) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "年" + date.substring(4, 6) + "月";
+    }
+    if (date.length < 12) {
+        return date.substring(0, 4) + "年" + date.substring(4, 6) + "月" + date.substring(6, 8) + "日";
+    }
+    if (date.length < 14) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12) + ":" + date.substring(12, 14);
+}
+
+function isNull(data) {
+    return (data == "" || data == undefined || data == null) ? true : false;
+}
+
+function checkMobile(sMobile) {
+    if (!(/^1[3|4|5|7|8|9][0-9]{9}$/.test(sMobile))) {
+        return false;
+    }
+    return true;
+}
+
+function isEmpty(str) {
+    if (!str || str == 'undefined' || str == null || str == '') {
+        return true;
+    }
+    return false;
+}
+
+function timeText(stime, t) {
+    var temp = parseInt((stime - t) / 1000);
+    if (temp <= 30) {
+        return '刚刚';
+    }
+    if (temp < 60) {
+        return temp + '秒钟前';
+    }
+    temp = parseInt(temp / 60);
+    if (temp < 60) {
+        return temp + '分钟前';
+    }
+    temp = parseInt(temp / 60);
+    if (temp < 24) {
+        return temp + '小时前';
+    }
+    temp = parseInt(temp / 24);
+    if (temp < 30) {
+        return temp + '天前';
+    }
+    temp = parseInt(temp / 30);
+    if (temp < 12) {
+        return temp + '个月前';
+    }
+    temp = parseInt(temp / 12);
+    return temp + '年前';
+}
+
+function trimTxt(str) {
+    if (isEmpty(str)) {
+        return '';
+    }
+    return str;
+}
+var wait=60;
+function btnTime(id) {
+    if (wait == 0) {
+        $("#"+id).removeAttr("disabled");      
+        $("#"+id).removeClass("vcodedisabled")    
+        $("#"+id).text("获取验证码");
+        wait = 60;
+    } else {
+        $("#"+id).attr("disabled", "disabled");
+        $("#"+id).text(wait + "s");
+        wait--;
+        setTimeout(function() {
+            btnTime(id)
+        },
+        1000)
+    }
+}
+var dialog;
+function showOk(m,callback){
+    if(!dialog||dialog==null){
+        dialog = new auiDialog({});
+    }
+    dialog.alert({
+        title:"提示",
+        msg:m,
+        buttons:['确定']
+    },function(ret){
+        if(callback){
+            callback(ret)
+        }
+    })
+}
+function alertError(msg){
+    $.alert(msg, "错误");
+}
+function alertOk(msg){
+    $.alert(msg, "提示");
+}
diff --git a/platforms/android/app/src/main/assets/www/js/signxy.js b/platforms/android/app/src/main/assets/www/js/signxy.js
new file mode 100644
index 0000000..b259a5b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/signxy.js
@@ -0,0 +1,52 @@
+var db = null;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        $.showLoading("加载中");
+        V1Bxy(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#content").html(ret.page);
+                    $("#btn").show();  
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("加载失败了:" + ret.status, "错误");
+            }
+        })
+    },
+    agreeXY:function(){
+        var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意签约代扣协议", "提示");
+            return;
+        }
+        $.showLoading("正在请求");
+        var param={
+            "agree":agree
+        }
+        V1Signbxy(param,function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    window.localStorage.setItem("signed",ret.signed); 
+                    window.location="main.html";
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/uxy.js b/platforms/android/app/src/main/assets/www/js/uxy.js
new file mode 100644
index 0000000..094b649
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/js/uxy.js
@@ -0,0 +1,30 @@
+var db = null;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        //$.showLoading("加载中");
+        IGetPage(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#content").html(ret.page)   
+                }else{
+                    /*$.alert(ret.msg, "错误", function() {
+                        window.location = "register.html";
+                    });*/
+                }
+            } else {
+                //$.hideLoading();
+                /*$.alert("加载失败了:" + ret.status, "错误", function() {
+                    window.location = "register.html";
+                });*/
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/login.html b/platforms/android/app/src/main/assets/www/login.html
new file mode 100644
index 0000000..60827f3
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/login.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/>
+    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+    <title>登录</title>
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css" />
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css" />
+    <link rel="stylesheet" type="text/css" href="css/aui.css" />
+    <link rel="stylesheet" type="text/css" href="css/index.css" />
+</head>
+<body>
+    <div class="login-top">
+        大理市民卡
+    </div>
+    <section class="aui-content" >
+       <ul class="aui-list aui-form-list">
+            <li class="aui-list-item" >
+                <div class="aui-list-item-inner" >
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-mobile" ></i>
+                    </div>
+                    <div class="aui-list-item-input">
+                        <input type="tel" pattern="[0-9]*" placeholder="请输入手机号" id="phone" maxlength="11">
+                    </div>
+                </div>
+            </li>
+            <li class="aui-list-item">
+                <div class="aui-list-item-inner" >
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-lock"></i>
+                    </div>
+                    <div class="aui-list-item-input">
+                        <input type="password"  placeholder="请输入登录密码"  id="pwd" >
+                    </div>
+                </div>
+            </li>
+        </ul>
+    </section>
+    <section class="aui-content-padded" style="margin-top: 30px;">
+        <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.login()">登录</div>
+    </section>
+    <section class="aui-content-padded" style="margin-top: 30px;">
+        <a class="aui-pull-left" href="findpwd.html" style="color: #666;">
+            忘记密码?
+        </a>
+        <a class="aui-pull-right" href="register.html" style="color: #666;">
+            新用户注册
+        </a>
+    </section>
+</body>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+
+</html>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/login1.html b/platforms/android/app/src/main/assets/www/login1.html
new file mode 100644
index 0000000..9f92162
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/login1.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>登录</title>
+</head>
+<body class="cover vertical-align-center align-center blend-soft-light" style="background: #49bce9;">
+    <div class="space"></div>
+    <div class="space"></div>
+    <div class="space"></div>
+    <h1 class="text-white" style="font-size: 35px;">大理市民卡</h1>
+    <div class="space"></div>
+    <div class="space"></div>
+    <div class="row">
+        <div class="col-90 col-center">
+            <div class="list no-border opacity-60 ">
+                <div class="item icon ion-android-phone-portrait border-white border-bottom text-white" style="display: flex;">
+                    <input class="placeholder-white text-white" type="number" style="font-size: 18px;" placeholder="请输入手机号" id="phone" maxlength="11">
+                </div>
+                <div class="item icon ion-android-lock border-white border-bottom text-white" style="display: flex;margin-top: 10px;">
+                    <input class="placeholder-white text-white" type="password" style="font-size: 18px;" placeholder="请输入密码" id="pwd">
+                </div>
+            </div>
+            <div class="space"></div>
+            <div class="space"></div>
+            <button class="border-white text-white full radius" onclick="app.login()" id="loginBtn" style="font-size: 18px;">登录</button>
+            <div class="left" style="margin-top: 20px;font-size: 16px;" onclick="app.toForget()">忘记密码?</div>
+            <div class="right"  style="margin-top: 20px;font-size: 16px;" onclick="app.toRegister()"> 新用户注册</div>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+<script type="text/javascript">
+
+</script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/main.html b/platforms/android/app/src/main/assets/www/main.html
new file mode 100644
index 0000000..2cb4444
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/main.html
@@ -0,0 +1,276 @@
+<!doctype html>
+<html>
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
+    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+    <link rel="stylesheet" type="text/css" href="css/aui.css" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css" />
+</head>
+
+<body>
+    <div id="main1">
+        <div id="maintop">
+            <section class="aui-content " style="background-color: #03a9f4 !important;">
+                <h1 class="text-white align-left" style="font-size: 26px;color: #fff;padding: 30px 20px 0 20px;"><span id="maingt">您好!</span><span id="homename"></span></h1>
+                <div class="aui-grid aui-bg-info">
+                    <div class="aui-row" id="classify">
+                        <div class="aui-col-xs-6 top-btn" id="scanBtn">
+                            <div class="center-in"><img src="img/icon_scan.png" style="width:56px;"></div>
+                            <div class="aui-grid-label top-title">扫一扫</div>
+                        </div>
+                        <div class="aui-col-xs-6 top-btn" id="qrcodeBtn">
+                            <div class="center-in"><img src="img/icon_qrcode.png" style="width:56px;"></div>
+                            <div class="aui-grid-label top-title">付款码</div>
+                        </div>
+                    </div>
+                </div>
+            </section>
+            <section class="aui-content aui-margin-b-10">
+                <div class="aui-grid">
+                    <div class="aui-row">
+                        <div class="aui-col-xs-4" id="cardBtn">
+                            <div class="center-in"><img src="img/icon_card.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">市民卡挂失</div>
+                        </div>
+                        <div class="aui-col-xs-4" id="billBtn">
+                            <div class="center-in"><img src="img/icon_bill.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">账单查询</div>
+                        </div>
+                        <div class="aui-col-xs-4" id="secBtn">
+                            <div class="center-in"><img src="img/icon_securty.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">账户安全</div>
+                        </div>
+                    </div>
+                </div>
+            </section>
+            <div class="aui-card-list">
+                <div class="aui-card-list-header" style="border-bottom: 1px solid #f2f2f2">
+                    <div class="aui-font-size-14">近期交易</div>
+                    <div class="aui-list-item-right" style="font-size: 16px;color:#49bce9" id="moreBtn">更多></div>
+                </div>
+            </div>
+        </div>
+        <div style="position: absolute;top:320px;bottom:52px;width: 100%;overflow: auto;" id="maincontent">
+            <section class="aui-content">
+                <div class="weui-loadmore" id="loaddata">
+                    <i class="weui-loading"></i>
+                    <span class="weui-loadmore__tips">正在加载</span>
+                </div>
+                <div class="weui-loadmore weui-loadmore_line" id="nodata" style="display: none" onclick="app.loadBill()">
+                    <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无数据</span>
+                </div>
+                <div class="aui-card-list" id="billcontent" style="display: none">
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                   
+                </div>
+            </section>
+        </div>
+    </div>
+    <div id="main2" style="display: none;">
+        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+            我的
+        </header>
+        <section class="aui-content bg-white aui-margin-b-15" style=" margin-top: -2px;">
+            <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
+                <div class="aui-list-item aui-list-item-middle top-btn">
+                    <div class="aui-media-list-item-inner ">
+                        <div class="aui-list-item-media" style="width:3rem;">
+                            <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
+                        </div>
+                        <div class="aui-list-item-inner">
+                            <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
+                            <div class="aui-list-item-text text-white">
+                                <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <section class="aui-content aui-grid ">
+                <div class="aui-row aui-margin-t-10">
+                    <div class="aui-col-xs-4 aui-border-r">
+                        <big class="aui-text-warning" id="user-amount">0.00</big>
+                        <div class="aui-gird-lable aui-font-size-12">余额</div>
+                    </div>
+                    <div class="aui-col-xs-4 aui-border-r">
+                        <big class="aui-text-success" id="user-point">0</big>
+                        <div class="aui-gird-lable aui-font-size-12">积分</div>
+                    </div>
+                    <div class="aui-col-xs-4 ">
+                        <big class="aui-text-danger" id="user-coupon">0</big>
+                        <div class="aui-gird-lable aui-font-size-12">优惠券</div>
+                    </div>
+                </div>
+            </section>
+            
+        </section>
+        <section class="aui-content">
+            <ul class="aui-list aui-list-in aui-margin-b-15">
+                <li class="aui-list-item">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">银行卡</div>
+                        <div class="aui-list-item-right" id="userbank"></div>
+                    </div>
+                </li>
+                <li class="aui-list-item">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">签约代扣免密付</div>
+                        <div class="aui-list-item-right" id="usersign"></div>
+                    </div>
+                </li>
+            </ul>
+            <ul class="aui-list aui-list-in">
+                <li class="aui-list-item" id="usersec">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">账户安全</div>
+                    </div>
+                </li>
+            </ul>
+        </section>
+    </div>
+    <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
+        <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
+            <i class="aui-iconfont aui-icon-home"></i>
+            <div class="aui-bar-tab-label">首页</div>
+        </div>
+        <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
+            <i class="aui-iconfont aui-icon-my"></i>
+            <div class="aui-bar-tab-label">我的</div>
+        </div>
+    </footer>
+</body>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/aui-tab.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/main.js"></script>
+<script type="text/javascript">
+var tab = new auiTab({
+    element: document.getElementById("footer"),
+}, function(ret) {
+    console.log(ret)
+    if (ret.index == 1) {
+        $("#main1").show();
+        $("#main2").hide();
+    } else if (ret.index == 2) {
+        $("#main1").hide();
+        $("#main2").show();
+    }
+});
+$("#maincontent").css("top", $("#maintop").height())
+</script>
+
+</html>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/main1.html b/platforms/android/app/src/main/assets/www/main1.html
new file mode 100644
index 0000000..73db78e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/main1.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="mobileui/css/imports.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>大理市民卡</title>
+</head>
+
+<body class="has-footer">
+    <div class="footer  shadow white tab tab-bottom" style="border-top: 1px solid #F2F5F5">
+        <button class="icon ion-ios-home-outline active " style="color: #49bce9;" onclick="openTab('myTabAbout')">首页</button>
+        <button class="icon ion-ios-person-outline " style="color: #49bce9;" onclick="openTab('myTabEvents')">我的</button>
+    </div>
+    <div class="tab-content active" id="myTabAbout">
+        <div>
+            <div class="mainbg cover padding align-center" style="padding:32px 20px 20px 20px;">
+                <h1 class="text-white align-left" style="font-size: 26px;">下午好!乔伟</h1>
+                <div class="space"></div>
+                <div class="item no-border row align-center">
+                    <div class="col text-red" id="scanBtn">
+                        <img src="img/icon_scan.png" style="width:48px;">
+                        <h1 class="text-white" style="margin-top:5px;font-size: 18px;">扫一扫</h1>
+                    </div>
+                    <div class="col text-grey" id="qrcodeBtn" >
+                        <img src="img/icon_qrcode.png" style="width:48px;">
+                        <h1 class="text-white" style="margin-top:5px;font-size: 18px;">付款码</h1>
+                    </div>
+                </div>
+            </div>
+            <div class="cover padding align-center white">
+                <div class="item no-border row align-center">
+                    <div class="col text-grey" id="cardBtn">
+                        <img src="img/icon_card.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">市民卡挂失</h1>
+                    </div>
+                    <div class="col text-grey" id="billBtn">
+                        <img src="img/icon_bill.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">账单查询</h1>
+                    </div>
+                    <div class="col text-grey" id="secBtn">
+                        <img src="img/icon_securty.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">账户安全</h1>
+                    </div>
+                </div>
+            </div>
+            
+        </div>
+        <div class="content" style="top:280px;bottom:52px;">
+            <div class="list white" style="border:0;">
+                <div class="item">
+                    <h2>近期交易</h2>
+                    <div class="right" style="font-size: 16px;color:#49bce9" id="moreBtn">更多></div>
+                </div>
+            </div>
+            <div class="list white" style="margin-bottom: 6px;">
+                <div class="item" onclick="app.toBillDetail()">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_meal.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>食堂就餐</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">+ 1002.5</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item" style="padding:10px;">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_water.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>生活用水</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class=" text-strong">- 0.01</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_car.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>交通出行</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">-1.00</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_meal.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>食堂就餐</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">+ 1002.5</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="align-center" style="color: #999">
+                        暂无数据
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="tab-content" id="myTabEvents">
+        <div class="mainbg" style="height: 3.90625vh;width: 100%"></div>
+        <div class="header mainbg" style="top: 3.6vh">
+            <h1 class="align-center text-white">我的</h1>
+        </div>
+        <div style="padding-top: 48px;">
+            <div class="row padding mainbg">
+                <div class="col-25 padding">
+                    <img class="avatar circle" src="img/icon_card.png" />
+                </div>
+                <div class="col padding">
+                    <h1 class="text-big text-white">张三</h1>
+                    <p class="text-white">134****4553</p>
+                </div>
+            </div>
+            <div class="list white">
+                <div class="item">
+                    <h2>银行卡</h2>
+                    <div class="right">
+                        <small class="maincolor">已绑定</small><i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+                <div class="item">
+                    <h2>签约代扣免密付</h2>
+                    <div class="right">
+                        <small class="maincolor">已签约</small><i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+            </div>
+            <div class="list white" style="margin-top: 8px;">
+                <div class="item">
+                    <h2>账户安全</h2>
+                    <div class="right">
+                        <i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="mobileui/mobileui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="mobileui/js/button.min.js"></script>
+<script type="text/javascript" src="mobileui/js/loading.min.js"></script>
+<script type="text/javascript" src="mobileui/js/toast.min.js"></script>
+<script type="text/javascript" src="mobileui/js/tab.min.js"></script>
+<script type="text/javascript" src="mobileui/js/page.min.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+<script type="text/javascript">
+</script>
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/alert.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/alert.min.css
new file mode 100755
index 0000000..272cda2
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/alert.min.css
@@ -0,0 +1 @@
+.alert-mobileui{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;z-index:99999;}.alert-mobileui .alert{font-family:Roboto,Noto,sans-serif;-webkit-font-smoothing:antialiased;position:relative;border-radius:4px;box-shadow:0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12),0 8px 10px -5px rgba(0,0,0,.4);max-width:270px}.platform-ios .alert-mobileui .alert{font-family:-apple-system,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;border-radius:8px;background-color:#fff!important;box-shadow:none}.alert-mobileui .alert h1{text-align:left;font-size:20px;font-weight:500;padding:22px 22px 0 24px}.platform-ios .alert-mobileui .alert h1{font-size:17px;font-weight:500;text-align:center;color:#000!important;padding:0;padding-top:22px}.alert-mobileui .alert p{text-align:left;font-size:16px;font-weight:400;line-height:20px;padding:0 24px;margin-top:24px;margin-bottom:24px;min-height:0;opacity:.8}.platform-ios .alert-mobileui .alert p{font-size:14px;text-align:center;color:#000!important}.alert-mobileui .alert .buttons{display:inline-block;box-sizing:border-box;width:100%}.alert-mobileui .alert .buttons button{text-transform:uppercase;display:inline-block;width:auto;min-width:70px;float:right;background:0 0;border-top:none;font-size:14px;font-weight:600;outline:0;margin-right:5px;text-transform:uppercase}.platform-ios .alert-mobileui .alert .buttons button{width:100%;text-align:center;text-transform:none;font-weight:400;font-size:16px;border-top:1px solid #ddd;padding:0 8px;margin-right:0;color:rgba(24,103,194,.81)!important;background:0 0!important}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/base.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/base.min.css
new file mode 100755
index 0000000..17e3958
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/base.min.css
@@ -0,0 +1 @@
+*{-webkit-tap-highlight-color:transparent;margin:0;padding:0;box-sizing:border-box;outline:0}body{-webkit-touch-callout:none;-webkit-text-size-adjust:none;-webkit-user-select:none;background-color:#fff;font-size:14px;height:100%;margin:0;padding:0;width:100%}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}*{box-sizing:border-box;outline:0}body{font-family:Roboto,"Helvetica Neue",sans-serif;-webkit-overflow-scrolling:touch;overflow:hidden;position:absolute}body.platform-ios{font-family:-apple-system,"Helvetica Neue",Roboto,sans-serif}a{cursor:pointer;color:#000;text-decoration:none}.content{position:absolute;width:100%;overflow:auto}.left{float:left}.right{float:right}.top{position:absolute;top:0;left:0}.bottom{position:absolute;bottom:0;left:0}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.border{border-width:1px;border-style:solid}.hidden{display:none}.opacity-90{opacity:.9}.opacity-80{opacity:.8}.opacity-70{opacity:.7}.opacity-60{opacity:.6}.opacity-50{opacity:.5}.opacity-40{opacity:.4}.opacity-30{opacity:.3}.opacity-20{opacity:.2}.opacity-10{opacity:.1}.line{width:100%;height:1px;display:block;clear:both}.icon{font-size:28px}img,video{max-width:100%}p{margin-top:5px;margin-bottom:5px}.padding{padding:10px}.padding-top{padding-top:10px}.margin{margin:10px}span.padding{padding:6px;padding-top:2px;padding-bottom:2px}.radius{border-radius:4px}.radius-big{border-radius:22px}.circle{border-radius:50%}.radius-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.radius-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.radius-top{border-top-left-radius:4px;border-top-right-radius:4px}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shadow{box-shadow:1px 1px 3px rgba(0,0,0,.2)}.space{width:100%;height:20px}.space-big{width:100%;height:50px}.space-huge{width:100%;height:100px}.margin-bottom{margin-bottom:10px}.margin-top{margin-top:10px}.text-shadow{text-shadow:1px 1px 3px rgba(0,0,0,.2)}.text-small{font-size:14px}.text-small .icon,.text-small.icon{font-size:14px!important}.icon-small{font-size:14px!important}.icon-big{font-size:50px!important}.icon-huge{font-size:65px!important}.icon-extra-huge{font-size:120px!important}.text-big{font-size:22px}.text-big .icon,.text-big.icon{font-size:22px!important}.text-extra-huge{font-size:65px}.text-extra-huge .icon,.text-extra-huge.icon{font-size:65px!important}.text-huge{font-size:32px}.text-huge .icon,.text-huge.icon{font-size:32px!important}.text-light{font-weight:300}.text-bold{font-weight:700}.text-strong{font-weight:800}.float-bottom-right{position:fixed;right:15px;bottom:15px}.float-bottom-left{position:fixed;left:15px;bottom:15px}.float-bottom-center{position:fixed;margin:auto;left:0;bottom:15px}.icon-circle{width:40px;height:40px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small{width:25px;height:25px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small i{font-size:15px}.icon-circle-big{width:80px;height:80px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-big i{font-size:70px}.backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.01;z-index:9999;transition-duration:280ms}.backdrop.show{opacity:.4}.mark{border-left-width:8px!important}.red{color:rgba(255,255,255,.9);background-color:#f44336!important}.red-100,.red-200,.red-300,.red-50{color:rgba(0,0,0,.8)}.red-50,input[type=checkbox].red-50.switch::after{background-color:#ffebee!important}.red-100,input[type=checkbox].red-100.switch::after{background-color:#ffcdd2!important}.red-200,input[type=checkbox].red-200.switch::after{background-color:#ef9a9a!important}.red-300,input[type=checkbox].red-300.switch::after{background-color:#e57373!important}.pink,.red-400,.red-500,.red-600,.red-700,.red-800,.red-900{color:rgba(255,255,255,.9)}.red-400,input[type=checkbox].red-400.switch::after{background-color:#ef5350!important}.red-500,input[type=checkbox].red-500.switch::after{background-color:#f44336!important}.red-600,input[type=checkbox].red-600.switch::after{background-color:#e53935!important}.red-700,input[type=checkbox].red-700.switch::after{background-color:#d32f2f!important}.red-800,input[type=checkbox].red-800.switch::after{background-color:#c62828!important}.red-900,input[type=checkbox].red-900.switch::after{background-color:#b71c1c!important}.pink,input[type=checkbox].pink.switch::after{background-color:#e91e63!important}.pink-100,.pink-200,.pink-50{color:rgba(0,0,0,.8)}.pink-50,input[type=checkbox].pink-50.switch::after{background-color:#fce4ec!important}.pink-100,input[type=checkbox].pink-100.switch::after{background-color:#f8bbd0!important}.pink-200,input[type=checkbox].pink-200.switch::after{background-color:#f48fb1!important}.Pink-300,.pink-400,.pink-500,.pink-600,.pink-700,.pink-800,.pink-900,.purple{color:rgba(255,255,255,.9)}.Pink-300,input[type=checkbox].Pink-300.switch::after{background-color:#f06292!important}.pink-400,input[type=checkbox].pink-400.switch::after{background-color:#ec407a!important}.pink-500,input[type=checkbox].pink-500.switch::after{background-color:#e91e63!important}.pink-600,input[type=checkbox].pink-600.switch::after{background-color:#d81b60!important}.pink-700,input[type=checkbox].pink-700.switch::after{background-color:#c2185b!important}.pink-800,input[type=checkbox].pink-800.switch::after{background-color:#ad1457!important}.pink-900,input[type=checkbox].pink-900.switch::after{background-color:#880e4f!important}.purple,input[type=checkbox].purple.switch::after{background-color:#9c27b0!important}.purple-100,.purple-200,.purple-50{color:rgba(0,0,0,.8)}.purple-50,input[type=checkbox].purple-50.switch::after{background-color:#f3e5f5!important}.purple-100,input[type=checkbox].purple-100.switch::after{background-color:#e1bee7!important}.purple-200,input[type=checkbox].purple-200.switch::after{background-color:#ce93d8!important}.deep-purple,.purple-300,.purple-400,.purple-500,.purple-600,.purple-700,.purple-800,.purple-900{color:rgba(255,255,255,.9)}.purple-300,input[type=checkbox].purple-300.switch::after{background-color:#ba68c8!important}.purple-400,input[type=checkbox].purple-400.switch::after{background-color:#ab47bc!important}.purple-500,input[type=checkbox].purple-500.switch::after{background-color:#9c27b0!important}.purple-600,input[type=checkbox].purple-600.switch::after{background-color:#8e24aa!important}.purple-700,input[type=checkbox].purple-700.switch::after{background-color:#7b1fa2!important}.purple-800,input[type=checkbox].purple-800.switch::after{background-color:#6a1b9a!important}.purple-900,input[type=checkbox].purple-900.switch::after{background-color:#4a148c!important}.deep-purple,input[type=checkbox].deep-purple.switch::after{background-color:#673ab7!important}.deep-purple-50{color:rgba(0,0,0,.8);background-color:#ede7f6!important}.deep-purple-100{color:rgba(0,0,0,.8);background-color:#d1c4e9!important}.deep-purple-200{color:rgba(0,0,0,.8);background-color:#b39ddb!important}.deep-purple-300,.deep-purple-400,.deep-purple-500,.deep-purple-600,.deep-purple-700,.deep-purple-800,.deep-purple-900,.indigo{color:rgba(255,255,255,.9)}.deep-purple-300,input[type=checkbox].deep-purple-300.switch::after{background-color:#9575cd!important}.deep-purple-400,input[type=checkbox].deep-purple-400.switch::after{background-color:#7e57c2!important}.deep-purple-500,input[type=checkbox].deep-purple-500.switch::after{background-color:#673ab7!important}.deep-purple-600,input[type=checkbox].deep-purple-600.switch::after{background-color:#5e35b1!important}.deep-purple-700,input[type=checkbox].deep-purple-700.switch::after{background-color:#512da8!important}.deep-purple-800,input[type=checkbox].deep-purple-800.switch::after{background-color:#4527a0!important}.deep-purple-900,input[type=checkbox].deep-purple-900.switch::after{background-color:#311b92!important}.indigo,input[type=checkbox].indigo.switch::after{background-color:#3f51b5!important}.indigo-100,.indigo-200,.indigo-50{color:rgba(0,0,0,.8)}.indigo-50,input[type=checkbox].indigo-50.switch::after{background-color:#e8eaf6!important}.indigo-100,input[type=checkbox].indigo-100.switch::after{background-color:#c5cae9!important}.indigo-200,input[type=checkbox].indigo-200.switch::after{background-color:#9fa8da!important}.blue,.indigo-300,.indigo-400,.indigo-500,.indigo-600,.indigo-700,.indigo-800,.indigo-900{color:rgba(255,255,255,.9)}.indigo-300,input[type=checkbox].indigo-300.switch::after{background-color:#7986cb!important}.indigo-400,input[type=checkbox].indigo-400.switch::after{background-color:#5c6bc0!important}.indigo-500,input[type=checkbox].indigo-500.switch::after{background-color:#3f51b5!important}.indigo-600,input[type=checkbox].indigo-600.switch::after{background-color:#3949ab!important}.indigo-700,input[type=checkbox].indigo-700.switch::after{background-color:#303f9f!important}.indigo-800,input[type=checkbox].indigo-800.switch::after{background-color:#283593!important}.indigo-900,input[type=checkbox].indigo-900.switch::after{background-color:#1a237e!important}.blue,input[type=checkbox].blue.switch::after{background-color:#2196f3!important}.blue-100,.blue-200,.blue-300,.blue-400,.blue-50{color:rgba(0,0,0,.8)}.blue-50,input[type=checkbox].blue-50.switch::after{background-color:#e3f2fd!important}.blue-100,input[type=checkbox].blue-100.switch::after{background-color:#bbdefb!important}.blue-200,input[type=checkbox].blue-200.switch::after{background-color:#90caf9!important}.blue-300,input[type=checkbox].blue-300.switch::after{background-color:#64b5f6!important}.blue-400,input[type=checkbox].blue-400.switch::after{background-color:#42a5f5!important}.blue-500,.blue-600,.blue-700,.blue-800,.blue-900,.light-blue{color:rgba(255,255,255,.9)}.blue-500,input[type=checkbox].blue-500.switch::after{background-color:#2196f3!important}.blue-600,input[type=checkbox].blue-600.switch::after{background-color:#1e88e5!important}.blue-700,input[type=checkbox].blue-700.switch::after{background-color:#1976d2!important}.blue-800,input[type=checkbox].blue-800.switch::after{background-color:#1565c0!important}.blue-900,input[type=checkbox].blue-900.switch::after{background-color:#0d47a1!important}.light-blue,input[type=checkbox].light-blue.switch::after{background-color:#03a9f4!important}.light-blue-100,.light-blue-200,.light-blue-300,.light-blue-400,.light-blue-50,.light-blue-500{color:rgba(0,0,0,.8)}.light-blue-50,input[type=checkbox].light-blue-50.switch::after{background-color:#e1f5fe!important}.light-blue-100,input[type=checkbox].light-blue-100.switch::after{background-color:#b3e5fc!important}.light-blue-200,input[type=checkbox].light-blue-200.switch::after{background-color:#81d4fa!important}.light-blue-300,input[type=checkbox].light-blue-300.switch::after{background-color:#4fc3f7!important}.light-blue-400,input[type=checkbox].light-blue-400.switch::after{background-color:#29b6f6!important}.light-blue-500,input[type=checkbox].light-blue-500.switch::after{background-color:#03a9f4!important}.cyan,.light-blue-600,.light-blue-700,.light-blue-800,.light-blue-900{color:rgba(255,255,255,.9)}.light-blue-600,input[type=checkbox].light-blue-600.switch::after{background-color:#039be5!important}.light-blue-700,input[type=checkbox].light-blue-700.switch::after{background-color:#0288d1!important}.light-blue-800,input[type=checkbox].light-blue-800.switch::after{background-color:#0277bd!important}.light-blue-900,input[type=checkbox].light-blue-900.switch::after{background-color:#01579b!important}.cyan,input[type=checkbox].cyan.switch::after{background-color:#00bcd4!important}.cyan-100,.cyan-200,.cyan-300,.cyan-400,.cyan-50,.cyan-500,.cyan-600{color:rgba(0,0,0,.8)}.cyan-50,input[type=checkbox].cyan-50.switch::after{background-color:#e0f7fa!important}.cyan-100,input[type=checkbox].cyan-100.switch::after{background-color:#b2ebf2!important}.cyan-200,input[type=checkbox].cyan-200.switch::after{background-color:#80deea!important}.cyan-300,input[type=checkbox].cyan-300.switch::after{background-color:#4dd0e1!important}.cyan-400,input[type=checkbox].cyan-400.switch::after{background-color:#26c6da!important}.cyan-500,input[type=checkbox].cyan-500.switch::after{background-color:#00bcd4!important}.cyan-600,input[type=checkbox].cyan-600.switch::after{background-color:#00acc1!important}.cyan-700,.cyan-800,.cyan-900,.teal{color:rgba(255,255,255,.9)}.cyan-700,input[type=checkbox].cyan-700.switch::after{background-color:#0097a7!important}.cyan-800,input[type=checkbox].cyan-800.switch::after{background-color:#00838f!important}.cyan-900,input[type=checkbox].cyan-900.switch::after{background-color:#006064!important}.teal,input[type=checkbox].teal.switch::after{background-color:#009688!important}.teal-100,.teal-200,.teal-300,.teal-400,.teal-50{color:rgba(0,0,0,.8)}.teal-50,input[type=checkbox].teal-50.switch::after{background-color:#e0f2f1!important}.teal-100,input[type=checkbox].teal-100.switch::after{background-color:#b2dfdb!important}.teal-200,input[type=checkbox].teal-200.switch::after{background-color:#80cbc4!important}.teal-300,input[type=checkbox].teal-300.switch::after{background-color:#4db6ac!important}.teal-400,input[type=checkbox].teal-400.switch::after{background-color:#26a69a!important}.green,.teal-500,.teal-600,.teal-700,.teal-800,.teal-900{color:rgba(255,255,255,.9)}.teal-500,input[type=checkbox].teal-500.switch::after{background-color:#009688!important}.teal-600,input[type=checkbox].teal-600.switch::after{background-color:#00897b!important}.teal-700,input[type=checkbox].teal-700.switch::after{background-color:#00796b!important}.teal-800,input[type=checkbox].teal-800.switch::after{background-color:#00695c!important}.teal-900,input[type=checkbox].teal-900.switch::after{background-color:#004d40!important}.green,input[type=checkbox].green.switch::after{background-color:#4caf50!important}.green-100,.green-200,.green-300,.green-400,.green-50,.green-500{color:rgba(0,0,0,.8)}.green-50,input[type=checkbox].green-50.switch::after{background-color:#e8f5e9!important}.green-100,input[type=checkbox].green-100.switch::after{background-color:#c8e6c9!important}.green-200,input[type=checkbox].green-200.switch::after{background-color:#a5d6a7!important}.green-300,input[type=checkbox].green-300.switch::after{background-color:#81c784!important}.green-400,input[type=checkbox].green-400.switch::after{background-color:#66bb6a!important}.green-500,input[type=checkbox].green-500.switch::after{background-color:#4caf50!important}.green-600,.green-700,.green-800,.green-900,.light-green{color:rgba(255,255,255,.9)}.green-600,input[type=checkbox].green-600.switch::after{background-color:#43a047!important}.green-700,input[type=checkbox].green-700.switch::after{background-color:#388e3c!important}.green-800,input[type=checkbox].green-800.switch::after{background-color:#2e7d32!important}.green-900,input[type=checkbox].green-900.switch::after{background-color:#1b5e20!important}.light-green,input[type=checkbox].light-green.switch::after{background-color:#8bc34a!important}.light-green-100,.light-green-200,.light-green-300,.light-green-400,.light-green-50,.light-green-500,.light-green-600{color:rgba(0,0,0,.8)}.light-green-50,input[type=checkbox].light-green-50.switch::after{background-color:#f1f8e9!important}.light-green-100,input[type=checkbox].light-green-100.switch::after{background-color:#dcedc8!important}.light-green-200,input[type=checkbox].light-green-200.switch::after{background-color:#c5e1a5!important}.light-green-300,input[type=checkbox].light-green-300.switch::after{background-color:#aed581!important}.light-green-400,input[type=checkbox].light-green-400.switch::after{background-color:#9ccc65!important}.light-green-500,input[type=checkbox].light-green-500.switch::after{background-color:#8bc34a!important}.light-green-600,input[type=checkbox].light-green-600.switch::after{background-color:#7cb342!important}.light-green-700,.light-green-800,.light-green-900,.lime{color:rgba(255,255,255,.9)}.light-green-700,input[type=checkbox].light-green-700.switch::after{background-color:#689f38!important}.light-green-800,input[type=checkbox].light-green-800.switch::after{background-color:#558b2f!important}.light-green-900,input[type=checkbox].light-green-900.switch::after{background-color:#33691e!important}.lime,input[type=checkbox].lime.switch::after{background-color:#cddc39!important}.lime-100,.lime-200,.lime-300,.lime-400,.lime-50,.lime-500,.lime-600,.lime-700,.lime-800{color:rgba(0,0,0,.8)}.lime-50,input[type=checkbox].lime-50.switch::after{background-color:#f9fbe7!important}.lime-100,input[type=checkbox].lime-100.switch::after{background-color:#f0f4c3!important}.lime-200,input[type=checkbox].lime-200.switch::after{background-color:#e6ee9c!important}.lime-300,input[type=checkbox].lime-300.switch::after{background-color:#dce775!important}.lime-400,input[type=checkbox].lime-400.switch::after{background-color:#d4e157!important}.lime-500,input[type=checkbox].lime-500.switch::after{background-color:#cddc39!important}.lime-600,input[type=checkbox].lime-600.switch::after{background-color:#c0ca33!important}.lime-700,input[type=checkbox].lime-700.switch::after{background-color:#afb42b!important}.lime-800,input[type=checkbox].lime-800.switch::after{background-color:#9e9d24!important}.lime-900,.yellow{color:rgba(255,255,255,.9)}.lime-900,input[type=checkbox].lime-900.switch::after{background-color:#827717!important}.yellow,input[type=checkbox].yellow.switch::after{background-color:#ffeb3b!important}.yellow-100,.yellow-200,.yellow-300,.yellow-50,.yellow-500,.yellow-600,.yellow-700,.yellow-800,.yellow-900{color:rgba(0,0,0,.8)}.yellow-50,input[type=checkbox].yellow-50.switch::after{background-color:#fffde7!important}.yellow-100,input[type=checkbox].yellow-100.switch::after{background-color:#fff9c4!important}.yellow-200,input[type=checkbox].yellow-200.switch::after{background-color:#fff59d!important}.yellow-300,input[type=checkbox].yellow-300.switch::after{background-color:#fff176!important}.yellow-400{color:rgba(0,0,0,.8);background-color:#ffee58!important}.yellow-500,input[type=checkbox].yellow-500.switch::after{background-color:#ffeb3b!important}.yellow-600,input[type=checkbox].yellow-600.switch::after{background-color:#fdd835!important}.yellow-700,input[type=checkbox].yellow-700.switch::after{background-color:#fbc02d!important}.yellow-800,input[type=checkbox].yellow-800.switch::after{background-color:#f9a825!important}.yellow-900,input[type=checkbox].yellow-900.switch::after{background-color:#f57f17!important}.amber{color:rgba(255,255,255,.9);background-color:#ffc107!important}.amber-100,.amber-200,.amber-300,.amber-50,.amber-500,.amber-600,.amber-700,.amber-800,.amber-900{color:rgba(0,0,0,.8)}.amber-50,input[type=checkbox].amber-50.switch::after{background-color:#fff8e1!important}.amber-100,input[type=checkbox].amber-100.switch::after{background-color:#ffecb3!important}.amber-200,input[type=checkbox].amber-200.switch::after{background-color:#ffe082!important}.amber-300,input[type=checkbox].amber-300.switch::after{background-color:#ffd54f!important}.amber-400{color:rgba(0,0,0,.8);background-color:#ffca28!important}.amber-500,input[type=checkbox].amber-500.switch::after{background-color:#ffc107!important}.amber-600,input[type=checkbox].amber-600.switch::after{background-color:#ffb300!important}.amber-700,input[type=checkbox].amber-700.switch::after{background-color:#ffa000!important}.amber-800,input[type=checkbox].amber-800.switch::after{background-color:#ff8f00!important}.amber-900,input[type=checkbox].amber-900.switch::after{background-color:#ff6f00!important}.orange{color:rgba(255,255,255,.9);background-color:#ff9800!important}.orange-100,.orange-200,.orange-300,.orange-400,.orange-50,.orange-500,.orange-600,.orange-700{color:rgba(0,0,0,.8)}.orange-50,input[type=checkbox].orange-50.switch::after{background-color:#fff3e0!important}.orange-100,input[type=checkbox].orange-100.switch::after{background-color:#ffe0b2!important}.orange-200,input[type=checkbox].orange-200.switch::after{background-color:#ffcc80!important}.orange-300,input[type=checkbox].orange-300.switch::after{background-color:#ffb74d!important}.orange-400,input[type=checkbox].orange-400.switch::after{background-color:#ffa726!important}.orange-500,input[type=checkbox].orange-500.switch::after{background-color:#ff9800!important}.orange-600,input[type=checkbox].orange-600.switch::after{background-color:#fb8c00!important}.orange-700,input[type=checkbox].orange-700.switch::after{background-color:#f57c00!important}.deep-orange,.orange-800,.orange-900{color:rgba(255,255,255,.9)}.orange-800,input[type=checkbox].orange-800.switch::after{background-color:#ef6c00!important}.orange-900,input[type=checkbox].orange-900.switch::after{background-color:#e65100!important}.deep-orange,input[type=checkbox].deep-orange.switch::after{background-color:#ff5722!important}.deep-orange-100,.deep-orange-200,.deep-orange-300,.deep-orange-400,.deep-orange-50{color:rgba(0,0,0,.8)}.deep-orange-50,input[type=checkbox].deep-orange-50.switch::after{background-color:#fbe9e7!important}.deep-orange-100,input[type=checkbox].deep-orange-100.switch::after{background-color:#ffccbc!important}.deep-orange-200,input[type=checkbox].deep-orange-200.switch::after{background-color:#ffab91!important}.deep-orange-300,input[type=checkbox].deep-orange-300.switch::after{background-color:#ff8a65!important}.deep-orange-400,input[type=checkbox].deep-orange-400.switch::after{background-color:#ff7043!important}.brown,.deep-orange-500,.deep-orange-600,.deep-orange-700,.deep-orange-800,.deep-orange-900{color:rgba(255,255,255,.9)}.deep-orange-500,input[type=checkbox].deep-orange-500.switch::after{background-color:#ff5722!important}.deep-orange-600,input[type=checkbox].deep-orange-600.switch::after{background-color:#f4511e!important}.deep-orange-700,input[type=checkbox].deep-orange-700.switch::after{background-color:#e64a19!important}.deep-orange-800,input[type=checkbox].deep-orange-800.switch::after{background-color:#d84315!important}.deep-orange-900,input[type=checkbox].deep-orange-900.switch::after{background-color:#bf360c!important}.brown,input[type=checkbox].brown.switch::after{background-color:#795548!important}.brown-100,.brown-200,.brown-50{color:rgba(0,0,0,.8)}.brown-50,input[type=checkbox].brown-50.switch::after{background-color:#efebe9!important}.brown-100,input[type=checkbox].brown-100.switch::after{background-color:#d7ccc8!important}.brown-200,input[type=checkbox].brown-200.switch::after{background-color:#bcaaa4!important}.brown-300,.brown-400,.brown-500,.brown-600,.brown-700,.brown-800,.brown-900,.grey{color:rgba(255,255,255,.9)}.brown-300,input[type=checkbox].brown-300.switch::after{background-color:#a1887f!important}.brown-400,input[type=checkbox].brown-400.switch::after{background-color:#8d6e63!important}.brown-500,input[type=checkbox].brown-500.switch::after{background-color:#795548!important}.brown-600,input[type=checkbox].brown-600.switch::after{background-color:#6d4c41!important}.brown-700,input[type=checkbox].brown-700.switch::after{background-color:#5d4037!important}.brown-800,input[type=checkbox].brown-800.switch::after{background-color:#4e342e!important}.brown-900,input[type=checkbox].brown-900.switch::after{background-color:#3e2723!important}.grey,input[type=checkbox].grey.switch::after{background-color:#9e9e9e!important}.grey-100,.grey-200,.grey-300,.grey-400,.grey-50,.grey-500{color:rgba(0,0,0,.8)}.grey-50,input[type=checkbox].grey-50.switch::after{background-color:#fafafa!important}.grey-100,input[type=checkbox].grey-100.switch::after{background-color:#f5f5f5!important}.grey-200,input[type=checkbox].grey-200.switch::after{background-color:#eee!important}.grey-300,input[type=checkbox].grey-300.switch::after{background-color:#e0e0e0!important}.grey-400,input[type=checkbox].grey-400.switch::after{background-color:#bdbdbd!important}.grey-500,input[type=checkbox].grey-500.switch::after{background-color:#9e9e9e!important}.blue-grey,.grey-600,.grey-700,.grey-800,.grey-900{color:rgba(255,255,255,.9)}.grey-600,input[type=checkbox].grey-600.switch::after{background-color:#757575!important}.grey-700,input[type=checkbox].grey-700.switch::after{background-color:#616161!important}.grey-800,input[type=checkbox].grey-800.switch::after{background-color:#424242!important}.grey-900,input[type=checkbox].grey-900.switch::after{background-color:#212121!important}.blue-grey,input[type=checkbox].blue-grey.switch::after{background-color:#607d8b!important}.blue-grey-100,.blue-grey-200,.blue-grey-300,.blue-grey-50{color:rgba(0,0,0,.8)}.blue-grey-50,input[type=checkbox].blue-grey-50.switch::after{background-color:#eceff1!important}.blue-grey-100,input[type=checkbox].blue-grey-100.switch::after{background-color:#cfd8dc!important}.blue-grey-200,input[type=checkbox].blue-grey-200.switch::after{background-color:#b0bec5!important}.blue-grey-300,input[type=checkbox].blue-grey-300.switch::after{background-color:#90a4ae!important}.black,.blue-grey-400,.blue-grey-500,.blue-grey-600,.blue-grey-700,.blue-grey-800,.blue-grey-900{color:rgba(255,255,255,.9)}.blue-grey-400,input[type=checkbox].blue-grey-400.switch::after{background-color:#78909c!important}.transparent{background-color:rgba(0,0,0,0)!important}.blue-grey-500,input[type=checkbox].blue-grey-500.switch::after{background-color:#607d8b!important}.blue-grey-600,input[type=checkbox].blue-grey-600.switch::after{background-color:#546e7a!important}.blue-grey-700,input[type=checkbox].blue-grey-700.switch::after{background-color:#455a64!important}.blue-grey-800,input[type=checkbox].blue-grey-800.switch::after{background-color:#37474f!important}.blue-grey-900,input[type=checkbox].blue-grey-900.switch::after{background-color:#263238!important}.black,input[type=checkbox].black.switch::after{background-color:#000!important}.black-opacity-90{background-color:rgba(0,0,0,.9)}.black-opacity-70{background-color:rgba(0,0,0,.7)}.black-opacity-50{background-color:rgba(0,0,0,.5)}.black-opacity-30{background-color:rgba(0,0,0,.3)}.black-opacity-10{background-color:rgba(0,0,0,.1)}.white{color:rgba(0,0,0,.8);background-color:#fff!important}.white-opacity-90{background-color:rgba(255,255,255,.9)}.white-opacity-70{background-color:rgba(255,255,255,.7)}.white-opacity-50{background-color:rgba(255,255,255,.5)}.white-opacity-30{background-color:rgba(255,255,255,.3)}.white-opacity-10{background-color:rgba(255,255,255,.1)}.text-red,i.red{color:#f44336}.text-red-50,i.red-50{color:#ffebee}.text-red-100,i.red-100{color:#ffcdd2}.text-red-200,i.red-200{color:#ef9a9a}.text-red-300,i.red-300{color:#e57373}.text-red-400,i.red-400{color:#ef5350}.text-red-500,i.red-500{color:#f44336}.text-red-600,i.red-600{color:#e53935}.text-red-700,i.red-700{color:#d32f2f}.text-red-800,i.red-800{color:#c62828}.text-red-900,i.red-900{color:#b71c1c}.text-pink,i.pink{color:#e91e63}.text-pink-50,i.pink-50{color:#fce4ec}.text-pink-100,i.pink-100{color:#f8bbd0}.text-pink-200,i.pink-200{color:#f48fb1}.text-Pink-300,i.Pink-300{color:#f06292}.text-pink-400,i.pink-400{color:#ec407a}.text-pink-500,i.pink-500{color:#e91e63}.text-pink-600,i.pink-600{color:#d81b60}.text-pink-700,i.pink-700{color:#c2185b}.text-pink-800,i.pink-800{color:#ad1457}.text-pink-900,i.pink-900{color:#880e4f}.text-purple,i.purple{color:#9c27b0}.text-purple-50,i.purple-50{color:#f3e5f5}.text-purple-100,i.purple-100{color:#e1bee7}.text-purple-200,i.purple-200{color:#ce93d8}.text-purple-300,i.purple-300{color:#ba68c8}.text-purple-400,i.purple-400{color:#ab47bc}.text-purple-500,i.purple-500{color:#9c27b0}.text-purple-600,i.purple-600{color:#8e24aa}.text-purple-700,i.purple-700{color:#7b1fa2}.text-purple-800,i.purple-800{color:#6a1b9a}.text-purple-900,i.purple-900{color:#4a148c}.text-deep-purple,i.deep-purple{color:#673ab7}.text-deep-purple-50,i.deep-purple-50{color:#ede7f6}.text-deep-purple-100,i.deep-purple-100{color:#d1c4e9}.text-deep-purple-200,i.deep-purple-200{color:#b39ddb}.text-deep-purple-300,i.deep-purple-300{color:#9575cd}.text-deep-purple-400,i.deep-purple-400{color:#7e57c2}.text-deep-purple-500,i.deep-purple-500{color:#673ab7}.text-deep-purple-600,i.deep-purple-600{color:#5e35b1}.text-deep-purple-700,i.deep-purple-700{color:#512da8}.text-deep-purple-800,i.deep-purple-800{color:#4527a0}.text-deep-purple-900,i.deep-purple-900{color:#311b92}.text-indigo,i.indigo{color:#3f51b5}.text-indigo-50,i.indigo-50{color:#e8eaf6}.text-indigo-100,i.indigo-100{color:#c5cae9}.text-indigo-200,i.indigo-200{color:#9fa8da}.text-indigo-300,i.indigo-300{color:#7986cb}.text-indigo-400,i.indigo-400{color:#5c6bc0}.text-indigo-500,i.indigo-500{color:#3f51b5}.text-indigo-600,i.indigo-600{color:#3949ab}.text-indigo-700,i.indigo-700{color:#303f9f}.text-indigo-800,i.indigo-800{color:#283593}.text-indigo-900,i.indigo-900{color:#1a237e}.text-blue,i.blue{color:#2196f3}.text-blue-50,i.blue-50{color:#e3f2fd}.text-blue-100,i.blue-100{color:#bbdefb}.text-blue-200,i.blue-200{color:#90caf9}.text-blue-300,i.blue-300{color:#64b5f6}.text-blue-400,i.blue-400{color:#42a5f5}.text-blue-500,i.blue-500{color:#2196f3}.text-blue-600,i.blue-600{color:#1e88e5}.text-blue-700,i.blue-700{color:#1976d2}.text-blue-800,i.blue-800{color:#1565c0}.text-blue-900,i.blue-900{color:#0d47a1}.text-light-blue,i.light-blue{color:#03a9f4}.text-light-blue-50,i.light-blue-50{color:#e1f5fe}.text-light-blue-100,i.light-blue-100{color:#b3e5fc}.text-light-blue-200,i.light-blue-200{color:#81d4fa}.text-light-blue-300,i.light-blue-300{color:#4fc3f7}.text-light-blue-400,i.light-blue-400{color:#29b6f6}.text-light-blue-500,i.light-blue-500{color:#03a9f4}.text-light-blue-600,i.light-blue-600{color:#039be5}.text-light-blue-700,i.light-blue-700{color:#0288d1}.text-light-blue-800,i.light-blue-800{color:#0277bd}.text-light-blue-900,i.light-blue-900{color:#01579b}.text-cyan,i.cyan{color:#00bcd4}.text-cyan-50,i.cyan-50{color:#e0f7fa}.text-cyan-100,i.cyan-100{color:#b2ebf2}.text-cyan-200,i.cyan-200{color:#80deea}.text-cyan-300,i.cyan-300{color:#4dd0e1}.text-cyan-400,i.cyan-400{color:#26c6da}.text-cyan-500,i.cyan-500{color:#00bcd4}.text-cyan-600,i.cyan-600{color:#00acc1}.text-cyan-700,i.cyan-700{color:#0097a7}.text-cyan-800,i.cyan-800{color:#00838f}.text-cyan-900,i.cyan-900{color:#006064}.text-teal,i.teal{color:#009688}.text-teal-50,i.teal-50{color:#e0f2f1}.text-teal-100,i.teal-100{color:#b2dfdb}.text-teal-200,i.teal-200{color:#80cbc4}.text-teal-300,i.teal-300{color:#4db6ac}.text-teal-400,i.teal-400{color:#26a69a}.text-teal-500,i.teal-500{color:#009688}.text-teal-600,i.teal-600{color:#00897b}.text-teal-700,i.teal-700{color:#00796b}.text-teal-800,i.teal-800{color:#00695c}.text-teal-900,i.teal-900{color:#004d40}.text-green,i.green{color:#4caf50}.text-green-50,i.green-50{color:#e8f5e9}.text-green-100,i.green-100{color:#c8e6c9}.text-green-200,i.green-200{color:#a5d6a7}.text-green-300,i.green-300{color:#81c784}.text-green-400,i.green-400{color:#66bb6a}.text-green-500,i.green-500{color:#4caf50}.text-green-600,i.green-600{color:#43a047}.text-green-700,i.green-700{color:#388e3c}.text-green-800,i.green-800{color:#2e7d32}.text-green-900,i.green-900{color:#1b5e20}.text-light-green,i.light-green{color:#8bc34a}.text-light-green-50,i.light-green-50{color:#f1f8e9}.text-light-green-100,i.light-green-100{color:#dcedc8}.text-light-green-200,i.light-green-200{color:#c5e1a5}.text-light-green-300,i.light-green-300{color:#aed581}.text-light-green-400,i.light-green-400{color:#9ccc65}.text-light-green-500,i.light-green-500{color:#8bc34a}.text-light-green-600,i.light-green-600{color:#7cb342}.text-light-green-700,i.light-green-700{color:#689f38}.text-light-green-800,i.light-green-800{color:#558b2f}.text-light-green-900,i.light-green-900{color:#33691e}.text-lime,i.lime{color:#cddc39}.text-lime-50,i.lime-50{color:#f9fbe7}.text-lime-100,i.lime-100{color:#f0f4c3}.text-lime-200,i.lime-200{color:#e6ee9c}.text-lime-300,i.lime-300{color:#dce775}.text-lime-400,i.lime-400{color:#d4e157}.text-lime-500,i.lime-500{color:#cddc39}.text-lime-600,i.lime-600{color:#c0ca33}.text-lime-700,i.lime-700{color:#afb42b}.text-lime-800,i.lime-800{color:#9e9d24}.text-lime-900,i.lime-900{color:#827717}.text-yellow,i.yellow{color:#ffeb3b}.text-yellow-50,i.yellow-50{color:#fffde7}.text-yellow-100,i.yellow-100{color:#fff9c4}.text-yellow-200,i.yellow-200{color:#fff59d}.text-yellow-300,i.yellow-300{color:#fff176}.text-yellow-400,i.yellow-400{color:#ffee58}.text-yellow-500,i.yellow-500{color:#ffeb3b}.text-yellow-600,i.yellow-600{color:#fdd835}.text-yellow-700,i.yellow-700{color:#fbc02d}.text-yellow-800,i.yellow-800{color:#f9a825}.text-yellow-900,i.yellow-900{color:#f57f17}.text-amber,i.amber{color:#ffc107}.text-amber-50,i.amber-50{color:#fff8e1}.text-amber-100,i.amber-100{color:#ffecb3}.text-amber-200,i.amber-200{color:#ffe082}.text-amber-300,i.amber-300{color:#ffd54f}.text-amber-400,i.amber-400{color:#ffca28}.text-amber-500,i.amber-500{color:#ffc107}.text-amber-600,i.amber-600{color:#ffb300}.text-amber-700,i.amber-700{color:#ffa000}.text-amber-800,i.amber-800{color:#ff8f00}.text-amber-900,i.amber-900{color:#ff6f00}.text-orange,i.orange{color:#ff9800}.text-orange-50,i.orange-50{color:#fff3e0}.text-orange-100,i.orange-100{color:#ffe0b2}.text-orange-200,i.orange-200{color:#ffcc80}.text-orange-300,i.orange-300{color:#ffb74d}.text-orange-400,i.orange-400{color:#ffa726}.text-orange-500,i.orange-500{color:#ff9800}.text-orange-600,i.orange-600{color:#fb8c00}.text-orange-700,i.orange-700{color:#f57c00}.text-orange-800,i.orange-800{color:#ef6c00}.text-orange-900,i.orange-900{color:#e65100}.text-deep-orange,i.deep-orange{color:#ff5722}.text-deep-orange-50,i.deep-orange-50{color:#fbe9e7}.text-deep-orange-100,i.deep-orange-100{color:#ffccbc}.text-deep-orange-200,i.deep-orange-200{color:#ffab91}.text-deep-orange-300,i.deep-orange-300{color:#ff8a65}.text-deep-orange-400,i.deep-orange-400{color:#ff7043}.text-deep-orange-500,i.deep-orange-500{color:#ff5722}.text-deep-orange-600,i.deep-orange-600{color:#f4511e}.text-deep-orange-700,i.deep-orange-700{color:#e64a19}.text-deep-orange-800,i.deep-orange-800{color:#d84315}.text-deep-orange-900,i.deep-orange-900{color:#bf360c}.text-brown,i.brown{color:#795548}.text-brown-50,i.brown-50{color:#efebe9}.text-brown-100,i.brown-100{color:#d7ccc8}.text-brown-200,i.brown-200{color:#bcaaa4}.text-brown-300,i.brown-300{color:#a1887f}.text-brown-400,i.brown-400{color:#8d6e63}.text-brown-500,i.brown-500{color:#795548}.text-brown-600,i.brown-600{color:#6d4c41}.text-brown-700,i.brown-700{color:#5d4037}.text-brown-800,i.brown-800{color:#4e342e}.text-brown-900,i.brown-900{color:#3e2723}.text-grey,i.grey{color:#9e9e9e}.text-grey-50,i.grey-50{color:#fafafa}.text-grey-100,i.grey-100{color:#f5f5f5}.text-grey-200,i.grey-200{color:#eee}.text-grey-300,i.grey-300{color:#e0e0e0}.text-grey-400,i.grey-400{color:#bdbdbd}.text-grey-500,i.grey-500{color:#9e9e9e}.text-grey-600,i.grey-600{color:#757575}.text-grey-700,i.grey-700{color:#616161}.text-grey-800,i.grey-800{color:#424242}.text-grey-900,i.grey-900{color:#212121}.text-blue-grey,i.blue-grey{color:#607d8b}.text-blue-grey-50,i.blue-grey-50{color:#eceff1}.text-blue-grey-100,i.blue-grey-100{color:#cfd8dc}.text-blue-grey-200,i.blue-grey-200{color:#b0bec5}.text-blue-grey-300,i.blue-grey-300{color:#90a4ae}.text-blue-grey-400,i.blue-grey-400{color:#78909c}.text-blue-grey-500,i.blue-grey-500{color:#607d8b}.text-blue-grey-600,i.blue-grey-600{color:#546e7a}.text-blue-grey-700,i.blue-grey-700{color:#455a64}.text-blue-grey-800,i.blue-grey-800{color:#37474f}.text-blue-grey-900,i.blue-grey-900{color:#263238}.text-black,i.black{color:#000}.text-white,i.white{color:#fff}.border-red{border:1px solid #f44336}.border-red-50{border:1px solid #ffebee}.border-red-100{border:1px solid #ffcdd2}.border-red-200{border:1px solid #ef9a9a}.border-red-300{border:1px solid #e57373}.border-red-400{border:1px solid #ef5350}.border-red-500{border:1px solid #f44336}.border-red-600{border:1px solid #e53935}.border-red-700{border:1px solid #d32f2f}.border-red-800{border:1px solid #c62828}.border-red-900{border:1px solid #b71c1c}.border-pink{border:1px solid #e91e63}.border-pink-50{border:1px solid #fce4ec}.border-pink-100{border:1px solid #f8bbd0}.border-pink-200{border:1px solid #f48fb1}.border-pink-300{border:1px solid #f06292}.border-pink-400{border:1px solid #ec407a}.border-pink-500{border:1px solid #e91e63}.border-pink-600{border:1px solid #d81b60}.border-pink-700{border:1px solid #c2185b}.border-pink-800{border:1px solid #ad1457}.border-pink-900{border:1px solid #880e4f}.border-purple{border:1px solid #9c27b0}.border-purple-50{border:1px solid #f3e5f5}.border-purple-100{border:1px solid #e1bee7}.border-purple-200{border:1px solid #ce93d8}.border-purple-300{border:1px solid #ba68c8}.border-purple-400{border:1px solid #ab47bc}.border-purple-500{border:1px solid #9c27b0}.border-purple-600{border:1px solid #8e24aa}.border-purple-700{border:1px solid #7b1fa2}.border-purple-800{border:1px solid #6a1b9a}.border-purple-900{border:1px solid #4a148c}.border-deep-purple{border:1px solid #673ab7}.border-deep-purple-50{border:1px solid #ede7f6}.border-deep-purple-100{border:1px solid #d1c4e9}.border-deep-purple-200{border:1px solid #b39ddb}.border-deep-purple-300{border:1px solid #9575cd}.border-deep-purple-400{border:1px solid #7e57c2}.border-deep-purple-500{border:1px solid #673ab7}.border-deep-purple-600{border:1px solid #5e35b1}.border-deep-purple-700{border:1px solid #512da8}.border-deep-purple-800{border:1px solid #4527a0}.border-deep-purple-900{border:1px solid #311b92}.border-indigo{border:1px solid #3f51b5}.border-indigo-50{border:1px solid #e8eaf6}.border-indigo-100{border:1px solid #c5cae9}.border-indigo-200{border:1px solid #9fa8da}.border-indigo-300{border:1px solid #7986cb}.border-indigo-400{border:1px solid #5c6bc0}.border-indigo-500{border:1px solid #3f51b5}.border-indigo-600{border:1px solid #3949ab}.border-indigo-700{border:1px solid #303f9f}.border-indigo-800{border:1px solid #283593}.border-indigo-900{border:1px solid #1a237e}.border-blue{border:1px solid #2196f3}.border-blue-50{border:1px solid #e3f2fd}.border-blue-100{border:1px solid #bbdefb}.border-blue-200{border:1px solid #90caf9}.border-blue-300{border:1px solid #64b5f6}.border-blue-400{border:1px solid #42a5f5}.border-blue-500{border:1px solid #2196f3}.border-blue-600{border:1px solid #1e88e5}.border-blue-700{border:1px solid #1976d2}.border-blue-800{border:1px solid #1565c0}.border-blue-900{border:1px solid #0d47a1}.border-light-blue{border:1px solid #03a9f4}.border-light-blue-50{border:1px solid #e1f5fe}.border-light-blue-100{border:1px solid #b3e5fc}.border-light-blue-200{border:1px solid #81d4fa}.border-light-blue-300{border:1px solid #4fc3f7}.border-light-blue-400{border:1px solid #29b6f6}.border-light-blue-500{border:1px solid #03a9f4}.border-light-blue-600{border:1px solid #039be5}.border-light-blue-700{border:1px solid #0288d1}.border-light-blue-800{border:1px solid #0277bd}.border-light-blue-900{border:1px solid #01579b}.border-cyan{border:1px solid #00bcd4}.border-cyan-50{border:1px solid #e0f7fa}.border-cyan-100{border:1px solid #b2ebf2}.border-cyan-200{border:1px solid #80deea}.border-cyan-300{border:1px solid #4dd0e1}.border-cyan-400{border:1px solid #26c6da}.border-cyan-500{border:1px solid #00bcd4}.border-cyan-600{border:1px solid #00acc1}.border-cyan-700{border:1px solid #0097a7}.border-cyan-800{border:1px solid #00838f}.border-cyan-900{border:1px solid #006064}.border-teal{border:1px solid #009688}.border-teal-50{border:1px solid #e0f2f1}.border-teal-100{border:1px solid #b2dfdb}.border-teal-200{border:1px solid #80cbc4}.border-teal-300{border:1px solid #4db6ac}.border-teal-400{border:1px solid #26a69a}.border-teal-500{border:1px solid #009688}.border-teal-600{border:1px solid #00897b}.border-teal-700{border:1px solid #00796b}.border-teal-800{border:1px solid #00695c}.border-teal-900{border:1px solid #004d40}.border-green{border:1px solid #4caf50}.border-green-50{border:1px solid #e8f5e9}.border-green-100{border:1px solid #c8e6c9}.border-green-200{border:1px solid #a5d6a7}.border-green-300{border:1px solid #81c784}.border-green-400{border:1px solid #66bb6a}.border-green-500{border:1px solid #4caf50}.border-green-600{border:1px solid #43a047}.border-green-700{border:1px solid #388e3c}.border-green-800{border:1px solid #2e7d32}.border-green-900{border:1px solid #1b5e20}.border-light-green{border:1px solid #8bc34a}.border-light-green-50{border:1px solid #f1f8e9}.border-light-green-100{border:1px solid #dcedc8}.border-light-green-200{border:1px solid #c5e1a5}.border-light-green-300{border:1px solid #aed581}.border-light-green-400{border:1px solid #9ccc65}.border-light-green-500{border:1px solid #8bc34a}.border-light-green-600{border:1px solid #7cb342}.border-light-green-700{border:1px solid #689f38}.border-light-green-800{border:1px solid #558b2f}.border-light-green-900{border:1px solid #33691e}.border-lime{border:1px solid #cddc39}.border-lime-50{border:1px solid #f9fbe7}.border-lime-100{border:1px solid #f0f4c3}.border-lime-200{border:1px solid #e6ee9c}.border-lime-300{border:1px solid #dce775}.border-lime-400{border:1px solid #d4e157}.border-lime-500{border:1px solid #cddc39}.border-lime-600{border:1px solid #c0ca33}.border-lime-700{border:1px solid #afb42b}.border-lime-800{border:1px solid #9e9d24}.border-lime-900{border:1px solid #827717}.border-yellow{border:1px solid #ffeb3b}.border-yellow-50{border:1px solid #fffde7}.border-yellow-100{border:1px solid #fff9c4}.border-yellow-200{border:1px solid #fff59d}.border-yellow-300{border:1px solid #fff176}.border-yellow-400{border:1px solid #ffee58}.border-yellow-500{border:1px solid #ffeb3b}.border-yellow-600{border:1px solid #fdd835}.border-yellow-700{border:1px solid #fbc02d}.border-yellow-800{border:1px solid #f9a825}.border-yellow-900{border:1px solid #f57f17}.border-amber{border:1px solid #ffc107}.border-amber-50{border:1px solid #fff8e1}.border-amber-100{border:1px solid #ffecb3}.border-amber-200{border:1px solid #ffe082}.border-amber-300{border:1px solid #ffd54f}.border-amber-400{border:1px solid #ffca28}.border-amber-500{border:1px solid #ffc107}.border-amber-600{border:1px solid #ffb300}.border-amber-700{border:1px solid #ffa000}.border-amber-800{border:1px solid #ff8f00}.border-amber-900{border:1px solid #ff6f00}.border-orange{border:1px solid #ff9800}.border-orange-50{border:1px solid #fff3e0}.border-orange-100{border:1px solid #ffe0b2}.border-orange-200{border:1px solid #ffcc80}.border-orange-300{border:1px solid #ffb74d}.border-orange-400{border:1px solid #ffa726}.border-orange-500{border:1px solid #ff9800}.border-orange-600{border:1px solid #fb8c00}.border-orange-700{border:1px solid #f57c00}.border-orange-800{border:1px solid #ef6c00}.border-orange-900{border:1px solid #e65100}.border-deep-orange{border:1px solid #ff5722}.border-deep-orange-50{border:1px solid #fbe9e7}.border-deep-orange-100{border:1px solid #ffccbc}.border-deep-orange-200{border:1px solid #ffab91}.border-deep-orange-300{border:1px solid #ff8a65}.border-deep-orange-400{border:1px solid #ff7043}.border-deep-orange-500{border:1px solid #ff5722}.border-deep-orange-600{border:1px solid #f4511e}.border-deep-orange-700{border:1px solid #e64a19}.border-deep-orange-800{border:1px solid #d84315}.border-deep-orange-900{border:1px solid #bf360c}.border-brown{border:1px solid #795548}.border-brown-50{border:1px solid #efebe9}.border-brown-100{border:1px solid #d7ccc8}.border-brown-200{border:1px solid #bcaaa4}.border-brown-300{border:1px solid #a1887f}.border-brown-400{border:1px solid #8d6e63}.border-brown-500{border:1px solid #795548}.border-brown-600{border:1px solid #6d4c41}.border-brown-700{border:1px solid #5d4037}.border-brown-800{border:1px solid #4e342e}.border-brown-900{border:1px solid #3e2723}.border-grey{border:1px solid #9e9e9e}.border-grey-50{border:1px solid #fafafa}.border-grey-100{border:1px solid #f5f5f5}.border-grey-200{border:1px solid #eee}.border-grey-300{border:1px solid #e0e0e0}.border-grey-400{border:1px solid #bdbdbd}.border-grey-500{border:1px solid #9e9e9e}.border-grey-600{border:1px solid #757575}.border-grey-700{border:1px solid #616161}.border-grey-800{border:1px solid #424242}.border-grey-900{border:1px solid #212121}.border-blue-grey{border:1px solid #607d8b}.border-blue-grey-50{border:1px solid #eceff1}.border-blue-grey-100{border:1px solid #cfd8dc}.border-blue-grey-200{border:1px solid #b0bec5}.border-blue-grey-300{border:1px solid #90a4ae}.border-blue-grey-400{border:1px solid #78909c}.border-blue-grey-500{border:1px solid #607d8b}.border-blue-grey-600{border:1px solid #546e7a}.border-blue-grey-700{border:1px solid #455a64}.border-blue-grey-800{border:1px solid #37474f}.border-blue-grey-900{border:1px solid #263238}.border-black{border:1px solid #000}.border-white{border:1px solid #fff}@font-face{font-family:Roboto;font-style:normal;font-weight:300;src:local('Roboto Light'),local('Roboto-Light'),url(fonts/robotolight.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:local('Roboto'),local('Roboto-Regular'),url(fonts/sTdaA6j0Psb920Vjv-mrzH-_kf6ByYO6CLYdB4HQE-Y.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:900;src:local('Roboto Black'),local('Roboto-Black'),url(fonts/robotoblack.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Ionicons;src:url(fonts/ionicons.woff?v=2.0.0) format("woff");font-weight:400;font-style:normal}i.icon{background:0 0!important}.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;min-width:22px;text-align:center}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/button.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/button.min.css
new file mode 100755
index 0000000..68b7f1b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/button.min.css
@@ -0,0 +1 @@
+button{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease;font-size:14px;border:none;background-color:rgba(0,0,0,0);color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-height:42px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer;overflow:hidden}button[disabled]{opacity:.8}button .icon{position:absolute;left:10px}button.circle{width:42px;height:42px;text-align:center;padding:0;line-height:0;font-size:22px;z-index:10}button.icon-text{padding-left:40px}button.icon-text i{font-size:22px}button.icon-text.icon-right{padding-left:12px;padding-right:40px;position:relative}button.icon-right i{position:absolute;right:12px;text-align:right;margin-top:2px}button[class*=border-]{min-height:40px;line-height:40px}button.full{width:100%}.buttons-group.big button,button.big{font-size:22px;min-height:50px;line-height:50px}button.circle.big{width:50px;height:50px;font-size:28px}button.big.icon-text{padding-left:40px}button.big.icon-text.icon-right{padding-left:12px;padding-right:40px}button.big.icon-text i{font-size:26px}.buttons-group.small button,button.small{font-size:12px;min-height:30px;line-height:30px}button.circle.small{width:30px;height:30px;font-size:18px}button.small.icon-text{padding-left:30px}button.small.icon-text.icon-right{padding-left:12px;padding-right:35px}button.small.icon-text i{font-size:18px}.buttons-group.huge button,button.huge{font-size:32px;min-height:70px;line-height:70px}button.circle.huge{width:70px;height:70px;font-size:32px}button.huge.icon-text{padding-left:40px}button.huge.icon-text.icon-right{padding-left:12px;padding-right:40px}button.huge.icon-text i{font-size:32px}.buttons-group{display:inline-block}.buttons-group button{float:left;margin-left:-1px}.buttons-group button:first-child{margin-left:0}.buttons-group.full{display:flex}.buttons-group.full button{flex:1}.ripple{position:absolute;background:rgba(255,255,255,.25);border-radius:100%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ripple.show{-webkit-animation:ripple .5s ease-out;-moz-animation:ripple .5s ease-out;-o-animation:ripple .5s ease-out;animation:ripple .5s ease-out}@-webkit-keyframes ripple{to{-webkit-transform:scale(1.5);opacity:0}}@-moz-keyframes ripple{to{-moz-transform:scale(1.5);opacity:0}}@-o-keyframes ripple{to{-o-transform:scale(1.5);opacity:0}}@keyframes ripple{to{transform:scale(1.5);opacity:0}}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/chart-bar.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/chart-bar.min.css
new file mode 100755
index 0000000..69d4056
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/chart-bar.min.css
@@ -0,0 +1 @@
+.chart-bar{display:table;table-layout:fixed;width:100%;height:250px;background-image:linear-gradient(to top,rgba(0,0,0,.1) 2%,rgba(0,0,0,0) 2%);background-size:100% 50px;background-position:left top}.chart-bar.line-white{background-image:linear-gradient(to top,rgba(255,255,255,.1) 2%,rgba(255,255,255,0) 2%)}.chart-bar.no-line{background-image:none}.chart-bar li{position:relative;display:table-cell;vertical-align:bottom;height:250px}.chart-bar li span{margin:0 5px;display:block}.chart-bar li div{width:100%;text-align:center;padding:5px}.chart-bar li span::before{position:relative;top:0;width:100%;padding-top:5px;padding-bottom:5px;display:block;text-align:center;content:attr(title);word-wrap:break-word;overflow:hidden;opacity:.7}.chart-bar.size-1{width:80px}.chart-bar.size-1,.chart-bar.size-1 li{height:40px}.chart-bar.size-1 li span{margin:0 2px}.chart-bar.size-2{width:150px}.chart-bar.size-2,.chart-bar.size-2 li{height:60px}.chart-bar.size-2 li span{margin:0 4px}.chart-bar.size-3{width:250px}.chart-bar.size-3,.chart-bar.size-3 li{height:80px}.chart-bar.size-3 li span{margin:0 5px}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/chartist-plugin-tooltip.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/chartist-plugin-tooltip.min.css
new file mode 100755
index 0000000..3d4a9ac
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/chartist-plugin-tooltip.min.css
@@ -0,0 +1 @@
+.chartist-tooltip{position:absolute;display:inline-block;opacity:0;min-width:5em;padding:.5em;background:#f4c63d;color:#453d3f;font-family:Oxygen,Helvetica,Arial,sans-serif;font-weight:700;text-align:center;pointer-events:none;z-index:1;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.chartist-tooltip:before{content:"";position:absolute;top:100%;left:50%;width:0;height:0;margin-left:-15px;border:15px solid transparent;border-top-color:#f4c63d}.chartist-tooltip.tooltip-show{opacity:1}.ct-area,.ct-line{pointer-events:none}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/chartist.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/chartist.min.css
new file mode 100755
index 0000000..9170721
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/chartist.min.css
@@ -0,0 +1 @@
+.ct-double-octave:after,.ct-major-eleventh:after,.ct-major-second:after,.ct-major-seventh:after,.ct-major-sixth:after,.ct-major-tenth:after,.ct-major-third:after,.ct-major-twelfth:after,.ct-minor-second:after,.ct-minor-seventh:after,.ct-minor-sixth:after,.ct-minor-third:after,.ct-octave:after,.ct-perfect-fifth:after,.ct-perfect-fourth:after,.ct-square:after{content:"";clear:both}.ct-label{fill:rgba(0,0,0,.4);color:rgba(0,0,0,.4);font-size:.75rem;line-height:1}.ct-grid-background,.ct-line{fill:none}.ct-chart-bar .ct-label,.ct-chart-line .ct-label{display:block;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.ct-chart-donut .ct-label,.ct-chart-pie .ct-label{dominant-baseline:central}.ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-vertical.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-end;-webkit-justify-content:flex-end;-ms-flex-pack:flex-end;justify-content:flex-end;text-align:right;text-anchor:end}.ct-label.ct-vertical.ct-end{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-start{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:flex-end;-webkit-justify-content:flex-end;-ms-flex-pack:flex-end;justify-content:flex-end;text-align:right;text-anchor:end}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-end{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:end}.ct-grid{stroke:rgba(0,0,0,.2);stroke-width:1px;stroke-dasharray:2px}.ct-point{stroke-width:10px;stroke-linecap:round}.ct-line{stroke-width:4px}.ct-area{stroke:none;fill-opacity:.1}.ct-bar{fill:none;stroke-width:10px}.ct-slice-donut{fill:none;stroke-width:60px}.ct-series-a .ct-bar,.ct-series-a .ct-line,.ct-series-a .ct-point,.ct-series-a .ct-slice-donut{stroke:#d70206}.ct-series-a .ct-area,.ct-series-a .ct-slice-donut-solid,.ct-series-a .ct-slice-pie{fill:#d70206}.ct-series-b .ct-bar,.ct-series-b .ct-line,.ct-series-b .ct-point,.ct-series-b .ct-slice-donut{stroke:#f05b4f}.ct-series-b .ct-area,.ct-series-b .ct-slice-donut-solid,.ct-series-b .ct-slice-pie{fill:#f05b4f}.ct-series-c .ct-bar,.ct-series-c .ct-line,.ct-series-c .ct-point,.ct-series-c .ct-slice-donut{stroke:#f4c63d}.ct-series-c .ct-area,.ct-series-c .ct-slice-donut-solid,.ct-series-c .ct-slice-pie{fill:#f4c63d}.ct-series-d .ct-bar,.ct-series-d .ct-line,.ct-series-d .ct-point,.ct-series-d .ct-slice-donut{stroke:#d17905}.ct-series-d .ct-area,.ct-series-d .ct-slice-donut-solid,.ct-series-d .ct-slice-pie{fill:#d17905}.ct-series-e .ct-bar,.ct-series-e .ct-line,.ct-series-e .ct-point,.ct-series-e .ct-slice-donut{stroke:#453d3f}.ct-series-e .ct-area,.ct-series-e .ct-slice-donut-solid,.ct-series-e .ct-slice-pie{fill:#453d3f}.ct-series-f .ct-bar,.ct-series-f .ct-line,.ct-series-f .ct-point,.ct-series-f .ct-slice-donut{stroke:#59922b}.ct-series-f .ct-area,.ct-series-f .ct-slice-donut-solid,.ct-series-f .ct-slice-pie{fill:#59922b}.ct-series-g .ct-bar,.ct-series-g .ct-line,.ct-series-g .ct-point,.ct-series-g .ct-slice-donut{stroke:#0544d3}.ct-series-g .ct-area,.ct-series-g .ct-slice-donut-solid,.ct-series-g .ct-slice-pie{fill:#0544d3}.ct-series-h .ct-bar,.ct-series-h .ct-line,.ct-series-h .ct-point,.ct-series-h .ct-slice-donut{stroke:#6b0392}.ct-series-h .ct-area,.ct-series-h .ct-slice-donut-solid,.ct-series-h .ct-slice-pie{fill:#6b0392}.ct-series-i .ct-bar,.ct-series-i .ct-line,.ct-series-i .ct-point,.ct-series-i .ct-slice-donut{stroke:#f05b4f}.ct-series-i .ct-area,.ct-series-i .ct-slice-donut-solid,.ct-series-i .ct-slice-pie{fill:#f05b4f}.ct-series-j .ct-bar,.ct-series-j .ct-line,.ct-series-j .ct-point,.ct-series-j .ct-slice-donut{stroke:#dda458}.ct-series-j .ct-area,.ct-series-j .ct-slice-donut-solid,.ct-series-j .ct-slice-pie{fill:#dda458}.ct-series-k .ct-bar,.ct-series-k .ct-line,.ct-series-k .ct-point,.ct-series-k .ct-slice-donut{stroke:#eacf7d}.ct-series-k .ct-area,.ct-series-k .ct-slice-donut-solid,.ct-series-k .ct-slice-pie{fill:#eacf7d}.ct-series-l .ct-bar,.ct-series-l .ct-line,.ct-series-l .ct-point,.ct-series-l .ct-slice-donut{stroke:#86797d}.ct-series-l .ct-area,.ct-series-l .ct-slice-donut-solid,.ct-series-l .ct-slice-pie{fill:#86797d}.ct-series-m .ct-bar,.ct-series-m .ct-line,.ct-series-m .ct-point,.ct-series-m .ct-slice-donut{stroke:#b2c326}.ct-series-m .ct-area,.ct-series-m .ct-slice-donut-solid,.ct-series-m .ct-slice-pie{fill:#b2c326}.ct-series-n .ct-bar,.ct-series-n .ct-line,.ct-series-n .ct-point,.ct-series-n .ct-slice-donut{stroke:#6188e2}.ct-series-n .ct-area,.ct-series-n .ct-slice-donut-solid,.ct-series-n .ct-slice-pie{fill:#6188e2}.ct-series-o .ct-bar,.ct-series-o .ct-line,.ct-series-o .ct-point,.ct-series-o .ct-slice-donut{stroke:#a748ca}.ct-series-o .ct-area,.ct-series-o .ct-slice-donut-solid,.ct-series-o .ct-slice-pie{fill:#a748ca}.ct-square{display:block;position:relative;width:100%}.ct-square:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:100%}.ct-square:after{display:table}.ct-square>svg{display:block;position:absolute;top:0;left:0}.ct-minor-second{display:block;position:relative;width:100%}.ct-minor-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:93.75%}.ct-minor-second:after{display:table}.ct-minor-second>svg{display:block;position:absolute;top:0;left:0}.ct-major-second{display:block;position:relative;width:100%}.ct-major-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:88.8888888889%}.ct-major-second:after{display:table}.ct-major-second>svg{display:block;position:absolute;top:0;left:0}.ct-minor-third{display:block;position:relative;width:100%}.ct-minor-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:83.3333333333%}.ct-minor-third:after{display:table}.ct-minor-third>svg{display:block;position:absolute;top:0;left:0}.ct-major-third{display:block;position:relative;width:100%}.ct-major-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:80%}.ct-major-third:after{display:table}.ct-major-third>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fourth{display:block;position:relative;width:100%}.ct-perfect-fourth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:75%}.ct-perfect-fourth:after{display:table}.ct-perfect-fourth>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fifth{display:block;position:relative;width:100%}.ct-perfect-fifth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:66.6666666667%}.ct-perfect-fifth:after{display:table}.ct-perfect-fifth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-sixth{display:block;position:relative;width:100%}.ct-minor-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:62.5%}.ct-minor-sixth:after{display:table}.ct-minor-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-golden-section{display:block;position:relative;width:100%}.ct-golden-section:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:61.804697157%}.ct-golden-section:after{content:"";display:table;clear:both}.ct-golden-section>svg{display:block;position:absolute;top:0;left:0}.ct-major-sixth{display:block;position:relative;width:100%}.ct-major-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:60%}.ct-major-sixth:after{display:table}.ct-major-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-seventh{display:block;position:relative;width:100%}.ct-minor-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:56.25%}.ct-minor-seventh:after{display:table}.ct-minor-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-seventh{display:block;position:relative;width:100%}.ct-major-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:53.3333333333%}.ct-major-seventh:after{display:table}.ct-major-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-octave{display:block;position:relative;width:100%}.ct-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:50%}.ct-octave:after{display:table}.ct-octave>svg{display:block;position:absolute;top:0;left:0}.ct-major-tenth{display:block;position:relative;width:100%}.ct-major-tenth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:40%}.ct-major-tenth:after{display:table}.ct-major-tenth>svg{display:block;position:absolute;top:0;left:0}.ct-major-eleventh{display:block;position:relative;width:100%}.ct-major-eleventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:37.5%}.ct-major-eleventh:after{display:table}.ct-major-eleventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-twelfth{display:block;position:relative;width:100%}.ct-major-twelfth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:33.3333333333%}.ct-major-twelfth:after{display:table}.ct-major-twelfth>svg{display:block;position:absolute;top:0;left:0}.ct-double-octave{display:block;position:relative;width:100%}.ct-double-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:25%}.ct-double-octave:after{display:table}.ct-double-octave>svg{display:block;position:absolute;top:0;left:0}.chartist-big .ct-series-a .ct-bar,.chartist-big .ct-series-a .ct-line,.chartist-big .ct-series-a .ct-point,.chartist-big .ct-series-a .ct-slice-donut,.chartist-big .ct-series-b .ct-bar,.chartist-big .ct-series-b .ct-line,.chartist-big .ct-series-b .ct-point,.chartist-big .ct-series-b .ct-slice-donut,.chartist-big .ct-series-c .ct-bar,.chartist-big .ct-series-c .ct-line,.chartist-big .ct-series-c .ct-point,.chartist-big .ct-series-c .ct-slice-donut,.chartist-big .ct-series-d .ct-bar,.chartist-big .ct-series-d .ct-line,.chartist-big .ct-series-d .ct-point,.chartist-big .ct-series-d .ct-slice-donut{stroke-width:20px}.chartist-huge .ct-series-a .ct-bar,.chartist-huge .ct-series-a .ct-line,.chartist-huge .ct-series-a .ct-point,.chartist-huge .ct-series-a .ct-slice-donut,.chartist-huge .ct-series-b .ct-bar,.chartist-huge .ct-series-b .ct-line,.chartist-huge .ct-series-b .ct-point,.chartist-huge .ct-series-b .ct-slice-donut,.chartist-huge .ct-series-c .ct-bar,.chartist-huge .ct-series-c .ct-line,.chartist-huge .ct-series-c .ct-point,.chartist-huge .ct-series-c .ct-slice-donut,.chartist-huge .ct-series-d .ct-bar,.chartist-huge .ct-series-d .ct-line,.chartist-huge .ct-series-d .ct-point,.chartist-huge .ct-series-d .ct-slice-donut{stroke-width:30px}.chartist-white.text-black .ct-label{fill:#000;color:#000}.chartist-white.text-white .ct-label{fill:#fff;color:#fff}.chartist-white .ct-label{fill:rgba(255,255,255,.4);color:rgba(255,255,255,.4)}.chartist-white .ct-grid{stroke:rgba(255,255,255,.2)}.chartist-white .ct-series-a .ct-bar,.chartist-white .ct-series-a .ct-line,.chartist-white .ct-series-a .ct-point,.chartist-white .ct-series-a .ct-slice-donut{stroke:rgba(255,255,255,1)}.chartist-white .ct-series-b .ct-bar,.chartist-white .ct-series-b .ct-line,.chartist-white .ct-series-b .ct-point,.chartist-white .ct-series-b .ct-slice-donut{stroke:rgba(255,255,255,.7)}.chartist-white .ct-series-c .ct-bar,.chartist-white .ct-series-c .ct-line,.chartist-white .ct-series-c .ct-point,.chartist-white .ct-series-c .ct-slice-donut{stroke:rgba(255,255,255,.4)}.chartist-white .ct-series-d .ct-bar,.chartist-white .ct-series-d .ct-line,.chartist-white .ct-series-d .ct-point,.chartist-white .ct-series-d .ct-slice-donut{stroke:rgba(255,255,255,.2)}.chartist-white .ct-series-a .ct-area,.chartist-white .ct-series-a .ct-slice-donut-solid,.chartist-white .ct-series-a .ct-slice-pie{fill:rgba(255,255,255,1)}.chartist-white .ct-series-b .ct-area,.chartist-white .ct-series-b .ct-slice-donut-solid,.chartist-white .ct-series-b .ct-slice-pie{fill:rgba(255,255,255,.7)}.chartist-white .ct-series-c .ct-area,.chartist-white .ct-series-c .ct-slice-donut-solid,.chartist-white .ct-series-c .ct-slice-pie{fill:rgba(255,255,255,.4)}.chartist-white .ct-series-d .ct-area,.chartist-white .ct-series-d .ct-slice-donut-solid,.chartist-white .ct-series-d .ct-slice-pie{fill:rgba(255,255,255,.2)}.chartist-red.text-black .ct-label{fill:#000;color:#000}.chartist-red.text-white .ct-label{fill:#fff;color:#fff}.chartist-red .ct-label{fill:rgba(244,67,54,.4);color:rgba(244,67,54,.4)}.chartist-red .ct-grid{stroke:rgba(244,67,54,.2)}.chartist-red .ct-series-a .ct-bar,.chartist-red .ct-series-a .ct-line,.chartist-red .ct-series-a .ct-point,.chartist-red .ct-series-a .ct-slice-donut{stroke:rgba(244,67,54,1)}.chartist-red .ct-series-b .ct-bar,.chartist-red .ct-series-b .ct-line,.chartist-red .ct-series-b .ct-point,.chartist-red .ct-series-b .ct-slice-donut{stroke:rgba(244,67,54,.7)}.chartist-red .ct-series-c .ct-bar,.chartist-red .ct-series-c .ct-line,.chartist-red .ct-series-c .ct-point,.chartist-red .ct-series-c .ct-slice-donut{stroke:rgba(244,67,54,.4)}.chartist-red .ct-series-d .ct-bar,.chartist-red .ct-series-d .ct-line,.chartist-red .ct-series-d .ct-point,.chartist-red .ct-series-d .ct-slice-donut{stroke:rgba(244,67,54,.2)}.chartist-red .ct-series-a .ct-area,.chartist-red .ct-series-a .ct-slice-donut-solid,.chartist-red .ct-series-a .ct-slice-pie{fill:rgba(244,67,54,1)}.chartist-red .ct-series-b .ct-area,.chartist-red .ct-series-b .ct-slice-donut-solid,.chartist-red .ct-series-b .ct-slice-pie{fill:rgba(244,67,54,.7)}.chartist-red .ct-series-c .ct-area,.chartist-red .ct-series-c .ct-slice-donut-solid,.chartist-red .ct-series-c .ct-slice-pie{fill:rgba(244,67,54,.4)}.chartist-red .ct-series-d .ct-area,.chartist-red .ct-series-d .ct-slice-donut-solid,.chartist-red .ct-series-d .ct-slice-pie{fill:rgba(244,67,54,.2)}.chartist-pink.text-black .ct-label{fill:#000;color:#000}.chartist-pink.text-white .ct-label{fill:#fff;color:#fff}.chartist-pink .ct-label{fill:rgba(233,30,99,.4);color:rgba(233,30,99,.4)}.chartist-pink .ct-grid{stroke:rgba(233,30,99,.2)}.chartist-pink .ct-series-a .ct-bar,.chartist-pink .ct-series-a .ct-line,.chartist-pink .ct-series-a .ct-point,.chartist-pink .ct-series-a .ct-slice-donut{stroke:rgba(233,30,99,1)}.chartist-pink .ct-series-b .ct-bar,.chartist-pink .ct-series-b .ct-line,.chartist-pink .ct-series-b .ct-point,.chartist-pink .ct-series-b .ct-slice-donut{stroke:rgba(233,30,99,.7)}.chartist-pink .ct-series-c .ct-bar,.chartist-pink .ct-series-c .ct-line,.chartist-pink .ct-series-c .ct-point,.chartist-pink .ct-series-c .ct-slice-donut{stroke:rgba(233,30,99,.4)}.chartist-pink .ct-series-d .ct-bar,.chartist-pink .ct-series-d .ct-line,.chartist-pink .ct-series-d .ct-point,.chartist-pink .ct-series-d .ct-slice-donut{stroke:rgba(233,30,99,.2)}.chartist-pink .ct-series-a .ct-area,.chartist-pink .ct-series-a .ct-slice-donut-solid,.chartist-pink .ct-series-a .ct-slice-pie{fill:rgba(233,30,99,1)}.chartist-pink .ct-series-b .ct-area,.chartist-pink .ct-series-b .ct-slice-donut-solid,.chartist-pink .ct-series-b .ct-slice-pie{fill:rgba(233,30,99,.7)}.chartist-pink .ct-series-c .ct-area,.chartist-pink .ct-series-c .ct-slice-donut-solid,.chartist-pink .ct-series-c .ct-slice-pie{fill:rgba(233,30,99,.4)}.chartist-pink .ct-series-d .ct-area,.chartist-pink .ct-series-d .ct-slice-donut-solid,.chartist-pink .ct-series-d .ct-slice-pie{fill:rgba(233,30,99,.2)}.chartist-purple.text-black .ct-label{fill:#000;color:#000}.chartist-purple.text-white .ct-label{fill:#fff;color:#fff}.chartist-purple .ct-label{fill:rgba(156,39,176,.4);color:rgba(156,39,176,.4)}.chartist-purple .ct-grid{stroke:rgba(156,39,176,.2)}.chartist-purple .ct-series-a .ct-bar,.chartist-purple .ct-series-a .ct-line,.chartist-purple .ct-series-a .ct-point,.chartist-purple .ct-series-a .ct-slice-donut{stroke:rgba(156,39,176,1)}.chartist-purple .ct-series-b .ct-bar,.chartist-purple .ct-series-b .ct-line,.chartist-purple .ct-series-b .ct-point,.chartist-purple .ct-series-b .ct-slice-donut{stroke:rgba(156,39,176,.7)}.chartist-purple .ct-series-c .ct-bar,.chartist-purple .ct-series-c .ct-line,.chartist-purple .ct-series-c .ct-point,.chartist-purple .ct-series-c .ct-slice-donut{stroke:rgba(156,39,176,.4)}.chartist-purple .ct-series-d .ct-bar,.chartist-purple .ct-series-d .ct-line,.chartist-purple .ct-series-d .ct-point,.chartist-purple .ct-series-d .ct-slice-donut{stroke:rgba(156,39,176,.2)}.chartist-purple .ct-series-a .ct-area,.chartist-purple .ct-series-a .ct-slice-donut-solid,.chartist-purple .ct-series-a .ct-slice-pie{fill:rgba(156,39,176,1)}.chartist-purple .ct-series-b .ct-area,.chartist-purple .ct-series-b .ct-slice-donut-solid,.chartist-purple .ct-series-b .ct-slice-pie{fill:rgba(156,39,176,.7)}.chartist-purple .ct-series-c .ct-area,.chartist-purple .ct-series-c .ct-slice-donut-solid,.chartist-purple .ct-series-c .ct-slice-pie{fill:rgba(156,39,176,.4)}.chartist-purple .ct-series-d .ct-area,.chartist-purple .ct-series-d .ct-slice-donut-solid,.chartist-purple .ct-series-d .ct-slice-pie{fill:rgba(156,39,176,.2)}.chartist-deep.text-white-purple .ct-label{fill:#fff;color:#fff}.chartist-deep-purple .ct-label{fill:rgba(103,58,183,.4);color:rgba(103,58,183,.4)}.chartist-deep-purple .ct-grid{stroke:rgba(103,58,183,.2)}.chartist-deep-purple .ct-series-a .ct-bar,.chartist-deep-purple .ct-series-a .ct-line,.chartist-deep-purple .ct-series-a .ct-point,.chartist-deep-purple .ct-series-a .ct-slice-donut{stroke:rgba(103,58,183,1)}.chartist-deep-purple .ct-series-b .ct-bar,.chartist-deep-purple .ct-series-b .ct-line,.chartist-deep-purple .ct-series-b .ct-point,.chartist-deep-purple .ct-series-b .ct-slice-donut{stroke:rgba(103,58,183,.7)}.chartist-deep-purple .ct-series-c .ct-bar,.chartist-deep-purple .ct-series-c .ct-line,.chartist-deep-purple .ct-series-c .ct-point,.chartist-deep-purple .ct-series-c .ct-slice-donut{stroke:rgba(103,58,183,.4)}.chartist-deep-purple .ct-series-d .ct-bar,.chartist-deep-purple .ct-series-d .ct-line,.chartist-deep-purple .ct-series-d .ct-point,.chartist-deep-purple .ct-series-d .ct-slice-donut{stroke:rgba(103,58,183,.2)}.chartist-deep-purple .ct-series-a .ct-area,.chartist-deep-purple .ct-series-a .ct-slice-donut-solid,.chartist-deep-purple .ct-series-a .ct-slice-pie{fill:rgba(103,58,183,1)}.chartist-deep-purple .ct-series-b .ct-area,.chartist-deep-purple .ct-series-b .ct-slice-donut-solid,.chartist-deep-purple .ct-series-b .ct-slice-pie{fill:rgba(103,58,183,.7)}.chartist-deep-purple .ct-series-c .ct-area,.chartist-deep-purple .ct-series-c .ct-slice-donut-solid,.chartist-deep-purple .ct-series-c .ct-slice-pie{fill:rgba(103,58,183,.4)}.chartist-deep-purple .ct-series-d .ct-area,.chartist-deep-purple .ct-series-d .ct-slice-donut-solid,.chartist-deep-purple .ct-series-d .ct-slice-pie{fill:rgba(103,58,183,.2)}.chartist-indigo.text-black .ct-label{fill:#000;color:#000}.chartist-indigo.text-white .ct-label{fill:#fff;color:#fff}.chartist-indigo .ct-label{fill:rgba(63,81,181,.4);color:rgba(63,81,181,.4)}.chartist-indigo .ct-grid{stroke:rgba(63,81,181,.2)}.chartist-indigo .ct-series-a .ct-bar,.chartist-indigo .ct-series-a .ct-line,.chartist-indigo .ct-series-a .ct-point,.chartist-indigo .ct-series-a .ct-slice-donut{stroke:rgba(63,81,181,1)}.chartist-indigo .ct-series-b .ct-bar,.chartist-indigo .ct-series-b .ct-line,.chartist-indigo .ct-series-b .ct-point,.chartist-indigo .ct-series-b .ct-slice-donut{stroke:rgba(63,81,181,.7)}.chartist-indigo .ct-series-c .ct-bar,.chartist-indigo .ct-series-c .ct-line,.chartist-indigo .ct-series-c .ct-point,.chartist-indigo .ct-series-c .ct-slice-donut{stroke:rgba(63,81,181,.4)}.chartist-indigo .ct-series-d .ct-bar,.chartist-indigo .ct-series-d .ct-line,.chartist-indigo .ct-series-d .ct-point,.chartist-indigo .ct-series-d .ct-slice-donut{stroke:rgba(63,81,181,.2)}.chartist-indigo .ct-series-a .ct-area,.chartist-indigo .ct-series-a .ct-slice-donut-solid,.chartist-indigo .ct-series-a .ct-slice-pie{fill:rgba(63,81,181,1)}.chartist-indigo .ct-series-b .ct-area,.chartist-indigo .ct-series-b .ct-slice-donut-solid,.chartist-indigo .ct-series-b .ct-slice-pie{fill:rgba(63,81,181,.7)}.chartist-indigo .ct-series-c .ct-area,.chartist-indigo .ct-series-c .ct-slice-donut-solid,.chartist-indigo .ct-series-c .ct-slice-pie{fill:rgba(63,81,181,.4)}.chartist-indigo .ct-series-d .ct-area,.chartist-indigo .ct-series-d .ct-slice-donut-solid,.chartist-indigo .ct-series-d .ct-slice-pie{fill:rgba(63,81,181,.2)}.chartist-blue.text-black .ct-label{fill:#000;color:#000}.chartist-blue.text-white .ct-label{fill:#fff;color:#fff}.chartist-blue .ct-label{fill:rgba(33,150,243,.4);color:rgba(33,150,243,.4)}.chartist-blue .ct-grid{stroke:rgba(33,150,243,.2)}.chartist-blue .ct-series-a .ct-bar,.chartist-blue .ct-series-a .ct-line,.chartist-blue .ct-series-a .ct-point,.chartist-blue .ct-series-a .ct-slice-donut{stroke:rgba(33,150,243,1)}.chartist-blue .ct-series-b .ct-bar,.chartist-blue .ct-series-b .ct-line,.chartist-blue .ct-series-b .ct-point,.chartist-blue .ct-series-b .ct-slice-donut{stroke:rgba(33,150,243,.7)}.chartist-blue .ct-series-c .ct-bar,.chartist-blue .ct-series-c .ct-line,.chartist-blue .ct-series-c .ct-point,.chartist-blue .ct-series-c .ct-slice-donut{stroke:rgba(33,150,243,.4)}.chartist-blue .ct-series-d .ct-bar,.chartist-blue .ct-series-d .ct-line,.chartist-blue .ct-series-d .ct-point,.chartist-blue .ct-series-d .ct-slice-donut{stroke:rgba(33,150,243,.2)}.chartist-blue .ct-series-a .ct-area,.chartist-blue .ct-series-a .ct-slice-donut-solid,.chartist-blue .ct-series-a .ct-slice-pie{fill:rgba(33,150,243,1)}.chartist-blue .ct-series-b .ct-area,.chartist-blue .ct-series-b .ct-slice-donut-solid,.chartist-blue .ct-series-b .ct-slice-pie{fill:rgba(33,150,243,.7)}.chartist-blue .ct-series-c .ct-area,.chartist-blue .ct-series-c .ct-slice-donut-solid,.chartist-blue .ct-series-c .ct-slice-pie{fill:rgba(33,150,243,.4)}.chartist-blue .ct-series-d .ct-area,.chartist-blue .ct-series-d .ct-slice-donut-solid,.chartist-blue .ct-series-d .ct-slice-pie{fill:rgba(33,150,243,.2)}.chartist-light.text-white-blue .ct-label{fill:#fff;color:#fff}.chartist-light-blue .ct-label{fill:rgba(3,169,244,.4);color:rgba(3,169,244,.4)}.chartist-light-blue .ct-grid{stroke:rgba(3,169,244,.2)}.chartist-light-blue .ct-series-a .ct-bar,.chartist-light-blue .ct-series-a .ct-line,.chartist-light-blue .ct-series-a .ct-point,.chartist-light-blue .ct-series-a .ct-slice-donut{stroke:rgba(3,169,244,1)}.chartist-light-blue .ct-series-b .ct-bar,.chartist-light-blue .ct-series-b .ct-line,.chartist-light-blue .ct-series-b .ct-point,.chartist-light-blue .ct-series-b .ct-slice-donut{stroke:rgba(3,169,244,.7)}.chartist-light-blue .ct-series-c .ct-bar,.chartist-light-blue .ct-series-c .ct-line,.chartist-light-blue .ct-series-c .ct-point,.chartist-light-blue .ct-series-c .ct-slice-donut{stroke:rgba(3,169,244,.4)}.chartist-light-blue .ct-series-d .ct-bar,.chartist-light-blue .ct-series-d .ct-line,.chartist-light-blue .ct-series-d .ct-point,.chartist-light-blue .ct-series-d .ct-slice-donut{stroke:rgba(3,169,244,.2)}.chartist-light-blue .ct-series-a .ct-area,.chartist-light-blue .ct-series-a .ct-slice-donut-solid,.chartist-light-blue .ct-series-a .ct-slice-pie{fill:rgba(3,169,244,1)}.chartist-light-blue .ct-series-b .ct-area,.chartist-light-blue .ct-series-b .ct-slice-donut-solid,.chartist-light-blue .ct-series-b .ct-slice-pie{fill:rgba(3,169,244,.7)}.chartist-light-blue .ct-series-c .ct-area,.chartist-light-blue .ct-series-c .ct-slice-donut-solid,.chartist-light-blue .ct-series-c .ct-slice-pie{fill:rgba(3,169,244,.4)}.chartist-light-blue .ct-series-d .ct-area,.chartist-light-blue .ct-series-d .ct-slice-donut-solid,.chartist-light-blue .ct-series-d .ct-slice-pie{fill:rgba(3,169,244,.2)}.chartist-cyan.text-black .ct-label{fill:#000;color:#000}.chartist-cyan.text-white .ct-label{fill:#fff;color:#fff}.chartist-cyan .ct-label{fill:rgba(0,188,212,.4);color:rgba(0,188,212,.4)}.chartist-cyan .ct-grid{stroke:rgba(0,188,212,.2)}.chartist-cyan .ct-series-a .ct-bar,.chartist-cyan .ct-series-a .ct-line,.chartist-cyan .ct-series-a .ct-point,.chartist-cyan .ct-series-a .ct-slice-donut{stroke:rgba(0,188,212,1)}.chartist-cyan .ct-series-b .ct-bar,.chartist-cyan .ct-series-b .ct-line,.chartist-cyan .ct-series-b .ct-point,.chartist-cyan .ct-series-b .ct-slice-donut{stroke:rgba(0,188,212,.7)}.chartist-cyan .ct-series-c .ct-bar,.chartist-cyan .ct-series-c .ct-line,.chartist-cyan .ct-series-c .ct-point,.chartist-cyan .ct-series-c .ct-slice-donut{stroke:rgba(0,188,212,.4)}.chartist-cyan .ct-series-d .ct-bar,.chartist-cyan .ct-series-d .ct-line,.chartist-cyan .ct-series-d .ct-point,.chartist-cyan .ct-series-d .ct-slice-donut{stroke:rgba(0,188,212,.2)}.chartist-cyan .ct-series-a .ct-area,.chartist-cyan .ct-series-a .ct-slice-donut-solid,.chartist-cyan .ct-series-a .ct-slice-pie{fill:rgba(0,188,212,1)}.chartist-cyan .ct-series-b .ct-area,.chartist-cyan .ct-series-b .ct-slice-donut-solid,.chartist-cyan .ct-series-b .ct-slice-pie{fill:rgba(0,188,212,.7)}.chartist-cyan .ct-series-c .ct-area,.chartist-cyan .ct-series-c .ct-slice-donut-solid,.chartist-cyan .ct-series-c .ct-slice-pie{fill:rgba(0,188,212,.4)}.chartist-cyan .ct-series-d .ct-area,.chartist-cyan .ct-series-d .ct-slice-donut-solid,.chartist-cyan .ct-series-d .ct-slice-pie{fill:rgba(0,188,212,.2)}.chartist-teal.text-black .ct-label{fill:#000;color:#000}.chartist-teal.text-white .ct-label{fill:#fff;color:#fff}.chartist-teal .ct-label{fill:rgba(0,150,136,.4);color:rgba(0,150,136,.4)}.chartist-teal .ct-grid{stroke:rgba(0,150,136,.2)}.chartist-teal .ct-series-a .ct-bar,.chartist-teal .ct-series-a .ct-line,.chartist-teal .ct-series-a .ct-point,.chartist-teal .ct-series-a .ct-slice-donut{stroke:rgba(0,150,136,1)}.chartist-teal .ct-series-b .ct-bar,.chartist-teal .ct-series-b .ct-line,.chartist-teal .ct-series-b .ct-point,.chartist-teal .ct-series-b .ct-slice-donut{stroke:rgba(0,150,136,.7)}.chartist-teal .ct-series-c .ct-bar,.chartist-teal .ct-series-c .ct-line,.chartist-teal .ct-series-c .ct-point,.chartist-teal .ct-series-c .ct-slice-donut{stroke:rgba(0,150,136,.4)}.chartist-teal .ct-series-d .ct-bar,.chartist-teal .ct-series-d .ct-line,.chartist-teal .ct-series-d .ct-point,.chartist-teal .ct-series-d .ct-slice-donut{stroke:rgba(0,150,136,.2)}.chartist-teal .ct-series-a .ct-area,.chartist-teal .ct-series-a .ct-slice-donut-solid,.chartist-teal .ct-series-a .ct-slice-pie{fill:rgba(0,150,136,1)}.chartist-teal .ct-series-b .ct-area,.chartist-teal .ct-series-b .ct-slice-donut-solid,.chartist-teal .ct-series-b .ct-slice-pie{fill:rgba(0,150,136,.7)}.chartist-teal .ct-series-c .ct-area,.chartist-teal .ct-series-c .ct-slice-donut-solid,.chartist-teal .ct-series-c .ct-slice-pie{fill:rgba(0,150,136,.4)}.chartist-teal .ct-series-d .ct-area,.chartist-teal .ct-series-d .ct-slice-donut-solid,.chartist-teal .ct-series-d .ct-slice-pie{fill:rgba(0,150,136,.2)}.chartist-green.text-black .ct-label{fill:#000;color:#000}.chartist-green.text-white .ct-label{fill:#fff;color:#fff}.chartist-green .ct-label{fill:rgba(76,175,79,.4);color:rgba(76,175,79,.4)}.chartist-green .ct-grid{stroke:rgba(76,175,79,.2)}.chartist-green .ct-series-a .ct-bar,.chartist-green .ct-series-a .ct-line,.chartist-green .ct-series-a .ct-point,.chartist-green .ct-series-a .ct-slice-donut{stroke:rgba(76,175,79,1)}.chartist-green .ct-series-b .ct-bar,.chartist-green .ct-series-b .ct-line,.chartist-green .ct-series-b .ct-point,.chartist-green .ct-series-b .ct-slice-donut{stroke:rgba(76,175,79,.7)}.chartist-green .ct-series-c .ct-bar,.chartist-green .ct-series-c .ct-line,.chartist-green .ct-series-c .ct-point,.chartist-green .ct-series-c .ct-slice-donut{stroke:rgba(76,175,79,.4)}.chartist-green .ct-series-d .ct-bar,.chartist-green .ct-series-d .ct-line,.chartist-green .ct-series-d .ct-point,.chartist-green .ct-series-d .ct-slice-donut{stroke:rgba(76,175,79,.2)}.chartist-green .ct-series-a .ct-area,.chartist-green .ct-series-a .ct-slice-donut-solid,.chartist-green .ct-series-a .ct-slice-pie{fill:rgba(76,175,79,1)}.chartist-green .ct-series-b .ct-area,.chartist-green .ct-series-b .ct-slice-donut-solid,.chartist-green .ct-series-b .ct-slice-pie{fill:rgba(76,175,79,.7)}.chartist-green .ct-series-c .ct-area,.chartist-green .ct-series-c .ct-slice-donut-solid,.chartist-green .ct-series-c .ct-slice-pie{fill:rgba(76,175,79,.4)}.chartist-green .ct-series-d .ct-area,.chartist-green .ct-series-d .ct-slice-donut-solid,.chartist-green .ct-series-d .ct-slice-pie{fill:rgba(76,175,79,.2)}.chartist-lime.text-black .ct-label{fill:#000;color:#000}.chartist-lime.text-white .ct-label{fill:#fff;color:#fff}.chartist-lime .ct-label{fill:rgba(205,220,57,.4);color:rgba(205,220,57,.4)}.chartist-lime .ct-grid{stroke:rgba(205,220,57,.2)}.chartist-lime .ct-series-a .ct-bar,.chartist-lime .ct-series-a .ct-line,.chartist-lime .ct-series-a .ct-point,.chartist-lime .ct-series-a .ct-slice-donut{stroke:rgba(205,220,57,1)}.chartist-lime .ct-series-b .ct-bar,.chartist-lime .ct-series-b .ct-line,.chartist-lime .ct-series-b .ct-point,.chartist-lime .ct-series-b .ct-slice-donut{stroke:rgba(205,220,57,.7)}.chartist-lime .ct-series-c .ct-bar,.chartist-lime .ct-series-c .ct-line,.chartist-lime .ct-series-c .ct-point,.chartist-lime .ct-series-c .ct-slice-donut{stroke:rgba(205,220,57,.4)}.chartist-lime .ct-series-d .ct-bar,.chartist-lime .ct-series-d .ct-line,.chartist-lime .ct-series-d .ct-point,.chartist-lime .ct-series-d .ct-slice-donut{stroke:rgba(205,220,57,.2)}.chartist-lime .ct-series-a .ct-area,.chartist-lime .ct-series-a .ct-slice-donut-solid,.chartist-lime .ct-series-a .ct-slice-pie{fill:rgba(205,220,57,1)}.chartist-lime .ct-series-b .ct-area,.chartist-lime .ct-series-b .ct-slice-donut-solid,.chartist-lime .ct-series-b .ct-slice-pie{fill:rgba(205,220,57,.7)}.chartist-lime .ct-series-c .ct-area,.chartist-lime .ct-series-c .ct-slice-donut-solid,.chartist-lime .ct-series-c .ct-slice-pie{fill:rgba(205,220,57,.4)}.chartist-lime .ct-series-d .ct-area,.chartist-lime .ct-series-d .ct-slice-donut-solid,.chartist-lime .ct-series-d .ct-slice-pie{fill:rgba(205,220,57,.2)}.chartist-yellow.text-black .ct-label{fill:#000;color:#000}.chartist-yellow.text-white .ct-label{fill:#fff;color:#fff}.chartist-yellow .ct-label{fill:rgba(255,235,59,.4);color:rgba(255,235,59,.4)}.chartist-yellow .ct-grid{stroke:rgba(255,235,59,.2)}.chartist-yellow .ct-series-a .ct-bar,.chartist-yellow .ct-series-a .ct-line,.chartist-yellow .ct-series-a .ct-point,.chartist-yellow .ct-series-a .ct-slice-donut{stroke:rgba(255,235,59,1)}.chartist-yellow .ct-series-b .ct-bar,.chartist-yellow .ct-series-b .ct-line,.chartist-yellow .ct-series-b .ct-point,.chartist-yellow .ct-series-b .ct-slice-donut{stroke:rgba(255,235,59,.7)}.chartist-yellow .ct-series-c .ct-bar,.chartist-yellow .ct-series-c .ct-line,.chartist-yellow .ct-series-c .ct-point,.chartist-yellow .ct-series-c .ct-slice-donut{stroke:rgba(255,235,59,.4)}.chartist-yellow .ct-series-d .ct-bar,.chartist-yellow .ct-series-d .ct-line,.chartist-yellow .ct-series-d .ct-point,.chartist-yellow .ct-series-d .ct-slice-donut{stroke:rgba(255,235,59,.2)}.chartist-yellow .ct-series-a .ct-area,.chartist-yellow .ct-series-a .ct-slice-donut-solid,.chartist-yellow .ct-series-a .ct-slice-pie{fill:rgba(255,235,59,1)}.chartist-yellow .ct-series-b .ct-area,.chartist-yellow .ct-series-b .ct-slice-donut-solid,.chartist-yellow .ct-series-b .ct-slice-pie{fill:rgba(255,235,59,.7)}.chartist-yellow .ct-series-c .ct-area,.chartist-yellow .ct-series-c .ct-slice-donut-solid,.chartist-yellow .ct-series-c .ct-slice-pie{fill:rgba(255,235,59,.4)}.chartist-yellow .ct-series-d .ct-area,.chartist-yellow .ct-series-d .ct-slice-donut-solid,.chartist-yellow .ct-series-d .ct-slice-pie{fill:rgba(255,235,59,.2)}.chartist-amber.text-black .ct-label{fill:#000;color:#000}.chartist-amber.text-white .ct-label{fill:#fff;color:#fff}.chartist-amber .ct-label{fill:rgba(255,193,7,.4);color:rgba(255,193,7,.4)}.chartist-amber .ct-grid{stroke:rgba(255,193,7,.2)}.chartist-amber .ct-series-a .ct-bar,.chartist-amber .ct-series-a .ct-line,.chartist-amber .ct-series-a .ct-point,.chartist-amber .ct-series-a .ct-slice-donut{stroke:rgba(255,193,7,1)}.chartist-amber .ct-series-b .ct-bar,.chartist-amber .ct-series-b .ct-line,.chartist-amber .ct-series-b .ct-point,.chartist-amber .ct-series-b .ct-slice-donut{stroke:rgba(255,193,7,.7)}.chartist-amber .ct-series-c .ct-bar,.chartist-amber .ct-series-c .ct-line,.chartist-amber .ct-series-c .ct-point,.chartist-amber .ct-series-c .ct-slice-donut{stroke:rgba(255,193,7,.4)}.chartist-amber .ct-series-d .ct-bar,.chartist-amber .ct-series-d .ct-line,.chartist-amber .ct-series-d .ct-point,.chartist-amber .ct-series-d .ct-slice-donut{stroke:rgba(255,193,7,.2)}.chartist-amber .ct-series-a .ct-area,.chartist-amber .ct-series-a .ct-slice-donut-solid,.chartist-amber .ct-series-a .ct-slice-pie{fill:rgba(255,193,7,1)}.chartist-amber .ct-series-b .ct-area,.chartist-amber .ct-series-b .ct-slice-donut-solid,.chartist-amber .ct-series-b .ct-slice-pie{fill:rgba(255,193,7,.7)}.chartist-amber .ct-series-c .ct-area,.chartist-amber .ct-series-c .ct-slice-donut-solid,.chartist-amber .ct-series-c .ct-slice-pie{fill:rgba(255,193,7,.4)}.chartist-amber .ct-series-d .ct-area,.chartist-amber .ct-series-d .ct-slice-donut-solid,.chartist-amber .ct-series-d .ct-slice-pie{fill:rgba(255,193,7,.2)}.chartist-orange.text-black .ct-label{fill:#000;color:#000}.chartist-orange.text-white .ct-label{fill:#fff;color:#fff}.chartist-orange .ct-label{fill:rgba(255,152,0,.4);color:rgba(255,152,0,.4)}.chartist-orange .ct-grid{stroke:rgba(255,152,0,.2)}.chartist-orange .ct-series-a .ct-bar,.chartist-orange .ct-series-a .ct-line,.chartist-orange .ct-series-a .ct-point,.chartist-orange .ct-series-a .ct-slice-donut{stroke:rgba(255,152,0,1)}.chartist-orange .ct-series-b .ct-bar,.chartist-orange .ct-series-b .ct-line,.chartist-orange .ct-series-b .ct-point,.chartist-orange .ct-series-b .ct-slice-donut{stroke:rgba(255,152,0,.7)}.chartist-orange .ct-series-c .ct-bar,.chartist-orange .ct-series-c .ct-line,.chartist-orange .ct-series-c .ct-point,.chartist-orange .ct-series-c .ct-slice-donut{stroke:rgba(255,152,0,.4)}.chartist-orange .ct-series-d .ct-bar,.chartist-orange .ct-series-d .ct-line,.chartist-orange .ct-series-d .ct-point,.chartist-orange .ct-series-d .ct-slice-donut{stroke:rgba(255,152,0,.2)}.chartist-orange .ct-series-a .ct-area,.chartist-orange .ct-series-a .ct-slice-donut-solid,.chartist-orange .ct-series-a .ct-slice-pie{fill:rgba(255,152,0,1)}.chartist-orange .ct-series-b .ct-area,.chartist-orange .ct-series-b .ct-slice-donut-solid,.chartist-orange .ct-series-b .ct-slice-pie{fill:rgba(255,152,0,.7)}.chartist-orange .ct-series-c .ct-area,.chartist-orange .ct-series-c .ct-slice-donut-solid,.chartist-orange .ct-series-c .ct-slice-pie{fill:rgba(255,152,0,.4)}.chartist-orange .ct-series-d .ct-area,.chartist-orange .ct-series-d .ct-slice-donut-solid,.chartist-orange .ct-series-d .ct-slice-pie{fill:rgba(255,152,0,.2)}.chartist-brown.text-black .ct-label{fill:#000;color:#000}.chartist-brown.text-white .ct-label{fill:#fff;color:#fff}.chartist-brown .ct-label{fill:rgba(121,85,72,.4);color:rgba(121,85,72,.4)}.chartist-brown .ct-grid{stroke:rgba(121,85,72,.2)}.chartist-brown .ct-series-a .ct-bar,.chartist-brown .ct-series-a .ct-line,.chartist-brown .ct-series-a .ct-point,.chartist-brown .ct-series-a .ct-slice-donut{stroke:rgba(121,85,72,1)}.chartist-brown .ct-series-b .ct-bar,.chartist-brown .ct-series-b .ct-line,.chartist-brown .ct-series-b .ct-point,.chartist-brown .ct-series-b .ct-slice-donut{stroke:rgba(121,85,72,.7)}.chartist-brown .ct-series-c .ct-bar,.chartist-brown .ct-series-c .ct-line,.chartist-brown .ct-series-c .ct-point,.chartist-brown .ct-series-c .ct-slice-donut{stroke:rgba(121,85,72,.4)}.chartist-brown .ct-series-d .ct-bar,.chartist-brown .ct-series-d .ct-line,.chartist-brown .ct-series-d .ct-point,.chartist-brown .ct-series-d .ct-slice-donut{stroke:rgba(121,85,72,.2)}.chartist-brown .ct-series-a .ct-area,.chartist-brown .ct-series-a .ct-slice-donut-solid,.chartist-brown .ct-series-a .ct-slice-pie{fill:rgba(121,85,72,1)}.chartist-brown .ct-series-b .ct-area,.chartist-brown .ct-series-b .ct-slice-donut-solid,.chartist-brown .ct-series-b .ct-slice-pie{fill:rgba(121,85,72,.7)}.chartist-brown .ct-series-c .ct-area,.chartist-brown .ct-series-c .ct-slice-donut-solid,.chartist-brown .ct-series-c .ct-slice-pie{fill:rgba(121,85,72,.4)}.chartist-brown .ct-series-d .ct-area,.chartist-brown .ct-series-d .ct-slice-donut-solid,.chartist-brown .ct-series-d .ct-slice-pie{fill:rgba(121,85,72,.2)}.chartist-grey.text-black .ct-label{fill:#000;color:#000}.chartist-grey.text-white .ct-label{fill:#fff;color:#fff}.chartist-grey .ct-label{fill:rgba(158,158,158,.4);color:rgba(158,158,158,.4)}.chartist-grey .ct-grid{stroke:rgba(158,158,158,.2)}.chartist-grey .ct-series-a .ct-bar,.chartist-grey .ct-series-a .ct-line,.chartist-grey .ct-series-a .ct-point,.chartist-grey .ct-series-a .ct-slice-donut{stroke:rgba(158,158,158,1)}.chartist-grey .ct-series-b .ct-bar,.chartist-grey .ct-series-b .ct-line,.chartist-grey .ct-series-b .ct-point,.chartist-grey .ct-series-b .ct-slice-donut{stroke:rgba(158,158,158,.7)}.chartist-grey .ct-series-c .ct-bar,.chartist-grey .ct-series-c .ct-line,.chartist-grey .ct-series-c .ct-point,.chartist-grey .ct-series-c .ct-slice-donut{stroke:rgba(158,158,158,.4)}.chartist-grey .ct-series-d .ct-bar,.chartist-grey .ct-series-d .ct-line,.chartist-grey .ct-series-d .ct-point,.chartist-grey .ct-series-d .ct-slice-donut{stroke:rgba(158,158,158,.2)}.chartist-grey .ct-series-a .ct-area,.chartist-grey .ct-series-a .ct-slice-donut-solid,.chartist-grey .ct-series-a .ct-slice-pie{fill:rgba(158,158,158,1)}.chartist-grey .ct-series-b .ct-area,.chartist-grey .ct-series-b .ct-slice-donut-solid,.chartist-grey .ct-series-b .ct-slice-pie{fill:rgba(158,158,158,.7)}.chartist-grey .ct-series-c .ct-area,.chartist-grey .ct-series-c .ct-slice-donut-solid,.chartist-grey .ct-series-c .ct-slice-pie{fill:rgba(158,158,158,.4)}.chartist-grey .ct-series-d .ct-area,.chartist-grey .ct-series-d .ct-slice-donut-solid,.chartist-grey .ct-series-d .ct-slice-pie{fill:rgba(158,158,158,.2)}.chartist-blue.text-white-grey .ct-label{fill:#fff;color:#fff}.chartist-blue-grey .ct-label{fill:rgba(96,125,139,.4);color:rgba(96,125,139,.4)}.chartist-blue-grey .ct-grid{stroke:rgba(96,125,139,.2)}.chartist-blue-grey .ct-series-a .ct-bar,.chartist-blue-grey .ct-series-a .ct-line,.chartist-blue-grey .ct-series-a .ct-point,.chartist-blue-grey .ct-series-a .ct-slice-donut{stroke:rgba(96,125,139,1)}.chartist-blue-grey .ct-series-b .ct-bar,.chartist-blue-grey .ct-series-b .ct-line,.chartist-blue-grey .ct-series-b .ct-point,.chartist-blue-grey .ct-series-b .ct-slice-donut{stroke:rgba(96,125,139,.7)}.chartist-blue-grey .ct-series-c .ct-bar,.chartist-blue-grey .ct-series-c .ct-line,.chartist-blue-grey .ct-series-c .ct-point,.chartist-blue-grey .ct-series-c .ct-slice-donut{stroke:rgba(96,125,139,.4)}.chartist-blue-grey .ct-series-d .ct-bar,.chartist-blue-grey .ct-series-d .ct-line,.chartist-blue-grey .ct-series-d .ct-point,.chartist-blue-grey .ct-series-d .ct-slice-donut{stroke:rgba(96,125,139,.2)}.chartist-blue-grey .ct-series-a .ct-area,.chartist-blue-grey .ct-series-a .ct-slice-donut-solid,.chartist-blue-grey .ct-series-a .ct-slice-pie{fill:rgba(96,125,139,1)}.chartist-blue-grey .ct-series-b .ct-area,.chartist-blue-grey .ct-series-b .ct-slice-donut-solid,.chartist-blue-grey .ct-series-b .ct-slice-pie{fill:rgba(96,125,139,.7)}.chartist-blue-grey .ct-series-c .ct-area,.chartist-blue-grey .ct-series-c .ct-slice-donut-solid,.chartist-blue-grey .ct-series-c .ct-slice-pie{fill:rgba(96,125,139,.4)}.chartist-blue-grey .ct-series-d .ct-area,.chartist-blue-grey .ct-series-d .ct-slice-donut-solid,.chartist-blue-grey .ct-series-d .ct-slice-pie{fill:rgba(96,125,139,.2)}.chartist-black.text-black .ct-label{fill:#000;color:#000}.chartist-black.text-white .ct-label{fill:#fff;color:#fff}.chartist-black .ct-label{fill:rgba(0,0,0,.4);color:rgba(0,0,0,.4)}.chartist-black .ct-grid{stroke:rgba(0,0,0,.2)}.chartist-black .ct-series-a .ct-bar,.chartist-black .ct-series-a .ct-line,.chartist-black .ct-series-a .ct-point,.chartist-black .ct-series-a .ct-slice-donut{stroke:rgba(0,0,0,1)}.chartist-black .ct-series-b .ct-bar,.chartist-black .ct-series-b .ct-line,.chartist-black .ct-series-b .ct-point,.chartist-black .ct-series-b .ct-slice-donut{stroke:rgba(0,0,0,.7)}.chartist-black .ct-series-c .ct-bar,.chartist-black .ct-series-c .ct-line,.chartist-black .ct-series-c .ct-point,.chartist-black .ct-series-c .ct-slice-donut{stroke:rgba(0,0,0,.4)}.chartist-black .ct-series-d .ct-bar,.chartist-black .ct-series-d .ct-line,.chartist-black .ct-series-d .ct-point,.chartist-black .ct-series-d .ct-slice-donut{stroke:rgba(0,0,0,.2)}.chartist-black .ct-series-a .ct-area,.chartist-black .ct-series-a .ct-slice-donut-solid,.chartist-black .ct-series-a .ct-slice-pie{fill:rgba(0,0,0,1)}.chartist-black .ct-series-b .ct-area,.chartist-black .ct-series-b .ct-slice-donut-solid,.chartist-black .ct-series-b .ct-slice-pie{fill:rgba(0,0,0,.7)}.chartist-black .ct-series-c .ct-area,.chartist-black .ct-series-c .ct-slice-donut-solid,.chartist-black .ct-series-c .ct-slice-pie{fill:rgba(0,0,0,.4)}.chartist-black .ct-series-d .ct-area,.chartist-black .ct-series-d .ct-slice-donut-solid,.chartist-black .ct-series-d .ct-slice-pie{fill:rgba(0,0,0,.2)}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/chartjs.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/chartjs.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/chartjs.min.css
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/cover.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/cover.min.css
new file mode 100755
index 0000000..3b133ba
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/cover.min.css
@@ -0,0 +1 @@
+.cover{padding:15px;background-position:50% 50%;background-size:cover;background-repeat:no-repeat;width:100%;position:relative}.cover.cover-200{height:300px}.cover.cover-200{height:300px}.cover.cover-400{height:400px}.cover.cover-500{height:500px}.cover.no-padding{padding:0}.cover .avatar{height:100px;border-width:4px;margin-bottom:5px}.cover .item .avatar{height:50px}.cover .float-bottom-center,.cover .float-bottom-left,.cover .float-bottom-right{margin-bottom:-30px;z-index:99;position:absolute}.cover .big.float-bottom-center,.cover .big.float-bottom-left,.cover .big.float-bottom-right{margin-bottom:-35px}.cover .small.float-bottom-center,.cover .small.float-bottom-left,.cover .small.float-bottom-right{margin-bottom:-25px}.cover .float-bottom-center{left:50%;margin-left:-21px}.cover .small.float-bottom-center{left:50%;margin-left:-15px}.cover .big.float-bottom-center{left:50%;margin-left:-25px}.cover .gradient{background:-webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,.65) 100%);background:linear-gradient(to bottom,rgba(0,0,0,0) 0,rgba(0,0,0,.65) 100%);width:100%;padding-bottom:10px;padding-top:20px}.cover.blend-multiply{background-blend-mode:multiply}.cover.blend-screen{background-blend-mode:screen}.cover.blend-overlay{background-blend-mode:overlay}.cover.blend-darken{background-blend-mode:darken}.cover.blend-lighten{background-blend-mode:lighten}.cover.blend-color-dodge{background-blend-mode:color-dodge}.cover.blend-color-burn{background-blend-mode:color-burn}.cover.blend-hard-light{background-blend-mode:hard-light}.cover.blend-soft-light{background-blend-mode:soft-light}.cover.blend-luminosity{background-blend-mode:luminosity}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/fonts/ionicons.woff b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/ionicons.woff
new file mode 100644
index 0000000..5f3a14e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/ionicons.woff
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/fonts/roboto.woff2 b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/roboto.woff2
new file mode 100644
index 0000000..46f1cde
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/roboto.woff2
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotoblack.woff2 b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotoblack.woff2
new file mode 100644
index 0000000..f193280
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotoblack.woff2
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotolight.woff2 b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotolight.woff2
new file mode 100644
index 0000000..eacda32
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/fonts/robotolight.woff2
Binary files differ
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/gfont.css b/platforms/android/app/src/main/assets/www/mobileui/css/gfont.css
new file mode 100644
index 0000000..c0fb730
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/gfont.css
@@ -0,0 +1,304 @@
+/* latin */
+@font-face {
+  font-family: 'Chewy';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Chewy Regular'), local('Chewy-Regular'), url(https://fonts.gstatic.com/s/chewy/v10/uK_94ruUb-k-wn52KjI9OPec.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Dosis';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Dosis Regular'), local('Dosis-Regular'), url(https://fonts.gstatic.com/s/dosis/v8/HhyaU5sn9vOmLzlmC_WoEoZKdbA.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Dosis';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Dosis Regular'), local('Dosis-Regular'), url(https://fonts.gstatic.com/s/dosis/v8/HhyaU5sn9vOmLzloC_WoEoZK.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin */
+@font-face {
+  font-family: 'Monoton';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Monoton'), local('Monoton-Regular'), url(https://fonts.gstatic.com/s/monoton/v8/5h1aiZUrOngCibe4TkHLQka4BU4.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OX-hpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OVuhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXuhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OUehpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXehpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXOhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OUuhpKKSTjw.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Raleway Light'), local('Raleway-Light'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwIYqWqhPANqczVsq4A.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Raleway Light'), local('Raleway-Light'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwIYqWqZPANqczVs.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Raleway'), local('Raleway-Regular'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptug8zYS_SKggPNyCMIT4ttDfCmxA.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Raleway'), local('Raleway-Regular'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptug8zYS_SKggPNyC0IT4ttDfA.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  src: local('Raleway Bold'), local('Raleway-Bold'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwJYtWqhPANqczVsq4A.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  src: local('Raleway Bold'), local('Raleway-Bold'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwJYtWqZPANqczVs.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fABc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCBc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fBxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fChc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fBBc4AMP6lQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCRc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfABc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCBc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfBxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfChc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfBBc4AMP6lQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/grid.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/grid.min.css
new file mode 100755
index 0000000..d3e0e6e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/grid.min.css
@@ -0,0 +1 @@
+.row{display:-webkit-box;display:-ms-flexbox;display:flex}.row-between{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.row-around{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around}.row-stretch{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.column{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.wrap{-ms-flex-wrap:wrap;flex-wrap:wrap}.vertical-align-top{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.vertical-align-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.vertical-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.horizontal-align-left{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.horizontal-align-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.horizontal-align-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.row-center{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.col{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}.col-10{position:relative;-ms-flex-preferred-size:10%;flex-basis:10%}.col-20{position:relative;-ms-flex-preferred-size:20%;flex-basis:20%}.col-25{position:relative;-ms-flex-preferred-size:25%;flex-basis:25%}.col-33,.col-34{position:relative;-ms-flex-preferred-size:33.3333%;flex-basis:33.3333%}.col-50{position:relative;-ms-flex-preferred-size:50%;flex-basis:50%}.col-66,.col-67{position:relative;-ms-flex-preferred-size:66.6666%;flex-basis:66.6666%}.col-75{position:relative;-ms-flex-preferred-size:75%;flex-basis:75%}.col-80{position:relative;-ms-flex-preferred-size:80%;flex-basis:80%}.col-90{position:relative;-ms-flex-preferred-size:100%;flex-basis:100%}.full-width{width:100%;margin:0 auto}.full-height{height:100%;margin:0 auto}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/header.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/header.min.css
new file mode 100755
index 0000000..0981cb8
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/header.min.css
@@ -0,0 +1 @@
+.footer,.header{font-size:18px;display:inline-block;width:100%;position:fixed;top:0;left:0;height:52px;z-index:9}.footer{top:initial;bottom:0}.header.sub{top:52px}.footer.sub{top:initial;bottom:52px}.has-header{padding-top:52px!important}.has-header.has-sub-header{padding-top:104px!important}.has-footer{padding-bottom:52px!important}.has-footer.has-sub-footer{padding-bottom:104px!important}.footer .left,.footer .right,.footer .title,.footer h1,.header .left,.header .right,.header .title,.header h1{margin-top:15px;margin-bottom:5px}.header .avatar{height:40px;margin-top:-8px;margin-left:4px}.header .border-big{border-width:2px;border-style:solid}.footer h2,.header h2{padding-top:8px;padding-left:10px}.footer p,.header p{padding-left:10px;margin:0;margin-top:-4px}.footer .left,.header .left{padding-left:5px}.footer .right,.header .right{padding-right:5px}.footer .title,.footer h1,.header .title,.header h1{margin-bottom:15px;padding-left:10px;padding-right:15px;display:inline-block}.footer button,.header button{margin-top:-10px}.footer button.icon,.header button.icon{font-size:30px;margin-top:-10px;z-index:99;background:0 0;border:none;padding:0 6px}.footer button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]),.header button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]){color:#fff}.footer button.icon.left,.footer button.icon.right,.header button.icon.left,.header button.icon.right{margin-top:5px;margin-bottom:5px}.footer button.icon.left,.header button.icon.left{margin-left:5px}.footer button.icon.right,.header button.icon.right{margin-right:5px}.footer .title.align-center,.footer h1.align-center,.footer p.align-center,.header .title.align-center,.header h1.align-center,.header p.align-center{width:100%;position:inherit;padding-right:15px;left:0;z-index:9}.footer .icon-badge,.header .icon-badge{position:absolute;margin-left:-6px;margin-top:-8px;border-radius:8px;z-index:999}.footer .buttons-group,.header .buttons-group{margin-top:15px;margin-left:5px;margin-right:5px}.footer .buttons-group.small,.header .buttons-group.small{margin-top:20px;margin-left:10px;margin-right:10px}.header input::-webkit-input-placeholder{color:rgba(0,0,0,.8)}.header input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.8)}.header input{padding:15px;position:absolute}.header .left+input{padding-right:50px}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/horizontal-scroll.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/horizontal-scroll.min.css
new file mode 100755
index 0000000..2ce80d4
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/horizontal-scroll.min.css
@@ -0,0 +1 @@
+.horizontal-scroll{width:100%;position:relative;border:1px solid #ddd;display:flex;display:-moz-flex;display:-ms-flexbox;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}.horizontal-scroll.no-scroll-bar::-webkit-scrollbar{display:none}.horizontal-scroll .item{padding:15px;display:inline-block;flex:0 0 auto;width:100%;border-right:1px solid #ddd;position:relative;font-size:18px}.horizontal-scroll .item.hidden{display:none}.horizontal-scroll .item.mark{border-right:0;border-bottom:0;border-top:0}.item .block{display:-webkit-box;display:flex}.horizontal-scroll .item.mark.margin-right{border-right:0;margin-right:10px}.horizontal-scroll .item.space-small{padding-left:5px;padding-right:5px}.horizontal-scroll.space-small .item{padding-left:5px;padding-right:5px}.horizontal-scroll .item.no-space-left{padding-left:0!important}.horizontal-scroll .item.no-space-right{padding-right:0!important}.horizontal-scroll.no-space-left .item{padding-left:0!important}.horizontal-scroll.no-space-right .item{padding-right:0!important}.horizontal-scroll.no-space-top .item{padding-top:0!important}.horizontal-scroll.no-space-bottom .item{padding-bottom:0!important}.horizontal-scroll.no-space .item{padding-left:0!important;padding-right:0!important;padding-top:0!important;padding-bottom:0!important}.horizontal-scroll .item.row{display:-moz-flex;display:-ms-flexbox;display:flex}.horizontal-scroll .item.full{width:100%}.horizontal-scroll .item.three-fourth{width:75%}.horizontal-scroll .item.half{width:50%}.horizontal-scroll .item.one-fourth{width:25%}.horizontal-scroll .item h1,.horizontal-scroll .item h2{font-size:16px;margin:0;padding:0}.horizontal-scroll .item h1{margin-top:7px}.horizontal-scroll .item p{font-size:14px;margin:0;padding:0;line-height:20px}.horizontal-scroll .left{margin-right:10px;min-width:25px}.horizontal-scroll .right{margin-right:20px;position:absolute;top:0;right:0;height:100%;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}.horizontal-scroll .right i{margin-left:5px}.horizontal-scroll .align-top{-ms-flex-align:center;-webkit-align-items:center;align-items:baseline;margin-top:10px}.horizontal-scroll .avatar{height:50px}.avatar-badge{position:absolute;margin-left:-4px;margin-top:-3px;border-radius:8px}.horizontal-scroll .item small,.horizontal-scroll .item small .icon{font-size:14px}.horizontal-scroll .item .icon{font-size:18px}.horizontal-scroll .item .icon.text-huge{font-size:32px}.horizontal-scroll .left .icon,.horizontal-scroll .right .icon{vertical-align:-webkit-baseline-middle}.horizontal-scroll .border-big{border-width:3px;border-style:solid}.horizontal-scroll.no-border{border:0}.horizontal-scroll .item.no-border.border-right,.horizontal-scroll.no-border .item.border-right{border-right-width:1px;border-right-style:solid}.horizontal-scroll .item.no-border,.horizontal-scroll.no-border .item{border:none}.horizontal-scroll .item:last-child{border-right:0}.horizontal-scroll .item .right .icon,.horizontal-scroll .item .right.icon{font-size:24px;padding:0;margin:0}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/imports.css b/platforms/android/app/src/main/assets/www/mobileui/css/imports.css
new file mode 100755
index 0000000..510317d
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/imports.css
@@ -0,0 +1,30 @@
+@import url("./alert.min.css");
+@import url("./base.min.css");
+@import url("./button.min.css");
+@import url("./chart-bar.min.css");
+@import url("./chartist.min.css");
+@import url("./chartist-plugin-tooltip.min.css");
+@import url("./chartjs.min.css");
+@import url("./cover.min.css");
+@import url("./grid.min.css");
+@import url("./header.min.css");
+@import url("./horizontal-scroll.min.css");
+@import url("./include.min.css");
+@import url("./input.min.css");
+@import url("./jquery.min.css");
+@import url("./list.min.css");
+@import url("./loading.min.css");
+@import url("./menu.min.css");
+@import url("./mobileui-colors.min.css");
+@import url("./mobileuijs.min.css");
+@import url("./momentjs.min.css");
+@import url("./page.min.css");
+@import url("./popover.min.css");
+@import url("./progress-circle.min.css");
+@import url("./progress-semicircle.min.css");
+@import url("./progressbarjs.min.css");
+@import url("./pulltorefresh.min.css");
+@import url("./swiper.min.css");
+@import url("./tab.min.css");
+@import url("./timeline.min.css");
+@import url("./toast.min.css");
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/include.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/include.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/include.min.css
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/input.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/input.min.css
new file mode 100755
index 0000000..e68a220
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/input.min.css
@@ -0,0 +1 @@
+input,select,textarea{border:none;background:0 0;font-size:14px;width:100%;-webkit-flex:1;-ms-flex:1;flex:1}input[disabled],select[disabled],textarea[disabled]{opacity:.8}label{font-size:14px}.item.label-fixed,.label-fixed{display:-moz-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.label-fixed label{-webkit-flex:0 0 100px;-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}.label-float label{margin-bottom:0;-webkit-transform:translate3d(0,27px,0);transform:translate3d(0,27px,0);-webkit-transform-origin:left top;transform-origin:left top;transition:-webkit-transform 150ms ease-in-out;transition:transform 150ms ease-in-out;transition:transform 150ms ease-in-out,-webkit-transform 150ms ease-in-out;align-self:stretch;-webkit-flex:initial;-ms-flex:initial;flex:initial;display:block}.label-float label.focus{-webkit-transform:translate3d(0,0,0) scale(.8);transform:translate3d(0,0,0) scale(.8)}.item.icon{display:flex}.item.icon.radius{border-radius:6px}.item.icon:not([class*=text-]){color:#9f9f9f}.item input::-webkit-input-placeholder{color:rgba(0,0,0,.6)}.item input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.6)}.item.icon:before{position:absolute}.item.icon.icon-right:before{right:20px}.item.icon input,.item.icon select{padding-left:30px}.item.icon.icon-right input,.item.icon.icon-right select{padding-left:0;padding-right:30px}input[type=checkbox]{width:17px;height:17px;z-index:1;border:0;vertical-align:top;outline:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:2px}.platform-ios input[type=checkbox]{height:23px;width:23px;border-radius:50%}input[type=checkbox]:not(:checked){background-color:#fff!important;box-shadow:inset 0 0 0 2px rgba(0,0,0,.5)}.platform-ios input[type=checkbox]:not(:checked){box-shadow:inset 0 0 0 1px rgba(0,0,0,.4)}input[type=checkbox]:disabled{opacity:.4}input[type=checkbox]::before{content:'';position:absolute;margin-top:1px;margin-left:5px;width:5px;height:10px;border-width:2px;border-top-width:0;border-left-width:0;border-style:solid;border-color:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.platform-ios input[type=checkbox]::before{margin-top:5px;margin-left:9px;width:4px;height:9px;border-width:1px;border-top-width:0;border-left-width:0}input[type=checkbox].switch{width:36px;height:14px;box-shadow:inset 0 0 0 30px rgba(255,255,255,.4);border-radius:28px;-webkit-transition-property:all;transition-property:all;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.platform-ios input[type=checkbox].switch{height:32px;width:51px;box-shadow:inset 0 0 0 2px rgba(0,0,0,.05)}input[type=checkbox].switch:not(:checked){background-color:#fff!important;box-shadow:inset 0 0 0 30px rgba(0,0,0,.35)}.platform-ios input[type=checkbox].switch:not(:checked){box-shadow:inset 0 0 0 2px rgba(0,0,0,.1)}input[type=checkbox].switch::before{content:'';border-radius:28px;height:20px;width:20px;margin-left:-1px;margin-top:-3px;-webkit-transition-duration:.35s;transition-duration:.35s;box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.4);border:0}.platform-ios input[type=checkbox].switch::before{height:28px;width:28px;box-shadow:0 0 0 1px #e4e4e4,0 3px 2px rgba(0,0,0,.25);margin-top:2px;margin-left:2px;background-color:#fff!important}input[type=checkbox].switch:checked::before{margin-left:16px}input[type=checkbox].switch:not(:checked)::before{background-color:#fff!important}.platform-ios input[type=checkbox].switch:checked::before{margin-left:21px;box-shadow:0 3px 2px rgba(0,0,0,.25);background-color:#fff}input[type=radio]{width:20px;height:20px;border-radius:50%;position:relative;overflow:hidden;z-index:1;vertical-align:top;outline:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0}.platform-ios input[type=radio]{background:0 0!important}input[type=radio]::after{content:'';width:100%;height:100%;position:absolute;border-radius:50%}.platform-ios input[type=radio]:not(:checked)::after{box-shadow:none}input[type=radio]:not(:checked)::after{box-shadow:inset 0 0 0 2px rgba(0,0,0,.4);background-color:#fff!important}input[type=radio]:checked::before{content:'';width:10px;height:10px;position:absolute;border:3px solid #fff;z-index:1;border-radius:50%;margin-top:2px;margin-left:2px}input[type=radio]:disabled{opacity:.4}.platform-ios input[type=radio]::after{background:0 0!important}.platform-ios input[type=radio]:checked::before{position:absolute;margin-top:4px;margin-left:7px;width:5px;height:12px;border-width:2px;border-top-width:0;border-left-width:0;border-style:solid;-webkit-transform:rotate(45deg);transform:rotate(45deg);border-radius:0}.item.range{position:relative;-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.item.range input{position:absolute;height:28px;width:calc(100% - 110px);margin:4px 0 5px 0;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;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:100% 2px;background-repeat:no-repeat;outline:0;border:none;box-sizing:content-box;-ms-background-position-y:500px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background-color:#666;width:13px;height:13px;border-radius:50%}input[type=range]:active::-webkit-slider-thumb{width:20px;height:20px}.platform-ios input[type=range]::-webkit-slider-thumb{background-color:#fff;box-shadow:1px 1px 5px rgba(0,0,0,.3);width:25px;height:25px;border:1px solid rgba(0,0,0,.05);border-radius:50%}input[type=checkbox].red-50.switch::before,input[type=radio].red-50::after{background-color:#ffebee}input[type=checkbox].red-100.switch::before,input[type=radio].red-100::after{background-color:#ffcdd2}input[type=checkbox].red-200.switch::before,input[type=radio].red-200::after{background-color:#ef9a9a}input[type=checkbox].red-300.switch::before,input[type=radio].red-300::after{background-color:#e57373}input[type=checkbox].red-400.switch::before,input[type=radio].red-400::after{background-color:#ef5350}input[type=checkbox].red-500.switch::before,input[type=radio].red-500::after{background-color:#f44336}input[type=checkbox].red-600.switch::before,input[type=radio].red-600::after{background-color:#e53935}input[type=checkbox].red-700.switch::before,input[type=radio].red-700::after{background-color:#d32f2f}input[type=checkbox].red-800.switch::before,input[type=radio].red-800::after{background-color:#c62828}input[type=checkbox].red-900.switch::before,input[type=radio].red-900::after{background-color:#b71c1c}input[type=checkbox].pink.switch::before,input[type=radio].pink::after{background-color:#e91e63}input[type=checkbox].pink-50.switch::before,input[type=radio].pink-50::after{background-color:#fce4ec}input[type=checkbox].pink-100.switch::before,input[type=radio].pink-100::after{background-color:#f8bbd0}input[type=checkbox].pink-200.switch::before,input[type=radio].pink-200::after{background-color:#f48fb1}input[type=checkbox].Pink-300.switch::before,input[type=radio].Pink-300::after{background-color:#f06292}input[type=checkbox].pink-400.switch::before,input[type=radio].pink-400::after{background-color:#ec407a}input[type=checkbox].pink-500.switch::before,input[type=radio].pink-500::after{background-color:#e91e63}input[type=checkbox].pink-600.switch::before,input[type=radio].pink-600::after{background-color:#d81b60}input[type=checkbox].pink-700.switch::before,input[type=radio].pink-700::after{background-color:#c2185b}input[type=checkbox].pink-800.switch::before,input[type=radio].pink-800::after{background-color:#ad1457}input[type=checkbox].pink-900.switch::before,input[type=radio].pink-900::after{background-color:#880e4f}input[type=checkbox].purple.switch::before,input[type=radio].purple::after{background-color:#9c27b0}input[type=checkbox].purple-50.switch::before,input[type=radio].purple-50::after{background-color:#f3e5f5}input[type=checkbox].purple-100.switch::before,input[type=radio].purple-100::after{background-color:#e1bee7}input[type=checkbox].purple-200.switch::before,input[type=radio].purple-200::after{background-color:#ce93d8}input[type=checkbox].Purple-300.switch::before,input[type=radio].Purple-300::after{background-color:#ba68c8}input[type=checkbox].Purple-400.switch::before,input[type=radio].Purple-400::after{background-color:#ab47bc}input[type=checkbox].purple-500.switch::before,input[type=radio].purple-500::after{background-color:#9c27b0}input[type=checkbox].purple-600.switch::before,input[type=radio].purple-600::after{background-color:#8e24aa}input[type=checkbox].purple-700.switch::before,input[type=radio].purple-700::after{background-color:#7b1fa2}input[type=checkbox].purple-800.switch::before,input[type=radio].purple-800::after{background-color:#6a1b9a}input[type=checkbox].purple-900.switch::before,input[type=radio].purple-900::after{background-color:#4a148c}input[type=checkbox].deep-purple.switch::before,input[type=radio].deep-purple::after{background-color:#673ab7}input[type=checkbox].deep-purple-300.switch::before,input[type=radio].deep-purple-300::after{background-color:#9575cd}input[type=checkbox].deep-purple-400.switch::before,input[type=radio].deep-purple-400::after{background-color:#7e57c2}input[type=checkbox].deep-purple-500.switch::before,input[type=radio].deep-purple-500::after{background-color:#673ab7}input[type=checkbox].deep-purple-600.switch::before,input[type=radio].deep-purple-600::after{background-color:#5e35b1}input[type=checkbox].deep-purple-700.switch::before,input[type=radio].deep-purple-700::after{background-color:#512da8}input[type=checkbox].deep-purple-800.switch::before,input[type=radio].deep-purple-800::after{background-color:#4527a0}input[type=checkbox].deep-purple-900.switch::before,input[type=radio].deep-purple-900::after{background-color:#311b92}input[type=checkbox].indigo.switch::before,input[type=radio].indigo::after{background-color:#3f51b5}input[type=checkbox].indigo-50.switch::before,input[type=radio].indigo-50::after{background-color:#e8eaf6}input[type=checkbox].indigo-100.switch::before,input[type=radio].indigo-100::after{background-color:#c5cae9}input[type=checkbox].indigo-200.switch::before,input[type=radio].indigo-200::after{background-color:#9fa8da}input[type=checkbox].indigo-300.switch::before,input[type=radio].indigo-300::after{background-color:#7986cb}input[type=checkbox].indigo-400.switch::before,input[type=radio].indigo-400::after{background-color:#5c6bc0}input[type=checkbox].indigo-500.switch::before,input[type=radio].indigo-500::after{background-color:#3f51b5}input[type=checkbox].indigo-600.switch::before,input[type=radio].indigo-600::after{background-color:#3949ab}input[type=checkbox].indigo-700.switch::before,input[type=radio].indigo-700::after{background-color:#303f9f}input[type=checkbox].indigo-800.switch::before,input[type=radio].indigo-800::after{background-color:#283593}input[type=checkbox].indigo-900.switch::before,input[type=radio].indigo-900::after{background-color:#1a237e}input[type=checkbox].blue.switch::before,input[type=radio].blue::after{background-color:#2196f3}input[type=checkbox].blue-50.switch::before,input[type=radio].blue-50::after{background-color:#e3f2fd}input[type=checkbox].blue-100.switch::before,input[type=radio].blue-100::after{background-color:#bbdefb}input[type=checkbox].blue-200.switch::before,input[type=radio].blue-200::after{background-color:#90caf9}input[type=checkbox].blue-300.switch::before,input[type=radio].blue-300::after{background-color:#64b5f6}input[type=checkbox].blue-400.switch::before,input[type=radio].blue-400::after{background-color:#42a5f5}input[type=checkbox].blue-500.switch::before,input[type=radio].blue-500::after{background-color:#2196f3}input[type=checkbox].blue-600.switch::before,input[type=radio].blue-600::after{background-color:#1e88e5}input[type=checkbox].blue-700.switch::before,input[type=radio].blue-700::after{background-color:#1976d2}input[type=checkbox].blue-800.switch::before,input[type=radio].blue-800::after{background-color:#1565c0}input[type=checkbox].blue-900.switch::before,input[type=radio].blue-900::after{background-color:#0d47a1}input[type=checkbox].light-blue.switch::before,input[type=radio].light-blue::after{background-color:#03a9f4}input[type=checkbox].light-blue-50.switch::before,input[type=radio].light-blue-50::after{background-color:#e1f5fe}input[type=checkbox].light-blue-100.switch::before,input[type=radio].light-blue-100::after{background-color:#b3e5fc}input[type=checkbox].light-blue-200.switch::before,input[type=radio].light-blue-200::after{background-color:#81d4fa}input[type=checkbox].light-blue-300.switch::before,input[type=radio].light-blue-300::after{background-color:#4fc3f7}input[type=checkbox].light-blue-400.switch::before,input[type=radio].light-blue-400::after{background-color:#29b6f6}input[type=checkbox].light-blue-500.switch::before,input[type=radio].light-blue-500::after{background-color:#03a9f4}input[type=checkbox].light-blue-600.switch::before,input[type=radio].light-blue-600::after{background-color:#039be5}input[type=checkbox].light-blue-700.switch::before,input[type=radio].light-blue-700::after{background-color:#0288d1}input[type=checkbox].light-blue-800.switch::before,input[type=radio].light-blue-800::after{background-color:#0277bd}input[type=checkbox].light-blue-900.switch::before,input[type=radio].light-blue-900::after{background-color:#01579b}input[type=checkbox].cyan.switch::before,input[type=radio].cyan::after{background-color:#00bcd4}input[type=checkbox].cyan-50.switch::before,input[type=radio].cyan-50::after{background-color:#e0f7fa}input[type=checkbox].cyan-100.switch::before,input[type=radio].cyan-100::after{background-color:#b2ebf2}input[type=checkbox].cyan-200.switch::before,input[type=radio].cyan-200::after{background-color:#80deea}input[type=checkbox].cyan-300.switch::before,input[type=radio].cyan-300::after{background-color:#4dd0e1}input[type=checkbox].cyan-400.switch::before,input[type=radio].cyan-400::after{background-color:#26c6da}input[type=checkbox].cyan-500.switch::before,input[type=radio].cyan-500::after{background-color:#00bcd4}input[type=checkbox].cyan-600.switch::before,input[type=radio].cyan-600::after{background-color:#00acc1}input[type=checkbox].cyan-700.switch::before,input[type=radio].cyan-700::after{background-color:#0097a7}input[type=checkbox].cyan-800.switch::before,input[type=radio].cyan-800::after{background-color:#00838f}input[type=checkbox].cyan-900.switch::before,input[type=radio].cyan-900::after{background-color:#006064}input[type=checkbox].teal.switch::before,input[type=radio].teal::after{background-color:#009688}input[type=checkbox].teal-50.switch::before,input[type=radio].teal-50::after{background-color:#e0f2f1}input[type=checkbox].teal-100.switch::before,input[type=radio].teal-100::after{background-color:#b2dfdb}input[type=checkbox].teal-200.switch::before,input[type=radio].teal-200::after{background-color:#80cbc4}input[type=checkbox].teal-300.switch::before,input[type=radio].teal-300::after{background-color:#4db6ac}input[type=checkbox].teal-400.switch::before,input[type=radio].teal-400::after{background-color:#26a69a}input[type=checkbox].teal-500.switch::before,input[type=radio].teal-500::after{background-color:#009688}input[type=checkbox].teal-600.switch::before,input[type=radio].teal-600::after{background-color:#00897b}input[type=checkbox].teal-700.switch::before,input[type=radio].teal-700::after{background-color:#00796b}input[type=checkbox].teal-800.switch::before,input[type=radio].teal-800::after{background-color:#00695c}input[type=checkbox].teal-900.switch::before,input[type=radio].teal-900::after{background-color:#004d40}input[type=checkbox].green.switch::before,input[type=radio].green::after{background-color:#4caf50}input[type=checkbox].green-50.switch::before,input[type=radio].green-50::after{background-color:#e8f5e9}input[type=checkbox].green-100.switch::before,input[type=radio].green-100::after{background-color:#c8e6c9}input[type=checkbox].green-200.switch::before,input[type=radio].green-200::after{background-color:#a5d6a7}input[type=checkbox].green-300.switch::before,input[type=radio].green-300::after{background-color:#81c784}input[type=checkbox].green-400.switch::before,input[type=radio].green-400::after{background-color:#66bb6a}input[type=checkbox].green-500.switch::before,input[type=radio].green-500::after{background-color:#4caf50}input[type=checkbox].green-600.switch::before,input[type=radio].green-600::after{background-color:#43a047}input[type=checkbox].green-700.switch::before,input[type=radio].green-700::after{background-color:#388e3c}input[type=checkbox].green-800.switch::before,input[type=radio].green-800::after{background-color:#2e7d32}input[type=checkbox].green-900.switch::before,input[type=radio].green-900::after{background-color:#1b5e20}input[type=checkbox].light-green.switch::before,input[type=radio].light-green::after{background-color:#8bc34a}input[type=checkbox].light-green-50.switch::before,input[type=radio].light-green-50::after{background-color:#f1f8e9}input[type=checkbox].light-green-100.switch::before,input[type=radio].light-green-100::after{background-color:#dcedc8}input[type=checkbox].light-green-200.switch::before,input[type=radio].light-green-200::after{background-color:#c5e1a5}input[type=checkbox].light-green-300.switch::before,input[type=radio].light-green-300::after{background-color:#aed581}input[type=checkbox].light-green-400.switch::before,input[type=radio].light-green-400::after{background-color:#9ccc65}input[type=checkbox].light-green-500.switch::before,input[type=radio].light-green-500::after{background-color:#8bc34a}input[type=checkbox].light-green-600.switch::before,input[type=radio].light-green-600::after{background-color:#7cb342}input[type=checkbox].light-green-700.switch::before,input[type=radio].light-green-700::after{background-color:#689f38}input[type=checkbox].light-green-800.switch::before,input[type=radio].light-green-800::after{background-color:#558b2f}input[type=checkbox].light-green-900.switch::before,input[type=radio].light-green-900::after{background-color:#33691e}input[type=checkbox].lime.switch::before,input[type=radio].lime::after{background-color:#cddc39}input[type=checkbox].lime-50.switch::before,input[type=radio].lime-50::after{background-color:#f9fbe7}input[type=checkbox].lime-100.switch::before,input[type=radio].lime-100::after{background-color:#f0f4c3}input[type=checkbox].lime-200.switch::before,input[type=radio].lime-200::after{background-color:#e6ee9c}input[type=checkbox].lime-300.switch::before,input[type=radio].lime-300::after{background-color:#dce775}input[type=checkbox].lime-400.switch::before,input[type=radio].lime-400::after{background-color:#d4e157}input[type=checkbox].lime-500.switch::before,input[type=radio].lime-500::after{background-color:#cddc39}input[type=checkbox].lime-600.switch::before,input[type=radio].lime-600::after{background-color:#c0ca33}input[type=checkbox].lime-700.switch::before,input[type=radio].lime-700::after{background-color:#afb42b}input[type=checkbox].lime-800.switch::before,input[type=radio].lime-800::after{background-color:#9e9d24}input[type=checkbox].lime-900.switch::before,input[type=radio].lime-900::after{background-color:#827717}input[type=checkbox].yellow.switch::before,input[type=radio].yellow::after{background-color:#ffeb3b}input[type=checkbox].yellow-50.switch::before,input[type=radio].yellow-50::after{background-color:#fffde7}input[type=checkbox].yellow-100.switch::before,input[type=radio].yellow-100::after{background-color:#fff9c4}input[type=checkbox].yellow-200.switch::before,input[type=radio].yellow-200::after{background-color:#fff59d}input[type=checkbox].yellow-300.switch::before,input[type=radio].yellow-300::after{background-color:#fff176}input[type=checkbox].yellow-500.switch::before,input[type=radio].yellow-500::after{background-color:#ffeb3b}input[type=checkbox].yellow-600.switch::before,input[type=radio].yellow-600::after{background-color:#fdd835}input[type=checkbox].yellow-700.switch::before,input[type=radio].yellow-700::after{background-color:#fbc02d}input[type=checkbox].yellow-800.switch::before,input[type=radio].yellow-800::after{background-color:#f9a825}input[type=checkbox].yellow-900.switch::before,input[type=radio].yellow-900::after{background-color:#f57f17}input[type=checkbox].amber-50.switch::before,input[type=radio].amber-50::after{background-color:#fff8e1}input[type=checkbox].amber-100.switch::before,input[type=radio].amber-100::after{background-color:#ffecb3}input[type=checkbox].amber-200.switch::before,input[type=radio].amber-200::after{background-color:#ffe082}input[type=checkbox].amber-300.switch::before,input[type=radio].amber-300::after{background-color:#ffd54f}input[type=checkbox].amber-500.switch::before,input[type=radio].amber-500::after{background-color:#ffc107}input[type=checkbox].amber-600.switch::before,input[type=radio].amber-600::after{background-color:#ffb300}input[type=checkbox].amber-700.switch::before,input[type=radio].amber-700::after{background-color:#ffa000}input[type=checkbox].amber-800.switch::before,input[type=radio].amber-800::after{background-color:#ff8f00}input[type=checkbox].amber-900.switch::before,input[type=radio].amber-900::after{background-color:#ff6f00}input[type=checkbox].orange-50.switch::before,input[type=radio].orange-50::after{background-color:#fff3e0}input[type=checkbox].orange-100.switch::before,input[type=radio].orange-100::after{background-color:#ffe0b2}input[type=checkbox].orange-200.switch::before,input[type=radio].orange-200::after{background-color:#ffcc80}input[type=checkbox].orange-300.switch::before,input[type=radio].orange-300::after{background-color:#ffb74d}input[type=checkbox].orange-400.switch::before,input[type=radio].orange-400::after{background-color:#ffa726}input[type=checkbox].orange-500.switch::before,input[type=radio].orange-500::after{background-color:#ff9800}input[type=checkbox].orange-600.switch::before,input[type=radio].orange-600::after{background-color:#fb8c00}input[type=checkbox].orange-700.switch::before,input[type=radio].orange-700::after{background-color:#f57c00}input[type=checkbox].orange-800.switch::before,input[type=radio].orange-800::after{background-color:#ef6c00}input[type=checkbox].orange-900.switch::before,input[type=radio].orange-900::after{background-color:#e65100}input[type=checkbox].deep-orange.switch::before,input[type=radio].deep-orange::after{background-color:#ff5722}input[type=checkbox].deep-orange-50.switch::before,input[type=radio].deep-orange-50::after{background-color:#fbe9e7}input[type=checkbox].deep-orange-100.switch::before,input[type=radio].deep-orange-100::after{background-color:#ffccbc}input[type=checkbox].deep-orange-200.switch::before,input[type=radio].deep-orange-200::after{background-color:#ffab91}input[type=checkbox].deep-orange-300.switch::before,input[type=radio].deep-orange-300::after{background-color:#ff8a65}input[type=checkbox].deep-orange-400.switch::before,input[type=radio].deep-orange-400::after{background-color:#ff7043}input[type=checkbox].deep-orange-500.switch::before,input[type=radio].deep-orange-500::after{background-color:#ff5722}input[type=checkbox].deep-orange-600.switch::before,input[type=radio].deep-orange-600::after{background-color:#f4511e}input[type=checkbox].deep-orange-700.switch::before,input[type=radio].deep-orange-700::after{background-color:#e64a19}input[type=checkbox].deep-orange-800.switch::before,input[type=radio].deep-orange-800::after{background-color:#d84315}input[type=checkbox].deep-orange-900.switch::before,input[type=radio].deep-orange-900::after{background-color:#bf360c}input[type=checkbox].brown.switch::before,input[type=radio].brown::after{background-color:#795548}input[type=checkbox].brown-50.switch::before,input[type=radio].brown-50::after{background-color:#efebe9}input[type=checkbox].brown-100.switch::before,input[type=radio].brown-100::after{background-color:#d7ccc8}input[type=checkbox].brown-200.switch::before,input[type=radio].brown-200::after{background-color:#bcaaa4}input[type=checkbox].brown-300.switch::before,input[type=radio].brown-300::after{background-color:#a1887f}input[type=checkbox].brown-400.switch::before,input[type=radio].brown-400::after{background-color:#8d6e63}input[type=checkbox].brown-500.switch::before,input[type=radio].brown-500::after{background-color:#795548}input[type=checkbox].brown-600.switch::before,input[type=radio].brown-600::after{background-color:#6d4c41}input[type=checkbox].brown-700.switch::before,input[type=radio].brown-700::after{background-color:#5d4037}input[type=checkbox].brown-800.switch::before,input[type=radio].brown-800::after{background-color:#4e342e}input[type=checkbox].brown-900.switch::before,input[type=radio].brown-900::after{background-color:#3e2723}input[type=checkbox].grey.switch::before,input[type=radio].grey::after{background-color:#9e9e9e}input[type=checkbox].grey-50.switch::before,input[type=radio].grey-50::after{background-color:#fafafa}input[type=checkbox].grey-100.switch::before,input[type=radio].grey-100::after{background-color:#f5f5f5}input[type=checkbox].grey-200.switch::before,input[type=radio].grey-200::after{background-color:#eee}input[type=checkbox].grey-300.switch::before,input[type=radio].grey-300::after{background-color:#e0e0e0}input[type=checkbox].grey-400.switch::before,input[type=radio].grey-400::after{background-color:#bdbdbd}input[type=checkbox].grey-500.switch::before,input[type=radio].grey-500::after{background-color:#9e9e9e}input[type=checkbox].grey-600.switch::before,input[type=radio].grey-600::after{background-color:#757575}input[type=checkbox].grey-700.switch::before,input[type=radio].grey-700::after{background-color:#616161}input[type=checkbox].grey-800.switch::before,input[type=radio].grey-800::after{background-color:#424242}input[type=checkbox].grey-900.switch::before,input[type=radio].grey-900::after{background-color:#212121}input[type=checkbox].blue-grey.switch::before,input[type=radio].blue-grey::after{background-color:#607d8b}input[type=checkbox].blue-grey-50.switch::before,input[type=radio].blue-grey-50::after{background-color:#eceff1}input[type=checkbox].blue-grey-100.switch::before,input[type=radio].blue-grey-100::after{background-color:#cfd8dc}input[type=checkbox].blue-grey-200.switch::before,input[type=radio].blue-grey-200::after{background-color:#b0bec5}input[type=checkbox].blue-grey-300.switch::before,input[type=radio].blue-grey-300::after{background-color:#90a4ae}input[type=checkbox].blue-grey-400.switch::before,input[type=radio].blue-grey-400::after{background-color:#78909c}input[type=checkbox].blue-grey-500.switch::before,input[type=radio].blue-grey-500::after{background-color:#607d8b}input[type=checkbox].blue-grey-600.switch::before,input[type=radio].blue-grey-600::after{background-color:#546e7a}input[type=checkbox].blue-grey-700.switch::before,input[type=radio].blue-grey-700::after{background-color:#455a64}input[type=checkbox].blue-grey-800.switch::before,input[type=radio].blue-grey-800::after{background-color:#37474f}input[type=checkbox].blue-grey-900.switch::before,input[type=radio].blue-grey-900::after{background-color:#263238}input[type=checkbox].black.switch::before,input[type=radio].black::after{background-color:#000}.platform-ios input[type=radio].red-50::before{border-color:#ffebee}.platform-ios input[type=radio].red-100::before{border-color:#ffcdd2}.platform-ios input[type=radio].red-200::before{border-color:#ef9a9a}.platform-ios input[type=radio].red-300::before{border-color:#e57373}.platform-ios input[type=radio].red-400::before{border-color:#ef5350}.platform-ios input[type=radio].red-500::before{border-color:#f44336}.platform-ios input[type=radio].red-600::before{border-color:#e53935}.platform-ios input[type=radio].red-700::before{border-color:#d32f2f}.platform-ios input[type=radio].red-800::before{border-color:#c62828}.platform-ios input[type=radio].red-900::before{border-color:#b71c1c}.platform-ios input[type=radio].pink::before{border-color:#e91e63}.platform-ios input[type=radio].pink-50::before{border-color:#fce4ec}.platform-ios input[type=radio].pink-100::before{border-color:#f8bbd0}.platform-ios input[type=radio].pink-200::before{border-color:#f48fb1}.platform-ios input[type=radio].Pink-300::before{border-color:#f06292}.platform-ios input[type=radio].pink-400::before{border-color:#ec407a}.platform-ios input[type=radio].pink-500::before{border-color:#e91e63}.platform-ios input[type=radio].pink-600::before{border-color:#d81b60}.platform-ios input[type=radio].pink-700::before{border-color:#c2185b}.platform-ios input[type=radio].pink-800::before{border-color:#ad1457}.platform-ios input[type=radio].pink-900::before{border-color:#880e4f}.platform-ios input[type=radio].purple::before{border-color:#9c27b0}.platform-ios input[type=radio].purple-50::before{border-color:#f3e5f5}.platform-ios input[type=radio].purple-100::before{border-color:#e1bee7}.platform-ios input[type=radio].purple-200::before{border-color:#ce93d8}.platform-ios input[type=radio].Purple-300::before{border-color:#ba68c8}.platform-ios input[type=radio].Purple-400::before{border-color:#ab47bc}.platform-ios input[type=radio].purple-500::before{border-color:#9c27b0}.platform-ios input[type=radio].purple-600::before{border-color:#8e24aa}.platform-ios input[type=radio].purple-700::before{border-color:#7b1fa2}.platform-ios input[type=radio].purple-800::before{border-color:#6a1b9a}.platform-ios input[type=radio].purple-900::before{border-color:#4a148c}.platform-ios input[type=radio].deep-purple::before{border-color:#673ab7}.platform-ios input[type=radio].deep-purple-300::before{border-color:#9575cd}.platform-ios input[type=radio].deep-purple-400::before{border-color:#7e57c2}.platform-ios input[type=radio].deep-purple-500::before{border-color:#673ab7}.platform-ios input[type=radio].deep-purple-600::before{border-color:#5e35b1}.platform-ios input[type=radio].deep-purple-700::before{border-color:#512da8}.platform-ios input[type=radio].deep-purple-800::before{border-color:#4527a0}.platform-ios input[type=radio].deep-purple-900::before{border-color:#311b92}.platform-ios input[type=radio].indigo::before{border-color:#3f51b5}.platform-ios input[type=radio].indigo-50::before{border-color:#e8eaf6}.platform-ios input[type=radio].indigo-100::before{border-color:#c5cae9}.platform-ios input[type=radio].indigo-200::before{border-color:#9fa8da}.platform-ios input[type=radio].indigo-300::before{border-color:#7986cb}.platform-ios input[type=radio].indigo-400::before{border-color:#5c6bc0}.platform-ios input[type=radio].indigo-500::before{border-color:#3f51b5}.platform-ios input[type=radio].indigo-600::before{border-color:#3949ab}.platform-ios input[type=radio].indigo-700::before{border-color:#303f9f}.platform-ios input[type=radio].indigo-800::before{border-color:#283593}.platform-ios input[type=radio].indigo-900::before{border-color:#1a237e}.platform-ios input[type=radio].blue::before{border-color:#2196f3}.platform-ios input[type=radio].blue-50::before{border-color:#e3f2fd}.platform-ios input[type=radio].blue-100::before{border-color:#bbdefb}.platform-ios input[type=radio].blue-200::before{border-color:#90caf9}.platform-ios input[type=radio].blue-300::before{border-color:#64b5f6}.platform-ios input[type=radio].blue-400::before{border-color:#42a5f5}.platform-ios input[type=radio].blue-500::before{border-color:#2196f3}.platform-ios input[type=radio].blue-600::before{border-color:#1e88e5}.platform-ios input[type=radio].blue-700::before{border-color:#1976d2}.platform-ios input[type=radio].blue-800::before{border-color:#1565c0}.platform-ios input[type=radio].blue-900::before{border-color:#0d47a1}.platform-ios input[type=radio].light-blue::before{border-color:#03a9f4}.platform-ios input[type=radio].light-blue-50::before{border-color:#e1f5fe}.platform-ios input[type=radio].light-blue-100::before{border-color:#b3e5fc}.platform-ios input[type=radio].light-blue-200::before{border-color:#81d4fa}.platform-ios input[type=radio].light-blue-300::before{border-color:#4fc3f7}.platform-ios input[type=radio].light-blue-400::before{border-color:#29b6f6}.platform-ios input[type=radio].light-blue-500::before{border-color:#03a9f4}.platform-ios input[type=radio].light-blue-600::before{border-color:#039be5}.platform-ios input[type=radio].light-blue-700::before{border-color:#0288d1}.platform-ios input[type=radio].light-blue-800::before{border-color:#0277bd}.platform-ios input[type=radio].light-blue-900::before{border-color:#01579b}.platform-ios input[type=radio].cyan::before{border-color:#00bcd4}.platform-ios input[type=radio].cyan-50::before{border-color:#e0f7fa}.platform-ios input[type=radio].cyan-100::before{border-color:#b2ebf2}.platform-ios input[type=radio].cyan-200::before{border-color:#80deea}.platform-ios input[type=radio].cyan-300::before{border-color:#4dd0e1}.platform-ios input[type=radio].cyan-400::before{border-color:#26c6da}.platform-ios input[type=radio].cyan-500::before{border-color:#00bcd4}.platform-ios input[type=radio].cyan-600::before{border-color:#00acc1}.platform-ios input[type=radio].cyan-700::before{border-color:#0097a7}.platform-ios input[type=radio].cyan-800::before{border-color:#00838f}.platform-ios input[type=radio].cyan-900::before{border-color:#006064}.platform-ios input[type=radio].teal::before{border-color:#009688}.platform-ios input[type=radio].teal-50::before{border-color:#e0f2f1}.platform-ios input[type=radio].teal-100::before{border-color:#b2dfdb}.platform-ios input[type=radio].teal-200::before{border-color:#80cbc4}.platform-ios input[type=radio].teal-300::before{border-color:#4db6ac}.platform-ios input[type=radio].teal-400::before{border-color:#26a69a}.platform-ios input[type=radio].teal-500::before{border-color:#009688}.platform-ios input[type=radio].teal-600::before{border-color:#00897b}.platform-ios input[type=radio].teal-700::before{border-color:#00796b}.platform-ios input[type=radio].teal-800::before{border-color:#00695c}.platform-ios input[type=radio].teal-900::before{border-color:#004d40}.platform-ios input[type=radio].green::before{border-color:#4caf50}.platform-ios input[type=radio].green-50::before{border-color:#e8f5e9}.platform-ios input[type=radio].green-100::before{border-color:#c8e6c9}.platform-ios input[type=radio].green-200::before{border-color:#a5d6a7}.platform-ios input[type=radio].green-300::before{border-color:#81c784}.platform-ios input[type=radio].green-400::before{border-color:#66bb6a}.platform-ios input[type=radio].green-500::before{border-color:#4caf50}.platform-ios input[type=radio].green-600::before{border-color:#43a047}.platform-ios input[type=radio].green-700::before{border-color:#388e3c}.platform-ios input[type=radio].green-800::before{border-color:#2e7d32}.platform-ios input[type=radio].green-900::before{border-color:#1b5e20}.platform-ios input[type=radio].light-green::before{border-color:#8bc34a}.platform-ios input[type=radio].light-green-50::before{border-color:#f1f8e9}.platform-ios input[type=radio].light-green-100::before{border-color:#dcedc8}.platform-ios input[type=radio].light-green-200::before{border-color:#c5e1a5}.platform-ios input[type=radio].light-green-300::before{border-color:#aed581}.platform-ios input[type=radio].light-green-400::before{border-color:#9ccc65}.platform-ios input[type=radio].light-green-500::before{border-color:#8bc34a}.platform-ios input[type=radio].light-green-600::before{border-color:#7cb342}.platform-ios input[type=radio].light-green-700::before{border-color:#689f38}.platform-ios input[type=radio].light-green-800::before{border-color:#558b2f}.platform-ios input[type=radio].light-green-900::before{border-color:#33691e}.platform-ios input[type=radio].lime::before{border-color:#cddc39}.platform-ios input[type=radio].lime-50::before{border-color:#f9fbe7}.platform-ios input[type=radio].lime-100::before{border-color:#f0f4c3}.platform-ios input[type=radio].lime-200::before{border-color:#e6ee9c}.platform-ios input[type=radio].lime-300::before{border-color:#dce775}.platform-ios input[type=radio].lime-400::before{border-color:#d4e157}.platform-ios input[type=radio].lime-500::before{border-color:#cddc39}.platform-ios input[type=radio].lime-600::before{border-color:#c0ca33}.platform-ios input[type=radio].lime-700::before{border-color:#afb42b}.platform-ios input[type=radio].lime-800::before{border-color:#9e9d24}.platform-ios input[type=radio].lime-900::before{border-color:#827717}.platform-ios input[type=radio].yellow::before{border-color:#ffeb3b}.platform-ios input[type=radio].yellow-50::before{border-color:#fffde7}.platform-ios input[type=radio].yellow-100::before{border-color:#fff9c4}.platform-ios input[type=radio].yellow-200::before{border-color:#fff59d}.platform-ios input[type=radio].yellow-300::before{border-color:#fff176}.platform-ios input[type=radio].yellow-500::before{border-color:#ffeb3b}.platform-ios input[type=radio].yellow-600::before{border-color:#fdd835}.platform-ios input[type=radio].yellow-700::before{border-color:#fbc02d}.platform-ios input[type=radio].yellow-800::before{border-color:#f9a825}.platform-ios input[type=radio].yellow-900::before{border-color:#f57f17}.platform-ios input[type=radio].amber-50::before{border-color:#fff8e1}.platform-ios input[type=radio].amber-100::before{border-color:#ffecb3}.platform-ios input[type=radio].amber-200::before{border-color:#ffe082}.platform-ios input[type=radio].amber-300::before{border-color:#ffd54f}.platform-ios input[type=radio].amber-500::before{border-color:#ffc107}.platform-ios input[type=radio].amber-600::before{border-color:#ffb300}.platform-ios input[type=radio].amber-700::before{border-color:#ffa000}.platform-ios input[type=radio].amber-800::before{border-color:#ff8f00}.platform-ios input[type=radio].amber-900::before{border-color:#ff6f00}.platform-ios input[type=radio].orange-50::before{border-color:#fff3e0}.platform-ios input[type=radio].orange-100::before{border-color:#ffe0b2}.platform-ios input[type=radio].orange-200::before{border-color:#ffcc80}.platform-ios input[type=radio].orange-300::before{border-color:#ffb74d}.platform-ios input[type=radio].orange-400::before{border-color:#ffa726}.platform-ios input[type=radio].orange-500::before{border-color:#ff9800}.platform-ios input[type=radio].orange-600::before{border-color:#fb8c00}.platform-ios input[type=radio].orange-700::before{border-color:#f57c00}.platform-ios input[type=radio].orange-800::before{border-color:#ef6c00}.platform-ios input[type=radio].orange-900::before{border-color:#e65100}.platform-ios input[type=radio].deep-orange::before{border-color:#ff5722}.platform-ios input[type=radio].deep-orange-50::before{border-color:#fbe9e7}.platform-ios input[type=radio].deep-orange-100::before{border-color:#ffccbc}.platform-ios input[type=radio].deep-orange-200::before{border-color:#ffab91}.platform-ios input[type=radio].deep-orange-300::before{border-color:#ff8a65}.platform-ios input[type=radio].deep-orange-400::before{border-color:#ff7043}.platform-ios input[type=radio].deep-orange-500::before{border-color:#ff5722}.platform-ios input[type=radio].deep-orange-600::before{border-color:#f4511e}.platform-ios input[type=radio].deep-orange-700::before{border-color:#e64a19}.platform-ios input[type=radio].deep-orange-800::before{border-color:#d84315}.platform-ios input[type=radio].deep-orange-900::before{border-color:#bf360c}.platform-ios input[type=radio].brown::before{border-color:#795548}.platform-ios input[type=radio].brown-50::before{border-color:#efebe9}.platform-ios input[type=radio].brown-100::before{border-color:#d7ccc8}.platform-ios input[type=radio].brown-200::before{border-color:#bcaaa4}.platform-ios input[type=radio].brown-300::before{border-color:#a1887f}.platform-ios input[type=radio].brown-400::before{border-color:#8d6e63}.platform-ios input[type=radio].brown-500::before{border-color:#795548}.platform-ios input[type=radio].brown-600::before{border-color:#6d4c41}.platform-ios input[type=radio].brown-700::before{border-color:#5d4037}.platform-ios input[type=radio].brown-800::before{border-color:#4e342e}.platform-ios input[type=radio].brown-900::before{border-color:#3e2723}.platform-ios input[type=radio].grey::before{border-color:#9e9e9e}.platform-ios input[type=radio].grey-50::before{border-color:#fafafa}.platform-ios input[type=radio].grey-100::before{border-color:#f5f5f5}.platform-ios input[type=radio].grey-200::before{border-color:#eee}.platform-ios input[type=radio].grey-300::before{border-color:#e0e0e0}.platform-ios input[type=radio].grey-400::before{border-color:#bdbdbd}.platform-ios input[type=radio].grey-500::before{border-color:#9e9e9e}.platform-ios input[type=radio].grey-600::before{border-color:#757575}.platform-ios input[type=radio].grey-700::before{border-color:#616161}.platform-ios input[type=radio].grey-800::before{border-color:#424242}.platform-ios input[type=radio].grey-900::before{border-color:#212121}.platform-ios input[type=radio].blue-grey::before{border-color:#607d8b}.platform-ios input[type=radio].blue-grey-50::before{border-color:#eceff1}.platform-ios input[type=radio].blue-grey-100::before{border-color:#cfd8dc}.platform-ios input[type=radio].blue-grey-200::before{border-color:#b0bec5}.platform-ios input[type=radio].blue-grey-300::before{border-color:#90a4ae}.platform-ios input[type=radio].blue-grey-400::before{border-color:#78909c}.platform-ios input[type=radio].blue-grey-500::before{border-color:#607d8b}.platform-ios input[type=radio].blue-grey-600::before{border-color:#546e7a}.platform-ios input[type=radio].blue-grey-700::before{border-color:#455a64}.platform-ios input[type=radio].blue-grey-800::before{border-color:#37474f}.platform-ios input[type=radio].blue-grey-900::before{border-color:#263238}.platform-ios input[type=radio].black::before{border-color:#000}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/list.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/list.min.css
new file mode 100755
index 0000000..0a6114a
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/list.min.css
@@ -0,0 +1 @@
+.list{width:100%;position:relative;border:1px solid #F2F5F5}.list .item{padding:10px 15px;;display:inline-block;border-bottom:1px solid #F2F5F5;width:100%;position:relative;font-size:18px}.list .item.hidden{display:none}.list ol,.list ul{list-style:none}.list .item.space-small{padding-top:5px;padding-bottom:5px}.list .item.mark{border-right:0;border-top:0}.item .block{display:-webkit-box;display:flex}.list .item.mark.margin-button{border-bottom:0;margin-bottom:10px}.list .item.no-space-top{padding-top:0!important}.list .item.no-space-bottom{padding-bottom:0!important}.list .item.row{display:-moz-flex;display:-ms-flexbox;display:flex}.list.no-border{border:0}.list .item.no-border.border-bottom,.list.no-border .item.border-bottom{border-bottom-width:1px;border-bottom-style:solid}.list .item.no-border,.list.no-border .item{border:none}.list .item.cover{padding:0;margin-left:20px;height:200px;width:-webkit-calc(100% - 40px);width:-moz-calc(100% - 40px);width:calc(100% - 40px)}.list .item.full{padding:0;display:flex}.list .item h1,.list .item h2{font-size:16px;margin:0;padding:0}.list .item h1{margin-top:7px}.list .item p{font-size:14px;margin:0;padding:0;line-height:20px}.list .item:last-child{border-bottom:0}.list .left{margin-right:10px;min-width:25px}.list .right{margin-right:20px;position:absolute;top:0;right:0;height:100%;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}.list .right i{margin-left:5px}.list .align-top{-ms-flex-align:center;-webkit-align-items:center;align-items:baseline;margin-top:10px}.list .avatar{height:50px}.avatar-badge{position:absolute;margin-left:-4px;margin-top:-3px;border-radius:8px}.list .item small,.list .item small .icon{font-size:14px}.list .item .icon{font-size:18px}.list .item .icon.text-huge{font-size:32px}.list .left .icon,.list .right .icon{vertical-align:-webkit-baseline-middle}.list .border-big{border-width:3px;border-style:solid}.list .item[onclick]:active,.list a.item:active{background-color:rgba(0,0,0,.1);cursor:pointer}.list .item .right .icon,.list .item .right.icon{font-size:24px;padding:0;margin:0}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/loading.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/loading.min.css
new file mode 100755
index 0000000..65c5258
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/loading.min.css
@@ -0,0 +1 @@
+.alert-loading .alert{padding:24px;text-align:center}.loading-circle{fill:transparent;stroke:#009688;stroke-width:5;-webkit-animation:dash 2s ease infinite,rotate 2s linear infinite;-moz-animation:dash 2s ease infinite,rotate 2s linear infinite;-o-animation:dash 2s ease infinite,rotate 2s linear infinite;animation:dash 2s ease infinite,rotate 2s linear infinite;margin:auto}.loading-circle.loading-element{zoom:.55;margin-top:-20px;margin-left:-20px;position:absolute}button .loading-circle.loading-element{left:50%;margin-left:-20px;top:50%;margin-top:-20px}.loading-circle.with-message.loading-element{margin-left:-50px;margin-top:17px;top:auto;left:auto}.loading-circle.loading-element.left{float:left;position:inherit;margin-left:0}.loading-circle.loading-element.right{float:right;position:inherit;margin-left:0}.loading-circle.white-loading{stroke:rgba(255,255,255,.8)}.loading-circle.with-message{margin-right:10px}.platform-ios .loading-circle{fill:#868686;-webkit-animation:none;-moz-animation:none;-o-animation:none;animation:none;stroke:none;stroke-width:0}.platform-ios .loading-circle.loading-element.white-loading{fill:rgba(255,255,255,.8)}.platform-ios .loading-circle path:nth-of-type(1){-webkit-animation:pulse 1s infinite linear;-moz-animation:pulse 1s infinite linear;-o-animation:pulse 1s infinite linear;animation:pulse 1s infinite linear}.platform-ios .loading-circle path:nth-of-type(2){-webkit-animation:pulse 1s -83ms infinite linear;-moz-animation:pulse 1s -83ms infinite linear;-o-animation:pulse 1s -83ms infinite linear;animation:pulse 1s -83ms infinite linear}.platform-ios .loading-circle path:nth-of-type(3){-webkit-animation:pulse 1s -.166s infinite linear;-moz-animation:pulse 1s -.166s infinite linear;-o-animation:pulse 1s -.166s infinite linear;animation:pulse 1s -.166s infinite linear}.platform-ios .loading-circle path:nth-of-type(4){-webkit-animation:pulse 1s -.249s infinite linear;-moz-animation:pulse 1s -.249s infinite linear;-o-animation:pulse 1s -.249s infinite linear;animation:pulse 1s -.249s infinite linear}.platform-ios .loading-circle path:nth-of-type(5){-webkit-animation:pulse 1s -.332s infinite linear;-moz-animation:pulse 1s -.332s infinite linear;-o-animation:pulse 1s -.332s infinite linear;animation:pulse 1s -.332s infinite linear}.platform-ios .loading-circle path:nth-of-type(6){-webkit-animation:pulse 1s -.415s infinite linear;-moz-animation:pulse 1s -.415s infinite linear;-o-animation:pulse 1s -.415s infinite linear;animation:pulse 1s -.415s infinite linear}.platform-ios .loading-circle path:nth-of-type(7){-webkit-animation:pulse 1s -.498s infinite linear;-moz-animation:pulse 1s -.498s infinite linear;-o-animation:pulse 1s -.498s infinite linear;animation:pulse 1s -.498s infinite linear}.platform-ios .loading-circle path:nth-of-type(8){-webkit-animation:pulse 1s -.581s infinite linear;-moz-animation:pulse 1s -.581s infinite linear;-o-animation:pulse 1s -.581s infinite linear;animation:pulse 1s -.581s infinite linear}.platform-ios .loading-circle path:nth-of-type(9){-webkit-animation:pulse 1s -.664s infinite linear;-moz-animation:pulse 1s -.664s infinite linear;-o-animation:pulse 1s -.664s infinite linear;animation:pulse 1s -.664s infinite linear}.platform-ios .loading-circle path:nth-of-type(10){-webkit-animation:pulse 1s -.747s infinite linear;-moz-animation:pulse 1s -.747s infinite linear;-o-animation:pulse 1s -.747s infinite linear;animation:pulse 1s -.747s infinite linear}.platform-ios .alert-loading .loading-circle path:nth-of-type(11){-webkit-animation:pulse 1s -.83s infinite linear;-moz-animation:pulse 1s -.83s infinite linear;-o-animation:pulse 1s -.83s infinite linear;animation:pulse 1s -.83s infinite linear}.platform-ios .alert-loading .loading-circle path:nth-of-type(12){-webkit-animation:pulse 1s -.913s infinite linear;-moz-animation:pulse 1s -.913s infinite linear;-o-animation:pulse 1s -.913s infinite linear;animation:pulse 1s -.913s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(1){-webkit-animation:pulse-white 1s infinite linear;-moz-animation:pulse-white 1s infinite linear;-o-animation:pulse-white 1s infinite linear;animation:pulse-white 1s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(2){-webkit-animation:pulse-white 1s -83ms infinite linear;-moz-animation:pulse-white 1s -83ms infinite linear;-o-animation:pulse-white 1s -83ms infinite linear;animation:pulse-white 1s -83ms infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(3){-webkit-animation:pulse-white 1s -.166s infinite linear;-moz-animation:pulse-white 1s -.166s infinite linear;-o-animation:pulse-white 1s -.166s infinite linear;animation:pulse-white 1s -.166s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(4){-webkit-animation:pulse-white 1s -.249s infinite linear;-moz-animation:pulse-white 1s -.249s infinite linear;-o-animation:pulse-white 1s -.249s infinite linear;animation:pulse-white 1s -.249s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(5){-webkit-animation:pulse-white 1s -.332s infinite linear;-moz-animation:pulse-white 1s -.332s infinite linear;-o-animation:pulse-white 1s -.332s infinite linear;animation:pulse-white 1s -.332s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(6){-webkit-animation:pulse-white 1s -.415s infinite linear;-moz-animation:pulse-white 1s -.415s infinite linear;-o-animation:pulse-white 1s -.415s infinite linear;animation:pulse-white 1s -.415s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(7){-webkit-animation:pulse-white 1s -.498s infinite linear;-moz-animation:pulse-white 1s -.498s infinite linear;-o-animation:pulse-white 1s -.498s infinite linear;animation:pulse-white 1s -.498s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(8){-webkit-animation:pulse-white 1s -.581s infinite linear;-moz-animation:pulse-white 1s -.581s infinite linear;-o-animation:pulse-white 1s -.581s infinite linear;animation:pulse-white 1s -.581s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(9){-webkit-animation:pulse-white 1s -.664s infinite linear;-moz-animation:pulse-white 1s -.664s infinite linear;-o-animation:pulse-white 1s -.664s infinite linear;animation:pulse-white 1s -.664s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(10){-webkit-animation:pulse-white 1s -.747s infinite linear;-moz-animation:pulse-white 1s -.747s infinite linear;-o-animation:pulse-white 1s -.747s infinite linear;animation:pulse-white 1s -.747s infinite linear}.platform-ios .alert-loading.white-loading .loading-circle path:nth-of-type(11){-webkit-animation:pulse-white 1s -.83s infinite linear;-moz-animation:pulse-white 1s -.83s infinite linear;-o-animation:pulse-white 1s -.83s infinite linear;animation:pulse-white 1s -.83s infinite linear}.platform-ios .alert-loading.white-loading .loading-circle path:nth-of-type(12){-webkit-animation:pulse-white 1s -.913s infinite linear;-moz-animation:pulse-white 1s -.913s infinite linear;-o-animation:pulse-white 1s -.913s infinite linear;animation:pulse-white 1s -.913s infinite linear}@-webkit-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-moz-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-o-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-webkit-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-moz-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-o-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-webkit-keyframes iosIntro{from{-webkit-transform:scale(0);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes iosIntro{from{-moz-transform:scale(0);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-o-keyframes iosIntro{from{-o-transform:scale(0);opacity:0}to{-o-transform:scale(1);opacity:1}}@keyframes iosIntro{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}.alert-mobileui.alert-loading .alert p{margin:0;margin-top:15px!important;text-align:center}@-webkit-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-moz-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-o-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotate{0%{-moz-transform:rotate(0)}100%{-moz-transform:rotate(360deg)}}@-o-keyframes rotate{0%{-o-transform:rotate(0)}100%{-o-transform:rotate(360deg)}}@keyframes rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/menu.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/menu.min.css
new file mode 100755
index 0000000..dbfc1cd
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/menu.min.css
@@ -0,0 +1 @@
+.menu{position:fixed;top:0;left:0;width:300px;height:100%;z-index:99999;transform:translateX(-312px);-webkit-transform:translateX(-312px);-moz-transform:translateX(-312px);-o-transform:translateX(-312px);transition-duration:280ms;-webkit-transition-duration:280ms;-moz-transition-duration:280ms;-o-transition-duration:280ms;box-shadow:0 0 10px rgba(0,0,0,.25);overflow:auto}.menu.cover{width:300px}.menu.menu-right{right:0;left:auto;transform:translateX(105%);-webkit-transform:translateX(105%);-moz-transform:translateX(105%);-o-transform:translateX(105%)}.menu.open{transform:translateX(0);-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0)}.menu.menu-right.open{margin-left:-312px}.platform-ios .backdrop-menu{opacity:.01}.platform-ios .menu{width:264px;box-shadow:none;transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s;transform:translateX(-264px);-webkit-transform:translateX(-264px);-moz-transform:translateX(-264px);-o-transform:translateX(-264px);box-shadow:none}.platform-ios .menu.cover{width:264px}.platform-ios .menu.menu-right{transform:translateX(105%);-webkit-transform:translateX(105%);-moz-transform:translateX(105%);-o-transform:translateX(105%);transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s}.platform-ios .menu.open{transform:translateX(-264px);-webkit-transform:translateX(-264px);-moz-transform:translateX(-264px);-o-transform:translateX(-264px);margin-left:-1px}.platform-ios .menu.menu-right.open{margin-left:-263px;transform:none;-webkit-transform:none;-moz-transform:none;-o-transform:none;box-shadow:0 0 10px rgba(0,0,0,.25)}.platform-ios .body,.platform-ios body{transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s}.platform-ios .body.side-menu,.platform-ios.side-menu{transform:translateX(264px);-webkit-transform:translateX(264px);-moz-transform:translateX(264px);-o-transform:translateX(264px);border-left:1px solid rgba(0,0,0,.15);overflow:hidden}.platform-ios .body.side-menu-right,.platform-ios .header.side-menu-right,.platform-ios.side-menu-right{margin-left:-264px}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/mobileui-colors.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/mobileui-colors.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/mobileui-colors.min.css
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/mobileuijs.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/mobileuijs.min.css
new file mode 100755
index 0000000..d4e2495
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/mobileuijs.min.css
@@ -0,0 +1 @@
+[data]{display:none!important}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/page.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/page.min.css
new file mode 100755
index 0000000..b0e3759
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/page.min.css
@@ -0,0 +1 @@
+.page{position:absolute;top:60px;left:0;display:block;width:100%;height:100%;opacity:.01;contain:strict;background-color:#fff;overflow:auto}.platform-ios .page{top:0;left:100%;opacity:1}.page.show{opacity:1;top:0}.platform-ios .page.show{opacity:1;top:0;left:0}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/popover.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/popover.min.css
new file mode 100755
index 0000000..9b4ffcb
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/popover.min.css
@@ -0,0 +1 @@
+.popover{position:absolute;z-index:10001;border-radius:3px;box-shadow:0 3px 12px 2px rgba(0,0,0,.3);overflow:hidden;display:none;background-color:#fff}.platform-ios .popover{border-radius:10px;box-shadow:none}.popover-arrow{z-index:10000;position:absolute;width:14px;height:14px;border-radius:3px;background-color:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.popover.show{display:block}.popover .item,.popover .list{border-width:0}.popover .list .item h1{margin:0}.popover .item{display:table!important;overflow:hidden;white-space:nowrap;padding:10px}.platform-ios .popover .item{border-width:1px}.popover .item:first-child{padding-top:15px}.popover .item:last-child{padding-bottom:15px}.backdrop-popover{opacity:.01}.platform-ios .backdrop-popover{opacity:.08}.popover .item[data]{display:none!important}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/progress-circle.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/progress-circle.min.css
new file mode 100755
index 0000000..5e0642d
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/progress-circle.min.css
@@ -0,0 +1 @@
+.progress-circle,.progress-circle-js{margin:auto}.progress-circle-title{opacity:.8}.progress-circle-subtitle{opacity:.6}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/progress-circular.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/progress-circular.min.css
new file mode 100755
index 0000000..169eb97
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/progress-circular.min.css
@@ -0,0 +1 @@
+.progress-circular{position:relative;font-size:30px;font-weight:300;width:100px;height:100px;border-radius:50%;background-color:rgba(0,0,0,.2);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.progress-circular>span{text-align:center;width:100%;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;z-index:5}.progress-circular::before{content:'';position:absolute;width:100px;height:100px;clip:rect(0,1em,1em,.5em)}.progress-circular::after{position:absolute;content:" ";border-radius:50%;background-color:#f5f5f5;width:94px;height:94px;text-align:center;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.progress-circular.background-blue::after{background-color:#2196f3!important}.progress-circular.background-blue>span{color:rgba(255,255,255,.9)}.progress-circular>span::before{content:'';position:absolute;left:0;top:0;border:2px solid #fff;width:100px;height:100px;clip:rect(0,150px,150px,0);border-radius:50%;-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);text-align:center;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/progress-semicircle.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/progress-semicircle.min.css
new file mode 100755
index 0000000..1fa5a65
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/progress-semicircle.min.css
@@ -0,0 +1 @@
+.progress-semicircle,.progress-semicircle-js{margin:auto}.progress-semicircle-title{opacity:.8}.progress-semicircle-subtitle{opacity:.6}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/progressbarjs.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/progressbarjs.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/progressbarjs.min.css
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/swiper.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/swiper.min.css
new file mode 100755
index 0000000..1beff1c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/swiper.min.css
@@ -0,0 +1 @@
+.swiper-container{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;z-index:1}.swiper-container-fullscreen{height:100%}.swipper-gallery{height:300px}.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%;z-index:1;height:100%;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{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-slide.vertical-align-center{display:flex;flex-direction:column;justify-content:center;padding:30px;text-align:center}.swiper-slide i{font-size:120px}.swiper-slide h1{font-size:40px;font-weight:600;width:100%}.swiper-slide h2{font-size:30px;font-weight:600;width:100%}.swiper-slide .margin-bottom{margin-bottom:25px}.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-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.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;background:#007aff}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{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-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;-moz-transform-origin:right top;-ms-transform-origin:right top;-o-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.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,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.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,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .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-slide{visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.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-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-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;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.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-zoom-container{width:100%;height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;object-fit:contain}.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)}}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/tab.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/tab.min.css
new file mode 100755
index 0000000..9904384
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/tab.min.css
@@ -0,0 +1 @@
+.tab{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.tab-content{display:none}.tab-content.active{display:block}.tab button{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:13px!important;text-transform:uppercase;opacity:.6;margin:0}.footer.tab button.icon{margin-top:0}.header.tab.shadow{box-shadow:2px 2px 3px rgba(0,0,0,.2)}.platform-ios .tab button{text-transform:none}.tab button.active{opacity:1}.tab button.icon{font-size:14px;line-height:16px}.tab button::before{display:block;font-size:25px}.tab button.active::after{content:'';position:absolute;bottom:0;left:0;width:100%;height:3px;/*background-color:#fff*/}.tab button .badge{width:20px;height:20px;margin-left:10px;text-align:center;font-size:14px;font-weight:700;border-radius:50%;margin-top:10px;position:absolute;line-height:18px;padding-top:1px}.tab.footer button.active::after{top:0}.header.tab.footer.shadow{box-shadow:-2px -2px 3px rgba(0,0,0,.2)}.platform-ios .tab button.active::after{display:none}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/timeline.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/timeline.min.css
new file mode 100755
index 0000000..0b85d62
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/timeline.min.css
@@ -0,0 +1 @@
+.timeline{font-size:14px;padding:2px}.timeline .marker{position:relative}.timeline .marker::before{background:rgba(0,0,0,.3);content:"";height:100%;width:2px;margin:0 auto;position:absolute;margin-top:10px;z-index:0;left:18px}.timeline .row:last-child .marker::before{display:none}.timeline .icon-circle,.timeline .icon-circle-big,.timeline .icon-circle-small{margin:0 auto;margin-top:10px;position:absolute;margin-left:7px}.timeline .icon-circle i::before,.timeline .icon-circle-big i::before,.timeline .icon-circle-small i::before{margin-top:4px}.timeline .avatar-group{-webkit-transform:translateX(10px);transform:translateX(10px)}.timeline .avatar-photo{background:#eaeaea;width:30px;height:30px;overflow:hidden;text-align:center;border:1px solid #d7d2d2}.timeline .avatar-photo small{margin-top:100px}.timeline .circle-more{background:#eaeaea;width:30px;height:30px;overflow:hidden;text-align:center;border-radius:50%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#bdbbbb;border:1px solid #d7d2d2;font-size:12px}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/css/toast.min.css b/platforms/android/app/src/main/assets/www/mobileui/css/toast.min.css
new file mode 100755
index 0000000..8ee986c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/css/toast.min.css
@@ -0,0 +1 @@
+.toast{z-index:999999;position:absolute;left:0;padding:20px;text-align:center;width:100%;opacity:0;transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-webkit-transition:opacity .25s ease-in-out}.toast.show{opacity:1}.toast.toast-bottom{bottom:10px}.toast.toast-top{top:10px}.toast.toast-center{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;height:100%;top:0}.toast div{padding:10px;display:inline-block}.toast .full{display:block;width:100%}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/alert.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/alert.min.js
new file mode 100755
index 0000000..78b8212
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/alert.min.js
@@ -0,0 +1 @@
+window.alert=function(e,t){var a={};"object"==typeof e?a=e:(a.message=e,a.title=t),a.id||(a.id="ALERT"+(new Date).getTime()),a.buttons&&a.buttons.length||(a.buttons=[{label:"OK",onclick:function(){closeAlert()}}]);var n=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(n=event.target.parentNode);var d=document.createElement("div");d.className="backdrop show backdrop-alert",d.id=a.id+"_BACKDROP",n.appendChild(d);var l=document.createElement("div");l.className="alert-mobileui",l.id=a.id,d.parentNode.appendChild(l);var o=document.createElement("div");if(a.class||(a.class="white"),o.className="alert "+a.class,a.width&&(o.style.maxWidth=a.width),l.appendChild(o),a.title){var r="<h1>"+a.title+"</h1>";o.insertAdjacentHTML("beforeend",r)}if(a.message){var s="<p>"+a.message+"</p>";o.insertAdjacentHTML("beforeend",s)}a.template&&o.insertAdjacentHTML("beforeend",document.getElementById(a.template).innerHTML);var c=document.createElement("div");c.className="buttons",o.appendChild(c);for(var i in a.buttons){var m=document.createElement("button");a.buttons[i].class||(a.buttons[i].class="text-teal"),m.className=a.buttons[i].class;var p=document.createTextNode(a.buttons[i].label);m.appendChild(p),a.buttons[i].onclick||(a.buttons[i].onclick=closeAlert),m.addEventListener("click",a.buttons[i].onclick),c.appendChild(m)}var u=new CustomEvent("alertOpened");document.dispatchEvent(u)},window.closeAlert=function(e){alertId=e,alertId||(alertId=event.target.parentNode.parentNode.parentNode.id);var t=document.getElementById(alertId);t.parentNode.removeChild(t);var a=document.getElementById(alertId+"_BACKDROP");a.parentNode.removeChild(a)};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/base.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/base.min.js
new file mode 100755
index 0000000..d6d093c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/base.min.js
@@ -0,0 +1 @@
+var userAgent=navigator.userAgent||navigator.vendor||window.opera,SO={name:"unknown",code:0};/android/i.test(userAgent)&&(SO.name="Android",SO.class="platform-android",SO.code=1);/iPad|iPhone|iPod/.test(userAgent)&&!window.MSStream&&(SO.name="iOS",SO.class="platform-ios",SO.code=2);/windows phone/i.test(userAgent)&&(SO.name="Windows Phone",SO.class="platform-wp",SO.code=3);SO.class&&document.getElementsByTagName("body").length&&(document.getElementsByTagName("body")[0].className+=" "+SO.class);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/button.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/button.min.js
new file mode 100755
index 0000000..4e7054c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/button.min.js
@@ -0,0 +1 @@
+document.addEventListener("click",function(e){if(1!==SO.code)return!1;var t=e.target;if("button"!==t.tagName.toLowerCase())return!1;var o=t.getBoundingClientRect(),s=t.querySelector(".ripple");s||((s=document.createElement("span")).className="ripple",s.style.height=s.style.width=Math.max(o.width,o.height)+"px",t.appendChild(s)),s.classList.remove("show");var a=e.pageY-o.top-s.offsetHeight/2-document.body.scrollTop,l=e.pageX-o.left-s.offsetWidth/2-document.body.scrollLeft;return s.style.top=a+"px",s.style.left=l+"px",s.classList.add("show"),!1},!1);
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/chart-bar.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/chart-bar.min.js
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/chart-bar.min.js
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/chartist-plugin-tooltip.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/chartist-plugin-tooltip.min.js
new file mode 100755
index 0000000..259aae0
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/chartist-plugin-tooltip.min.js
@@ -0,0 +1 @@
+!function(t,e){"function"==typeof define&&define.amd?define(["chartist"],function(o){return t.returnExportsGlobal=e(o)}):"object"==typeof exports?module.exports=e(require("chartist")):t["Chartist.plugins.tooltip"]=e(Chartist)}(this,function(t){return function(t,e,o){"use strict";function n(t){a(t,"tooltip-show")||(t.className=t.className+" tooltip-show")}function i(t){var e=new RegExp("tooltip-show\\s*","gi");t.className=t.className.replace(e,"").trim()}function a(t,e){return(" "+t.getAttribute("class")+" ").indexOf(" "+e+" ")>-1}function r(t,e){do{t=t.nextSibling}while(t&&!a(t,e));return t}var s={currency:void 0,currencyFormatCallback:void 0,tooltipOffset:{x:0,y:-20},anchorToPoint:!1,appendToBody:!1,class:void 0,pointClass:"ct-point"};o.plugins=o.plugins||{},o.plugins.tooltip=function(c){return c=o.extend({},s,c),function(s){function l(t,e,o){f.addEventListener(t,function(t){e&&!a(t.target,e)||o(t)})}function p(e){g=g||d.offsetHeight;var o,n,i=-(m=m||d.offsetWidth)/2+c.tooltipOffset.x,a=-g+c.tooltipOffset.y;if(c.appendToBody)d.style.top=e.pageY+a+"px",d.style.left=e.pageX+i+"px";else{var r=f.getBoundingClientRect(),s=e.pageX-r.left-t.pageXOffset,l=e.pageY-r.top-t.pageYOffset;!0===c.anchorToPoint&&e.target.x2&&e.target.y2&&(o=parseInt(e.target.x2.baseVal.value),n=parseInt(e.target.y2.baseVal.value)),d.style.top=(n||l)+a+"px",d.style.left=(o||s)+i+"px"}}var u=c.pointClass;s.constructor.name==o.Bar.prototype.constructor.name?u="ct-bar":s.constructor.name==o.Pie.prototype.constructor.name&&(u=s.options.donut?"ct-slice-donut":"ct-slice-pie");var f=s.container,d=f.querySelector(".chartist-tooltip");d||(d=e.createElement("div"),d.className=c.class?"chartist-tooltip "+c.class:"chartist-tooltip",c.appendToBody?e.body.appendChild(d):f.appendChild(d));var g=d.offsetHeight,m=d.offsetWidth;i(d),l("mouseover",u,function(t){var i=t.target,a="",l=(s instanceof o.Pie?i:i.parentNode)?i.parentNode.getAttribute("ct:meta")||i.parentNode.getAttribute("ct:series-name"):"",u=i.getAttribute("ct:meta")||l||"",f=!!u,h=i.getAttribute("ct:value");if(c.transformTooltipTextFnc&&"function"==typeof c.transformTooltipTextFnc&&(h=c.transformTooltipTextFnc(h)),c.tooltipFnc&&"function"==typeof c.tooltipFnc)a=c.tooltipFnc(u,h);else{if(c.metaIsHTML){var y=e.createElement("textarea");y.innerHTML=u,u=y.value}if(u='<span class="chartist-tooltip-meta">'+u+"</span>",f)a+=u+"<br>";else if(s instanceof o.Pie){var v=r(i,"ct-label");v&&(a+=function(t){return t.innerText||t.textContent}(v)+"<br>")}h&&(c.currency&&(h=void 0!=c.currencyFormatCallback?c.currencyFormatCallback(h,c):c.currency+h.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g,"$1,")),h='<span class="chartist-tooltip-value">'+h+"</span>",a+=h)}a&&(d.innerHTML=a,p(t),n(d),g=d.offsetHeight,m=d.offsetWidth)}),l("mouseout",u,function(){i(d)}),l("mousemove",null,function(t){!1===c.anchorToPoint&&p(t)})}}}(window,document,t),t.plugins.tooltip});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/chartist.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/chartist.min.js
new file mode 100755
index 0000000..924d43a
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/chartist.min.js
@@ -0,0 +1 @@
+!function(e,t){"function"==typeof define&&define.amd?define("Chartist",[],function(){return e.Chartist=t()}):"object"==typeof module&&module.exports?module.exports=t():e.Chartist=t()}(this,function(){var e={version:"0.11.0"};return function(e,t,i){"use strict";i.namespaces={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns/",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",ct:"http://gionkunz.github.com/chartist-js/ct"},i.noop=function(e){return e},i.alphaNumerate=function(e){return String.fromCharCode(97+e%26)},i.extend=function(e){var t,n,s;for(e=e||{},t=1;t<arguments.length;t++){n=arguments[t];for(var r in n)"object"!=typeof(s=n[r])||null===s||s instanceof Array?e[r]=s:e[r]=i.extend(e[r],s)}return e},i.replaceAll=function(e,t,i){return e.replace(new RegExp(t,"g"),i)},i.ensureUnit=function(e,t){return"number"==typeof e&&(e+=t),e},i.quantity=function(e){if("string"==typeof e){var t=/^(\d+)\s*(.*)$/g.exec(e);return{value:+t[1],unit:t[2]||void 0}}return{value:e}},i.querySelector=function(e){return e instanceof Node?e:t.querySelector(e)},i.times=function(e){return Array.apply(null,new Array(e))},i.sum=function(e,t){return e+(t||0)},i.mapMultiply=function(e){return function(t){return t*e}},i.mapAdd=function(e){return function(t){return t+e}},i.serialMap=function(e,t){var n=[],s=Math.max.apply(null,e.map(function(e){return e.length}));return i.times(s).forEach(function(i,s){var r=e.map(function(e){return e[s]});n[s]=t.apply(null,r)}),n},i.roundWithPrecision=function(e,t){var n=Math.pow(10,t||i.precision);return Math.round(e*n)/n},i.precision=8,i.escapingMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"},i.serialize=function(e){return null===e||void 0===e?e:("number"==typeof e?e=""+e:"object"==typeof e&&(e=JSON.stringify({data:e})),Object.keys(i.escapingMap).reduce(function(e,t){return i.replaceAll(e,t,i.escapingMap[t])},e))},i.deserialize=function(e){if("string"!=typeof e)return e;e=Object.keys(i.escapingMap).reduce(function(e,t){return i.replaceAll(e,i.escapingMap[t],t)},e);try{e=void 0!==(e=JSON.parse(e)).data?e.data:e}catch(e){}return e},i.createSvg=function(e,t,n,s){var r;return t=t||"100%",n=n||"100%",Array.prototype.slice.call(e.querySelectorAll("svg")).filter(function(e){return e.getAttributeNS(i.namespaces.xmlns,"ct")}).forEach(function(t){e.removeChild(t)}),r=new i.Svg("svg").attr({width:t,height:n}).addClass(s),r._node.style.width=t,r._node.style.height=n,e.appendChild(r._node),r},i.normalizeData=function(e,t,n){var s,r={raw:e,normalized:{}};return r.normalized.series=i.getDataArray({series:e.series||[]},t,n),s=r.normalized.series.every(function(e){return e instanceof Array})?Math.max.apply(null,r.normalized.series.map(function(e){return e.length})):r.normalized.series.length,r.normalized.labels=(e.labels||[]).slice(),Array.prototype.push.apply(r.normalized.labels,i.times(Math.max(0,s-r.normalized.labels.length)).map(function(){return""})),t&&i.reverseData(r.normalized),r},i.safeHasProperty=function(e,t){return null!==e&&"object"==typeof e&&e.hasOwnProperty(t)},i.isDataHoleValue=function(e){return null===e||void 0===e||"number"==typeof e&&isNaN(e)},i.reverseData=function(e){e.labels.reverse(),e.series.reverse();for(var t=0;t<e.series.length;t++)"object"==typeof e.series[t]&&void 0!==e.series[t].data?e.series[t].data.reverse():e.series[t]instanceof Array&&e.series[t].reverse()},i.getDataArray=function(e,t,n){function s(e){if(i.safeHasProperty(e,"value"))return s(e.value);if(i.safeHasProperty(e,"data"))return s(e.data);if(e instanceof Array)return e.map(s);if(!i.isDataHoleValue(e)){if(n){var t={};return"string"==typeof n?t[n]=i.getNumberOrUndefined(e):t.y=i.getNumberOrUndefined(e),t.x=e.hasOwnProperty("x")?i.getNumberOrUndefined(e.x):t.x,t.y=e.hasOwnProperty("y")?i.getNumberOrUndefined(e.y):t.y,t}return i.getNumberOrUndefined(e)}}return e.series.map(s)},i.normalizePadding=function(e,t){return t=t||0,"number"==typeof e?{top:e,right:e,bottom:e,left:e}:{top:"number"==typeof e.top?e.top:t,right:"number"==typeof e.right?e.right:t,bottom:"number"==typeof e.bottom?e.bottom:t,left:"number"==typeof e.left?e.left:t}},i.getMetaData=function(e,t){var i=e.data?e.data[t]:e[t];return i?i.meta:void 0},i.orderOfMagnitude=function(e){return Math.floor(Math.log(Math.abs(e))/Math.LN10)},i.projectLength=function(e,t,i){return t/i.range*e},i.getAvailableHeight=function(e,t){return Math.max((i.quantity(t.height).value||e.height())-(t.chartPadding.top+t.chartPadding.bottom)-t.axisX.offset,0)},i.getHighLow=function(e,t,n){function s(e){if(void 0!==e)if(e instanceof Array)for(var t=0;t<e.length;t++)s(e[t]);else{var i=n?+e[n]:+e;a&&i>r.high&&(r.high=i),o&&i<r.low&&(r.low=i)}}var r={high:void 0===(t=i.extend({},t,n?t["axis"+n.toUpperCase()]:{})).high?-Number.MAX_VALUE:+t.high,low:void 0===t.low?Number.MAX_VALUE:+t.low},a=void 0===t.high,o=void 0===t.low;return(a||o)&&s(e),(t.referenceValue||0===t.referenceValue)&&(r.high=Math.max(t.referenceValue,r.high),r.low=Math.min(t.referenceValue,r.low)),r.high<=r.low&&(0===r.low?r.high=1:r.low<0?r.high=0:r.high>0?r.low=0:(r.high=1,r.low=0)),r},i.isNumeric=function(e){return null!==e&&isFinite(e)},i.isFalseyButZero=function(e){return!e&&0!==e},i.getNumberOrUndefined=function(e){return i.isNumeric(e)?+e:void 0},i.isMultiValue=function(e){return"object"==typeof e&&("x"in e||"y"in e)},i.getMultiValue=function(e,t){return i.isMultiValue(e)?i.getNumberOrUndefined(e[t||"y"]):i.getNumberOrUndefined(e)},i.rho=function(e){function t(e,i){return e%i==0?i:t(i,e%i)}function i(e){return e*e+1}if(1===e)return e;var n,s=2,r=2;if(e%2==0)return 2;do{s=i(s)%e,r=i(i(r))%e,n=t(Math.abs(s-r),e)}while(1===n);return n},i.getBounds=function(e,t,n,s){function r(e,t){return e===(e+=t)&&(e*=1+(t>0?p:-p)),e}var a,o,l,u=0,c={high:t.high,low:t.low};c.valueRange=c.high-c.low,c.oom=i.orderOfMagnitude(c.valueRange),c.step=Math.pow(10,c.oom),c.min=Math.floor(c.low/c.step)*c.step,c.max=Math.ceil(c.high/c.step)*c.step,c.range=c.max-c.min,c.numberOfSteps=Math.round(c.range/c.step);var h=i.projectLength(e,c.step,c)<n,d=s?i.rho(c.range):0;if(s&&i.projectLength(e,1,c)>=n)c.step=1;else if(s&&d<c.step&&i.projectLength(e,d,c)>=n)c.step=d;else for(;;){if(h&&i.projectLength(e,c.step,c)<=n)c.step*=2;else{if(h||!(i.projectLength(e,c.step/2,c)>=n))break;if(c.step/=2,s&&c.step%1!=0){c.step*=2;break}}if(u++>1e3)throw new Error("Exceeded maximum number of iterations while optimizing scale step!")}var p=2.221e-16;for(c.step=Math.max(c.step,p),o=c.min,l=c.max;o+c.step<=c.low;)o=r(o,c.step);for(;l-c.step>=c.high;)l=r(l,-c.step);c.min=o,c.max=l,c.range=c.max-c.min;var m=[];for(a=c.min;a<=c.max;a=r(a,c.step)){var f=i.roundWithPrecision(a);f!==m[m.length-1]&&m.push(f)}return c.values=m,c},i.polarToCartesian=function(e,t,i,n){var s=(n-90)*Math.PI/180;return{x:e+i*Math.cos(s),y:t+i*Math.sin(s)}},i.createChartRect=function(e,t,n){var s=!(!t.axisX&&!t.axisY),r=s?t.axisY.offset:0,a=s?t.axisX.offset:0,o=e.width()||i.quantity(t.width).value||0,l=e.height()||i.quantity(t.height).value||0,u=i.normalizePadding(t.chartPadding,n);o=Math.max(o,r+u.left+u.right),l=Math.max(l,a+u.top+u.bottom);var c={padding:u,width:function(){return this.x2-this.x1},height:function(){return this.y1-this.y2}};return s?("start"===t.axisX.position?(c.y2=u.top+a,c.y1=Math.max(l-u.bottom,c.y2+1)):(c.y2=u.top,c.y1=Math.max(l-u.bottom-a,c.y2+1)),"start"===t.axisY.position?(c.x1=u.left+r,c.x2=Math.max(o-u.right,c.x1+1)):(c.x1=u.left,c.x2=Math.max(o-u.right-r,c.x1+1))):(c.x1=u.left,c.x2=Math.max(o-u.right,c.x1+1),c.y2=u.top,c.y1=Math.max(l-u.bottom,c.y2+1)),c},i.createGrid=function(e,t,n,s,r,a,o,l){var u={};u[n.units.pos+"1"]=e,u[n.units.pos+"2"]=e,u[n.counterUnits.pos+"1"]=s,u[n.counterUnits.pos+"2"]=s+r;var c=a.elem("line",u,o.join(" "));l.emit("draw",i.extend({type:"grid",axis:n,index:t,group:a,element:c},u))},i.createGridBackground=function(e,t,i,n){var s=e.elem("rect",{x:t.x1,y:t.y2,width:t.width(),height:t.height()},i,!0);n.emit("draw",{type:"gridBackground",group:e,element:s})},i.createLabel=function(e,n,s,r,a,o,l,u,c,h,d){var p,m={};if(m[a.units.pos]=e+l[a.units.pos],m[a.counterUnits.pos]=l[a.counterUnits.pos],m[a.units.len]=n,m[a.counterUnits.len]=Math.max(0,o-10),h){var f=t.createElement("span");f.className=c.join(" "),f.setAttribute("xmlns",i.namespaces.xhtml),f.innerText=r[s],f.style[a.units.len]=Math.round(m[a.units.len])+"px",f.style[a.counterUnits.len]=Math.round(m[a.counterUnits.len])+"px",p=u.foreignObject(f,i.extend({style:"overflow: visible;"},m))}else p=u.elem("text",m,c.join(" ")).text(r[s]);d.emit("draw",i.extend({type:"label",axis:a,index:s,group:u,element:p,text:r[s]},m))},i.getSeriesOption=function(e,t,i){if(e.name&&t.series&&t.series[e.name]){var n=t.series[e.name];return n.hasOwnProperty(i)?n[i]:t[i]}return t[i]},i.optionsProvider=function(t,n,s){function r(t){var r=a;if(a=i.extend({},l),n)for(o=0;o<n.length;o++){e.matchMedia(n[o][0]).matches&&(a=i.extend(a,n[o][1]))}s&&t&&s.emit("optionsChanged",{previousOptions:r,currentOptions:a})}var a,o,l=i.extend({},t),u=[];if(!e.matchMedia)throw"window.matchMedia not found! Make sure you're using a polyfill.";if(n)for(o=0;o<n.length;o++){var c=e.matchMedia(n[o][0]);c.addListener(r),u.push(c)}return r(),{removeMediaQueryListeners:function(){u.forEach(function(e){e.removeListener(r)})},getCurrentOptions:function(){return i.extend({},a)}}},i.splitIntoSegments=function(e,t,n){n=i.extend({},{increasingX:!1,fillHoles:!1},n);for(var s=[],r=!0,a=0;a<e.length;a+=2)void 0===i.getMultiValue(t[a/2].value)?n.fillHoles||(r=!0):(n.increasingX&&a>=2&&e[a]<=e[a-2]&&(r=!0),r&&(s.push({pathCoordinates:[],valueData:[]}),r=!1),s[s.length-1].pathCoordinates.push(e[a],e[a+1]),s[s.length-1].valueData.push(t[a/2]));return s}}(window,document,e),function(e,t,i){"use strict";i.Interpolation={},i.Interpolation.none=function(e){return e=i.extend({},{fillHoles:!1},e),function(t,n){for(var s=new i.Svg.Path,r=!0,a=0;a<t.length;a+=2){var o=t[a],l=t[a+1],u=n[a/2];void 0!==i.getMultiValue(u.value)?(r?s.move(o,l,!1,u):s.line(o,l,!1,u),r=!1):e.fillHoles||(r=!0)}return s}},i.Interpolation.simple=function(e){e=i.extend({},{divisor:2,fillHoles:!1},e);var t=1/Math.max(1,e.divisor);return function(n,s){for(var r,a,o,l=new i.Svg.Path,u=0;u<n.length;u+=2){var c=n[u],h=n[u+1],d=(c-r)*t,p=s[u/2];void 0!==p.value?(void 0===o?l.move(c,h,!1,p):l.curve(r+d,a,c-d,h,c,h,!1,p),r=c,a=h,o=p):e.fillHoles||(r=c=o=void 0)}return l}},i.Interpolation.cardinal=function(e){e=i.extend({},{tension:1,fillHoles:!1},e);var t=Math.min(1,Math.max(0,e.tension)),n=1-t;return function s(r,a){var o=i.splitIntoSegments(r,a,{fillHoles:e.fillHoles});if(o.length){if(o.length>1){var l=[];return o.forEach(function(e){l.push(s(e.pathCoordinates,e.valueData))}),i.Svg.Path.join(l)}if(r=o[0].pathCoordinates,a=o[0].valueData,r.length<=4)return i.Interpolation.none()(r,a);for(var u=(new i.Svg.Path).move(r[0],r[1],!1,a[0]),c=0,h=r.length;h-2>c;c+=2){var d=[{x:+r[c-2],y:+r[c-1]},{x:+r[c],y:+r[c+1]},{x:+r[c+2],y:+r[c+3]},{x:+r[c+4],y:+r[c+5]}];h-4===c?d[3]=d[2]:c||(d[0]={x:+r[c],y:+r[c+1]}),u.curve(t*(-d[0].x+6*d[1].x+d[2].x)/6+n*d[2].x,t*(-d[0].y+6*d[1].y+d[2].y)/6+n*d[2].y,t*(d[1].x+6*d[2].x-d[3].x)/6+n*d[2].x,t*(d[1].y+6*d[2].y-d[3].y)/6+n*d[2].y,d[2].x,d[2].y,!1,a[(c+2)/2])}return u}return i.Interpolation.none()([])}},i.Interpolation.monotoneCubic=function(e){return e=i.extend({},{fillHoles:!1},e),function t(n,s){var r=i.splitIntoSegments(n,s,{fillHoles:e.fillHoles,increasingX:!0});if(r.length){if(r.length>1){var a=[];return r.forEach(function(e){a.push(t(e.pathCoordinates,e.valueData))}),i.Svg.Path.join(a)}if(n=r[0].pathCoordinates,s=r[0].valueData,n.length<=4)return i.Interpolation.none()(n,s);var o,l,u=[],c=[],h=n.length/2,d=[],p=[],m=[],f=[];for(o=0;o<h;o++)u[o]=n[2*o],c[o]=n[2*o+1];for(o=0;o<h-1;o++)m[o]=c[o+1]-c[o],f[o]=u[o+1]-u[o],p[o]=m[o]/f[o];for(d[0]=p[0],d[h-1]=p[h-2],o=1;o<h-1;o++)0===p[o]||0===p[o-1]||p[o-1]>0!=p[o]>0?d[o]=0:(d[o]=3*(f[o-1]+f[o])/((2*f[o]+f[o-1])/p[o-1]+(f[o]+2*f[o-1])/p[o]),isFinite(d[o])||(d[o]=0));for(l=(new i.Svg.Path).move(u[0],c[0],!1,s[0]),o=0;o<h-1;o++)l.curve(u[o]+f[o]/3,c[o]+d[o]*f[o]/3,u[o+1]-f[o]/3,c[o+1]-d[o+1]*f[o]/3,u[o+1],c[o+1],!1,s[o+1]);return l}return i.Interpolation.none()([])}},i.Interpolation.step=function(e){return e=i.extend({},{postpone:!0,fillHoles:!1},e),function(t,n){for(var s,r,a,o=new i.Svg.Path,l=0;l<t.length;l+=2){var u=t[l],c=t[l+1],h=n[l/2];void 0!==h.value?(void 0===a?o.move(u,c,!1,h):(e.postpone?o.line(u,r,!1,a):o.line(s,c,!1,h),o.line(u,c,!1,h)),s=u,r=c,a=h):e.fillHoles||(s=r=a=void 0)}return o}}}(window,document,e),function(e,t,i){"use strict";i.EventEmitter=function(){var e=[];return{addEventHandler:function(t,i){e[t]=e[t]||[],e[t].push(i)},removeEventHandler:function(t,i){e[t]&&(i?(e[t].splice(e[t].indexOf(i),1),0===e[t].length&&delete e[t]):delete e[t])},emit:function(t,i){e[t]&&e[t].forEach(function(e){e(i)}),e["*"]&&e["*"].forEach(function(e){e(t,i)})}}}}(window,document,e),function(e,t,i){"use strict";i.Class={extend:function(e,t){var n=t||this.prototype||i.Class,s=Object.create(n);i.Class.cloneDefinitions(s,e);var r=function(){var e,t=s.constructor||function(){};return e=this===i?Object.create(s):this,t.apply(e,Array.prototype.slice.call(arguments,0)),e};return r.prototype=s,r.super=n,r.extend=this.extend,r},cloneDefinitions:function(){var e=function(e){var t=[];if(e.length)for(var i=0;i<e.length;i++)t.push(e[i]);return t}(arguments),t=e[0];return e.splice(1,e.length-1).forEach(function(e){Object.getOwnPropertyNames(e).forEach(function(i){delete t[i],Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))})}),t}}}(window,document,e),function(e,t,i){"use strict";function n(){e.addEventListener("resize",this.resizeListener),this.optionsProvider=i.optionsProvider(this.options,this.responsiveOptions,this.eventEmitter),this.eventEmitter.addEventHandler("optionsChanged",function(){this.update()}.bind(this)),this.options.plugins&&this.options.plugins.forEach(function(e){e instanceof Array?e[0](this,e[1]):e(this)}.bind(this)),this.eventEmitter.emit("data",{type:"initial",data:this.data}),this.createChart(this.optionsProvider.getCurrentOptions()),this.initializeTimeoutId=void 0}i.Base=i.Class.extend({constructor:function(e,t,s,r,a){this.container=i.querySelector(e),this.data=t||{},this.data.labels=this.data.labels||[],this.data.series=this.data.series||[],this.defaultOptions=s,this.options=r,this.responsiveOptions=a,this.eventEmitter=i.EventEmitter(),this.supportsForeignObject=i.Svg.isSupported("Extensibility"),this.supportsAnimations=i.Svg.isSupported("AnimationEventsAttribute"),this.resizeListener=function(){this.update()}.bind(this),this.container&&(this.container.__chartist__&&this.container.__chartist__.detach(),this.container.__chartist__=this),this.initializeTimeoutId=setTimeout(n.bind(this),0)},optionsProvider:void 0,container:void 0,svg:void 0,eventEmitter:void 0,createChart:function(){throw new Error("Base chart type can't be instantiated!")},update:function(e,t,n){return e&&(this.data=e||{},this.data.labels=this.data.labels||[],this.data.series=this.data.series||[],this.eventEmitter.emit("data",{type:"update",data:this.data})),t&&(this.options=i.extend({},n?this.options:this.defaultOptions,t),this.initializeTimeoutId||(this.optionsProvider.removeMediaQueryListeners(),this.optionsProvider=i.optionsProvider(this.options,this.responsiveOptions,this.eventEmitter))),this.initializeTimeoutId||this.createChart(this.optionsProvider.getCurrentOptions()),this},detach:function(){return this.initializeTimeoutId?e.clearTimeout(this.initializeTimeoutId):(e.removeEventListener("resize",this.resizeListener),this.optionsProvider.removeMediaQueryListeners()),this},on:function(e,t){return this.eventEmitter.addEventHandler(e,t),this},off:function(e,t){return this.eventEmitter.removeEventHandler(e,t),this},version:i.version,supportsForeignObject:!1})}(window,document,e),function(e,t,i){"use strict";i.Svg=i.Class.extend({constructor:function(e,n,s,r,a){e instanceof Element?this._node=e:(this._node=t.createElementNS(i.namespaces.svg,e),"svg"===e&&this.attr({"xmlns:ct":i.namespaces.ct})),n&&this.attr(n),s&&this.addClass(s),r&&(a&&r._node.firstChild?r._node.insertBefore(this._node,r._node.firstChild):r._node.appendChild(this._node))},attr:function(e,t){return"string"==typeof e?t?this._node.getAttributeNS(t,e):this._node.getAttribute(e):(Object.keys(e).forEach(function(t){if(void 0!==e[t])if(-1!==t.indexOf(":")){var n=t.split(":");this._node.setAttributeNS(i.namespaces[n[0]],t,e[t])}else this._node.setAttribute(t,e[t])}.bind(this)),this)},elem:function(e,t,n,s){return new i.Svg(e,t,n,this,s)},parent:function(){return this._node.parentNode instanceof SVGElement?new i.Svg(this._node.parentNode):null},root:function(){for(var e=this._node;"svg"!==e.nodeName;)e=e.parentNode;return new i.Svg(e)},querySelector:function(e){var t=this._node.querySelector(e);return t?new i.Svg(t):null},querySelectorAll:function(e){var t=this._node.querySelectorAll(e);return t.length?new i.Svg.List(t):null},getNode:function(){return this._node},foreignObject:function(e,n,s,r){if("string"==typeof e){var a=t.createElement("div");a.innerHTML=e,e=a.firstChild}e.setAttribute("xmlns",i.namespaces.xmlns);var o=this.elem("foreignObject",n,s,r);return o._node.appendChild(e),o},text:function(e){return this._node.appendChild(t.createTextNode(e)),this},empty:function(){for(;this._node.firstChild;)this._node.removeChild(this._node.firstChild);return this},remove:function(){return this._node.parentNode.removeChild(this._node),this.parent()},replace:function(e){return this._node.parentNode.replaceChild(e._node,this._node),e},append:function(e,t){return t&&this._node.firstChild?this._node.insertBefore(e._node,this._node.firstChild):this._node.appendChild(e._node),this},classes:function(){return this._node.getAttribute("class")?this._node.getAttribute("class").trim().split(/\s+/):[]},addClass:function(e){return this._node.setAttribute("class",this.classes(this._node).concat(e.trim().split(/\s+/)).filter(function(e,t,i){return i.indexOf(e)===t}).join(" ")),this},removeClass:function(e){var t=e.trim().split(/\s+/);return this._node.setAttribute("class",this.classes(this._node).filter(function(e){return-1===t.indexOf(e)}).join(" ")),this},removeAllClasses:function(){return this._node.setAttribute("class",""),this},height:function(){return this._node.getBoundingClientRect().height},width:function(){return this._node.getBoundingClientRect().width},animate:function(e,t,n){return void 0===t&&(t=!0),Object.keys(e).forEach(function(s){function r(e,t){var r,a,o,l={};e.easing&&(o=e.easing instanceof Array?e.easing:i.Svg.Easing[e.easing],delete e.easing),e.begin=i.ensureUnit(e.begin,"ms"),e.dur=i.ensureUnit(e.dur,"ms"),o&&(e.calcMode="spline",e.keySplines=o.join(" "),e.keyTimes="0;1"),t&&(e.fill="freeze",l[s]=e.from,this.attr(l),a=i.quantity(e.begin||0).value,e.begin="indefinite"),r=this.elem("animate",i.extend({attributeName:s},e)),t&&setTimeout(function(){try{r._node.beginElement()}catch(t){l[s]=e.to,this.attr(l),r.remove()}}.bind(this),a),n&&r._node.addEventListener("beginEvent",function(){n.emit("animationBegin",{element:this,animate:r._node,params:e})}.bind(this)),r._node.addEventListener("endEvent",function(){n&&n.emit("animationEnd",{element:this,animate:r._node,params:e}),t&&(l[s]=e.to,this.attr(l),r.remove())}.bind(this))}e[s]instanceof Array?e[s].forEach(function(e){r.bind(this)(e,!1)}.bind(this)):r.bind(this)(e[s],t)}.bind(this)),this}}),i.Svg.isSupported=function(e){return t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#"+e,"1.1")};i.Svg.Easing={easeInSine:[.47,0,.745,.715],easeOutSine:[.39,.575,.565,1],easeInOutSine:[.445,.05,.55,.95],easeInQuad:[.55,.085,.68,.53],easeOutQuad:[.25,.46,.45,.94],easeInOutQuad:[.455,.03,.515,.955],easeInCubic:[.55,.055,.675,.19],easeOutCubic:[.215,.61,.355,1],easeInOutCubic:[.645,.045,.355,1],easeInQuart:[.895,.03,.685,.22],easeOutQuart:[.165,.84,.44,1],easeInOutQuart:[.77,0,.175,1],easeInQuint:[.755,.05,.855,.06],easeOutQuint:[.23,1,.32,1],easeInOutQuint:[.86,0,.07,1],easeInExpo:[.95,.05,.795,.035],easeOutExpo:[.19,1,.22,1],easeInOutExpo:[1,0,0,1],easeInCirc:[.6,.04,.98,.335],easeOutCirc:[.075,.82,.165,1],easeInOutCirc:[.785,.135,.15,.86],easeInBack:[.6,-.28,.735,.045],easeOutBack:[.175,.885,.32,1.275],easeInOutBack:[.68,-.55,.265,1.55]},i.Svg.List=i.Class.extend({constructor:function(e){var t=this;this.svgElements=[];for(var n=0;n<e.length;n++)this.svgElements.push(new i.Svg(e[n]));Object.keys(i.Svg.prototype).filter(function(e){return-1===["constructor","parent","querySelector","querySelectorAll","replace","append","classes","height","width"].indexOf(e)}).forEach(function(e){t[e]=function(){var n=Array.prototype.slice.call(arguments,0);return t.svgElements.forEach(function(t){i.Svg.prototype[e].apply(t,n)}),t}})}})}(window,document,e),function(e,t,i){"use strict";function n(e,t,n,s,r,a){var o=i.extend({command:r?e.toLowerCase():e.toUpperCase()},t,a?{data:a}:{});n.splice(s,0,o)}function s(e,t){e.forEach(function(i,n){r[i.command.toLowerCase()].forEach(function(s,r){t(i,s,n,r,e)})})}var r={m:["x","y"],l:["x","y"],c:["x1","y1","x2","y2","x","y"],a:["rx","ry","xAr","lAf","sf","x","y"]},a={accuracy:3};i.Svg.Path=i.Class.extend({constructor:function(e,t){this.pathElements=[],this.pos=0,this.close=e,this.options=i.extend({},a,t)},position:function(e){return void 0!==e?(this.pos=Math.max(0,Math.min(this.pathElements.length,e)),this):this.pos},remove:function(e){return this.pathElements.splice(this.pos,e),this},move:function(e,t,i,s){return n("M",{x:+e,y:+t},this.pathElements,this.pos++,i,s),this},line:function(e,t,i,s){return n("L",{x:+e,y:+t},this.pathElements,this.pos++,i,s),this},curve:function(e,t,i,s,r,a,o,l){return n("C",{x1:+e,y1:+t,x2:+i,y2:+s,x:+r,y:+a},this.pathElements,this.pos++,o,l),this},arc:function(e,t,i,s,r,a,o,l,u){return n("A",{rx:+e,ry:+t,xAr:+i,lAf:+s,sf:+r,x:+a,y:+o},this.pathElements,this.pos++,l,u),this},scale:function(e,t){return s(this.pathElements,function(i,n){i[n]*="x"===n[0]?e:t}),this},translate:function(e,t){return s(this.pathElements,function(i,n){i[n]+="x"===n[0]?e:t}),this},transform:function(e){return s(this.pathElements,function(t,i,n,s,r){var a=e(t,i,n,s,r);(a||0===a)&&(t[i]=a)}),this},parse:function(e){var t=e.replace(/([A-Za-z])([0-9])/g,"$1 $2").replace(/([0-9])([A-Za-z])/g,"$1 $2").split(/[\s,]+/).reduce(function(e,t){return t.match(/[A-Za-z]/)&&e.push([]),e[e.length-1].push(t),e},[]);"Z"===t[t.length-1][0].toUpperCase()&&t.pop();var n=t.map(function(e){var t=e.shift(),n=r[t.toLowerCase()];return i.extend({command:t},n.reduce(function(t,i,n){return t[i]=+e[n],t},{}))}),s=[this.pos,0];return Array.prototype.push.apply(s,n),Array.prototype.splice.apply(this.pathElements,s),this.pos+=n.length,this},stringify:function(){var e=Math.pow(10,this.options.accuracy);return this.pathElements.reduce(function(t,i){var n=r[i.command.toLowerCase()].map(function(t){return this.options.accuracy?Math.round(i[t]*e)/e:i[t]}.bind(this));return t+i.command+n.join(",")}.bind(this),"")+(this.close?"Z":"")},clone:function(e){var t=new i.Svg.Path(e||this.close);return t.pos=this.pos,t.pathElements=this.pathElements.slice().map(function(e){return i.extend({},e)}),t.options=i.extend({},this.options),t},splitByCommand:function(e){var t=[new i.Svg.Path];return this.pathElements.forEach(function(n){n.command===e.toUpperCase()&&0!==t[t.length-1].pathElements.length&&t.push(new i.Svg.Path),t[t.length-1].pathElements.push(n)}),t}}),i.Svg.Path.elementDescriptions=r,i.Svg.Path.join=function(e,t,n){for(var s=new i.Svg.Path(t,n),r=0;r<e.length;r++)for(var a=e[r],o=0;o<a.pathElements.length;o++)s.pathElements.push(a.pathElements[o]);return s}}(window,document,e),function(e,t,i){"use strict";var n={x:{pos:"x",len:"width",dir:"horizontal",rectStart:"x1",rectEnd:"x2",rectOffset:"y2"},y:{pos:"y",len:"height",dir:"vertical",rectStart:"y2",rectEnd:"y1",rectOffset:"x1"}};i.Axis=i.Class.extend({constructor:function(e,t,i,s){this.units=e,this.counterUnits=e===n.x?n.y:n.x,this.chartRect=t,this.axisLength=t[e.rectEnd]-t[e.rectStart],this.gridOffset=t[e.rectOffset],this.ticks=i,this.options=s},createGridAndLabels:function(e,t,n,s,r){var a=s["axis"+this.units.pos.toUpperCase()],o=this.ticks.map(this.projectValue.bind(this)),l=this.ticks.map(a.labelInterpolationFnc);o.forEach(function(u,c){var h,d={x:0,y:0};h=o[c+1]?o[c+1]-u:Math.max(this.axisLength-u,30),i.isFalseyButZero(l[c])&&""!==l[c]||("x"===this.units.pos?(u=this.chartRect.x1+u,d.x=s.axisX.labelOffset.x,"start"===s.axisX.position?d.y=this.chartRect.padding.top+s.axisX.labelOffset.y+(n?5:20):d.y=this.chartRect.y1+s.axisX.labelOffset.y+(n?5:20)):(u=this.chartRect.y1-u,d.y=s.axisY.labelOffset.y-(n?h:0),"start"===s.axisY.position?d.x=n?this.chartRect.padding.left+s.axisY.labelOffset.x:this.chartRect.x1-10:d.x=this.chartRect.x2+s.axisY.labelOffset.x+10),a.showGrid&&i.createGrid(u,c,this,this.gridOffset,this.chartRect[this.counterUnits.len](),e,[s.classNames.grid,s.classNames[this.units.dir]],r),a.showLabel&&i.createLabel(u,h,c,l,this,a.offset,d,t,[s.classNames.label,s.classNames[this.units.dir],"start"===a.position?s.classNames[a.position]:s.classNames.end],n,r))}.bind(this))},projectValue:function(e,t,i){throw new Error("Base axis can't be instantiated!")}}),i.Axis.units=n}(window,document,e),function(e,t,i){"use strict";i.AutoScaleAxis=i.Axis.extend({constructor:function(e,t,n,s){var r=s.highLow||i.getHighLow(t,s,e.pos);this.bounds=i.getBounds(n[e.rectEnd]-n[e.rectStart],r,s.scaleMinSpace||20,s.onlyInteger),this.range={min:this.bounds.min,max:this.bounds.max},i.AutoScaleAxis.super.constructor.call(this,e,n,this.bounds.values,s)},projectValue:function(e){return this.axisLength*(+i.getMultiValue(e,this.units.pos)-this.bounds.min)/this.bounds.range}})}(window,document,e),function(e,t,i){"use strict";i.FixedScaleAxis=i.Axis.extend({constructor:function(e,t,n,s){var r=s.highLow||i.getHighLow(t,s,e.pos);this.divisor=s.divisor||1,this.ticks=s.ticks||i.times(this.divisor).map(function(e,t){return r.low+(r.high-r.low)/this.divisor*t}.bind(this)),this.ticks.sort(function(e,t){return e-t}),this.range={min:r.low,max:r.high},i.FixedScaleAxis.super.constructor.call(this,e,n,this.ticks,s),this.stepLength=this.axisLength/this.divisor},projectValue:function(e){return this.axisLength*(+i.getMultiValue(e,this.units.pos)-this.range.min)/(this.range.max-this.range.min)}})}(window,document,e),function(e,t,i){"use strict";i.StepAxis=i.Axis.extend({constructor:function(e,t,n,s){i.StepAxis.super.constructor.call(this,e,n,s.ticks,s);var r=Math.max(1,s.ticks.length-(s.stretch?1:0));this.stepLength=this.axisLength/r},projectValue:function(e,t){return this.stepLength*t}})}(window,document,e),function(e,t,i){"use strict";var n={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,type:void 0},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,type:void 0,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,showLine:!0,showPoint:!0,showArea:!1,areaBase:0,lineSmooth:!0,showGridBackground:!1,low:void 0,high:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},fullWidth:!1,reverseData:!1,classNames:{chart:"ct-chart-line",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",line:"ct-line",point:"ct-point",area:"ct-area",grid:"ct-grid",gridGroup:"ct-grids",gridBackground:"ct-grid-background",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};i.Line=i.Base.extend({constructor:function(e,t,s,r){i.Line.super.constructor.call(this,e,t,n,i.extend({},n,s),r)},createChart:function(e){var t=i.normalizeData(this.data,e.reverseData,!0);this.svg=i.createSvg(this.container,e.width,e.height,e.classNames.chart);var s,r,a=this.svg.elem("g").addClass(e.classNames.gridGroup),o=this.svg.elem("g"),l=this.svg.elem("g").addClass(e.classNames.labelGroup),u=i.createChartRect(this.svg,e,n.padding);s=void 0===e.axisX.type?new i.StepAxis(i.Axis.units.x,t.normalized.series,u,i.extend({},e.axisX,{ticks:t.normalized.labels,stretch:e.fullWidth})):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,u,e.axisX),r=void 0===e.axisY.type?new i.AutoScaleAxis(i.Axis.units.y,t.normalized.series,u,i.extend({},e.axisY,{high:i.isNumeric(e.high)?e.high:e.axisY.high,low:i.isNumeric(e.low)?e.low:e.axisY.low})):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,u,e.axisY),s.createGridAndLabels(a,l,this.supportsForeignObject,e,this.eventEmitter),r.createGridAndLabels(a,l,this.supportsForeignObject,e,this.eventEmitter),e.showGridBackground&&i.createGridBackground(a,u,e.classNames.gridBackground,this.eventEmitter),t.raw.series.forEach(function(n,a){var l=o.elem("g");l.attr({"ct:series-name":n.name,"ct:meta":i.serialize(n.meta)}),l.addClass([e.classNames.series,n.className||e.classNames.series+"-"+i.alphaNumerate(a)].join(" "));var c=[],h=[];t.normalized.series[a].forEach(function(e,o){var l={x:u.x1+s.projectValue(e,o,t.normalized.series[a]),y:u.y1-r.projectValue(e,o,t.normalized.series[a])};c.push(l.x,l.y),h.push({value:e,valueIndex:o,meta:i.getMetaData(n,o)})}.bind(this));var d={lineSmooth:i.getSeriesOption(n,e,"lineSmooth"),showPoint:i.getSeriesOption(n,e,"showPoint"),showLine:i.getSeriesOption(n,e,"showLine"),showArea:i.getSeriesOption(n,e,"showArea"),areaBase:i.getSeriesOption(n,e,"areaBase")},p=("function"==typeof d.lineSmooth?d.lineSmooth:d.lineSmooth?i.Interpolation.monotoneCubic():i.Interpolation.none())(c,h);if(d.showPoint&&p.pathElements.forEach(function(t){var o=l.elem("line",{x1:t.x,y1:t.y,x2:t.x+.01,y2:t.y},e.classNames.point).attr({"ct:value":[t.data.value.x,t.data.value.y].filter(i.isNumeric).join(","),"ct:meta":i.serialize(t.data.meta)});this.eventEmitter.emit("draw",{type:"point",value:t.data.value,index:t.data.valueIndex,meta:t.data.meta,series:n,seriesIndex:a,axisX:s,axisY:r,group:l,element:o,x:t.x,y:t.y})}.bind(this)),d.showLine){var m=l.elem("path",{d:p.stringify()},e.classNames.line,!0);this.eventEmitter.emit("draw",{type:"line",values:t.normalized.series[a],path:p.clone(),chartRect:u,index:a,series:n,seriesIndex:a,seriesMeta:n.meta,axisX:s,axisY:r,group:l,element:m})}if(d.showArea&&r.range){var f=Math.max(Math.min(d.areaBase,r.range.max),r.range.min),g=u.y1-r.projectValue(f);p.splitByCommand("M").filter(function(e){return e.pathElements.length>1}).map(function(e){var t=e.pathElements[0],i=e.pathElements[e.pathElements.length-1];return e.clone(!0).position(0).remove(1).move(t.x,g).line(t.x,t.y).position(e.pathElements.length+1).line(i.x,g)}).forEach(function(i){var o=l.elem("path",{d:i.stringify()},e.classNames.area,!0);this.eventEmitter.emit("draw",{type:"area",values:t.normalized.series[a],path:i.clone(),series:n,seriesIndex:a,axisX:s,axisY:r,chartRect:u,index:a,group:l,element:o})}.bind(this))}}.bind(this)),this.eventEmitter.emit("created",{bounds:r.bounds,chartRect:u,axisX:s,axisY:r,svg:this.svg,options:e})}})}(window,document,e),function(e,t,i){"use strict";var n={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,scaleMinSpace:30,onlyInteger:!1},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,high:void 0,low:void 0,referenceValue:0,chartPadding:{top:15,right:15,bottom:5,left:10},seriesBarDistance:15,stackBars:!1,stackMode:"accumulate",horizontalBars:!1,distributeSeries:!1,reverseData:!1,showGridBackground:!1,classNames:{chart:"ct-chart-bar",horizontalBars:"ct-horizontal-bars",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",bar:"ct-bar",grid:"ct-grid",gridGroup:"ct-grids",gridBackground:"ct-grid-background",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};i.Bar=i.Base.extend({constructor:function(e,t,s,r){i.Bar.super.constructor.call(this,e,t,n,i.extend({},n,s),r)},createChart:function(e){var t,s;e.distributeSeries?(t=i.normalizeData(this.data,e.reverseData,e.horizontalBars?"x":"y"),t.normalized.series=t.normalized.series.map(function(e){return[e]})):t=i.normalizeData(this.data,e.reverseData,e.horizontalBars?"x":"y"),this.svg=i.createSvg(this.container,e.width,e.height,e.classNames.chart+(e.horizontalBars?" "+e.classNames.horizontalBars:""));var r=this.svg.elem("g").addClass(e.classNames.gridGroup),a=this.svg.elem("g"),o=this.svg.elem("g").addClass(e.classNames.labelGroup);if(e.stackBars&&0!==t.normalized.series.length){var l=i.serialMap(t.normalized.series,function(){return Array.prototype.slice.call(arguments).map(function(e){return e}).reduce(function(e,t){return{x:e.x+(t&&t.x)||0,y:e.y+(t&&t.y)||0}},{x:0,y:0})});s=i.getHighLow([l],e,e.horizontalBars?"x":"y")}else s=i.getHighLow(t.normalized.series,e,e.horizontalBars?"x":"y");s.high=+e.high||(0===e.high?0:s.high),s.low=+e.low||(0===e.low?0:s.low);var u,c,h,d,p,m=i.createChartRect(this.svg,e,n.padding);c=e.distributeSeries&&e.stackBars?t.normalized.labels.slice(0,1):t.normalized.labels,e.horizontalBars?(u=d=void 0===e.axisX.type?new i.AutoScaleAxis(i.Axis.units.x,t.normalized.series,m,i.extend({},e.axisX,{highLow:s,referenceValue:0})):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,m,i.extend({},e.axisX,{highLow:s,referenceValue:0})),h=p=void 0===e.axisY.type?new i.StepAxis(i.Axis.units.y,t.normalized.series,m,{ticks:c}):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,m,e.axisY)):(h=d=void 0===e.axisX.type?new i.StepAxis(i.Axis.units.x,t.normalized.series,m,{ticks:c}):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,m,e.axisX),u=p=void 0===e.axisY.type?new i.AutoScaleAxis(i.Axis.units.y,t.normalized.series,m,i.extend({},e.axisY,{highLow:s,referenceValue:0})):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,m,i.extend({},e.axisY,{highLow:s,referenceValue:0})));var f=e.horizontalBars?m.x1+u.projectValue(0):m.y1-u.projectValue(0),g=[];h.createGridAndLabels(r,o,this.supportsForeignObject,e,this.eventEmitter),u.createGridAndLabels(r,o,this.supportsForeignObject,e,this.eventEmitter),e.showGridBackground&&i.createGridBackground(r,m,e.classNames.gridBackground,this.eventEmitter),t.raw.series.forEach(function(n,s){var r,o,l=s-(t.raw.series.length-1)/2;r=e.distributeSeries&&!e.stackBars?h.axisLength/t.normalized.series.length/2:e.distributeSeries&&e.stackBars?h.axisLength/2:h.axisLength/t.normalized.series[s].length/2,(o=a.elem("g")).attr({"ct:series-name":n.name,"ct:meta":i.serialize(n.meta)}),o.addClass([e.classNames.series,n.className||e.classNames.series+"-"+i.alphaNumerate(s)].join(" ")),t.normalized.series[s].forEach(function(a,c){var v,x,y,b;if(b=e.distributeSeries&&!e.stackBars?s:e.distributeSeries&&e.stackBars?0:c,v=e.horizontalBars?{x:m.x1+u.projectValue(a&&a.x?a.x:0,c,t.normalized.series[s]),y:m.y1-h.projectValue(a&&a.y?a.y:0,b,t.normalized.series[s])}:{x:m.x1+h.projectValue(a&&a.x?a.x:0,b,t.normalized.series[s]),y:m.y1-u.projectValue(a&&a.y?a.y:0,c,t.normalized.series[s])},h instanceof i.StepAxis&&(h.options.stretch||(v[h.units.pos]+=r*(e.horizontalBars?-1:1)),v[h.units.pos]+=e.stackBars||e.distributeSeries?0:l*e.seriesBarDistance*(e.horizontalBars?-1:1)),y=g[c]||f,g[c]=y-(f-v[h.counterUnits.pos]),void 0!==a){var w={};w[h.units.pos+"1"]=v[h.units.pos],w[h.units.pos+"2"]=v[h.units.pos],!e.stackBars||"accumulate"!==e.stackMode&&e.stackMode?(w[h.counterUnits.pos+"1"]=f,w[h.counterUnits.pos+"2"]=v[h.counterUnits.pos]):(w[h.counterUnits.pos+"1"]=y,w[h.counterUnits.pos+"2"]=g[c]),w.x1=Math.min(Math.max(w.x1,m.x1),m.x2),w.x2=Math.min(Math.max(w.x2,m.x1),m.x2),w.y1=Math.min(Math.max(w.y1,m.y2),m.y1),w.y2=Math.min(Math.max(w.y2,m.y2),m.y1);var E=i.getMetaData(n,c);x=o.elem("line",w,e.classNames.bar).attr({"ct:value":[a.x,a.y].filter(i.isNumeric).join(","),"ct:meta":i.serialize(E)}),this.eventEmitter.emit("draw",i.extend({type:"bar",value:a,index:c,meta:E,series:n,seriesIndex:s,axisX:d,axisY:p,chartRect:m,group:o,element:x},w))}}.bind(this))}.bind(this)),this.eventEmitter.emit("created",{bounds:u.bounds,chartRect:m,axisX:d,axisY:p,svg:this.svg,options:e})}})}(window,document,e),function(e,t,i){"use strict";function n(e,t,i){var n=t.x>e.x;return n&&"explode"===i||!n&&"implode"===i?"start":n&&"implode"===i||!n&&"explode"===i?"end":"middle"}var s={width:void 0,height:void 0,chartPadding:5,classNames:{chartPie:"ct-chart-pie",chartDonut:"ct-chart-donut",series:"ct-series",slicePie:"ct-slice-pie",sliceDonut:"ct-slice-donut",sliceDonutSolid:"ct-slice-donut-solid",label:"ct-label"},startAngle:0,total:void 0,donut:!1,donutSolid:!1,donutWidth:60,showLabel:!0,labelOffset:0,labelPosition:"inside",labelInterpolationFnc:i.noop,labelDirection:"neutral",reverseData:!1,ignoreEmptyValues:!1};i.Pie=i.Base.extend({constructor:function(e,t,n,r){i.Pie.super.constructor.call(this,e,t,s,i.extend({},s,n),r)},createChart:function(e){var t,r,a,o,l,u=i.normalizeData(this.data),c=[],h=e.startAngle;this.svg=i.createSvg(this.container,e.width,e.height,e.donut?e.classNames.chartDonut:e.classNames.chartPie),r=i.createChartRect(this.svg,e,s.padding),a=Math.min(r.width()/2,r.height()/2),l=e.total||u.normalized.series.reduce(function(e,t){return e+t},0);var d=i.quantity(e.donutWidth);"%"===d.unit&&(d.value*=a/100),a-=e.donut&&!e.donutSolid?d.value/2:0,o="outside"===e.labelPosition||e.donut&&!e.donutSolid?a:"center"===e.labelPosition?0:e.donutSolid?a-d.value/2:a/2,o+=e.labelOffset;var p={x:r.x1+r.width()/2,y:r.y2+r.height()/2},m=1===u.raw.series.filter(function(e){return e.hasOwnProperty("value")?0!==e.value:0!==e}).length;u.raw.series.forEach(function(e,t){c[t]=this.svg.elem("g",null,null)}.bind(this)),e.showLabel&&(t=this.svg.elem("g",null,null)),u.raw.series.forEach(function(s,r){if(0!==u.normalized.series[r]||!e.ignoreEmptyValues){c[r].attr({"ct:series-name":s.name}),c[r].addClass([e.classNames.series,s.className||e.classNames.series+"-"+i.alphaNumerate(r)].join(" "));var f=l>0?h+u.normalized.series[r]/l*360:0,g=Math.max(0,h-(0===r||m?0:.2));f-g>=359.99&&(f=g+359.99);var v,x,y,b=i.polarToCartesian(p.x,p.y,a,g),w=i.polarToCartesian(p.x,p.y,a,f),E=new i.Svg.Path(!e.donut||e.donutSolid).move(w.x,w.y).arc(a,a,0,f-h>180,0,b.x,b.y);e.donut?e.donutSolid&&(y=a-d.value,v=i.polarToCartesian(p.x,p.y,y,h-(0===r||m?0:.2)),x=i.polarToCartesian(p.x,p.y,y,f),E.line(v.x,v.y),E.arc(y,y,0,f-h>180,1,x.x,x.y)):E.line(p.x,p.y);var S=e.classNames.slicePie;e.donut&&(S=e.classNames.sliceDonut,e.donutSolid&&(S=e.classNames.sliceDonutSolid));var A=c[r].elem("path",{d:E.stringify()},S);if(A.attr({"ct:value":u.normalized.series[r],"ct:meta":i.serialize(s.meta)}),e.donut&&!e.donutSolid&&(A._node.style.strokeWidth=d.value+"px"),this.eventEmitter.emit("draw",{type:"slice",value:u.normalized.series[r],totalDataSum:l,index:r,meta:s.meta,series:s,group:c[r],element:A,path:E.clone(),center:p,radius:a,startAngle:h,endAngle:f}),e.showLabel){var z;z=1===u.raw.series.length?{x:p.x,y:p.y}:i.polarToCartesian(p.x,p.y,o,h+(f-h)/2);var M;M=u.normalized.labels&&!i.isFalseyButZero(u.normalized.labels[r])?u.normalized.labels[r]:u.normalized.series[r];var O=e.labelInterpolationFnc(M,r);if(O||0===O){var C=t.elem("text",{dx:z.x,dy:z.y,"text-anchor":n(p,z,e.labelDirection)},e.classNames.label).text(""+O);this.eventEmitter.emit("draw",{type:"label",index:r,group:t,element:C,text:""+O,x:z.x,y:z.y})}}h=f}}.bind(this)),this.eventEmitter.emit("created",{chartRect:r,svg:this.svg,options:e})},determineAnchorPosition:n})}(window,document,e),e});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/chartjs.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/chartjs.min.js
new file mode 100755
index 0000000..6fc5d34
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/chartjs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)a(i[r]);return a}({1:[function(t,e,n){},{}],2:[function(t,e,n){function i(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3})$/);if(i){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i[a]+i[a],16)}else if(i=t.match(/^#([a-fA-F0-9]{6})$/)){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i.slice(2*a,2*a+2),16)}else if(i=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/)){for(a=0;a<e.length;a++)e[a]=parseInt(i[a+1]);n=parseFloat(i[4])}else if(i=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/)){for(a=0;a<e.length;a++)e[a]=Math.round(2.55*parseFloat(i[a+1]));n=parseFloat(i[4])}else if(i=t.match(/(\w+)/)){if("transparent"==i[1])return[0,0,0,0];if(!(e=c[i[1]]))return}for(var a=0;a<e.length;a++)e[a]=u(e[a],0,255);return n=n||0==n?u(n,0,1):1,e[3]=n,e}}function a(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function o(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function r(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(6);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?r(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:r,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:s,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{6:6}],3:[function(t,e,n){var i=t(5),a=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.valid=!1,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};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};o.prototype={isValid:function(){return this.valid},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 t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=t<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},o.prototype.setValues=function(t,e){var n,a=this.values,o=this.spaces,r=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(n=0;n<t.length;n++)a[t][n]=e[s[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(r[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in o)d!==t&&(a[d]=i[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},o.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(l+s)/2,n=s==l?0:i<=.5?u/(s+l):u/(2-s-l),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],o=t[1],r=t[2],l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return n=0==s?0:u/s*1e3/10,s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=s/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function l(t){var e,n,i,a,o=t[0]/255,r=t[1]/255,l=t[2]/255;return a=Math.min(1-o,1-r,1-l),e=(1-o-a)/(1-a)||0,n=(1-r-a)/(1-a)||0,i=(1-l-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function s(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?(n=100*o/903.3,a=n/100*7.787+16/116):(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return m(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:m,xyz2lab:v,xyz2lch:function(t){return y(v(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={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]},C={};for(var D in S)C[JSON.stringify(S[D])]=D},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,n){e.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(t,e,n){var i=t(28)();t(26)(i),t(40)(i),t(22)(i),t(25)(i),t(30)(i),t(21)(i),t(23)(i),t(24)(i),t(29)(i),t(32)(i),t(33)(i),t(31)(i),t(27)(i),t(34)(i),t(35)(i),t(36)(i),t(37)(i),t(38)(i),t(46)(i),t(44)(i),t(45)(i),t(47)(i),t(48)(i),t(49)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(41)(i),t(42)(i),t(43)(i)),i.plugins.register(a),e.exports=i,"undefined"!=typeof window&&(window.Chart=i)},{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,40:40,41:41,42:42,43:43,44:44,45:45,46:46,47:47,48:48,49:49,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.defaults.scatter={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}},t.controllers.scatter=t.controllers.line,t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,n,i){var a=this,o=a.chart,r=a.getMeta(),l=a.getDataset(),s=t.custom||{},u=o.options.elements.rectangle;t._xScale=a.getScaleForId(r.xAxisID),t._yScale=a.getScaleForId(r.yAxisID),t._datasetIndex=a.index,t._index=n,t._model={datasetLabel:l.label,label:o.data.labels[n],borderSkipped:s.borderSkipped?s.borderSkipped:u.borderSkipped,backgroundColor:s.backgroundColor?s.backgroundColor:e.getValueAtIndexOrDefault(l.backgroundColor,n,u.backgroundColor),borderColor:s.borderColor?s.borderColor:e.getValueAtIndexOrDefault(l.borderColor,n,u.borderColor),borderWidth:s.borderWidth?s.borderWidth:e.getValueAtIndexOrDefault(l.borderWidth,n,u.borderWidth)},a.updateElementGeometry(t,n,i),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,o=i.getValueScale(),r=o.getBasePixel(),l=o.isHorizontal(),s=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,s);a.horizontal=l,a.base=n?r:u.base,a.x=l?n?r:u.head:d.center,a.y=l?d.center:n?r:u.head,a.height=l?d.size:void 0,a.width=l?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this.chart,a=this.getIndexScale().options.stacked,o=void 0===t?i.data.datasets.length:t+1,r=[];for(e=0;e<o;++e)(n=i.getDatasetMeta(e)).bar&&i.isDatasetVisible(e)&&(!1===a||!0===a&&-1===r.indexOf(n.stack)||void 0===a&&(void 0===n.stack||-1===r.indexOf(n.stack)))&&r.push(n.stack);return r.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t=this.getIndexScale(),n=t.options,i=this.getStackCount(),a=(t.isHorizontal()?t.width:t.height)/t.ticks.length,o=a*n.categoryPercentage,r=o/i,l=r*n.barPercentage;return l=Math.min(e.getValueOrDefault(n.barThickness,l),e.getValueOrDefault(n.maxBarThickness,1/0)),{stackCount:i,tickSize:a,categorySize:o,categorySpacing:a-o,fullBarSize:r,barSize:l,barSpacing:r-l,scale:t}},calculateBarValuePixels:function(t,e){var n,i,a,o,r,l,s=this,u=s.chart,d=s.getMeta(),c=s.getValueScale(),h=u.data.datasets,f=Number(h[t].data[e]),g=c.options.stacked,p=d.stack,m=0;if(g||void 0===g&&void 0!==p)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===p&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=Number(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(m+=a));return o=c.getPixelForValue(m),r=c.getPixelForValue(m+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i=n.scale,a=this.chart.isCombo,o=this.getStackIndex(t),r=i.getPixelForValue(null,e,t,a),l=n.barSize;return r-=a?n.tickSize/2:0,r+=n.fullBarSize*o,r+=n.categorySpacing/2,r+=n.barSpacing/2,{size:l,base:r,head:r+l,center:r+l/2}},draw:function(){var t,n=this,i=n.chart,a=n.getMeta().data,o=n.getDataset(),r=a.length,l=0;for(e.canvas.clipArea(i.ctx,i.chartArea);l<r;++l)null===(t=o.data[l])||void 0===t||isNaN(t)||a[l].draw();e.canvas.unclipArea(i.ctx)},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;o.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.hoverBackgroundColor,i,e.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(n.hoverBorderColor,i,e.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(n.hoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model,r=this.chart.options.elements.rectangle;o.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(n.backgroundColor,i,r.backgroundColor),o.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(n.borderColor,i,r.borderColor),o.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(n.borderWidth,i,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{}],16:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var n=this,i=n.getMeta().data;e.each(i,function(e,i){n.updateElement(e,i,t)})},updateElement:function(n,i,a){var o=this,r=o.getMeta(),l=o.getScaleForId(r.xAxisID),s=o.getScaleForId(r.yAxisID),u=n.custom||{},d=o.getDataset(),c=d.data[i],h=o.chart.options.elements.point,f=o.index;e.extend(n,{_xScale:l,_yScale:s,_datasetIndex:f,_index:i,_model:{x:a?l.getPixelForDecimal(.5):l.getPixelForValue("object"==typeof c?c:NaN,i,f,o.chart.isCombo),y:a?s.getBasePixel():s.getPixelForValue(c,i,f),radius:a?0:u.radius?u.radius:o.getRadius(c),hitRadius:u.hitRadius?u.hitRadius:e.getValueAtIndexOrDefault(d.hitRadius,i,h.hitRadius)}}),t.DatasetController.prototype.removeHoverStyle.call(o,n,h);var g=n._model;g.skip=u.skip?u.skip:isNaN(g.x)||isNaN(g.y),n.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(n){var i=this;t.DatasetController.prototype.setHoverStyle.call(i,n);var a=i.chart.data.datasets[n._datasetIndex],o=n._index,r=n.custom||{};n._model.radius=r.hoverRadius?r.hoverRadius:e.getValueAtIndexOrDefault(a.hoverRadius,o,i.chart.options.elements.point.hoverRadius)+i.getRadius(a.data[o])},removeHoverStyle:function(e){var n=this;t.DatasetController.prototype.removeHoverStyle.call(n,e,n.chart.options.elements.point);var i=n.chart.data.datasets[e._datasetIndex].data[e._index],a=e.custom||{};e._model.radius=a.radius?a.radius:n.getRadius(i)}})}},{}],17:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults;n.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var o=t.getDatasetMeta(0),r=n.datasets[0],l=o.data[a],s=l&&l.custom||{},u=e.getValueAtIndexOrDefault,d=t.options.elements.arc;return{text:i,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,a,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,a,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,a,d.borderWidth),hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,n){var i=n.labels[t.index],a=": "+n.datasets[t.datasetIndex].data[t.index];return e.isArray(i)?(i=i.slice(),i[0]+=a):i+=a,i}}}},n.pie=e.clone(n.doughnut),e.extend(n.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var n=this,i=n.chart,a=i.chartArea,o=i.options,r=o.elements.arc,l=a.right-a.left-r.borderWidth,s=a.bottom-a.top-r.borderWidth,u=Math.min(l,s),d={x:0,y:0},c=n.getMeta(),h=o.cutoutPercentage,f=o.circumference;if(f<2*Math.PI){var g=o.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,m={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&0<=p||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(m.x*(m.x<0?1:w),v.x*(v.x<0?1:w)),y:k?-1:Math.min(m.y*(m.y<0?1:w),v.y*(v.y<0?1:w))},S={x:b?1:Math.max(m.x*(m.x>0?1:w),v.x*(v.x>0?1:w)),y:x?1:Math.max(m.y*(m.y>0?1:w),v.y*(v.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}i.borderWidth=n.getMaxBorderWidth(c.data),i.outerRadius=Math.max((u-i.borderWidth)/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:0,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=d.x*i.outerRadius,i.offsetY=d.y*i.outerRadius,c.total=n.calculateTotal(),n.outerRadius=i.outerRadius-i.radiusLength*n.getRingIndex(n.index),n.innerRadius=Math.max(n.outerRadius-i.radiusLength,0),e.each(c.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){var a=this,o=a.chart,r=o.chartArea,l=o.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=a.getDataset(),g=i&&s.animateRotate?0:t.hidden?0:a.calculateCircumference(f.data[n])*(l.circumference/(2*Math.PI)),p=i&&s.animateScale?0:a.innerRadius,m=i&&s.animateScale?0:a.outerRadius,v=e.getValueAtIndexOrDefault;e.extend(t,{_datasetIndex:a.index,_index:n,_model:{x:u+o.offsetX,y:d+o.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:v(f.label,n,o.data.labels[n])}});var b=t._model;this.removeHoverStyle(t),i&&s.animateRotate||(b.startAngle=0===n?l.rotation:a.getMeta().data[n-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,n=this.getDataset(),i=this.getMeta(),a=0;return e.each(i.data,function(e,i){t=n.data[i],isNaN(t)||e.hidden||(a+=Math.abs(t))}),a},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,n=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0,i=e>i?e:i,i=n>i?n:i;return i}})}},{}],18:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return n.getValueOrDefault(t.showLine,e.showLines)}var n=t.helpers;t.defaults.line={showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,update:function(t){var i,a,o,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(o=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:o.tension?o.tension:n.getValueOrDefault(f.lineTension,c.tension),backgroundColor:o.backgroundColor?o.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:f.borderWidth||c.borderWidth,borderColor:o.borderColor?o.borderColor:f.borderColor||c.borderColor,borderCapStyle:o.borderCapStyle?o.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:o.borderDash?o.borderDash:f.borderDash||c.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:o.fill?o.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:o.steppedLine?o.steppedLine:n.getValueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:o.cubicInterpolationMode?o.cubicInterpolationMode:n.getValueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),i=0,a=u.length;i<a;++i)r.updateElement(u[i],i,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),i=0,a=u.length;i<a;++i)u[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,a=this.getDataset(),o=t.custom||{};return o.backgroundColor?i=o.backgroundColor:a.pointBackgroundColor?i=n.getValueAtIndexOrDefault(a.pointBackgroundColor,e,i):a.backgroundColor&&(i=a.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,a=this.getDataset(),o=t.custom||{};return o.borderColor?i=o.borderColor:a.pointBorderColor?i=n.getValueAtIndexOrDefault(a.pointBorderColor,e,i):a.borderColor&&(i=a.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,a=this.getDataset(),o=t.custom||{};return isNaN(o.borderWidth)?isNaN(a.pointBorderWidth)?isNaN(a.borderWidth)||(i=a.borderWidth):i=n.getValueAtIndexOrDefault(a.pointBorderWidth,e,i):i=o.borderWidth,i},updateElement:function(t,e,i){var a,o,r=this,l=r.getMeta(),s=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point,p=1===(r.chart.data.labels||[]).length||1===u.data.length||r.chart.isCombo;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),a=f.getPixelForValue("object"==typeof c?c:NaN,e,d,p),o=i?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:a,y:o,skip:s.skip||isNaN(a)||isNaN(o),radius:s.radius||n.getValueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:s.pointStyle||n.getValueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:!!l.dataset._model&&l.dataset._model.steppedLine,hitRadius:s.hitRadius||n.getValueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,o,r=this,l=r.chart,s=r.getMeta(),u=r.getScaleForId(s.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=l.data.datasets[i],"line"===(o=l.getDatasetMeta(i)).type&&o.yAxisID===u.id&&l.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,i,a,o,r,l=this,s=l.getMeta(),u=l.chart.chartArea,d=s.data||[];if(s.dataset._model.spanGaps&&(d=d.filter(function(t){return!t._model.skip})),"monotone"===s.dataset._model.cubicInterpolationMode)n.splineCurveMonotone(d);else for(e=0,i=d.length;e<i;++e)a=d[e],o=a._model,r=n.splineCurve(n.previousItem(d,e)._model,o,n.nextItem(d,e)._model,s.dataset._model.tension),o.controlPointPreviousX=r.previous.x,o.controlPointPreviousY=r.previous.y,o.controlPointNextX=r.next.x,o.controlPointNextY=r.next.y;if(l.chart.options.elements.line.capBezierPoints)for(e=0,i=d.length;e<i;++e)o=d[e]._model,o.controlPointPreviousX=t(o.controlPointPreviousX,u.left,u.right),o.controlPointPreviousY=t(o.controlPointPreviousY,u.top,u.bottom),o.controlPointNextX=t(o.controlPointNextX,u.left,u.right),o.controlPointNextY=t(o.controlPointNextY,u.top,u.bottom)},draw:function(){var n=this,i=n.chart,a=n.getMeta(),o=a.data||[],r=i.chartArea,l=o.length,s=0;for(t.canvasHelpers.clipArea(i.ctx,r),e(n.getDataset(),i.options)&&a.dataset.draw(),t.canvasHelpers.unclipArea(i.ctx);s<l;++s)o[s].draw(r)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;o.radius=a.hoverRadius||n.getValueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),o.backgroundColor=a.hoverBackgroundColor||n.getValueAtIndexOrDefault(e.pointHoverBackgroundColor,i,n.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor||n.getValueAtIndexOrDefault(e.pointHoverBorderColor,i,n.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth||n.getValueAtIndexOrDefault(e.pointHoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),r.radius=o.radius||n.getValueAtIndexOrDefault(i.pointRadius,a,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,a),r.borderColor=e.getPointBorderColor(t,a),r.borderWidth=e.getPointBorderWidth(t,a)}})}},{}],19:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var o=t.getDatasetMeta(0),r=n.datasets[0],l=o.data[a].custom||{},s=e.getValueAtIndexOrDefault,u=t.options.elements.arc;return{text:i,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,a,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,a,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,a,u.borderWidth),hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)a=r.getDatasetMeta(n),a.data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var n=this,i=n.chart,a=i.chartArea,o=n.getMeta(),r=i.options,l=r.elements.arc,s=Math.min(a.right-a.left,a.bottom-a.top);i.outerRadius=Math.max((s-l.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),n.outerRadius=i.outerRadius-i.radiusLength*n.index,n.innerRadius=n.outerRadius-i.radiusLength,o.count=n.countVisibleElements(),e.each(o.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){for(var a=this,o=a.chart,r=a.getDataset(),l=o.options,s=l.animation,u=o.scale,d=e.getValueAtIndexOrDefault,c=o.data.labels,h=a.calculateCircumference(r.data[n]),f=u.xCenter,g=u.yCenter,p=0,m=a.getMeta(),v=0;v<n;++v)isNaN(r.data[v])||m.data[v].hidden||++p;var b=l.startAngle,x=t.hidden?0:u.getDistanceFromCenterForValue(r.data[n]),y=b+h*p,k=y+(t.hidden?0:h),w=s.animateScale?0:u.getDistanceFromCenterForValue(r.data[n]);e.extend(t,{_datasetIndex:a.index,_index:n,_scale:u,_model:{x:f,y:g,innerRadius:0,outerRadius:i?w:x,startAngle:i&&s.animateRotate?b:y,endAngle:i&&s.animateRotate?b:k,label:d(c,n,c[n])}}),a.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),n=this.getMeta(),i=0;return e.each(n.data,function(e,n){isNaN(t.data[n])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={aspectRatio:1,scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,update:function(t){var n=this,i=n.getMeta(),a=i.dataset,o=i.data,r=a.custom||{},l=n.getDataset(),s=n.chart.options.elements.line,u=n.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),e.extend(i.dataset,{_datasetIndex:n.index,_scale:u,_children:o,_loop:!0,_model:{tension:r.tension?r.tension:e.getValueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),i.dataset.pivot(),e.each(o,function(e,i){n.updateElement(e,i,t)},n),n.updateBezierControlPoints()},updateElement:function(t,n,i){var a=this,o=t.custom||{},r=a.getDataset(),l=a.chart.scale,s=a.chart.options.elements.point,u=l.getPointPositionForValue(n,r.data[n]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),e.extend(t,{_datasetIndex:a.index,_index:n,_scale:l,_model:{x:i?l.xCenter:u.x,y:i?l.yCenter:u.y,tension:o.tension?o.tension:e.getValueOrDefault(r.lineTension,a.chart.options.elements.line.tension),radius:o.radius?o.radius:e.getValueAtIndexOrDefault(r.pointRadius,n,s.radius),backgroundColor:o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(r.pointBackgroundColor,n,s.backgroundColor),borderColor:o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(r.pointBorderColor,n,s.borderColor),borderWidth:o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(r.pointBorderWidth,n,s.borderWidth),pointStyle:o.pointStyle?o.pointStyle:e.getValueAtIndexOrDefault(r.pointStyle,n,s.pointStyle),hitRadius:o.hitRadius?o.hitRadius:e.getValueAtIndexOrDefault(r.pointHitRadius,n,s.hitRadius)}}),t._model.skip=o.skip?o.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,n=this.getMeta();e.each(n.data,function(i,a){var o=i._model,r=e.splineCurve(e.previousItem(n.data,a,!0)._model,o,e.nextItem(n.data,a,!0)._model,o.tension);o.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),o.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),o.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),o.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,o=t._model;o.radius=i.hoverRadius?i.hoverRadius:e.getValueAtIndexOrDefault(n.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),o.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.pointHoverBackgroundColor,a,e.getHoverColor(o.backgroundColor)),o.borderColor=i.hoverBorderColor?i.hoverBorderColor:e.getValueAtIndexOrDefault(n.pointHoverBorderColor,a,e.getHoverColor(o.borderColor)),o.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:e.getValueAtIndexOrDefault(n.pointHoverBorderWidth,a,o.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,o=t._model,r=this.chart.options.elements.point;o.radius=i.radius?i.radius:e.getValueAtIndexOrDefault(n.pointRadius,a,r.radius),o.backgroundColor=i.backgroundColor?i.backgroundColor:e.getValueAtIndexOrDefault(n.pointBackgroundColor,a,r.backgroundColor),o.borderColor=i.borderColor?i.borderColor:e.getValueAtIndexOrDefault(n.pointBorderColor,a,r.borderColor),o.borderWidth=i.borderWidth?i.borderWidth:e.getValueAtIndexOrDefault(n.pointBorderWidth,a,r.borderWidth)}})}},{}],21:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var n=e.findIndex(this.animations,function(e){return e.chart===t});-1!==n&&(this.animations.splice(n,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var n,i,a=this.animations,o=0;o<a.length;)n=a[o],i=n.chart,n.currentStep=(n.currentStep||0)+t,n.currentStep=Math.min(n.currentStep,n.numSteps),e.callback(n.render,[i,n],i),e.callback(n.onAnimationProgress,[n],i),n.currentStep>=n.numSteps?(e.callback(n.onAnimationComplete,[n],i),i.animating=!1,a.splice(o,1)):++o}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{}],22:[function(t,e,n){"use strict";e.exports=function(t){var e=t.canvasHelpers={};e.drawPoint=function(e,n,i,a,o){var r,l,s,u,d,c;if("object"!=typeof n||"[object HTMLImageElement]"!==(r=n.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(i)||i<=0)){switch(n){default:e.beginPath(),e.arc(a,o,i,0,2*Math.PI),e.closePath(),e.fill();break;case"triangle":e.beginPath(),d=(l=3*i/Math.sqrt(3))*Math.sqrt(3)/2,e.moveTo(a-l/2,o+d/3),e.lineTo(a+l/2,o+d/3),e.lineTo(a,o-2*d/3),e.closePath(),e.fill();break;case"rect":c=1/Math.SQRT2*i,e.beginPath(),e.fillRect(a-c,o-c,2*c,2*c),e.strokeRect(a-c,o-c,2*c,2*c);break;case"rectRounded":var h=i/Math.SQRT2,f=a-h,g=o-h,p=Math.SQRT2*i;t.helpers.drawRoundedRectangle(e,f,g,p,p,i/2),e.fill();break;case"rectRot":c=1/Math.SQRT2*i,e.beginPath(),e.moveTo(a-c,o),e.lineTo(a,o+c),e.lineTo(a+c,o),e.lineTo(a,o-c),e.closePath(),e.fill();break;case"cross":e.beginPath(),e.moveTo(a,o+i),e.lineTo(a,o-i),e.moveTo(a-i,o),e.lineTo(a+i,o),e.closePath();break;case"crossRot":e.beginPath(),s=Math.cos(Math.PI/4)*i,u=Math.sin(Math.PI/4)*i,e.moveTo(a-s,o-u),e.lineTo(a+s,o+u),e.moveTo(a-s,o+u),e.lineTo(a+s,o-u),e.closePath();break;case"star":e.beginPath(),e.moveTo(a,o+i),e.lineTo(a,o-i),e.moveTo(a-i,o),e.lineTo(a+i,o),s=Math.cos(Math.PI/4)*i,u=Math.sin(Math.PI/4)*i,e.moveTo(a-s,o-u),e.lineTo(a+s,o+u),e.moveTo(a-s,o+u),e.lineTo(a+s,o-u),e.closePath();break;case"line":e.beginPath(),e.moveTo(a-i,o),e.lineTo(a+i,o),e.closePath();break;case"dash":e.beginPath(),e.moveTo(a,o),e.lineTo(a+i,o),e.closePath()}e.stroke()}}else e.drawImage(n,a-n.width/2,o-n.height/2,n.width,n.height)},e.clipArea=function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},e.unclipArea=function(t){t.restore()},e.lineTo=function(t,e,n,i){return n.steppedLine?("after"===n.steppedLine?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y)):n.tension?void t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):void t.lineTo(n.x,n.y)},t.helpers.canvas=e}},{}],23:[function(t,e,n){"use strict";e.exports=function(t){function e(t){return"top"===t||"bottom"===t}var n=t.helpers,i=t.plugins,a=t.platform;t.types={},t.instances={},t.controllers={},n.extend(t.prototype,{construct:function(e,i){var o=this;i=function(e){var i=(e=e||{}).data=e.data||{};return i.datasets=i.datasets||[],i.labels=i.labels||[],e.options=n.configMerge(t.defaults.global,t.defaults[e.type],e.options||{}),e}(i);var r=a.acquireContext(e,i),l=r&&r.canvas,s=l&&l.height,u=l&&l.width;return o.id=n.uid(),o.ctx=r,o.canvas=l,o.config=i,o.width=u,o.height=s,o.aspectRatio=s?u/s:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),r&&l?(o.initialize(),void o.update()):void console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return i.notify(t,"beforeInit"),n.retinaScale(t),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),i.notify(t,"afterInit"),t},clear:function(){return n.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,a=e.options,o=e.canvas,r=a.maintainAspectRatio&&e.aspectRatio||null,l=Math.floor(n.getMaximumWidth(o)),s=Math.floor(r?l/r:n.getMaximumHeight(o));if((e.width!==l||e.height!==s)&&(o.width=e.width=l,o.height=e.height=s,o.style.width=l+"px",o.style.height=s+"px",n.retinaScale(e),!t)){var u={width:l,height:s};i.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},i=t.scale;n.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),n.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildScales:function(){var i=this,a=i.options,o=i.scales={},r=[];a.scales&&(r=r.concat((a.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(a.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),a.scale&&r.push({options:a.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),n.each(r,function(a){var r=a.options,l=n.getValueOrDefault(r.type,a.dtype),s=t.scaleService.getScaleConstructor(l);if(s){e(r.position)!==e(a.dposition)&&(r.position=a.dposition);var u=new s({id:r.id,options:r,ctx:i.ctx,chart:i});o[u.id]=u,a.isDefault&&(i.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,i=[],a=[];if(n.each(e.data.datasets,function(n,o){var r=e.getDatasetMeta(o);if(r.type||(r.type=n.type||e.config.type),i.push(r.type),r.controller)r.controller.updateIndex(o);else{var l=t.controllers[r.type];if(void 0===l)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new l(e,o),a.push(r.controller)}},e),i.length>1)for(var o=1;o<i.length;o++)if(i[o]!==i[o-1]){e.isCombo=!0;break}return a},resetElements:function(){var t=this;n.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t,e){var a=this;if(function(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}(a),!1!==i.notify(a,"beforeUpdate")){a.tooltip._data=a.data;var o=a.buildOrUpdateControllers();n.each(a.data.datasets,function(t,e){a.getDatasetMeta(e).controller.buildOrUpdateElements()},a),a.updateLayout(),n.each(o,function(t){t.reset()}),a.updateDatasets(),i.notify(a,"afterUpdate"),a._bufferedRender?a._bufferedRequest={lazy:e,duration:t}:a.render(t,e)}},updateLayout:function(){var e=this;!1!==i.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),i.notify(e,"afterScaleUpdate"),i.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==i.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);i.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),a={meta:n,index:t};!1!==i.notify(e,"beforeDatasetUpdate",[a])&&(n.controller.update(),i.notify(e,"afterDatasetUpdate",[a]))},render:function(e,a){var o=this;if(!1!==i.notify(o,"beforeRender")){var r=o.options.animation,l=function(t){i.notify(o,"afterRender"),n.callback(r&&r.onComplete,[t],o)};if(r&&(void 0!==e&&0!==e||void 0===e&&0!==r.duration)){var s=new t.Animation({numSteps:(e||r.duration)/16.66,easing:r.easing,render:function(t,e){var i=n.easingEffects[e.easing],a=e.currentStep,o=a/e.numSteps;t.draw(i(o),o,a)},onAnimationProgress:r.onProgress,onAnimationComplete:l});t.animationService.addAnimation(o,s,e,a)}else o.draw(),l(new t.Animation({numSteps:0,chart:o}));return o}},draw:function(t){var e=this;e.clear(),void 0!==t&&null!==t||(t=1),e.transition(t),!1!==i.notify(e,"beforeDraw",[t])&&(n.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),i.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==i.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);i.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,a=n.getDatasetMeta(t),o={meta:a,index:t,easingValue:e};!1!==i.notify(n,"beforeDatasetDraw",[o])&&(a.controller.draw(e),i.notify(n,"afterDatasetDraw",[o]))},getElementAtEvent:function(e){return t.Interaction.modes.single(this,e)},getElementsAtEvent:function(e){return t.Interaction.modes.label(this,e,{intersect:!0})},getElementsAtXAxis:function(e){return t.Interaction.modes["x-axis"](this,e,{intersect:!0})},getElementsAtEventForMode:function(e,n,i){var a=t.Interaction.modes[n];return"function"==typeof a?a(this,e,i):[]},getDatasetAtEvent:function(e){return t.Interaction.modes.dataset(this,e,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){var e,o,r,l=this,s=l.canvas;for(l.stop(),o=0,r=l.data.datasets.length;o<r;++o)(e=l.getDatasetMeta(o)).controller&&(e.controller.destroy(),e.controller=null);s&&(l.unbindEvents(),n.clear(l),a.releaseContext(l.ctx),l.canvas=null,l.ctx=null),i.notify(l,"destroy"),delete t.instances[l.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e),e.tooltip.initialize()},bindEvents:function(){var t=this,e=t._listeners={},i=function(){t.eventHandler.apply(t,arguments)};n.each(t.options.events,function(n){a.addEventListener(t,n,i),e[n]=i}),t.options.responsive&&(i=function(){t.resize()},a.addEventListener(t,"resize",i),e.resize=i)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,n.each(e,function(e,n){a.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,o,r=n?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==i.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var a=e.handleEvent(t);a|=n&&n.handleEvent(t),i.notify(e,"afterEvent",[t]);var o=e._bufferedRequest;return o?e.render(o.duration,o.lazy):a&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,i=e.options||{},a=i.hover,o=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,a.mode,a),a.onHover&&a.onHover.call(e,t.native,e.active),"mouseup"!==t.type&&"click"!==t.type||i.onClick&&i.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,a.mode,!1),e.active.length&&a.mode&&e.updateHoverStyle(e.active,a.mode,!0),o=!n.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,o}}),t.Controller=t}},{}],24:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t._chartjs?void t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),void a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),o}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,o=i.indexOf(e);-1!==o&&i.splice(o,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var i=t.helpers,a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.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(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;t<e;++t)o[t]=o[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=i.getValueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=i.getValueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,n,r(l.backgroundColor)),l.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,n,r(l.borderColor)),l.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,n,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{}],25:[function(t,e,n){"use strict";var i=t(3);e.exports=function(t){function e(t,e,n,a){var o,r,l,s,u,d,c,h,f,g=Object.keys(n);for(o=0,r=g.length;o<r;++o)if(l=g[o],d=n[l],e.hasOwnProperty(l)||(e[l]=d),(s=e[l])!==d&&"_"!==l[0]){if(t.hasOwnProperty(l)||(t[l]=s),u=t[l],(c=typeof d)===typeof u)if("string"===c){if((h=i(u)).valid&&(f=i(d)).valid){e[l]=f.mix(h,a).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[l]=u+(d-u)*a;continue}e[l]=d}}var n=t.helpers;t.elements={},t.Element=function(t){n.extend(this,t),this.initialize.apply(this,arguments)},n.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=n.clone(t._model)),t._start={},t},transition:function(t){var n=this,i=n._model,a=n._start,o=n._view;return i&&1!==t?(o||(o=n._view={}),a||(a=n._start={}),e(a,o,i,t),n):(n._view=i,n._start=null,n)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return n.isNumber(this._model.x)&&n.isNumber(this._model.y)}}),t.Element.extend=n.inherits}},{3:3}],26:[function(t,e,n){"use strict";var i=t(3);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function a(t,i,a){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],u=n(l),d=n(s),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(l,t,a):c,d?e(s,r,a):c):"none"}var o=t.helpers={};o.each=function(t,e,n,i){var a,r;if(o.isArray(t))if(r=t.length,i)for(a=r-1;a>=0;a--)e.call(n,t[a],a);else for(a=0;a<r;a++)e.call(n,t[a],a);else if("object"==typeof t){var l=Object.keys(t);for(r=l.length,a=0;a<r;a++)e.call(n,t[l[a]],l[a])}},o.clone=function(t){var e={};return o.each(t,function(t,n){o.isArray(t)?e[n]=t.slice(0):e[n]="object"==typeof t&&null!==t?o.clone(t):t}),e},o.extend=function(t){for(var e=function(e,n){t[n]=e},n=1,i=arguments.length;n<i;n++)o.each(arguments[n],e);return t},o.configMerge=function(e){var n=o.clone(e);return o.each(Array.prototype.slice.call(arguments,1),function(e){o.each(e,function(e,i){var a=n.hasOwnProperty(i),r=a?n[i]:{};"scales"===i?n[i]=o.scaleMerge(r,e):"scale"===i?n[i]=o.configMerge(r,t.scaleService.getScaleDefaults(e.type),e):!a||"object"!=typeof r||o.isArray(r)||null===r||"object"!=typeof e||o.isArray(e)?n[i]=e:n[i]=o.configMerge(r,e)})}),n},o.scaleMerge=function(e,n){var i=o.clone(e);return o.each(n,function(e,n){"xAxes"===n||"yAxes"===n?i.hasOwnProperty(n)?o.each(e,function(e,a){var r=o.getValueOrDefault(e.type,"xAxes"===n?"category":"linear"),l=t.scaleService.getScaleDefaults(r);a>=i[n].length||!i[n][a].type?i[n].push(o.configMerge(l,e)):e.type&&e.type!==i[n][a].type?i[n][a]=o.configMerge(i[n][a],l,e):i[n][a]=o.configMerge(i[n][a],e)}):(i[n]=[],o.each(e,function(e){var a=o.getValueOrDefault(e.type,"xAxes"===n?"category":"linear");i[n].push(o.configMerge(t.scaleService.getScaleDefaults(a),e))})):i.hasOwnProperty(n)&&"object"==typeof i[n]&&null!==i[n]&&"object"==typeof e?i[n]=o.configMerge(i[n],e):i[n]=e}),i},o.getValueAtIndexOrDefault=function(t,e,n){return void 0===t||null===t?n:o.isArray(t)?e<t.length?t[e]:n:t},o.getValueOrDefault=function(t,e){return void 0===t?e:t},o.indexOf=Array.prototype.indexOf?function(t,e){return t.indexOf(e)}:function(t,e){for(var n=0,i=t.length;n<i;++n)if(t[n]===e)return n;return-1},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,n){void 0!==n&&null!==n||(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},o.findPreviousWhere=function(t,e,n){void 0!==n&&null!==n||(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},o.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=o.inherits,t&&o.extend(n.prototype,t),n.__super__=e.prototype,n},o.noop=function(){},o.uid=function(){var t=0;return function(){return t++}}(),o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)<n},o.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e<l;++e)if(!(i=r[e]).model.skip){if(n=e>0?r[e-1]:null,(a=e<l-1?r[e+1]:null)&&!a.model.skip){var s=a.model.x-i.model.x;i.deltaK=0!==s?(a.model.y-i.model.y)/s:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<l-1;++e)i=r[e],a=r[e+1],i.model.skip||a.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<l;++e)(i=r[e]).model.skip||(n=e>0?r[e-1]:null,a=e<l-1?r[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},o.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)};var r=o.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--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){return(t/=.5)<1?.5*t*t*t:.5*((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){return(t/=.5)<1?.5*t*t*t*t:-.5*((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){return(t/=.5)<1?.5*t*t*t*t*t:.5*((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-.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(1-Math.pow(2,-10*t/1))},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1==(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1==(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.3*1.5*1),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t*1:t<2/2.75?1*(7.5625*(t-=1.5/2.75)*t+.75):t<2.5/2.75?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return t<.5?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.addEvent=function(t,e,n){t.addEventListener?t.addEventListener(e,n):t.attachEvent?t.attachEvent("on"+e,n):t["on"+e]=n},o.removeEvent=function(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent?t.detachEvent("on"+e,n):t["on"+e]=o.noop},o.getConstraintWidth=function(t){return a(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return a(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode,n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode,n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t){var e=t.currentDevicePixelRatio=window.devicePixelRatio||1;if(1!==e){var n=t.canvas,i=t.height,a=t.width;n.height=i*e,n.width=a*e,t.ctx.scale(e,e),n.style.height=i+"px",n.style.width=a+"px"}},o.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;u<s;u++)delete a[r[u]];r.splice(0,s)}return l},o.measureText=function(t,e,n,i,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,n.push(a)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.drawRoundedRectangle=function(t,e,n,i,a,o){t.beginPath(),t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+o),t.lineTo(e+i,n+a-o),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-o),t.lineTo(e,n+o),t.quadraticCurveTo(e,n,e+o,n),t.closePath()},o.color=i?function(e){return e instanceof CanvasGradient&&(e=t.defaults.global.defaultColor),i(e)}:function(t){return console.error("Color.js not found!"),t},o.isArray=Array.isArray?function(t){return Array.isArray(t)}:function(t){return"[object Array]"===Object.prototype.toString.call(t)},o.arrayEquals=function(t,e){var n,i,a,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,i=t.length;n<i;++n)if(a=t[n],r=e[n],a instanceof Array&&r instanceof Array){if(!o.arrayEquals(a,r))return!1}else if(a!==r)return!1;return!0},o.callback=function(t,e,n){t&&"function"==typeof t.call&&t.apply(n,e)},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()},o.callCallback=o.callback}},{3:3}],27:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t.native?{x:t.x,y:t.y}:r.getRelativePosition(t,e)}function n(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i<o;++i)if(t.isDatasetVisible(i))for(n=t.getDatasetMeta(i),a=0,r=n.data.length;a<r;++a){var l=n.data[a];l._view.skip||e(l)}}function i(t,e){var i=[];return n(t,function(t){t.inRange(e.x,e.y)&&i.push(t)}),i}function a(t,e,i,a){var o=Number.POSITIVE_INFINITY,l=[];return a||(a=r.distanceBetweenPoints),n(t,function(t){if(!i||t.inRange(e.x,e.y)){var n=t.getCenterPoint(),r=a(e,n);r<o?(l=[t],o=r):r===o&&l.push(t)}}),l}function o(t,n,o){var r=e(n,t),l=o.intersect?i(t,r):a(t,r,!1,function(t,e){return Math.abs(t.x-e.x)}),s=[];return l.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[l[0]._index];i&&!i._view.skip&&s.push(i)}}),s):[]}var r=t.helpers;t.Interaction={modes:{single:function(t,i){var a=e(i,t),o=[];return n(t,function(t){if(t.inRange(a.x,a.y))return o.push(t),o}),o.slice(0,1)},label:o,index:o,dataset:function(t,n,o){var r=e(n,t),l=o.intersect?i(t,r):a(t,r,!1);return l.length>0&&(l=t.getDatasetMeta(l[0]._datasetIndex).data),l},"x-axis":function(t,e){return o(t,e,!0)},point:function(t,n){return i(t,e(n,t))},nearest:function(t,n,i){var o=a(t,e(n,t),i.intersect);return o.length>1&&o.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),o.slice(0,1)},x:function(t,i,a){var o=e(i,t),r=[],l=!1;return n(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),a.intersect&&!l&&(r=[]),r},y:function(t,i,a){var o=e(i,t),r=[],l=!1;return n(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),a.intersect&&!l&&(r=[]),r}}}}},{}],28:[function(t,e,n){"use strict";e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,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:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t.Chart=t,t}},{}],29:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}var i=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)i=a[r],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,o){function r(t){var e=i.findNextWhere(D,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(T,I),right:Math.max(F,A),top:0,bottom:0};t.update(t.fullWidth?x:S,y/2,n)}else t.update(e.minSize.width,C)}function l(t){t.isHorizontal()?(t.left=t.fullWidth?d:T,t.right=t.fullWidth?a-c:T+S,t.top=N,t.bottom=N+t.height,N=t.bottom):(t.left=W,t.right=W+t.width,t.top=R,t.bottom=R+C,W=t.right)}if(t){var s=t.options.layout,u=s?s.padding:null,d=0,c=0,h=0,f=0;isNaN(u)?(d=u.left||0,c=u.right||0,h=u.top||0,f=u.bottom||0):(d=u,c=u,h=u,f=u);var g=e(t.boxes,"left"),p=e(t.boxes,"right"),m=e(t.boxes,"top"),v=e(t.boxes,"bottom"),b=e(t.boxes,"chartArea");n(g,!0),n(p,!1),n(m,!0),n(v,!1);var x=a-d-c,y=o-h-f,k=y/2,w=(a-x/2)/(g.length+p.length),M=(o-k)/(m.length+v.length),S=x,C=y,D=[];i.each(g.concat(p,m,v),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?x:S,M),C-=e.height):(e=t.update(w,k),S-=e.width),D.push({horizontal:n,minSize:e,box:t})});var I=0,A=0,P=0,_=0;i.each(m.concat(v),function(t){if(t.getPadding){var e=t.getPadding();I=Math.max(I,e.left),A=Math.max(A,e.right)}}),i.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();P=Math.max(P,e.top),_=Math.max(_,e.bottom)}});var T=d,F=c,R=h,L=f;i.each(g.concat(p),r),i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(m.concat(v),r),i.each(m,function(t){R+=t.height}),i.each(v,function(t){L+=t.height}),i.each(g.concat(p),function(t){var e=i.findNextWhere(D,function(e){return e.box===t}),n={left:0,right:0,top:R,bottom:L};e&&t.update(e.minSize.width,C,n)}),T=d,F=c,R=h,L=f,i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(m,function(t){R+=t.height}),i.each(v,function(t){L+=t.height});var V=Math.max(I-T,0);T+=V,F+=Math.max(A-F,0);var O=Math.max(P-R,0);R+=O,L+=Math.max(_-L,0);var z=o-R-L,B=a-T-F;B===S&&z===C||(i.each(g,function(t){t.height=z}),i.each(p,function(t){t.height=z}),i.each(m,function(t){t.fullWidth||(t.width=B)}),i.each(v,function(t){t.fullWidth||(t.width=B)}),C=z,S=B);var W=d+V,N=h+O;i.each(g.concat(m),l),W+=S,N+=C,i.each(p,l),i.each(v,l),t.chartArea={left:T,top:R,right:T+S,bottom:R+C},i.each(b,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(S,C)})}}}}},{}],30:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.plugins={},t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,o,r,l,s=this.descriptors(t),u=s.length;for(i=0;i<u;++i)if(a=s[i],o=a.plugin,"function"==typeof(l=o[e])&&((r=[t].concat(n||[])).push(a.options),!1===l.apply(o,r)))return!1;return!0},descriptors:function(n){var i=n._plugins||(n._plugins={});if(i.id===this._cacheId)return i.descriptors;var a=[],o=[],r=n&&n.config||{},l=t.defaults.global.plugins,s=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===a.indexOf(t)){var n=t.id,i=s[n];!1!==i&&(!0===i&&(i=e.clone(l[n])),a.push(t),o.push({plugin:t,options:i||{}}))}}),i.descriptors=o,i.id=this._cacheId,o}},t.pluginService=t.plugins,t.PluginBase=t.Element.extend({})}},{}],31:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e,n){return i.isArray(e)?i.longestText(t,n,e):t.measureText(e).width}function n(e){var n=i.getValueOrDefault,a=t.defaults.global,o=n(e.fontSize,a.defaultFontSize),r=n(e.fontStyle,a.defaultFontStyle),l=n(e.fontFamily,a.defaultFontFamily);return{size:o,style:r,family:l,font:i.fontString(o,r,l)}}var i=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:t.Ticks.formatters.values}},t.Scale=t.Element.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},beforeUpdate:function(){i.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var a=this;return a.beforeUpdate(),a.maxWidth=t,a.maxHeight=e,a.margins=i.extend({left:0,right:0,top:0,bottom:0},n),a.longestTextCache=a.longestTextCache||{},a.beforeSetDimensions(),a.setDimensions(),a.afterSetDimensions(),a.beforeDataLimits(),a.determineDataLimits(),a.afterDataLimits(),a.beforeBuildTicks(),a.buildTicks(),a.afterBuildTicks(),a.beforeTickToLabelConversion(),a.convertTicksToLabels(),a.afterTickToLabelConversion(),a.beforeCalculateTickRotation(),a.calculateTickRotation(),a.afterCalculateTickRotation(),a.beforeFit(),a.fit(),a.afterFit(),a.afterUpdate(),a.minSize},afterUpdate:function(){i.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){i.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){i.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){i.callback(this.options.beforeDataLimits,[this])},determineDataLimits:i.noop,afterDataLimits:function(){i.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){i.callback(this.options.beforeBuildTicks,[this])},buildTicks:i.noop,afterBuildTicks:function(){i.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){i.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback)},afterTickToLabelConversion:function(){i.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){i.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,o=n(a);e.font=o.font;var r=a.minRotation||0;if(t.options.display&&t.isHorizontal())for(var l,s=i.longestText(e,o.font,t.ticks,t.longestTextCache),u=s,d=t.getPixelForTick(1)-t.getPixelForTick(0)-6;u>d&&r<a.maxRotation;){var c=i.toRadians(r);if(l=Math.cos(c),Math.sin(c)*s>t.maxHeight){r--;break}r++,u=l*s}t.labelRotation=r},afterCalculateTickRotation:function(){i.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){i.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=t.options,r=o.ticks,l=o.scaleLabel,s=o.gridLines,u=o.display,d=t.isHorizontal(),c=n(r),h=1.5*n(l).size,f=o.gridLines.tickMarkLength;if(a.width=d?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:u&&s.drawTicks?f:0,a.height=d?u&&s.drawTicks?f:0:t.maxHeight,l.display&&u&&(d?a.height+=h:a.width+=h),r.display&&u){var g=i.longestText(t.ctx,c.font,t.ticks,t.longestTextCache),p=i.numberOfLabelLines(t.ticks),m=.5*c.size;if(d){t.longestLabelWidth=g;var v=i.toRadians(t.labelRotation),b=Math.cos(v),x=Math.sin(v)*g+c.size*p+m*p;a.height=Math.min(t.maxHeight,a.height+x),t.ctx.font=c.font;var y=t.ticks[0],k=e(t.ctx,y,c.font),w=t.ticks[t.ticks.length-1],M=e(t.ctx,w,c.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?b*k+3:b*m+3,t.paddingRight="bottom"===o.position?b*m+3:b*M+3):(t.paddingLeft=k/2+3,t.paddingRight=M/2+3)}else r.mirror?g=0:g+=t.options.ticks.padding,a.width=Math.min(t.maxWidth,a.width+g),t.paddingTop=c.size/2,t.paddingBottom=c.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){i.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){return null===t||void 0===t?NaN:"number"!=typeof t||isFinite(t)?"object"==typeof t?t instanceof Date||t.isValid?t:this.getRightValue(this.isHorizontal()?t.x:t.y):t:NaN},getLabelForIndex:i.noop,getPixelForValue:i.noop,getValueForPixel:i.noop,getPixelForTick:function(t,e){var n=this;if(n.isHorizontal()){var i=(n.width-(n.paddingLeft+n.paddingRight))/Math.max(n.ticks.length-(n.options.gridLines.offsetGridLines?0:1),1),a=i*t+n.paddingLeft;e&&(a+=i/2);var o=n.left+Math.round(a);return o+=n.isFullWidth()?n.margins.left:0}var r=n.height-(n.paddingTop+n.paddingBottom);return n.top+t*(r/(n.ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},draw:function(e){var a=this,o=a.options;if(o.display){var r,l,s=a.ctx,u=t.defaults.global,d=o.ticks,c=o.gridLines,h=o.scaleLabel,f=0!==a.labelRotation,g=d.autoSkip,p=a.isHorizontal();d.maxTicksLimit&&(l=d.maxTicksLimit);var m=i.getValueOrDefault(d.fontColor,u.defaultFontColor),v=n(d),b=c.drawTicks?c.tickMarkLength:0,x=i.getValueOrDefault(h.fontColor,u.defaultFontColor),y=n(h),k=i.toRadians(a.labelRotation),w=Math.cos(k),M=a.longestLabelWidth*w;s.fillStyle=m;var S=[];if(p){if(r=!1,(M+d.autoSkipPadding)*a.ticks.length>a.width-(a.paddingLeft+a.paddingRight)&&(r=1+Math.floor((M+d.autoSkipPadding)*a.ticks.length/(a.width-(a.paddingLeft+a.paddingRight)))),l&&a.ticks.length>l)for(;!r||a.ticks.length/(r||1)>l;)r||(r=1),r+=1;g||(r=!1)}var C="right"===o.position?a.left:a.right-b,D="right"===o.position?a.left+b:a.right,I="bottom"===o.position?a.top:a.bottom-b,A="bottom"===o.position?a.top+b:a.bottom;if(i.each(a.ticks,function(t,n){if(void 0!==t&&null!==t){var l=a.ticks.length===n+1;if((!(r>1&&n%r>0||n%r==0&&n+r>=a.ticks.length)||l)&&void 0!==t&&null!==t){var s,h,g,m;n===(void 0!==a.zeroLineIndex?a.zeroLineIndex:0)?(s=c.zeroLineWidth,h=c.zeroLineColor,g=c.zeroLineBorderDash,m=c.zeroLineBorderDashOffset):(s=i.getValueAtIndexOrDefault(c.lineWidth,n),h=i.getValueAtIndexOrDefault(c.color,n),g=i.getValueOrDefault(c.borderDash,u.borderDash),m=i.getValueOrDefault(c.borderDashOffset,u.borderDashOffset));var v,x,y,w,M,P,_,T,F,R,L="middle",V="middle";if(p){"bottom"===o.position?(V=f?"middle":"top",L=f?"right":"center",R=a.top+b):(V=f?"middle":"bottom",L=f?"left":"center",R=a.bottom-b);var O=a.getPixelForTick(n)+i.aliasPixel(s);F=a.getPixelForTick(n,c.offsetGridLines)+d.labelOffset,v=y=M=_=O,x=I,w=A,P=e.top,T=e.bottom}else{var z,B="left"===o.position,W=d.padding;d.mirror?(L=B?"left":"right",z=W):(L=B?"right":"left",z=b+W),F=B?a.right-z:a.left+z;var N=a.getPixelForTick(n);N+=i.aliasPixel(s),R=a.getPixelForTick(n,c.offsetGridLines),v=C,y=D,M=e.left,_=e.right,x=w=P=T=N}S.push({tx1:v,ty1:x,tx2:y,ty2:w,x1:M,y1:P,x2:_,y2:T,labelX:F,labelY:R,glWidth:s,glColor:h,glBorderDash:g,glBorderDashOffset:m,rotation:-1*k,label:t,textBaseline:V,textAlign:L})}}}),i.each(S,function(t){if(c.display&&(s.save(),s.lineWidth=t.glWidth,s.strokeStyle=t.glColor,s.setLineDash&&(s.setLineDash(t.glBorderDash),s.lineDashOffset=t.glBorderDashOffset),s.beginPath(),c.drawTicks&&(s.moveTo(t.tx1,t.ty1),s.lineTo(t.tx2,t.ty2)),c.drawOnChartArea&&(s.moveTo(t.x1,t.y1),s.lineTo(t.x2,t.y2)),s.stroke(),s.restore()),d.display){s.save(),s.translate(t.labelX,t.labelY),s.rotate(t.rotation),s.font=v.font,s.textBaseline=t.textBaseline,s.textAlign=t.textAlign;var e=t.label;if(i.isArray(e))for(var n=0,a=0;n<e.length;++n)s.fillText(""+e[n],0,a),a+=1.5*v.size;else s.fillText(e,0,0);s.restore()}}),h.display){var P,_,T=0;if(p)P=a.left+(a.right-a.left)/2,_="bottom"===o.position?a.bottom-y.size/2:a.top+y.size/2;else{var F="left"===o.position;P=F?a.left+y.size/2:a.right-y.size/2,_=a.top+(a.bottom-a.top)/2,T=F?-.5*Math.PI:.5*Math.PI}s.save(),s.translate(P,_),s.rotate(T),s.textAlign="center",s.textBaseline="middle",s.fillStyle=x,s.font=y.font,s.fillText(h.labelString,0,0),s.restore()}if(c.drawBorder){s.lineWidth=i.getValueAtIndexOrDefault(c.lineWidth,0),s.strokeStyle=i.getValueAtIndexOrDefault(c.color,0);var R=a.left,L=a.right,V=a.top,O=a.bottom,z=i.aliasPixel(s.lineWidth);p?(V=O="top"===o.position?a.bottom:a.top,V+=z,O+=z):(R=L="left"===o.position?a.right:a.left,R+=z,L+=z),s.beginPath(),s.moveTo(R,V),s.lineTo(L,O),s.stroke()}}}})}},{}],32:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,n,i){this.constructors[t]=n,this.defaults[t]=e.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(n){return this.defaults.hasOwnProperty(n)?e.scaleMerge(t.defaults.scale,this.defaults[n]):{}},updateScaleDefaults:function(t,n){var i=this.defaults;i.hasOwnProperty(t)&&(i[t]=e.extend(i[t],n))},addScalesToLayout:function(n){e.each(n.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,t.layoutService.addBox(n,e)})}}}},{}],33:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.Ticks={generators:{linear:function(t,n){var i,a=[];if(t.stepSize&&t.stepSize>0)i=t.stepSize;else{var o=e.niceNum(n.max-n.min,!1);i=e.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(n.min/i)*i,l=Math.ceil(n.max/i)*i;t.min&&t.max&&t.stepSize&&e.almostWhole((t.max-t.min)/t.stepSize,i/1e3)&&(r=t.min,l=t.max);var s=(l-r)/i;s=e.almostEquals(s,Math.round(s),i/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u<s;++u)a.push(r+u*i);return a.push(void 0!==t.max?t.max:l),a},logarithmic:function(t,n){var i,a,o=[],r=e.getValueOrDefault,l=r(t.min,Math.pow(10,Math.floor(e.log10(n.min)))),s=Math.floor(e.log10(n.max)),u=Math.ceil(n.max/Math.pow(10,s));0===l?(i=Math.floor(e.log10(n.minNotZero)),a=Math.floor(n.minNotZero/Math.pow(10,i)),o.push(l),l=a*Math.pow(10,i)):(i=Math.floor(e.log10(l)),a=Math.floor(l/Math.pow(10,i)));do{o.push(l),10===++a&&(a=1,++i),l=a*Math.pow(10,i)}while(i<s||i===s&&a<u);var d=r(t.max,l);return o.push(d),o}},formatters:{values:function(t){return e.isArray(t)?t:""+t},linear:function(t,n,i){var a=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=e.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,n,i){var a=t/Math.pow(10,Math.floor(e.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===n||n===i.length-1?t.toExponential():""}}}}},{}],34:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){var n=o.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function i(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function a(e){var n=t.defaults.global,i=o.getValueOrDefault;return{xPadding:e.xPadding,yPadding:e.yPadding,xAlign:e.xAlign,yAlign:e.yAlign,bodyFontColor:e.bodyFontColor,_bodyFontFamily:i(e.bodyFontFamily,n.defaultFontFamily),_bodyFontStyle:i(e.bodyFontStyle,n.defaultFontStyle),_bodyAlign:e.bodyAlign,bodyFontSize:i(e.bodyFontSize,n.defaultFontSize),bodySpacing:e.bodySpacing,titleFontColor:e.titleFontColor,_titleFontFamily:i(e.titleFontFamily,n.defaultFontFamily),_titleFontStyle:i(e.titleFontStyle,n.defaultFontStyle),titleFontSize:i(e.titleFontSize,n.defaultFontSize),_titleAlign:e.titleAlign,titleSpacing:e.titleSpacing,titleMarginBottom:e.titleMarginBottom,footerFontColor:e.footerFontColor,_footerFontFamily:i(e.footerFontFamily,n.defaultFontFamily),_footerFontStyle:i(e.footerFontStyle,n.defaultFontStyle),footerFontSize:i(e.footerFontSize,n.defaultFontSize),_footerAlign:e.footerAlign,footerSpacing:e.footerSpacing,footerMarginTop:e.footerMarginTop,caretSize:e.caretSize,cornerRadius:e.cornerRadius,backgroundColor:e.backgroundColor,opacity:0,legendColorBackground:e.multiKeyBackground,displayColors:e.displayColors,borderColor:e.borderColor,borderWidth:e.borderWidth}}var o=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,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,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.index<a&&(n=i[o.index])}return n},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}},t.Tooltip=t.Element.extend({initialize:function(){this._model=a(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,r,l=this,s=l._options,u=l._model,d=l._model=a(s),c=l._active,h=l._data,f={xAlign:u.xAlign,yAlign:u.yAlign},g={x:u.x,y:u.y},p={width:u.width,height:u.height},m={x:u.caretX,y:u.caretY};if(c.length){d.opacity=1;var v=[];m=t.Tooltip.positioners[s.position](c,l._eventPosition);var b=[];for(n=0,r=c.length;n<r;++n)b.push(i(c[n]));s.filter&&(b=b.filter(function(t){return s.filter(t,h)})),s.itemSort&&(b=b.sort(function(t,e){return s.itemSort(t,e,h)})),o.each(b,function(t){v.push(s.callbacks.labelColor.call(l,t,l._chart))}),d.title=l.getTitle(b,h),d.beforeBody=l.getBeforeBody(b,h),d.body=l.getBody(b,h),d.afterBody=l.getAfterBody(b,h),d.footer=l.getFooter(b,h),d.x=Math.round(m.x),d.y=Math.round(m.y),d.caretPadding=s.caretPadding,d.labelColors=v,d.dataPoints=b,p=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,l=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);l+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=s*d,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=l*c,i+=l?(l-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),n.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,n.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}(this,d),g=function(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}(d,p,f=function(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,o="center",r="center";n.y<e.height?r="top":n.y>i.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}(this,p))}else d.opacity=0;return d.xAlign=f.xAlign,d.yAlign=f.yAlign,d.x=g.x,d.y=g.y,d.width=p.width,d.height=p.height,d.caretX=m.x,d.caretY=m.y,l._model=d,e&&s.custom&&s.custom.call(l,d),l},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,o,r,l,s,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===h)l=g+m/2,"left"===c?(i=f,a=i-u,o=i,r=l+u,s=l-u):(i=f+p,a=i+u,o=i,r=l-u,s=l+u);else if("left"===c?(a=f+d+u,i=a-u,o=a+u):"right"===c?(a=f+p-d-u,i=a-u,o=a+u):(a=f+p/2,i=a-u,o=a+u),"top"===h)r=g,l=r-u,s=r;else{l=(r=g+m)+u,s=r;var v=o;o=i,i=v}return{x1:i,x2:a,x3:o,y1:r,y2:l,y3:s}},drawTitle:function(t,n,i,a){var r=n.title;if(r.length){i.textAlign=n._titleAlign,i.textBaseline="top";var l=n.titleFontSize,s=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=o.fontString(l,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=r.length;u<d;++u)i.fillText(r[u],t.x,t.y),t.y+=l+s,u+1===r.length&&(t.y+=n.titleMarginBottom-s)}},drawBody:function(t,n,i,a){var r=n.bodyFontSize,l=n.bodySpacing,s=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top";var u=e(n.bodyFontColor,a);i.fillStyle=u,i.font=o.fontString(r,n._bodyFontStyle,n._bodyFontFamily);var d=0,c=function(e){i.fillText(e,t.x+d,t.y),t.y+=r+l};o.each(n.beforeBody,c);var h=n.displayColors;d=h?r+2:0,o.each(s,function(l,s){o.each(l.before,c),o.each(l.lines,function(o){h&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,r,r),i.strokeStyle=e(n.labelColors[s].borderColor,a),i.strokeRect(t.x,t.y,r,r),i.fillStyle=e(n.labelColors[s].backgroundColor,a),i.fillRect(t.x+1,t.y+1,r-2,r-2),i.fillStyle=u),c(o)}),o.each(l.after,c)}),d=0,o.each(n.afterBody,c),t.y-=l},drawFooter:function(t,n,i,a){var r=n.footer;r.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=o.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),o.each(r,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,o){i.fillStyle=e(n.backgroundColor,o),i.strokeStyle=e(n.borderColor,o),i.lineWidth=n.borderWidth;var r=n.xAlign,l=n.yAlign,s=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(s+h,u),"top"===l&&this.drawCaret(t,a),i.lineTo(s+d-h,u),i.quadraticCurveTo(s+d,u,s+d,u+h),"center"===l&&"right"===r&&this.drawCaret(t,a),i.lineTo(s+d,u+c-h),i.quadraticCurveTo(s+d,u+c,s+d-h,u+c),"bottom"===l&&this.drawCaret(t,a),i.lineTo(s+h,u+c),i.quadraticCurveTo(s,u+c,s,u+c-h),"center"===l&&"left"===r&&this.drawCaret(t,a),i.lineTo(s,u+h),i.quadraticCurveTo(s,u,s+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;e<n;++e){var r=t[e];if(r&&r.hasValue()){var l=r.tooltipPosition();i+=l.x,a+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(a/o)}},nearest:function(t,e){var n,i,a,r=e.x,l=e.y,s=Number.POSITIVE_INFINITY;for(i=0,a=t.length;i<a;++i){var u=t[i];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<s&&(s=c,n=u)}}if(n){var h=n.tooltipPosition();r=h.x,l=h.y}return{x:r,y:l}}}}},{}],35:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global;n.elements.arc={backgroundColor:n.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,n){var i=this._view;if(i){for(var a=e.getAngleFromPoint(i,{x:t,y:n}),o=a.angle,r=a.distance,l=i.startAngle,s=i.endAngle;s<l;)s+=2*Math.PI;for(;o>s;)o-=2*Math.PI;for(;o<l;)o+=2*Math.PI;var u=o>=l&&o<=s,d=r>=i.innerRadius&&r<=i.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],36:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:n.defaultColor,borderWidth:3,borderColor:n.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0},t.elements.Line=t.Element.extend({draw:function(){var t,i,a,o,r=this,l=r._view,s=r._chart.ctx,u=l.spanGaps,d=r._children.slice(),c=n.elements.line,h=-1;for(r._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||n.defaultColor,s.beginPath(),h=-1,t=0;t<d.length;++t)i=d[t],a=e.previousItem(d,t),o=i._view,0===t?o.skip||(s.moveTo(o.x,o.y),h=t):(a=-1===h?a:d[h],o.skip||(h!==t-1&&!u||-1===h?s.moveTo(o.x,o.y):e.canvas.lineTo(s,a._view,i._view),h=t));s.stroke(),s.restore()}})}},{}],37:[function(t,e,n){"use strict";e.exports=function(t){function e(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var n=t.helpers,i=t.defaults.global,a=i.defaultColor;i.elements.point={radius:3,pointStyle:"circle",backgroundColor:a,borderWidth:1,borderColor:a,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:e,inXRange:e,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(e){var o=this._view,r=this._model,l=this._chart.ctx,s=o.pointStyle,u=o.radius,d=o.x,c=o.y,h=t.helpers.color,f=1.01,g=0;o.skip||(l.strokeStyle=o.borderColor||a,l.lineWidth=n.getValueOrDefault(o.borderWidth,i.elements.point.borderWidth),l.fillStyle=o.backgroundColor||a,void 0!==e&&(r.x<e.left||e.right*f<r.x||r.y<e.top||e.bottom*f<r.y)&&(r.x<e.left?g=(d-r.x)/(e.left-r.x):e.right*f<r.x?g=(r.x-d)/(r.x-e.right):r.y<e.top?g=(c-r.y)/(e.top-r.y):e.bottom*f<r.y&&(g=(r.y-c)/(r.y-e.bottom)),g=Math.round(100*g)/100,l.strokeStyle=h(l.strokeStyle).alpha(g).rgbString(),l.fillStyle=h(l.fillStyle).alpha(g).rgbString()),t.canvasHelpers.drawPoint(l,s,u,d,c))}})}},{}],38:[function(t,e,n){"use strict";e.exports=function(t){function e(t){return void 0!==t._view.width}function n(t){var n,i,a,o,r=t._view;if(e(t)){var l=r.width/2;n=r.x-l,i=r.x+l,a=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;n=Math.min(r.x,r.base),i=Math.max(r.x,r.base),a=r.y-s,o=r.y+s}return{left:n,top:a,right:i,bottom:o}}var i=t.defaults.global;i.elements.rectangle={backgroundColor:i.defaultColor,borderWidth:0,borderColor:i.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return v[(b+t)%4]}var e,n,i,a,o,r,l,s=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,o=n>e?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,a=u.base,o=1,r=a>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),m=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=m),p!==m&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=!1;if(this._view){var a=n(this);i=t>=a.left&&t<=a.right&&e>=a.top&&e<=a.bottom}return i},inLabelRange:function(t,i){var a=this;if(!a._view)return!1;var o=n(a);return e(a)?t>=o.left&&t<=o.right:i>=o.top&&i<=o.bottom},inXRange:function(t){var e=n(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=n(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,n,i=this._view;return e(this)?(t=i.x,n=(i.y+i.base)/2):(t=(i.x+i.base)/2,n=i.y),{x:t,y:n}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],39:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){var n=r.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function n(t,n){var i=t.style,a=t.getAttribute("height"),o=t.getAttribute("width");if(t._chartjs={initial:{height:a,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",null===o||""===o){var r=e(t,"width");void 0!==r&&(t.width=r)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(n.options.aspectRatio||2);else{var l=e(t,"height");void 0!==r&&(t.height=l)}return t}function i(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function a(t,e){var n=l[t.type]||t.type,a=r.getRelativePosition(t,e);return i(n,e,a.x,a.y,t)}function o(t,e,n){var a=t._chartjs={ticking:!1};a.resizer=function(t){var e=document.createElement("iframe");return e.className="chartjs-hidden-iframe",e.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;",e.tabIndex=-1,r.addEvent(e,"load",function(){r.addEvent(e.contentWindow||e,"resize",t),t()}),e}(function(){a.ticking||(a.ticking=!0,r.requestAnimFrame.call(window,function(){if(a.resizer)return a.ticking=!1,e(i("resize",n))}))}),t.insertBefore(a.resizer,t.firstChild)}var r=t.helpers,l={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};return{acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(n(t,e),i):null},releaseContext:function(t){var e=t.canvas;if(e._chartjs){var n=e._chartjs.initial;["height","width"].forEach(function(t){var i=n[t];void 0===i||null===i?e.removeAttribute(t):e.setAttribute(t,i)}),r.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e._chartjs}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var l=n._chartjs||(n._chartjs={}),s=(l.proxies||(l.proxies={}))[t.id+"_"+e]=function(e){n(a(e,t))};r.addEvent(i,e,s)}else o(i.parentNode,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n._chartjs||{}).proxies||{})[t.id+"_"+e];a&&r.removeEvent(i,e,a)}else!function(t){if(t&&t._chartjs){var e=t._chartjs.resizer;e&&(e.parentNode.removeChild(e),t._chartjs.resizer=null),delete t._chartjs}}(i.parentNode)}}}},{}],40:[function(t,e,n){"use strict";var i=t(39);e.exports=function(t){t.platform={acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},t.helpers.extend(t.platform,i(t))}},{39:39}],41:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function n(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function i(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function a(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function o(t){return t&&!t.skip}function r(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)u.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)u.canvas.lineTo(t,n[o],n[o-1],!0)}}function l(t,e,n,i,a,l){var s,u,d,c,h,f,g,p=e.length,m=i.spanGaps,v=[],b=[],x=0,y=0;for(t.beginPath(),s=0,u=p+!!l;s<u;++s)d=s%p,c=e[d]._view,h=n(c,d,i),f=o(c),g=o(h),f&&g?(x=v.push(c),y=b.push(h)):x&&y&&(m?(f&&v.push(c),g&&b.push(h)):(r(t,v,b,x,y),x=y=0,v=[],b=[]));r(t,v,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}t.defaults.global.plugins.filler={propagate:!0};var s=t.defaults,u=t.helpers,d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[];return a.length?function(t,e){return a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(o,r){var l,s,u,d,c=(o.data.datasets||[]).length,h=r.propagate,f=[];for(s=0;s<c;++s)l=o.getDatasetMeta(s),u=l.dataset,d=null,u&&u._model&&u instanceof t.elements.Line&&(d={visible:o.isDatasetVisible(s),fill:e(u,s,c),chart:o,el:u}),l.$filler=d,f.push(d);for(s=0;s<c;++s)(d=f[s])&&(d.fill=i(f,s,h),d.boundary=n(d),d.mapper=a(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var i=n.el,a=i._view,o=i._children||[],r=n.mapper,u=a.backgroundColor||s.global.defaultColor;r&&u&&o.length&&l(t.ctx,o,r,a,u,i._loop)}}}}},{}],42:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});a.configure(e,i,n),a.addBox(e,i),e.legend=i}var i=t.helpers,a=t.layoutService,o=i.noop;return t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return i.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:i.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){i.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:function(){var t=this,e=t.options.labels,n=e.generateLabels.call(t,t.chart);e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:o,beforeFit:o,fit:function(){var n=this,a=n.options,o=a.labels,r=a.display,l=n.ctx,s=t.defaults.global,u=i.getValueOrDefault,d=u(o.fontSize,s.defaultFontSize),c=u(o.fontStyle,s.defaultFontStyle),h=u(o.fontFamily,s.defaultFontFamily),f=i.fontString(d,c,h),g=n.legendHitBoxes=[],p=n.minSize,m=n.isHorizontal();if(m?(p.width=n.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=n.maxHeight),r)if(l.font=f,m){var v=n.lineWidths=[0],b=n.legendItems.length?d+o.padding:0;l.textAlign="left",l.textBaseline="top",i.each(n.legendItems,function(t,i){var a=e(o,d)+d/2+l.measureText(t.text).width;v[v.length-1]+a+o.padding>=n.width&&(b+=d+o.padding,v[v.length]=n.left),g[i]={left:0,top:0,width:a,height:d},v[v.length-1]+=a+o.padding}),p.height+=b}else{var x=o.padding,y=n.columnWidths=[],k=o.padding,w=0,M=0,S=d+x;i.each(n.legendItems,function(t,n){var i=e(o,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+o.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}n.width=p.width,n.height=p.height},afterFit:o,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var n=this,a=n.options,o=a.labels,r=t.defaults.global,l=r.elements.line,s=n.width,u=n.lineWidths;if(a.display){var d,c=n.ctx,h=i.getValueOrDefault,f=h(o.fontColor,r.defaultFontColor),g=h(o.fontSize,r.defaultFontSize),p=h(o.fontStyle,r.defaultFontStyle),m=h(o.fontFamily,r.defaultFontFamily),v=i.fontString(g,p,m);c.textAlign="left",c.textBaseline="top",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var b=e(o,g),x=n.legendHitBoxes,y=function(e,n,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var o=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),a.labels&&a.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=e+u,f=n+u;t.canvasHelpers.drawPoint(c,i.pointStyle,s,d,f)}else o||c.strokeRect(e,n,b,g),c.fillRect(e,n,b,g);c.restore()}},k=n.isHorizontal();d=k?{x:n.left+(s-u[0])/2,y:n.top+o.padding,line:0}:{x:n.left+o.padding,y:n.top+o.padding,line:0};var w=g+o.padding;i.each(n.legendItems,function(t,e){var i=c.measureText(t.text).width,a=b+g/2+i,r=d.x,l=d.y;k?r+a>=s&&(l=d.y+=w,d.line++,r=d.x=n.left+(s-u[d.line])/2):l+w>n.bottom&&(r=d.x=r+n.columnWidths[d.line]+o.padding,l=d.y=n.top+o.padding,d.line++),y(r,l,t),x[e].left=r,x[e].top=l,function(t,e,n,i){c.fillText(n.text,b+g/2+t,e),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(b+g/2+t,e+g/2),c.lineTo(b+g/2+t+i,e+g/2),c.stroke())}(r,l,t,i),k?d.x+=a+o.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s<l.length;++s){var u=l[s];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(e){var o=e.options.legend,r=e.legend;o?(o=i.configMerge(t.defaults.global.legend,o),r?(a.configure(e,r,o),r.options=o):n(e,o)):r&&(a.removeBox(e,r),delete e.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{}],43:[function(t,e,n){"use strict";e.exports=function(t){function e(e,n){var a=new t.Title({ctx:e.ctx,options:n,chart:e});i.configure(e,a,n),i.addBox(e,a),e.titleBlock=a}var n=t.helpers,i=t.layoutService,a=n.noop;return t.defaults.global.title={display:!1,position:"top",fullWidth:!0,weight:2e3,fontStyle:"bold",padding:10,text:""},t.Title=t.Element.extend({initialize:function(t){n.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:a,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:a,beforeSetDimensions:a,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:a,beforeBuildLabels:a,buildLabels:a,afterBuildLabels:a,beforeFit:a,fit:function(){var e=this,i=n.getValueOrDefault,a=e.options,o=t.defaults.global,r=a.display,l=i(a.fontSize,o.defaultFontSize),s=e.minSize;e.isHorizontal()?(s.width=e.maxWidth,s.height=r?l+2*a.padding:0):(s.width=r?l+2*a.padding:0,s.height=e.maxHeight),e.width=s.width,e.height=s.height},afterFit:a,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var e=this,i=e.ctx,a=n.getValueOrDefault,o=e.options,r=t.defaults.global;if(o.display){var l,s,u,d=a(o.fontSize,r.defaultFontSize),c=a(o.fontStyle,r.defaultFontStyle),h=a(o.fontFamily,r.defaultFontFamily),f=n.fontString(d,c,h),g=0,p=e.top,m=e.left,v=e.bottom,b=e.right;i.fillStyle=a(o.fontColor,r.defaultFontColor),i.font=f,e.isHorizontal()?(l=m+(b-m)/2,s=p+(v-p)/2,u=b-m):(l="left"===o.position?m+d/2:b-d/2,s=p+(v-p)/2,u=v-p,g=Math.PI*("left"===o.position?-.5:.5)),i.save(),i.translate(l,s),i.rotate(g),i.textAlign="center",i.textBaseline="middle",i.fillText(o.text,0,0,u),i.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,r=a.titleBlock;o?(o=n.configMerge(t.defaults.global.title,o),r?(i.configure(a,r,o),r.options=o):e(a,o)):r&&(t.layoutService.removeBox(a,r),delete a.titleBlock)}}}},{}],44:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,n=t.getLabels();t.minIndex=0,t.maxIndex=n.length-1;var i;void 0!==t.options.ticks.min&&(i=e.indexOf(n,t.options.ticks.min),t.minIndex=-1!==i?i:t.minIndex),void 0!==t.options.ticks.max&&(i=e.indexOf(n,t.options.ticks.max),t.maxIndex=-1!==i?i:t.maxIndex),t.min=n[t.minIndex],t.max=n[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e,n,i){var a,o=this,r=Math.max(o.maxIndex+1-o.minIndex-(o.options.gridLines.offsetGridLines?0:1),1);if(void 0!==t&&null!==t&&(a=o.isHorizontal()?t.x:t.y),void 0!==a||void 0!==t&&isNaN(e)){var l=o.getLabels();t=a||t;var s=l.indexOf(t);e=-1!==s?s:e}if(o.isHorizontal()){var u=o.width/r,d=u*(e-o.minIndex);return(o.options.gridLines.offsetGridLines&&i||o.maxIndex===o.minIndex&&i)&&(d+=u/2),o.left+Math.round(d)}var c=o.height/r,h=c*(e-o.minIndex);return o.options.gridLines.offsetGridLines&&i&&(h+=c/2),o.top+Math.round(h)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e=this,n=Math.max(e.ticks.length-(e.options.gridLines.offsetGridLines?0:1),1),i=e.isHorizontal(),a=(i?e.width:e.height)/n;return t-=i?e.left:e.top,e.options.gridLines.offsetGridLines&&(t-=a/2),t<=0?0:Math.round(t/a)},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,{position:"bottom"})}},{}],45:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:t.Ticks.formatters.linear}},i=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return r?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=n.chart,o=a.data.datasets,r=n.isHorizontal();n.min=null,n.max=null;var l=i.stacked;if(void 0===l&&e.each(o,function(e,n){if(!l){var i=a.getDatasetMeta(n);a.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(l=!0)}}),i.stacked||l){var s={};e.each(o,function(o,r){var l=a.getDatasetMeta(r),u=[l.type,void 0===i.stacked&&void 0===l.stack?r:"",l.stack].join(".");void 0===s[u]&&(s[u]={positiveValues:[],negativeValues:[]});var d=s[u].positiveValues,c=s[u].negativeValues;a.isDatasetVisible(r)&&t(l)&&e.each(o.data,function(t,e){var a=+n.getRightValue(t);isNaN(a)||l.data[e].hidden||(d[e]=d[e]||0,c[e]=c[e]||0,i.relativePoints?d[e]=100:a<0?c[e]+=a:d[e]+=a)})}),e.each(s,function(t){var i=t.positiveValues.concat(t.negativeValues),a=e.min(i),o=e.max(i);n.min=null===n.min?a:Math.min(n.min,a),n.max=null===n.max?o:Math.max(n.max,o)})}else e.each(o,function(i,o){var r=a.getDatasetMeta(o);a.isDatasetVisible(o)&&t(r)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i))})});n.min=isFinite(n.min)?n.min:0,n.max=isFinite(n.max)?n.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var n,i=this,a=i.options.ticks;if(i.isHorizontal())n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.width/50));else{var o=e.getValueOrDefault(a.fontSize,t.defaults.global.defaultFontSize);n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.height/(2*o)))}return n},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",i,n)}},{}],46:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=e.noop;t.LinearScaleBase=t.Scale.extend({handleTickRangeOptions:function(){var t=this,n=t.options.ticks;if(n.beginAtZero){var i=e.sign(t.min),a=e.sign(t.max);i<0&&a<0?t.max=0:i>0&&a>0&&(t.min=0)}void 0!==n.min?t.min=n.min:void 0!==n.suggestedMin&&(null===t.min?t.min=n.suggestedMin:t.min=Math.min(t.min,n.suggestedMin)),void 0!==n.max?t.max=n.max:void 0!==n.suggestedMax&&(null===t.max?t.max=n.suggestedMax:t.max=Math.max(t.max,n.suggestedMax)),t.min===t.max&&(t.max++,n.beginAtZero||t.min--)},getTickLimit:n,handleDirectionalChanges:n,buildTicks:function(){var n=this,i=n.options.ticks,a=n.getTickLimit(),o={maxTicks:a=Math.max(2,a),min:i.min,max:i.max,stepSize:e.getValueOrDefault(i.fixedStepSize,i.stepSize)},r=n.ticks=t.Ticks.generators.linear(o,n);n.handleDirectionalChanges(),n.max=e.max(r),n.min=e.min(r),i.reverse?(r.reverse(),n.start=n.max,n.end=n.min):(n.start=n.min,n.end=n.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{}],47:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:t.Ticks.formatters.logarithmic}},i=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=i.ticks,o=n.chart,r=o.data.datasets,l=e.getValueOrDefault,s=n.isHorizontal();n.min=null,n.max=null,n.minNotZero=null;var u=i.stacked;if(void 0===u&&e.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),i.stacked||u){var d={};e.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===i.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),e.each(a.data,function(t,e){var a=d[s],o=+n.getRightValue(t);isNaN(o)||l.data[e].hidden||(a[e]=a[e]||0,i.relativePoints?a[e]=100:a[e]+=o)}))}),e.each(d,function(t){var i=e.min(t),a=e.max(t);n.min=null===n.min?i:Math.min(n.min,i),n.max=null===n.max?a:Math.max(n.max,a)})}else e.each(r,function(i,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i),0!==i&&(null===n.minNotZero||i<n.minNotZero)&&(n.minNotZero=i))})});n.min=l(a.min,n.min),n.max=l(a.max,n.max),n.min===n.max&&(0!==n.min&&null!==n.min?(n.min=Math.pow(10,Math.floor(e.log10(n.min))-1),n.max=Math.pow(10,Math.floor(e.log10(n.max))+1)):(n.min=1,n.max=10))},buildTicks:function(){var n=this,i=n.options.ticks,a={min:i.min,max:i.max},o=n.ticks=t.Ticks.generators.logarithmic(a,n);n.isHorizontal()||o.reverse(),n.max=e.max(o),n.min=e.min(o),i.reverse?(o.reverse(),n.start=n.max,n.end=n.min):(n.start=n.min,n.end=n.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var n,i,a,o=this,r=o.start,l=+o.getRightValue(t),s=o.options.ticks;return o.isHorizontal()?(a=e.log10(o.end)-e.log10(r),0===l?i=o.left:(n=o.width,i=o.left+n/a*(e.log10(l)-e.log10(r)))):(n=o.height,0!==r||s.reverse?0===o.end&&s.reverse?(a=e.log10(o.start)-e.log10(o.minNotZero),i=l===o.end?o.top:l===o.minNotZero?o.top+.02*n:o.top+.02*n+.98*n/a*(e.log10(l)-e.log10(o.minNotZero))):0===l?i=s.reverse?o.top:o.bottom:(a=e.log10(o.end)-e.log10(r),n=o.height,i=o.bottom-n/a*(e.log10(l)-e.log10(r))):(a=e.log10(o.end)-e.log10(o.minNotZero),i=l===r?o.bottom:l===o.minNotZero?o.bottom-.02*n:o.bottom-.02*n-.98*n/a*(e.log10(l)-e.log10(o.minNotZero)))),i},getValueForPixel:function(t){var n,i,a=this,o=e.log10(a.end)-e.log10(a.start);return a.isHorizontal()?(i=a.width,n=a.start*Math.pow(10,(t-a.left)*o/i)):(i=a.height,n=Math.pow(10,(a.bottom-t)*o/i)/a.start),n}});t.scaleService.registerScaleType("logarithmic",i,n)}},{}],48:[function(t,e,n){"use strict";e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=c.getValueOrDefault(e.fontSize,h.defaultFontSize),i=c.getValueOrDefault(e.fontStyle,h.defaultFontStyle),a=c.getValueOrDefault(e.fontFamily,h.defaultFontFamily);return{size:n,style:i,family:a,font:c.fontString(n,i,a)}}function i(t,e,n){return c.isArray(n)?{w:c.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function a(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function o(t){return 0===t||180===t?"center":t<180?"left":"right"}function r(t,e,n,i){if(c.isArray(e))for(var a=n.y,o=1.5*i,r=0;r<e.length;++r)t.fillText(e[r],n.x,a),a+=o;else t.fillText(e,n.x,n.y)}function l(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function s(t){var i=t.ctx,a=c.getValueOrDefault,s=t.options,u=s.angleLines,d=s.pointLabels;i.lineWidth=u.lineWidth,i.strokeStyle=u.color;var f=t.getDistanceFromCenterForValue(s.reverse?t.min:t.max),g=n(t);i.textBaseline="top";for(var p=e(t)-1;p>=0;p--){if(u.display){var m=t.getPointPosition(p,f);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(d.display){var v=t.getPointPosition(p,f+5),b=a(d.fontColor,h.defaultFontColor);i.font=g.font,i.fillStyle=b;var x=t.getIndexAngle(p),y=c.toDegrees(x);i.textAlign=o(y),l(y,t._pointLabelSizes[p],v),r(i,t.pointLabels[p]||"",v,g.size)}}}function u(t,n,i,a){var o=t.ctx;if(o.strokeStyle=c.getValueAtIndexOrDefault(n.color,a-1),o.lineWidth=c.getValueAtIndexOrDefault(n.lineWidth,a-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var r=e(t);if(0===r)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var s=1;s<r;s++)l=t.getPointPosition(s,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}function d(t){return c.isNumber(t)?t:0}var c=t.helpers,h=t.defaults.global,f={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:t.Ticks.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},g=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=c.min([t.height,t.width]),a=c.getValueOrDefault(n.fontSize,h.defaultFontSize);t.drawingArea=e.display?i/2-(a/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;c.each(e.data.datasets,function(a,o){if(e.isDatasetVisible(o)){var r=e.getDatasetMeta(o);c.each(a.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||r.data[a].hidden||(n=Math.min(o,n),i=Math.max(o,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=c.getValueOrDefault(t.fontSize,h.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?function(t){var o,r,l,s=n(t),u=Math.min(t.height/2,t.width/2),d={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=s.font,t._pointLabelSizes=[];var f=e(t);for(o=0;o<f;o++){l=t.getPointPosition(o,u),r=i(t.ctx,s.size,t.pointLabels[o]||""),t._pointLabelSizes[o]=r;var g=t.getIndexAngle(o),p=c.toDegrees(g)%360,m=a(p,l.x,r.w,0,180),v=a(p,l.y,r.h,90,270);m.start<d.l&&(d.l=m.start,h.l=g),m.end>d.r&&(d.r=m.end,h.r=g),v.start<d.t&&(d.t=v.start,h.t=g),v.end>d.b&&(d.b=v.end,h.b=g)}t.setReductions(u,d,h)}(this):function(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),o=Math.max(e.r-i.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),l=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=d(a),o=d(o),r=d(r),l=d(l),i.drawingArea=Math.min(Math.round(t-(a+o)/2),Math.round(t-(r+l)/2)),i.setCenterPoint(a,o,r,l)},setCenterPoint:function(t,e,n,i){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,l=n+a.drawingArea,s=a.height-i-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((l+s)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,a=c.getValueOrDefault;if(e.display){var o=t.ctx,r=a(i.fontSize,h.defaultFontSize),l=a(i.fontStyle,h.defaultFontStyle),d=a(i.fontFamily,h.defaultFontFamily),f=c.fontString(r,l,d);c.each(t.ticks,function(l,s){if(s>0||e.reverse){var d=t.getDistanceFromCenterForValue(t.ticksAsNumbers[s]),c=t.yCenter-d;if(n.display&&0!==s&&u(t,n,d,s),i.display){var g=a(i.fontColor,h.defaultFontColor);if(o.font=f,i.showLabelBackdrop){var p=o.measureText(l).width;o.fillStyle=i.backdropColor,o.fillRect(t.xCenter-p/2-i.backdropPaddingX,c-r/2-i.backdropPaddingY,p+2*i.backdropPaddingX,r+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=g,o.fillText(l,t.xCenter,c)}}}),(e.angleLines.display||e.pointLabels.display)&&s(t)}}});t.scaleService.registerScaleType("radialLinear",g,f)}},{}],49:[function(t,e,n){"use strict";var i=t(1);i="function"==typeof i?i:window.moment,e.exports=function(t){function e(t,e){var n=t.options.time;if("string"==typeof n.parser)return i(e,n.parser);if("function"==typeof n.parser)return n.parser(e);if("function"==typeof e.getMonth||"number"==typeof e)return i(e);if(e.isValid&&e.isValid())return e;var a=n.format;return"string"!=typeof a&&a.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser."),a(e)):i(e,a)}function n(t,e,n,i){for(var a,o=Object.keys(r),l=o.length,s=o.indexOf(t);s<l;s++){a=o[s];var u=r[a],d=u.steps&&u.steps[u.steps.length-1]||u.maxStep;if(void 0===d||Math.ceil((n-e)/(d*u.size))<=i)break}return a}function a(t,e,n,i){var a=r[n],o=a.size,l=Math.ceil((e-t)/o),s=1,u=e-t;if(a.steps)for(var d=a.steps.length,c=0;c<d&&l>i;c++)s=a.steps[c],l=Math.ceil(u/(o*s));else for(;l>i&&i>0;)++s,l=Math.ceil(u/(o*s));return s}var o=t.helpers,r={millisecond:{size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{size:1e3,steps:[1,2,5,10,30]},minute:{size:6e4,steps:[1,2,5,10,30]},hour:{size:36e5,steps:[1,2,3,6,12]},day:{size:864e5,steps:[1,2,5]},week:{size:6048e5,maxStep:4},month:{size:2628e6,maxStep:3},quarter:{size:7884e6,maxStep:4},year:{size:3154e7,maxStep:!1}};t.Ticks.generators.time=function(t,e){var n,a,o=t.isoWeekday;return"week"===t.unit&&!1!==o?(n=i(e.min).startOf("isoWeek").isoWeekday(o).valueOf(),a=i(e.max).startOf("isoWeek").isoWeekday(o),e.max-a>0&&a.add(1,"week"),a=a.valueOf()):(n=i(e.min).startOf(t.unit).valueOf(),a=i(e.max).startOf(t.unit),e.max-a>0&&a.add(1,t.unit),a=a.valueOf()),function(t,e,n){var a=[];if(t.maxTicks){var o=t.stepSize;a.push(void 0!==t.min?t.min:n.min);for(var r=i(n.min);r.add(o,t.unit).valueOf()<n.max;)a.push(r.valueOf());var l=t.max||n.max;a[a.length-1]!==l&&a.push(l)}return a}(t,0,{min:n,max:a})};var l=t.Scale.extend({initialize:function(){if(!i)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");t.Scale.prototype.initialize.call(this)},determineDataLimits:function(){var t,n=this,i=n.options.time,a=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,l=n.chart.data,s={labels:[],datasets:[]};o.each(l.labels,function(o,l){var u=e(n,o);u.isValid()&&(i.round&&u.startOf(i.round),t=u.valueOf(),a=Math.min(t,a),r=Math.max(t,r),s.labels[l]=t)}),o.each(l.datasets,function(l,u){var d=[];"object"==typeof l.data[0]&&null!==l.data[0]&&n.chart.isDatasetVisible(u)?o.each(l.data,function(o,l){var s=e(n,n.getRightValue(o));s.isValid()&&(i.round&&s.startOf(i.round),t=s.valueOf(),a=Math.min(t,a),r=Math.max(t,r),d[l]=t)}):d=s.labels.slice(),s.datasets[u]=d}),n.dataMin=a,n.dataMax=r,n._parsedData=s},buildTicks:function(){var i,r,l=this,s=l.options.time,u=l.dataMin,d=l.dataMax;if(s.min){var c=e(l,s.min);s.round&&c.round(s.round),i=c.valueOf()}s.max&&(r=e(l,s.max).valueOf());var h=l.getLabelCapacity(i||u),f=s.unit||n(s.minUnit,i||u,r||d,h);l.displayFormat=s.displayFormats[f];var g=s.stepSize||a(i||u,r||d,f,h);l.ticks=t.Ticks.generators.time({maxTicks:h,min:i,max:r,stepSize:g,unit:f,isoWeekday:s.isoWeekday},{min:u,max:d}),l.max=o.max(l.ticks),l.min=o.min(l.ticks)},getLabelForIndex:function(t,n){var i=this,a=i.chart.data.labels&&t<i.chart.data.labels.length?i.chart.data.labels[t]:"",o=i.chart.data.datasets[n].data[t];return null!==o&&"object"==typeof o&&(a=i.getRightValue(o)),i.options.time.tooltipFormat&&(a=e(i,a).format(i.options.time.tooltipFormat)),a},tickFormatFunction:function(t,e,n){var i=t.format(this.displayFormat),a=this.options.ticks,r=o.getValueOrDefault(a.callback,a.userCallback);return r?r(i,e,n):i},convertTicksToLabels:function(){var t=this;t.ticksAsTimestamps=t.ticks,t.ticks=t.ticks.map(function(t){return i(t)}).map(t.tickFormatFunction,t)},getPixelForOffset:function(t){var e=this,n=e.max-e.min,i=n?(t-e.min)/n:0;if(e.isHorizontal()){var a=e.width*i;return e.left+Math.round(a)}var o=e.height*i;return e.top+Math.round(o)},getPixelForValue:function(t,n,i){var a=this,o=null;if(void 0!==n&&void 0!==i&&(o=a._parsedData.datasets[i][n]),null===o&&(t&&t.isValid||(t=e(a,a.getRightValue(t))),t&&t.isValid&&t.isValid()&&(o=t.valueOf())),null!==o)return a.getPixelForOffset(o)},getPixelForTick:function(t){return this.getPixelForOffset(this.ticksAsTimestamps[t])},getValueForPixel:function(t){var e=this,n=e.isHorizontal()?e.width:e.height,a=(t-(e.isHorizontal()?e.left:e.top))/n;return i(e.min+a*(e.max-e.min))},getLabelWidth:function(e){var n=this.options.ticks,i=this.ctx.measureText(e).width,a=Math.cos(o.toRadians(n.maxRotation)),r=Math.sin(o.toRadians(n.maxRotation));return i*a+o.getValueOrDefault(n.fontSize,t.defaults.global.defaultFontSize)*r},getLabelCapacity:function(t){var e=this;e.displayFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(i(t),0,[]),a=e.getLabelWidth(n);return(e.isHorizontal()?e.width:e.height)/a}});t.scaleService.registerScaleType("time",l,{position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}})}},{1:1}]},{},[7])(7)});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/include.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/include.min.js
new file mode 100755
index 0000000..54ef4aa
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/include.min.js
@@ -0,0 +1 @@
+window.include=function(n,e,t){e.indexOf(".html")<0&&(e+=".html");var i=new XMLHttpRequest;i.onload=function(){if(4==this.readyState){var e=this.responseText,i="string"==typeof n?document.getElementById(n):n;console.log(i),i&&(i.innerHTML=e),t&&t()}},i.open("GET",e+"?cache="+(new Date).getTime(),!0),i.send()},window.bindIncludeEvent=function(){document.querySelectorAll("[include]").forEach(function(n,e){window.include(n,n.getAttribute("include"))})},window.bindIncludeEvent(),document.addEventListener("openPage",function(){window.bindIncludeEvent()});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/input.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/input.min.js
new file mode 100755
index 0000000..3e585b7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/input.min.js
@@ -0,0 +1 @@
+!function e(){setTimeout(function(){var t=document.getElementsByTagName("input");for(i in t){var a=t[i].parentNode;a&&(a.className.indexOf("left")>=0||a.className.indexOf("right")>=0)&&a.parentNode.className.indexOf("item")>=0&&(a=a.parentNode),a&&a.className.indexOf("item")>=0&&a.className.indexOf("bind-input-event-click")<0&&(a.className+=" bind-input-event-click",a.addEventListener("click",function(){this.getElementsByTagName("input").length&&(this.getElementsByTagName("input")[0].focus(),"radio"!==this.getElementsByTagName("input")[0].type||this.getElementsByTagName("input")[0].disabled||(this.getElementsByTagName("input")[0].checked=!0))},!1))}var l=document.getElementsByClassName("label-float");for(i in l)l[i].className&&l[i].className.indexOf("bind-input-event-focus")<0&&l[i].querySelectorAll("input,textarea").length&&(l[i].className+=" bind-input-event-focus",l[i].querySelectorAll("input,textarea")[0].addEventListener("focus",function(){this.parentNode.getElementsByTagName("label").length&&this.parentNode.getElementsByTagName("label")[0].className.indexOf("focus")<0&&(this.parentNode.getElementsByTagName("label")[0].className+=" focus")},!1),l[i].querySelectorAll("input,textarea")[0].addEventListener("blur",function(){this.parentNode.getElementsByTagName("label").length&&this.parentNode.getElementsByTagName("label")[0].className&&!this.value.length&&(this.parentNode.getElementsByTagName("label")[0].className=this.parentNode.getElementsByTagName("label")[0].className.replace("focus",""))},!1),l[i].querySelectorAll("input,textarea")[0].value&&l[i].querySelectorAll("input,textarea")[0].value.length&&(l[i].querySelectorAll("input,textarea")[0].parentNode.getElementsByTagName("label")[0].className+=" focus"));e()},500)}();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/jquery.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/jquery.min.js
new file mode 100755
index 0000000..6756324
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/jquery.min.js
@@ -0,0 +1 @@
+!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t)}(this,function(t){var e=function(){function e(t){return null==t?String(t):B[U.call(t)]||"object"}function n(t){return"function"==e(t)}function r(t){return null!=t&&t==t.window}function i(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function o(t){return"object"==e(t)}function a(t){return o(t)&&!r(t)&&Object.getPrototypeOf(t)==Object.prototype}function s(t){var e=!!t&&"length"in t&&t.length,n=j.type(t);return"function"!=n&&!r(t)&&("array"==n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function u(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function c(t){return t in L?L[t]:L[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function l(t,e){return"number"!=typeof e||$[u(t)]?e:e+"px"}function f(t){return"children"in t?P.call(t.children):j.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function h(t,e){var n,r=t?t.length:0;for(n=0;n<r;n++)this[n]=t[n];this.length=r,this.selector=e||""}function p(t,e,n){for(E in e)n&&(a(e[E])||Y(e[E]))?(a(e[E])&&!a(t[E])&&(t[E]={}),Y(e[E])&&!Y(t[E])&&(t[E]=[]),p(t[E],e[E],n)):e[E]!==b&&(t[E]=e[E])}function d(t,e){return null==e?j(t):j(t).filter(e)}function m(t,e,r,i){return n(e)?e.call(t,r,i):e}function v(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function g(t,e){var n=t.className||"",r=n&&n.baseVal!==b;if(e===b)return r?n.baseVal:n;r?n.baseVal=e:t.className=e}function y(t){try{return t?"true"==t||"false"!=t&&("null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?j.parseJSON(t):t):t}catch(e){return t}}function x(t,e){e(t);for(var n=0,r=t.childNodes.length;n<r;n++)x(t.childNodes[n],e)}var b,E,j,T,w,S,C=[],N=C.concat,O=C.filter,P=C.slice,A=t.document,D={},L={},$={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},F=/^\s*<(\w+|!)[^>]*>/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,M=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,R=/^(?:body|html)$/i,Z=/([A-Z])/g,z=["val","css","html","text","data","width","height","offset"],q=A.createElement("table"),H=A.createElement("tr"),I={tr:A.createElement("tbody"),tbody:q,thead:q,tfoot:q,td:H,th:H,"*":A.createElement("div")},V=/complete|loaded|interactive/,_=/^[\w-]*$/,B={},U=B.toString,X={},J=A.createElement("div"),W={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Y=Array.isArray||function(t){return t instanceof Array};return X.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=J).appendChild(t),r=~X.qsa(i,e).indexOf(t),o&&J.removeChild(t),r},w=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},S=function(t){return O.call(t,function(e,n){return t.indexOf(e)==n})},X.fragment=function(t,e,n){var r,i,o;return k.test(t)&&(r=j(A.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(M,"<$1></$2>")),e===b&&(e=F.test(t)&&RegExp.$1),e in I||(e="*"),(o=I[e]).innerHTML=""+t,r=j.each(P.call(o.childNodes),function(){o.removeChild(this)})),a(n)&&(i=j(r),j.each(n,function(t,e){z.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},X.Z=function(t,e){return new h(t,e)},X.isZ=function(t){return t instanceof X.Z},X.init=function(t,e){var r;if(!t)return X.Z();if("string"==typeof t)if("<"==(t=t.trim())[0]&&F.test(t))r=X.fragment(t,RegExp.$1,e),t=null;else{if(e!==b)return j(e).find(t);r=X.qsa(A,t)}else{if(n(t))return j(A).ready(t);if(X.isZ(t))return t;if(Y(t))r=function(t){return O.call(t,function(t){return null!=t})}(t);else if(o(t))r=[t],t=null;else if(F.test(t))r=X.fragment(t.trim(),RegExp.$1,e),t=null;else{if(e!==b)return j(e).find(t);r=X.qsa(A,t)}}return X.Z(r,t)},j=function(t,e){return X.init(t,e)},j.extend=function(t){var e,n=P.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){p(t,n,e)}),t},X.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,a=_.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:P.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},j.contains=A.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},j.type=e,j.isFunction=n,j.isWindow=r,j.isArray=Y,j.isPlainObject=a,j.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},j.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},j.inArray=function(t,e,n){return C.indexOf.call(e,t,n)},j.camelCase=w,j.trim=function(t){return null==t?"":String.prototype.trim.call(t)},j.uuid=0,j.support={},j.expr={},j.noop=function(){},j.map=function(t,e){var n,r,i,o=[];if(s(t))for(r=0;r<t.length;r++)null!=(n=e(t[r],r))&&o.push(n);else for(i in t)null!=(n=e(t[i],i))&&o.push(n);return function(t){return t.length>0?j.fn.concat.apply([],t):t}(o)},j.each=function(t,e){var n,r;if(s(t)){for(n=0;n<t.length;n++)if(!1===e.call(t[n],n,t[n]))return t}else for(r in t)if(!1===e.call(t[r],r,t[r]))return t;return t},j.grep=function(t,e){return O.call(t,e)},t.JSON&&(j.parseJSON=JSON.parse),j.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(t,e){B["[object "+e+"]"]=e.toLowerCase()}),j.fn={constructor:X.Z,length:0,forEach:C.forEach,reduce:C.reduce,push:C.push,sort:C.sort,splice:C.splice,indexOf:C.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=X.isZ(e)?e.toArray():e;return N.apply(X.isZ(this)?this.toArray():this,n)},map:function(t){return j(j.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return j(P.apply(this,arguments))},ready:function(t){return V.test(A.readyState)&&A.body?t(j):A.addEventListener("DOMContentLoaded",function(){t(j)},!1),this},get:function(t){return t===b?P.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return C.every.call(this,function(e,n){return!1!==t.call(e,n,e)}),this},filter:function(t){return n(t)?this.not(this.not(t)):j(O.call(this,function(e){return X.matches(e,t)}))},add:function(t,e){return j(S(this.concat(j(t,e))))},is:function(t){return this.length>0&&X.matches(this[0],t)},not:function(t){var e=[];if(n(t)&&t.call!==b)this.each(function(n){t.call(this,n)||e.push(this)});else{var r="string"==typeof t?this.filter(t):s(t)&&n(t.item)?P.call(t):j(t);this.forEach(function(t){r.indexOf(t)<0&&e.push(t)})}return j(e)},has:function(t){return this.filter(function(){return o(t)?j.contains(this,t):j(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!o(t)?t:j(t)},last:function(){var t=this[this.length-1];return t&&!o(t)?t:j(t)},find:function(t){var e=this;return t?"object"==typeof t?j(t).filter(function(){var t=this;return C.some.call(e,function(e){return j.contains(e,t)})}):1==this.length?j(X.qsa(this[0],t)):this.map(function(){return X.qsa(this,t)}):j()},closest:function(t,e){var n=[],r="object"==typeof t&&j(t);return this.each(function(o,a){for(;a&&!(r?r.indexOf(a)>=0:X.matches(a,t));)a=a!==e&&!i(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),j(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=j.map(n,function(t){if((t=t.parentNode)&&!i(t)&&e.indexOf(t)<0)return e.push(t),t});return d(e,t)},parent:function(t){return d(S(this.pluck("parentNode")),t)},children:function(t){return d(this.map(function(){return f(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||P.call(this.childNodes)})},siblings:function(t){return d(this.map(function(t,e){return O.call(f(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return j.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=function(t){var e,n;return D[t]||(e=A.createElement(t),A.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),D[t]=n),D[t]}(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=n(t);if(this[0]&&!e)var r=j(t).get(0),i=r.parentNode||this.length>1;return this.each(function(n){j(this).wrapAll(e?t.call(this,n):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){j(this[0]).before(t=j(t));for(var e;(e=t.children()).length;)t=e.first();j(t).append(this)}return this},wrapInner:function(t){var e=n(t);return this.each(function(n){var r=j(this),i=r.contents(),o=e?t.call(this,n):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){j(this).replaceWith(j(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=j(this);(t===b?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return j(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return j(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;j(this).empty().append(m(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=m(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(o(t))for(E in t)v(this,E,t[E]);else v(this,t,m(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:b},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){v(this,t)},this)})},prop:function(t,e){return t=W[t]||t,1 in arguments?this.each(function(n){this[t]=m(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=W[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n="data-"+t.replace(Z,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?y(r):b},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=m(this,t,e,this.value)})):this[0]&&(this[0].multiple?j(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each(function(t){var n=j(this),r=m(this,e,t,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(A.documentElement!==this[0]&&!j.contains(A.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,n){if(arguments.length<2){var r=this[0];if("string"==typeof t){if(!r)return;return r.style[w(t)]||getComputedStyle(r,"").getPropertyValue(t)}if(Y(t)){if(!r)return;var i={},o=getComputedStyle(r,"");return j.each(t,function(t,e){i[e]=r.style[w(e)]||o.getPropertyValue(e)}),i}}var a="";if("string"==e(t))n||0===n?a=u(t)+":"+l(t,n):this.each(function(){this.style.removeProperty(u(t))});else for(E in t)t[E]||0===t[E]?a+=u(E)+":"+l(E,t[E])+";":this.each(function(){this.style.removeProperty(u(E))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(j(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&C.some.call(this,function(t){return this.test(g(t))},c(t))},addClass:function(t){return t?this.each(function(e){if("className"in this){T=[];var n=g(this);m(this,t,e,n).split(/\s+/g).forEach(function(t){j(this).hasClass(t)||T.push(t)},this),T.length&&g(this,n+(n?" ":"")+T.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===b)return g(this,"");T=g(this),m(this,t,e,T).split(/\s+/g).forEach(function(t){T=T.replace(c(t)," ")}),g(this,T.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=j(this);m(this,t,n,g(this)).split(/\s+/g).forEach(function(t){(e===b?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===b?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===b?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=R.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(j(t).css("margin-top"))||0,n.left-=parseFloat(j(t).css("margin-left"))||0,r.top+=parseFloat(j(e[0]).css("border-top-width"))||0,r.left+=parseFloat(j(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||A.body;t&&!R.test(t.nodeName)&&"static"==j(t).css("position");)t=t.offsetParent;return t})}},j.fn.detach=j.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});j.fn[t]=function(n){var o,a=this[0];return n===b?r(a)?a["inner"+e]:i(a)?a.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){(a=j(this)).css(t,m(this,n,e,a[t]()))})}}),["after","prepend","before","append"].forEach(function(n,r){var i=r%2;j.fn[n]=function(){var n,o,a=j.map(arguments,function(t){var r=[];return"array"==(n=e(t))?(t.forEach(function(t){return t.nodeType!==b?r.push(t):j.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(X.fragment(t)))}),r):"object"==n||null==t?t:X.fragment(t)}),s=this.length>1;return a.length<1?this:this.each(function(e,n){o=i?n:n.parentNode,n=0==r?n.nextSibling:1==r?n.firstChild:2==r?n:null;var u=j.contains(A.documentElement,o);a.forEach(function(e){if(s)e=e.cloneNode(!0);else if(!o)return j(e).remove();o.insertBefore(e,n),u&&x(e,function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}})})})},j.fn[i?n+"To":"insert"+(r?"Before":"After")]=function(t){return j(t)[n](this),this}}),X.Z.prototype=h.prototype=j.fn,X.uniq=S,X.deserializeValue=y,j.zepto=X,j}();return t.Zepto=e,void 0===t.$&&(t.$=e),function(e){function n(t){return t._zid||(t._zid=h++)}function r(t,e,r,o){if((e=i(e)).ns)var a=function(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}(e.ns);return(v[n(t)]||[]).filter(function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||a.test(t.ns))&&(!r||n(t.fn)===n(r))&&(!o||t.sel==o)})}function i(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(t,r,s,u,l,h,p){var d=n(t),m=v[d]||(v[d]=[]);r.split(/\s/).forEach(function(n){if("ready"==n)return e(document).ready(s);var r=i(n);r.fn=s,r.sel=l,r.e in b&&(s=function(t){var n=t.relatedTarget;if(!n||n!==this&&!e.contains(this,n))return r.fn.apply(this,arguments)}),r.del=h;var d=h||s;r.proxy=function(e){if(!(e=c(e)).isImmediatePropagationStopped()){e.data=u;var n=d.apply(t,e._args==f?[e]:[e].concat(e._args));return!1===n&&(e.preventDefault(),e.stopPropagation()),n}},r.i=m.length,m.push(r),"addEventListener"in t&&t.addEventListener(a(r.e),r.proxy,o(r,p))})}function u(t,e,i,s,u){var c=n(t);(e||"").split(/\s/).forEach(function(e){r(t,e,i,s).forEach(function(e){delete v[c][e.i],"removeEventListener"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(t,n){return!n&&t.isDefaultPrevented||(n||(n=t),e.each(w,function(e,r){var i=n[e];t[e]=function(){return this[r]=E,i&&i.apply(n,arguments)},t[r]=j}),t.timeStamp||(t.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?!1===n.returnValue:n.getPreventDefault&&n.getPreventDefault())&&(t.isDefaultPrevented=E)),t}function l(t){var e,n={originalEvent:t};for(e in t)T.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=e.isFunction,m=function(t){return"string"==typeof t},v={},g={},y="onfocusin"in t,x={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};g.click=g.mousedown=g.mouseup=g.mousemove="MouseEvents",e.event={add:s,remove:u},e.proxy=function(t,r){var i=2 in arguments&&p.call(arguments,2);if(d(t)){var o=function(){return t.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=n(t),o}if(m(r))return i?(i.unshift(t[r],t),e.proxy.apply(null,i)):e.proxy(t[r],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var E=function(){return!0},j=function(){return!1},T=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,w={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,n,r,i,o){var a,c,h=this;return t&&!m(t)?(e.each(t,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||!1===i||(i=r,r=n,n=f),i!==f&&!1!==r||(i=r,r=f),!1===i&&(i=j),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(t){var r,o=e(t.target).closest(n,h).get(0);if(o&&o!==h)return r=e.extend(l(t),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,t,i,r,n,c||a)}))},e.fn.off=function(t,n,r){var i=this;return t&&!m(t)?(e.each(t,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||!1===r||(r=n,n=f),!1===r&&(r=j),i.each(function(){u(this,t,r,n)}))},e.fn.trigger=function(t,n){return t=m(t)||e.isPlainObject(t)?e.Event(t):c(t),t._args=n,this.each(function(){t.type in x&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)})},e.fn.triggerHandler=function(t,n){var i,o;return this.each(function(a,s){(i=l(m(t)?e.Event(t):t))._args=n,i.target=s,e.each(r(s,t.type||t),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}}),e.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(e){function n(t,n,r,i){if(t.global)return function(t,n,r){var i=e.Event(n);return e(t).trigger(i,r),!i.isDefaultPrevented()}(n||d,r,i)}function r(t,e){var r=e.context;if(!1===e.beforeSend.call(r,t,e)||!1===n(e,r,"ajaxBeforeSend",[t,e]))return!1;n(e,r,"ajaxSend",[t,e])}function i(t,e,r,i){var o=r.context;r.success.call(o,t,"success",e),i&&i.resolveWith(o,[t,"success",e]),n(r,o,"ajaxSuccess",[e,r,t]),a("success",e,r)}function o(t,e,r,i,o){var s=i.context;i.error.call(s,r,e,t),o&&o.rejectWith(s,[r,e,t]),n(i,s,"ajaxError",[r,i,t||e]),a(e,r,i)}function a(t,r,i){var o=i.context;i.complete.call(o,r,t),n(i,o,"ajaxComplete",[r,i]),function(t){t.global&&!--e.active&&n(t,null,"ajaxStop")}(i)}function s(){}function u(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function c(t,n,r,i){return e.isFunction(n)&&(i=r,r=n,n=void 0),e.isFunction(r)||(i=r,r=void 0),{url:t,data:n,success:r,dataType:i}}function l(t,n,r,i){var o,a=e.isArray(n),s=e.isPlainObject(n);e.each(n,function(n,u){o=e.type(u),i&&(n=r?i:i+"["+(s||"object"==o||"array"==o?n:"")+"]"),!i&&a?t.add(u.name,u.value):"array"==o||!r&&"object"==o?l(t,u,r,n):t.add(n,u)})}var f,h,p=+new Date,d=t.document,m=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,v=/^(?:text|application)\/javascript/i,g=/^(?:text|application)\/xml/i,y="application/json",x="text/html",b=/^\s*$/,E=d.createElement("a");E.href=t.location.href,e.active=0,e.ajaxJSONP=function(n,a){if(!("type"in n))return e.ajax(n);var s,u,c=n.jsonpCallback,l=(e.isFunction(c)?c():c)||"Zepto"+p++,f=d.createElement("script"),h=t[l],m=function(t){e(f).triggerHandler("error",t||"abort")},v={abort:m};return a&&a.promise(v),e(f).on("load error",function(r,c){clearTimeout(u),e(f).off().remove(),"error"!=r.type&&s?i(s[0],v,n,a):o(null,c||"error",v,n,a),t[l]=h,s&&e.isFunction(h)&&h(s[0]),h=s=void 0}),!1===r(v,n)?(m("abort"),v):(t[l]=function(){s=arguments},f.src=n.url.replace(/\?(.+)=\?/,"?$1="+l),d.head.appendChild(f),n.timeout>0&&(u=setTimeout(function(){m("timeout")},n.timeout)),v)},e.ajaxSettings={type:"GET",beforeSend:s,success:s,error:s,complete:s,context:null,global:!0,xhr:function(){return new t.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:y,xml:"application/xml, text/xml",html:x,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:s},e.ajax=function(a){var c,l,p=e.extend({},a||{}),m=e.Deferred&&e.Deferred();for(f in e.ajaxSettings)void 0===p[f]&&(p[f]=e.ajaxSettings[f]);!function(t){t.global&&0==e.active++&&n(t,null,"ajaxStart")}(p),p.crossDomain||((c=d.createElement("a")).href=p.url,c.href=c.href,p.crossDomain=E.protocol+"//"+E.host!=c.protocol+"//"+c.host),p.url||(p.url=t.location.toString()),(l=p.url.indexOf("#"))>-1&&(p.url=p.url.slice(0,l)),function(t){t.processData&&t.data&&"string"!=e.type(t.data)&&(t.data=e.param(t.data,t.traditional)),!t.data||t.type&&"GET"!=t.type.toUpperCase()&&"jsonp"!=t.dataType||(t.url=u(t.url,t.data),t.data=void 0)}(p);var j=p.dataType,T=/\?.+=\?/.test(p.url);if(T&&(j="jsonp"),!1!==p.cache&&(a&&!0===a.cache||"script"!=j&&"jsonp"!=j)||(p.url=u(p.url,"_="+Date.now())),"jsonp"==j)return T||(p.url=u(p.url,p.jsonp?p.jsonp+"=?":!1===p.jsonp?"":"callback=?")),e.ajaxJSONP(p,m);var w,S=p.accepts[j],C={},N=function(t,e){C[t.toLowerCase()]=[t,e]},O=/^([\w-]+:)\/\//.test(p.url)?RegExp.$1:t.location.protocol,P=p.xhr(),A=P.setRequestHeader;if(m&&m.promise(P),p.crossDomain||N("X-Requested-With","XMLHttpRequest"),N("Accept",S||"*/*"),(S=p.mimeType||S)&&(S.indexOf(",")>-1&&(S=S.split(",",2)[0]),P.overrideMimeType&&P.overrideMimeType(S)),(p.contentType||!1!==p.contentType&&p.data&&"GET"!=p.type.toUpperCase())&&N("Content-Type",p.contentType||"application/x-www-form-urlencoded"),p.headers)for(h in p.headers)N(h,p.headers[h]);if(P.setRequestHeader=N,P.onreadystatechange=function(){if(4==P.readyState){P.onreadystatechange=s,clearTimeout(w);var t,n=!1;if(P.status>=200&&P.status<300||304==P.status||0==P.status&&"file:"==O){if(j=j||function(t){return t&&(t=t.split(";",2)[0]),t&&(t==x?"html":t==y?"json":v.test(t)?"script":g.test(t)&&"xml")||"text"}(p.mimeType||P.getResponseHeader("content-type")),"arraybuffer"==P.responseType||"blob"==P.responseType)t=P.response;else{t=P.responseText;try{t=function(t,e,n){if(n.dataFilter==s)return t;var r=n.context;return n.dataFilter.call(r,t,e)}(t,j,p),"script"==j?(0,eval)(t):"xml"==j?t=P.responseXML:"json"==j&&(t=b.test(t)?null:e.parseJSON(t))}catch(t){n=t}if(n)return o(n,"parsererror",P,p,m)}i(t,P,p,m)}else o(P.statusText||null,P.status?"error":"abort",P,p,m)}},!1===r(P,p))return P.abort(),o(null,"abort",P,p,m),P;var D=!("async"in p)||p.async;if(P.open(p.type,p.url,D,p.username,p.password),p.xhrFields)for(h in p.xhrFields)P[h]=p.xhrFields[h];for(h in C)A.apply(P,C[h]);return p.timeout>0&&(w=setTimeout(function(){P.onreadystatechange=s,P.abort(),o(null,"timeout",P,p,m)},p.timeout)),P.send(p.data?p.data:null),P},e.get=function(){return e.ajax(c.apply(null,arguments))},e.post=function(){var t=c.apply(null,arguments);return t.type="POST",e.ajax(t)},e.getJSON=function(){var t=c.apply(null,arguments);return t.dataType="json",e.ajax(t)},e.fn.load=function(t,n,r){if(!this.length)return this;var i,o=this,a=t.split(/\s/),s=c(t,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(t){o.html(i?e("<div>").html(t.replace(m,"")).find(i):t),u&&u.apply(o,arguments)},e.ajax(s),this};var j=encodeURIComponent;e.param=function(t,n){var r=[];return r.add=function(t,n){e.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(j(t)+"="+j(n))},l(r,t,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){if(t.forEach)return t.forEach(i);r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,(e=o.name)&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(n){var e=getComputedStyle;t.getComputedStyle=function(t,n){try{return e(t,n)}catch(t){return null}}}}(),e});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/loading.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/loading.min.js
new file mode 100755
index 0000000..c230eb0
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/loading.min.js
@@ -0,0 +1 @@
+window.loading=function(e){var c={};"object"==typeof e?c=e:c.message=e,c.id||(c.id="LOADING"+(new Date).getTime());var t=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(t=event.target.parentNode);var d=document.createElement("div");d.className="backdrop show backdrop-alert",d.id=c.id+"_BACKDROP",t.appendChild(d);var a=document.createElement("div");a.className="alert-mobileui alert-loading",a.id=c.id,d.parentNode.appendChild(a);var l=document.createElement("div");c.class="white",l.className="alert "+c.class,window.SO&&2===SO.code?l.innerHTML='<div class="loading-circle"><svg xmlns="http://www.w3.org/2000/svg" width="37" height="37" viewBox="0 0 27 27"><path d="M18.696,10.5c-0.275-0.479-0.113-1.09,0.365-1.367l4.759-2.751c0.482-0.273,1.095-0.11,1.37,0.368 c0.276,0.479,0.115,1.092-0.364,1.364l-4.764,2.751C19.583,11.141,18.973,10.977,18.696,10.5z"/><path d="M16.133,6.938l2.75-4.765c0.276-0.478,0.889-0.643,1.367-0.366c0.479,0.276,0.641,0.886,0.365,1.366l-2.748,4.762 C17.591,8.415,16.979,8.58,16.5,8.303C16.021,8.027,15.856,7.414,16.133,6.938z"/><path d="M13.499,7.5c-0.552,0-1-0.448-1-1.001V1c0-0.554,0.448-1,1-1c0.554,0,1.003,0.447,1.003,1v5.499 C14.5,7.053,14.053,7.5,13.499,7.5z"/><path d="M8.303,10.5c-0.277,0.477-0.888,0.641-1.365,0.365L2.175,8.114C1.697,7.842,1.532,7.229,1.808,6.75 c0.277-0.479,0.89-0.642,1.367-0.368l4.762,2.751C8.416,9.41,8.58,10.021,8.303,10.5z"/><path d="M9.133,7.937l-2.75-4.763c-0.276-0.48-0.111-1.09,0.365-1.366c0.479-0.277,1.09-0.114,1.367,0.366l2.75,4.765 c0.274,0.476,0.112,1.088-0.367,1.364C10.021,8.581,9.409,8.415,9.133,7.937z"/><path d="M6.499,14.5H1c-0.554,0-1-0.448-1-1c0-0.554,0.447-1.001,1-1.001h5.499c0.552,0,1.001,0.448,1.001,1.001 C7.5,14.052,7.052,14.5,6.499,14.5z"/><path d="M8.303,16.502c0.277,0.478,0.113,1.088-0.365,1.366l-4.762,2.749c-0.478,0.273-1.091,0.112-1.368-0.366 c-0.276-0.479-0.111-1.089,0.367-1.368l4.762-2.748C7.415,15.856,8.026,16.021,8.303,16.502z"/><path d="M10.866,20.062l-2.75,4.767c-0.277,0.475-0.89,0.639-1.367,0.362c-0.477-0.277-0.642-0.886-0.365-1.365l2.75-4.764 c0.277-0.477,0.888-0.638,1.366-0.365C10.978,18.974,11.141,19.585,10.866,20.062z"/><path d="M13.499,19.502c0.554,0,1.003,0.448,1.003,1.002v5.498c0,0.55-0.448,0.999-1.003,0.999c-0.552,0-1-0.447-1-0.999v-5.498 C12.499,19.95,12.946,19.502,13.499,19.502z"/><path d="M17.867,19.062l2.748,4.764c0.275,0.479,0.113,1.088-0.365,1.365c-0.479,0.276-1.091,0.112-1.367-0.362l-2.75-4.767 c-0.276-0.477-0.111-1.088,0.367-1.365C16.979,18.424,17.591,18.585,17.867,19.062z"/><path d="M18.696,16.502c0.276-0.48,0.887-0.646,1.365-0.367l4.765,2.748c0.479,0.279,0.64,0.889,0.364,1.368 c-0.275,0.479-0.888,0.64-1.37,0.366l-4.759-2.749C18.583,17.59,18.421,16.979,18.696,16.502z"/><path d="M25.998,12.499h-5.501c-0.552,0-1.001,0.448-1.001,1.001c0,0.552,0.447,1,1.001,1h5.501c0.554,0,1.002-0.448,1.002-1 C27,12.946,26.552,12.499,25.998,12.499z"/></svg></div>':l.innerHTML='<svg class="loading-circle" width="40" height="40" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="20" cy="20" r="15"></svg>',c.message&&(l.innerHTML+="<p>"+c.message+"</p>"),a.appendChild(l)},window.loadingElement=function(e,c,t,d){"object"!=typeof e&&(e=document.getElementById(e));var a=c?"with-message":"";d=d?"":"white-loading",t||(t="");document.createElement("div");var l="";l=window.SO&&2===SO.code?'<svg class="loading-circle loading-element '+d+" "+a+" "+t+'" xmlns="http://www.w3.org/2000/svg" width="37" height="37" viewBox="0 0 27 27"><path d="M18.696,10.5c-0.275-0.479-0.113-1.09,0.365-1.367l4.759-2.751c0.482-0.273,1.095-0.11,1.37,0.368 c0.276,0.479,0.115,1.092-0.364,1.364l-4.764,2.751C19.583,11.141,18.973,10.977,18.696,10.5z"/><path d="M16.133,6.938l2.75-4.765c0.276-0.478,0.889-0.643,1.367-0.366c0.479,0.276,0.641,0.886,0.365,1.366l-2.748,4.762 C17.591,8.415,16.979,8.58,16.5,8.303C16.021,8.027,15.856,7.414,16.133,6.938z"/><path d="M13.499,7.5c-0.552,0-1-0.448-1-1.001V1c0-0.554,0.448-1,1-1c0.554,0,1.003,0.447,1.003,1v5.499 C14.5,7.053,14.053,7.5,13.499,7.5z"/><path d="M8.303,10.5c-0.277,0.477-0.888,0.641-1.365,0.365L2.175,8.114C1.697,7.842,1.532,7.229,1.808,6.75 c0.277-0.479,0.89-0.642,1.367-0.368l4.762,2.751C8.416,9.41,8.58,10.021,8.303,10.5z"/><path d="M9.133,7.937l-2.75-4.763c-0.276-0.48-0.111-1.09,0.365-1.366c0.479-0.277,1.09-0.114,1.367,0.366l2.75,4.765 c0.274,0.476,0.112,1.088-0.367,1.364C10.021,8.581,9.409,8.415,9.133,7.937z"/><path d="M6.499,14.5H1c-0.554,0-1-0.448-1-1c0-0.554,0.447-1.001,1-1.001h5.499c0.552,0,1.001,0.448,1.001,1.001 C7.5,14.052,7.052,14.5,6.499,14.5z"/><path d="M8.303,16.502c0.277,0.478,0.113,1.088-0.365,1.366l-4.762,2.749c-0.478,0.273-1.091,0.112-1.368-0.366 c-0.276-0.479-0.111-1.089,0.367-1.368l4.762-2.748C7.415,15.856,8.026,16.021,8.303,16.502z"/><path d="M10.866,20.062l-2.75,4.767c-0.277,0.475-0.89,0.639-1.367,0.362c-0.477-0.277-0.642-0.886-0.365-1.365l2.75-4.764 c0.277-0.477,0.888-0.638,1.366-0.365C10.978,18.974,11.141,19.585,10.866,20.062z"/><path d="M13.499,19.502c0.554,0,1.003,0.448,1.003,1.002v5.498c0,0.55-0.448,0.999-1.003,0.999c-0.552,0-1-0.447-1-0.999v-5.498 C12.499,19.95,12.946,19.502,13.499,19.502z"/><path d="M17.867,19.062l2.748,4.764c0.275,0.479,0.113,1.088-0.365,1.365c-0.479,0.276-1.091,0.112-1.367-0.362l-2.75-4.767 c-0.276-0.477-0.111-1.088,0.367-1.365C16.979,18.424,17.591,18.585,17.867,19.062z"/><path d="M18.696,16.502c0.276-0.48,0.887-0.646,1.365-0.367l4.765,2.748c0.479,0.279,0.64,0.889,0.364,1.368 c-0.275,0.479-0.888,0.64-1.37,0.366l-4.759-2.749C18.583,17.59,18.421,16.979,18.696,16.502z"/><path d="M25.998,12.499h-5.501c-0.552,0-1.001,0.448-1.001,1.001c0,0.552,0.447,1,1.001,1h5.501c0.554,0,1.002-0.448,1.002-1 C27,12.946,26.552,12.499,25.998,12.499z"/></svg>':'<svg class="loading-circle loading-element '+d+" "+a+" "+t+'" width="40" height="40" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="20" cy="20" r="15"></svg>',e.oldValue=e.innerHTML,e.innerHTML=l,e.disabled=!0,c&&(e.innerHTML+=c)},window.closeLoading=function(e){if(e)"object"!=typeof e&&(e=document.getElementById(e)),e.innerHTML=e.oldValue,e.disabled=!1;else{var c=document.getElementsByClassName("alert-mobileui")[0],t=c.id;(c=document.getElementById(t)).parentNode.removeChild(c);var d=document.getElementById(t+"_BACKDROP");d.parentNode.removeChild(d)}};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/menu.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/menu.min.js
new file mode 100755
index 0000000..46cf212
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/menu.min.js
@@ -0,0 +1 @@
+window.menu={},window.openMenu=function(e){var n=e;if((e=document.getElementById(e)).className.indexOf("menu")>=0&&e.className.indexOf("open")<0){var o=document.createElement("div");if(o.className="backdrop backdrop-menu",e.parentNode.appendChild(o),setTimeout(function(){o.className+=" show"}),o.addEventListener("click",function(e){window.closeMenu(n)},!1),2===SO.code){e.style.height=window.innerHeight+"px";var d=" side-menu";if(window.menu.position="left",e.className.indexOf("menu-right")>=0){d=" side-menu-right",window.menu.position="right";var a=document.getElementsByClassName("header");if(a.length)for(i in a)a[i].className&&a[i].className.indexOf("side-menu-right")<0&&(a[i].className+=" side-menu-right")}e.parentNode.className.indexOf("body")>=0?e.parentNode.className+=d:document.getElementsByTagName("body")[0].className+=d}e.className+=" open";var t=new CustomEvent("openMenu",{detail:{menu:n}});document.dispatchEvent(t),window.menu.openFired=!0,document.addEventListener("firedCloseMenu",function(e){window.closeMenu(n)},!1)}},window.closeMenu=function(e){var n=e;if((e=document.getElementById(e)).className.indexOf("open")<0)return!1;var o=new CustomEvent("closeMenu",{detail:{menu:n}});document.dispatchEvent(o),window.menu.openFired=!1,e.className=e.className.replace("open","");var d=document.getElementsByClassName("header");if(d.length)for(i in d)d[i].className&&d[i].className.indexOf("side-menu-right")>=0&&(d[i].className=d[i].className.replace(" side-menu-right",""));var a=e.parentNode.getElementsByClassName("backdrop-menu");a&&a.length&&((a=a[0]).className=a.className.replace("show",""),setTimeout(function(){a&&a.parentNode&&a.parentNode.removeChild(a)},500)),1!==SO.code&&(e.parentNode.className.indexOf("body")>=0?e.parentNode.className=e.parentNode.className.replace("side-menu",""):document.getElementsByTagName("body")[0].className=document.getElementsByTagName("body")[0].className.replace("side-menu",""))},document.querySelector("body").addEventListener("touchstart",function(e){window.menu.xDown=e.touches[0].clientX,window.menu.yDown=e.touches[0].clientY},!1),window.menu.handleTouchMove=function(e,n){if(window.menu.xDown&&window.menu.yDown){var o=e.touches[0].clientX,i=e.touches[0].clientY;if(window.menu.xDiff=window.menu.xDown-o,window.menu.yDiff=window.menu.yDown-i,Math.abs(window.menu.xDiff)>Math.abs(window.menu.yDiff)){var d=-1!==document.getElementById(n).classList.value.indexOf("menu-right");window.menu.xDiff>0?d&&!window.menu.openFired?window.openMenu(n):!d&&window.menu.openFired&&window.closeMenu(n):d||window.menu.openFired?d&&window.menu.openFired&&window.closeMenu(n):window.openMenu(n)}window.menu.xDown=null,window.menu.yDown=null}},window.menu.enableSwiper=function(e){document.querySelector("body").addEventListener("touchmove",function(n){window.menu.handleTouchMove(n,e)},!1)};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/mobileui-colors.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/mobileui-colors.min.js
new file mode 100755
index 0000000..cbae6e3
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/mobileui-colors.min.js
@@ -0,0 +1 @@
+window.colorsMobileUI=[],window.colorsMobileUI.red="rgb(244, 67, 54)",window.colorsMobileUI["red-50"]="rgb(255, 235, 238)",window.colorsMobileUI["red-100"]="rgb(255, 205, 210)",window.colorsMobileUI["red-200"]="rgb(239, 154, 154)",window.colorsMobileUI["red-300"]="rgb(229, 115, 115)",window.colorsMobileUI["red-400"]="rgb(239, 83, 80)",window.colorsMobileUI["red-500"]="rgb(244, 67, 54)",window.colorsMobileUI["red-600"]="rgb(229, 57, 53)",window.colorsMobileUI["red-700"]="rgb(211, 47, 47)",window.colorsMobileUI["red-800"]="rgb(198, 40, 40)",window.colorsMobileUI["red-900"]="rgb(183, 28, 28)",window.colorsMobileUI.pink="rgb(233, 30, 99)",window.colorsMobileUI["pink-50"]="rgb(252, 228, 236)",window.colorsMobileUI["pink-100"]="rgb(248, 187, 208)",window.colorsMobileUI["pink-200"]="rgb(244, 143, 177)",window.colorsMobileUI["Pink-300"]="rgb(240, 98, 146)",window.colorsMobileUI["pink-400"]="rgb(236, 64, 122)",window.colorsMobileUI["pink-500"]="rgb(233, 30, 99)",window.colorsMobileUI["pink-600"]="rgb(216, 27, 96)",window.colorsMobileUI["pink-700"]="rgb(194, 24, 91)",window.colorsMobileUI["pink-800"]="rgb(173, 20, 87)",window.colorsMobileUI["pink-900"]="rgb(136, 14, 79)",window.colorsMobileUI.purple="rgb(156, 39, 176)",window.colorsMobileUI["purple-50"]="rgb(243, 229, 245)",window.colorsMobileUI["purple-100"]="rgb(225, 190, 231)",window.colorsMobileUI["purple-200"]="rgb(206, 147, 216)",window.colorsMobileUI["Purple-300"]="rgb(186, 104, 200)",window.colorsMobileUI["Purple-400"]="rgb(171, 71, 188)",window.colorsMobileUI["purple-500"]="rgb(156, 39, 176)",window.colorsMobileUI["purple-600"]="rgb(142, 36, 170)",window.colorsMobileUI["purple-700"]="rgb(123, 31, 162)",window.colorsMobileUI["purple-800"]="rgb(106, 27, 154)",window.colorsMobileUI["purple-900"]="rgb(74, 20, 140)",window.colorsMobileUI["deep-purple"]="rgb(103, 58, 183)",window.colorsMobileUI["deep-purple-50"]="rgb(237, 231, 246)",window.colorsMobileUI["deep-purple-100"]="rgb(209, 196, 233)",window.colorsMobileUI["deep-purple-200"]="rgb(179, 157, 219)",window.colorsMobileUI["deep-purple-300"]="rgb(149, 117, 205)",window.colorsMobileUI["deep-purple-400"]="rgb(126, 87, 194)",window.colorsMobileUI["deep-purple-500"]="rgb(103, 58, 183)",window.colorsMobileUI["deep-purple-600"]="rgb(94, 53, 177)",window.colorsMobileUI["deep-purple-700"]="rgb(81, 45, 168)",window.colorsMobileUI["deep-purple-800"]="rgb(69, 39, 160)",window.colorsMobileUI["deep-purple-900"]="rgb(49, 27, 146)",window.colorsMobileUI.indigo="rgb(63, 81, 181)",window.colorsMobileUI["indigo-50"]="rgb(232, 234, 246)",window.colorsMobileUI["indigo-100"]="rgb(197, 202, 233)",window.colorsMobileUI["indigo-200"]="rgb(159, 168, 218)",window.colorsMobileUI["indigo-300"]="rgb(121, 134, 203)",window.colorsMobileUI["indigo-400"]="rgb(92, 107, 192)",window.colorsMobileUI["indigo-500"]="rgb(63, 81, 181)",window.colorsMobileUI["indigo-600"]="rgb(57, 73, 171)",window.colorsMobileUI["indigo-700"]="rgb(48, 63, 159)",window.colorsMobileUI["indigo-800"]="rgb(40, 53, 147)",window.colorsMobileUI["indigo-900"]="rgb(26, 35, 126)",window.colorsMobileUI.blue="rgb(33, 150, 243)",window.colorsMobileUI["blue-50"]="rgb(227, 242, 253)",window.colorsMobileUI["blue-100"]="rgb(187, 222, 251)",window.colorsMobileUI["blue-200"]="rgb(144, 202, 249)",window.colorsMobileUI["blue-300"]="rgb(100, 181, 246)",window.colorsMobileUI["blue-400"]="rgb(66, 165, 245)",window.colorsMobileUI["blue-500"]="rgb(33, 150, 243)",window.colorsMobileUI["blue-600"]="rgb(30, 136, 229)",window.colorsMobileUI["blue-700"]="rgb(25, 118, 210)",window.colorsMobileUI["blue-800"]="rgb(21, 101, 192)",window.colorsMobileUI["blue-900"]="rgb(13, 71, 161)",window.colorsMobileUI["light-blue"]="rgb(3, 169, 244)",window.colorsMobileUI["light-blue-50"]="rgb(225, 245, 254)",window.colorsMobileUI["light-blue-100"]="rgb(179, 229, 252)",window.colorsMobileUI["light-blue-200"]="rgb(129, 212, 250)",window.colorsMobileUI["light-blue-300"]="rgb(79, 195, 247)",window.colorsMobileUI["light-blue-400"]="rgb(41, 182, 246)",window.colorsMobileUI["light-blue-500"]="rgb(3, 169, 244)",window.colorsMobileUI["light-blue-600"]="rgb(3, 155, 229)",window.colorsMobileUI["light-blue-700"]="rgb(2, 136, 209)",window.colorsMobileUI["light-blue-800"]="rgb(2, 119, 189)",window.colorsMobileUI["light-blue-900"]="rgb(1, 87, 155)",window.colorsMobileUI.cyan="rgb(0, 188, 212)",window.colorsMobileUI["cyan-50"]="rgb(224, 247, 250)",window.colorsMobileUI["cyan-100"]="rgb(178, 235, 242)",window.colorsMobileUI["cyan-200"]="rgb(128, 222, 234)",window.colorsMobileUI["cyan-300"]="rgb(77, 208, 225)",window.colorsMobileUI["cyan-400"]="rgb(38, 198, 218)",window.colorsMobileUI["cyan-500"]="rgb(0, 188, 212)",window.colorsMobileUI["cyan-600"]="rgb(0, 172, 193)",window.colorsMobileUI["cyan-700"]="rgb(0, 151, 167)",window.colorsMobileUI["cyan-800"]="rgb(0, 131, 143)",window.colorsMobileUI["cyan-900"]="rgb(0, 96, 100)",window.colorsMobileUI.teal="rgb(0, 150, 136)",window.colorsMobileUI["teal-50"]="rgb(224, 242, 241)",window.colorsMobileUI["teal-100"]="rgb(178, 223, 219)",window.colorsMobileUI["teal-200"]="rgb(128, 203, 196)",window.colorsMobileUI["teal-300"]="rgb(77, 182, 172)",window.colorsMobileUI["teal-400"]="rgb(38, 166, 154)",window.colorsMobileUI["teal-500"]="rgb(0, 150, 136)",window.colorsMobileUI["teal-600"]="rgb(0, 137, 123)",window.colorsMobileUI["teal-700"]="rgb(0, 121, 107)",window.colorsMobileUI["teal-800"]="rgb(0, 105, 92)",window.colorsMobileUI["teal-900"]="rgb(0, 77, 64)",window.colorsMobileUI.green="rgb(76, 175, 80)",window.colorsMobileUI["green-50"]="rgb(232, 245, 233)",window.colorsMobileUI["green-100"]="rgb(200, 230, 201)",window.colorsMobileUI["green-200"]="rgb(165, 214, 167)",window.colorsMobileUI["green-300"]="rgb(129, 199, 132)",window.colorsMobileUI["green-400"]="rgb(102, 187, 106)",window.colorsMobileUI["green-500"]="rgb(76, 175, 80)",window.colorsMobileUI["green-600"]="rgb(67, 160, 71)",window.colorsMobileUI["green-700"]="rgb(56, 142, 60)",window.colorsMobileUI["green-800"]="rgb(46, 125, 50)",window.colorsMobileUI["green-900"]="rgb(27, 94, 32)",window.colorsMobileUI["light-green"]="rgb(139, 195, 74)",window.colorsMobileUI["light-green-50"]="rgb(241, 248, 233)",window.colorsMobileUI["light-green-100"]="rgb(220, 237, 200)",window.colorsMobileUI["light-green-200"]="rgb(197, 225, 165)",window.colorsMobileUI["light-green-300"]="rgb(174, 213, 129)",window.colorsMobileUI["light-green-400"]="rgb(156, 204, 101)",window.colorsMobileUI["light-green-500"]="rgb(139, 195, 74)",window.colorsMobileUI["light-green-600"]="rgb(124, 179, 66)",window.colorsMobileUI["light-green-700"]="rgb(104, 159, 56)",window.colorsMobileUI["light-green-800"]="rgb(85, 139, 47)",window.colorsMobileUI["light-green-900"]="rgb(51, 105, 30)",window.colorsMobileUI.lime="rgb(205, 220, 57)",window.colorsMobileUI["lime-50"]="rgb(249, 251, 231)",window.colorsMobileUI["lime-100"]="rgb(240, 244, 195)",window.colorsMobileUI["lime-200"]="rgb(230, 238, 156)",window.colorsMobileUI["lime-300"]="rgb(220, 231, 117)",window.colorsMobileUI["lime-400"]="rgb(212, 225, 87)",window.colorsMobileUI["lime-500"]="rgb(205, 220, 57)",window.colorsMobileUI["lime-600"]="rgb(192, 202, 51)",window.colorsMobileUI["lime-700"]="rgb(175, 180, 43)",window.colorsMobileUI["lime-800"]="rgb(158, 157, 36)",window.colorsMobileUI["lime-900"]="rgb(130, 119, 23)",window.colorsMobileUI.yellow="rgb(255, 235, 59)",window.colorsMobileUI["yellow-50"]="rgb(255, 253, 231)",window.colorsMobileUI["yellow-100"]="rgb(255, 249, 196)",window.colorsMobileUI["yellow-200"]="rgb(255, 245, 157)",window.colorsMobileUI["yellow-300"]="rgb(255, 241, 118)",window.colorsMobileUI["yellow-400"]="rgb(255, 238, 88)",window.colorsMobileUI["yellow-500"]="rgb(255, 235, 59)",window.colorsMobileUI["yellow-600"]="rgb(253, 216, 53)",window.colorsMobileUI["yellow-700"]="rgb(251, 192, 45)",window.colorsMobileUI["yellow-800"]="rgb(249, 168, 37)",window.colorsMobileUI["yellow-900"]="rgb(245, 127, 23)",window.colorsMobileUI.amber="rgb(255, 193, 7)",window.colorsMobileUI["amber-50"]="rgb(255, 248, 225)",window.colorsMobileUI["amber-100"]="rgb(255, 236, 179)",window.colorsMobileUI["amber-200"]="rgb(255, 224, 130)",window.colorsMobileUI["amber-300"]="rgb(255, 213, 79)",window.colorsMobileUI["amber-400"]="rgb(255, 202, 40)",window.colorsMobileUI["amber-500"]="rgb(255, 193, 7)",window.colorsMobileUI["amber-600"]="rgb(255, 179, 0)",window.colorsMobileUI["amber-700"]="rgb(255, 160, 0)",window.colorsMobileUI["amber-800"]="rgb(255, 143, 0)",window.colorsMobileUI["amber-900"]="rgb(255, 111, 0)",window.colorsMobileUI.orange="rgb(255, 152, 0)",window.colorsMobileUI["orange-50"]="rgb(255, 243, 224)",window.colorsMobileUI["orange-100"]="rgb(255, 224, 178)",window.colorsMobileUI["orange-200"]="rgb(255, 204, 128)",window.colorsMobileUI["orange-300"]="rgb(255, 183, 77)",window.colorsMobileUI["orange-400"]="rgb(255, 167, 38)",window.colorsMobileUI["orange-500"]="rgb(255, 152, 0)",window.colorsMobileUI["orange-600"]="rgb(251, 140, 0)",window.colorsMobileUI["orange-700"]="rgb(245, 124, 0)",window.colorsMobileUI["orange-800"]="rgb(239, 108, 0)",window.colorsMobileUI["orange-900"]="rgb(230, 81, 0)",window.colorsMobileUI["deep-orange"]="rgb(255, 87, 34)",window.colorsMobileUI["deep-orange-50"]="rgb(251, 233, 231)",window.colorsMobileUI["deep-orange-100"]="rgb(255, 204, 188)",window.colorsMobileUI["deep-orange-200"]="rgb(255, 171, 145)",window.colorsMobileUI["deep-orange-300"]="rgb(255, 138, 101)",window.colorsMobileUI["deep-orange-400"]="rgb(255, 112, 67)",window.colorsMobileUI["deep-orange-500"]="rgb(255, 87, 34)",window.colorsMobileUI["deep-orange-600"]="rgb(244, 81, 30)",window.colorsMobileUI["deep-orange-700"]="rgb(230, 74, 25)",window.colorsMobileUI["deep-orange-800"]="rgb(216, 67, 21)",window.colorsMobileUI["deep-orange-900"]="rgb(191, 54, 12)",window.colorsMobileUI.brown="rgb(121, 85, 72)",window.colorsMobileUI["brown-50"]="rgb(239, 235, 233)",window.colorsMobileUI["brown-100"]="rgb(215, 204, 200)",window.colorsMobileUI["brown-200"]="rgb(188, 170, 164)",window.colorsMobileUI["brown-300"]="rgb(161, 136, 127)",window.colorsMobileUI["brown-400"]="rgb(141, 110, 99)",window.colorsMobileUI["brown-500"]="rgb(121, 85, 72)",window.colorsMobileUI["brown-600"]="rgb(109, 76, 65)",window.colorsMobileUI["brown-700"]="rgb(93, 64, 55)",window.colorsMobileUI["brown-800"]="rgb(78, 52, 46)",window.colorsMobileUI["brown-900"]="rgb(62, 39, 35)",window.colorsMobileUI.grey="rgb(158, 158, 158)",window.colorsMobileUI["grey-50"]="rgb(250, 250, 250)",window.colorsMobileUI["grey-100"]="rgb(245, 245, 245)",window.colorsMobileUI["grey-200"]="rgb(238, 238, 238)",window.colorsMobileUI["grey-300"]="rgb(224, 224, 224)",window.colorsMobileUI["grey-400"]="rgb(189, 189, 189)",window.colorsMobileUI["grey-500"]="rgb(158, 158, 158)",window.colorsMobileUI["grey-600"]="rgb(117, 117, 117)",window.colorsMobileUI["grey-700"]="rgb(97, 97, 97)",window.colorsMobileUI["grey-800"]="rgb(66, 66, 66)",window.colorsMobileUI["grey-900"]="rgb(33, 33, 33)",window.colorsMobileUI["blue-grey"]="rgb(96, 125, 139)",window.colorsMobileUI["blue-grey-50"]="rgb(236, 239, 241)",window.colorsMobileUI["blue-grey-100"]="rgb(207, 216, 220)",window.colorsMobileUI["blue-grey-200"]="rgb(176, 190, 197)",window.colorsMobileUI["blue-grey-300"]="rgb(144, 164, 174)",window.colorsMobileUI["blue-grey-400"]="rgb(120, 144, 156)",window.colorsMobileUI["blue-grey-500"]="rgb(96, 125, 139)",window.colorsMobileUI["blue-grey-600"]="rgb(84, 110, 122)",window.colorsMobileUI["blue-grey-700"]="rgb(69, 90, 100)",window.colorsMobileUI["blue-grey-800"]="rgb(55, 71, 79)",window.colorsMobileUI["blue-grey-900"]="rgb(38, 50, 56)",window.colorsMobileUI.black="rgb(0, 0, 0)",window.colorsMobileUI.white="rgb(255, 255, 255)",window.colorsMobileUI["black-opacity-90"]="rgba(0, 0, 0, 0.9)",window.colorsMobileUI["white-opacity-90"]="rgba(255, 255, 255, 0.9)",window.colorsMobileUI["black-opacity-70"]="rgba(0, 0, 0, 0.8)",window.colorsMobileUI["white-opacity-70"]="rgba(255, 255, 255, 0.7)",window.colorsMobileUI["black-opacity-50"]="rgba(0, 0, 0, 0.7)",window.colorsMobileUI["white-opacity-50"]="rgba(255, 255, 255, 0.5)",window.colorsMobileUI["black-opacity-30"]="rgba(0, 0, 0, 0.6)",window.colorsMobileUI["white-opacity-30"]="rgba(255, 255, 255, 0.3)",window.colorsMobileUI["black-opacity-10"]="rgba(0, 0, 0, 0.5)",window.colorsMobileUI["white-opacity-10"]="rgba(255, 255, 255, 0.1)";
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/mobileuijs.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/mobileuijs.min.js
new file mode 100755
index 0000000..4a7e1b6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/mobileuijs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).superagent=t()}}(function(){return function t(e,r,n){function i(s,a){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var h=r[s]={exports:{}};e[s][0].call(h.exports,function(t){return i(e[s][1][t]||t)},h,h.exports,t,e,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s<n.length;s++)i(n[s]);return i}({1:[function(t,e,r){var n=t("./is-object");e.exports=function(t){return"[object Function]"===(n(t)?Object.prototype.toString.call(t):"")}},{"./is-object":2}],2:[function(t,e,r){e.exports=function(t){return null!==t&&"object"==typeof t}},{}],3:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}var i=t("./is-object");e.exports=n,n.prototype.clearTimeout=function(){return clearTimeout(this._timer),clearTimeout(this._responseTimeoutTimer),delete this._timer,delete this._responseTimeoutTimer,this},n.prototype.parse=function(t){return this._parser=t,this},n.prototype.responseType=function(t){return this._responseType=t,this},n.prototype.serialize=function(t){return this._serializer=t,this},n.prototype.timeout=function(t){if(!t||"object"!=typeof t)return this._timeout=t,this._responseTimeout=0,this;for(var e in t)switch(e){case"deadline":this._timeout=t.deadline;break;case"response":this._responseTimeout=t.response;break;default:console.warn("Unknown timeout option",e)}return this},n.prototype.retry=function(t){return 0!==arguments.length&&!0!==t||(t=1),t<=0&&(t=0),this._maxRetries=t,this._retries=0,this},n.prototype._retry=function(){return this.clearTimeout(),this.req&&(this.req=null,this.req=this.request()),this._aborted=!1,this.timedout=!1,this._end()},n.prototype.then=function(t,e){if(!this._fullfilledPromise){var r=this;this._endCalled&&console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises"),this._fullfilledPromise=new Promise(function(t,e){r.end(function(r,n){r?e(r):t(n)})})}return this._fullfilledPromise.then(t,e)},n.prototype.catch=function(t){return this.then(void 0,t)},n.prototype.use=function(t){return t(this),this},n.prototype.ok=function(t){if("function"!=typeof t)throw Error("Callback required");return this._okCallback=t,this},n.prototype._isResponseOK=function(t){return!!t&&(this._okCallback?this._okCallback(t):t.status>=200&&t.status<300)},n.prototype.get=function(t){return this._header[t.toLowerCase()]},n.prototype.getHeader=n.prototype.get,n.prototype.set=function(t,e){if(i(t)){for(var r in t)this.set(r,t[r]);return this}return this._header[t.toLowerCase()]=e,this.header[t]=e,this},n.prototype.unset=function(t){return delete this._header[t.toLowerCase()],delete this.header[t],this},n.prototype.field=function(t,e){if(null===t||void 0===t)throw new Error(".field(name, val) name can not be empty");if(this._data&&console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()"),i(t)){for(var r in t)this.field(r,t[r]);return this}if(Array.isArray(e)){for(var n in e)this.field(t,e[n]);return this}if(null===e||void 0===e)throw new Error(".field(name, val) val can not be empty");return"boolean"==typeof e&&(e=""+e),this._getFormData().append(t,e),this},n.prototype.abort=function(){return this._aborted?this:(this._aborted=!0,this.xhr&&this.xhr.abort(),this.req&&this.req.abort(),this.clearTimeout(),this.emit("abort"),this)},n.prototype.withCredentials=function(t){return void 0==t&&(t=!0),this._withCredentials=t,this},n.prototype.redirects=function(t){return this._maxRedirects=t,this},n.prototype.toJSON=function(){return{method:this.method,url:this.url,data:this._data,headers:this._header}},n.prototype.send=function(t){var e=i(t),r=this._header["content-type"];if(this._formData&&console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()"),e&&!this._data)Array.isArray(t)?this._data=[]:this._isHost(t)||(this._data={});else if(t&&this._data&&this._isHost(this._data))throw Error("Can't merge these send calls");if(e&&i(this._data))for(var n in t)this._data[n]=t[n];else"string"==typeof t?(r||this.type("form"),r=this._header["content-type"],this._data="application/x-www-form-urlencoded"==r?this._data?this._data+"&"+t:t:(this._data||"")+t):this._data=t;return!e||this._isHost(t)?this:(r||this.type("json"),this)},n.prototype.sortQuery=function(t){return this._sort=void 0===t||t,this},n.prototype._timeoutError=function(t,e,r){if(!this._aborted){var n=new Error(t+e+"ms exceeded");n.timeout=e,n.code="ECONNABORTED",n.errno=r,this.timedout=!0,this.abort(),this.callback(n)}},n.prototype._setTimeouts=function(){var t=this;this._timeout&&!this._timer&&(this._timer=setTimeout(function(){t._timeoutError("Timeout of ",t._timeout,"ETIME")},this._timeout)),this._responseTimeout&&!this._responseTimeoutTimer&&(this._responseTimeoutTimer=setTimeout(function(){t._timeoutError("Response timeout of ",t._responseTimeout,"ETIMEDOUT")},this._responseTimeout))}},{"./is-object":2}],4:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}var i=t("./utils");e.exports=n,n.prototype.get=function(t){return this.header[t.toLowerCase()]},n.prototype._setHeaderProperties=function(t){var e=t["content-type"]||"";this.type=i.type(e);var r=i.params(e);for(var n in r)this[n]=r[n];this.links={};try{t.link&&(this.links=i.parseLinks(t.link))}catch(t){}},n.prototype._setStatusProperties=function(t){var e=t/100|0;this.status=this.statusCode=t,this.statusType=e,this.info=1==e,this.ok=2==e,this.redirect=3==e,this.clientError=4==e,this.serverError=5==e,this.error=(4==e||5==e)&&this.toError(),this.accepted=202==t,this.noContent=204==t,this.badRequest=400==t,this.unauthorized=401==t,this.notAcceptable=406==t,this.forbidden=403==t,this.notFound=404==t}},{"./utils":6}],5:[function(t,e,r){var n=["ECONNRESET","ETIMEDOUT","EADDRINFO","ESOCKETTIMEDOUT"];e.exports=function(t,e){return!!(t&&t.code&&~n.indexOf(t.code)||e&&e.status&&e.status>=500||t&&"timeout"in t&&"ECONNABORTED"==t.code||t&&"crossDomain"in t)}},{}],6:[function(t,e,r){r.type=function(t){return t.split(/ *; */).shift()},r.params=function(t){return t.split(/ *; */).reduce(function(t,e){var r=e.split(/ *= */),n=r.shift(),i=r.shift();return n&&i&&(t[n]=i),t},{})},r.parseLinks=function(t){return t.split(/ *, */).reduce(function(t,e){var r=e.split(/ *; */),n=r[0].slice(1,-1);return t[r[1].split(/ *= */)[1].slice(1,-1)]=n,t},{})},r.cleanHeader=function(t,e){return delete t["content-type"],delete t["content-length"],delete t["transfer-encoding"],delete t.host,e&&delete t.cookie,t}},{}],7:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}void 0!==e&&(e.exports=n),n.prototype.on=n.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},n.prototype.once=function(t,e){function r(){this.off(t,r),e.apply(this,arguments)}return r.fn=e,this.on(t,r),this},n.prototype.off=n.prototype.removeListener=n.prototype.removeAllListeners=n.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var r=this._callbacks["$"+t];if(!r)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var n,i=0;i<r.length;i++)if((n=r[i])===e||n.fn===e){r.splice(i,1);break}return this},n.prototype.emit=function(t){this._callbacks=this._callbacks||{};var e=[].slice.call(arguments,1),r=this._callbacks["$"+t];if(r)for(var n=0,i=(r=r.slice(0)).length;n<i;++n)r[n].apply(this,e);return this},n.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks["$"+t]||[]},n.prototype.hasListeners=function(t){return!!this.listeners(t).length}},{}],8:[function(t,e,r){function n(t){if(!p(t))return t;var e=[];for(var r in t)i(e,r,t[r]);return e.join("&")}function i(t,e,r){if(null!=r)if(Array.isArray(r))r.forEach(function(r){i(t,e,r)});else if(p(r))for(var n in r)i(t,e+"["+n+"]",r[n]);else t.push(encodeURIComponent(e)+"="+encodeURIComponent(r));else null===r&&t.push(encodeURIComponent(e))}function o(t){for(var e,r,n={},i=t.split("&"),o=0,s=i.length;o<s;++o)e=i[o],-1==(r=e.indexOf("="))?n[decodeURIComponent(e)]="":n[decodeURIComponent(e.slice(0,r))]=decodeURIComponent(e.slice(r+1));return n}function s(t){return/[\/+]json\b/.test(t)}function a(t){this.req=t,this.xhr=this.req.xhr,this.text="HEAD"!=this.req.method&&(""===this.xhr.responseType||"text"===this.xhr.responseType)||void 0===this.xhr.responseType?this.xhr.responseText:null,this.statusText=this.req.xhr.statusText;var e=this.xhr.status;1223===e&&(e=204),this._setStatusProperties(e),this.header=this.headers=function(t){var e,r,n,i,o=t.split(/\r?\n/),s={};o.pop();for(var a=0,u=o.length;a<u;++a)r=o[a],e=r.indexOf(":"),n=r.slice(0,e).toLowerCase(),i=v(r.slice(e+1)),s[n]=i;return s}(this.xhr.getAllResponseHeaders()),this.header["content-type"]=this.xhr.getResponseHeader("content-type"),this._setHeaderProperties(this.header),null===this.text&&t._responseType?this.body=this.xhr.response:this.body="HEAD"!=this.req.method?this._parseBody(this.text?this.text:this.xhr.response):null}function u(t,e){var r=this;this._query=this._query||[],this.method=t,this.url=e,this.header={},this._header={},this.on("end",function(){var t=null,e=null;try{e=new a(r)}catch(e){return t=new Error("Parser is unable to parse the response"),t.parse=!0,t.original=e,r.xhr?(t.rawResponse=void 0===r.xhr.responseType?r.xhr.responseText:r.xhr.response,t.status=r.xhr.status?r.xhr.status:null,t.statusCode=t.status):(t.rawResponse=null,t.status=null),r.callback(t)}r.emit("response",e);var n;try{r._isResponseOK(e)||(n=new Error(e.statusText||"Unsuccessful HTTP response"),n.original=t,n.response=e,n.status=e.status)}catch(t){n=t}n?r.callback(n,e):r.callback(null,e)})}function c(t,e,r){var n=b("DELETE",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n}var h;"undefined"!=typeof window?h=window:"undefined"!=typeof self?h=self:(console.warn("Using browser-only version of superagent in non-browser environment"),h=this);var l=t("component-emitter"),d=t("./request-base"),p=t("./is-object"),f=t("./is-function"),y=t("./response-base"),m=t("./should-retry"),b=r=e.exports=function(t,e){return"function"==typeof e?new r.Request("GET",t).end(e):1==arguments.length?new r.Request("GET",t):new r.Request(t,e)};r.Request=u,b.getXHR=function(){if(!(!h.XMLHttpRequest||h.location&&"file:"==h.location.protocol&&h.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(t){}throw Error("Browser-only verison of superagent could not find XHR")};var v="".trim?function(t){return t.trim()}:function(t){return t.replace(/(^\s*|\s*$)/g,"")};b.serializeObject=n,b.parseString=o,b.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},b.serialize={"application/x-www-form-urlencoded":n,"application/json":JSON.stringify},b.parse={"application/x-www-form-urlencoded":o,"application/json":JSON.parse},y(a.prototype),a.prototype._parseBody=function(t){var e=b.parse[this.type];return this.req._parser?this.req._parser(this,t):(!e&&s(this.type)&&(e=b.parse["application/json"]),e&&t&&(t.length||t instanceof Object)?e(t):null)},a.prototype.toError=function(){var t=this.req,e=t.method,r=t.url,n="cannot "+e+" "+r+" ("+this.status+")",i=new Error(n);return i.status=this.status,i.method=e,i.url=r,i},b.Response=a,l(u.prototype),d(u.prototype),u.prototype.type=function(t){return this.set("Content-Type",b.types[t]||t),this},u.prototype.accept=function(t){return this.set("Accept",b.types[t]||t),this},u.prototype.auth=function(t,e,r){switch("object"==typeof e&&null!==e&&(r=e),r||(r={type:"function"==typeof btoa?"basic":"auto"}),r.type){case"basic":this.set("Authorization","Basic "+btoa(t+":"+e));break;case"auto":this.username=t,this.password=e;break;case"bearer":this.set("Authorization","Bearer "+t)}return this},u.prototype.query=function(t){return"string"!=typeof t&&(t=n(t)),t&&this._query.push(t),this},u.prototype.attach=function(t,e,r){if(e){if(this._data)throw Error("superagent can't mix .send() and .attach()");this._getFormData().append(t,e,r||e.name)}return this},u.prototype._getFormData=function(){return this._formData||(this._formData=new h.FormData),this._formData},u.prototype.callback=function(t,e){if(this._maxRetries&&this._retries++<this._maxRetries&&m(t,e))return this._retry();var r=this._callback;this.clearTimeout(),t&&(this._maxRetries&&(t.retries=this._retries-1),this.emit("error",t)),r(t,e)},u.prototype.crossDomainError=function(){var t=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");t.crossDomain=!0,t.status=this.status,t.method=this.method,t.url=this.url,this.callback(t)},u.prototype.buffer=u.prototype.ca=u.prototype.agent=function(){return console.warn("This is not supported in browser version of superagent"),this},u.prototype.pipe=u.prototype.write=function(){throw Error("Streaming is not supported in browser version of superagent")},u.prototype._appendQueryString=function(){var t=this._query.join("&");if(t&&(this.url+=(this.url.indexOf("?")>=0?"&":"?")+t),this._sort){var e=this.url.indexOf("?");if(e>=0){var r=this.url.substring(e+1).split("&");f(this._sort)?r.sort(this._sort):r.sort(),this.url=this.url.substring(0,e)+"?"+r.join("&")}}},u.prototype._isHost=function(t){return t&&"object"==typeof t&&!Array.isArray(t)&&"[object Object]"!==Object.prototype.toString.call(t)},u.prototype.end=function(t){return this._endCalled&&console.warn("Warning: .end() was called twice. This is not supported in superagent"),this._endCalled=!0,this._callback=t||function(){},this._appendQueryString(),this._end()},u.prototype._end=function(){var t=this,e=this.xhr=b.getXHR(),r=this._formData||this._data;this._setTimeouts(),e.onreadystatechange=function(){var r=e.readyState;if(r>=2&&t._responseTimeoutTimer&&clearTimeout(t._responseTimeoutTimer),4==r){var n;try{n=e.status}catch(t){n=0}if(!n){if(t.timedout||t._aborted)return;return t.crossDomainError()}t.emit("end")}};var n=function(e,r){r.total>0&&(r.percent=r.loaded/r.total*100),r.direction=e,t.emit("progress",r)};if(this.hasListeners("progress"))try{e.onprogress=n.bind(null,"download"),e.upload&&(e.upload.onprogress=n.bind(null,"upload"))}catch(t){}try{this.username&&this.password?e.open(this.method,this.url,!0,this.username,this.password):e.open(this.method,this.url,!0)}catch(t){return this.callback(t)}if(this._withCredentials&&(e.withCredentials=!0),!this._formData&&"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof r&&!this._isHost(r)){var i=this._header["content-type"],o=this._serializer||b.serialize[i?i.split(";")[0]:""];!o&&s(i)&&(o=b.serialize["application/json"]),o&&(r=o(r))}for(var a in this.header)null!=this.header[a]&&this.header.hasOwnProperty(a)&&e.setRequestHeader(a,this.header[a]);return this._responseType&&(e.responseType=this._responseType),this.emit("request",this),e.send(void 0!==r?r:null),this},b.get=function(t,e,r){var n=b("GET",t);return"function"==typeof e&&(r=e,e=null),e&&n.query(e),r&&n.end(r),n},b.head=function(t,e,r){var n=b("HEAD",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.options=function(t,e,r){var n=b("OPTIONS",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.del=c,b.delete=c,b.patch=function(t,e,r){var n=b("PATCH",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.post=function(t,e,r){var n=b("POST",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.put=function(t,e,r){var n=b("PUT",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n}},{"./is-function":1,"./is-object":2,"./request-base":3,"./response-base":4,"./should-retry":5,"component-emitter":7}]},{},[8])(8)}),function(){var observerWatchers=[],tokenObserver=0,dataBind=function(){for(var t=document.querySelectorAll("[data]"),e=0;e<t.length;e++)if(t[e].getAttribute("data")&&!t[e].getAttribute("data-binded")){var r=t[e].getAttribute("data");(r=fetchFromObject(window,r))&&(writeElement(t[e],r),t[e].setAttribute("data-binded","mobileui"),dataObserver(t[e].getAttribute("data"),tokenObserver++))}eventLoopBind()};eventLoopBind=function(){setTimeout(function(){dataBind()},100)},reDataBind=function(t){for(var e=fetchFromObject(window,t.dataKey),r=document.querySelectorAll("[data-binded]"),n=0;n<r.length;n++)r[n].getAttribute("data-binded")===t.dataKey&&r[n].parentNode.removeChild(r[n]);r=document.querySelectorAll("[data][data-binded]");for(n=0;n<r.length;n++)r[n].getAttribute("data")===t.dataKey&&writeElement(r[n],e);t.dataValue=copyObj(e)},writeElement=function(elm,data){var bindWriteElement=function(dataObj,index){for(var html=elm.outerHTML,exp=/\${/g;match=exp.exec(html);){var prop=html.slice(match.index+2,html.length).split("}")[0],value=fetchFromObject(dataObj,prop);html=html.replace("${"+prop+"}",value)}index&&(html=html.replace(new RegExp("\\$\\$index","g"),index));for(var functionBind=html.split("$$"),i=1;i<functionBind.length;i++){var prop=functionBind[i].split("{")[1].split(",")[0].split("}")[0],value=fetchFromObject(dataObj,prop),functionName=functionBind[i].split("{")[0],functionReplace=functionBind[i].split("}")[0]+"}",functionInvoke="window.MobileUI."+functionBind[i].split("}")[0].replace(prop,"'"+value+"'").replace("{","(")+")",valueBind=eval(functionInvoke);html=html.replace(new RegExp("\\$\\$"+functionReplace,"g"),valueBind)}var divBind=document.createElement("div");elm.parentNode.insertBefore(divBind,elm),html=html.replace("data=","data-binded="),divBind.outerHTML=html};if(data.constructor===Array)for(var id in data)bindWriteElement(data[id],id);else bindWriteElement(data)},fetchFromObject=function(t,e){if(void 0===t)return console.error("Object for property ",e," is undefined!"),"";var r=e.indexOf(".");return r>-1?fetchFromObject(t[e.substring(0,r)],e.substr(r+1)):t.constructor===String||t.constructor===Number||t.constructor===Boolean||t.constructor===Date?t||"":t[e]?t[e]:""},dispatchEventObserver=function(t){var e=new CustomEvent("dataUpdated",{detail:{dataKey:t.dataKey,dataValue:t.dataValue}});document.dispatchEvent(e)},dataObserver=function(t,e){observerWatchers[e]||(observerWatchers[e]={dataKey:t,dataValue:copyObj(fetchFromObject(window,t))});var r=fetchFromObject(window,observerWatchers[e].dataKey);observerWatchers[e].dataValue.constructor===Array&&observerWatchers[e].dataValue.length!==r.length?(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])):observerWatchers[e].dataValue.constructor===Array&&observerWatchers[e].dataValue.toString()!==r.toString()?(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])):JSON.stringify(observerWatchers[e].dataValue)!==JSON.stringify(r)&&(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])),setTimeout(function(){dataObserver(t,e)},100)},copyObj=function(t){return JSON.parse(JSON.stringify(t))},dataBind(),window.MobileUI={bind:function(){dataBind()},objectByForm:function(t){for(var e=document.getElementById(t),r={},n=e.querySelectorAll("input,textarea,select"),i=0;i<n.length;i++)if(n[i].id&&"checkbox"===n[i].type)r[n[i].id]=n[i].checked;else if(n[i].name&&"radio"===n[i].type){var o=e.querySelector('input[name="'+n[i].name+'"]:checked').value;o&&(r[n[i].name]=o)}else n[i].id&&(r[n[i].id]=n[i].value);return r},disable:function(t){for(var e=document.getElementById(t).querySelectorAll("input,textarea,select,button,a"),r=0;r<e.length;r++)e[r].setAttribute("disabled","disabled")},enable:function(t){for(var e=document.getElementById(t).querySelectorAll("input,textarea,select,button,a"),r=0;r<e.length;r++)e[r].removeAttribute("disabled")},formByObject:function(t,e){for(var r=document.getElementById(t),n=r.querySelectorAll("input,textarea,select"),i=0;i<n.length;i++)if(n[i].id&&"checkbox"===n[i].type)n[i].checked=e[n[i].id];else if(n[i].name&&"radio"===n[i].type){var o=r.querySelector('input[name="'+n[i].name+'"][value="'+e[n[i].name]+'"]');o&&(o.checked=!0)}else n[i].id&&e[n[i].id]&&(n[i].value=e[n[i].id])},clearForm:function(t){for(var e=document.getElementById(t),r=e.querySelectorAll("input,textarea,select"),n=0;n<r.length;n++)if(r[n].id&&r[n].type.indexOf("select")>=0){for(var i=r[n].options,o=0;o<i.length;o++)i[o].defaultSelected&&(r[n].selectedIndex=o,r[n].found=!0);r[n].found||(r[n].selectedIndex=0)}else r[n].id&&"checkbox"===r[n].type?r[n].checked=null!==r[n].getAttribute("checked"):r[n].name&&"radio"===r[n].type?e.querySelector('input[name="'+r[n].name+'"][checked]').checked=!0:r[n].id&&(r[n].value="")},show:function(t){document.getElementById(t).style.display="block"},hide:function(t){document.getElementById(t).style.display="none"},showHide:function(t){null===document.getElementById(t).offsetParent?this.show(t):this.hide(t)},focus:function(t){document.getElementById(t).focus()},formatMoney:function(t,e,r,n){var e=isNaN(e=Math.abs(e))?2:e,r=void 0==r?".":r,n=void 0==n?",":n,i=t<0?"-":"",o=String(parseInt(t=Math.abs(Number(t)||0).toFixed(e))),s=(s=o.length)>3?s%3:0;return i+(s?o.substr(0,s)+n:"")+o.substr(s).replace(/(\d{3})(?=\d)/g,"$1"+n)+(e?r+Math.abs(t-o).toFixed(e).slice(2):"")},ajax:superagent}}();
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/momentjs.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/momentjs.min.js
new file mode 100755
index 0000000..a2734f4
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/momentjs.min.js
@@ -0,0 +1 @@
+!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 Xe.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 we(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=Ke.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),et.length>0)for(n=0;n<et.length;n++)s(r=t[i=et[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===tt&&(tt=!0,e.updateOffset(this),tt=!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),nt[t]||(w(n),nt[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();it[n]=it[n+"s"]=it[t]=e}function O(e){return"string"==typeof e?it[e]||it[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){rt[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&&(lt[e]=i),t&&(lt[t[0]]=function(){return b(i.apply(this,arguments),t[1],t[2])}),n&&(lt[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()),ut[t]=ut[t]||function(e){var t,n,s=e.match(at);for(t=0,n=s.length;t<n;t++)lt[s[t]]?s[t]=lt[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),ut[t](e)):e.localeData().invalidDate()}function C(e,t){var n=5;for(ot.lastIndex=0;n>=0&&ot.test(e);)e=e.replace(ot,function(e){return t.longDateFormat(e)||e}),ot.lastIndex=0,n-=1;return e}function F(e,t,n){Ot[e]=k(t)?t:function(e,s){return e&&n?n:t}}function U(e,t){return o(Ot,e)?Ot[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++)xt[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(xt,e)&&xt[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())?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(!Kt[e]&&"undefined"!=typeof module&&module&&module.exports){t=Bt._abbr;try{require("moment/locale/"+e)}catch(t){try{require("./locale/"+e)}catch(e){}}ae(t)}return Kt[e]}function ae(e,t){var n;return e&&(n=s(t)?ue(e):oe(e,t))&&(Bt=n),Bt._abbr}function oe(e,t){if(null!==t){var n=Xt;if(t.abbr=e,null!=Kt[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=Kt[e]._config;else if(null!=t.parentLocale){if(null==Kt[t.parentLocale])return en[t.parentLocale]||(en[t.parentLocale]=[]),en[t.parentLocale].push({name:e,config:t}),null;n=Kt[t.parentLocale]._config}return Kt[e]=new D(S(n,t)),en[e]&&en[e].forEach(function(e){oe(e.name,e.config)}),ae(e),Kt[e]}return delete Kt[e],null}function ue(e){var n;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Bt;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[bt]<0||n[bt]>11?bt:n[Pt]<1||n[Pt]>z(n[Tt],n[bt])?Pt:n[Wt]<0||n[Wt]>24||24===n[Wt]&&(0!==n[Rt]||0!==n[Ct]||0!==n[Ft])?Wt:n[Rt]<0||n[Rt]>59?Rt:n[Ct]<0||n[Ct]>59?Ct:n[Ft]<0||n[Ft]>999?Ft:-1,d(e)._overflowDayOfYear&&(t<Tt||t>Pt)&&(t=Pt),d(e)._overflowWeeks&&-1===t&&(t=Ut),d(e)._overflowWeekday&&-1===t&&(t=Nt),d(e).overflow=t),e}function de(e,t,n){return null!=e?e:null!=t?t:n}function he(t){var n=new Date(e.now());return t._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}function ce(e){var t,n,s,i,r=[];if(!e._d){for(s=he(e),e._w&&null==e._a[Pt]&&null==e._a[bt]&&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[Tt],X(ve(),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(ve(),r,a);n=de(t.gg,e._a[Tt],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[Tt]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(i=de(e._a[Tt],s[Tt]),(e._dayOfYear>V(i)||0===e._dayOfYear)&&(d(e)._overflowDayOfYear=!0),n=J(i,0,e._dayOfYear),e._a[bt]=n.getUTCMonth(),e._a[Pt]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=r[t]=s[t];for(;t<7;t++)e._a[t]=r[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[Wt]&&0===e._a[Rt]&&0===e._a[Ct]&&0===e._a[Ft]&&(e._nextDay=!0,e._a[Wt]=0),e._d=(e._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,r),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Wt]=24),e._w&&void 0!==e._w.d&&e._w.d!==e._d.getDay()&&(d(e).weekdayMismatch=!0)}}function fe(e){var t,n,s,i,r,a,o=e._i,u=tn.exec(o)||nn.exec(o);if(u){for(d(e).iso=!0,t=0,n=rn.length;t<n;t++)if(rn[t][1].exec(u[1])){i=rn[t][0],s=!1!==rn[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=an.length;t<n;t++)if(an[t][1].exec(u[3])){r=(u[2]||" ")+an[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!sn.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),ye(e)}else e._isValid=!1}function me(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);return t<=49?2e3+t:t<=999?1900+t:t}(e),jt.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}function _e(e){var t=un.exec(function(e){return e.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim()}(e._i));if(t){var n=me(t[4],t[3],t[2],t[5],t[6],t[7]);if(!function(e,t,n){return!e||zt.indexOf(e)===new Date(t[0],t[1],t[2]).getDay()||(d(n).weekdayMismatch=!0,n._isValid=!1,!1)}(t[1],n,e))return;e._a=n,e._tzm=function(e,t,n){if(e)return ln[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 ye(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(at)||[],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),lt[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[Wt]<=12&&!0===d(t).bigHour&&t._a[Wt]>0&&(d(t).bigHour=void 0),d(t).parsedDateParts=t._a.slice(0),d(t).meridiem=t._meridiem,t._a[Wt]=function(e,t,n){var s;return null==n?t: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[Wt],t._meridiem),ce(t),le(t)}else _e(t);else fe(t)}function ge(e){var n=e._i,s=e._f;return e._locale=e._locale||ue(e._l),null===n||void 0===s&&""===n?c({nullInput:!0}):("string"==typeof n&&(e._i=n=e._locale.preparse(n)),_(n)?new m(le(n)):(r(n)?e._d=n:t(s)?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],ye(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)}(e):s?ye(e):pe(e),h(e)||(e._d=null),e))}function pe(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=on.exec(t._i);null===n?(fe(t),!1===t._isValid&&(delete t._isValid,_e(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)}),ce(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)}),ce(e)}}(o):i(u)?o._d=new Date(u):e.createFromInputFallback(o)}function we(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(ge(e)));return t._nextDay&&(t.add(1,"d"),t._nextDay=void 0),t}(o)}function ve(e,t,n,s){return we(e,t,n,s,!1)}function Me(e,n){var s,i;if(1===n.length&&t(n[0])&&(n=n[0]),!n.length)return ve();for(s=n[0],i=1;i<n.length;++i)n[i].isValid()&&!n[i][e](s)||(s=n[i]);return s}function ke(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===Ht.call(cn,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<cn.length;++s)if(e[cn[s]]){if(n)return!1;parseFloat(e[cn[s]])!==g(e[cn[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 Se(e){return e instanceof ke}function De(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ye(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 Oe(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(fn)||["-",0,0],i=60*s[1]+g(s[2]);return 0===i?0:"+"===s[0]?i:-i}function xe(t,n){var s,i;return n._isUTC?(s=n.clone(),i=(_(t)||r(t)?t.valueOf():ve(t).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),e.updateOffset(s,!1),s):ve(t).local()}function Te(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function be(){return!!this.isValid()&&this._isUTC&&0===this._offset}function Pe(e,t){var n,s,r,a=e,u=null;return Se(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:i(e)?(a={},t?a[t]=e:a.milliseconds=e):(u=mn.exec(e))?(n="-"===u[1]?-1:1,a={y:0,d:g(u[Pt])*n,h:g(u[Wt])*n,m:g(u[Rt])*n,s:g(u[Ct])*n,ms:g(De(1e3*u[Ft]))*n}):(u=_n.exec(e))?(n="-"===u[1]?-1:(u[1],1),a={y:We(u[2],n),M:We(u[3],n),w:We(u[4],n),d:We(u[5],n),h:We(u[6],n),m:We(u[7],n),s:We(u[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(r=function(e,t){var n;return e.isValid()&&t.isValid()?(t=xe(t,e),e.isBefore(t)?n=Re(e,t):((n=Re(t,e)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}(ve(a.from),ve(a.to)),(a={}).ms=r.milliseconds,a.M=r.months),s=new ke(a),Se(e)&&o(e,"_locale")&&(s._locale=e._locale),s}function We(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Re(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 Ce(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=Pe(n,s),Fe(this,i,e),this}}function Fe(t,n,s,i){var r=n._milliseconds,a=De(n._days),o=De(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 Ue(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 Ne(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ue(e))&&(this._locale=t),this)}function He(){return this._locale}function Le(e,t){P(0,[e,e.length],0,t)}function Ge(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 Ve(e){return e}function je(e,t,n,s){var i=ue(),r=l().set(s,t);return i[n](r,e)}function Ie(e,t,n){if(i(e)&&(t=e,e=void 0),e=e||"",null!=t)return je(e,t,n,"month");var s,r=[];for(s=0;s<12;s++)r[s]=je(e,s,n,"month");return r}function Ee(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 je(t,(n+a)%7,s,"day");var o,u=[];for(o=0;o<7;o++)u[o]=je(t,(o+a)%7,s,"day");return u}function Ae(e,t,n,s){var i=Pe(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function ze(e){return e<0?Math.floor(e):Math.ceil(e)}function Ze(e){return 4800*e/146097}function $e(e){return 146097*e/4800}function qe(e){return function(){return this.as(e)}}function Je(e){return function(){return this.isValid()?this._data[e]:NaN}}function Be(e){return(e>0)-(e<0)||+e}function Qe(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,s=An(this._milliseconds)/1e3,i=An(this._days),r=An(this._months);t=y((e=y(s/60))/60),s%=60,e%=60;var a=n=y(r/12),o=r%=12,u=i,l=t,d=e,h=s?s.toFixed(3).replace(/\.?0+$/,""):"",c=this.asSeconds();if(!c)return"P0D";var f=c<0?"-":"",m=Be(this._months)!==Be(c)?"-":"",_=Be(this._days)!==Be(c)?"-":"",g=Be(this._milliseconds)!==Be(c)?"-":"";return f+"P"+(a?m+a+"Y":"")+(o?m+o+"M":"")+(u?_+u+"D":"")+(l||d||h?"T":"")+(l?g+l+"H":"")+(d?g+d+"M":"")+(h?g+h+"S":"")}var Xe,Ke;Ke=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 et=e.momentProperties=[],tt=!1,nt={};e.suppressDeprecationWarnings=!1,e.deprecationHandler=null;var st;st=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)o(e,t)&&n.push(t);return n};var it={},rt={},at=/(\[[^\[]*\])|(\\)?([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,ot=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,ut={},lt={},dt=/\d/,ht=/\d\d/,ct=/\d{3}/,ft=/\d{4}/,mt=/[+-]?\d{6}/,_t=/\d\d?/,yt=/\d\d\d\d?/,gt=/\d\d\d\d\d\d?/,pt=/\d{1,3}/,wt=/\d{1,4}/,vt=/[+-]?\d{1,6}/,Mt=/\d+/,kt=/[+-]?\d+/,St=/Z|[+-]\d\d:?\d\d/gi,Dt=/Z|[+-]\d\d(?::?\d\d)?/gi,Yt=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Ot={},xt={},Tt=0,bt=1,Pt=2,Wt=3,Rt=4,Ct=5,Ft=6,Ut=7,Nt=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",kt),F("YY",_t,ht),F("YYYY",wt,ft),F("YYYYY",vt,mt),F("YYYYYY",vt,mt),H(["YYYYY","YYYYYY"],Tt),H("YYYY",function(t,n){n[Tt]=2===t.length?e.parseTwoDigitYear(t):g(t)}),H("YY",function(t,n){n[Tt]=e.parseTwoDigitYear(t)}),H("Y",function(e,t){t[Tt]=parseInt(e,10)}),e.parseTwoDigitYear=function(e){return g(e)+(g(e)>68?1900:2e3)};var Ht,Lt=I("FullYear",!0);Ht=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",_t),F("MM",_t,ht),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[bt]=g(e)-1}),H(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[bt]=i:d(n).invalidMonth=e});var Gt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Vt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),jt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),It=Yt,Et=Yt;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",_t),F("ww",_t,ht),F("W",_t),F("WW",_t,ht),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",_t),F("e",_t),F("E",_t),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 At="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),zt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Zt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),$t=Yt,qt=Yt,Jt=Yt;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",_t),F("h",_t),F("k",_t),F("HH",_t,ht),F("hh",_t,ht),F("kk",_t,ht),F("hmm",yt),F("hmmss",gt),F("Hmm",yt),F("Hmmss",gt),H(["H","HH"],Wt),H(["k","kk"],function(e,t,n){var s=g(e);t[Wt]=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[Wt]=g(e),d(n).bigHour=!0}),H("hmm",function(e,t,n){var s=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s)),d(n).bigHour=!0}),H("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s,2)),t[Ct]=g(e.substr(i)),d(n).bigHour=!0}),H("Hmm",function(e,t,n){var s=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s))}),H("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s,2)),t[Ct]=g(e.substr(i))});var Bt,Qt=I("Hours",!0),Xt={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:Vt,monthsShort:jt,week:{dow:0,doy:6},weekdays:At,weekdaysMin:Zt,weekdaysShort:zt,meridiemParse:/[ap]\.?m?\.?/i},Kt={},en={},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=/^\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)?)?$/,sn=/Z|[+-]\d\d(?::?\d\d)?/,rn=[["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}/]],an=[["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/]],on=/^\/?Date\((\-?\d+)/i,un=/^(?:(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}))$/,ln={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 dn=v("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=ve.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:c()}),hn=v("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=ve.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:c()}),cn=["year","quarter","month","week","day","hour","minute","second","millisecond"];Ye("Z",":"),Ye("ZZ",""),F("Z",Dt),F("ZZ",Dt),H(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Oe(Dt,e)});var fn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var mn=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,_n=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Pe.fn=ke.prototype,Pe.invalid=function(){return Pe(NaN)};var yn=Ce(1,"add"),gn=Ce(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var pn=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}),Le("gggg","weekYear"),Le("ggggg","weekYear"),Le("GGGG","isoWeekYear"),Le("GGGGG","isoWeekYear"),Y("weekYear","gg"),Y("isoWeekYear","GG"),T("weekYear",1),T("isoWeekYear",1),F("G",kt),F("g",kt),F("GG",_t,ht),F("gg",_t,ht),F("GGGG",wt,ft),F("gggg",wt,ft),F("GGGGG",vt,mt),F("ggggg",vt,mt),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",dt),H("Q",function(e,t){t[bt]=3*(g(e)-1)}),P("D",["DD",2],"Do","date"),Y("date","D"),T("date",9),F("D",_t),F("DD",_t,ht),F("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),H(["D","DD"],Pt),H("Do",function(e,t){t[Pt]=g(e.match(_t)[0])});var wn=I("Date",!0);P("DDD",["DDDD",3],"DDDo","dayOfYear"),Y("dayOfYear","DDD"),T("dayOfYear",4),F("DDD",pt),F("DDDD",ct),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",_t),F("mm",_t,ht),H(["m","mm"],Rt);var vn=I("Minutes",!1);P("s",["ss",2],0,"second"),Y("second","s"),T("second",15),F("s",_t),F("ss",_t,ht),H(["s","ss"],Ct);var Mn=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",pt,dt),F("SS",pt,ht),F("SSS",pt,ct);var kn;for(kn="SSSS";kn.length<=9;kn+="S")F(kn,Mt);for(kn="S";kn.length<=9;kn+="S")H(kn,function(e,t){t[Ft]=g(1e3*("0."+e))});var Sn=I("Milliseconds",!1);P("z",0,0,"zoneAbbr"),P("zz",0,0,"zoneName");var Dn=m.prototype;Dn.add=yn,Dn.calendar=function(t,n){var s=t||ve(),i=xe(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,ve(s)))},Dn.clone=function(){return new m(this)},Dn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=xe(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=O(t)){case"year":r=Ue(this,s)/12;break;case"month":r=Ue(this,s);break;case"quarter":r=Ue(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)},Dn.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"))},Dn.format=function(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var n=R(this,t);return this.localeData().postformat(n)},Dn.from=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||ve(e).isValid())?Pe({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Dn.fromNow=function(e){return this.from(ve(),e)},Dn.to=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||ve(e).isValid())?Pe({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Dn.toNow=function(e){return this.to(ve(),e)},Dn.get=function(e){return e=O(e),k(this[e])?this[e]():this},Dn.invalidAt=function(){return d(this).overflow},Dn.isAfter=function(e,t){var n=_(e)?e:ve(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},Dn.isBefore=function(e,t){var n=_(e)?e:ve(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},Dn.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))},Dn.isSame=function(e,t){var n,s=_(e)?e:ve(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()))},Dn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},Dn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},Dn.isValid=function(){return h(this)},Dn.lang=pn,Dn.locale=Ne,Dn.localeData=He,Dn.max=hn,Dn.min=dn,Dn.parsingFlags=function(){return u({},d(this))},Dn.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:rt[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},Dn.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},Dn.subtract=gn,Dn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},Dn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},Dn.toDate=function(){return new Date(this.valueOf())},Dn.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]")},Dn.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)},Dn.toJSON=function(){return this.isValid()?this.toISOString():null},Dn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Dn.unix=function(){return Math.floor(this.valueOf()/1e3)},Dn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Dn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Dn.year=Lt,Dn.isLeapYear=function(){return j(this.year())},Dn.weekYear=function(e){return Ge.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Dn.isoWeekYear=function(e){return Ge.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},Dn.quarter=Dn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},Dn.month=$,Dn.daysInMonth=function(){return z(this.year(),this.month())},Dn.week=Dn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},Dn.isoWeek=Dn.isoWeeks=function(e){var t=X(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},Dn.weeksInYear=function(){var e=this.localeData()._week;return K(this.year(),e.dow,e.doy)},Dn.isoWeeksInYear=function(){return K(this.year(),1,4)},Dn.date=wn,Dn.day=Dn.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},Dn.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")},Dn.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},Dn.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")},Dn.hour=Dn.hours=Qt,Dn.minute=Dn.minutes=vn,Dn.second=Dn.seconds=Mn,Dn.millisecond=Dn.milliseconds=Sn,Dn.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=Oe(Dt,t)))return this}else Math.abs(t)<16&&!s&&(t*=60);return!this._isUTC&&n&&(i=Te(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!n||this._changeInProgress?Fe(this,Pe(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Te(this)},Dn.utc=function(e){return this.utcOffset(0,e)},Dn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Te(this),"m")),this},Dn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Oe(St,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},Dn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?ve(e).utcOffset():0,(this.utcOffset()-e)%60==0)},Dn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Dn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Dn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Dn.isUtc=be,Dn.isUTC=be,Dn.zoneAbbr=function(){return this._isUTC?"UTC":""},Dn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Dn.dates=v("dates accessor is deprecated. Use date instead.",wn),Dn.months=v("months accessor is deprecated. Use month instead",$),Dn.years=v("years accessor is deprecated. Use year instead",Lt),Dn.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()}),Dn.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=ge(e))._a){var t=e._isUTC?l(e._a):ve(e._a);this._isDSTShifted=this.isValid()&&p(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var Yn=D.prototype;Yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return k(s)?s.call(t,n):s},Yn.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])},Yn.invalidDate=function(){return this._invalidDate},Yn.ordinal=function(e){return this._ordinal.replace("%d",e)},Yn.preparse=Ve,Yn.postformat=Ve,Yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return k(i)?i(e,t,n,s):i.replace(/%d/i,e)},Yn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return k(n)?n(t):n.replace(/%s/i,t)},Yn.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)},Yn.months=function(e,n){return e?t(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||Gt).test(n)?"format":"standalone"][e.month()]:t(this._months)?this._months:this._months.standalone},Yn.monthsShort=function(e,n){return e?t(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[Gt.test(n)?"format":"standalone"][e.month()]:t(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Yn.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=Ht.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ht.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ht.call(this._shortMonthsParse,a))?i:-1!==(i=Ht.call(this._longMonthsParse,a))?i:null:-1!==(i=Ht.call(this._longMonthsParse,a))?i:-1!==(i=Ht.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}},Yn.monthsRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsStrictRegex:this._monthsRegex):(o(this,"_monthsRegex")||(this._monthsRegex=Et),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},Yn.monthsShortRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(o(this,"_monthsShortRegex")||(this._monthsShortRegex=It),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},Yn.week=function(e){return X(e,this._week.dow,this._week.doy).week},Yn.firstDayOfYear=function(){return this._week.doy},Yn.firstDayOfWeek=function(){return this._week.dow},Yn.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},Yn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},Yn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},Yn.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=Ht.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.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}},Yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(o(this,"_weekdaysRegex")||(this._weekdaysRegex=$t),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},Yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(o(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qt),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(o(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Jt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},Yn.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 On=Math.abs,xn=qe("ms"),Tn=qe("s"),bn=qe("m"),Pn=qe("h"),Wn=qe("d"),Rn=qe("w"),Cn=qe("M"),Fn=qe("y"),Un=Je("milliseconds"),Nn=Je("seconds"),Hn=Je("minutes"),Ln=Je("hours"),Gn=Je("days"),Vn=Je("months"),jn=Je("years"),In=Math.round,En={ss:44,s:45,m:45,h:22,d:26,M:11},An=Math.abs,zn=ke.prototype;return zn.isValid=function(){return this._isValid},zn.abs=function(){var e=this._data;return this._milliseconds=On(this._milliseconds),this._days=On(this._days),this._months=On(this._months),e.milliseconds=On(e.milliseconds),e.seconds=On(e.seconds),e.minutes=On(e.minutes),e.hours=On(e.hours),e.months=On(e.months),e.years=On(e.years),this},zn.add=function(e,t){return Ae(this,e,t,1)},zn.subtract=function(e,t){return Ae(this,e,t,-1)},zn.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($e(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)}},zn.asMilliseconds=xn,zn.asSeconds=Tn,zn.asMinutes=bn,zn.asHours=Pn,zn.asDays=Wn,zn.asWeeks=Rn,zn.asMonths=Cn,zn.asYears=Fn,zn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12):NaN},zn._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*ze($e(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-=ze($e(i)),s=y(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},zn.clone=function(){return Pe(this)},zn.get=function(e){return e=O(e),this.isValid()?this[e+"s"]():NaN},zn.milliseconds=Un,zn.seconds=Nn,zn.minutes=Hn,zn.hours=Ln,zn.days=Gn,zn.weeks=function(){return y(this.days()/7)},zn.months=Vn,zn.years=jn,zn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=function(e,t,n){var s=Pe(e).abs(),i=In(s.as("s")),r=In(s.as("m")),a=In(s.as("h")),o=In(s.as("d")),u=In(s.as("M")),l=In(s.as("y")),d=i<=En.ss&&["s",i]||i<En.s&&["ss",i]||r<=1&&["m"]||r<En.m&&["mm",r]||a<=1&&["h"]||a<En.h&&["hh",a]||o<=1&&["d"]||o<En.d&&["dd",o]||u<=1&&["M"]||u<En.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)},zn.toISOString=Qe,zn.toString=Qe,zn.toJSON=Qe,zn.locale=Ne,zn.localeData=He,zn.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Qe),zn.lang=pn,P("X",0,0,"unix"),P("x",0,0,"valueOf"),F("x",kt),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.0",Xe=ve,e.fn=Dn,e.min=function(){return Me("isBefore",[].slice.call(arguments,0))},e.max=function(){return Me("isAfter",[].slice.call(arguments,0))},e.now=function(){return Date.now?Date.now():+new Date},e.utc=l,e.unix=function(e){return ve(1e3*e)},e.months=function(e,t){return Ie(e,t,"months")},e.isDate=r,e.locale=ae,e.invalid=c,e.duration=Pe,e.isMoment=_,e.weekdays=function(e,t,n){return Ee(e,t,n,"weekdays")},e.parseZone=function(){return ve.apply(null,arguments).parseZone()},e.localeData=ue,e.isDuration=Se,e.monthsShort=function(e,t){return Ie(e,t,"monthsShort")},e.weekdaysMin=function(e,t,n){return Ee(e,t,n,"weekdaysMin")},e.defineLocale=oe,e.updateLocale=function(e,t){if(null!=t){var n,s=Xt;null!=Kt[e]&&(s=Kt[e]._config),(n=new D(t=S(s,t))).parentLocale=Kt[e],Kt[e]=n,ae(e)}else null!=Kt[e]&&(null!=Kt[e].parentLocale?Kt[e]=Kt[e].parentLocale:null!=Kt[e]&&delete Kt[e]);return Kt[e]},e.locales=function(){return st(Kt)},e.weekdaysShort=function(e,t,n){return Ee(e,t,n,"weekdaysShort")},e.normalizeUnits=O,e.relativeTimeRounding=function(e){return void 0===e?In:"function"==typeof e&&(In=e,!0)},e.relativeTimeThreshold=function(e,t){return void 0!==En[e]&&(void 0===t?En[e]:(En[e]=t,"s"===e&&(En.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=Dn,e});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/page.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/page.min.js
new file mode 100755
index 0000000..57bdd94
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/page.min.js
@@ -0,0 +1 @@
+window.PAGE={handePage:100},document.addEventListener("deviceready",function(){document.addEventListener("backbutton",function(e){if(window.disabledBackButton)return e.preventDefault();var t=document.getElementsByClassName("box-block");t.length?(e.preventDefault(),window.backPage(t[t.length-1].id)):navigator.app.exitApp()},!1)},!1),window.dispatch=function(e,t){return(e="function"==typeof e?e:window[e]).apply(this,t||[])},window.openPage=function(e,t,n){if(2===arguments.length&&(n=t),e.indexOf(".html")<0&&(e+=".html"),document.getElementById(e)){var a=document.getElementsByClassName("box-block");if(a[a.length-1].id===document.getElementById(e).id)return!1;document.getElementById(e).parentNode.removeChild(document.getElementById(e))}var s=new XMLHttpRequest;s.onload=function(){if(4==this.readyState){var a=this.responseText;a=a.replace("backPage()","backPage('"+e+"')");var s=document.getElementsByTagName("body")[0];document.getElementsByClassName("body").length&&(s=document.getElementsByClassName("body")[0]);var d=document.createElement("div");d.setAttribute("class","box-block"),d.setAttribute("id",e),d.innerHTML=a,s.appendChild(d),function(){window.PAGE.handePage++;var a="z-index:"+window.PAGE.handePage,s=";transform: translateY(0px);will-change: transform, -webkit-transform, opacity;transition-duration: 280ms;transition-timing-function: cubic-bezier(0.36,0.66,0.04,1);";2===SO.code&&(s=";transform: translateX(0px);transition-duration: 280ms;"),window.disabledOpenPageEffect&&(s=";opacity: 1;top: 0;");var d=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");d?d+=" "+a+s:d=a+s,document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",d),n&&window.dispatch(n,[t]);var o=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("class");o+=" show";var l=function(){setTimeout(function(){document.getElementById(e)&&document.getElementById(e).querySelectorAll(".page").length?i():l()},10)};l();var m=new CustomEvent("openPage",{detail:{page:e}});document.dispatchEvent(m);var i=function(){setTimeout(function(){document.getElementById(e).getElementsByClassName("page")[0].setAttribute("class",o),setTimeout(function(){var t=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");t=t.replace(s,""),document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",t)},280)},100)}}()}},s.open("GET",e+"?cache="+(new Date).getTime(),!0),document.dispatchEvent(new Event("firedCloseMenu")),s.send()},window.backPage=function(e){if(!e){for(var t=document.querySelectorAll(".page.show"),n={zIndex:-1},a=0;a<t.length;a++){var s=Number(t[a].style.zIndex);n.zIndex<s&&(n.zIndex=s,n.element=t[a])}n.zIndex&&(e=n.element.parentElement.id)}document.getElementById(e).getElementsByClassName("page")[0];var d=";transform: translateY(0px);will-change: transform, -webkit-transform, opacity;transition-duration: 280ms;";window.disabledOpenPageEffect&&(d="");var o=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");o?o+=" "+d:o=d,document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",o);var l=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("class");l+=l.replace("show",""),document.getElementById(e).getElementsByClassName("page")[0].setAttribute("class",l);var m=new CustomEvent("backPage",{detail:{page:e}});document.dispatchEvent(m),setTimeout(function(){var t=document.getElementById(e);t.parentElement.removeChild(t)},window.disabledOpenPageEffect?0:280)};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/popover.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/popover.min.js
new file mode 100755
index 0000000..35eca94
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/popover.min.js
@@ -0,0 +1 @@
+window.openPopover=function(e){var t=event.target.getBoundingClientRect(),o=e,e=document.getElementById(e),n=document.createElement("div");n.className="backdrop backdrop-popover",e.parentNode.appendChild(n),n.addEventListener("click",function(e){window.closePopover(o)}),e.addEventListener("click",function(e){window.closePopover(o)});var i=document.body.offsetWidth-t.left,r=document.body.offsetWidth-i;if(i-=t.width,e.style+=r>250?";top: 110%;right: "+i+"px;transform-origin: right top 0px;transform: scale(1);":";top: 110%;left: "+r+"px;transform-origin: right top 0px;transform: scale(1);",e.classList.add("show"),2===SO.code){e.style.top=t.top+t.height+"px";var s=document.createElement("div");s.classList.add("popover-arrow"),e.parentNode.appendChild(s),s.setAttribute("style","top:"+(t.top+t.height-5)+"px;left:"+(t.left+t.width/2-7)+"px")}else{var d=e.clientHeight,a=e.clientWidth;e.style.height=0,e.style.width=0,e.style.top=t.top+"px",setTimeout(function(){var t=e.getAttribute("style");t+=" ;-webkit-transition: all 200ms ease;transition: all 200ms ease;",e.setAttribute("style",t),e.style.height=d+"px",e.style.width=a+"px"})}var p=new CustomEvent("popoverOpened");document.dispatchEvent(p)},window.closePopover=function(e){var e=document.getElementById(e),t=0;2!==SO.code&&(e.style.opacity=0,t=200),setTimeout(function(){var t=document.getElementsByClassName("popover-arrow");t.length&&t[0].parentNode.removeChild(t[0]),e.classList.remove("show");var o=e.parentNode.getElementsByClassName("backdrop-popover");o&&o.length&&(o=o[0])&&o.parentNode&&o.parentNode.removeChild(o);var n=new CustomEvent("popoverClosed");document.dispatchEvent(n)},t)};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/progress-circle.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/progress-circle.min.js
new file mode 100755
index 0000000..57ad8b6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/progress-circle.min.js
@@ -0,0 +1 @@
+window.ProgressCircle={rebind:function(){for(var t=document.querySelectorAll(".progress-circle"),e=0;e<t.length;e++)t[e].classList.remove("binded"),t[e].innerHTML="";this.bind()},bind:function(){for(var t=document.querySelectorAll(".progress-circle:not(.binded)"),e=0;e<t.length;e++){var i={};i.value=Number(t[e].getAttribute("value")),i.maxValue=Number(t[e].getAttribute("maxValue"))||100,i.showValue="1"===t[e].getAttribute("showValue")||"true"===t[e].getAttribute("showValue")||!1,i.title=t[e].getAttribute("title")||"",i.subTitle=t[e].getAttribute("subTitle")||"",i.text=t[e].getAttribute("text")||"",i.color=t[e].getAttribute("color")||"blue",i.textColor=t[e].getAttribute("textColor")||"grey-800",i.textWeight=t[e].getAttribute("textWeight")||"normal",i.titleWeight=t[e].getAttribute("titleWeight")||"normal",i.subTitleWeight=t[e].getAttribute("subTitleWeight")||"normal",i.titleColor=t[e].getAttribute("titleColor")||"grey-500",i.subTitleColor=t[e].getAttribute("subTitleColor")||"grey-300",i.width=t[e].getAttribute("width")||"100%",i.height=t[e].getAttribute("height")||"300px",i.trailColor=t[e].getAttribute("trailColor")||"grey",i.strokeWidth=t[e].getAttribute("strokeWidth")||"1",i.trailWidth=t[e].getAttribute("trailWidth")||"1",i.textSize=t[e].getAttribute("textSize")||"16px",i.titleSize=t[e].getAttribute("titleSize")||"14px",i.subTitleSize=t[e].getAttribute("subTitleSize")||"12px",i.fill=t[e].getAttribute("fill")||"",i.padding=t[e].getAttribute("padding")||"0",i.durationAnimate=Number(t[e].getAttribute("duration")||"800"),this.create(t[e],i)}},create:function(t,e){t.classList.contains("binded")||(t.classList.add("binded"),t.classList.contains("progress-circle")||t.classList.add("progress-circle-js"),e.value=e.value||0,e.maxValue=e.maxValue||100,e.showValue=e.showValue||!1,e.title=e.title||"",e.subTitle=e.subTitle||"",e.text=e.text||"",e.color=e.color||"blue",e.textColor=e.textColor||"grey-800",e.textWeight=e.textWeight||"normal",e.titleWeight=e.titleWeight||"normal",e.subTitleWeight=e.subTitleWeight||"normal",e.titleColor=e.titleColor||"grey-500",e.subTitleColor=e.subTitleColor||"grey-300",e.width=e.width||"100%",e.height=e.height||"300px",e.trailColor=e.trailColor||"grey",e.strokeWidth=e.strokeWidth||"1",e.trailWidth=e.trailWidth||"1",e.textSize=e.textSize||"16px",e.titleSize=e.titleSize||"14px",e.subTitleSize=e.subTitleSize||"12px",e.fill=e.fill||"",e.padding=e.padding||"0",e.durationAnimate=e.durationAnimate||"800",t.style.width=e.width,t.style.height=e.height,t.progressCircle={},t.progressCircle.bar=new ProgressBar.Circle(t,{color:colorsMobileUI[e.color],trailColor:colorsMobileUI[e.trailColor],strokeWidth:e.strokeWidth,trailWidth:e.trailWidth,easing:"easeInOut",duration:e.durationAnimate,fill:e.fill,text:{autoStyleContainer:!0,style:{color:colorsMobileUI[e.textColor],position:"absolute",fontSize:e.textSize,fontWeight:e.textWeight,left:"50%",top:"50%",padding:0,margin:0,transform:{prefix:!0,value:"translate(-50%, -50%)"}}},svgStyle:{display:"block",width:e.width,height:e.height,padding:e.padding},from:{color:colorsMobileUI[e.color],width:e.strokeWidth},to:{color:colorsMobileUI[e.color],width:e.strokeWidth},step:function(t,i){i.path.setAttribute("stroke",t.color),i.path.setAttribute("stroke-width",t.width);var l=Math.round(i.value()*e.maxValue);e.showValue&&(l=e.value);var r="";if(e.title){o='style="';e.titleSize&&(o+=";font-size:"+e.titleSize),e.titleWeight&&(o+=";font-weight:"+e.titleWeight),e.titleColor&&(o+=";color:"+colorsMobileUI[e.titleColor]),r+="<div "+(o+='"')+' class="progress-circle-title">'+e.title+"</div>"}if(r+=l+e.text,e.subTitle){var o='style="';e.subTitleSize&&(o+=";font-size:"+e.subTitleSize),e.subTitleWeight&&(o+=";font-weight:"+e.subTitleWeight),e.subTitleColor&&(o+=";color:"+colorsMobileUI[e.subTitleColor]),r+="<div "+(o+='"')+' class="progress-circle-subtitle">'+e.subTitle+"</div>"}i.setText(r)}}),t.progressCircle.update=function(t){var i=0;t<=e.maxValue&&t>=0?i=t/e.maxValue:t<0?console.warn("Value for progress circle is too small. (Requested value is "+t+")"):(console.warn("Value for progress circle is too high. Maximum is "+e.maxValue+" and requested value is "+t+". (Value set to maximum for now.)"),i=1),this.bar.animate(i)},t.progressCircle.update(e.value))}};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/progress-circular.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/progress-circular.min.js
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/progress-circular.min.js
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/progress-semicircle.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/progress-semicircle.min.js
new file mode 100755
index 0000000..70be9cf
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/progress-semicircle.min.js
@@ -0,0 +1 @@
+window.ProgressSemicircle={rebind:function(){for(var t=document.querySelectorAll(".progress-semicircle"),e=0;e<t.length;e++)t[e].classList.remove("binded"),t[e].innerHTML="";this.bind()},bind:function(){for(var t=document.querySelectorAll(".progress-semicircle:not(.binded)"),e=0;e<t.length;e++){var i={};i.value=Number(t[e].getAttribute("value")),i.maxValue=Number(t[e].getAttribute("maxValue"))||100,i.title=t[e].getAttribute("title")||"",i.subTitle=t[e].getAttribute("subTitle")||"",i.text=t[e].getAttribute("text")||"",i.color=t[e].getAttribute("color")||"blue",i.textColor=t[e].getAttribute("textColor")||"grey-800",i.textWeight=t[e].getAttribute("textWeight")||"normal",i.titleWeight=t[e].getAttribute("titleWeight")||"normal",i.titleLineHeight=t[e].getAttribute("titleLineHeight")||"normal",i.subTitleWeight=t[e].getAttribute("subTitleWeight")||"normal",i.titleColor=t[e].getAttribute("titleColor")||"grey-500",i.subTitleColor=t[e].getAttribute("subTitleColor")||"grey-300",i.width=t[e].getAttribute("width")||"100%",i.height=t[e].getAttribute("height")||"300px",i.trailColor=t[e].getAttribute("trailColor")||"grey",i.strokeWidth=t[e].getAttribute("strokeWidth")||"1",i.trailWidth=t[e].getAttribute("trailWidth")||"1",i.textSize=t[e].getAttribute("textSize")||"16px",i.titleSize=t[e].getAttribute("titleSize")||"14px",i.subTitleSize=t[e].getAttribute("subTitleSize")||"12px",i.fill=t[e].getAttribute("fill")||"",i.padding=t[e].getAttribute("padding")||"0",i.textMargin=t[e].getAttribute("textMargin")||"100px 0",i.durationAnimate=Number(t[e].getAttribute("duration")||"800"),this.create(t[e],i)}},create:function(t,e){t.classList.contains("binded")||(t.classList.add("binded"),t.classList.contains("progress-semicircle")||t.classList.add("progress-semicircle-js"),e.value=e.value||0,e.maxValue=e.maxValue||100,e.title=e.title||"",e.subTitle=e.subTitle||"",e.text=e.text||"",e.color=e.color||"blue",e.textColor=e.textColor||"grey-800",e.textWeight=e.textWeight||"normal",e.titleWeight=e.titleWeight||"normal",e.subTitleWeight=e.subTitleWeight||"normal",e.titleColor=e.titleColor||"grey-500",e.subTitleColor=e.subTitleColor||"grey-300",e.width=e.width||"100%",e.height=e.height||"300px",e.trailColor=e.trailColor||"grey",e.strokeWidth=e.strokeWidth||"1",e.trailWidth=e.trailWidth||"1",e.textSize=e.textSize||"16px",e.titleSize=e.titleSize||"14px",e.subTitleSize=e.subTitleSize||"12px",e.fill=e.fill||"",e.padding=e.padding||"0",e.durationAnimate=e.durationAnimate||"800",e.textMargin=e.textMargin||"100px 0",t.style.width=e.width,t.style.height=e.height,t.progressSemicircle={},t.progressSemicircle.bar=new ProgressBar.SemiCircle(t,{color:colorsMobileUI[e.color],trailColor:colorsMobileUI[e.trailColor],strokeWidth:e.strokeWidth,trailWidth:e.trailWidth,easing:"easeInOut",duration:e.durationAnimate,fill:e.fill,text:{alignToBottom:!1,style:{color:colorsMobileUI[e.textColor],position:"absolute",fontSize:e.textSize,fontWeight:e.textWeight,left:"50%",padding:0,margin:e.textMargin}},svgStyle:{display:"block",width:e.width,height:e.height,padding:e.padding},from:{color:colorsMobileUI[e.color],width:e.strokeWidth},to:{color:colorsMobileUI[e.color],width:e.strokeWidth},step:function(t,i){i.path.setAttribute("stroke",t.color),i.path.setAttribute("stroke-width",t.width);var l=Math.round(i.value()*e.maxValue),r="";if(e.title){o='style="';e.titleSize&&(o+=";font-size:"+e.titleSize),e.titleWeight&&(o+=";font-weight:"+e.titleWeight),e.titleLineHeight&&(o+=";line-height:"+e.titleLineHeight),e.titleColor&&(o+=";color:"+colorsMobileUI[e.titleColor]),r+="<div "+(o+='"')+' class="progress-semicircle-title">'+e.title+"</div>"}if(r+=l+e.text,e.subTitle){var o='style="';e.subTitleSize&&(o+=";font-size:"+e.subTitleSize),e.subTitleWeight&&(o+=";font-weight:"+e.subTitleWeight),e.subTitleColor&&(o+=";color:"+colorsMobileUI[e.subTitleColor]),r+="<div "+(o+='"')+' class="progress-semicircle-subtitle">'+e.subTitle+"</div>"}i.setText(r)}}),t.progressSemicircle.update=function(t){var i=0;t<=e.maxValue&&t>=0?i=t/e.maxValue:t<0?console.warn("Value for progress semicircle is too small. (Requested value is "+t+")"):(console.warn("Value for progress semicircle is too high. Maximum is "+e.maxValue+" and requested value is "+t+". (Value set to maximum for now.)"),i=1),this.bar.animate(i)},t.progressSemicircle.update(e.value))}};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/progressbarjs.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/progressbarjs.min.js
new file mode 100755
index 0000000..24920e4
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/progressbarjs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).ProgressBar=t()}}(function(){return function t(e,n,i){function r(s,a){if(!n[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=n[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return r(n||t)},c,c.exports,t,e,n,i)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s<i.length;s++)r(i[s]);return r}({1:[function(t,e,n){(function(){var t=this||Function("return this")(),i=function(){"use strict";function i(){}function r(t,e){var n;for(n in t)Object.hasOwnProperty.call(t,n)&&e(n)}function o(t,e){return r(e,function(n){t[n]=e[n]}),t}function s(t,e){r(e,function(n){void 0===t[n]&&(t[n]=e[n])})}function a(t,e,n,i,r,o,s){var a,h,c,p=o>t?0:(t-o)/r;for(a in e)e.hasOwnProperty(a)&&(h=s[a],c="function"==typeof h?h:f[h],e[a]=u(n[a],i[a],c,p));return e}function u(t,e,n,i){return t+(e-t)*n(i)}function h(t,e){var n=l.prototype.filter,i=t._filterArgs;r(n,function(r){void 0!==n[r][e]&&n[r][e].apply(t,i)})}function c(t,e,n,i,r,o,s,u,c,p,l){m=e+n+i,v=Math.min(l||y(),m),S=v>=m,x=i-(m-v),t.isPlaying()&&(S?(c(s,t._attachment,x),t.stop(!0)):(t._scheduleId=p(t._timeoutHandler,g),h(t,"beforeTween"),e+n>v?a(1,r,o,s,1,1,u):a(v,r,o,s,i,e+n,u),h(t,"afterTween"),c(r,t._attachment,x)))}function p(t,e){var n={},i=typeof e;return"string"===i||"function"===i?r(t,function(t){n[t]=e}):r(t,function(t){n[t]||(n[t]=e[t]||d)}),n}function l(t,e){this._currentState=t||{},this._configured=!1,this._scheduleFunction=_,void 0!==e&&this.setConfig(e)}var f,_,d="linear",g=1e3/60,w=Date.now?Date.now:function(){return+new Date},y="undefined"!=typeof SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:w;_="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var m,v,S,x;return l.prototype.tween=function(t){return this._isTweening?this:(void 0===t&&this._configured||this.setConfig(t),this._timestamp=y(),this._start(this.get(),this._attachment),this.resume())},l.prototype.setConfig=function(t){t=t||{},this._configured=!0,this._attachment=t.attachment,this._pausedAtTime=null,this._scheduleId=null,this._delay=t.delay||0,this._start=t.start||i,this._step=t.step||i,this._finish=t.finish||i,this._duration=t.duration||500,this._currentState=o({},t.from)||this.get(),this._originalState=this.get(),this._targetState=o({},t.to)||this.get();var e=this;this._timeoutHandler=function(){c(e,e._timestamp,e._delay,e._duration,e._currentState,e._originalState,e._targetState,e._easing,e._step,e._scheduleFunction)};var n=this._currentState,r=this._targetState;return s(r,n),this._easing=p(n,t.easing||d),this._filterArgs=[n,this._originalState,r,this._easing],h(this,"tweenCreated"),this},l.prototype.get=function(){return o({},this._currentState)},l.prototype.set=function(t){this._currentState=t},l.prototype.pause=function(){return this._pausedAtTime=y(),this._isPaused=!0,this},l.prototype.resume=function(){return this._isPaused&&(this._timestamp+=y()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0,this._timeoutHandler(),this},l.prototype.seek=function(t){t=Math.max(t,0);var e=y();return this._timestamp+t===0?this:(this._timestamp=e-t,this.isPlaying()||(this._isTweening=!0,this._isPaused=!1,c(this,this._timestamp,this._delay,this._duration,this._currentState,this._originalState,this._targetState,this._easing,this._step,this._scheduleFunction,e),this.pause()),this)},l.prototype.stop=function(e){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=i,(t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.oCancelAnimationFrame||t.msCancelAnimationFrame||t.mozCancelRequestAnimationFrame||t.clearTimeout)(this._scheduleId),e&&(h(this,"beforeTween"),a(1,this._currentState,this._originalState,this._targetState,1,0,this._easing),h(this,"afterTween"),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState,this._attachment)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(t){this._scheduleFunction=t},l.prototype.dispose=function(){var t;for(t in this)this.hasOwnProperty(t)&&delete this[t]},l.prototype.filter={},l.prototype.formula={linear:function(t){return t}},f=l.prototype.formula,o(l,{now:y,each:r,tweenProps:a,tweenProp:u,applyFilter:h,shallowCopy:o,defaults:s,composeEasingObject:p}),"function"==typeof SHIFTY_DEBUG_NOW&&(t.timeoutHandler=c),"object"==typeof n?e.exports=l:void 0===t.Tweenable&&(t.Tweenable=l),l}();i.shallowCopy(i.prototype.formula,{easeInQuad:function(t){return Math.pow(t,2)},easeOutQuad:function(t){return-(Math.pow(t-1,2)-1)},easeInOutQuad:function(t){return(t/=.5)<1?.5*Math.pow(t,2):-.5*((t-=2)*t-2)},easeInCubic:function(t){return Math.pow(t,3)},easeOutCubic:function(t){return Math.pow(t-1,3)+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)},easeInQuart:function(t){return Math.pow(t,4)},easeOutQuart:function(t){return-(Math.pow(t-1,4)-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},easeInQuint:function(t){return Math.pow(t,5)},easeOutQuint:function(t){return Math.pow(t-1,5)+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*Math.pow(t,5):.5*(Math.pow(t-2,5)+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-Math.pow(t-1,2))},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeOutBounce:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},elastic:function(t){return-1*Math.pow(4,-8*t)*Math.sin((6*t-1)*(2*Math.PI)/2)+1},swingFromTo:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},swingFrom:function(t){var e=1.70158;return t*t*((e+1)*t-e)},swingTo:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},bounce:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bouncePast:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?2-(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?2-(7.5625*(t-=2.25/2.75)*t+.9375):2-(7.5625*(t-=2.625/2.75)*t+.984375)},easeFromTo:function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},easeFrom:function(t){return Math.pow(t,4)},easeTo:function(t){return Math.pow(t,.25)}}),function(){function t(t,e,n,i,r,o){function s(t){return((c*t+p)*t+l)*t}function a(t){return(3*c*t+2*p)*t+l}function u(t,e){return function(t){return((f*t+_)*t+d)*t}(function(t,e){var n,i,r,o,u,c;for(r=t,c=0;8>c;c++){if(o=s(r)-t,h(o)<e)return r;if(u=a(r),h(u)<1e-6)break;r-=o/u}if(n=0,i=1,r=t,n>r)return n;if(r>i)return i;for(;i>n;){if(o=s(r),h(o-t)<e)return r;t>o?n=r:i=r,r=.5*(i-n)+n}return r}(t,e))}function h(t){return t>=0?t:0-t}var c=0,p=0,l=0,f=0,_=0,d=0;return l=3*e,p=3*(i-e)-l,c=1-l-p,d=3*n,_=3*(r-n)-d,f=1-d-_,u(t,function(t){return 1/(200*t)}(o))}function e(e,n,i,r){return function(o){return t(o,e,n,i,r,1)}}i.setBezierFunction=function(t,n,r,o,s){var a=e(n,r,o,s);return a.displayName=t,a.x1=n,a.y1=r,a.x2=o,a.y2=s,i.prototype.formula[t]=a},i.unsetBezierFunction=function(t){delete i.prototype.formula[t]}}(),function(){var t=new i;t._filterArgs=[],i.interpolate=function(e,n,r,o,s){var a=i.shallowCopy({},e),u=s||0,h=i.composeEasingObject(e,o||"linear");t.set({});var c=t._filterArgs;c.length=0,c[0]=a,c[1]=e,c[2]=n,c[3]=h,i.applyFilter(t,"tweenCreated"),i.applyFilter(t,"beforeTween");var p=function(t,e,n,r,o,s){return i.tweenProps(r,e,t,n,1,s,o)}(e,a,n,r,h,u);return i.applyFilter(t,"afterTween"),p}}(),function(t){function e(e){t.each(e,function(t){var i=e[t];"string"==typeof i&&i.match(w)&&(e[t]=function(t){return r(w,t,n)}(i))})}function n(t){var e=function(t){return 3===(t=t.replace(/#/,"")).length&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),m[0]=i(t.substr(0,2)),m[1]=i(t.substr(2,2)),m[2]=i(t.substr(4,2)),m}(t);return"rgb("+e[0]+","+e[1]+","+e[2]+")"}function i(t){return parseInt(t,16)}function r(t,e,n){var i=e.match(t),r=e.replace(t,y);if(i)for(var o,s=i.length,a=0;s>a;a++)o=i.shift(),r=r.replace(y,n(o));return r}function o(t){for(var e=t.match(_),n=e.length,i=t.match(g)[0],r=0;n>r;r++)i+=parseInt(e[r],10)+",";return i=i.slice(0,-1)+")"}function s(e){var n={};return t.each(e,function(t){var i=e[t];if("string"==typeof i){var r=h(i);n[t]={formatString:function(t){var e=t.match(f);return e?(1===e.length||t[0].match(l))&&e.unshift(""):e=["",""],e.join(y)}(i),chunkNames:function(t,e){var n,i=[],r=t.length;for(n=0;r>n;n++)i.push("_"+e+"_"+n);return i}(r,t)}}}),n}function a(e,n){t.each(n,function(t){for(var i=h(e[t]),r=i.length,o=0;r>o;o++)e[n[t].chunkNames[o]]=+i[o];delete e[t]})}function u(e,n){t.each(n,function(t){var i=e[t],s=function(t,e){v.length=0;for(var n=e.length,i=0;n>i;i++)v.push(t[e[i]]);return v}(function(t,e){for(var n,i={},r=e.length,o=0;r>o;o++)n=e[o],i[n]=t[n],delete t[n];return i}(e,n[t].chunkNames),n[t].chunkNames);i=function(t,e){for(var n=t,i=e.length,r=0;i>r;r++)n=n.replace(y,+e[r].toFixed(4));return n}(n[t].formatString,s),e[t]=function(t){return r(d,t,o)}(i)})}function h(t){return t.match(_)}function c(e,n){t.each(n,function(t){var i,r=n[t].chunkNames,o=r.length,s=e[t];if("string"==typeof s){var a=s.split(" "),u=a[a.length-1];for(i=0;o>i;i++)e[r[i]]=a[i]||u}else for(i=0;o>i;i++)e[r[i]]=s;delete e[t]})}function p(e,n){t.each(n,function(t){var i=n[t].chunkNames,r=i.length,o=e[i[0]];if("string"===typeof o){for(var s="",a=0;r>a;a++)s+=" "+e[i[a]],delete e[i[a]];e[t]=s.substr(1)}else e[t]=o})}var l=/(\d|\-|\.)/,f=/([^\-0-9\.]+)/g,_=/[0-9.\-]+/g,d=new RegExp("rgb\\("+_.source+/,\s*/.source+_.source+/,\s*/.source+_.source+"\\)","g"),g=/^.*\(/,w=/#([0-9]|[a-f]){3,6}/gi,y="VAL",m=[],v=[];t.prototype.filter.token={tweenCreated:function(t,n,i,r){e(t),e(n),e(i),this._tokenData=s(t)},beforeTween:function(t,e,n,i){c(i,this._tokenData),a(t,this._tokenData),a(e,this._tokenData),a(n,this._tokenData)},afterTween:function(t,e,n,i){u(t,this._tokenData),u(e,this._tokenData),u(n,this._tokenData),p(i,this._tokenData)}}}(i)}).call(null)},{}],2:[function(t,e,n){var i=t("./shape"),r=t("./utils"),o=function(t,e){this._pathTemplate="M 50,50 m 0,-{radius} a {radius},{radius} 0 1 1 0,{2radius} a {radius},{radius} 0 1 1 0,-{2radius}",this.containerAspectRatio=1,i.apply(this,arguments)};(o.prototype=new i).constructor=o,o.prototype._pathString=function(t){var e=t.strokeWidth;t.trailWidth&&t.trailWidth>t.strokeWidth&&(e=t.trailWidth);var n=50-e/2;return r.render(this._pathTemplate,{radius:n,"2radius":2*n})},o.prototype._trailString=function(t){return this._pathString(t)},e.exports=o},{"./shape":7,"./utils":8}],3:[function(t,e,n){var i=t("./shape"),r=t("./utils"),o=function(t,e){this._pathTemplate="M 0,{center} L 100,{center}",i.apply(this,arguments)};(o.prototype=new i).constructor=o,o.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 "+e.strokeWidth),t.setAttribute("preserveAspectRatio","none")},o.prototype._pathString=function(t){return r.render(this._pathTemplate,{center:t.strokeWidth/2})},o.prototype._trailString=function(t){return this._pathString(t)},e.exports=o},{"./shape":7,"./utils":8}],4:[function(t,e,n){e.exports={Line:t("./line"),Circle:t("./circle"),SemiCircle:t("./semicircle"),Path:t("./path"),Shape:t("./shape"),utils:t("./utils")}},{"./circle":2,"./line":3,"./path":5,"./semicircle":6,"./shape":7,"./utils":8}],5:[function(t,e,n){var i=t("shifty"),r=t("./utils"),o={easeIn:"easeInCubic",easeOut:"easeOutCubic",easeInOut:"easeInOutCubic"},s=function t(e,n){if(!(this instanceof t))throw new Error("Constructor was called without new keyword");n=r.extend({duration:800,easing:"linear",from:{},to:{},step:function(){}},n);var i;i=r.isString(e)?document.querySelector(e):e,this.path=i,this._opts=n,this._tweenable=null;var o=this.path.getTotalLength();this.path.style.strokeDasharray=o+" "+o,this.set(0)};s.prototype.value=function(){var t=1-this._getComputedDashOffset()/this.path.getTotalLength();return parseFloat(t.toFixed(6),10)},s.prototype.set=function(t){this.stop(),this.path.style.strokeDashoffset=this._progressToOffset(t);var e=this._opts.step;if(r.isFunction(e)){var n=this._easing(this._opts.easing);e(this._calculateTo(t,n),this._opts.shape||this,this._opts.attachment)}},s.prototype.stop=function(){this._stopTween(),this.path.style.strokeDashoffset=this._getComputedDashOffset()},s.prototype.animate=function(t,e,n){e=e||{},r.isFunction(e)&&(n=e,e={});var o=r.extend({},e),s=r.extend({},this._opts);e=r.extend(s,e);var a=this._easing(e.easing),u=this._resolveFromAndTo(t,a,o);this.stop(),this.path.getBoundingClientRect();var h=this._getComputedDashOffset(),c=this._progressToOffset(t),p=this;this._tweenable=new i,this._tweenable.tween({from:r.extend({offset:h},u.from),to:r.extend({offset:c},u.to),duration:e.duration,easing:a,step:function(t){p.path.style.strokeDashoffset=t.offset;var n=e.shape||p;e.step(t,n,e.attachment)},finish:function(t){r.isFunction(n)&&n()}})},s.prototype._getComputedDashOffset=function(){var t=window.getComputedStyle(this.path,null);return parseFloat(t.getPropertyValue("stroke-dashoffset"),10)},s.prototype._progressToOffset=function(t){var e=this.path.getTotalLength();return e-t*e},s.prototype._resolveFromAndTo=function(t,e,n){return n.from&&n.to?{from:n.from,to:n.to}:{from:this._calculateFrom(e),to:this._calculateTo(t,e)}},s.prototype._calculateFrom=function(t){return i.interpolate(this._opts.from,this._opts.to,this.value(),t)},s.prototype._calculateTo=function(t,e){return i.interpolate(this._opts.from,this._opts.to,t,e)},s.prototype._stopTween=function(){null!==this._tweenable&&(this._tweenable.stop(),this._tweenable=null)},s.prototype._easing=function(t){return o.hasOwnProperty(t)?o[t]:t},e.exports=s},{"./utils":8,shifty:1}],6:[function(t,e,n){var i=t("./shape"),r=t("./circle"),o=t("./utils"),s=function(t,e){this._pathTemplate="M 50,50 m -{radius},0 a {radius},{radius} 0 1 1 {2radius},0",this.containerAspectRatio=2,i.apply(this,arguments)};(s.prototype=new i).constructor=s,s.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 50")},s.prototype._initializeTextContainer=function(t,e,n){t.text.style&&(n.style.top="auto",n.style.bottom="0",t.text.alignToBottom?o.setStyle(n,"transform","translate(-50%, 0)"):o.setStyle(n,"transform","translate(-50%, 50%)"))},s.prototype._pathString=r.prototype._pathString,s.prototype._trailString=r.prototype._trailString,e.exports=s},{"./circle":2,"./shape":7,"./utils":8}],7:[function(t,e,n){var i=t("./path"),r=t("./utils"),o="Object is destroyed",s=function t(e,n){if(!(this instanceof t))throw new Error("Constructor was called without new keyword");if(0!==arguments.length){this._opts=r.extend({color:"#555",strokeWidth:1,trailColor:null,trailWidth:null,fill:null,text:{style:{color:null,position:"absolute",left:"50%",top:"50%",padding:0,margin:0,transform:{prefix:!0,value:"translate(-50%, -50%)"}},autoStyleContainer:!0,alignToBottom:!0,value:null,className:"progressbar-text"},svgStyle:{display:"block",width:"100%"},warnings:!1},n,!0),r.isObject(n)&&void 0!==n.svgStyle&&(this._opts.svgStyle=n.svgStyle),r.isObject(n)&&r.isObject(n.text)&&void 0!==n.text.style&&(this._opts.text.style=n.text.style);var o,s=this._createSvgView(this._opts);if(!(o=r.isString(e)?document.querySelector(e):e))throw new Error("Container does not exist: "+e);this._container=o,this._container.appendChild(s.svg),this._opts.warnings&&this._warnContainerAspectRatio(this._container),this._opts.svgStyle&&r.setStyles(s.svg,this._opts.svgStyle),this.svg=s.svg,this.path=s.path,this.trail=s.trail,this.text=null;var a=r.extend({attachment:void 0,shape:this},this._opts);this._progressPath=new i(s.path,a),r.isObject(this._opts.text)&&null!==this._opts.text.value&&this.setText(this._opts.text.value)}};s.prototype.animate=function(t,e,n){if(null===this._progressPath)throw new Error(o);this._progressPath.animate(t,e,n)},s.prototype.stop=function(){if(null===this._progressPath)throw new Error(o);void 0!==this._progressPath&&this._progressPath.stop()},s.prototype.destroy=function(){if(null===this._progressPath)throw new Error(o);this.stop(),this.svg.parentNode.removeChild(this.svg),this.svg=null,this.path=null,this.trail=null,this._progressPath=null,null!==this.text&&(this.text.parentNode.removeChild(this.text),this.text=null)},s.prototype.set=function(t){if(null===this._progressPath)throw new Error(o);this._progressPath.set(t)},s.prototype.value=function(){if(null===this._progressPath)throw new Error(o);return void 0===this._progressPath?0:this._progressPath.value()},s.prototype.setText=function(t){if(null===this._progressPath)throw new Error(o);null===this.text&&(this.text=this._createTextContainer(this._opts,this._container),this._container.appendChild(this.text)),r.isObject(t)?(r.removeChildren(this.text),this.text.appendChild(t)):this.text.innerHTML=t},s.prototype._createSvgView=function(t){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");this._initializeSvg(e,t);var n=null;(t.trailColor||t.trailWidth)&&(n=this._createTrail(t),e.appendChild(n));var i=this._createPath(t);return e.appendChild(i),{svg:e,path:i,trail:n}},s.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 100")},s.prototype._createPath=function(t){var e=this._pathString(t);return this._createPathElement(e,t)},s.prototype._createTrail=function(t){var e=this._trailString(t),n=r.extend({},t);return n.trailColor||(n.trailColor="#eee"),n.trailWidth||(n.trailWidth=n.strokeWidth),n.color=n.trailColor,n.strokeWidth=n.trailWidth,n.fill=null,this._createPathElement(e,n)},s.prototype._createPathElement=function(t,e){var n=document.createElementNS("http://www.w3.org/2000/svg","path");return n.setAttribute("d",t),n.setAttribute("stroke",e.color),n.setAttribute("stroke-width",e.strokeWidth),e.fill?n.setAttribute("fill",e.fill):n.setAttribute("fill-opacity","0"),n},s.prototype._createTextContainer=function(t,e){var n=document.createElement("div");n.className=t.text.className;var i=t.text.style;return i&&(t.text.autoStyleContainer&&(e.style.position="relative"),r.setStyles(n,i),i.color||(n.style.color=t.color)),this._initializeTextContainer(t,e,n),n},s.prototype._initializeTextContainer=function(t,e,n){},s.prototype._pathString=function(t){throw new Error("Override this function for each progress bar")},s.prototype._trailString=function(t){throw new Error("Override this function for each progress bar")},s.prototype._warnContainerAspectRatio=function(t){if(this.containerAspectRatio){var e=window.getComputedStyle(t,null),n=parseFloat(e.getPropertyValue("width"),10),i=parseFloat(e.getPropertyValue("height"),10);r.floatEquals(this.containerAspectRatio,n/i)||(console.warn("Incorrect aspect ratio of container","#"+t.id,"detected:",e.getPropertyValue("width")+"(width)","/",e.getPropertyValue("height")+"(height)","=",n/i),console.warn("Aspect ratio of should be",this.containerAspectRatio))}},e.exports=s},{"./path":5,"./utils":8}],8:[function(t,e,n){function i(t,e,n){t=t||{},e=e||{},n=n||!1;for(var r in e)if(e.hasOwnProperty(r)){var o=t[r],a=e[r];n&&s(o)&&s(a)?t[r]=i(o,a,n):t[r]=a}return t}function r(t,e,n){for(var i=t.style,r=0;r<u.length;++r){i[u[r]+o(e)]=n}i[e]=n}function o(t){return t.charAt(0).toUpperCase()+t.slice(1)}function s(t){if(function(t){return"[object Array]"===Object.prototype.toString.call(t)}(t))return!1;return"object"===typeof t&&!!t}function a(t,e){for(var n in t)if(t.hasOwnProperty(n)){e(t[n],n)}}var u="Webkit Moz O ms".split(" "),h=.001;e.exports={extend:i,render:function(t,e){var n=t;for(var i in e)if(e.hasOwnProperty(i)){var r=e[i],o="\\{"+i+"\\}",s=new RegExp(o,"g");n=n.replace(s,r)}return n},setStyle:r,setStyles:function(t,e){a(e,function(e,n){null!==e&&void 0!==e&&(s(e)&&!0===e.prefix?r(t,n,e.value):t.style[n]=e)})},capitalize:o,isString:function(t){return"string"==typeof t||t instanceof String},isFunction:function(t){return"function"==typeof t},isObject:s,forEachObject:a,floatEquals:function(t,e){return Math.abs(t-e)<h},removeChildren:function(t){for(;t.firstChild;)t.removeChild(t.firstChild)}}},{}]},{},[4])(4)});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/pulltorefresh.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/pulltorefresh.min.js
new file mode 100755
index 0000000..5b273cd
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/pulltorefresh.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.PullToRefresh=t()}(this,function(){function e(){function e(e){var t=r.handlers.filter(function(t){return t.contains(e.target)})[0];r.enable=!!t,t&&"pending"===r.state&&(o=i.setupDOM(t),t.shouldPullToRefresh()&&(r.pullStartY=e.touches[0].screenY),clearTimeout(r.timeout),i.update(t))}function t(e){o&&o.ptrElement&&r.enable&&(r.pullStartY?r.pullMoveY=e.touches[0].screenY:o.shouldPullToRefresh()&&(r.pullStartY=e.touches[0].screenY),"refreshing"!==r.state?("pending"===r.state&&(o.ptrElement.classList.add(o.classPrefix+"pull"),r.state="pulling",i.update(o)),r.pullStartY&&r.pullMoveY&&(r.dist=r.pullMoveY-r.pullStartY),r.dist>0&&(e.preventDefault(),o.ptrElement.style[o.cssProp]=r.distResisted+"px",r.distResisted=o.resistanceFunction(r.dist/o.distThreshold)*Math.min(o.distMax,r.dist),"pulling"===r.state&&r.distResisted>o.distThreshold&&(o.ptrElement.classList.add(o.classPrefix+"release"),r.state="releasing",i.update(o)),"releasing"===r.state&&r.distResisted<o.distThreshold&&(o.ptrElement.classList.remove(o.classPrefix+"release"),r.state="pulling",i.update(o)))):o.shouldPullToRefresh()&&r.pullStartY<r.pullMoveY&&e.preventDefault())}function n(){if(o&&o.ptrElement&&r.enable){if("releasing"===r.state&&r.distResisted>o.distThreshold)r.state="refreshing",o.ptrElement.style[o.cssProp]=o.distReload+"px",o.ptrElement.classList.add(o.classPrefix+"refresh"),r.timeout=setTimeout(function(){var e=o.onRefresh(function(){return i.onReset(o)});e&&"function"==typeof e.then&&e.then(function(){return i.onReset(o)}),e||o.onRefresh.length||i.onReset(o)},o.refreshTimeout);else{if("refreshing"===r.state)return;o.ptrElement.style[o.cssProp]="0px",r.state="pending"}i.update(o),o.ptrElement.classList.remove(o.classPrefix+"release"),o.ptrElement.classList.remove(o.classPrefix+"pull"),r.pullStartY=r.pullMoveY=null,r.dist=r.distResisted=0}}function s(){o&&o.mainElement.classList.toggle(o.classPrefix+"top",o.shouldPullToRefresh())}var o,l=r.supportsPassive?{passive:r.passive||!1}:void 0;return window.addEventListener("touchend",n),window.addEventListener("touchstart",e),window.addEventListener("touchmove",t,l),window.addEventListener("scroll",s),{onTouchEnd:n,onTouchStart:e,onTouchMove:t,onScroll:s,destroy:function(){window.removeEventListener("touchstart",e),window.removeEventListener("touchend",n),window.removeEventListener("touchmove",t,l),window.removeEventListener("scroll",s)}}}function t(t){var i={};return Object.keys(n).forEach(function(e){i[e]=t[e]||n[e]}),i.refreshTimeout="number"==typeof t.refreshTimeout?t.refreshTimeout:n.refreshTimeout,s.forEach(function(e){"string"==typeof i[e]&&(i[e]=document.querySelector(i[e]))}),r.events||(r.events=e()),i.contains=function(e){return i.triggerElement.contains(e)},i.destroy=function(){clearTimeout(r.timeout),r.handlers.splice(i.offset,1)},i}var n={distThreshold:60,distMax:80,distReload:50,bodyOffset:20,mainElement:"body",triggerElement:"body",ptrElement:".ptr",classPrefix:"ptr--",cssProp:"min-height",iconArrow:"&#8675;",iconRefreshing:"&hellip;",instructionsPullToRefresh:"Pull down to refresh",instructionsReleaseToRefresh:"Release to refresh",instructionsRefreshing:"Refreshing",refreshTimeout:500,getMarkup:function(){return'\n<div class="__PREFIX__box">\n  <div class="__PREFIX__content">\n    <div class="__PREFIX__icon"></div>\n    <div class="__PREFIX__text"></div>\n  </div>\n</div>'},getStyles:function(){return".__PREFIX__ptr {\n  box-shadow: inset 0 -3px 5px rgba(0, 0, 0, 0.12);\n  pointer-events: none;\n  font-size: 0.85em;\n  font-weight: bold;\n  top: 0;\n  height: 0;\n  transition: height 0.3s, min-height 0.3s;\n  text-align: center;\n  width: 100%;\n  overflow: hidden;\n  display: flex;\n  align-items: flex-end;\n  align-content: stretch;\n}\n.__PREFIX__box {\n  padding: 10px;\n  flex-basis: 100%;\n}\n.__PREFIX__pull {\n  transition: none;\n}\n.__PREFIX__text {\n  margin-top: .33em;\n  color: rgba(0, 0, 0, 0.3);\n}\n.__PREFIX__icon {\n  color: rgba(0, 0, 0, 0.3);\n  transition: transform .3s;\n}\n.__PREFIX__top {\n  touch-action: pan-x pan-down pinch-zoom;\n}\n.__PREFIX__release .__PREFIX__icon {\n  transform: rotate(180deg);\n}\n"},onInit:function(){},onRefresh:function(){return location.reload()},resistanceFunction:function(e){return Math.min(1,e/2.5)},shouldPullToRefresh:function(){return!window.scrollY}},s=["mainElement","ptrElement","triggerElement"],r={pullStartY:null,pullMoveY:null,handlers:[],styleEl:null,events:null,dist:0,state:"pending",timeout:null,distResisted:0,supportsPassive:!1};try{window.addEventListener("test",null,{get passive(){r.supportsPassive=!0}})}catch(e){}var i={setupDOM:function(e){if(!e.ptrElement){var t=document.createElement("div");e.mainElement!==document.body?e.mainElement.parentNode.insertBefore(t,e.mainElement):document.body.insertBefore(t,document.body.firstChild),t.classList.add(e.classPrefix+"ptr"),t.innerHTML=e.getMarkup().replace(/__PREFIX__/g,e.classPrefix),e.ptrElement=t,"function"==typeof e.onInit&&e.onInit(e),r.styleEl||(r.styleEl=document.createElement("style"),r.styleEl.setAttribute("id","pull-to-refresh-js-style"),document.head.appendChild(r.styleEl)),r.styleEl.textContent=e.getStyles().replace(/__PREFIX__/g,e.classPrefix).replace(/\s+/g," ")}return e},onReset:function(e){e.ptrElement.classList.remove(e.classPrefix+"refresh"),e.ptrElement.style[e.cssProp]="0px",setTimeout(function(){e.ptrElement&&e.ptrElement.parentNode&&(e.ptrElement.parentNode.removeChild(e.ptrElement),e.ptrElement=null),r.state="pending"},e.refreshTimeout)},update:function(e){var t=e.ptrElement.querySelector("."+e.classPrefix+"icon"),n=e.ptrElement.querySelector("."+e.classPrefix+"text");t&&("refreshing"===r.state?t.innerHTML=e.iconRefreshing:t.innerHTML=e.iconArrow),n&&("releasing"===r.state&&(n.innerHTML=e.instructionsReleaseToRefresh),"pulling"!==r.state&&"pending"!==r.state||(n.innerHTML=e.instructionsPullToRefresh),"refreshing"===r.state&&(n.innerHTML=e.instructionsRefreshing))}};return{setPassiveMode:function(e){r.passive=e},destroyAll:function(){r.events&&(r.events.destroy(),r.events=null),r.handlers.forEach(function(e){e.destroy()})},init:function(e){void 0===e&&(e={});var n=t(e);return n.offset=r.handlers.push(n)-1,n},_:{setupHandler:t,setupEvents:e,setupDOM:i.setupDOM,onReset:i.onReset,update:i.update}}});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/swiper.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/swiper.min.js
new file mode 100755
index 0000000..ae35ad5
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/swiper.min.js
@@ -0,0 +1 @@
+!function(){"use strict";var e,a=function(s,i){function r(e){return Math.floor(e)}function n(){var e=x.params.autoplay,a=x.slides.eq(x.activeIndex);a.attr("data-swiper-autoplay")&&(e=a.attr("data-swiper-autoplay")||x.params.autoplay),x.autoplayTimeoutId=setTimeout(function(){x.params.loop?(x.fixLoop(),x._slideNext(),x.emit("onAutoplay",x)):x.isEnd?i.autoplayStopOnLast?x.stopAutoplay():(x._slideTo(0),x.emit("onAutoplay",x)):(x._slideNext(),x.emit("onAutoplay",x))},e)}function o(a,t){var s=e(a.target);if(!s.is(t))if("string"==typeof t)s=s.parents(t);else if(t.nodeType){var i;return s.parents().each(function(e,a){a===t&&(i=t)}),i?t:void 0}if(0!==s.length)return s[0]}function l(e,a){a=a||{};var t=new(window.MutationObserver||window.WebkitMutationObserver)(function(e){e.forEach(function(e){x.onResize(!0),x.emit("onObserverUpdate",x,e)})});t.observe(e,{attributes:void 0===a.attributes||a.attributes,childList:void 0===a.childList||a.childList,characterData:void 0===a.characterData||a.characterData}),x.observers.push(t)}function p(e){e.originalEvent&&(e=e.originalEvent);var a=e.keyCode||e.charCode;if(!x.params.allowSwipeToNext&&(x.isHorizontal()&&39===a||!x.isHorizontal()&&40===a))return!1;if(!x.params.allowSwipeToPrev&&(x.isHorizontal()&&37===a||!x.isHorizontal()&&38===a))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===a||39===a||38===a||40===a){var t=!1;if(x.container.parents("."+x.params.slideClass).length>0&&0===x.container.parents("."+x.params.slideActiveClass).length)return;var s={left:window.pageXOffset,top:window.pageYOffset},i=window.innerWidth,r=window.innerHeight,n=x.container.offset();x.rtl&&(n.left=n.left-x.container[0].scrollLeft);for(var o=[[n.left,n.top],[n.left+x.width,n.top],[n.left,n.top+x.height],[n.left+x.width,n.top+x.height]],l=0;l<o.length;l++){var p=o[l];p[0]>=s.left&&p[0]<=s.left+i&&p[1]>=s.top&&p[1]<=s.top+r&&(t=!0)}if(!t)return}x.isHorizontal()?(37!==a&&39!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===a&&!x.rtl||37===a&&x.rtl)&&x.slideNext(),(37===a&&!x.rtl||39===a&&x.rtl)&&x.slidePrev()):(38!==a&&40!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),40===a&&x.slideNext(),38===a&&x.slidePrev()),x.emit("onKeyPress",x,a)}}function d(e){e.originalEvent&&(e=e.originalEvent);var a=0,t=x.rtl?-1:1,s=function(e){var a=0,t=0,s=0,i=0;return"detail"in e&&(t=e.detail),"wheelDelta"in e&&(t=-e.wheelDelta/120),"wheelDeltaY"in e&&(t=-e.wheelDeltaY/120),"wheelDeltaX"in e&&(a=-e.wheelDeltaX/120),"axis"in e&&e.axis===e.HORIZONTAL_AXIS&&(a=t,t=0),s=10*a,i=10*t,"deltaY"in e&&(i=e.deltaY),"deltaX"in e&&(s=e.deltaX),(s||i)&&e.deltaMode&&(1===e.deltaMode?(s*=40,i*=40):(s*=800,i*=800)),s&&!a&&(a=s<1?-1:1),i&&!t&&(t=i<1?-1:1),{spinX:a,spinY:t,pixelX:s,pixelY:i}}(e);if(x.params.mousewheelForceToAxis)if(x.isHorizontal()){if(!(Math.abs(s.pixelX)>Math.abs(s.pixelY)))return;a=s.pixelX*t}else{if(!(Math.abs(s.pixelY)>Math.abs(s.pixelX)))return;a=s.pixelY}else a=Math.abs(s.pixelX)>Math.abs(s.pixelY)?-s.pixelX*t:-s.pixelY;if(0!==a){if(x.params.mousewheelInvert&&(a=-a),x.params.freeMode){var i=x.getWrapperTranslate()+a*x.params.mousewheelSensitivity,r=x.isBeginning,n=x.isEnd;if(i>=x.minTranslate()&&(i=x.minTranslate()),i<=x.maxTranslate()&&(i=x.maxTranslate()),x.setWrapperTransition(0),x.setWrapperTranslate(i),x.updateProgress(),x.updateActiveIndex(),(!r&&x.isBeginning||!n&&x.isEnd)&&x.updateClasses(),x.params.freeModeSticky?(clearTimeout(x.mousewheel.timeout),x.mousewheel.timeout=setTimeout(function(){x.slideReset()},300)):x.params.lazyLoading&&x.lazy&&x.lazy.load(),x.emit("onScroll",x,e),x.params.autoplay&&x.params.autoplayDisableOnInteraction&&x.stopAutoplay(),0===i||i===x.maxTranslate())return}else{if((new window.Date).getTime()-x.mousewheel.lastScrollTime>60)if(a<0)if(x.isEnd&&!x.params.loop||x.animating){if(x.params.mousewheelReleaseOnEdges)return!0}else x.slideNext(),x.emit("onScroll",x,e);else if(x.isBeginning&&!x.params.loop||x.animating){if(x.params.mousewheelReleaseOnEdges)return!0}else x.slidePrev(),x.emit("onScroll",x,e);x.mousewheel.lastScrollTime=(new window.Date).getTime()}return e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function u(a,t){a=e(a);var s,i,r,n=x.rtl?-1:1;s=a.attr("data-swiper-parallax")||"0",i=a.attr("data-swiper-parallax-x"),r=a.attr("data-swiper-parallax-y"),i||r?(i=i||"0",r=r||"0"):x.isHorizontal()?(i=s,r="0"):(r=s,i="0"),i=i.indexOf("%")>=0?parseInt(i,10)*t*n+"%":i*t*n+"px",r=r.indexOf("%")>=0?parseInt(r,10)*t+"%":r*t+"px",a.transform("translate3d("+i+", "+r+",0px)")}function c(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof a))return new a(s,i);var m={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,autoplayStopOnLast:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeMomentumVelocityRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flip:{slideShadows:!0,limitRotation:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,zoom:!1,zoomMax:3,zoomMin:1,zoomToggle:!0,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,mousewheelEventsTarged:"container",hashnav:!1,hashnavWatchState:!1,history:!1,replaceState:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,touchReleaseOnEdges:!1,uniqueNavElements:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,paginationProgressRender:null,paginationFractionRender:null,paginationCustomRender:null,paginationType:"bullets",resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingInPrevNextAmount:1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",normalizeSlideIndex:!0,allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",passiveListeners:!0,containerModifierClass:"swiper-container-",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideDuplicateActiveClass:"swiper-slide-duplicate-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slideDuplicateNextClass:"swiper-slide-duplicate-next",slidePrevClass:"swiper-slide-prev",slideDuplicatePrevClass:"swiper-slide-duplicate-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationCurrentClass:"swiper-pagination-current",paginationTotalClass:"swiper-pagination-total",paginationHiddenClass:"swiper-pagination-hidden",paginationProgressbarClass:"swiper-pagination-progressbar",paginationClickableClass:"swiper-pagination-clickable",paginationModifierClass:"swiper-pagination-",lazyLoadingClass:"swiper-lazy",lazyStatusLoadingClass:"swiper-lazy-loading",lazyStatusLoadedClass:"swiper-lazy-loaded",lazyPreloaderClass:"swiper-lazy-preloader",notificationClass:"swiper-notification",preloaderClass:"preloader",zoomContainerClass:"swiper-zoom-container",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},h=i&&i.virtualTranslate;i=i||{};var g={};for(var f in i)if("object"!=typeof i[f]||null===i[f]||(i[f].nodeType||i[f]===window||i[f]===document||void 0!==t&&i[f]instanceof t||"undefined"!=typeof jQuery&&i[f]instanceof jQuery))g[f]=i[f];else{g[f]={};for(var v in i[f])g[f][v]=i[f][v]}for(var w in m)if(void 0===i[w])i[w]=m[w];else if("object"==typeof i[w])for(var y in m[w])void 0===i[w][y]&&(i[w][y]=m[w][y]);var x=this;if(x.params=i,x.originalParams=g,x.classNames=[],void 0!==e&&void 0!==t&&(e=t),(void 0!==e||(e=void 0===t?window.Dom7||window.Zepto||window.jQuery:t))&&(x.$=e,x.currentBreakpoint=void 0,x.getActiveBreakpoint=function(){if(!x.params.breakpoints)return!1;var e,a=!1,t=[];for(e in x.params.breakpoints)x.params.breakpoints.hasOwnProperty(e)&&t.push(e);t.sort(function(e,a){return parseInt(e,10)>parseInt(a,10)});for(var s=0;s<t.length;s++)(e=t[s])>=window.innerWidth&&!a&&(a=e);return a||"max"},x.setBreakpoint=function(){var e=x.getActiveBreakpoint();if(e&&x.currentBreakpoint!==e){var a=e in x.params.breakpoints?x.params.breakpoints[e]:x.originalParams,t=x.params.loop&&a.slidesPerView!==x.params.slidesPerView;for(var s in a)x.params[s]=a[s];x.currentBreakpoint=e,t&&x.destroyLoop&&x.reLoop(!0)}},x.params.breakpoints&&x.setBreakpoint(),x.container=e(s),0!==x.container.length)){if(x.container.length>1){var T=[];return x.container.each(function(){T.push(new a(this,i))}),T}x.container[0].swiper=x,x.container.data("swiper",x),x.classNames.push(x.params.containerModifierClass+x.params.direction),x.params.freeMode&&x.classNames.push(x.params.containerModifierClass+"free-mode"),x.support.flexbox||(x.classNames.push(x.params.containerModifierClass+"no-flexbox"),x.params.slidesPerColumn=1),x.params.autoHeight&&x.classNames.push(x.params.containerModifierClass+"autoheight"),(x.params.parallax||x.params.watchSlidesVisibility)&&(x.params.watchSlidesProgress=!0),x.params.touchReleaseOnEdges&&(x.params.resistanceRatio=0),["cube","coverflow","flip"].indexOf(x.params.effect)>=0&&(x.support.transforms3d?(x.params.watchSlidesProgress=!0,x.classNames.push(x.params.containerModifierClass+"3d")):x.params.effect="slide"),"slide"!==x.params.effect&&x.classNames.push(x.params.containerModifierClass+x.params.effect),"cube"===x.params.effect&&(x.params.resistanceRatio=0,x.params.slidesPerView=1,x.params.slidesPerColumn=1,x.params.slidesPerGroup=1,x.params.centeredSlides=!1,x.params.spaceBetween=0,x.params.virtualTranslate=!0),"fade"!==x.params.effect&&"flip"!==x.params.effect||(x.params.slidesPerView=1,x.params.slidesPerColumn=1,x.params.slidesPerGroup=1,x.params.watchSlidesProgress=!0,x.params.spaceBetween=0,void 0===h&&(x.params.virtualTranslate=!0)),x.params.grabCursor&&x.support.touch&&(x.params.grabCursor=!1),x.wrapper=x.container.children("."+x.params.wrapperClass),x.params.pagination&&(x.paginationContainer=e(x.params.pagination),x.params.uniqueNavElements&&"string"==typeof x.params.pagination&&x.paginationContainer.length>1&&1===x.container.find(x.params.pagination).length&&(x.paginationContainer=x.container.find(x.params.pagination)),"bullets"===x.params.paginationType&&x.params.paginationClickable?x.paginationContainer.addClass(x.params.paginationModifierClass+"clickable"):x.params.paginationClickable=!1,x.paginationContainer.addClass(x.params.paginationModifierClass+x.params.paginationType)),(x.params.nextButton||x.params.prevButton)&&(x.params.nextButton&&(x.nextButton=e(x.params.nextButton),x.params.uniqueNavElements&&"string"==typeof x.params.nextButton&&x.nextButton.length>1&&1===x.container.find(x.params.nextButton).length&&(x.nextButton=x.container.find(x.params.nextButton))),x.params.prevButton&&(x.prevButton=e(x.params.prevButton),x.params.uniqueNavElements&&"string"==typeof x.params.prevButton&&x.prevButton.length>1&&1===x.container.find(x.params.prevButton).length&&(x.prevButton=x.container.find(x.params.prevButton)))),x.isHorizontal=function(){return"horizontal"===x.params.direction},x.rtl=x.isHorizontal()&&("rtl"===x.container[0].dir.toLowerCase()||"rtl"===x.container.css("direction")),x.rtl&&x.classNames.push(x.params.containerModifierClass+"rtl"),x.rtl&&(x.wrongRTL="-webkit-box"===x.wrapper.css("display")),x.params.slidesPerColumn>1&&x.classNames.push(x.params.containerModifierClass+"multirow"),x.device.android&&x.classNames.push(x.params.containerModifierClass+"android"),x.container.addClass(x.classNames.join(" ")),x.translate=0,x.progress=0,x.velocity=0,x.lockSwipeToNext=function(){x.params.allowSwipeToNext=!1,!1===x.params.allowSwipeToPrev&&x.params.grabCursor&&x.unsetGrabCursor()},x.lockSwipeToPrev=function(){x.params.allowSwipeToPrev=!1,!1===x.params.allowSwipeToNext&&x.params.grabCursor&&x.unsetGrabCursor()},x.lockSwipes=function(){x.params.allowSwipeToNext=x.params.allowSwipeToPrev=!1,x.params.grabCursor&&x.unsetGrabCursor()},x.unlockSwipeToNext=function(){x.params.allowSwipeToNext=!0,!0===x.params.allowSwipeToPrev&&x.params.grabCursor&&x.setGrabCursor()},x.unlockSwipeToPrev=function(){x.params.allowSwipeToPrev=!0,!0===x.params.allowSwipeToNext&&x.params.grabCursor&&x.setGrabCursor()},x.unlockSwipes=function(){x.params.allowSwipeToNext=x.params.allowSwipeToPrev=!0,x.params.grabCursor&&x.setGrabCursor()},x.setGrabCursor=function(e){x.container[0].style.cursor="move",x.container[0].style.cursor=e?"-webkit-grabbing":"-webkit-grab",x.container[0].style.cursor=e?"-moz-grabbin":"-moz-grab",x.container[0].style.cursor=e?"grabbing":"grab"},x.unsetGrabCursor=function(){x.container[0].style.cursor=""},x.params.grabCursor&&x.setGrabCursor(),x.imagesToLoad=[],x.imagesLoaded=0,x.loadImage=function(e,a,t,s,i,r){function n(){r&&r()}var o;e.complete&&i?n():a?((o=new window.Image).onload=n,o.onerror=n,s&&(o.sizes=s),t&&(o.srcset=t),a&&(o.src=a)):n()},x.preloadImages=function(){function e(){void 0!==x&&null!==x&&x&&(void 0!==x.imagesLoaded&&x.imagesLoaded++,x.imagesLoaded===x.imagesToLoad.length&&(x.params.updateOnImagesReady&&x.update(),x.emit("onImagesReady",x)))}x.imagesToLoad=x.container.find("img");for(var a=0;a<x.imagesToLoad.length;a++)x.loadImage(x.imagesToLoad[a],x.imagesToLoad[a].currentSrc||x.imagesToLoad[a].getAttribute("src"),x.imagesToLoad[a].srcset||x.imagesToLoad[a].getAttribute("srcset"),x.imagesToLoad[a].sizes||x.imagesToLoad[a].getAttribute("sizes"),!0,e)},x.autoplayTimeoutId=void 0,x.autoplaying=!1,x.autoplayPaused=!1,x.startAutoplay=function(){return void 0===x.autoplayTimeoutId&&(!!x.params.autoplay&&(!x.autoplaying&&(x.autoplaying=!0,x.emit("onAutoplayStart",x),void n())))},x.stopAutoplay=function(e){x.autoplayTimeoutId&&(x.autoplayTimeoutId&&clearTimeout(x.autoplayTimeoutId),x.autoplaying=!1,x.autoplayTimeoutId=void 0,x.emit("onAutoplayStop",x))},x.pauseAutoplay=function(e){x.autoplayPaused||(x.autoplayTimeoutId&&clearTimeout(x.autoplayTimeoutId),x.autoplayPaused=!0,0===e?(x.autoplayPaused=!1,n()):x.wrapper.transitionEnd(function(){x&&(x.autoplayPaused=!1,x.autoplaying?n():x.stopAutoplay())}))},x.minTranslate=function(){return-x.snapGrid[0]},x.maxTranslate=function(){return-x.snapGrid[x.snapGrid.length-1]},x.updateAutoHeight=function(){var e,a=[],t=0;if("auto"!==x.params.slidesPerView&&x.params.slidesPerView>1)for(e=0;e<Math.ceil(x.params.slidesPerView);e++){var s=x.activeIndex+e;if(s>x.slides.length)break;a.push(x.slides.eq(s)[0])}else a.push(x.slides.eq(x.activeIndex)[0]);for(e=0;e<a.length;e++)if(void 0!==a[e]){var i=a[e].offsetHeight;t=i>t?i:t}t&&x.wrapper.css("height",t+"px")},x.updateContainerSize=function(){var e,a;e=void 0!==x.params.width?x.params.width:x.container[0].clientWidth,a=void 0!==x.params.height?x.params.height:x.container[0].clientHeight,0===e&&x.isHorizontal()||0===a&&!x.isHorizontal()||(e=e-parseInt(x.container.css("padding-left"),10)-parseInt(x.container.css("padding-right"),10),a=a-parseInt(x.container.css("padding-top"),10)-parseInt(x.container.css("padding-bottom"),10),x.width=e,x.height=a,x.size=x.isHorizontal()?x.width:x.height)},x.updateSlidesSize=function(){x.slides=x.wrapper.children("."+x.params.slideClass),x.snapGrid=[],x.slidesGrid=[],x.slidesSizesGrid=[];var e,a=x.params.spaceBetween,t=-x.params.slidesOffsetBefore,s=0,i=0;if(void 0!==x.size){"string"==typeof a&&a.indexOf("%")>=0&&(a=parseFloat(a.replace("%",""))/100*x.size),x.virtualSize=-a,x.rtl?x.slides.css({marginLeft:"",marginTop:""}):x.slides.css({marginRight:"",marginBottom:""});var n;x.params.slidesPerColumn>1&&(n=Math.floor(x.slides.length/x.params.slidesPerColumn)===x.slides.length/x.params.slidesPerColumn?x.slides.length:Math.ceil(x.slides.length/x.params.slidesPerColumn)*x.params.slidesPerColumn,"auto"!==x.params.slidesPerView&&"row"===x.params.slidesPerColumnFill&&(n=Math.max(n,x.params.slidesPerView*x.params.slidesPerColumn)));var o,l=x.params.slidesPerColumn,p=n/l,d=p-(x.params.slidesPerColumn*p-x.slides.length);for(e=0;e<x.slides.length;e++){o=0;var u=x.slides.eq(e);if(x.params.slidesPerColumn>1){var c,m,h;"column"===x.params.slidesPerColumnFill?(h=e-(m=Math.floor(e/l))*l,(m>d||m===d&&h===l-1)&&++h>=l&&(h=0,m++),c=m+h*n/l,u.css({"-webkit-box-ordinal-group":c,"-moz-box-ordinal-group":c,"-ms-flex-order":c,"-webkit-order":c,order:c})):m=e-(h=Math.floor(e/p))*p,u.css("margin-"+(x.isHorizontal()?"top":"left"),0!==h&&x.params.spaceBetween&&x.params.spaceBetween+"px").attr("data-swiper-column",m).attr("data-swiper-row",h)}"none"!==u.css("display")&&("auto"===x.params.slidesPerView?(o=x.isHorizontal()?u.outerWidth(!0):u.outerHeight(!0),x.params.roundLengths&&(o=r(o))):(o=(x.size-(x.params.slidesPerView-1)*a)/x.params.slidesPerView,x.params.roundLengths&&(o=r(o)),x.isHorizontal()?x.slides[e].style.width=o+"px":x.slides[e].style.height=o+"px"),x.slides[e].swiperSlideSize=o,x.slidesSizesGrid.push(o),x.params.centeredSlides?(t=t+o/2+s/2+a,0===s&&0!==e&&(t=t-x.size/2-a),0===e&&(t=t-x.size/2-a),Math.abs(t)<.001&&(t=0),i%x.params.slidesPerGroup==0&&x.snapGrid.push(t),x.slidesGrid.push(t)):(i%x.params.slidesPerGroup==0&&x.snapGrid.push(t),x.slidesGrid.push(t),t=t+o+a),x.virtualSize+=o+a,s=o,i++)}x.virtualSize=Math.max(x.virtualSize,x.size)+x.params.slidesOffsetAfter;var g;if(x.rtl&&x.wrongRTL&&("slide"===x.params.effect||"coverflow"===x.params.effect)&&x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}),x.support.flexbox&&!x.params.setWrapperSize||(x.isHorizontal()?x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}):x.wrapper.css({height:x.virtualSize+x.params.spaceBetween+"px"})),x.params.slidesPerColumn>1&&(x.virtualSize=(o+x.params.spaceBetween)*n,x.virtualSize=Math.ceil(x.virtualSize/x.params.slidesPerColumn)-x.params.spaceBetween,x.isHorizontal()?x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}):x.wrapper.css({height:x.virtualSize+x.params.spaceBetween+"px"}),x.params.centeredSlides)){for(g=[],e=0;e<x.snapGrid.length;e++)x.snapGrid[e]<x.virtualSize+x.snapGrid[0]&&g.push(x.snapGrid[e]);x.snapGrid=g}if(!x.params.centeredSlides){for(g=[],e=0;e<x.snapGrid.length;e++)x.snapGrid[e]<=x.virtualSize-x.size&&g.push(x.snapGrid[e]);x.snapGrid=g,Math.floor(x.virtualSize-x.size)-Math.floor(x.snapGrid[x.snapGrid.length-1])>1&&x.snapGrid.push(x.virtualSize-x.size)}0===x.snapGrid.length&&(x.snapGrid=[0]),0!==x.params.spaceBetween&&(x.isHorizontal()?x.rtl?x.slides.css({marginLeft:a+"px"}):x.slides.css({marginRight:a+"px"}):x.slides.css({marginBottom:a+"px"})),x.params.watchSlidesProgress&&x.updateSlidesOffset()}},x.updateSlidesOffset=function(){for(var e=0;e<x.slides.length;e++)x.slides[e].swiperSlideOffset=x.isHorizontal()?x.slides[e].offsetLeft:x.slides[e].offsetTop},x.currentSlidesPerView=function(){var e,a,t=1;if(x.params.centeredSlides){var s,i=x.slides[x.activeIndex].swiperSlideSize;for(e=x.activeIndex+1;e<x.slides.length;e++)x.slides[e]&&!s&&(t++,(i+=x.slides[e].swiperSlideSize)>x.size&&(s=!0));for(a=x.activeIndex-1;a>=0;a--)x.slides[a]&&!s&&(t++,(i+=x.slides[a].swiperSlideSize)>x.size&&(s=!0))}else for(e=x.activeIndex+1;e<x.slides.length;e++)x.slidesGrid[e]-x.slidesGrid[x.activeIndex]<x.size&&t++;return t},x.updateSlidesProgress=function(e){if(void 0===e&&(e=x.translate||0),0!==x.slides.length){void 0===x.slides[0].swiperSlideOffset&&x.updateSlidesOffset();var a=-e;x.rtl&&(a=e),x.slides.removeClass(x.params.slideVisibleClass);for(var t=0;t<x.slides.length;t++){var s=x.slides[t],i=(a+(x.params.centeredSlides?x.minTranslate():0)-s.swiperSlideOffset)/(s.swiperSlideSize+x.params.spaceBetween);if(x.params.watchSlidesVisibility){var r=-(a-s.swiperSlideOffset),n=r+x.slidesSizesGrid[t];(r>=0&&r<x.size||n>0&&n<=x.size||r<=0&&n>=x.size)&&x.slides.eq(t).addClass(x.params.slideVisibleClass)}s.progress=x.rtl?-i:i}}},x.updateProgress=function(e){void 0===e&&(e=x.translate||0);var a=x.maxTranslate()-x.minTranslate(),t=x.isBeginning,s=x.isEnd;0===a?(x.progress=0,x.isBeginning=x.isEnd=!0):(x.progress=(e-x.minTranslate())/a,x.isBeginning=x.progress<=0,x.isEnd=x.progress>=1),x.isBeginning&&!t&&x.emit("onReachBeginning",x),x.isEnd&&!s&&x.emit("onReachEnd",x),x.params.watchSlidesProgress&&x.updateSlidesProgress(e),x.emit("onProgress",x,x.progress)},x.updateActiveIndex=function(){var e,a,t,s=x.rtl?x.translate:-x.translate;for(a=0;a<x.slidesGrid.length;a++)void 0!==x.slidesGrid[a+1]?s>=x.slidesGrid[a]&&s<x.slidesGrid[a+1]-(x.slidesGrid[a+1]-x.slidesGrid[a])/2?e=a:s>=x.slidesGrid[a]&&s<x.slidesGrid[a+1]&&(e=a+1):s>=x.slidesGrid[a]&&(e=a);x.params.normalizeSlideIndex&&(e<0||void 0===e)&&(e=0),(t=Math.floor(e/x.params.slidesPerGroup))>=x.snapGrid.length&&(t=x.snapGrid.length-1),e!==x.activeIndex&&(x.snapIndex=t,x.previousIndex=x.activeIndex,x.activeIndex=e,x.updateClasses(),x.updateRealIndex())},x.updateRealIndex=function(){x.realIndex=parseInt(x.slides.eq(x.activeIndex).attr("data-swiper-slide-index")||x.activeIndex,10)},x.updateClasses=function(){x.slides.removeClass(x.params.slideActiveClass+" "+x.params.slideNextClass+" "+x.params.slidePrevClass+" "+x.params.slideDuplicateActiveClass+" "+x.params.slideDuplicateNextClass+" "+x.params.slideDuplicatePrevClass);var a=x.slides.eq(x.activeIndex);a.addClass(x.params.slideActiveClass),i.loop&&(a.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+x.realIndex+'"]').addClass(x.params.slideDuplicateActiveClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+x.realIndex+'"]').addClass(x.params.slideDuplicateActiveClass));var t=a.next("."+x.params.slideClass).addClass(x.params.slideNextClass);x.params.loop&&0===t.length&&(t=x.slides.eq(0)).addClass(x.params.slideNextClass);var s=a.prev("."+x.params.slideClass).addClass(x.params.slidePrevClass);if(x.params.loop&&0===s.length&&(s=x.slides.eq(-1)).addClass(x.params.slidePrevClass),i.loop&&(t.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicateNextClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicateNextClass),s.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicatePrevClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicatePrevClass)),x.paginationContainer&&x.paginationContainer.length>0){var r,n=x.params.loop?Math.ceil((x.slides.length-2*x.loopedSlides)/x.params.slidesPerGroup):x.snapGrid.length;if(x.params.loop?((r=Math.ceil((x.activeIndex-x.loopedSlides)/x.params.slidesPerGroup))>x.slides.length-1-2*x.loopedSlides&&(r-=x.slides.length-2*x.loopedSlides),r>n-1&&(r-=n),r<0&&"bullets"!==x.params.paginationType&&(r=n+r)):r=void 0!==x.snapIndex?x.snapIndex:x.activeIndex||0,"bullets"===x.params.paginationType&&x.bullets&&x.bullets.length>0&&(x.bullets.removeClass(x.params.bulletActiveClass),x.paginationContainer.length>1?x.bullets.each(function(){e(this).index()===r&&e(this).addClass(x.params.bulletActiveClass)}):x.bullets.eq(r).addClass(x.params.bulletActiveClass)),"fraction"===x.params.paginationType&&(x.paginationContainer.find("."+x.params.paginationCurrentClass).text(r+1),x.paginationContainer.find("."+x.params.paginationTotalClass).text(n)),"progress"===x.params.paginationType){var o=(r+1)/n,l=o,p=1;x.isHorizontal()||(p=o,l=1),x.paginationContainer.find("."+x.params.paginationProgressbarClass).transform("translate3d(0,0,0) scaleX("+l+") scaleY("+p+")").transition(x.params.speed)}"custom"===x.params.paginationType&&x.params.paginationCustomRender&&(x.paginationContainer.html(x.params.paginationCustomRender(x,r+1,n)),x.emit("onPaginationRendered",x,x.paginationContainer[0]))}x.params.loop||(x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.isBeginning?(x.prevButton.addClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.disable(x.prevButton)):(x.prevButton.removeClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.enable(x.prevButton))),x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.isEnd?(x.nextButton.addClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.disable(x.nextButton)):(x.nextButton.removeClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.enable(x.nextButton))))},x.updatePagination=function(){if(x.params.pagination&&x.paginationContainer&&x.paginationContainer.length>0){var e="";if("bullets"===x.params.paginationType){for(var a=x.params.loop?Math.ceil((x.slides.length-2*x.loopedSlides)/x.params.slidesPerGroup):x.snapGrid.length,t=0;t<a;t++)x.params.paginationBulletRender?e+=x.params.paginationBulletRender(x,t,x.params.bulletClass):e+="<"+x.params.paginationElement+' class="'+x.params.bulletClass+'"></'+x.params.paginationElement+">";x.paginationContainer.html(e),x.bullets=x.paginationContainer.find("."+x.params.bulletClass),x.params.paginationClickable&&x.params.a11y&&x.a11y&&x.a11y.initPagination()}"fraction"===x.params.paginationType&&(e=x.params.paginationFractionRender?x.params.paginationFractionRender(x,x.params.paginationCurrentClass,x.params.paginationTotalClass):'<span class="'+x.params.paginationCurrentClass+'"></span> / <span class="'+x.params.paginationTotalClass+'"></span>',x.paginationContainer.html(e)),"progress"===x.params.paginationType&&(e=x.params.paginationProgressRender?x.params.paginationProgressRender(x,x.params.paginationProgressbarClass):'<span class="'+x.params.paginationProgressbarClass+'"></span>',x.paginationContainer.html(e)),"custom"!==x.params.paginationType&&x.emit("onPaginationRendered",x,x.paginationContainer[0])}},x.update=function(e){function a(){x.rtl,x.translate;t=Math.min(Math.max(x.translate,x.maxTranslate()),x.minTranslate()),x.setWrapperTranslate(t),x.updateActiveIndex(),x.updateClasses()}if(x){x.updateContainerSize(),x.updateSlidesSize(),x.updateProgress(),x.updatePagination(),x.updateClasses(),x.params.scrollbar&&x.scrollbar&&x.scrollbar.set();var t;if(e){x.controller&&x.controller.spline&&(x.controller.spline=void 0),x.params.freeMode?(a(),x.params.autoHeight&&x.updateAutoHeight()):(("auto"===x.params.slidesPerView||x.params.slidesPerView>1)&&x.isEnd&&!x.params.centeredSlides?x.slideTo(x.slides.length-1,0,!1,!0):x.slideTo(x.activeIndex,0,!1,!0))||a()}else x.params.autoHeight&&x.updateAutoHeight()}},x.onResize=function(e){x.params.onBeforeResize&&x.params.onBeforeResize(x),x.params.breakpoints&&x.setBreakpoint();var a=x.params.allowSwipeToPrev,t=x.params.allowSwipeToNext;x.params.allowSwipeToPrev=x.params.allowSwipeToNext=!0,x.updateContainerSize(),x.updateSlidesSize(),("auto"===x.params.slidesPerView||x.params.freeMode||e)&&x.updatePagination(),x.params.scrollbar&&x.scrollbar&&x.scrollbar.set(),x.controller&&x.controller.spline&&(x.controller.spline=void 0);var s=!1;if(x.params.freeMode){var i=Math.min(Math.max(x.translate,x.maxTranslate()),x.minTranslate());x.setWrapperTranslate(i),x.updateActiveIndex(),x.updateClasses(),x.params.autoHeight&&x.updateAutoHeight()}else x.updateClasses(),s=("auto"===x.params.slidesPerView||x.params.slidesPerView>1)&&x.isEnd&&!x.params.centeredSlides?x.slideTo(x.slides.length-1,0,!1,!0):x.slideTo(x.activeIndex,0,!1,!0);x.params.lazyLoading&&!s&&x.lazy&&x.lazy.load(),x.params.allowSwipeToPrev=a,x.params.allowSwipeToNext=t,x.params.onAfterResize&&x.params.onAfterResize(x)},x.touchEventsDesktop={start:"mousedown",move:"mousemove",end:"mouseup"},window.navigator.pointerEnabled?x.touchEventsDesktop={start:"pointerdown",move:"pointermove",end:"pointerup"}:window.navigator.msPointerEnabled&&(x.touchEventsDesktop={start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}),x.touchEvents={start:x.support.touch||!x.params.simulateTouch?"touchstart":x.touchEventsDesktop.start,move:x.support.touch||!x.params.simulateTouch?"touchmove":x.touchEventsDesktop.move,end:x.support.touch||!x.params.simulateTouch?"touchend":x.touchEventsDesktop.end},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===x.params.touchEventsTarget?x.container:x.wrapper).addClass("swiper-wp8-"+x.params.direction),x.initEvents=function(e){var a=e?"off":"on",t=e?"removeEventListener":"addEventListener",s="container"===x.params.touchEventsTarget?x.container[0]:x.wrapper[0],r=x.support.touch?s:document,n=!!x.params.nested;if(x.browser.ie)s[t](x.touchEvents.start,x.onTouchStart,!1),r[t](x.touchEvents.move,x.onTouchMove,n),r[t](x.touchEvents.end,x.onTouchEnd,!1);else{if(x.support.touch){var o=!("touchstart"!==x.touchEvents.start||!x.support.passiveListener||!x.params.passiveListeners)&&{passive:!0,capture:!1};s[t](x.touchEvents.start,x.onTouchStart,o),s[t](x.touchEvents.move,x.onTouchMove,n),s[t](x.touchEvents.end,x.onTouchEnd,o)}(i.simulateTouch&&!x.device.ios&&!x.device.android||i.simulateTouch&&!x.support.touch&&x.device.ios)&&(s[t]("mousedown",x.onTouchStart,!1),document[t]("mousemove",x.onTouchMove,n),document[t]("mouseup",x.onTouchEnd,!1))}window[t]("resize",x.onResize),x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.nextButton[a]("click",x.onClickNext),x.params.a11y&&x.a11y&&x.nextButton[a]("keydown",x.a11y.onEnterKey)),x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.prevButton[a]("click",x.onClickPrev),x.params.a11y&&x.a11y&&x.prevButton[a]("keydown",x.a11y.onEnterKey)),x.params.pagination&&x.params.paginationClickable&&(x.paginationContainer[a]("click","."+x.params.bulletClass,x.onClickIndex),x.params.a11y&&x.a11y&&x.paginationContainer[a]("keydown","."+x.params.bulletClass,x.a11y.onEnterKey)),(x.params.preventClicks||x.params.preventClicksPropagation)&&s[t]("click",x.preventClicks,!0)},x.attachEvents=function(){x.initEvents()},x.detachEvents=function(){x.initEvents(!0)},x.allowClick=!0,x.preventClicks=function(e){x.allowClick||(x.params.preventClicks&&e.preventDefault(),x.params.preventClicksPropagation&&x.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},x.onClickNext=function(e){e.preventDefault(),x.isEnd&&!x.params.loop||x.slideNext()},x.onClickPrev=function(e){e.preventDefault(),x.isBeginning&&!x.params.loop||x.slidePrev()},x.onClickIndex=function(a){a.preventDefault();var t=e(this).index()*x.params.slidesPerGroup;x.params.loop&&(t+=x.loopedSlides),x.slideTo(t)},x.updateClickedSlide=function(a){var t=o(a,"."+x.params.slideClass),s=!1;if(t)for(var i=0;i<x.slides.length;i++)x.slides[i]===t&&(s=!0);if(!t||!s)return x.clickedSlide=void 0,void(x.clickedIndex=void 0);if(x.clickedSlide=t,x.clickedIndex=e(t).index(),x.params.slideToClickedSlide&&void 0!==x.clickedIndex&&x.clickedIndex!==x.activeIndex){var r,n=x.clickedIndex,l="auto"===x.params.slidesPerView?x.currentSlidesPerView():x.params.slidesPerView;if(x.params.loop){if(x.animating)return;r=parseInt(e(x.clickedSlide).attr("data-swiper-slide-index"),10),x.params.centeredSlides?n<x.loopedSlides-l/2||n>x.slides.length-x.loopedSlides+l/2?(x.fixLoop(),n=x.wrapper.children("."+x.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+x.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){x.slideTo(n)},0)):x.slideTo(n):n>x.slides.length-l?(x.fixLoop(),n=x.wrapper.children("."+x.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+x.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){x.slideTo(n)},0)):x.slideTo(n)}else x.slideTo(n)}};var b,S,C,z,M,E,P,I,k,L,D="input, select, textarea, button, video",B=Date.now(),H=[];x.animating=!1,x.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var G,X;x.onTouchStart=function(a){if(a.originalEvent&&(a=a.originalEvent),(G="touchstart"===a.type)||!("which"in a)||3!==a.which)if(x.params.noSwiping&&o(a,"."+x.params.noSwipingClass))x.allowClick=!0;else if(!x.params.swipeHandler||o(a,x.params.swipeHandler)){var t=x.touches.currentX="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,s=x.touches.currentY="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY;if(!(x.device.ios&&x.params.iOSEdgeSwipeDetection&&t<=x.params.iOSEdgeSwipeThreshold)){if(b=!0,S=!1,C=!0,M=void 0,X=void 0,x.touches.startX=t,x.touches.startY=s,z=Date.now(),x.allowClick=!0,x.updateContainerSize(),x.swipeDirection=void 0,x.params.threshold>0&&(I=!1),"touchstart"!==a.type){var i=!0;e(a.target).is(D)&&(i=!1),document.activeElement&&e(document.activeElement).is(D)&&document.activeElement.blur(),i&&a.preventDefault()}x.emit("onTouchStart",x,a)}}},x.onTouchMove=function(a){if(a.originalEvent&&(a=a.originalEvent),!G||"mousemove"!==a.type){if(a.preventedByNestedSwiper)return x.touches.startX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,void(x.touches.startY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY);if(x.params.onlyExternal)return x.allowClick=!1,void(b&&(x.touches.startX=x.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,x.touches.startY=x.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,z=Date.now()));if(G&&x.params.touchReleaseOnEdges&&!x.params.loop)if(x.isHorizontal()){if(x.touches.currentX<x.touches.startX&&x.translate<=x.maxTranslate()||x.touches.currentX>x.touches.startX&&x.translate>=x.minTranslate())return}else if(x.touches.currentY<x.touches.startY&&x.translate<=x.maxTranslate()||x.touches.currentY>x.touches.startY&&x.translate>=x.minTranslate())return;if(G&&document.activeElement&&a.target===document.activeElement&&e(a.target).is(D))return S=!0,void(x.allowClick=!1);if(C&&x.emit("onTouchMove",x,a),!(a.targetTouches&&a.targetTouches.length>1)){if(x.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,x.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,void 0===M){var t;x.isHorizontal()&&x.touches.currentY===x.touches.startY||!x.isHorizontal()&&x.touches.currentX===x.touches.startX?M=!1:(t=180*Math.atan2(Math.abs(x.touches.currentY-x.touches.startY),Math.abs(x.touches.currentX-x.touches.startX))/Math.PI,M=x.isHorizontal()?t>x.params.touchAngle:90-t>x.params.touchAngle)}if(M&&x.emit("onTouchMoveOpposite",x,a),void 0===X&&(x.touches.currentX===x.touches.startX&&x.touches.currentY===x.touches.startY||(X=!0)),b)if(M)b=!1;else if(X){x.allowClick=!1,x.emit("onSliderMove",x,a),a.preventDefault(),x.params.touchMoveStopPropagation&&!x.params.nested&&a.stopPropagation(),S||(i.loop&&x.fixLoop(),P=x.getWrapperTranslate(),x.setWrapperTransition(0),x.animating&&x.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),x.params.autoplay&&x.autoplaying&&(x.params.autoplayDisableOnInteraction?x.stopAutoplay():x.pauseAutoplay()),L=!1,!x.params.grabCursor||!0!==x.params.allowSwipeToNext&&!0!==x.params.allowSwipeToPrev||x.setGrabCursor(!0)),S=!0;var s=x.touches.diff=x.isHorizontal()?x.touches.currentX-x.touches.startX:x.touches.currentY-x.touches.startY;s*=x.params.touchRatio,x.rtl&&(s=-s),x.swipeDirection=s>0?"prev":"next",E=s+P;var r=!0;if(s>0&&E>x.minTranslate()?(r=!1,x.params.resistance&&(E=x.minTranslate()-1+Math.pow(-x.minTranslate()+P+s,x.params.resistanceRatio))):s<0&&E<x.maxTranslate()&&(r=!1,x.params.resistance&&(E=x.maxTranslate()+1-Math.pow(x.maxTranslate()-P-s,x.params.resistanceRatio))),r&&(a.preventedByNestedSwiper=!0),!x.params.allowSwipeToNext&&"next"===x.swipeDirection&&E<P&&(E=P),!x.params.allowSwipeToPrev&&"prev"===x.swipeDirection&&E>P&&(E=P),x.params.threshold>0){if(!(Math.abs(s)>x.params.threshold||I))return void(E=P);if(!I)return I=!0,x.touches.startX=x.touches.currentX,x.touches.startY=x.touches.currentY,E=P,void(x.touches.diff=x.isHorizontal()?x.touches.currentX-x.touches.startX:x.touches.currentY-x.touches.startY)}x.params.followFinger&&((x.params.freeMode||x.params.watchSlidesProgress)&&x.updateActiveIndex(),x.params.freeMode&&(0===H.length&&H.push({position:x.touches[x.isHorizontal()?"startX":"startY"],time:z}),H.push({position:x.touches[x.isHorizontal()?"currentX":"currentY"],time:(new window.Date).getTime()})),x.updateProgress(E),x.setWrapperTranslate(E))}}}},x.onTouchEnd=function(a){if(a.originalEvent&&(a=a.originalEvent),C&&x.emit("onTouchEnd",x,a),C=!1,b){x.params.grabCursor&&S&&b&&(!0===x.params.allowSwipeToNext||!0===x.params.allowSwipeToPrev)&&x.setGrabCursor(!1);var t=Date.now(),s=t-z;if(x.allowClick&&(x.updateClickedSlide(a),x.emit("onTap",x,a),s<300&&t-B>300&&(k&&clearTimeout(k),k=setTimeout(function(){x&&(x.params.paginationHide&&x.paginationContainer.length>0&&!e(a.target).hasClass(x.params.bulletClass)&&x.paginationContainer.toggleClass(x.params.paginationHiddenClass),x.emit("onClick",x,a))},300)),s<300&&t-B<300&&(k&&clearTimeout(k),x.emit("onDoubleTap",x,a))),B=Date.now(),setTimeout(function(){x&&(x.allowClick=!0)},0),b&&S&&x.swipeDirection&&0!==x.touches.diff&&E!==P){b=S=!1;var i;if(i=x.params.followFinger?x.rtl?x.translate:-x.translate:-E,x.params.freeMode){if(i<-x.minTranslate())return void x.slideTo(x.activeIndex);if(i>-x.maxTranslate())return void(x.slides.length<x.snapGrid.length?x.slideTo(x.snapGrid.length-1):x.slideTo(x.slides.length-1));if(x.params.freeModeMomentum){if(H.length>1){var r=H.pop(),n=H.pop(),o=r.position-n.position,l=r.time-n.time;x.velocity=o/l,x.velocity=x.velocity/2,Math.abs(x.velocity)<x.params.freeModeMinimumVelocity&&(x.velocity=0),(l>150||(new window.Date).getTime()-r.time>300)&&(x.velocity=0)}else x.velocity=0;x.velocity=x.velocity*x.params.freeModeMomentumVelocityRatio,H.length=0;var p=1e3*x.params.freeModeMomentumRatio,d=x.velocity*p,u=x.translate+d;x.rtl&&(u=-u);var c,m=!1,h=20*Math.abs(x.velocity)*x.params.freeModeMomentumBounceRatio;if(u<x.maxTranslate())x.params.freeModeMomentumBounce?(u+x.maxTranslate()<-h&&(u=x.maxTranslate()-h),c=x.maxTranslate(),m=!0,L=!0):u=x.maxTranslate();else if(u>x.minTranslate())x.params.freeModeMomentumBounce?(u-x.minTranslate()>h&&(u=x.minTranslate()+h),c=x.minTranslate(),m=!0,L=!0):u=x.minTranslate();else if(x.params.freeModeSticky){var g,f=0;for(f=0;f<x.snapGrid.length;f+=1)if(x.snapGrid[f]>-u){g=f;break}u=Math.abs(x.snapGrid[g]-u)<Math.abs(x.snapGrid[g-1]-u)||"next"===x.swipeDirection?x.snapGrid[g]:x.snapGrid[g-1],x.rtl||(u=-u)}if(0!==x.velocity)p=x.rtl?Math.abs((-u-x.translate)/x.velocity):Math.abs((u-x.translate)/x.velocity);else if(x.params.freeModeSticky)return void x.slideReset();x.params.freeModeMomentumBounce&&m?(x.updateProgress(c),x.setWrapperTransition(p),x.setWrapperTranslate(u),x.onTransitionStart(),x.animating=!0,x.wrapper.transitionEnd(function(){x&&L&&(x.emit("onMomentumBounce",x),x.setWrapperTransition(x.params.speed),x.setWrapperTranslate(c),x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd()}))})):x.velocity?(x.updateProgress(u),x.setWrapperTransition(p),x.setWrapperTranslate(u),x.onTransitionStart(),x.animating||(x.animating=!0,x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd()}))):x.updateProgress(u),x.updateActiveIndex()}(!x.params.freeModeMomentum||s>=x.params.longSwipesMs)&&(x.updateProgress(),x.updateActiveIndex())}else{var v,w=0,y=x.slidesSizesGrid[0];for(v=0;v<x.slidesGrid.length;v+=x.params.slidesPerGroup)void 0!==x.slidesGrid[v+x.params.slidesPerGroup]?i>=x.slidesGrid[v]&&i<x.slidesGrid[v+x.params.slidesPerGroup]&&(w=v,y=x.slidesGrid[v+x.params.slidesPerGroup]-x.slidesGrid[v]):i>=x.slidesGrid[v]&&(w=v,y=x.slidesGrid[x.slidesGrid.length-1]-x.slidesGrid[x.slidesGrid.length-2]);var T=(i-x.slidesGrid[w])/y;if(s>x.params.longSwipesMs){if(!x.params.longSwipes)return void x.slideTo(x.activeIndex);"next"===x.swipeDirection&&(T>=x.params.longSwipesRatio?x.slideTo(w+x.params.slidesPerGroup):x.slideTo(w)),"prev"===x.swipeDirection&&(T>1-x.params.longSwipesRatio?x.slideTo(w+x.params.slidesPerGroup):x.slideTo(w))}else{if(!x.params.shortSwipes)return void x.slideTo(x.activeIndex);"next"===x.swipeDirection&&x.slideTo(w+x.params.slidesPerGroup),"prev"===x.swipeDirection&&x.slideTo(w)}}}else b=S=!1}},x._slideTo=function(e,a){return x.slideTo(e,a,!0,!0)},x.slideTo=function(e,a,t,s){void 0===t&&(t=!0),void 0===e&&(e=0),e<0&&(e=0),x.snapIndex=Math.floor(e/x.params.slidesPerGroup),x.snapIndex>=x.snapGrid.length&&(x.snapIndex=x.snapGrid.length-1);var i=-x.snapGrid[x.snapIndex];if(x.params.autoplay&&x.autoplaying&&(s||!x.params.autoplayDisableOnInteraction?x.pauseAutoplay(a):x.stopAutoplay()),x.updateProgress(i),x.params.normalizeSlideIndex)for(var r=0;r<x.slidesGrid.length;r++)-Math.floor(100*i)>=Math.floor(100*x.slidesGrid[r])&&(e=r);return!(!x.params.allowSwipeToNext&&i<x.translate&&i<x.minTranslate())&&(!(!x.params.allowSwipeToPrev&&i>x.translate&&i>x.maxTranslate()&&(x.activeIndex||0)!==e)&&(void 0===a&&(a=x.params.speed),x.previousIndex=x.activeIndex||0,x.activeIndex=e,x.updateRealIndex(),x.rtl&&-i===x.translate||!x.rtl&&i===x.translate?(x.params.autoHeight&&x.updateAutoHeight(),x.updateClasses(),"slide"!==x.params.effect&&x.setWrapperTranslate(i),!1):(x.updateClasses(),x.onTransitionStart(t),0===a||x.browser.lteIE9?(x.setWrapperTranslate(i),x.setWrapperTransition(0),x.onTransitionEnd(t)):(x.setWrapperTranslate(i),x.setWrapperTransition(a),x.animating||(x.animating=!0,x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd(t)}))),!0)))},x.onTransitionStart=function(e){void 0===e&&(e=!0),x.params.autoHeight&&x.updateAutoHeight(),x.lazy&&x.lazy.onTransitionStart(),e&&(x.emit("onTransitionStart",x),x.activeIndex!==x.previousIndex&&(x.emit("onSlideChangeStart",x),x.activeIndex>x.previousIndex?x.emit("onSlideNextStart",x):x.emit("onSlidePrevStart",x)))},x.onTransitionEnd=function(e){x.animating=!1,x.setWrapperTransition(0),void 0===e&&(e=!0),x.lazy&&x.lazy.onTransitionEnd(),e&&(x.emit("onTransitionEnd",x),x.activeIndex!==x.previousIndex&&(x.emit("onSlideChangeEnd",x),x.activeIndex>x.previousIndex?x.emit("onSlideNextEnd",x):x.emit("onSlidePrevEnd",x))),x.params.history&&x.history&&x.history.setHistory(x.params.history,x.activeIndex),x.params.hashnav&&x.hashnav&&x.hashnav.setHash()},x.slideNext=function(e,a,t){if(x.params.loop){if(x.animating)return!1;x.fixLoop();x.container[0].clientLeft;return x.slideTo(x.activeIndex+x.params.slidesPerGroup,a,e,t)}return x.slideTo(x.activeIndex+x.params.slidesPerGroup,a,e,t)},x._slideNext=function(e){return x.slideNext(!0,e,!0)},x.slidePrev=function(e,a,t){if(x.params.loop){if(x.animating)return!1;x.fixLoop();x.container[0].clientLeft;return x.slideTo(x.activeIndex-1,a,e,t)}return x.slideTo(x.activeIndex-1,a,e,t)},x._slidePrev=function(e){return x.slidePrev(!0,e,!0)},x.slideReset=function(e,a,t){return x.slideTo(x.activeIndex,a,e)},x.disableTouchControl=function(){return x.params.onlyExternal=!0,!0},x.enableTouchControl=function(){return x.params.onlyExternal=!1,!0},x.setWrapperTransition=function(e,a){x.wrapper.transition(e),"slide"!==x.params.effect&&x.effects[x.params.effect]&&x.effects[x.params.effect].setTransition(e),x.params.parallax&&x.parallax&&x.parallax.setTransition(e),x.params.scrollbar&&x.scrollbar&&x.scrollbar.setTransition(e),x.params.control&&x.controller&&x.controller.setTransition(e,a),x.emit("onSetTransition",x,e)},x.setWrapperTranslate=function(e,a,t){var s=0,i=0;x.isHorizontal()?s=x.rtl?-e:e:i=e,x.params.roundLengths&&(s=r(s),i=r(i)),x.params.virtualTranslate||(x.support.transforms3d?x.wrapper.transform("translate3d("+s+"px, "+i+"px, 0px)"):x.wrapper.transform("translate("+s+"px, "+i+"px)")),x.translate=x.isHorizontal()?s:i;var n=x.maxTranslate()-x.minTranslate();(0===n?0:(e-x.minTranslate())/n)!==x.progress&&x.updateProgress(e),a&&x.updateActiveIndex(),"slide"!==x.params.effect&&x.effects[x.params.effect]&&x.effects[x.params.effect].setTranslate(x.translate),x.params.parallax&&x.parallax&&x.parallax.setTranslate(x.translate),x.params.scrollbar&&x.scrollbar&&x.scrollbar.setTranslate(x.translate),x.params.control&&x.controller&&x.controller.setTranslate(x.translate,t),x.emit("onSetTranslate",x,x.translate)},x.getTranslate=function(e,a){var t,s,i,r;return void 0===a&&(a="x"),x.params.virtualTranslate?x.rtl?-x.translate:x.translate:(i=window.getComputedStyle(e,null),window.WebKitCSSMatrix?((s=i.transform||i.webkitTransform).split(",").length>6&&(s=s.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),r=new window.WebKitCSSMatrix("none"===s?"":s)):t=(r=i.MozTransform||i.OTransform||i.MsTransform||i.msTransform||i.transform||i.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,")).toString().split(","),"x"===a&&(s=window.WebKitCSSMatrix?r.m41:16===t.length?parseFloat(t[12]):parseFloat(t[4])),"y"===a&&(s=window.WebKitCSSMatrix?r.m42:16===t.length?parseFloat(t[13]):parseFloat(t[5])),x.rtl&&s&&(s=-s),s||0)},x.getWrapperTranslate=function(e){return void 0===e&&(e=x.isHorizontal()?"x":"y"),x.getTranslate(x.wrapper[0],e)},x.observers=[],x.initObservers=function(){if(x.params.observeParents)for(var e=x.container.parents(),a=0;a<e.length;a++)l(e[a]);l(x.container[0],{childList:!1}),l(x.wrapper[0],{attributes:!1})},x.disconnectObservers=function(){for(var e=0;e<x.observers.length;e++)x.observers[e].disconnect();x.observers=[]},x.createLoop=function(){x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass).remove();var a=x.wrapper.children("."+x.params.slideClass);"auto"!==x.params.slidesPerView||x.params.loopedSlides||(x.params.loopedSlides=a.length),x.loopedSlides=parseInt(x.params.loopedSlides||x.params.slidesPerView,10),x.loopedSlides=x.loopedSlides+x.params.loopAdditionalSlides,x.loopedSlides>a.length&&(x.loopedSlides=a.length);var t,s=[],i=[];for(a.each(function(t,r){var n=e(this);t<x.loopedSlides&&i.push(r),t<a.length&&t>=a.length-x.loopedSlides&&s.push(r),n.attr("data-swiper-slide-index",t)}),t=0;t<i.length;t++)x.wrapper.append(e(i[t].cloneNode(!0)).addClass(x.params.slideDuplicateClass));for(t=s.length-1;t>=0;t--)x.wrapper.prepend(e(s[t].cloneNode(!0)).addClass(x.params.slideDuplicateClass))},x.destroyLoop=function(){x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass).remove(),x.slides.removeAttr("data-swiper-slide-index")},x.reLoop=function(e){var a=x.activeIndex-x.loopedSlides;x.destroyLoop(),x.createLoop(),x.updateSlidesSize(),e&&x.slideTo(a+x.loopedSlides,0,!1)},x.fixLoop=function(){var e;x.activeIndex<x.loopedSlides?(e=x.slides.length-3*x.loopedSlides+x.activeIndex,e+=x.loopedSlides,x.slideTo(e,0,!1,!0)):("auto"===x.params.slidesPerView&&x.activeIndex>=2*x.loopedSlides||x.activeIndex>x.slides.length-2*x.params.slidesPerView)&&(e=-x.slides.length+x.activeIndex+x.loopedSlides,e+=x.loopedSlides,x.slideTo(e,0,!1,!0))},x.appendSlide=function(e){if(x.params.loop&&x.destroyLoop(),"object"==typeof e&&e.length)for(var a=0;a<e.length;a++)e[a]&&x.wrapper.append(e[a]);else x.wrapper.append(e);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0)},x.prependSlide=function(e){x.params.loop&&x.destroyLoop();var a=x.activeIndex+1;if("object"==typeof e&&e.length){for(var t=0;t<e.length;t++)e[t]&&x.wrapper.prepend(e[t]);a=x.activeIndex+e.length}else x.wrapper.prepend(e);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0),x.slideTo(a,0,!1)},x.removeSlide=function(e){x.params.loop&&(x.destroyLoop(),x.slides=x.wrapper.children("."+x.params.slideClass));var a,t=x.activeIndex;if("object"==typeof e&&e.length){for(var s=0;s<e.length;s++)a=e[s],x.slides[a]&&x.slides.eq(a).remove(),a<t&&t--;t=Math.max(t,0)}else a=e,x.slides[a]&&x.slides.eq(a).remove(),a<t&&t--,t=Math.max(t,0);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0),x.params.loop?x.slideTo(t+x.loopedSlides,0,!1):x.slideTo(t,0,!1)},x.removeAllSlides=function(){for(var e=[],a=0;a<x.slides.length;a++)e.push(a);x.removeSlide(e)},x.effects={fade:{setTranslate:function(){for(var e=0;e<x.slides.length;e++){var a=x.slides.eq(e),t=-a[0].swiperSlideOffset;x.params.virtualTranslate||(t-=x.translate);var s=0;x.isHorizontal()||(s=t,t=0);var i=x.params.fade.crossFade?Math.max(1-Math.abs(a[0].progress),0):1+Math.min(Math.max(a[0].progress,-1),0);a.css({opacity:i}).transform("translate3d("+t+"px, "+s+"px, 0px)")}},setTransition:function(e){if(x.slides.transition(e),x.params.virtualTranslate&&0!==e){var a=!1;x.slides.transitionEnd(function(){if(!a&&x){a=!0,x.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],t=0;t<e.length;t++)x.wrapper.trigger(e[t])}})}}},flip:{setTranslate:function(){for(var a=0;a<x.slides.length;a++){var t=x.slides.eq(a),s=t[0].progress;x.params.flip.limitRotation&&(s=Math.max(Math.min(t[0].progress,1),-1));var i=-180*s,r=0,n=-t[0].swiperSlideOffset,o=0;if(x.isHorizontal()?x.rtl&&(i=-i):(o=n,n=0,r=-i,i=0),t[0].style.zIndex=-Math.abs(Math.round(s))+x.slides.length,x.params.flip.slideShadows){var l=x.isHorizontal()?t.find(".swiper-slide-shadow-left"):t.find(".swiper-slide-shadow-top"),p=x.isHorizontal()?t.find(".swiper-slide-shadow-right"):t.find(".swiper-slide-shadow-bottom");0===l.length&&(l=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),t.append(l)),0===p.length&&(p=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),t.append(p)),l.length&&(l[0].style.opacity=Math.max(-s,0)),p.length&&(p[0].style.opacity=Math.max(s,0))}t.transform("translate3d("+n+"px, "+o+"px, 0px) rotateX("+r+"deg) rotateY("+i+"deg)")}},setTransition:function(a){if(x.slides.transition(a).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(a),x.params.virtualTranslate&&0!==a){var t=!1;x.slides.eq(x.activeIndex).transitionEnd(function(){if(!t&&x&&e(this).hasClass(x.params.slideActiveClass)){t=!0,x.animating=!1;for(var a=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],s=0;s<a.length;s++)x.wrapper.trigger(a[s])}})}}},cube:{setTranslate:function(){var a,t=0;x.params.cube.shadow&&(x.isHorizontal()?(0===(a=x.wrapper.find(".swiper-cube-shadow")).length&&(a=e('<div class="swiper-cube-shadow"></div>'),x.wrapper.append(a)),a.css({height:x.width+"px"})):0===(a=x.container.find(".swiper-cube-shadow")).length&&(a=e('<div class="swiper-cube-shadow"></div>'),x.container.append(a)));for(var s=0;s<x.slides.length;s++){var i=x.slides.eq(s),r=90*s,n=Math.floor(r/360);x.rtl&&(r=-r,n=Math.floor(-r/360));var o=Math.max(Math.min(i[0].progress,1),-1),l=0,p=0,d=0;s%4==0?(l=4*-n*x.size,d=0):(s-1)%4==0?(l=0,d=4*-n*x.size):(s-2)%4==0?(l=x.size+4*n*x.size,d=x.size):(s-3)%4==0&&(l=-x.size,d=3*x.size+4*x.size*n),x.rtl&&(l=-l),x.isHorizontal()||(p=l,l=0);var u="rotateX("+(x.isHorizontal()?0:-r)+"deg) rotateY("+(x.isHorizontal()?r:0)+"deg) translate3d("+l+"px, "+p+"px, "+d+"px)";if(o<=1&&o>-1&&(t=90*s+90*o,x.rtl&&(t=90*-s-90*o)),i.transform(u),x.params.cube.slideShadows){var c=x.isHorizontal()?i.find(".swiper-slide-shadow-left"):i.find(".swiper-slide-shadow-top"),m=x.isHorizontal()?i.find(".swiper-slide-shadow-right"):i.find(".swiper-slide-shadow-bottom");0===c.length&&(c=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),i.append(c)),0===m.length&&(m=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),i.append(m)),c.length&&(c[0].style.opacity=Math.max(-o,0)),m.length&&(m[0].style.opacity=Math.max(o,0))}}if(x.wrapper.css({"-webkit-transform-origin":"50% 50% -"+x.size/2+"px","-moz-transform-origin":"50% 50% -"+x.size/2+"px","-ms-transform-origin":"50% 50% -"+x.size/2+"px","transform-origin":"50% 50% -"+x.size/2+"px"}),x.params.cube.shadow)if(x.isHorizontal())a.transform("translate3d(0px, "+(x.width/2+x.params.cube.shadowOffset)+"px, "+-x.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+x.params.cube.shadowScale+")");else{var h=Math.abs(t)-90*Math.floor(Math.abs(t)/90),g=1.5-(Math.sin(2*h*Math.PI/360)/2+Math.cos(2*h*Math.PI/360)/2),f=x.params.cube.shadowScale,v=x.params.cube.shadowScale/g,w=x.params.cube.shadowOffset;a.transform("scale3d("+f+", 1, "+v+") translate3d(0px, "+(x.height/2+w)+"px, "+-x.height/2/v+"px) rotateX(-90deg)")}var y=x.isSafari||x.isUiWebView?-x.size/2:0;x.wrapper.transform("translate3d(0px,0,"+y+"px) rotateX("+(x.isHorizontal()?0:t)+"deg) rotateY("+(x.isHorizontal()?-t:0)+"deg)")},setTransition:function(e){x.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),x.params.cube.shadow&&!x.isHorizontal()&&x.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var a=x.translate,t=x.isHorizontal()?-a+x.width/2:-a+x.height/2,s=x.isHorizontal()?x.params.coverflow.rotate:-x.params.coverflow.rotate,i=x.params.coverflow.depth,r=0,n=x.slides.length;r<n;r++){var o=x.slides.eq(r),l=x.slidesSizesGrid[r],p=(t-o[0].swiperSlideOffset-l/2)/l*x.params.coverflow.modifier,d=x.isHorizontal()?s*p:0,u=x.isHorizontal()?0:s*p,c=-i*Math.abs(p),m=x.isHorizontal()?0:x.params.coverflow.stretch*p,h=x.isHorizontal()?x.params.coverflow.stretch*p:0;Math.abs(h)<.001&&(h=0),Math.abs(m)<.001&&(m=0),Math.abs(c)<.001&&(c=0),Math.abs(d)<.001&&(d=0),Math.abs(u)<.001&&(u=0);var g="translate3d("+h+"px,"+m+"px,"+c+"px)  rotateX("+u+"deg) rotateY("+d+"deg)";if(o.transform(g),o[0].style.zIndex=1-Math.abs(Math.round(p)),x.params.coverflow.slideShadows){var f=x.isHorizontal()?o.find(".swiper-slide-shadow-left"):o.find(".swiper-slide-shadow-top"),v=x.isHorizontal()?o.find(".swiper-slide-shadow-right"):o.find(".swiper-slide-shadow-bottom");0===f.length&&(f=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),o.append(f)),0===v.length&&(v=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),o.append(v)),f.length&&(f[0].style.opacity=p>0?p:0),v.length&&(v[0].style.opacity=-p>0?-p:0)}}if(x.browser.ie){x.wrapper[0].style.perspectiveOrigin=t+"px 50%"}},setTransition:function(e){x.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},x.lazy={initialImageLoaded:!1,loadImageInSlide:function(a,t){if(void 0!==a&&(void 0===t&&(t=!0),0!==x.slides.length)){var s=x.slides.eq(a),i=s.find("."+x.params.lazyLoadingClass+":not(."+x.params.lazyStatusLoadedClass+"):not(."+x.params.lazyStatusLoadingClass+")");!s.hasClass(x.params.lazyLoadingClass)||s.hasClass(x.params.lazyStatusLoadedClass)||s.hasClass(x.params.lazyStatusLoadingClass)||(i=i.add(s[0])),0!==i.length&&i.each(function(){var a=e(this);a.addClass(x.params.lazyStatusLoadingClass);var i=a.attr("data-background"),r=a.attr("data-src"),n=a.attr("data-srcset"),o=a.attr("data-sizes");x.loadImage(a[0],r||i,n,o,!1,function(){if(void 0!==x&&null!==x&&x){if(i?(a.css("background-image",'url("'+i+'")'),a.removeAttr("data-background")):(n&&(a.attr("srcset",n),a.removeAttr("data-srcset")),o&&(a.attr("sizes",o),a.removeAttr("data-sizes")),r&&(a.attr("src",r),a.removeAttr("data-src"))),a.addClass(x.params.lazyStatusLoadedClass).removeClass(x.params.lazyStatusLoadingClass),s.find("."+x.params.lazyPreloaderClass+", ."+x.params.preloaderClass).remove(),x.params.loop&&t){var e=s.attr("data-swiper-slide-index");if(s.hasClass(x.params.slideDuplicateClass)){var l=x.wrapper.children('[data-swiper-slide-index="'+e+'"]:not(.'+x.params.slideDuplicateClass+")");x.lazy.loadImageInSlide(l.index(),!1)}else{var p=x.wrapper.children("."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+e+'"]');x.lazy.loadImageInSlide(p.index(),!1)}}x.emit("onLazyImageReady",x,s[0],a[0])}}),x.emit("onLazyImageLoad",x,s[0],a[0])})}},load:function(){var a,t=x.params.slidesPerView;if("auto"===t&&(t=0),x.lazy.initialImageLoaded||(x.lazy.initialImageLoaded=!0),x.params.watchSlidesVisibility)x.wrapper.children("."+x.params.slideVisibleClass).each(function(){x.lazy.loadImageInSlide(e(this).index())});else if(t>1)for(a=x.activeIndex;a<x.activeIndex+t;a++)x.slides[a]&&x.lazy.loadImageInSlide(a);else x.lazy.loadImageInSlide(x.activeIndex);if(x.params.lazyLoadingInPrevNext)if(t>1||x.params.lazyLoadingInPrevNextAmount&&x.params.lazyLoadingInPrevNextAmount>1){var s=x.params.lazyLoadingInPrevNextAmount,i=t,r=Math.min(x.activeIndex+i+Math.max(s,i),x.slides.length),n=Math.max(x.activeIndex-Math.max(i,s),0);for(a=x.activeIndex+t;a<r;a++)x.slides[a]&&x.lazy.loadImageInSlide(a);for(a=n;a<x.activeIndex;a++)x.slides[a]&&x.lazy.loadImageInSlide(a)}else{var o=x.wrapper.children("."+x.params.slideNextClass);o.length>0&&x.lazy.loadImageInSlide(o.index());var l=x.wrapper.children("."+x.params.slidePrevClass);l.length>0&&x.lazy.loadImageInSlide(l.index())}},onTransitionStart:function(){x.params.lazyLoading&&(x.params.lazyLoadingOnTransitionStart||!x.params.lazyLoadingOnTransitionStart&&!x.lazy.initialImageLoaded)&&x.lazy.load()},onTransitionEnd:function(){x.params.lazyLoading&&!x.params.lazyLoadingOnTransitionStart&&x.lazy.load()}},x.scrollbar={isTouched:!1,setDragPosition:function(e){var a=x.scrollbar,t=(x.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY)-a.track.offset()[x.isHorizontal()?"left":"top"]-a.dragSize/2,s=-x.minTranslate()*a.moveDivider,i=-x.maxTranslate()*a.moveDivider;t<s?t=s:t>i&&(t=i),t=-t/a.moveDivider,x.updateProgress(t),x.setWrapperTranslate(t,!0)},dragStart:function(e){var a=x.scrollbar;a.isTouched=!0,e.preventDefault(),e.stopPropagation(),a.setDragPosition(e),clearTimeout(a.dragTimeout),a.track.transition(0),x.params.scrollbarHide&&a.track.css("opacity",1),x.wrapper.transition(100),a.drag.transition(100),x.emit("onScrollbarDragStart",x)},dragMove:function(e){var a=x.scrollbar;a.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,a.setDragPosition(e),x.wrapper.transition(0),a.track.transition(0),a.drag.transition(0),x.emit("onScrollbarDragMove",x))},dragEnd:function(e){var a=x.scrollbar;a.isTouched&&(a.isTouched=!1,x.params.scrollbarHide&&(clearTimeout(a.dragTimeout),a.dragTimeout=setTimeout(function(){a.track.css("opacity",0),a.track.transition(400)},1e3)),x.emit("onScrollbarDragEnd",x),x.params.scrollbarSnapOnRelease&&x.slideReset())},draggableEvents:!1!==x.params.simulateTouch||x.support.touch?x.touchEvents:x.touchEventsDesktop,enableDraggable:function(){var a=x.scrollbar,t=x.support.touch?a.track:document;e(a.track).on(a.draggableEvents.start,a.dragStart),e(t).on(a.draggableEvents.move,a.dragMove),e(t).on(a.draggableEvents.end,a.dragEnd)},disableDraggable:function(){var a=x.scrollbar,t=x.support.touch?a.track:document;e(a.track).off(a.draggableEvents.start,a.dragStart),e(t).off(a.draggableEvents.move,a.dragMove),e(t).off(a.draggableEvents.end,a.dragEnd)},set:function(){if(x.params.scrollbar){var a=x.scrollbar;a.track=e(x.params.scrollbar),x.params.uniqueNavElements&&"string"==typeof x.params.scrollbar&&a.track.length>1&&1===x.container.find(x.params.scrollbar).length&&(a.track=x.container.find(x.params.scrollbar)),a.drag=a.track.find(".swiper-scrollbar-drag"),0===a.drag.length&&(a.drag=e('<div class="swiper-scrollbar-drag"></div>'),a.track.append(a.drag)),a.drag[0].style.width="",a.drag[0].style.height="",a.trackSize=x.isHorizontal()?a.track[0].offsetWidth:a.track[0].offsetHeight,a.divider=x.size/x.virtualSize,a.moveDivider=a.divider*(a.trackSize/x.size),a.dragSize=a.trackSize*a.divider,x.isHorizontal()?a.drag[0].style.width=a.dragSize+"px":a.drag[0].style.height=a.dragSize+"px",a.divider>=1?a.track[0].style.display="none":a.track[0].style.display="",x.params.scrollbarHide&&(a.track[0].style.opacity=0)}},setTranslate:function(){if(x.params.scrollbar){var e,a=x.scrollbar,t=(x.translate,a.dragSize);e=(a.trackSize-a.dragSize)*x.progress,x.rtl&&x.isHorizontal()?(e=-e)>0?(t=a.dragSize-e,e=0):-e+a.dragSize>a.trackSize&&(t=a.trackSize+e):e<0?(t=a.dragSize+e,e=0):e+a.dragSize>a.trackSize&&(t=a.trackSize-e),x.isHorizontal()?(x.support.transforms3d?a.drag.transform("translate3d("+e+"px, 0, 0)"):a.drag.transform("translateX("+e+"px)"),a.drag[0].style.width=t+"px"):(x.support.transforms3d?a.drag.transform("translate3d(0px, "+e+"px, 0)"):a.drag.transform("translateY("+e+"px)"),a.drag[0].style.height=t+"px"),x.params.scrollbarHide&&(clearTimeout(a.timeout),a.track[0].style.opacity=1,a.timeout=setTimeout(function(){a.track[0].style.opacity=0,a.track.transition(400)},1e3))}},setTransition:function(e){x.params.scrollbar&&x.scrollbar.drag.transition(e)}},x.controller={LinearSpline:function(e,a){var t=function(){var e,a,t;return function(s,i){for(a=-1,e=s.length;e-a>1;)s[t=e+a>>1]<=i?a=t:e=t;return e}}();this.x=e,this.y=a,this.lastIndex=e.length-1;var s,i;this.x.length;this.interpolate=function(e){return e?(i=t(this.x,e),s=i-1,(e-this.x[s])*(this.y[i]-this.y[s])/(this.x[i]-this.x[s])+this.y[s]):0}},getInterpolateFunction:function(e){x.controller.spline||(x.controller.spline=x.params.loop?new x.controller.LinearSpline(x.slidesGrid,e.slidesGrid):new x.controller.LinearSpline(x.snapGrid,e.snapGrid))},setTranslate:function(e,t){function s(a){e=a.rtl&&"horizontal"===a.params.direction?-x.translate:x.translate,"slide"===x.params.controlBy&&(x.controller.getInterpolateFunction(a),r=-x.controller.spline.interpolate(-e)),r&&"container"!==x.params.controlBy||(i=(a.maxTranslate()-a.minTranslate())/(x.maxTranslate()-x.minTranslate()),r=(e-x.minTranslate())*i+a.minTranslate()),x.params.controlInverse&&(r=a.maxTranslate()-r),a.updateProgress(r),a.setWrapperTranslate(r,!1,x),a.updateActiveIndex()}var i,r,n=x.params.control;if(Array.isArray(n))for(var o=0;o<n.length;o++)n[o]!==t&&n[o]instanceof a&&s(n[o]);else n instanceof a&&t!==n&&s(n)},setTransition:function(e,t){function s(a){a.setWrapperTransition(e,x),0!==e&&(a.onTransitionStart(),a.wrapper.transitionEnd(function(){r&&(a.params.loop&&"slide"===x.params.controlBy&&a.fixLoop(),a.onTransitionEnd())}))}var i,r=x.params.control;if(Array.isArray(r))for(i=0;i<r.length;i++)r[i]!==t&&r[i]instanceof a&&s(r[i]);else r instanceof a&&t!==r&&s(r)}},x.hashnav={onHashCange:function(e,a){var t=document.location.hash.replace("#","");t!==x.slides.eq(x.activeIndex).attr("data-hash")&&x.slideTo(x.wrapper.children("."+x.params.slideClass+'[data-hash="'+t+'"]').index())},attachEvents:function(a){var t=a?"off":"on";e(window)[t]("hashchange",x.hashnav.onHashCange)},setHash:function(){if(x.hashnav.initialized&&x.params.hashnav)if(x.params.replaceState&&window.history&&window.history.replaceState)window.history.replaceState(null,null,"#"+x.slides.eq(x.activeIndex).attr("data-hash")||"");else{var e=x.slides.eq(x.activeIndex),a=e.attr("data-hash")||e.attr("data-history");document.location.hash=a||""}},init:function(){if(x.params.hashnav&&!x.params.history){x.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var a=0,t=x.slides.length;a<t;a++){var s=x.slides.eq(a);if((s.attr("data-hash")||s.attr("data-history"))===e&&!s.hasClass(x.params.slideDuplicateClass)){var i=s.index();x.slideTo(i,0,x.params.runCallbacksOnInit,!0)}}x.params.hashnavWatchState&&x.hashnav.attachEvents()}},destroy:function(){x.params.hashnavWatchState&&x.hashnav.attachEvents(!0)}},x.history={init:function(){if(x.params.history){if(!window.history||!window.history.pushState)return x.params.history=!1,void(x.params.hashnav=!0);x.history.initialized=!0,this.paths=this.getPathValues(),(this.paths.key||this.paths.value)&&(this.scrollToSlide(0,this.paths.value,x.params.runCallbacksOnInit),x.params.replaceState||window.addEventListener("popstate",this.setHistoryPopState))}},setHistoryPopState:function(){x.history.paths=x.history.getPathValues(),x.history.scrollToSlide(x.params.speed,x.history.paths.value,!1)},getPathValues:function(){var e=window.location.pathname.slice(1).split("/"),a=e.length;return{key:e[a-2],value:e[a-1]}},setHistory:function(e,a){if(x.history.initialized&&x.params.history){var t=x.slides.eq(a),s=this.slugify(t.attr("data-history"));window.location.pathname.includes(e)||(s=e+"/"+s),x.params.replaceState?window.history.replaceState(null,null,s):window.history.pushState(null,null,s)}},slugify:function(e){return e.toString().toLowerCase().replace(/\s+/g,"-").replace(/[^\w\-]+/g,"").replace(/\-\-+/g,"-").replace(/^-+/,"").replace(/-+$/,"")},scrollToSlide:function(e,a,t){if(a)for(var s=0,i=x.slides.length;s<i;s++){var r=x.slides.eq(s);if(this.slugify(r.attr("data-history"))===a&&!r.hasClass(x.params.slideDuplicateClass)){var n=r.index();x.slideTo(n,e,t)}}else x.slideTo(0,e,t)}},x.disableKeyboardControl=function(){x.params.keyboardControl=!1,e(document).off("keydown",p)},x.enableKeyboardControl=function(){x.params.keyboardControl=!0,e(document).on("keydown",p)},x.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},x.params.mousewheelControl&&(x.mousewheel.event=navigator.userAgent.indexOf("firefox")>-1?"DOMMouseScroll":function(){var e="onwheel"in document;if(!e){var a=document.createElement("div");a.setAttribute("onwheel","return;"),e="function"==typeof a.onwheel}return!e&&document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("","")&&(e=document.implementation.hasFeature("Events.wheel","3.0")),e}()?"wheel":"mousewheel"),x.disableMousewheelControl=function(){if(!x.mousewheel.event)return!1;var a=x.container;return"container"!==x.params.mousewheelEventsTarged&&(a=e(x.params.mousewheelEventsTarged)),a.off(x.mousewheel.event,d),x.params.mousewheelControl=!1,!0},x.enableMousewheelControl=function(){if(!x.mousewheel.event)return!1;var a=x.container;return"container"!==x.params.mousewheelEventsTarged&&(a=e(x.params.mousewheelEventsTarged)),a.on(x.mousewheel.event,d),x.params.mousewheelControl=!0,!0},x.parallax={setTranslate:function(){x.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){u(this,x.progress)}),x.slides.each(function(){var a=e(this);a.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){u(this,Math.min(Math.max(a[0].progress,-1),1))})})},setTransition:function(a){void 0===a&&(a=x.params.speed),x.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=e(this),s=parseInt(t.attr("data-swiper-parallax-duration"),10)||a;0===a&&(s=0),t.transition(s)})}},x.zoom={scale:1,currentScale:1,isScaling:!1,gesture:{slide:void 0,slideWidth:void 0,slideHeight:void 0,image:void 0,imageWrap:void 0,zoomMax:x.params.zoomMax},image:{isTouched:void 0,isMoved:void 0,currentX:void 0,currentY:void 0,minX:void 0,minY:void 0,maxX:void 0,maxY:void 0,width:void 0,height:void 0,startX:void 0,startY:void 0,touchesStart:{},touchesCurrent:{}},velocity:{x:void 0,y:void 0,prevPositionX:void 0,prevPositionY:void 0,prevTime:void 0},getDistanceBetweenTouches:function(e){if(e.targetTouches.length<2)return 1;var a=e.targetTouches[0].pageX,t=e.targetTouches[0].pageY,s=e.targetTouches[1].pageX,i=e.targetTouches[1].pageY;return Math.sqrt(Math.pow(s-a,2)+Math.pow(i-t,2))},onGestureStart:function(a){var t=x.zoom;if(!x.support.gestures){if("touchstart"!==a.type||"touchstart"===a.type&&a.targetTouches.length<2)return;t.gesture.scaleStart=t.getDistanceBetweenTouches(a)}t.gesture.slide&&t.gesture.slide.length||(t.gesture.slide=e(this),0===t.gesture.slide.length&&(t.gesture.slide=x.slides.eq(x.activeIndex)),t.gesture.image=t.gesture.slide.find("img, svg, canvas"),t.gesture.imageWrap=t.gesture.image.parent("."+x.params.zoomContainerClass),t.gesture.zoomMax=t.gesture.imageWrap.attr("data-swiper-zoom")||x.params.zoomMax,0!==t.gesture.imageWrap.length)?(t.gesture.image.transition(0),t.isScaling=!0):t.gesture.image=void 0},onGestureChange:function(e){var a=x.zoom;if(!x.support.gestures){if("touchmove"!==e.type||"touchmove"===e.type&&e.targetTouches.length<2)return;a.gesture.scaleMove=a.getDistanceBetweenTouches(e)}a.gesture.image&&0!==a.gesture.image.length&&(x.support.gestures?a.scale=e.scale*a.currentScale:a.scale=a.gesture.scaleMove/a.gesture.scaleStart*a.currentScale,a.scale>a.gesture.zoomMax&&(a.scale=a.gesture.zoomMax-1+Math.pow(a.scale-a.gesture.zoomMax+1,.5)),a.scale<x.params.zoomMin&&(a.scale=x.params.zoomMin+1-Math.pow(x.params.zoomMin-a.scale+1,.5)),a.gesture.image.transform("translate3d(0,0,0) scale("+a.scale+")"))},onGestureEnd:function(e){var a=x.zoom;!x.support.gestures&&("touchend"!==e.type||"touchend"===e.type&&e.changedTouches.length<2)||a.gesture.image&&0!==a.gesture.image.length&&(a.scale=Math.max(Math.min(a.scale,a.gesture.zoomMax),x.params.zoomMin),a.gesture.image.transition(x.params.speed).transform("translate3d(0,0,0) scale("+a.scale+")"),a.currentScale=a.scale,a.isScaling=!1,1===a.scale&&(a.gesture.slide=void 0))},onTouchStart:function(e,a){var t=e.zoom;t.gesture.image&&0!==t.gesture.image.length&&(t.image.isTouched||("android"===e.device.os&&a.preventDefault(),t.image.isTouched=!0,t.image.touchesStart.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,t.image.touchesStart.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY))},onTouchMove:function(e){var a=x.zoom;if(a.gesture.image&&0!==a.gesture.image.length&&(x.allowClick=!1,a.image.isTouched&&a.gesture.slide)){a.image.isMoved||(a.image.width=a.gesture.image[0].offsetWidth,a.image.height=a.gesture.image[0].offsetHeight,a.image.startX=x.getTranslate(a.gesture.imageWrap[0],"x")||0,a.image.startY=x.getTranslate(a.gesture.imageWrap[0],"y")||0,a.gesture.slideWidth=a.gesture.slide[0].offsetWidth,a.gesture.slideHeight=a.gesture.slide[0].offsetHeight,a.gesture.imageWrap.transition(0),x.rtl&&(a.image.startX=-a.image.startX),x.rtl&&(a.image.startY=-a.image.startY));var t=a.image.width*a.scale,s=a.image.height*a.scale;if(!(t<a.gesture.slideWidth&&s<a.gesture.slideHeight)){if(a.image.minX=Math.min(a.gesture.slideWidth/2-t/2,0),a.image.maxX=-a.image.minX,a.image.minY=Math.min(a.gesture.slideHeight/2-s/2,0),a.image.maxY=-a.image.minY,a.image.touchesCurrent.x="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,a.image.touchesCurrent.y="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,!a.image.isMoved&&!a.isScaling){if(x.isHorizontal()&&Math.floor(a.image.minX)===Math.floor(a.image.startX)&&a.image.touchesCurrent.x<a.image.touchesStart.x||Math.floor(a.image.maxX)===Math.floor(a.image.startX)&&a.image.touchesCurrent.x>a.image.touchesStart.x)return void(a.image.isTouched=!1);if(!x.isHorizontal()&&Math.floor(a.image.minY)===Math.floor(a.image.startY)&&a.image.touchesCurrent.y<a.image.touchesStart.y||Math.floor(a.image.maxY)===Math.floor(a.image.startY)&&a.image.touchesCurrent.y>a.image.touchesStart.y)return void(a.image.isTouched=!1)}e.preventDefault(),e.stopPropagation(),a.image.isMoved=!0,a.image.currentX=a.image.touchesCurrent.x-a.image.touchesStart.x+a.image.startX,a.image.currentY=a.image.touchesCurrent.y-a.image.touchesStart.y+a.image.startY,a.image.currentX<a.image.minX&&(a.image.currentX=a.image.minX+1-Math.pow(a.image.minX-a.image.currentX+1,.8)),a.image.currentX>a.image.maxX&&(a.image.currentX=a.image.maxX-1+Math.pow(a.image.currentX-a.image.maxX+1,.8)),a.image.currentY<a.image.minY&&(a.image.currentY=a.image.minY+1-Math.pow(a.image.minY-a.image.currentY+1,.8)),a.image.currentY>a.image.maxY&&(a.image.currentY=a.image.maxY-1+Math.pow(a.image.currentY-a.image.maxY+1,.8)),a.velocity.prevPositionX||(a.velocity.prevPositionX=a.image.touchesCurrent.x),a.velocity.prevPositionY||(a.velocity.prevPositionY=a.image.touchesCurrent.y),a.velocity.prevTime||(a.velocity.prevTime=Date.now()),a.velocity.x=(a.image.touchesCurrent.x-a.velocity.prevPositionX)/(Date.now()-a.velocity.prevTime)/2,a.velocity.y=(a.image.touchesCurrent.y-a.velocity.prevPositionY)/(Date.now()-a.velocity.prevTime)/2,Math.abs(a.image.touchesCurrent.x-a.velocity.prevPositionX)<2&&(a.velocity.x=0),Math.abs(a.image.touchesCurrent.y-a.velocity.prevPositionY)<2&&(a.velocity.y=0),a.velocity.prevPositionX=a.image.touchesCurrent.x,a.velocity.prevPositionY=a.image.touchesCurrent.y,a.velocity.prevTime=Date.now(),a.gesture.imageWrap.transform("translate3d("+a.image.currentX+"px, "+a.image.currentY+"px,0)")}}},onTouchEnd:function(e,a){var t=e.zoom;if(t.gesture.image&&0!==t.gesture.image.length){if(!t.image.isTouched||!t.image.isMoved)return t.image.isTouched=!1,void(t.image.isMoved=!1);t.image.isTouched=!1,t.image.isMoved=!1;var s=300,i=300,r=t.velocity.x*s,n=t.image.currentX+r,o=t.velocity.y*i,l=t.image.currentY+o;0!==t.velocity.x&&(s=Math.abs((n-t.image.currentX)/t.velocity.x)),0!==t.velocity.y&&(i=Math.abs((l-t.image.currentY)/t.velocity.y));var p=Math.max(s,i);t.image.currentX=n,t.image.currentY=l;var d=t.image.width*t.scale,u=t.image.height*t.scale;t.image.minX=Math.min(t.gesture.slideWidth/2-d/2,0),t.image.maxX=-t.image.minX,t.image.minY=Math.min(t.gesture.slideHeight/2-u/2,0),t.image.maxY=-t.image.minY,t.image.currentX=Math.max(Math.min(t.image.currentX,t.image.maxX),t.image.minX),t.image.currentY=Math.max(Math.min(t.image.currentY,t.image.maxY),t.image.minY),t.gesture.imageWrap.transition(p).transform("translate3d("+t.image.currentX+"px, "+t.image.currentY+"px,0)")}},onTransitionEnd:function(e){var a=e.zoom;a.gesture.slide&&e.previousIndex!==e.activeIndex&&(a.gesture.image.transform("translate3d(0,0,0) scale(1)"),a.gesture.imageWrap.transform("translate3d(0,0,0)"),a.gesture.slide=a.gesture.image=a.gesture.imageWrap=void 0,a.scale=a.currentScale=1)},toggleZoom:function(a,t){var s=a.zoom;if(s.gesture.slide||(s.gesture.slide=a.clickedSlide?e(a.clickedSlide):a.slides.eq(a.activeIndex),s.gesture.image=s.gesture.slide.find("img, svg, canvas"),s.gesture.imageWrap=s.gesture.image.parent("."+a.params.zoomContainerClass)),s.gesture.image&&0!==s.gesture.image.length){var i,r,n,o,l,p,d,u,c,m,h,g,f,v,w,y;void 0===s.image.touchesStart.x&&t?(i="touchend"===t.type?t.changedTouches[0].pageX:t.pageX,r="touchend"===t.type?t.changedTouches[0].pageY:t.pageY):(i=s.image.touchesStart.x,r=s.image.touchesStart.y),s.scale&&1!==s.scale?(s.scale=s.currentScale=1,s.gesture.imageWrap.transition(300).transform("translate3d(0,0,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale(1)"),s.gesture.slide=void 0):(s.scale=s.currentScale=s.gesture.imageWrap.attr("data-swiper-zoom")||a.params.zoomMax,t?(w=s.gesture.slide[0].offsetWidth,y=s.gesture.slide[0].offsetHeight,n=s.gesture.slide.offset().left+w/2-i,o=s.gesture.slide.offset().top+y/2-r,d=s.gesture.image[0].offsetWidth,u=s.gesture.image[0].offsetHeight,c=d*s.scale,m=u*s.scale,f=-(h=Math.min(w/2-c/2,0)),v=-(g=Math.min(y/2-m/2,0)),l=n*s.scale,p=o*s.scale,l<h&&(l=h),l>f&&(l=f),p<g&&(p=g),p>v&&(p=v)):(l=0,p=0),s.gesture.imageWrap.transition(300).transform("translate3d("+l+"px, "+p+"px,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale("+s.scale+")"))}},attachEvents:function(a){var t=a?"off":"on";if(x.params.zoom){x.slides;var s=!("touchstart"!==x.touchEvents.start||!x.support.passiveListener||!x.params.passiveListeners)&&{passive:!0,capture:!1};x.support.gestures?(x.slides[t]("gesturestart",x.zoom.onGestureStart,s),x.slides[t]("gesturechange",x.zoom.onGestureChange,s),x.slides[t]("gestureend",x.zoom.onGestureEnd,s)):"touchstart"===x.touchEvents.start&&(x.slides[t](x.touchEvents.start,x.zoom.onGestureStart,s),x.slides[t](x.touchEvents.move,x.zoom.onGestureChange,s),x.slides[t](x.touchEvents.end,x.zoom.onGestureEnd,s)),x[t]("touchStart",x.zoom.onTouchStart),x.slides.each(function(a,s){e(s).find("."+x.params.zoomContainerClass).length>0&&e(s)[t](x.touchEvents.move,x.zoom.onTouchMove)}),x[t]("touchEnd",x.zoom.onTouchEnd),x[t]("transitionEnd",x.zoom.onTransitionEnd),x.params.zoomToggle&&x.on("doubleTap",x.zoom.toggleZoom)}},init:function(){x.zoom.attachEvents()},destroy:function(){x.zoom.attachEvents(!0)}},x._plugins=[];for(var A in x.plugins){var Y=x.plugins[A](x,x.params[A]);Y&&x._plugins.push(Y)}return x.callPlugins=function(e){for(var a=0;a<x._plugins.length;a++)e in x._plugins[a]&&x._plugins[a][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},x.emitterEventListeners={},x.emit=function(e){x.params[e]&&x.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var a;if(x.emitterEventListeners[e])for(a=0;a<x.emitterEventListeners[e].length;a++)x.emitterEventListeners[e][a](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);x.callPlugins&&x.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},x.on=function(e,a){return e=c(e),x.emitterEventListeners[e]||(x.emitterEventListeners[e]=[]),x.emitterEventListeners[e].push(a),x},x.off=function(e,a){var t;if(e=c(e),void 0===a)return x.emitterEventListeners[e]=[],x;if(x.emitterEventListeners[e]&&0!==x.emitterEventListeners[e].length){for(t=0;t<x.emitterEventListeners[e].length;t++)x.emitterEventListeners[e][t]===a&&x.emitterEventListeners[e].splice(t,1);return x}},x.once=function(e,a){e=c(e);var t=function(){a(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),x.off(e,t)};return x.on(e,t),x},x.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,a){return e.attr("role",a),e},addLabel:function(e,a){return e.attr("aria-label",a),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(a){13===a.keyCode&&(e(a.target).is(x.params.nextButton)?(x.onClickNext(a),x.isEnd?x.a11y.notify(x.params.lastSlideMessage):x.a11y.notify(x.params.nextSlideMessage)):e(a.target).is(x.params.prevButton)&&(x.onClickPrev(a),x.isBeginning?x.a11y.notify(x.params.firstSlideMessage):x.a11y.notify(x.params.prevSlideMessage)),e(a.target).is("."+x.params.bulletClass)&&e(a.target)[0].click())},liveRegion:e('<span class="'+x.params.notificationClass+'" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var a=x.a11y.liveRegion;0!==a.length&&(a.html(""),a.html(e))},init:function(){x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.a11y.makeFocusable(x.nextButton),x.a11y.addRole(x.nextButton,"button"),x.a11y.addLabel(x.nextButton,x.params.nextSlideMessage)),x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.a11y.makeFocusable(x.prevButton),x.a11y.addRole(x.prevButton,"button"),x.a11y.addLabel(x.prevButton,x.params.prevSlideMessage)),e(x.container).append(x.a11y.liveRegion)},initPagination:function(){x.params.pagination&&x.params.paginationClickable&&x.bullets&&x.bullets.length&&x.bullets.each(function(){var a=e(this);x.a11y.makeFocusable(a),x.a11y.addRole(a,"button"),x.a11y.addLabel(a,x.params.paginationBulletMessage.replace(/{{index}}/,a.index()+1))})},destroy:function(){x.a11y.liveRegion&&x.a11y.liveRegion.length>0&&x.a11y.liveRegion.remove()}},x.init=function(){x.params.loop&&x.createLoop(),x.updateContainerSize(),x.updateSlidesSize(),x.updatePagination(),x.params.scrollbar&&x.scrollbar&&(x.scrollbar.set(),x.params.scrollbarDraggable&&x.scrollbar.enableDraggable()),"slide"!==x.params.effect&&x.effects[x.params.effect]&&(x.params.loop||x.updateProgress(),x.effects[x.params.effect].setTranslate()),x.params.loop?x.slideTo(x.params.initialSlide+x.loopedSlides,0,x.params.runCallbacksOnInit):(x.slideTo(x.params.initialSlide,0,x.params.runCallbacksOnInit),0===x.params.initialSlide&&(x.parallax&&x.params.parallax&&x.parallax.setTranslate(),x.lazy&&x.params.lazyLoading&&(x.lazy.load(),x.lazy.initialImageLoaded=!0))),x.attachEvents(),x.params.observer&&x.support.observer&&x.initObservers(),x.params.preloadImages&&!x.params.lazyLoading&&x.preloadImages(),x.params.zoom&&x.zoom&&x.zoom.init(),x.params.autoplay&&x.startAutoplay(),x.params.keyboardControl&&x.enableKeyboardControl&&x.enableKeyboardControl(),x.params.mousewheelControl&&x.enableMousewheelControl&&x.enableMousewheelControl(),x.params.hashnavReplaceState&&(x.params.replaceState=x.params.hashnavReplaceState),x.params.history&&x.history&&x.history.init(),x.params.hashnav&&x.hashnav&&x.hashnav.init(),x.params.a11y&&x.a11y&&x.a11y.init(),x.emit("onInit",x)},x.cleanupStyles=function(){x.container.removeClass(x.classNames.join(" ")).removeAttr("style"),x.wrapper.removeAttr("style"),x.slides&&x.slides.length&&x.slides.removeClass([x.params.slideVisibleClass,x.params.slideActiveClass,x.params.slideNextClass,x.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),x.paginationContainer&&x.paginationContainer.length&&x.paginationContainer.removeClass(x.params.paginationHiddenClass),x.bullets&&x.bullets.length&&x.bullets.removeClass(x.params.bulletActiveClass),x.params.prevButton&&e(x.params.prevButton).removeClass(x.params.buttonDisabledClass),x.params.nextButton&&e(x.params.nextButton).removeClass(x.params.buttonDisabledClass),x.params.scrollbar&&x.scrollbar&&(x.scrollbar.track&&x.scrollbar.track.length&&x.scrollbar.track.removeAttr("style"),x.scrollbar.drag&&x.scrollbar.drag.length&&x.scrollbar.drag.removeAttr("style"))},x.destroy=function(e,a){x.detachEvents(),x.stopAutoplay(),x.params.scrollbar&&x.scrollbar&&x.params.scrollbarDraggable&&x.scrollbar.disableDraggable(),x.params.loop&&x.destroyLoop(),a&&x.cleanupStyles(),x.disconnectObservers(),x.params.zoom&&x.zoom&&x.zoom.destroy(),x.params.keyboardControl&&x.disableKeyboardControl&&x.disableKeyboardControl(),x.params.mousewheelControl&&x.disableMousewheelControl&&x.disableMousewheelControl(),x.params.a11y&&x.a11y&&x.a11y.destroy(),x.params.history&&!x.params.replaceState&&window.removeEventListener("popstate",x.history.setHistoryPopState),x.params.hashnav&&x.hashnav&&x.hashnav.destroy(),x.emit("onDestroy"),!1!==e&&(x=null)},x.init(),x}};a.prototype={isSafari:function(){var e=window.navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1,lteIE9:function(){var e=document.createElement("div");return e.innerHTML="\x3c!--[if lte IE 9]><i></i><![endif]--\x3e",1===e.getElementsByTagName("i").length}()},device:function(){var e=window.navigator.userAgent,a=e.match(/(Android);?[\s\/]+([\d.]+)?/),t=e.match(/(iPad).*OS\s([\d_]+)/),s=e.match(/(iPod)(.*OS\s([\d_]+))?/),i=!t&&e.match(/(iPhone\sOS|iOS)\s([\d_]+)/);return{ios:t||i||s,android:a}}(),support:{touch:window.Modernizr&&!0===Modernizr.touch||!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch),transforms3d:window.Modernizr&&!0===Modernizr.csstransforms3d||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,a="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),t=0;t<a.length;t++)if(a[t]in e)return!0}(),observer:"MutationObserver"in window||"WebkitMutationObserver"in window,passiveListener:function(){var e=!1;try{var a=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("testPassiveListener",null,a)}catch(e){}return e}(),gestures:"ongesturestart"in window},plugins:{}};for(var t=function(){var e=function(e){var a=0;for(a=0;a<e.length;a++)this[a]=e[a];return this.length=e.length,this},a=function(a,t){var s=[],i=0;if(a&&!t&&a instanceof e)return a;if(a)if("string"==typeof a){var r,n,o=a.trim();if(o.indexOf("<")>=0&&o.indexOf(">")>=0){var l="div";for(0===o.indexOf("<li")&&(l="ul"),0===o.indexOf("<tr")&&(l="tbody"),0!==o.indexOf("<td")&&0!==o.indexOf("<th")||(l="tr"),0===o.indexOf("<tbody")&&(l="table"),0===o.indexOf("<option")&&(l="select"),(n=document.createElement(l)).innerHTML=a,i=0;i<n.childNodes.length;i++)s.push(n.childNodes[i])}else for(r=t||"#"!==a[0]||a.match(/[ .<>:~]/)?(t||document).querySelectorAll(a):[document.getElementById(a.split("#")[1])],i=0;i<r.length;i++)r[i]&&s.push(r[i])}else if(a.nodeType||a===window||a===document)s.push(a);else if(a.length>0&&a[0].nodeType)for(i=0;i<a.length;i++)s.push(a[i]);return new e(s)};return e.prototype={addClass:function(e){if(void 0===e)return this;for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.add(a[t]);return this},removeClass:function(e){for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.remove(a[t]);return this},hasClass:function(e){return!!this[0]&&this[0].classList.contains(e)},toggleClass:function(e){for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.toggle(a[t]);return this},attr:function(e,a){if(1===arguments.length&&"string"==typeof e)return this[0]?this[0].getAttribute(e):void 0;for(var t=0;t<this.length;t++)if(2===arguments.length)this[t].setAttribute(e,a);else for(var s in e)this[t][s]=e[s],this[t].setAttribute(s,e[s]);return this},removeAttr:function(e){for(var a=0;a<this.length;a++)this[a].removeAttribute(e);return this},data:function(e,a){if(void 0!==a){for(var t=0;t<this.length;t++){var s=this[t];s.dom7ElementDataStorage||(s.dom7ElementDataStorage={}),s.dom7ElementDataStorage[e]=a}return this}if(this[0]){var i=this[0].getAttribute("data-"+e);return i||(this[0].dom7ElementDataStorage&&e in this[0].dom7ElementDataStorage?this[0].dom7ElementDataStorage[e]:void 0)}},transform:function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this},transition:function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this},on:function(e,t,s,i){function r(e){var i=e.target;if(a(i).is(t))s.call(i,e);else for(var r=a(i).parents(),n=0;n<r.length;n++)a(r[n]).is(t)&&s.call(r[n],e)}var n,o,l=e.split(" ");for(n=0;n<this.length;n++)if("function"==typeof t||!1===t)for("function"==typeof t&&(s=arguments[1],i=arguments[2]||!1),o=0;o<l.length;o++)this[n].addEventListener(l[o],s,i);else for(o=0;o<l.length;o++)this[n].dom7LiveListeners||(this[n].dom7LiveListeners=[]),this[n].dom7LiveListeners.push({listener:s,liveListener:r}),this[n].addEventListener(l[o],r,i);return this},off:function(e,a,t,s){for(var i=e.split(" "),r=0;r<i.length;r++)for(var n=0;n<this.length;n++)if("function"==typeof a||!1===a)"function"==typeof a&&(t=arguments[1],s=arguments[2]||!1),this[n].removeEventListener(i[r],t,s);else if(this[n].dom7LiveListeners)for(var o=0;o<this[n].dom7LiveListeners.length;o++)this[n].dom7LiveListeners[o].listener===t&&this[n].removeEventListener(i[r],this[n].dom7LiveListeners[o].liveListener,s);return this},once:function(e,a,t,s){function i(n){t(n),r.off(e,a,i,s)}var r=this;"function"==typeof a&&(a=!1,t=arguments[1],s=arguments[2]),r.on(e,a,i,s)},trigger:function(e,a){for(var t=0;t<this.length;t++){var s;try{s=new window.CustomEvent(e,{detail:a,bubbles:!0,cancelable:!0})}catch(t){(s=document.createEvent("Event")).initEvent(e,!0,!0),s.detail=a}this[t].dispatchEvent(s)}return this},transitionEnd:function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<s.length;t++)i.off(s[t],a)}var t,s=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=this;if(e)for(t=0;t<s.length;t++)i.on(s[t],a);return this},width:function(){return this[0]===window?window.innerWidth:this.length>0?parseFloat(this.css("width")):null},outerWidth:function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?parseFloat(this.css("height")):null},outerHeight:function(e){return this.length>0?e?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var e=this[0],a=e.getBoundingClientRect(),t=document.body,s=e.clientTop||t.clientTop||0,i=e.clientLeft||t.clientLeft||0,r=window.pageYOffset||e.scrollTop,n=window.pageXOffset||e.scrollLeft;return{top:a.top+r-s,left:a.left+n-i}}return null},css:function(e,a){var t;if(1===arguments.length){if("string"!=typeof e){for(t=0;t<this.length;t++)for(var s in e)this[t].style[s]=e[s];return this}if(this[0])return window.getComputedStyle(this[0],null).getPropertyValue(e)}if(2===arguments.length&&"string"==typeof e){for(t=0;t<this.length;t++)this[t].style[e]=a;return this}return this},each:function(e){for(var a=0;a<this.length;a++)e.call(this[a],a,this[a]);return this},html:function(e){if(void 0===e)return this[0]?this[0].innerHTML:void 0;for(var a=0;a<this.length;a++)this[a].innerHTML=e;return this},text:function(e){if(void 0===e)return this[0]?this[0].textContent.trim():null;for(var a=0;a<this.length;a++)this[a].textContent=e;return this},is:function(t){if(!this[0])return!1;var s,i;if("string"==typeof t){var r=this[0];if(r===document)return t===document;if(r===window)return t===window;if(r.matches)return r.matches(t);if(r.webkitMatchesSelector)return r.webkitMatchesSelector(t);if(r.mozMatchesSelector)return r.mozMatchesSelector(t);if(r.msMatchesSelector)return r.msMatchesSelector(t);for(s=a(t),i=0;i<s.length;i++)if(s[i]===this[0])return!0;return!1}if(t===document)return this[0]===document;if(t===window)return this[0]===window;if(t.nodeType||t instanceof e){for(s=t.nodeType?[t]:t,i=0;i<s.length;i++)if(s[i]===this[0])return!0;return!1}return!1},index:function(){if(this[0]){for(var e=this[0],a=0;null!==(e=e.previousSibling);)1===e.nodeType&&a++;return a}},eq:function(a){if(void 0===a)return this;var t,s=this.length;return a>s-1?new e([]):a<0?(t=s+a,new e(t<0?[]:[this[t]])):new e([this[a]])},append:function(a){var t,s;for(t=0;t<this.length;t++)if("string"==typeof a){var i=document.createElement("div");for(i.innerHTML=a;i.firstChild;)this[t].appendChild(i.firstChild)}else if(a instanceof e)for(s=0;s<a.length;s++)this[t].appendChild(a[s]);else this[t].appendChild(a);return this},prepend:function(a){var t,s;for(t=0;t<this.length;t++)if("string"==typeof a){var i=document.createElement("div");for(i.innerHTML=a,s=i.childNodes.length-1;s>=0;s--)this[t].insertBefore(i.childNodes[s],this[t].childNodes[0])}else if(a instanceof e)for(s=0;s<a.length;s++)this[t].insertBefore(a[s],this[t].childNodes[0]);else this[t].insertBefore(a,this[t].childNodes[0]);return this},insertBefore:function(e){for(var t=a(e),s=0;s<this.length;s++)if(1===t.length)t[0].parentNode.insertBefore(this[s],t[0]);else if(t.length>1)for(var i=0;i<t.length;i++)t[i].parentNode.insertBefore(this[s].cloneNode(!0),t[i])},insertAfter:function(e){for(var t=a(e),s=0;s<this.length;s++)if(1===t.length)t[0].parentNode.insertBefore(this[s],t[0].nextSibling);else if(t.length>1)for(var i=0;i<t.length;i++)t[i].parentNode.insertBefore(this[s].cloneNode(!0),t[i].nextSibling)},next:function(t){return new e(this.length>0?t?this[0].nextElementSibling&&a(this[0].nextElementSibling).is(t)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.nextElementSibling;){var r=i.nextElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},prev:function(t){return new e(this.length>0?t?this[0].previousElementSibling&&a(this[0].previousElementSibling).is(t)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.previousElementSibling;){var r=i.previousElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},parent:function(e){for(var t=[],s=0;s<this.length;s++)e?a(this[s].parentNode).is(e)&&t.push(this[s].parentNode):t.push(this[s].parentNode);return a(a.unique(t))},parents:function(e){for(var t=[],s=0;s<this.length;s++)for(var i=this[s].parentNode;i;)e?a(i).is(e)&&t.push(i):t.push(i),i=i.parentNode;return a(a.unique(t))},find:function(a){for(var t=[],s=0;s<this.length;s++)for(var i=this[s].querySelectorAll(a),r=0;r<i.length;r++)t.push(i[r]);return new e(t)},children:function(t){for(var s=[],i=0;i<this.length;i++)for(var r=this[i].childNodes,n=0;n<r.length;n++)t?1===r[n].nodeType&&a(r[n]).is(t)&&s.push(r[n]):1===r[n].nodeType&&s.push(r[n]);return new e(a.unique(s))},remove:function(){for(var e=0;e<this.length;e++)this[e].parentNode&&this[e].parentNode.removeChild(this[e]);return this},add:function(){var e,t;for(e=0;e<arguments.length;e++){var s=a(arguments[e]);for(t=0;t<s.length;t++)this[this.length]=s[t],this.length++}return this}},a.fn=e.prototype,a.unique=function(e){for(var a=[],t=0;t<e.length;t++)-1===a.indexOf(e[t])&&a.push(e[t]);return a},a}(),s=["jQuery","Zepto","Dom7"],i=0;i<s.length;i++)window[s[i]]&&function(e){e.fn.swiper=function(t){var s;return e(this).each(function(){var e=new a(this,t);s||(s=e)}),s}}(window[s[i]]);var r;(r=void 0===t?window.Dom7||window.Zepto||window.jQuery:t)&&("transitionEnd"in r.fn||(r.fn.transitionEnd=function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<s.length;t++)i.off(s[t],a)}var t,s=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=this;if(e)for(t=0;t<s.length;t++)i.on(s[t],a);return this}),"transform"in r.fn||(r.fn.transform=function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this}),"transition"in r.fn||(r.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this}),"outerWidth"in r.fn||(r.fn.outerWidth=function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null})),window.Swiper=a}(),"undefined"!=typeof module?module.exports=window.Swiper:"function"==typeof define&&define.amd&&define([],function(){"use strict";return window.Swiper});
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/tab.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/tab.min.js
new file mode 100755
index 0000000..94476aa
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/tab.min.js
@@ -0,0 +1 @@
+window.openTab=function(e){for(var t=event.target;!t.parentNode.classList.contains("tab");){if("BODY"==t.nodeName)return console.error("The component tab not found, please check your code."),!1;t=t.parentNode}for(var a=document.getElementById(e).parentNode.getElementsByClassName("tab-content"),s=t.parentNode.getElementsByClassName("active"),n=0;n<a.length;n++)a[n].setAttribute("class",a[n].getAttribute("class").replace("active",""));for(n=0;n<s.length;n++)s[n].setAttribute("class",s[n].getAttribute("class").replace("active",""));t.setAttribute("class",t.getAttribute("class")+" active"),document.getElementById(e).setAttribute("class",document.getElementById(e).getAttribute("class")+" active")};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/js/toast.min.js b/platforms/android/app/src/main/assets/www/mobileui/js/toast.min.js
new file mode 100755
index 0000000..75db5f7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/js/toast.min.js
@@ -0,0 +1 @@
+window.openToast=function(e){var t={class:"black radius padding shadow",duration:2e3,position:"bottom",onclick:window.closeToast};"string"==typeof e&&(t.message=e),"object"==typeof e&&e.message&&(t.message=e.message),"object"==typeof e&&e.class&&(t.class=e.class),"object"==typeof e&&e.duration&&(t.duration=e.duration),"object"==typeof e&&e.position&&(t.position="toast-"+e.position),"object"==typeof e&&e.onclick&&(t.onclick=e.onclick);var o=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(o=event.target.parentNode);var a=document.createElement("div");a.className="toast",a.classList.add(t.position);var n=document.createElement("div");n.className=t.class,n.innerHTML=t.message,n.onclick=t.onclick,a.appendChild(n),o.appendChild(a),setTimeout(function(){a.classList.add("show")},100),setTimeout(function(){if(!a)return!1;a.classList.remove("show"),setTimeout(function(){if(!a.parentNode)return!1;a.parentNode.removeChild(a)},400)},t.duration)},window.closeToast=function(e){e.target.parentNode.classList.remove("show"),setTimeout(function(){e.target.parentNode.parentNode.removeChild(e.target.parentNode)},400)};
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/mobileui/mobileui.js b/platforms/android/app/src/main/assets/www/mobileui/mobileui.js
new file mode 100644
index 0000000..4675be7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/mobileui.js
@@ -0,0 +1,3 @@
+/*component-base*/var userAgent=navigator.userAgent||navigator.vendor||window.opera,SO={name:"unknown",code:0};/android/i.test(userAgent)&&(SO.name="Android",SO.class="platform-android",SO.code=1);/iPad|iPhone|iPod/.test(userAgent)&&!window.MSStream&&(SO.name="iOS",SO.class="platform-ios",SO.code=2);/windows phone/i.test(userAgent)&&(SO.name="Windows Phone",SO.class="platform-wp",SO.code=3);SO.class&&document.getElementsByTagName("body").length&&(document.getElementsByTagName("body")[0].className+=" "+SO.class);
+
+/*component-button*/document.addEventListener("click",function(e){if(1!==SO.code)return!1;var t=e.target;if("button"!==t.tagName.toLowerCase())return!1;var o=t.getBoundingClientRect(),s=t.querySelector(".ripple");s||((s=document.createElement("span")).className="ripple",s.style.height=s.style.width=Math.max(o.width,o.height)+"px",t.appendChild(s)),s.classList.remove("show");var a=e.pageY-o.top-s.offsetHeight/2-document.body.scrollTop,l=e.pageX-o.left-s.offsetWidth/2-document.body.scrollLeft;return s.style.top=a+"px",s.style.left=l+"px",s.classList.add("show"),!1},!1);
diff --git a/platforms/android/app/src/main/assets/www/mobileui/style.css b/platforms/android/app/src/main/assets/www/mobileui/style.css
new file mode 100644
index 0000000..d0433d2
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/mobileui/style.css
@@ -0,0 +1,34 @@
+.component-base{display:block}*{-webkit-tap-highlight-color:transparent;margin:0;padding:0;box-sizing:border-box;outline:0}body{-webkit-touch-callout:none;-webkit-text-size-adjust:none;-webkit-user-select:none;background-color:#fff;font-size:14px;height:100%;margin:0;padding:0;width:100%}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}*{box-sizing:border-box;outline:0}body{font-family:Roboto,"Helvetica Neue",sans-serif;-webkit-overflow-scrolling:touch;overflow:hidden;position:absolute}body.platform-ios{font-family:-apple-system,"Helvetica Neue",Roboto,sans-serif}a{cursor:pointer;color:#000;text-decoration:none}.content{position:absolute;width:100%;overflow:auto}.left{float:left}.right{float:right}.top{position:absolute;top:0;left:0}.bottom{position:absolute;bottom:0;left:0}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.border{border-width:1px;border-style:solid}.hidden{display:none}.opacity-90{opacity:.9}.opacity-80{opacity:.8}.opacity-70{opacity:.7}.opacity-60{opacity:.6}.opacity-50{opacity:.5}.opacity-40{opacity:.4}.opacity-30{opacity:.3}.opacity-20{opacity:.2}.opacity-10{opacity:.1}.line{width:100%;height:1px;display:block;clear:both}.icon{font-size:28px}img,video{max-width:100%}p{margin-top:5px;margin-bottom:5px}.padding{padding:10px}.padding-top{padding-top:10px}.margin{margin:10px}span.padding{padding:6px;padding-top:2px;padding-bottom:2px}.radius{border-radius:4px}.radius-big{border-radius:22px}.circle{border-radius:50%}.radius-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.radius-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.radius-top{border-top-left-radius:4px;border-top-right-radius:4px}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shadow{box-shadow:1px 1px 3px rgba(0,0,0,.2)}.space{width:100%;height:20px}.space-big{width:100%;height:50px}.space-huge{width:100%;height:100px}.margin-bottom{margin-bottom:10px}.margin-top{margin-top:10px}.text-shadow{text-shadow:1px 1px 3px rgba(0,0,0,.2)}.text-small{font-size:14px}.text-small .icon,.text-small.icon{font-size:14px!important}.icon-small{font-size:14px!important}.icon-big{font-size:50px!important}.icon-huge{font-size:65px!important}.icon-extra-huge{font-size:120px!important}.text-big{font-size:22px}.text-big .icon,.text-big.icon{font-size:22px!important}.text-extra-huge{font-size:65px}.text-extra-huge .icon,.text-extra-huge.icon{font-size:65px!important}.text-huge{font-size:32px}.text-huge .icon,.text-huge.icon{font-size:32px!important}.text-light{font-weight:300}.text-bold{font-weight:700}.text-strong{font-weight:800}.float-bottom-right{position:fixed;right:15px;bottom:15px}.float-bottom-left{position:fixed;left:15px;bottom:15px}.float-bottom-center{position:fixed;margin:auto;left:0;bottom:15px}.icon-circle{width:40px;height:40px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small{width:25px;height:25px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small i{font-size:15px}.icon-circle-big{width:80px;height:80px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-big i{font-size:70px}.backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.01;z-index:9999;transition-duration:280ms}.backdrop.show{opacity:0.3}.mark{border-left-width:8px!important}.red{color:rgba(255,255,255,.9);background-color:#f44336!important}.red-100,.red-200,.red-300,.red-50{color:rgba(0,0,0,.8)}.red-50,input[type=checkbox].red-50.switch::after{background-color:#ffebee!important}.red-100,input[type=checkbox].red-100.switch::after{background-color:#ffcdd2!important}.red-200,input[type=checkbox].red-200.switch::after{background-color:#ef9a9a!important}.red-300,input[type=checkbox].red-300.switch::after{background-color:#e57373!important}.pink,.red-400,.red-500,.red-600,.red-700,.red-800,.red-900{color:rgba(255,255,255,.9)}.red-400,input[type=checkbox].red-400.switch::after{background-color:#ef5350!important}.red-500,input[type=checkbox].red-500.switch::after{background-color:#f44336!important}.red-600,input[type=checkbox].red-600.switch::after{background-color:#e53935!important}.red-700,input[type=checkbox].red-700.switch::after{background-color:#d32f2f!important}.red-800,input[type=checkbox].red-800.switch::after{background-color:#c62828!important}.red-900,input[type=checkbox].red-900.switch::after{background-color:#b71c1c!important}.pink,input[type=checkbox].pink.switch::after{background-color:#e91e63!important}.pink-100,.pink-200,.pink-50{color:rgba(0,0,0,.8)}.pink-50,input[type=checkbox].pink-50.switch::after{background-color:#fce4ec!important}.pink-100,input[type=checkbox].pink-100.switch::after{background-color:#f8bbd0!important}.pink-200,input[type=checkbox].pink-200.switch::after{background-color:#f48fb1!important}.Pink-300,.pink-400,.pink-500,.pink-600,.pink-700,.pink-800,.pink-900,.purple{color:rgba(255,255,255,.9)}.Pink-300,input[type=checkbox].Pink-300.switch::after{background-color:#f06292!important}.pink-400,input[type=checkbox].pink-400.switch::after{background-color:#ec407a!important}.pink-500,input[type=checkbox].pink-500.switch::after{background-color:#e91e63!important}.pink-600,input[type=checkbox].pink-600.switch::after{background-color:#d81b60!important}.pink-700,input[type=checkbox].pink-700.switch::after{background-color:#c2185b!important}.pink-800,input[type=checkbox].pink-800.switch::after{background-color:#ad1457!important}.pink-900,input[type=checkbox].pink-900.switch::after{background-color:#880e4f!important}.purple,input[type=checkbox].purple.switch::after{background-color:#9c27b0!important}.purple-100,.purple-200,.purple-50{color:rgba(0,0,0,.8)}.purple-50,input[type=checkbox].purple-50.switch::after{background-color:#f3e5f5!important}.purple-100,input[type=checkbox].purple-100.switch::after{background-color:#e1bee7!important}.purple-200,input[type=checkbox].purple-200.switch::after{background-color:#ce93d8!important}.deep-purple,.purple-300,.purple-400,.purple-500,.purple-600,.purple-700,.purple-800,.purple-900{color:rgba(255,255,255,.9)}.purple-300,input[type=checkbox].purple-300.switch::after{background-color:#ba68c8!important}.purple-400,input[type=checkbox].purple-400.switch::after{background-color:#ab47bc!important}.purple-500,input[type=checkbox].purple-500.switch::after{background-color:#9c27b0!important}.purple-600,input[type=checkbox].purple-600.switch::after{background-color:#8e24aa!important}.purple-700,input[type=checkbox].purple-700.switch::after{background-color:#7b1fa2!important}.purple-800,input[type=checkbox].purple-800.switch::after{background-color:#6a1b9a!important}.purple-900,input[type=checkbox].purple-900.switch::after{background-color:#4a148c!important}.deep-purple,input[type=checkbox].deep-purple.switch::after{background-color:#673ab7!important}.deep-purple-50{color:rgba(0,0,0,.8);background-color:#ede7f6!important}.deep-purple-100{color:rgba(0,0,0,.8);background-color:#d1c4e9!important}.deep-purple-200{color:rgba(0,0,0,.8);background-color:#b39ddb!important}.deep-purple-300,.deep-purple-400,.deep-purple-500,.deep-purple-600,.deep-purple-700,.deep-purple-800,.deep-purple-900,.indigo{color:rgba(255,255,255,.9)}.deep-purple-300,input[type=checkbox].deep-purple-300.switch::after{background-color:#9575cd!important}.deep-purple-400,input[type=checkbox].deep-purple-400.switch::after{background-color:#7e57c2!important}.deep-purple-500,input[type=checkbox].deep-purple-500.switch::after{background-color:#673ab7!important}.deep-purple-600,input[type=checkbox].deep-purple-600.switch::after{background-color:#5e35b1!important}.deep-purple-700,input[type=checkbox].deep-purple-700.switch::after{background-color:#512da8!important}.deep-purple-800,input[type=checkbox].deep-purple-800.switch::after{background-color:#4527a0!important}.deep-purple-900,input[type=checkbox].deep-purple-900.switch::after{background-color:#311b92!important}.indigo,input[type=checkbox].indigo.switch::after{background-color:#3f51b5!important}.indigo-100,.indigo-200,.indigo-50{color:rgba(0,0,0,.8)}.indigo-50,input[type=checkbox].indigo-50.switch::after{background-color:#e8eaf6!important}.indigo-100,input[type=checkbox].indigo-100.switch::after{background-color:#c5cae9!important}.indigo-200,input[type=checkbox].indigo-200.switch::after{background-color:#9fa8da!important}.blue,.indigo-300,.indigo-400,.indigo-500,.indigo-600,.indigo-700,.indigo-800,.indigo-900{color:rgba(255,255,255,.9)}.indigo-300,input[type=checkbox].indigo-300.switch::after{background-color:#7986cb!important}.indigo-400,input[type=checkbox].indigo-400.switch::after{background-color:#5c6bc0!important}.indigo-500,input[type=checkbox].indigo-500.switch::after{background-color:#3f51b5!important}.indigo-600,input[type=checkbox].indigo-600.switch::after{background-color:#3949ab!important}.indigo-700,input[type=checkbox].indigo-700.switch::after{background-color:#303f9f!important}.indigo-800,input[type=checkbox].indigo-800.switch::after{background-color:#283593!important}.indigo-900,input[type=checkbox].indigo-900.switch::after{background-color:#1a237e!important}.blue,input[type=checkbox].blue.switch::after{background-color:#2196f3!important}.blue-100,.blue-200,.blue-300,.blue-400,.blue-50{color:rgba(0,0,0,.8)}.blue-50,input[type=checkbox].blue-50.switch::after{background-color:#e3f2fd!important}.blue-100,input[type=checkbox].blue-100.switch::after{background-color:#bbdefb!important}.blue-200,input[type=checkbox].blue-200.switch::after{background-color:#90caf9!important}.blue-300,input[type=checkbox].blue-300.switch::after{background-color:#64b5f6!important}.blue-400,input[type=checkbox].blue-400.switch::after{background-color:#42a5f5!important}.blue-500,.blue-600,.blue-700,.blue-800,.blue-900,.light-blue{color:rgba(255,255,255,.9)}.blue-500,input[type=checkbox].blue-500.switch::after{background-color:#2196f3!important}.blue-600,input[type=checkbox].blue-600.switch::after{background-color:#1e88e5!important}.blue-700,input[type=checkbox].blue-700.switch::after{background-color:#1976d2!important}.blue-800,input[type=checkbox].blue-800.switch::after{background-color:#1565c0!important}.blue-900,input[type=checkbox].blue-900.switch::after{background-color:#0d47a1!important}.light-blue,input[type=checkbox].light-blue.switch::after{background-color:#03a9f4!important}.light-blue-100,.light-blue-200,.light-blue-300,.light-blue-400,.light-blue-50,.light-blue-500{color:rgba(0,0,0,.8)}.light-blue-50,input[type=checkbox].light-blue-50.switch::after{background-color:#e1f5fe!important}.light-blue-100,input[type=checkbox].light-blue-100.switch::after{background-color:#b3e5fc!important}.light-blue-200,input[type=checkbox].light-blue-200.switch::after{background-color:#81d4fa!important}.light-blue-300,input[type=checkbox].light-blue-300.switch::after{background-color:#4fc3f7!important}.light-blue-400,input[type=checkbox].light-blue-400.switch::after{background-color:#29b6f6!important}.light-blue-500,input[type=checkbox].light-blue-500.switch::after{background-color:#03a9f4!important}.cyan,.light-blue-600,.light-blue-700,.light-blue-800,.light-blue-900{color:rgba(255,255,255,.9)}.light-blue-600,input[type=checkbox].light-blue-600.switch::after{background-color:#039be5!important}.light-blue-700,input[type=checkbox].light-blue-700.switch::after{background-color:#0288d1!important}.light-blue-800,input[type=checkbox].light-blue-800.switch::after{background-color:#0277bd!important}.light-blue-900,input[type=checkbox].light-blue-900.switch::after{background-color:#01579b!important}.cyan,input[type=checkbox].cyan.switch::after{background-color:#00bcd4!important}.cyan-100,.cyan-200,.cyan-300,.cyan-400,.cyan-50,.cyan-500,.cyan-600{color:rgba(0,0,0,.8)}.cyan-50,input[type=checkbox].cyan-50.switch::after{background-color:#e0f7fa!important}.cyan-100,input[type=checkbox].cyan-100.switch::after{background-color:#b2ebf2!important}.cyan-200,input[type=checkbox].cyan-200.switch::after{background-color:#80deea!important}.cyan-300,input[type=checkbox].cyan-300.switch::after{background-color:#4dd0e1!important}.cyan-400,input[type=checkbox].cyan-400.switch::after{background-color:#26c6da!important}.cyan-500,input[type=checkbox].cyan-500.switch::after{background-color:#00bcd4!important}.cyan-600,input[type=checkbox].cyan-600.switch::after{background-color:#00acc1!important}.cyan-700,.cyan-800,.cyan-900,.teal{color:rgba(255,255,255,.9)}.cyan-700,input[type=checkbox].cyan-700.switch::after{background-color:#0097a7!important}.cyan-800,input[type=checkbox].cyan-800.switch::after{background-color:#00838f!important}.cyan-900,input[type=checkbox].cyan-900.switch::after{background-color:#006064!important}.teal,input[type=checkbox].teal.switch::after{background-color:#009688!important}.teal-100,.teal-200,.teal-300,.teal-400,.teal-50{color:rgba(0,0,0,.8)}.teal-50,input[type=checkbox].teal-50.switch::after{background-color:#e0f2f1!important}.teal-100,input[type=checkbox].teal-100.switch::after{background-color:#b2dfdb!important}.teal-200,input[type=checkbox].teal-200.switch::after{background-color:#80cbc4!important}.teal-300,input[type=checkbox].teal-300.switch::after{background-color:#4db6ac!important}.teal-400,input[type=checkbox].teal-400.switch::after{background-color:#26a69a!important}.green,.teal-500,.teal-600,.teal-700,.teal-800,.teal-900{color:rgba(255,255,255,.9)}.teal-500,input[type=checkbox].teal-500.switch::after{background-color:#009688!important}.teal-600,input[type=checkbox].teal-600.switch::after{background-color:#00897b!important}.teal-700,input[type=checkbox].teal-700.switch::after{background-color:#00796b!important}.teal-800,input[type=checkbox].teal-800.switch::after{background-color:#00695c!important}.teal-900,input[type=checkbox].teal-900.switch::after{background-color:#004d40!important}.green,input[type=checkbox].green.switch::after{background-color:#4caf50!important}.green-100,.green-200,.green-300,.green-400,.green-50,.green-500{color:rgba(0,0,0,.8)}.green-50,input[type=checkbox].green-50.switch::after{background-color:#e8f5e9!important}.green-100,input[type=checkbox].green-100.switch::after{background-color:#c8e6c9!important}.green-200,input[type=checkbox].green-200.switch::after{background-color:#a5d6a7!important}.green-300,input[type=checkbox].green-300.switch::after{background-color:#81c784!important}.green-400,input[type=checkbox].green-400.switch::after{background-color:#66bb6a!important}.green-500,input[type=checkbox].green-500.switch::after{background-color:#4caf50!important}.green-600,.green-700,.green-800,.green-900,.light-green{color:rgba(255,255,255,.9)}.green-600,input[type=checkbox].green-600.switch::after{background-color:#43a047!important}.green-700,input[type=checkbox].green-700.switch::after{background-color:#388e3c!important}.green-800,input[type=checkbox].green-800.switch::after{background-color:#2e7d32!important}.green-900,input[type=checkbox].green-900.switch::after{background-color:#1b5e20!important}.light-green,input[type=checkbox].light-green.switch::after{background-color:#8bc34a!important}.light-green-100,.light-green-200,.light-green-300,.light-green-400,.light-green-50,.light-green-500,.light-green-600{color:rgba(0,0,0,.8)}.light-green-50,input[type=checkbox].light-green-50.switch::after{background-color:#f1f8e9!important}.light-green-100,input[type=checkbox].light-green-100.switch::after{background-color:#dcedc8!important}.light-green-200,input[type=checkbox].light-green-200.switch::after{background-color:#c5e1a5!important}.light-green-300,input[type=checkbox].light-green-300.switch::after{background-color:#aed581!important}.light-green-400,input[type=checkbox].light-green-400.switch::after{background-color:#9ccc65!important}.light-green-500,input[type=checkbox].light-green-500.switch::after{background-color:#8bc34a!important}.light-green-600,input[type=checkbox].light-green-600.switch::after{background-color:#7cb342!important}.light-green-700,.light-green-800,.light-green-900,.lime{color:rgba(255,255,255,.9)}.light-green-700,input[type=checkbox].light-green-700.switch::after{background-color:#689f38!important}.light-green-800,input[type=checkbox].light-green-800.switch::after{background-color:#558b2f!important}.light-green-900,input[type=checkbox].light-green-900.switch::after{background-color:#33691e!important}.lime,input[type=checkbox].lime.switch::after{background-color:#cddc39!important}.lime-100,.lime-200,.lime-300,.lime-400,.lime-50,.lime-500,.lime-600,.lime-700,.lime-800{color:rgba(0,0,0,.8)}.lime-50,input[type=checkbox].lime-50.switch::after{background-color:#f9fbe7!important}.lime-100,input[type=checkbox].lime-100.switch::after{background-color:#f0f4c3!important}.lime-200,input[type=checkbox].lime-200.switch::after{background-color:#e6ee9c!important}.lime-300,input[type=checkbox].lime-300.switch::after{background-color:#dce775!important}.lime-400,input[type=checkbox].lime-400.switch::after{background-color:#d4e157!important}.lime-500,input[type=checkbox].lime-500.switch::after{background-color:#cddc39!important}.lime-600,input[type=checkbox].lime-600.switch::after{background-color:#c0ca33!important}.lime-700,input[type=checkbox].lime-700.switch::after{background-color:#afb42b!important}.lime-800,input[type=checkbox].lime-800.switch::after{background-color:#9e9d24!important}.lime-900,.yellow{color:rgba(255,255,255,.9)}.lime-900,input[type=checkbox].lime-900.switch::after{background-color:#827717!important}.yellow,input[type=checkbox].yellow.switch::after{background-color:#ffeb3b!important}.yellow-100,.yellow-200,.yellow-300,.yellow-50,.yellow-500,.yellow-600,.yellow-700,.yellow-800,.yellow-900{color:rgba(0,0,0,.8)}.yellow-50,input[type=checkbox].yellow-50.switch::after{background-color:#fffde7!important}.yellow-100,input[type=checkbox].yellow-100.switch::after{background-color:#fff9c4!important}.yellow-200,input[type=checkbox].yellow-200.switch::after{background-color:#fff59d!important}.yellow-300,input[type=checkbox].yellow-300.switch::after{background-color:#fff176!important}.yellow-400{color:rgba(0,0,0,.8);background-color:#ffee58!important}.yellow-500,input[type=checkbox].yellow-500.switch::after{background-color:#ffeb3b!important}.yellow-600,input[type=checkbox].yellow-600.switch::after{background-color:#fdd835!important}.yellow-700,input[type=checkbox].yellow-700.switch::after{background-color:#fbc02d!important}.yellow-800,input[type=checkbox].yellow-800.switch::after{background-color:#f9a825!important}.yellow-900,input[type=checkbox].yellow-900.switch::after{background-color:#f57f17!important}.amber{color:rgba(255,255,255,.9);background-color:#ffc107!important}.amber-100,.amber-200,.amber-300,.amber-50,.amber-500,.amber-600,.amber-700,.amber-800,.amber-900{color:rgba(0,0,0,.8)}.amber-50,input[type=checkbox].amber-50.switch::after{background-color:#fff8e1!important}.amber-100,input[type=checkbox].amber-100.switch::after{background-color:#ffecb3!important}.amber-200,input[type=checkbox].amber-200.switch::after{background-color:#ffe082!important}.amber-300,input[type=checkbox].amber-300.switch::after{background-color:#ffd54f!important}.amber-400{color:rgba(0,0,0,.8);background-color:#ffca28!important}.amber-500,input[type=checkbox].amber-500.switch::after{background-color:#ffc107!important}.amber-600,input[type=checkbox].amber-600.switch::after{background-color:#ffb300!important}.amber-700,input[type=checkbox].amber-700.switch::after{background-color:#ffa000!important}.amber-800,input[type=checkbox].amber-800.switch::after{background-color:#ff8f00!important}.amber-900,input[type=checkbox].amber-900.switch::after{background-color:#ff6f00!important}.orange{color:rgba(255,255,255,.9);background-color:#ff9800!important}.orange-100,.orange-200,.orange-300,.orange-400,.orange-50,.orange-500,.orange-600,.orange-700{color:rgba(0,0,0,.8)}.orange-50,input[type=checkbox].orange-50.switch::after{background-color:#fff3e0!important}.orange-100,input[type=checkbox].orange-100.switch::after{background-color:#ffe0b2!important}.orange-200,input[type=checkbox].orange-200.switch::after{background-color:#ffcc80!important}.orange-300,input[type=checkbox].orange-300.switch::after{background-color:#ffb74d!important}.orange-400,input[type=checkbox].orange-400.switch::after{background-color:#ffa726!important}.orange-500,input[type=checkbox].orange-500.switch::after{background-color:#ff9800!important}.orange-600,input[type=checkbox].orange-600.switch::after{background-color:#fb8c00!important}.orange-700,input[type=checkbox].orange-700.switch::after{background-color:#f57c00!important}.deep-orange,.orange-800,.orange-900{color:rgba(255,255,255,.9)}.orange-800,input[type=checkbox].orange-800.switch::after{background-color:#ef6c00!important}.orange-900,input[type=checkbox].orange-900.switch::after{background-color:#e65100!important}.deep-orange,input[type=checkbox].deep-orange.switch::after{background-color:#ff5722!important}.deep-orange-100,.deep-orange-200,.deep-orange-300,.deep-orange-400,.deep-orange-50{color:rgba(0,0,0,.8)}.deep-orange-50,input[type=checkbox].deep-orange-50.switch::after{background-color:#fbe9e7!important}.deep-orange-100,input[type=checkbox].deep-orange-100.switch::after{background-color:#ffccbc!important}.deep-orange-200,input[type=checkbox].deep-orange-200.switch::after{background-color:#ffab91!important}.deep-orange-300,input[type=checkbox].deep-orange-300.switch::after{background-color:#ff8a65!important}.deep-orange-400,input[type=checkbox].deep-orange-400.switch::after{background-color:#ff7043!important}.brown,.deep-orange-500,.deep-orange-600,.deep-orange-700,.deep-orange-800,.deep-orange-900{color:rgba(255,255,255,.9)}.deep-orange-500,input[type=checkbox].deep-orange-500.switch::after{background-color:#ff5722!important}.deep-orange-600,input[type=checkbox].deep-orange-600.switch::after{background-color:#f4511e!important}.deep-orange-700,input[type=checkbox].deep-orange-700.switch::after{background-color:#e64a19!important}.deep-orange-800,input[type=checkbox].deep-orange-800.switch::after{background-color:#d84315!important}.deep-orange-900,input[type=checkbox].deep-orange-900.switch::after{background-color:#bf360c!important}.brown,input[type=checkbox].brown.switch::after{background-color:#795548!important}.brown-100,.brown-200,.brown-50{color:rgba(0,0,0,.8)}.brown-50,input[type=checkbox].brown-50.switch::after{background-color:#efebe9!important}.brown-100,input[type=checkbox].brown-100.switch::after{background-color:#d7ccc8!important}.brown-200,input[type=checkbox].brown-200.switch::after{background-color:#bcaaa4!important}.brown-300,.brown-400,.brown-500,.brown-600,.brown-700,.brown-800,.brown-900,.grey{color:rgba(255,255,255,.9)}.brown-300,input[type=checkbox].brown-300.switch::after{background-color:#a1887f!important}.brown-400,input[type=checkbox].brown-400.switch::after{background-color:#8d6e63!important}.brown-500,input[type=checkbox].brown-500.switch::after{background-color:#795548!important}.brown-600,input[type=checkbox].brown-600.switch::after{background-color:#6d4c41!important}.brown-700,input[type=checkbox].brown-700.switch::after{background-color:#5d4037!important}.brown-800,input[type=checkbox].brown-800.switch::after{background-color:#4e342e!important}.brown-900,input[type=checkbox].brown-900.switch::after{background-color:#3e2723!important}.grey,input[type=checkbox].grey.switch::after{background-color:#9e9e9e!important}.grey-100,.grey-200,.grey-300,.grey-400,.grey-50,.grey-500{color:rgba(0,0,0,.8)}.grey-50,input[type=checkbox].grey-50.switch::after{background-color:#fafafa!important}.grey-100,input[type=checkbox].grey-100.switch::after{background-color:#f5f5f5!important}.grey-200,input[type=checkbox].grey-200.switch::after{background-color:#eee!important}.grey-300,input[type=checkbox].grey-300.switch::after{background-color:#e0e0e0!important}.grey-400,input[type=checkbox].grey-400.switch::after{background-color:#bdbdbd!important}.grey-500,input[type=checkbox].grey-500.switch::after{background-color:#9e9e9e!important}.blue-grey,.grey-600,.grey-700,.grey-800,.grey-900{color:rgba(255,255,255,.9)}.grey-600,input[type=checkbox].grey-600.switch::after{background-color:#757575!important}.grey-700,input[type=checkbox].grey-700.switch::after{background-color:#616161!important}.grey-800,input[type=checkbox].grey-800.switch::after{background-color:#424242!important}.grey-900,input[type=checkbox].grey-900.switch::after{background-color:#212121!important}.blue-grey,input[type=checkbox].blue-grey.switch::after{background-color:#607d8b!important}.blue-grey-100,.blue-grey-200,.blue-grey-300,.blue-grey-50{color:rgba(0,0,0,.8)}.blue-grey-50,input[type=checkbox].blue-grey-50.switch::after{background-color:#eceff1!important}.blue-grey-100,input[type=checkbox].blue-grey-100.switch::after{background-color:#cfd8dc!important}.blue-grey-200,input[type=checkbox].blue-grey-200.switch::after{background-color:#b0bec5!important}.blue-grey-300,input[type=checkbox].blue-grey-300.switch::after{background-color:#90a4ae!important}.black,.blue-grey-400,.blue-grey-500,.blue-grey-600,.blue-grey-700,.blue-grey-800,.blue-grey-900{color:rgba(255,255,255,.9)}.blue-grey-400,input[type=checkbox].blue-grey-400.switch::after{background-color:#78909c!important}.transparent{background-color:rgba(0,0,0,0)!important}.blue-grey-500,input[type=checkbox].blue-grey-500.switch::after{background-color:#607d8b!important}.blue-grey-600,input[type=checkbox].blue-grey-600.switch::after{background-color:#546e7a!important}.blue-grey-700,input[type=checkbox].blue-grey-700.switch::after{background-color:#455a64!important}.blue-grey-800,input[type=checkbox].blue-grey-800.switch::after{background-color:#37474f!important}.blue-grey-900,input[type=checkbox].blue-grey-900.switch::after{background-color:#263238!important}.black,input[type=checkbox].black.switch::after{background-color:#000!important}.black-opacity-90{background-color:rgba(0,0,0,.9)}.black-opacity-70{background-color:rgba(0,0,0,.7)}.black-opacity-50{background-color:rgba(0,0,0,.5)}.black-opacity-30{background-color:rgba(0,0,0,.3)}.black-opacity-10{background-color:rgba(0,0,0,.1)}.white{color:rgba(0,0,0,.8);background-color:#fff!important}.white-opacity-90{background-color:rgba(255,255,255,.9)}.white-opacity-70{background-color:rgba(255,255,255,.7)}.white-opacity-50{background-color:rgba(255,255,255,.5)}.white-opacity-30{background-color:rgba(255,255,255,.3)}.white-opacity-10{background-color:rgba(255,255,255,.1)}.text-red,i.red{color:#f44336}.text-red-50,i.red-50{color:#ffebee}.text-red-100,i.red-100{color:#ffcdd2}.text-red-200,i.red-200{color:#ef9a9a}.text-red-300,i.red-300{color:#e57373}.text-red-400,i.red-400{color:#ef5350}.text-red-500,i.red-500{color:#f44336}.text-red-600,i.red-600{color:#e53935}.text-red-700,i.red-700{color:#d32f2f}.text-red-800,i.red-800{color:#c62828}.text-red-900,i.red-900{color:#b71c1c}.text-pink,i.pink{color:#e91e63}.text-pink-50,i.pink-50{color:#fce4ec}.text-pink-100,i.pink-100{color:#f8bbd0}.text-pink-200,i.pink-200{color:#f48fb1}.text-Pink-300,i.Pink-300{color:#f06292}.text-pink-400,i.pink-400{color:#ec407a}.text-pink-500,i.pink-500{color:#e91e63}.text-pink-600,i.pink-600{color:#d81b60}.text-pink-700,i.pink-700{color:#c2185b}.text-pink-800,i.pink-800{color:#ad1457}.text-pink-900,i.pink-900{color:#880e4f}.text-purple,i.purple{color:#9c27b0}.text-purple-50,i.purple-50{color:#f3e5f5}.text-purple-100,i.purple-100{color:#e1bee7}.text-purple-200,i.purple-200{color:#ce93d8}.text-purple-300,i.purple-300{color:#ba68c8}.text-purple-400,i.purple-400{color:#ab47bc}.text-purple-500,i.purple-500{color:#9c27b0}.text-purple-600,i.purple-600{color:#8e24aa}.text-purple-700,i.purple-700{color:#7b1fa2}.text-purple-800,i.purple-800{color:#6a1b9a}.text-purple-900,i.purple-900{color:#4a148c}.text-deep-purple,i.deep-purple{color:#673ab7}.text-deep-purple-50,i.deep-purple-50{color:#ede7f6}.text-deep-purple-100,i.deep-purple-100{color:#d1c4e9}.text-deep-purple-200,i.deep-purple-200{color:#b39ddb}.text-deep-purple-300,i.deep-purple-300{color:#9575cd}.text-deep-purple-400,i.deep-purple-400{color:#7e57c2}.text-deep-purple-500,i.deep-purple-500{color:#673ab7}.text-deep-purple-600,i.deep-purple-600{color:#5e35b1}.text-deep-purple-700,i.deep-purple-700{color:#512da8}.text-deep-purple-800,i.deep-purple-800{color:#4527a0}.text-deep-purple-900,i.deep-purple-900{color:#311b92}.text-indigo,i.indigo{color:#3f51b5}.text-indigo-50,i.indigo-50{color:#e8eaf6}.text-indigo-100,i.indigo-100{color:#c5cae9}.text-indigo-200,i.indigo-200{color:#9fa8da}.text-indigo-300,i.indigo-300{color:#7986cb}.text-indigo-400,i.indigo-400{color:#5c6bc0}.text-indigo-500,i.indigo-500{color:#3f51b5}.text-indigo-600,i.indigo-600{color:#3949ab}.text-indigo-700,i.indigo-700{color:#303f9f}.text-indigo-800,i.indigo-800{color:#283593}.text-indigo-900,i.indigo-900{color:#1a237e}.text-blue,i.blue{color:#2196f3}.text-blue-50,i.blue-50{color:#e3f2fd}.text-blue-100,i.blue-100{color:#bbdefb}.text-blue-200,i.blue-200{color:#90caf9}.text-blue-300,i.blue-300{color:#64b5f6}.text-blue-400,i.blue-400{color:#42a5f5}.text-blue-500,i.blue-500{color:#2196f3}.text-blue-600,i.blue-600{color:#1e88e5}.text-blue-700,i.blue-700{color:#1976d2}.text-blue-800,i.blue-800{color:#1565c0}.text-blue-900,i.blue-900{color:#0d47a1}.text-light-blue,i.light-blue{color:#03a9f4}.text-light-blue-50,i.light-blue-50{color:#e1f5fe}.text-light-blue-100,i.light-blue-100{color:#b3e5fc}.text-light-blue-200,i.light-blue-200{color:#81d4fa}.text-light-blue-300,i.light-blue-300{color:#4fc3f7}.text-light-blue-400,i.light-blue-400{color:#29b6f6}.text-light-blue-500,i.light-blue-500{color:#03a9f4}.text-light-blue-600,i.light-blue-600{color:#039be5}.text-light-blue-700,i.light-blue-700{color:#0288d1}.text-light-blue-800,i.light-blue-800{color:#0277bd}.text-light-blue-900,i.light-blue-900{color:#01579b}.text-cyan,i.cyan{color:#00bcd4}.text-cyan-50,i.cyan-50{color:#e0f7fa}.text-cyan-100,i.cyan-100{color:#b2ebf2}.text-cyan-200,i.cyan-200{color:#80deea}.text-cyan-300,i.cyan-300{color:#4dd0e1}.text-cyan-400,i.cyan-400{color:#26c6da}.text-cyan-500,i.cyan-500{color:#00bcd4}.text-cyan-600,i.cyan-600{color:#00acc1}.text-cyan-700,i.cyan-700{color:#0097a7}.text-cyan-800,i.cyan-800{color:#00838f}.text-cyan-900,i.cyan-900{color:#006064}.text-teal,i.teal{color:#009688}.text-teal-50,i.teal-50{color:#e0f2f1}.text-teal-100,i.teal-100{color:#b2dfdb}.text-teal-200,i.teal-200{color:#80cbc4}.text-teal-300,i.teal-300{color:#4db6ac}.text-teal-400,i.teal-400{color:#26a69a}.text-teal-500,i.teal-500{color:#009688}.text-teal-600,i.teal-600{color:#00897b}.text-teal-700,i.teal-700{color:#00796b}.text-teal-800,i.teal-800{color:#00695c}.text-teal-900,i.teal-900{color:#004d40}.text-green,i.green{color:#4caf50}.text-green-50,i.green-50{color:#e8f5e9}.text-green-100,i.green-100{color:#c8e6c9}.text-green-200,i.green-200{color:#a5d6a7}.text-green-300,i.green-300{color:#81c784}.text-green-400,i.green-400{color:#66bb6a}.text-green-500,i.green-500{color:#4caf50}.text-green-600,i.green-600{color:#43a047}.text-green-700,i.green-700{color:#388e3c}.text-green-800,i.green-800{color:#2e7d32}.text-green-900,i.green-900{color:#1b5e20}.text-light-green,i.light-green{color:#8bc34a}.text-light-green-50,i.light-green-50{color:#f1f8e9}.text-light-green-100,i.light-green-100{color:#dcedc8}.text-light-green-200,i.light-green-200{color:#c5e1a5}.text-light-green-300,i.light-green-300{color:#aed581}.text-light-green-400,i.light-green-400{color:#9ccc65}.text-light-green-500,i.light-green-500{color:#8bc34a}.text-light-green-600,i.light-green-600{color:#7cb342}.text-light-green-700,i.light-green-700{color:#689f38}.text-light-green-800,i.light-green-800{color:#558b2f}.text-light-green-900,i.light-green-900{color:#33691e}.text-lime,i.lime{color:#cddc39}.text-lime-50,i.lime-50{color:#f9fbe7}.text-lime-100,i.lime-100{color:#f0f4c3}.text-lime-200,i.lime-200{color:#e6ee9c}.text-lime-300,i.lime-300{color:#dce775}.text-lime-400,i.lime-400{color:#d4e157}.text-lime-500,i.lime-500{color:#cddc39}.text-lime-600,i.lime-600{color:#c0ca33}.text-lime-700,i.lime-700{color:#afb42b}.text-lime-800,i.lime-800{color:#9e9d24}.text-lime-900,i.lime-900{color:#827717}.text-yellow,i.yellow{color:#ffeb3b}.text-yellow-50,i.yellow-50{color:#fffde7}.text-yellow-100,i.yellow-100{color:#fff9c4}.text-yellow-200,i.yellow-200{color:#fff59d}.text-yellow-300,i.yellow-300{color:#fff176}.text-yellow-400,i.yellow-400{color:#ffee58}.text-yellow-500,i.yellow-500{color:#ffeb3b}.text-yellow-600,i.yellow-600{color:#fdd835}.text-yellow-700,i.yellow-700{color:#fbc02d}.text-yellow-800,i.yellow-800{color:#f9a825}.text-yellow-900,i.yellow-900{color:#f57f17}.text-amber,i.amber{color:#ffc107}.text-amber-50,i.amber-50{color:#fff8e1}.text-amber-100,i.amber-100{color:#ffecb3}.text-amber-200,i.amber-200{color:#ffe082}.text-amber-300,i.amber-300{color:#ffd54f}.text-amber-400,i.amber-400{color:#ffca28}.text-amber-500,i.amber-500{color:#ffc107}.text-amber-600,i.amber-600{color:#ffb300}.text-amber-700,i.amber-700{color:#ffa000}.text-amber-800,i.amber-800{color:#ff8f00}.text-amber-900,i.amber-900{color:#ff6f00}.text-orange,i.orange{color:#ff9800}.text-orange-50,i.orange-50{color:#fff3e0}.text-orange-100,i.orange-100{color:#ffe0b2}.text-orange-200,i.orange-200{color:#ffcc80}.text-orange-300,i.orange-300{color:#ffb74d}.text-orange-400,i.orange-400{color:#ffa726}.text-orange-500,i.orange-500{color:#ff9800}.text-orange-600,i.orange-600{color:#fb8c00}.text-orange-700,i.orange-700{color:#f57c00}.text-orange-800,i.orange-800{color:#ef6c00}.text-orange-900,i.orange-900{color:#e65100}.text-deep-orange,i.deep-orange{color:#ff5722}.text-deep-orange-50,i.deep-orange-50{color:#fbe9e7}.text-deep-orange-100,i.deep-orange-100{color:#ffccbc}.text-deep-orange-200,i.deep-orange-200{color:#ffab91}.text-deep-orange-300,i.deep-orange-300{color:#ff8a65}.text-deep-orange-400,i.deep-orange-400{color:#ff7043}.text-deep-orange-500,i.deep-orange-500{color:#ff5722}.text-deep-orange-600,i.deep-orange-600{color:#f4511e}.text-deep-orange-700,i.deep-orange-700{color:#e64a19}.text-deep-orange-800,i.deep-orange-800{color:#d84315}.text-deep-orange-900,i.deep-orange-900{color:#bf360c}.text-brown,i.brown{color:#795548}.text-brown-50,i.brown-50{color:#efebe9}.text-brown-100,i.brown-100{color:#d7ccc8}.text-brown-200,i.brown-200{color:#bcaaa4}.text-brown-300,i.brown-300{color:#a1887f}.text-brown-400,i.brown-400{color:#8d6e63}.text-brown-500,i.brown-500{color:#795548}.text-brown-600,i.brown-600{color:#6d4c41}.text-brown-700,i.brown-700{color:#5d4037}.text-brown-800,i.brown-800{color:#4e342e}.text-brown-900,i.brown-900{color:#3e2723}.text-grey,i.grey{color:#9e9e9e}.text-grey-50,i.grey-50{color:#fafafa}.text-grey-100,i.grey-100{color:#f5f5f5}.text-grey-200,i.grey-200{color:#eee}.text-grey-300,i.grey-300{color:#e0e0e0}.text-grey-400,i.grey-400{color:#bdbdbd}.text-grey-500,i.grey-500{color:#9e9e9e}.text-grey-600,i.grey-600{color:#757575}.text-grey-700,i.grey-700{color:#616161}.text-grey-800,i.grey-800{color:#424242}.text-grey-900,i.grey-900{color:#212121}.text-blue-grey,i.blue-grey{color:#607d8b}.text-blue-grey-50,i.blue-grey-50{color:#eceff1}.text-blue-grey-100,i.blue-grey-100{color:#cfd8dc}.text-blue-grey-200,i.blue-grey-200{color:#b0bec5}.text-blue-grey-300,i.blue-grey-300{color:#90a4ae}.text-blue-grey-400,i.blue-grey-400{color:#78909c}.text-blue-grey-500,i.blue-grey-500{color:#607d8b}.text-blue-grey-600,i.blue-grey-600{color:#546e7a}.text-blue-grey-700,i.blue-grey-700{color:#455a64}.text-blue-grey-800,i.blue-grey-800{color:#37474f}.text-blue-grey-900,i.blue-grey-900{color:#263238}.text-black,i.black{color:#000}.text-white,i.white{color:#fff}.border-red{border:1px solid #f44336}.border-red-50{border:1px solid #ffebee}.border-red-100{border:1px solid #ffcdd2}.border-red-200{border:1px solid #ef9a9a}.border-red-300{border:1px solid #e57373}.border-red-400{border:1px solid #ef5350}.border-red-500{border:1px solid #f44336}.border-red-600{border:1px solid #e53935}.border-red-700{border:1px solid #d32f2f}.border-red-800{border:1px solid #c62828}.border-red-900{border:1px solid #b71c1c}.border-pink{border:1px solid #e91e63}.border-pink-50{border:1px solid #fce4ec}.border-pink-100{border:1px solid #f8bbd0}.border-pink-200{border:1px solid #f48fb1}.border-pink-300{border:1px solid #f06292}.border-pink-400{border:1px solid #ec407a}.border-pink-500{border:1px solid #e91e63}.border-pink-600{border:1px solid #d81b60}.border-pink-700{border:1px solid #c2185b}.border-pink-800{border:1px solid #ad1457}.border-pink-900{border:1px solid #880e4f}.border-purple{border:1px solid #9c27b0}.border-purple-50{border:1px solid #f3e5f5}.border-purple-100{border:1px solid #e1bee7}.border-purple-200{border:1px solid #ce93d8}.border-purple-300{border:1px solid #ba68c8}.border-purple-400{border:1px solid #ab47bc}.border-purple-500{border:1px solid #9c27b0}.border-purple-600{border:1px solid #8e24aa}.border-purple-700{border:1px solid #7b1fa2}.border-purple-800{border:1px solid #6a1b9a}.border-purple-900{border:1px solid #4a148c}.border-deep-purple{border:1px solid #673ab7}.border-deep-purple-50{border:1px solid #ede7f6}.border-deep-purple-100{border:1px solid #d1c4e9}.border-deep-purple-200{border:1px solid #b39ddb}.border-deep-purple-300{border:1px solid #9575cd}.border-deep-purple-400{border:1px solid #7e57c2}.border-deep-purple-500{border:1px solid #673ab7}.border-deep-purple-600{border:1px solid #5e35b1}.border-deep-purple-700{border:1px solid #512da8}.border-deep-purple-800{border:1px solid #4527a0}.border-deep-purple-900{border:1px solid #311b92}.border-indigo{border:1px solid #3f51b5}.border-indigo-50{border:1px solid #e8eaf6}.border-indigo-100{border:1px solid #c5cae9}.border-indigo-200{border:1px solid #9fa8da}.border-indigo-300{border:1px solid #7986cb}.border-indigo-400{border:1px solid #5c6bc0}.border-indigo-500{border:1px solid #3f51b5}.border-indigo-600{border:1px solid #3949ab}.border-indigo-700{border:1px solid #303f9f}.border-indigo-800{border:1px solid #283593}.border-indigo-900{border:1px solid #1a237e}.border-blue{border:1px solid #2196f3}.border-blue-50{border:1px solid #e3f2fd}.border-blue-100{border:1px solid #bbdefb}.border-blue-200{border:1px solid #90caf9}.border-blue-300{border:1px solid #64b5f6}.border-blue-400{border:1px solid #42a5f5}.border-blue-500{border:1px solid #2196f3}.border-blue-600{border:1px solid #1e88e5}.border-blue-700{border:1px solid #1976d2}.border-blue-800{border:1px solid #1565c0}.border-blue-900{border:1px solid #0d47a1}.border-light-blue{border:1px solid #03a9f4}.border-light-blue-50{border:1px solid #e1f5fe}.border-light-blue-100{border:1px solid #b3e5fc}.border-light-blue-200{border:1px solid #81d4fa}.border-light-blue-300{border:1px solid #4fc3f7}.border-light-blue-400{border:1px solid #29b6f6}.border-light-blue-500{border:1px solid #03a9f4}.border-light-blue-600{border:1px solid #039be5}.border-light-blue-700{border:1px solid #0288d1}.border-light-blue-800{border:1px solid #0277bd}.border-light-blue-900{border:1px solid #01579b}.border-cyan{border:1px solid #00bcd4}.border-cyan-50{border:1px solid #e0f7fa}.border-cyan-100{border:1px solid #b2ebf2}.border-cyan-200{border:1px solid #80deea}.border-cyan-300{border:1px solid #4dd0e1}.border-cyan-400{border:1px solid #26c6da}.border-cyan-500{border:1px solid #00bcd4}.border-cyan-600{border:1px solid #00acc1}.border-cyan-700{border:1px solid #0097a7}.border-cyan-800{border:1px solid #00838f}.border-cyan-900{border:1px solid #006064}.border-teal{border:1px solid #009688}.border-teal-50{border:1px solid #e0f2f1}.border-teal-100{border:1px solid #b2dfdb}.border-teal-200{border:1px solid #80cbc4}.border-teal-300{border:1px solid #4db6ac}.border-teal-400{border:1px solid #26a69a}.border-teal-500{border:1px solid #009688}.border-teal-600{border:1px solid #00897b}.border-teal-700{border:1px solid #00796b}.border-teal-800{border:1px solid #00695c}.border-teal-900{border:1px solid #004d40}.border-green{border:1px solid #4caf50}.border-green-50{border:1px solid #e8f5e9}.border-green-100{border:1px solid #c8e6c9}.border-green-200{border:1px solid #a5d6a7}.border-green-300{border:1px solid #81c784}.border-green-400{border:1px solid #66bb6a}.border-green-500{border:1px solid #4caf50}.border-green-600{border:1px solid #43a047}.border-green-700{border:1px solid #388e3c}.border-green-800{border:1px solid #2e7d32}.border-green-900{border:1px solid #1b5e20}.border-light-green{border:1px solid #8bc34a}.border-light-green-50{border:1px solid #f1f8e9}.border-light-green-100{border:1px solid #dcedc8}.border-light-green-200{border:1px solid #c5e1a5}.border-light-green-300{border:1px solid #aed581}.border-light-green-400{border:1px solid #9ccc65}.border-light-green-500{border:1px solid #8bc34a}.border-light-green-600{border:1px solid #7cb342}.border-light-green-700{border:1px solid #689f38}.border-light-green-800{border:1px solid #558b2f}.border-light-green-900{border:1px solid #33691e}.border-lime{border:1px solid #cddc39}.border-lime-50{border:1px solid #f9fbe7}.border-lime-100{border:1px solid #f0f4c3}.border-lime-200{border:1px solid #e6ee9c}.border-lime-300{border:1px solid #dce775}.border-lime-400{border:1px solid #d4e157}.border-lime-500{border:1px solid #cddc39}.border-lime-600{border:1px solid #c0ca33}.border-lime-700{border:1px solid #afb42b}.border-lime-800{border:1px solid #9e9d24}.border-lime-900{border:1px solid #827717}.border-yellow{border:1px solid #ffeb3b}.border-yellow-50{border:1px solid #fffde7}.border-yellow-100{border:1px solid #fff9c4}.border-yellow-200{border:1px solid #fff59d}.border-yellow-300{border:1px solid #fff176}.border-yellow-400{border:1px solid #ffee58}.border-yellow-500{border:1px solid #ffeb3b}.border-yellow-600{border:1px solid #fdd835}.border-yellow-700{border:1px solid #fbc02d}.border-yellow-800{border:1px solid #f9a825}.border-yellow-900{border:1px solid #f57f17}.border-amber{border:1px solid #ffc107}.border-amber-50{border:1px solid #fff8e1}.border-amber-100{border:1px solid #ffecb3}.border-amber-200{border:1px solid #ffe082}.border-amber-300{border:1px solid #ffd54f}.border-amber-400{border:1px solid #ffca28}.border-amber-500{border:1px solid #ffc107}.border-amber-600{border:1px solid #ffb300}.border-amber-700{border:1px solid #ffa000}.border-amber-800{border:1px solid #ff8f00}.border-amber-900{border:1px solid #ff6f00}.border-orange{border:1px solid #ff9800}.border-orange-50{border:1px solid #fff3e0}.border-orange-100{border:1px solid #ffe0b2}.border-orange-200{border:1px solid #ffcc80}.border-orange-300{border:1px solid #ffb74d}.border-orange-400{border:1px solid #ffa726}.border-orange-500{border:1px solid #ff9800}.border-orange-600{border:1px solid #fb8c00}.border-orange-700{border:1px solid #f57c00}.border-orange-800{border:1px solid #ef6c00}.border-orange-900{border:1px solid #e65100}.border-deep-orange{border:1px solid #ff5722}.border-deep-orange-50{border:1px solid #fbe9e7}.border-deep-orange-100{border:1px solid #ffccbc}.border-deep-orange-200{border:1px solid #ffab91}.border-deep-orange-300{border:1px solid #ff8a65}.border-deep-orange-400{border:1px solid #ff7043}.border-deep-orange-500{border:1px solid #ff5722}.border-deep-orange-600{border:1px solid #f4511e}.border-deep-orange-700{border:1px solid #e64a19}.border-deep-orange-800{border:1px solid #d84315}.border-deep-orange-900{border:1px solid #bf360c}.border-brown{border:1px solid #795548}.border-brown-50{border:1px solid #efebe9}.border-brown-100{border:1px solid #d7ccc8}.border-brown-200{border:1px solid #bcaaa4}.border-brown-300{border:1px solid #a1887f}.border-brown-400{border:1px solid #8d6e63}.border-brown-500{border:1px solid #795548}.border-brown-600{border:1px solid #6d4c41}.border-brown-700{border:1px solid #5d4037}.border-brown-800{border:1px solid #4e342e}.border-brown-900{border:1px solid #3e2723}.border-grey{border:1px solid #9e9e9e}.border-grey-50{border:1px solid #fafafa}.border-grey-100{border:1px solid #f5f5f5}.border-grey-200{border:1px solid #eee}.border-grey-300{border:1px solid #e0e0e0}.border-grey-400{border:1px solid #bdbdbd}.border-grey-500{border:1px solid #9e9e9e}.border-grey-600{border:1px solid #757575}.border-grey-700{border:1px solid #616161}.border-grey-800{border:1px solid #424242}.border-grey-900{border:1px solid #212121}.border-blue-grey{border:1px solid #607d8b}.border-blue-grey-50{border:1px solid #eceff1}.border-blue-grey-100{border:1px solid #cfd8dc}.border-blue-grey-200{border:1px solid #b0bec5}.border-blue-grey-300{border:1px solid #90a4ae}.border-blue-grey-400{border:1px solid #78909c}.border-blue-grey-500{border:1px solid #607d8b}.border-blue-grey-600{border:1px solid #546e7a}.border-blue-grey-700{border:1px solid #455a64}.border-blue-grey-800{border:1px solid #37474f}.border-blue-grey-900{border:1px solid #263238}.border-black{border:1px solid #000}.border-white{border:1px solid #fff}@font-face{font-family:Roboto;font-style:normal;font-weight:300;src:local('Roboto Light'),local('Roboto-Light'),url(fonts/robotolight.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:local('Roboto'),local('Roboto-Regular'),url(fonts/sTdaA6j0Psb920Vjv-mrzH-_kf6ByYO6CLYdB4HQE-Y.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:900;src:local('Roboto Black'),local('Roboto-Black'),url(fonts/robotoblack.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Ionicons;src:url(fonts/ionicons.woff?v=2.0.0) format("woff");font-weight:400;font-style:normal}i.icon{background:0 0!important}.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;min-width:22px;text-align:center}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}
+
+.component-header{display:block}.footer,.header{font-size:18px;display:inline-block;width:100%;position:fixed;top:0;left:0;height:52px;z-index:9}.footer{top:initial;bottom:0}.header.sub{top:52px}.footer.sub{top:initial;bottom:52px}.has-header{padding-top:52px!important}.has-header.has-sub-header{padding-top:104px!important}.has-footer{padding-bottom:52px!important}.has-footer.has-sub-footer{padding-bottom:104px!important}.footer .left,.footer .right,.footer .title,.footer h1,.header .left,.header .right,.header .title,.header h1{margin-top:15px;margin-bottom:5px}.header .avatar{height:40px;margin-top:-8px;margin-left:4px}.header .border-big{border-width:2px;border-style:solid}.footer h2,.header h2{padding-top:8px;padding-left:10px}.footer p,.header p{padding-left:10px;margin:0;margin-top:-4px}.footer .left,.header .left{padding-left:5px}.footer .right,.header .right{padding-right:5px}.footer .title,.footer h1,.header .title,.header h1{margin-bottom:15px;padding-left:10px;padding-right:15px;display:inline-block}.footer button,.header button{margin-top:-10px}.footer button.icon,.header button.icon{font-size:30px;margin-top:-10px;z-index:99;background:0 0;border:none;padding:0 6px}.footer button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]),.header button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]){color:#fff}.footer button.icon.left,.footer button.icon.right,.header button.icon.left,.header button.icon.right{margin-top:5px;margin-bottom:5px}.footer button.icon.left,.header button.icon.left{margin-left:5px}.footer button.icon.right,.header button.icon.right{margin-right:5px}.footer .title.align-center,.footer h1.align-center,.footer p.align-center,.header .title.align-center,.header h1.align-center,.header p.align-center{width:100%;position:inherit;padding-right:15px;left:0;z-index:9}.footer .icon-badge,.header .icon-badge{position:absolute;margin-left:-6px;margin-top:-8px;border-radius:8px;z-index:999}.footer .buttons-group,.header .buttons-group{margin-top:15px;margin-left:5px;margin-right:5px}.footer .buttons-group.small,.header .buttons-group.small{margin-top:20px;margin-left:10px;margin-right:10px}.header input::-webkit-input-placeholder{color:rgba(0,0,0,.8)}.header input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.8)}.header input{padding:15px;position:absolute}.header .left+input{padding-right:50px}
+.component-button{display:block}button{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease;font-size:14px;border:none;background-color:rgba(0,0,0,0);color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-height:42px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer;overflow:hidden}button[disabled]{opacity:.8}button .icon{position:absolute;left:10px}button.circle{width:42px;height:42px;text-align:center;padding:0;line-height:0;font-size:22px;z-index:10}button.icon-text{padding-left:40px}button.icon-text i{font-size:22px}button.icon-text.icon-right{padding-left:12px;padding-right:40px;position:relative}button.icon-right i{position:absolute;right:12px;text-align:right;margin-top:2px}button[class*=border-]{min-height:40px;line-height:40px}button.full{width:100%}.buttons-group.big button,button.big{font-size:22px;min-height:50px;line-height:50px}button.circle.big{width:50px;height:50px;font-size:28px}button.big.icon-text{padding-left:40px}button.big.icon-text.icon-right{padding-left:12px;padding-right:40px}button.big.icon-text i{font-size:26px}.buttons-group.small button,button.small{font-size:12px;min-height:30px;line-height:30px}button.circle.small{width:30px;height:30px;font-size:18px}button.small.icon-text{padding-left:30px}button.small.icon-text.icon-right{padding-left:12px;padding-right:35px}button.small.icon-text i{font-size:18px}.buttons-group.huge button,button.huge{font-size:32px;min-height:70px;line-height:70px}button.circle.huge{width:70px;height:70px;font-size:32px}button.huge.icon-text{padding-left:40px}button.huge.icon-text.icon-right{padding-left:12px;padding-right:40px}button.huge.icon-text i{font-size:32px}.buttons-group{display:inline-block}.buttons-group button{float:left;margin-left:-1px}.buttons-group button:first-child{margin-left:0}.buttons-group.full{display:flex}.buttons-group.full button{flex:1}.ripple{position:absolute;background:rgba(255,255,255,.25);border-radius:100%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ripple.show{-webkit-animation:ripple .5s ease-out;-moz-animation:ripple .5s ease-out;-o-animation:ripple .5s ease-out;animation:ripple .5s ease-out}@-webkit-keyframes ripple{to{-webkit-transform:scale(1.5);opacity:0}}@-moz-keyframes ripple{to{-moz-transform:scale(1.5);opacity:0}}@-o-keyframes ripple{to{-o-transform:scale(1.5);opacity:0}}@keyframes ripple{to{transform:scale(1.5);opacity:0}}
+.alert-mobileui .alert {
+    font-family: Roboto,Noto,sans-serif;
+    position: relative;
+    border-radius: 4px;
+    box-shadow: 0 16px 24px 2px rgba(0,0,0,.14), 0 6px 30px 5px rgba(0,0,0,.12), 0 8px 10px -5px rgba(0,0,0,.4);
+    max-width: 270px;
+    word-break: break-all;
+}
+.alert-mobileui {
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-pack: center;
+    -ms-flex-pack: center;
+    justify-content: center;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    align-items: center;
+    position: absolute;
+    top:40%;
+    left: 0;
+    right: 0;
+}
+.backdrop {
+    height: 100%;
+    background-color: #000;
+    opacity: .01;
+    z-index: 9999;
+    transition-duration: 280ms;
+}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/paypwdset.html b/platforms/android/app/src/main/assets/www/paypwdset.html
new file mode 100644
index 0000000..1714ab1
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/paypwdset.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>设置支付密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">设置支付密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd"  pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd"  pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">保存</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/paypwdset.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..5faece0
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,23 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) {
+/*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..e7cdb39
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,73 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) {
+module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+  var storeKey = '__advancedHttpCookieStore__';
+
+  var store = new WebStorageCookieStore(storage, storeKey);
+  var cookieJar = new ToughCookie.CookieJar(store);
+
+  return {
+    setCookieFromString: setCookieFromString,
+    setCookie: setCookie,
+    getCookieString: getCookieString,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies
+  };
+
+  function splitCookieString(cookieStr) {
+    var cookieParts = cookieStr.split(',');
+    var splitCookies = [];
+    var processedCookie = null;
+
+    for (var i = 0; i < cookieParts.length; ++i) {
+      if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+        processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+        i++;
+      } else {
+        processedCookie = cookieParts[i];
+      }
+
+      processedCookie = processedCookie.trim();
+      splitCookies.push(processedCookie);
+    }
+
+    return splitCookies;
+  }
+
+  function setCookieFromString(url, cookieStr) {
+    if (!cookieStr) return;
+
+    var cookies = splitCookieString(cookieStr);
+
+    for (var i = 0; i < cookies.length; ++i) {
+      cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+    }
+  }
+
+  function setCookie(url, cookie, options) {
+    options = options || {};
+    options.ignoreError = false;
+    cookieJar.setCookieSync(cookie, url, options);
+  }
+
+  function getCookieString(url) {
+    return cookieJar.getCookieStringSync(url);
+  }
+
+  function clearCookies() {
+    window.localStorage.removeItem(storeKey);
+  }
+
+  function removeCookies(url, cb) {
+    cookieJar.getCookies(url, function (error, cookies) {
+      if (!cookies || cookies.length === 0) {
+        return cb(null, []);
+      }
+
+      var domain = cookies[0].domain;
+
+      cookieJar.store.removeCookies(domain, null, cb);
+    });
+  }
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..5e85416
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,11 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) {
+var globalConfigs = {
+  headers: {},
+  serializer: 'urlencoded',
+  followRedirect: true,
+  timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..855e84c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,353 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) {
+module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+  var validSerializers = ['urlencoded', 'json', 'utf8'];
+  var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+  var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+  var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+  var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+  var interface = {
+    b64EncodeUnicode: b64EncodeUnicode,
+    checkSerializer: checkSerializer,
+    checkSSLCertMode: checkSSLCertMode,
+    checkClientAuthMode: checkClientAuthMode,
+    checkClientAuthOptions: checkClientAuthOptions,
+    checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+    checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+    checkTimeoutValue: checkTimeoutValue,
+    checkFollowRedirectValue: checkFollowRedirectValue,
+    injectCookieHandler: injectCookieHandler,
+    injectRawResponseHandler: injectRawResponseHandler,
+    injectFileEntryHandler: injectFileEntryHandler,
+    getMergedHeaders: getMergedHeaders,
+    getProcessedData: getProcessedData,
+    handleMissingCallbacks: handleMissingCallbacks,
+    handleMissingOptions: handleMissingOptions
+  };
+
+  // expose all functions for testing purposes
+  if (init.debug) {
+    interface.mergeHeaders = mergeHeaders;
+    interface.checkForValidStringValue = checkForValidStringValue;
+    interface.checkKeyValuePairObject = checkKeyValuePairObject;
+    interface.checkHttpMethod = checkHttpMethod;
+    interface.checkResponseType = checkResponseType;
+    interface.checkHeadersObject = checkHeadersObject;
+    interface.checkParamsObject = checkParamsObject;
+    interface.resolveCookieString = resolveCookieString;
+    interface.createFileEntry = createFileEntry;
+    interface.getCookieHeader = getCookieHeader;
+    interface.getMatchingHostHeaders = getMatchingHostHeaders;
+    interface.getAllowedDataTypes = getAllowedDataTypes;
+  }
+
+  return interface;
+
+  // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+  function b64EncodeUnicode(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode('0x' + p1);
+    }));
+  }
+
+  function mergeHeaders(globalHeaders, localHeaders) {
+    var globalKeys = Object.keys(globalHeaders);
+    var key;
+
+    for (var i = 0; i < globalKeys.length; i++) {
+      key = globalKeys[i];
+
+      if (!localHeaders.hasOwnProperty(key)) {
+        localHeaders[key] = globalHeaders[key];
+      }
+    }
+
+    return localHeaders;
+  }
+
+  function checkForValidStringValue(list, value, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    value = value.trim().toLowerCase();
+
+    if (list.indexOf(value) === -1) {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    return value;
+  }
+
+  function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(obj) !== 'Object') {
+      throw new Error(onInvalidValueMessage);
+    }
+
+    var keys = Object.keys(obj);
+
+    for (var i = 0; i < keys.length; i++) {
+      if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+        throw new Error(onInvalidValueMessage);
+      }
+    }
+
+    return obj;
+  }
+
+  function checkHttpMethod(method) {
+    return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+  }
+
+  function checkResponseType(type) {
+    return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+  }
+
+  function checkSerializer(serializer) {
+    return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+  }
+
+  function checkSSLCertMode(mode) {
+    return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+  }
+
+  function checkClientAuthMode(mode) {
+    return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+  }
+
+  function checkClientAuthOptions(mode, options) {
+    options = options || {};
+
+    // none
+    if (mode === validClientAuthModes[0]) {
+      return {
+        alias: null,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    if (jsUtil.getTypeOf(options) !== 'Object') {
+      throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+    }
+
+    // systemstore
+    if (mode === validClientAuthModes[1]) {
+      if (jsUtil.getTypeOf(options.alias) !== 'String'
+        && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+      }
+
+      return {
+        alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    // buffer
+    if (mode === validClientAuthModes[2]) {
+      if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+      }
+
+      if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+      }
+
+      return {
+        alias: null,
+        rawPkcs: options.rawPkcs,
+        pkcsPassword: options.pkcsPassword
+      }
+    }
+  }
+
+  function checkForBlacklistedHeaderKey(key) {
+    if (key.toLowerCase() === 'cookie') {
+      throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+    }
+
+    return key;
+  }
+
+  function checkForInvalidHeaderValue(value) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(messages.INVALID_HEADERS_VALUE);
+    }
+
+    return value;
+  }
+
+  function checkTimeoutValue(timeout) {
+    if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+      throw new Error(messages.INVALID_TIMEOUT_VALUE);
+    }
+
+    return timeout;
+  }
+
+  function checkFollowRedirectValue(follow) {
+    if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+      throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+    }
+
+    return follow;
+  }
+
+  function checkHeadersObject(headers) {
+    return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+  }
+
+  function checkParamsObject(params) {
+    return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+  }
+
+  function resolveCookieString(headers) {
+    var keys = Object.keys(headers || {});
+
+    for (var i = 0; i < keys.length; ++i) {
+      if (keys[i].match(/^set-cookie$/i)) {
+        return headers[keys[i]];
+      }
+    }
+
+    return null;
+  }
+
+  function createFileEntry(rawEntry) {
+    var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+    entry.isDirectory = rawEntry.isDirectory;
+    entry.isFile = rawEntry.isFile;
+    entry.name = rawEntry.name;
+    entry.fullPath = rawEntry.fullPath;
+    entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+    entry.nativeURL = rawEntry.nativeURL;
+
+    return entry;
+  }
+
+  function injectCookieHandler(url, cb) {
+    return function (response) {
+      cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+      cb(response);
+    }
+  }
+
+  function injectRawResponseHandler(responseType, cb) {
+    return function (response) {
+      var dataType = jsUtil.getTypeOf(response.data);
+
+      // don't need post-processing if it's already binary type (on browser platform)
+      if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+        return cb(response);
+      }
+
+      // arraybuffer
+      if (responseType === validResponseTypes[1]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        response.data = buffer;
+      }
+
+      // blob
+      if (responseType === validResponseTypes[2]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        var type = response.headers['content-type'] || '';
+        var blob = new Blob([ buffer ], { type: type });
+        response.data = blob;
+      }
+
+      cb(response);
+    }
+  }
+
+  function injectFileEntryHandler(cb) {
+    return function (response) {
+      cb(createFileEntry(response.file));
+    }
+  }
+
+  function getCookieHeader(url) {
+    var cookieString = cookieHandler.getCookieString(url);
+
+    if (cookieString.length) {
+      return { Cookie: cookieHandler.getCookieString(url) };
+    }
+
+    return {};
+  }
+
+  function getMatchingHostHeaders(url, headersList) {
+    var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+    var domain = matches && matches[1];
+
+    return headersList[domain] || null;
+  }
+
+  function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+    var globalHeaders = predefinedHeaders['*'] || {};
+    var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+    var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+    mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+    mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+    return mergedHeaders;
+  }
+
+  function getAllowedDataTypes(dataSerializer) {
+    switch (dataSerializer) {
+      case 'utf8':
+        return ['String'];
+      case 'urlencoded':
+        return ['Object'];
+      default:
+        return ['Array', 'Object'];
+    }
+  }
+
+  function getProcessedData(data, dataSerializer) {
+    var currentDataType = jsUtil.getTypeOf(data);
+    var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+    if (allowedDataTypes.indexOf(currentDataType) === -1) {
+      throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+    }
+
+    if (dataSerializer === 'utf8') {
+      data = { text: data };
+    }
+
+    return data;
+  }
+
+  function handleMissingCallbacks(successFn, failFn) {
+    if (jsUtil.getTypeOf(successFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_SUCCESS);
+    }
+
+    if (jsUtil.getTypeOf(failFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_FAIL);
+    }
+  }
+
+  function handleMissingOptions(options, globals) {
+    options = options || {};
+
+    return {
+      method: checkHttpMethod(options.method || validHttpMethods[0]),
+      responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+      serializer: checkSerializer(options.serializer || globals.serializer),
+      timeout: checkTimeoutValue(options.timeout || globals.timeout),
+      followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+      headers: checkHeadersObject(options.headers || {}),
+      params: checkParamsObject(options.params || {}),
+      data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+      filePath: options.filePath || '',
+      name: options.name || ''
+    };
+  }
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..cbe1c51
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) {
+module.exports = {
+  // typeof is not working reliably in JS
+  getTypeOf: function (object) {
+    switch (Object.prototype.toString.call(object)) {
+      case '[object Array]':
+        return 'Array';
+      case '[object Blob]':
+        return 'Blob';
+      case '[object ArrayBuffer]':
+        return 'ArrayBuffer';
+      case '[object Boolean]':
+        return 'Boolean';
+      case '[object Function]':
+        return 'Function';
+      case '[object Null]':
+        return 'Null';
+      case '[object Number]':
+        return 'Number';
+      case '[object Object]':
+        return 'Object';
+      case '[object String]':
+        return 'String';
+      case '[object Undefined]':
+        return 'Undefined';
+      default:
+        return 'Unknown';
+    }
+  }
+}
+
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..800c6b7
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,184 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) {
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+  function WebStorageCookieStore(storage, storeKey) {
+    ToughCookie.Store.call(this);
+    this._storage = storage;
+    this._storeKey = storeKey || '__cookieStore__';
+    this.synchronous = true;
+  }
+
+  WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+  WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+    var cookie = _.get(store, [domain, path, key], null);
+
+    callback(null, ToughCookie.Cookie.fromJSON(cookie));
+  };
+
+  WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+    if (!domain) {
+      callback(null, []);
+      return;
+    }
+
+    var that = this;
+    var cookies = [];
+    var store = this._readStore();
+    var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+    domains.forEach(function (domain) {
+      if (!store[domain]) {
+        return;
+      }
+
+      var matchingPaths = Object.keys(store[domain]);
+
+      if (path != null) {
+        matchingPaths = matchingPaths.filter(function (cookiePath) {
+          return that._isOnPath(cookiePath, path);
+        });
+      }
+
+      matchingPaths.forEach(function (path) {
+        Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    callback(null, cookies);
+  };
+
+  /**
+   * Returns whether `cookiePath` is on the given `urlPath`
+   */
+  WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+    if (!cookiePath) {
+      return false;
+    }
+
+    if (cookiePath === urlPath) {
+      return true;
+    }
+
+    if (urlPath.indexOf(cookiePath) !== 0) {
+      return false;
+    }
+
+    if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+      return false;
+    }
+
+    return true;
+  };
+
+  WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+    var store = this._readStore();
+
+    _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+    this.putCookie(newCookie, callback);
+  };
+
+
+  WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+
+    _.unset(store, [domain, path, key]);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+    var store = this._readStore();
+
+    if (path == null) {
+      _.unset(store, [domain]);
+    } else {
+      _.unset(store, [domain, path]);
+    }
+
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+    var cookies = [];
+    var store = this._readStore();
+
+    Object.keys(store).forEach(function (domain) {
+      Object.keys(store[domain]).forEach(function (path) {
+        Array.protype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    cookies.sort(function (c1, c2) {
+      return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+    });
+
+    callback(null, cookies);
+  };
+
+  WebStorageCookieStore.prototype._readStore = function () {
+    var json = this._storage.getItem(this._storeKey);
+
+    if (json !== null) {
+      try {
+        return JSON.parse(json);
+      } catch (e) { }
+    }
+
+    return {};
+  };
+
+  WebStorageCookieStore.prototype._writeStore = function (store) {
+    this._storage.setItem(this._storeKey, JSON.stringify(store));
+  };
+
+  return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..f35be77
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) {
+/**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..13efb2b
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) {
+module.exports = {
+  ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+  DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+  INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+  INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+  INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+  INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+  INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+  INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+  INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+  INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+  INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+  INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+  INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+  INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+  INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+  MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+  MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a77c8e0
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,202 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) {
+module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+  const publicInterface = {
+    getBasicAuthHeader: getBasicAuthHeader,
+    useBasicAuth: useBasicAuth,
+    getHeaders: getHeaders,
+    setHeader: setHeader,
+    getDataSerializer: getDataSerializer,
+    setDataSerializer: setDataSerializer,
+    setCookie: setCookie,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies,
+    getCookieString: getCookieString,
+    getRequestTimeout: getRequestTimeout,
+    setRequestTimeout: setRequestTimeout,
+    getFollowRedirect: getFollowRedirect,
+    setFollowRedirect: setFollowRedirect,
+    // @DEPRECATED
+    disableRedirect: disableRedirect,
+    // @DEPRECATED
+    setSSLCertMode: setServerTrustMode,
+    setServerTrustMode: setServerTrustMode,
+    setClientAuthMode: setClientAuthMode,
+    sendRequest: sendRequest,
+    post: post,
+    get: get,
+    put: put,
+    patch: patch,
+    delete: del,
+    head: head,
+    uploadFile: uploadFile,
+    downloadFile: downloadFile
+  };
+
+  function getBasicAuthHeader(username, password) {
+    return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+  }
+
+  function useBasicAuth(username, password) {
+    this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+  }
+
+  function getHeaders(host) {
+    return globalConfigs.headers[host || '*'] || null;
+  }
+
+  function setHeader() {
+    // this one is for being backward compatible
+    var host = '*';
+    var header = arguments[0];
+    var value = arguments[1];
+
+    if (arguments.length === 3) {
+      host = arguments[0];
+      header = arguments[1];
+      value = arguments[2];
+    }
+
+    helpers.checkForBlacklistedHeaderKey(header);
+    helpers.checkForInvalidHeaderValue(value);
+
+    globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+    globalConfigs.headers[host][header] = value;
+  }
+
+  function getDataSerializer() {
+    return globalConfigs.serializer;
+  }
+
+  function setDataSerializer(serializer) {
+    globalConfigs.serializer = helpers.checkSerializer(serializer);
+  }
+
+  function setCookie(url, cookie, options) {
+    cookieHandler.setCookie(url, cookie, options);
+  }
+
+  function clearCookies() {
+    cookieHandler.clearCookies();
+  }
+
+  function removeCookies(url, callback) {
+    cookieHandler.removeCookies(url, callback);
+  }
+
+  function getCookieString(url) {
+    return cookieHandler.getCookieString(url);
+  }
+
+  function getRequestTimeout() {
+    return globalConfigs.timeout;
+  }
+
+  function setRequestTimeout(timeout) {
+    globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+  }
+
+  function getFollowRedirect() {
+    return globalConfigs.followRedirect;
+  }
+
+  function setFollowRedirect(follow) {
+    globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+  }
+
+  // @DEPRECATED
+  function disableRedirect(disable, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    setFollowRedirect(!disable);
+    success();
+  }
+
+  function setServerTrustMode(mode, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+  }
+
+  function setClientAuthMode() {
+    var mode = arguments[0];
+    var options = null;
+    var success = arguments[1];
+    var failure = arguments[2];
+
+    if (arguments.length === 4) {
+      options = arguments[1];
+      success = arguments[2];
+      failure = arguments[3];
+    }
+
+    mode = helpers.checkClientAuthMode(mode);
+    options = helpers.checkClientAuthOptions(mode, options);
+
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+  }
+
+  function sendRequest(url, options, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    options = helpers.handleMissingOptions(options, globalConfigs);
+    url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+    var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+    var onFail = helpers.injectCookieHandler(url, failure);
+    var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+    switch (options.method) {
+      case 'post':
+      case 'put':
+      case 'patch':
+        var data = helpers.getProcessedData(options.data, options.serializer);
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+      case 'upload':
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+      case 'download':
+        var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+        return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+      default:
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+    }
+  }
+
+  function post(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+  };
+
+  function get(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+  };
+
+  function put(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+  }
+
+  function patch(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+  }
+
+  function del(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+  }
+
+  function head(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+  }
+
+  function uploadFile(url, params, headers, filePath, name, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+  }
+
+  function downloadFile(url, params, headers, filePath, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+  }
+
+  return publicInterface;
+}
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..bd8ab68
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5091 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) {
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["ToughCookie"] = factory();
+	else
+		root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var net = __webpack_require__(1);
+	var urlParse = __webpack_require__(2).parse;
+	var util = __webpack_require__(9);
+	var pubsuffix = __webpack_require__(13);
+	var Store = __webpack_require__(17).Store;
+	var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var VERSION = __webpack_require__(21).version;
+
+	var punycode;
+	try {
+	  punycode = __webpack_require__(15);
+	} catch(e) {
+	  console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+	}
+
+	// From RFC6265 S4.1.1
+	// note that it excludes \x3B ";"
+	var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+	var CONTROL_CHARS = /[\x00-\x1F]/;
+
+	// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+	// the "relaxed" mode, see:
+	// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+	var TERMINATORS = ['\n', '\r', '\0'];
+
+	// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+	// Note ';' is \x3B
+	var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+	// date-time parsing constants (RFC6265 S5.1.1)
+
+	var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+	var MONTH_TO_NUM = {
+	  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+	  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+	};
+	var NUM_TO_MONTH = [
+	  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+	];
+	var NUM_TO_DAY = [
+	  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+	];
+
+	var MAX_TIME = 2147483647000; // 31-bit max
+	var MIN_TIME = 0; // 31-bit min
+
+	/*
+	 * Parses a Natural number (i.e., non-negative integer) with either the
+	 *    <min>*<max>DIGIT ( non-digit *OCTET )
+	 * or
+	 *    <min>*<max>DIGIT
+	 * grammar (RFC6265 S5.1.1).
+	 *
+	 * The "trailingOK" boolean controls if the grammar accepts a
+	 * "( non-digit *OCTET )" trailer.
+	 */
+	function parseDigits(token, minDigits, maxDigits, trailingOK) {
+	  var count = 0;
+	  while (count < token.length) {
+	    var c = token.charCodeAt(count);
+	    // "non-digit = %x00-2F / %x3A-FF"
+	    if (c <= 0x2F || c >= 0x3A) {
+	      break;
+	    }
+	    count++;
+	  }
+
+	  // constrain to a minimum and maximum number of digits.
+	  if (count < minDigits || count > maxDigits) {
+	    return null;
+	  }
+
+	  if (!trailingOK && count != token.length) {
+	    return null;
+	  }
+
+	  return parseInt(token.substr(0,count), 10);
+	}
+
+	function parseTime(token) {
+	  var parts = token.split(':');
+	  var result = [0,0,0];
+
+	  /* RF6256 S5.1.1:
+	   *      time            = hms-time ( non-digit *OCTET )
+	   *      hms-time        = time-field ":" time-field ":" time-field
+	   *      time-field      = 1*2DIGIT
+	   */
+
+	  if (parts.length !== 3) {
+	    return null;
+	  }
+
+	  for (var i = 0; i < 3; i++) {
+	    // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+	    // followed by "( non-digit *OCTET )" so therefore the last time-field can
+	    // have a trailer
+	    var trailingOK = (i == 2);
+	    var num = parseDigits(parts[i], 1, 2, trailingOK);
+	    if (num === null) {
+	      return null;
+	    }
+	    result[i] = num;
+	  }
+
+	  return result;
+	}
+
+	function parseMonth(token) {
+	  token = String(token).substr(0,3).toLowerCase();
+	  var num = MONTH_TO_NUM[token];
+	  return num >= 0 ? num : null;
+	}
+
+	/*
+	 * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+	 */
+	function parseDate(str) {
+	  if (!str) {
+	    return;
+	  }
+
+	  /* RFC6265 S5.1.1:
+	   * 2. Process each date-token sequentially in the order the date-tokens
+	   * appear in the cookie-date
+	   */
+	  var tokens = str.split(DATE_DELIM);
+	  if (!tokens) {
+	    return;
+	  }
+
+	  var hour = null;
+	  var minute = null;
+	  var second = null;
+	  var dayOfMonth = null;
+	  var month = null;
+	  var year = null;
+
+	  for (var i=0; i<tokens.length; i++) {
+	    var token = tokens[i].trim();
+	    if (!token.length) {
+	      continue;
+	    }
+
+	    var result;
+
+	    /* 2.1. If the found-time flag is not set and the token matches the time
+	     * production, set the found-time flag and set the hour- value,
+	     * minute-value, and second-value to the numbers denoted by the digits in
+	     * the date-token, respectively.  Skip the remaining sub-steps and continue
+	     * to the next date-token.
+	     */
+	    if (second === null) {
+	      result = parseTime(token);
+	      if (result) {
+	        hour = result[0];
+	        minute = result[1];
+	        second = result[2];
+	        continue;
+	      }
+	    }
+
+	    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+	     * the day-of-month production, set the found-day-of- month flag and set
+	     * the day-of-month-value to the number denoted by the date-token.  Skip
+	     * the remaining sub-steps and continue to the next date-token.
+	     */
+	    if (dayOfMonth === null) {
+	      // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 1, 2, true);
+	      if (result !== null) {
+	        dayOfMonth = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.3. If the found-month flag is not set and the date-token matches the
+	     * month production, set the found-month flag and set the month-value to
+	     * the month denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (month === null) {
+	      result = parseMonth(token);
+	      if (result !== null) {
+	        month = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.4. If the found-year flag is not set and the date-token matches the
+	     * year production, set the found-year flag and set the year-value to the
+	     * number denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (year === null) {
+	      // "year = 2*4DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 2, 4, true);
+	      if (result !== null) {
+	        year = result;
+	        /* From S5.1.1:
+	         * 3.  If the year-value is greater than or equal to 70 and less
+	         * than or equal to 99, increment the year-value by 1900.
+	         * 4.  If the year-value is greater than or equal to 0 and less
+	         * than or equal to 69, increment the year-value by 2000.
+	         */
+	        if (year >= 70 && year <= 99) {
+	          year += 1900;
+	        } else if (year >= 0 && year <= 69) {
+	          year += 2000;
+	        }
+	      }
+	    }
+	  }
+
+	  /* RFC 6265 S5.1.1
+	   * "5. Abort these steps and fail to parse the cookie-date if:
+	   *     *  at least one of the found-day-of-month, found-month, found-
+	   *        year, or found-time flags is not set,
+	   *     *  the day-of-month-value is less than 1 or greater than 31,
+	   *     *  the year-value is less than 1601,
+	   *     *  the hour-value is greater than 23,
+	   *     *  the minute-value is greater than 59, or
+	   *     *  the second-value is greater than 59.
+	   *     (Note that leap seconds cannot be represented in this syntax.)"
+	   *
+	   * So, in order as above:
+	   */
+	  if (
+	    dayOfMonth === null || month === null || year === null || second === null ||
+	    dayOfMonth < 1 || dayOfMonth > 31 ||
+	    year < 1601 ||
+	    hour > 23 ||
+	    minute > 59 ||
+	    second > 59
+	  ) {
+	    return;
+	  }
+
+	  return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+	}
+
+	function formatDate(date) {
+	  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+	  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+	  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+	  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+	  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+	    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+	    h+':'+m+':'+s+' GMT';
+	}
+
+	// S5.1.2 Canonicalized Host Names
+	function canonicalDomain(str) {
+	  if (str == null) {
+	    return null;
+	  }
+	  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+	  // convert to IDN if any non-ASCII characters
+	  if (punycode && /[^\u0001-\u007f]/.test(str)) {
+	    str = punycode.toASCII(str);
+	  }
+
+	  return str.toLowerCase();
+	}
+
+	// S5.1.3 Domain Matching
+	function domainMatch(str, domStr, canonicalize) {
+	  if (str == null || domStr == null) {
+	    return null;
+	  }
+	  if (canonicalize !== false) {
+	    str = canonicalDomain(str);
+	    domStr = canonicalDomain(domStr);
+	  }
+
+	  /*
+	   * "The domain string and the string are identical. (Note that both the
+	   * domain string and the string will have been canonicalized to lower case at
+	   * this point)"
+	   */
+	  if (str == domStr) {
+	    return true;
+	  }
+
+	  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+	  /* "* The string is a host name (i.e., not an IP address)." */
+	  if (net.isIP(str)) {
+	    return false;
+	  }
+
+	  /* "* The domain string is a suffix of the string" */
+	  var idx = str.indexOf(domStr);
+	  if (idx <= 0) {
+	    return false; // it's a non-match (-1) or prefix (0)
+	  }
+
+	  // e.g "a.b.c".indexOf("b.c") === 2
+	  // 5 === 3+2
+	  if (str.length !== domStr.length + idx) { // it's not a suffix
+	    return false;
+	  }
+
+	  /* "* The last character of the string that is not included in the domain
+	  * string is a %x2E (".") character." */
+	  if (str.substr(idx-1,1) !== '.') {
+	    return false;
+	  }
+
+	  return true;
+	}
+
+
+	// RFC6265 S5.1.4 Paths and Path-Match
+
+	/*
+	 * "The user agent MUST use an algorithm equivalent to the following algorithm
+	 * to compute the default-path of a cookie:"
+	 *
+	 * Assumption: the path (and not query part or absolute uri) is passed in.
+	 */
+	function defaultPath(path) {
+	  // "2. If the uri-path is empty or if the first character of the uri-path is not
+	  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+	  if (!path || path.substr(0,1) !== "/") {
+	    return "/";
+	  }
+
+	  // "3. If the uri-path contains no more than one %x2F ("/") character, output
+	  // %x2F ("/") and skip the remaining step."
+	  if (path === "/") {
+	    return path;
+	  }
+
+	  var rightSlash = path.lastIndexOf("/");
+	  if (rightSlash === 0) {
+	    return "/";
+	  }
+
+	  // "4. Output the characters of the uri-path from the first character up to,
+	  // but not including, the right-most %x2F ("/")."
+	  return path.slice(0, rightSlash);
+	}
+
+	function trimTerminator(str) {
+	  for (var t = 0; t < TERMINATORS.length; t++) {
+	    var terminatorIdx = str.indexOf(TERMINATORS[t]);
+	    if (terminatorIdx !== -1) {
+	      str = str.substr(0,terminatorIdx);
+	    }
+	  }
+
+	  return str;
+	}
+
+	function parseCookiePair(cookiePair, looseMode) {
+	  cookiePair = trimTerminator(cookiePair);
+
+	  var firstEq = cookiePair.indexOf('=');
+	  if (looseMode) {
+	    if (firstEq === 0) { // '=' is immediately at start
+	      cookiePair = cookiePair.substr(1);
+	      firstEq = cookiePair.indexOf('='); // might still need to split on '='
+	    }
+	  } else { // non-loose mode
+	    if (firstEq <= 0) { // no '=' or is at start
+	      return; // needs to have non-empty "cookie-name"
+	    }
+	  }
+
+	  var cookieName, cookieValue;
+	  if (firstEq <= 0) {
+	    cookieName = "";
+	    cookieValue = cookiePair.trim();
+	  } else {
+	    cookieName = cookiePair.substr(0, firstEq).trim();
+	    cookieValue = cookiePair.substr(firstEq+1).trim();
+	  }
+
+	  if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+	    return;
+	  }
+
+	  var c = new Cookie();
+	  c.key = cookieName;
+	  c.value = cookieValue;
+	  return c;
+	}
+
+	function parse(str, options) {
+	  if (!options || typeof options !== 'object') {
+	    options = {};
+	  }
+	  str = str.trim();
+
+	  // We use a regex to parse the "name-value-pair" part of S5.2
+	  var firstSemi = str.indexOf(';'); // S5.2 step 1
+	  var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+	  var c = parseCookiePair(cookiePair, !!options.loose);
+	  if (!c) {
+	    return;
+	  }
+
+	  if (firstSemi === -1) {
+	    return c;
+	  }
+
+	  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+	  // (including the %x3B (";") in question)." plus later on in the same section
+	  // "discard the first ";" and trim".
+	  var unparsed = str.slice(firstSemi + 1).trim();
+
+	  // "If the unparsed-attributes string is empty, skip the rest of these
+	  // steps."
+	  if (unparsed.length === 0) {
+	    return c;
+	  }
+
+	  /*
+	   * S5.2 says that when looping over the items "[p]rocess the attribute-name
+	   * and attribute-value according to the requirements in the following
+	   * subsections" for every item.  Plus, for many of the individual attributes
+	   * in S5.3 it says to use the "attribute-value of the last attribute in the
+	   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
+	   * the previous value.
+	   */
+	  var cookie_avs = unparsed.split(';');
+	  while (cookie_avs.length) {
+	    var av = cookie_avs.shift().trim();
+	    if (av.length === 0) { // happens if ";;" appears
+	      continue;
+	    }
+	    var av_sep = av.indexOf('=');
+	    var av_key, av_value;
+
+	    if (av_sep === -1) {
+	      av_key = av;
+	      av_value = null;
+	    } else {
+	      av_key = av.substr(0,av_sep);
+	      av_value = av.substr(av_sep+1);
+	    }
+
+	    av_key = av_key.trim().toLowerCase();
+
+	    if (av_value) {
+	      av_value = av_value.trim();
+	    }
+
+	    switch(av_key) {
+	    case 'expires': // S5.2.1
+	      if (av_value) {
+	        var exp = parseDate(av_value);
+	        // "If the attribute-value failed to parse as a cookie date, ignore the
+	        // cookie-av."
+	        if (exp) {
+	          // over and underflow not realistically a concern: V8's getTime() seems to
+	          // store something larger than a 32-bit time_t (even with 32-bit node)
+	          c.expires = exp;
+	        }
+	      }
+	      break;
+
+	    case 'max-age': // S5.2.2
+	      if (av_value) {
+	        // "If the first character of the attribute-value is not a DIGIT or a "-"
+	        // character ...[or]... If the remainder of attribute-value contains a
+	        // non-DIGIT character, ignore the cookie-av."
+	        if (/^-?[0-9]+$/.test(av_value)) {
+	          var delta = parseInt(av_value, 10);
+	          // "If delta-seconds is less than or equal to zero (0), let expiry-time
+	          // be the earliest representable date and time."
+	          c.setMaxAge(delta);
+	        }
+	      }
+	      break;
+
+	    case 'domain': // S5.2.3
+	      // "If the attribute-value is empty, the behavior is undefined.  However,
+	      // the user agent SHOULD ignore the cookie-av entirely."
+	      if (av_value) {
+	        // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+	        // (".") character."
+	        var domain = av_value.trim().replace(/^\./, '');
+	        if (domain) {
+	          // "Convert the cookie-domain to lower case."
+	          c.domain = domain.toLowerCase();
+	        }
+	      }
+	      break;
+
+	    case 'path': // S5.2.4
+	      /*
+	       * "If the attribute-value is empty or if the first character of the
+	       * attribute-value is not %x2F ("/"):
+	       *   Let cookie-path be the default-path.
+	       * Otherwise:
+	       *   Let cookie-path be the attribute-value."
+	       *
+	       * We'll represent the default-path as null since it depends on the
+	       * context of the parsing.
+	       */
+	      c.path = av_value && av_value[0] === "/" ? av_value : null;
+	      break;
+
+	    case 'secure': // S5.2.5
+	      /*
+	       * "If the attribute-name case-insensitively matches the string "Secure",
+	       * the user agent MUST append an attribute to the cookie-attribute-list
+	       * with an attribute-name of Secure and an empty attribute-value."
+	       */
+	      c.secure = true;
+	      break;
+
+	    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+	      c.httpOnly = true;
+	      break;
+
+	    default:
+	      c.extensions = c.extensions || [];
+	      c.extensions.push(av);
+	      break;
+	    }
+	  }
+
+	  return c;
+	}
+
+	// avoid the V8 deoptimization monster!
+	function jsonParse(str) {
+	  var obj;
+	  try {
+	    obj = JSON.parse(str);
+	  } catch (e) {
+	    return e;
+	  }
+	  return obj;
+	}
+
+	function fromJSON(str) {
+	  if (!str) {
+	    return null;
+	  }
+
+	  var obj;
+	  if (typeof str === 'string') {
+	    obj = jsonParse(str);
+	    if (obj instanceof Error) {
+	      return null;
+	    }
+	  } else {
+	    // assume it's an Object
+	    obj = str;
+	  }
+
+	  var c = new Cookie();
+	  for (var i=0; i<Cookie.serializableProperties.length; i++) {
+	    var prop = Cookie.serializableProperties[i];
+	    if (obj[prop] === undefined ||
+	        obj[prop] === Cookie.prototype[prop])
+	    {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (obj[prop] === null) {
+	        c[prop] = null;
+	      } else {
+	        c[prop] = obj[prop] == "Infinity" ?
+	          "Infinity" : new Date(obj[prop]);
+	      }
+	    } else {
+	      c[prop] = obj[prop];
+	    }
+	  }
+
+	  return c;
+	}
+
+	/* Section 5.4 part 2:
+	 * "*  Cookies with longer paths are listed before cookies with
+	 *     shorter paths.
+	 *
+	 *  *  Among cookies that have equal-length path fields, cookies with
+	 *     earlier creation-times are listed before cookies with later
+	 *     creation-times."
+	 */
+
+	function cookieCompare(a,b) {
+	  var cmp = 0;
+
+	  // descending for length: b CMP a
+	  var aPathLen = a.path ? a.path.length : 0;
+	  var bPathLen = b.path ? b.path.length : 0;
+	  cmp = bPathLen - aPathLen;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // ascending for time: a CMP b
+	  var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+	  var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+	  cmp = aTime - bTime;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // break ties for the same millisecond (precision of JavaScript's clock)
+	  cmp = a.creationIndex - b.creationIndex;
+
+	  return cmp;
+	}
+
+	// Gives the permutation of all possible pathMatch()es of a given path. The
+	// array is in longest-to-shortest order.  Handy for indexing.
+	function permutePath(path) {
+	  if (path === '/') {
+	    return ['/'];
+	  }
+	  if (path.lastIndexOf('/') === path.length-1) {
+	    path = path.substr(0,path.length-1);
+	  }
+	  var permutations = [path];
+	  while (path.length > 1) {
+	    var lindex = path.lastIndexOf('/');
+	    if (lindex === 0) {
+	      break;
+	    }
+	    path = path.substr(0,lindex);
+	    permutations.push(path);
+	  }
+	  permutations.push('/');
+	  return permutations;
+	}
+
+	function getCookieContext(url) {
+	  if (url instanceof Object) {
+	    return url;
+	  }
+	  // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+	  // Therefore, we will just skip decoding for such URIs.
+	  try {
+	    url = decodeURI(url);
+	  }
+	  catch(err) {
+	    // Silently swallow error
+	  }
+
+	  return urlParse(url);
+	}
+
+	function Cookie(options) {
+	  options = options || {};
+
+	  Object.keys(options).forEach(function(prop) {
+	    if (Cookie.prototype.hasOwnProperty(prop) &&
+	        Cookie.prototype[prop] !== options[prop] &&
+	        prop.substr(0,1) !== '_')
+	    {
+	      this[prop] = options[prop];
+	    }
+	  }, this);
+
+	  this.creation = this.creation || new Date();
+
+	  // used to break creation ties in cookieCompare():
+	  Object.defineProperty(this, 'creationIndex', {
+	    configurable: false,
+	    enumerable: false, // important for assert.deepEqual checks
+	    writable: true,
+	    value: ++Cookie.cookiesCreated
+	  });
+	}
+
+	Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+	Cookie.parse = parse;
+	Cookie.fromJSON = fromJSON;
+
+	Cookie.prototype.key = "";
+	Cookie.prototype.value = "";
+
+	// the order in which the RFC has them:
+	Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+	Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+	Cookie.prototype.domain = null;
+	Cookie.prototype.path = null;
+	Cookie.prototype.secure = false;
+	Cookie.prototype.httpOnly = false;
+	Cookie.prototype.extensions = null;
+
+	// set by the CookieJar:
+	Cookie.prototype.hostOnly = null; // boolean when set
+	Cookie.prototype.pathIsDefault = null; // boolean when set
+	Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+	Cookie.prototype.lastAccessed = null; // Date when set
+	Object.defineProperty(Cookie.prototype, 'creationIndex', {
+	  configurable: true,
+	  enumerable: false,
+	  writable: true,
+	  value: 0
+	});
+
+	Cookie.serializableProperties = Object.keys(Cookie.prototype)
+	  .filter(function(prop) {
+	    return !(
+	      Cookie.prototype[prop] instanceof Function ||
+	      prop === 'creationIndex' ||
+	      prop.substr(0,1) === '_'
+	    );
+	  });
+
+	Cookie.prototype.inspect = function inspect() {
+	  var now = Date.now();
+	  return 'Cookie="'+this.toString() +
+	    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+	    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+	    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+	    '"';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+	}
+
+	Cookie.prototype.toJSON = function() {
+	  var obj = {};
+
+	  var props = Cookie.serializableProperties;
+	  for (var i=0; i<props.length; i++) {
+	    var prop = props[i];
+	    if (this[prop] === Cookie.prototype[prop]) {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (this[prop] === null) {
+	        obj[prop] = null;
+	      } else {
+	        obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+	          "Infinity" : this[prop].toISOString();
+	      }
+	    } else if (prop === 'maxAge') {
+	      if (this[prop] !== null) {
+	        // again, intentionally not ===
+	        obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+	          this[prop].toString() : this[prop];
+	      }
+	    } else {
+	      if (this[prop] !== Cookie.prototype[prop]) {
+	        obj[prop] = this[prop];
+	      }
+	    }
+	  }
+
+	  return obj;
+	};
+
+	Cookie.prototype.clone = function() {
+	  return fromJSON(this.toJSON());
+	};
+
+	Cookie.prototype.validate = function validate() {
+	  if (!COOKIE_OCTETS.test(this.value)) {
+	    return false;
+	  }
+	  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+	    return false;
+	  }
+	  if (this.maxAge != null && this.maxAge <= 0) {
+	    return false; // "Max-Age=" non-zero-digit *DIGIT
+	  }
+	  if (this.path != null && !PATH_VALUE.test(this.path)) {
+	    return false;
+	  }
+
+	  var cdomain = this.cdomain();
+	  if (cdomain) {
+	    if (cdomain.match(/\.$/)) {
+	      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+	    }
+	    var suffix = pubsuffix.getPublicSuffix(cdomain);
+	    if (suffix == null) { // it's a public suffix
+	      return false;
+	    }
+	  }
+	  return true;
+	};
+
+	Cookie.prototype.setExpires = function setExpires(exp) {
+	  if (exp instanceof Date) {
+	    this.expires = exp;
+	  } else {
+	    this.expires = parseDate(exp) || "Infinity";
+	  }
+	};
+
+	Cookie.prototype.setMaxAge = function setMaxAge(age) {
+	  if (age === Infinity || age === -Infinity) {
+	    this.maxAge = age.toString(); // so JSON.stringify() works
+	  } else {
+	    this.maxAge = age;
+	  }
+	};
+
+	// gives Cookie header format
+	Cookie.prototype.cookieString = function cookieString() {
+	  var val = this.value;
+	  if (val == null) {
+	    val = '';
+	  }
+	  if (this.key === '') {
+	    return val;
+	  }
+	  return this.key+'='+val;
+	};
+
+	// gives Set-Cookie header format
+	Cookie.prototype.toString = function toString() {
+	  var str = this.cookieString();
+
+	  if (this.expires != Infinity) {
+	    if (this.expires instanceof Date) {
+	      str += '; Expires='+formatDate(this.expires);
+	    } else {
+	      str += '; Expires='+this.expires;
+	    }
+	  }
+
+	  if (this.maxAge != null && this.maxAge != Infinity) {
+	    str += '; Max-Age='+this.maxAge;
+	  }
+
+	  if (this.domain && !this.hostOnly) {
+	    str += '; Domain='+this.domain;
+	  }
+	  if (this.path) {
+	    str += '; Path='+this.path;
+	  }
+
+	  if (this.secure) {
+	    str += '; Secure';
+	  }
+	  if (this.httpOnly) {
+	    str += '; HttpOnly';
+	  }
+	  if (this.extensions) {
+	    this.extensions.forEach(function(ext) {
+	      str += '; '+ext;
+	    });
+	  }
+
+	  return str;
+	};
+
+	// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	// S5.3 says to give the "latest representable date" for which we use Infinity
+	// For "expired" we use 0
+	Cookie.prototype.TTL = function TTL(now) {
+	  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+	   * attribute, the Max-Age attribute has precedence and controls the
+	   * expiration date of the cookie.
+	   * (Concurs with S5.3 step 3)
+	   */
+	  if (this.maxAge != null) {
+	    return this.maxAge<=0 ? 0 : this.maxAge*1000;
+	  }
+
+	  var expires = this.expires;
+	  if (expires != Infinity) {
+	    if (!(expires instanceof Date)) {
+	      expires = parseDate(expires) || Infinity;
+	    }
+
+	    if (expires == Infinity) {
+	      return Infinity;
+	    }
+
+	    return expires.getTime() - (now || Date.now());
+	  }
+
+	  return Infinity;
+	};
+
+	// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	Cookie.prototype.expiryTime = function expiryTime(now) {
+	  if (this.maxAge != null) {
+	    var relativeTo = now || this.creation || new Date();
+	    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+	    return relativeTo.getTime() + age;
+	  }
+
+	  if (this.expires == Infinity) {
+	    return Infinity;
+	  }
+	  return this.expires.getTime();
+	};
+
+	// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere), except it returns a Date
+	Cookie.prototype.expiryDate = function expiryDate(now) {
+	  var millisec = this.expiryTime(now);
+	  if (millisec == Infinity) {
+	    return new Date(MAX_TIME);
+	  } else if (millisec == -Infinity) {
+	    return new Date(MIN_TIME);
+	  } else {
+	    return new Date(millisec);
+	  }
+	};
+
+	// This replaces the "persistent-flag" parts of S5.3 step 3
+	Cookie.prototype.isPersistent = function isPersistent() {
+	  return (this.maxAge != null || this.expires != Infinity);
+	};
+
+	// Mostly S5.1.2 and S5.2.3:
+	Cookie.prototype.cdomain =
+	Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+	  if (this.domain == null) {
+	    return null;
+	  }
+	  return canonicalDomain(this.domain);
+	};
+
+	function CookieJar(store, options) {
+	  if (typeof options === "boolean") {
+	    options = {rejectPublicSuffixes: options};
+	  } else if (options == null) {
+	    options = {};
+	  }
+	  if (options.rejectPublicSuffixes != null) {
+	    this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+	  }
+	  if (options.looseMode != null) {
+	    this.enableLooseMode = options.looseMode;
+	  }
+
+	  if (!store) {
+	    store = new MemoryCookieStore();
+	  }
+	  this.store = store;
+	}
+	CookieJar.prototype.store = null;
+	CookieJar.prototype.rejectPublicSuffixes = true;
+	CookieJar.prototype.enableLooseMode = false;
+	var CAN_BE_SYNC = [];
+
+	CAN_BE_SYNC.push('setCookie');
+	CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+	  var err;
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var loose = this.enableLooseMode;
+	  if (options.loose != null) {
+	    loose = options.loose;
+	  }
+
+	  // S5.3 step 1
+	  if (!(cookie instanceof Cookie)) {
+	    cookie = Cookie.parse(cookie, { loose: loose });
+	  }
+	  if (!cookie) {
+	    err = new Error("Cookie failed to parse");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  // S5.3 step 2
+	  var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+	  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+	  // S5.3 step 4: NOOP; domain is null by default
+
+	  // S5.3 step 5: public suffixes
+	  if (this.rejectPublicSuffixes && cookie.domain) {
+	    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+	    if (suffix == null) { // e.g. "com"
+	      err = new Error("Cookie has domain set to a public suffix");
+	      return cb(options.ignoreError ? null : err);
+	    }
+	  }
+
+	  // S5.3 step 6:
+	  if (cookie.domain) {
+	    if (!domainMatch(host, cookie.cdomain(), false)) {
+	      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+	      return cb(options.ignoreError ? null : err);
+	    }
+
+	    if (cookie.hostOnly == null) { // don't reset if already set
+	      cookie.hostOnly = false;
+	    }
+
+	  } else {
+	    cookie.hostOnly = true;
+	    cookie.domain = host;
+	  }
+
+	  //S5.2.4 If the attribute-value is empty or if the first character of the
+	  //attribute-value is not %x2F ("/"):
+	  //Let cookie-path be the default-path.
+	  if (!cookie.path || cookie.path[0] !== '/') {
+	    cookie.path = defaultPath(context.pathname);
+	    cookie.pathIsDefault = true;
+	  }
+
+	  // S5.3 step 8: NOOP; secure attribute
+	  // S5.3 step 9: NOOP; httpOnly attribute
+
+	  // S5.3 step 10
+	  if (options.http === false && cookie.httpOnly) {
+	    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  var store = this.store;
+
+	  if (!store.updateCookie) {
+	    store.updateCookie = function(oldCookie, newCookie, cb) {
+	      this.putCookie(newCookie, cb);
+	    };
+	  }
+
+	  function withCookie(err, oldCookie) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    var next = function(err) {
+	      if (err) {
+	        return cb(err);
+	      } else {
+	        cb(null, cookie);
+	      }
+	    };
+
+	    if (oldCookie) {
+	      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+	      // domain, and path as the newly created cookie:"
+	      if (options.http === false && oldCookie.httpOnly) { // step 11.2
+	        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+	        return cb(options.ignoreError ? null : err);
+	      }
+	      cookie.creation = oldCookie.creation; // step 11.3
+	      cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+	      cookie.lastAccessed = now;
+	      // Step 11.4 (delete cookie) is implied by just setting the new one:
+	      store.updateCookie(oldCookie, cookie, next); // step 12
+
+	    } else {
+	      cookie.creation = cookie.lastAccessed = now;
+	      store.putCookie(cookie, next); // step 12
+	    }
+	  }
+
+	  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+	};
+
+	// RFC6365 S5.4
+	CAN_BE_SYNC.push('getCookies');
+	CookieJar.prototype.getCookies = function(url, options, cb) {
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var path = context.pathname || '/';
+
+	  var secure = options.secure;
+	  if (secure == null && context.protocol &&
+	      (context.protocol == 'https:' || context.protocol == 'wss:'))
+	  {
+	    secure = true;
+	  }
+
+	  var http = options.http;
+	  if (http == null) {
+	    http = true;
+	  }
+
+	  var now = options.now || Date.now();
+	  var expireCheck = options.expire !== false;
+	  var allPaths = !!options.allPaths;
+	  var store = this.store;
+
+	  function matchingCookie(c) {
+	    // "Either:
+	    //   The cookie's host-only-flag is true and the canonicalized
+	    //   request-host is identical to the cookie's domain.
+	    // Or:
+	    //   The cookie's host-only-flag is false and the canonicalized
+	    //   request-host domain-matches the cookie's domain."
+	    if (c.hostOnly) {
+	      if (c.domain != host) {
+	        return false;
+	      }
+	    } else {
+	      if (!domainMatch(host, c.domain, false)) {
+	        return false;
+	      }
+	    }
+
+	    // "The request-uri's path path-matches the cookie's path."
+	    if (!allPaths && !pathMatch(path, c.path)) {
+	      return false;
+	    }
+
+	    // "If the cookie's secure-only-flag is true, then the request-uri's
+	    // scheme must denote a "secure" protocol"
+	    if (c.secure && !secure) {
+	      return false;
+	    }
+
+	    // "If the cookie's http-only-flag is true, then exclude the cookie if the
+	    // cookie-string is being generated for a "non-HTTP" API"
+	    if (c.httpOnly && !http) {
+	      return false;
+	    }
+
+	    // deferred from S5.3
+	    // non-RFC: allow retention of expired cookies by choice
+	    if (expireCheck && c.expiryTime() <= now) {
+	      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+	      return false;
+	    }
+
+	    return true;
+	  }
+
+	  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    cookies = cookies.filter(matchingCookie);
+
+	    // sorting of S5.4 part 2
+	    if (options.sort !== false) {
+	      cookies = cookies.sort(cookieCompare);
+	    }
+
+	    // S5.4 part 3
+	    var now = new Date();
+	    cookies.forEach(function(c) {
+	      c.lastAccessed = now;
+	    });
+	    // TODO persist lastAccessed
+
+	    cb(null,cookies);
+	  });
+	};
+
+	CAN_BE_SYNC.push('getCookieString');
+	CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies
+	        .sort(cookieCompare)
+	        .map(function(c){
+	          return c.cookieString();
+	        })
+	        .join('; '));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('getSetCookieStrings');
+	CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies.map(function(c){
+	        return c.toString();
+	      }));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('serialize');
+	CookieJar.prototype.serialize = function(cb) {
+	  var type = this.store.constructor.name;
+	  if (type === 'Object') {
+	    type = null;
+	  }
+
+	  // update README.md "Serialization Format" if you change this, please!
+	  var serialized = {
+	    // The version of tough-cookie that serialized this jar. Generally a good
+	    // practice since future versions can make data import decisions based on
+	    // known past behavior. When/if this matters, use `semver`.
+	    version: 'tough-cookie@'+VERSION,
+
+	    // add the store type, to make humans happy:
+	    storeType: type,
+
+	    // CookieJar configuration:
+	    rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+	    // this gets filled from getAllCookies:
+	    cookies: []
+	  };
+
+	  if (!(this.store.getAllCookies &&
+	        typeof this.store.getAllCookies === 'function'))
+	  {
+	    return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+	  }
+
+	  this.store.getAllCookies(function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    serialized.cookies = cookies.map(function(cookie) {
+	      // convert to serialized 'raw' cookies
+	      cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+	      // Remove the index so new ones get assigned during deserialization
+	      delete cookie.creationIndex;
+
+	      return cookie;
+	    });
+
+	    return cb(null, serialized);
+	  });
+	};
+
+	// well-known name that JSON.stringify calls
+	CookieJar.prototype.toJSON = function() {
+	  return this.serializeSync();
+	};
+
+	// use the class method CookieJar.deserialize instead of calling this directly
+	CAN_BE_SYNC.push('_importCookies');
+	CookieJar.prototype._importCookies = function(serialized, cb) {
+	  var jar = this;
+	  var cookies = serialized.cookies;
+	  if (!cookies || !Array.isArray(cookies)) {
+	    return cb(new Error('serialized jar has no cookies array'));
+	  }
+	  cookies = cookies.slice(); // do not modify the original
+
+	  function putNext(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    if (!cookies.length) {
+	      return cb(err, jar);
+	    }
+
+	    var cookie;
+	    try {
+	      cookie = fromJSON(cookies.shift());
+	    } catch (e) {
+	      return cb(e);
+	    }
+
+	    if (cookie === null) {
+	      return putNext(null); // skip this cookie
+	    }
+
+	    jar.store.putCookie(cookie, putNext);
+	  }
+
+	  putNext();
+	};
+
+	CookieJar.deserialize = function(strOrObj, store, cb) {
+	  if (arguments.length !== 3) {
+	    // store is optional
+	    cb = store;
+	    store = null;
+	  }
+
+	  var serialized;
+	  if (typeof strOrObj === 'string') {
+	    serialized = jsonParse(strOrObj);
+	    if (serialized instanceof Error) {
+	      return cb(serialized);
+	    }
+	  } else {
+	    serialized = strOrObj;
+	  }
+
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+	  jar._importCookies(serialized, function(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    cb(null, jar);
+	  });
+	};
+
+	CookieJar.deserializeSync = function(strOrObj, store) {
+	  var serialized = typeof strOrObj === 'string' ?
+	    JSON.parse(strOrObj) : strOrObj;
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+	  // catch this mistake early:
+	  if (!jar.store.synchronous) {
+	    throw new Error('CookieJar store is not synchronous; use async API instead.');
+	  }
+
+	  jar._importCookiesSync(serialized);
+	  return jar;
+	};
+	CookieJar.fromJSON = CookieJar.deserializeSync;
+
+	CAN_BE_SYNC.push('clone');
+	CookieJar.prototype.clone = function(newStore, cb) {
+	  if (arguments.length === 1) {
+	    cb = newStore;
+	    newStore = null;
+	  }
+
+	  this.serialize(function(err,serialized) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    CookieJar.deserialize(newStore, serialized, cb);
+	  });
+	};
+
+	// Use a closure to provide a true imperative API for synchronous stores.
+	function syncWrap(method) {
+	  return function() {
+	    if (!this.store.synchronous) {
+	      throw new Error('CookieJar store is not synchronous; use async API instead.');
+	    }
+
+	    var args = Array.prototype.slice.call(arguments);
+	    var syncErr, syncResult;
+	    args.push(function syncCb(err, result) {
+	      syncErr = err;
+	      syncResult = result;
+	    });
+	    this[method].apply(this, args);
+
+	    if (syncErr) {
+	      throw syncErr;
+	    }
+	    return syncResult;
+	  };
+	}
+
+	// wrap all declared CAN_BE_SYNC methods in the sync wrapper
+	CAN_BE_SYNC.forEach(function(method) {
+	  CookieJar.prototype[method+'Sync'] = syncWrap(method);
+	});
+
+	exports.CookieJar = CookieJar;
+	exports.Cookie = Cookie;
+	exports.Store = Store;
+	exports.MemoryCookieStore = MemoryCookieStore;
+	exports.parseDate = parseDate;
+	exports.formatDate = formatDate;
+	exports.parse = parse;
+	exports.fromJSON = fromJSON;
+	exports.domainMatch = domainMatch;
+	exports.defaultPath = defaultPath;
+	exports.pathMatch = pathMatch;
+	exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+	exports.cookieCompare = cookieCompare;
+	exports.permuteDomain = __webpack_require__(19).permuteDomain;
+	exports.permutePath = permutePath;
+	exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+	/*
+	* Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+	* Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+	*/
+
+	var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+	var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+	function isIPv4(hostOrIp) {
+	  return hostOrIp.match(patternIPv4) ? true : false;
+	}
+
+	function isIPv6(hostOrIp) {
+	  return hostOrIp.match(patternIPv6) ? true : false;
+	}
+
+	function isIP(hostOrIp) {
+	  if (isIPv4(hostOrIp)) {
+	    return 4;
+	  }
+
+	  if (isIPv6(hostOrIp)) {
+	    return 6;
+	  }
+
+	  return 0;
+	}
+
+	module.exports = {
+	  isIPv4: isIPv4,
+	  isIPv6: isIPv6,
+	  isIP: isIP
+	};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var punycode = __webpack_require__(3);
+	var util = __webpack_require__(5);
+
+	exports.parse = urlParse;
+	exports.resolve = urlResolve;
+	exports.resolveObject = urlResolveObject;
+	exports.format = urlFormat;
+
+	exports.Url = Url;
+
+	function Url() {
+	  this.protocol = null;
+	  this.slashes = null;
+	  this.auth = null;
+	  this.host = null;
+	  this.port = null;
+	  this.hostname = null;
+	  this.hash = null;
+	  this.search = null;
+	  this.query = null;
+	  this.pathname = null;
+	  this.path = null;
+	  this.href = null;
+	}
+
+	// Reference: RFC 3986, RFC 1808, RFC 2396
+
+	// define these here so at least they only have to be
+	// compiled once on the first module load.
+	var protocolPattern = /^([a-z0-9.+-]+:)/i,
+	    portPattern = /:[0-9]*$/,
+
+	    // Special case for a simple path URL
+	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+	    // RFC 2396: characters reserved for delimiting URLs.
+	    // We actually just auto-escape these.
+	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+	    // RFC 2396: characters not allowed for various reasons.
+	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
+	    autoEscape = ['\''].concat(unwise),
+	    // Characters that are never ever allowed in a hostname.
+	    // Note that any invalid chars are also handled, but these
+	    // are the ones that are *expected* to be seen, so we fast-path
+	    // them.
+	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+	    hostEndingChars = ['/', '?', '#'],
+	    hostnameMaxLen = 255,
+	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+	    // protocols that can allow "unsafe" and "unwise" chars.
+	    unsafeProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that never have a hostname.
+	    hostlessProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that always contain a // bit.
+	    slashedProtocol = {
+	      'http': true,
+	      'https': true,
+	      'ftp': true,
+	      'gopher': true,
+	      'file': true,
+	      'http:': true,
+	      'https:': true,
+	      'ftp:': true,
+	      'gopher:': true,
+	      'file:': true
+	    },
+	    querystring = __webpack_require__(6);
+
+	function urlParse(url, parseQueryString, slashesDenoteHost) {
+	  if (url && util.isObject(url) && url instanceof Url) return url;
+
+	  var u = new Url;
+	  u.parse(url, parseQueryString, slashesDenoteHost);
+	  return u;
+	}
+
+	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+	  if (!util.isString(url)) {
+	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+	  }
+
+	  // Copy chrome, IE, opera backslash-handling behavior.
+	  // Back slashes before the query string get converted to forward slashes
+	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
+	  var queryIndex = url.indexOf('?'),
+	      splitter =
+	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+	      uSplit = url.split(splitter),
+	      slashRegex = /\\/g;
+	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
+	  url = uSplit.join(splitter);
+
+	  var rest = url;
+
+	  // trim before proceeding.
+	  // This is to support parse stuff like "  http://foo.com  \n"
+	  rest = rest.trim();
+
+	  if (!slashesDenoteHost && url.split('#').length === 1) {
+	    // Try fast path regexp
+	    var simplePath = simplePathPattern.exec(rest);
+	    if (simplePath) {
+	      this.path = rest;
+	      this.href = rest;
+	      this.pathname = simplePath[1];
+	      if (simplePath[2]) {
+	        this.search = simplePath[2];
+	        if (parseQueryString) {
+	          this.query = querystring.parse(this.search.substr(1));
+	        } else {
+	          this.query = this.search.substr(1);
+	        }
+	      } else if (parseQueryString) {
+	        this.search = '';
+	        this.query = {};
+	      }
+	      return this;
+	    }
+	  }
+
+	  var proto = protocolPattern.exec(rest);
+	  if (proto) {
+	    proto = proto[0];
+	    var lowerProto = proto.toLowerCase();
+	    this.protocol = lowerProto;
+	    rest = rest.substr(proto.length);
+	  }
+
+	  // figure out if it's got a host
+	  // user@server is *always* interpreted as a hostname, and url
+	  // resolution will treat //foo/bar as host=foo,path=bar because that's
+	  // how the browser resolves relative URLs.
+	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+	    var slashes = rest.substr(0, 2) === '//';
+	    if (slashes && !(proto && hostlessProtocol[proto])) {
+	      rest = rest.substr(2);
+	      this.slashes = true;
+	    }
+	  }
+
+	  if (!hostlessProtocol[proto] &&
+	      (slashes || (proto && !slashedProtocol[proto]))) {
+
+	    // there's a hostname.
+	    // the first instance of /, ?, ;, or # ends the host.
+	    //
+	    // If there is an @ in the hostname, then non-host chars *are* allowed
+	    // to the left of the last @ sign, unless some host-ending character
+	    // comes *before* the @-sign.
+	    // URLs are obnoxious.
+	    //
+	    // ex:
+	    // http://a@b@c/ => user:a@b host:c
+	    // http://a@b?@c => user:a host:c path:/?@c
+
+	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+	    // Review our test case against browsers more comprehensively.
+
+	    // find the first instance of any hostEndingChars
+	    var hostEnd = -1;
+	    for (var i = 0; i < hostEndingChars.length; i++) {
+	      var hec = rest.indexOf(hostEndingChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+
+	    // at this point, either we have an explicit point where the
+	    // auth portion cannot go past, or the last @ char is the decider.
+	    var auth, atSign;
+	    if (hostEnd === -1) {
+	      // atSign can be anywhere.
+	      atSign = rest.lastIndexOf('@');
+	    } else {
+	      // atSign must be in auth portion.
+	      // http://a@b/c@d => host:b auth:a path:/c@d
+	      atSign = rest.lastIndexOf('@', hostEnd);
+	    }
+
+	    // Now we have a portion which is definitely the auth.
+	    // Pull that off.
+	    if (atSign !== -1) {
+	      auth = rest.slice(0, atSign);
+	      rest = rest.slice(atSign + 1);
+	      this.auth = decodeURIComponent(auth);
+	    }
+
+	    // the host is the remaining to the left of the first non-host char
+	    hostEnd = -1;
+	    for (var i = 0; i < nonHostChars.length; i++) {
+	      var hec = rest.indexOf(nonHostChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+	    // if we still have not hit it, then the entire thing is a host.
+	    if (hostEnd === -1)
+	      hostEnd = rest.length;
+
+	    this.host = rest.slice(0, hostEnd);
+	    rest = rest.slice(hostEnd);
+
+	    // pull out port.
+	    this.parseHost();
+
+	    // we've indicated that there is a hostname,
+	    // so even if it's empty, it has to be present.
+	    this.hostname = this.hostname || '';
+
+	    // if hostname begins with [ and ends with ]
+	    // assume that it's an IPv6 address.
+	    var ipv6Hostname = this.hostname[0] === '[' &&
+	        this.hostname[this.hostname.length - 1] === ']';
+
+	    // validate a little.
+	    if (!ipv6Hostname) {
+	      var hostparts = this.hostname.split(/\./);
+	      for (var i = 0, l = hostparts.length; i < l; i++) {
+	        var part = hostparts[i];
+	        if (!part) continue;
+	        if (!part.match(hostnamePartPattern)) {
+	          var newpart = '';
+	          for (var j = 0, k = part.length; j < k; j++) {
+	            if (part.charCodeAt(j) > 127) {
+	              // we replace non-ASCII char with a temporary placeholder
+	              // we need this to make sure size of hostname is not
+	              // broken by replacing non-ASCII by nothing
+	              newpart += 'x';
+	            } else {
+	              newpart += part[j];
+	            }
+	          }
+	          // we test again with ASCII char only
+	          if (!newpart.match(hostnamePartPattern)) {
+	            var validParts = hostparts.slice(0, i);
+	            var notHost = hostparts.slice(i + 1);
+	            var bit = part.match(hostnamePartStart);
+	            if (bit) {
+	              validParts.push(bit[1]);
+	              notHost.unshift(bit[2]);
+	            }
+	            if (notHost.length) {
+	              rest = '/' + notHost.join('.') + rest;
+	            }
+	            this.hostname = validParts.join('.');
+	            break;
+	          }
+	        }
+	      }
+	    }
+
+	    if (this.hostname.length > hostnameMaxLen) {
+	      this.hostname = '';
+	    } else {
+	      // hostnames are always lower case.
+	      this.hostname = this.hostname.toLowerCase();
+	    }
+
+	    if (!ipv6Hostname) {
+	      // IDNA Support: Returns a punycoded representation of "domain".
+	      // It only converts parts of the domain name that
+	      // have non-ASCII characters, i.e. it doesn't matter if
+	      // you call it with a domain that already is ASCII-only.
+	      this.hostname = punycode.toASCII(this.hostname);
+	    }
+
+	    var p = this.port ? ':' + this.port : '';
+	    var h = this.hostname || '';
+	    this.host = h + p;
+	    this.href += this.host;
+
+	    // strip [ and ] from the hostname
+	    // the host field still retains them, though
+	    if (ipv6Hostname) {
+	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+	      if (rest[0] !== '/') {
+	        rest = '/' + rest;
+	      }
+	    }
+	  }
+
+	  // now rest is set to the post-host stuff.
+	  // chop off any delim chars.
+	  if (!unsafeProtocol[lowerProto]) {
+
+	    // First, make 100% sure that any "autoEscape" chars get
+	    // escaped, even if encodeURIComponent doesn't think they
+	    // need to be.
+	    for (var i = 0, l = autoEscape.length; i < l; i++) {
+	      var ae = autoEscape[i];
+	      if (rest.indexOf(ae) === -1)
+	        continue;
+	      var esc = encodeURIComponent(ae);
+	      if (esc === ae) {
+	        esc = escape(ae);
+	      }
+	      rest = rest.split(ae).join(esc);
+	    }
+	  }
+
+
+	  // chop off from the tail first.
+	  var hash = rest.indexOf('#');
+	  if (hash !== -1) {
+	    // got a fragment string.
+	    this.hash = rest.substr(hash);
+	    rest = rest.slice(0, hash);
+	  }
+	  var qm = rest.indexOf('?');
+	  if (qm !== -1) {
+	    this.search = rest.substr(qm);
+	    this.query = rest.substr(qm + 1);
+	    if (parseQueryString) {
+	      this.query = querystring.parse(this.query);
+	    }
+	    rest = rest.slice(0, qm);
+	  } else if (parseQueryString) {
+	    // no query string, but parseQueryString still requested
+	    this.search = '';
+	    this.query = {};
+	  }
+	  if (rest) this.pathname = rest;
+	  if (slashedProtocol[lowerProto] &&
+	      this.hostname && !this.pathname) {
+	    this.pathname = '/';
+	  }
+
+	  //to support http.request
+	  if (this.pathname || this.search) {
+	    var p = this.pathname || '';
+	    var s = this.search || '';
+	    this.path = p + s;
+	  }
+
+	  // finally, reconstruct the href based on what has been validated.
+	  this.href = this.format();
+	  return this;
+	};
+
+	// format a parsed object into a url string
+	function urlFormat(obj) {
+	  // ensure it's an object, and not a string url.
+	  // If it's an obj, this is a no-op.
+	  // this way, you can call url_format() on strings
+	  // to clean up potentially wonky urls.
+	  if (util.isString(obj)) obj = urlParse(obj);
+	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+	  return obj.format();
+	}
+
+	Url.prototype.format = function() {
+	  var auth = this.auth || '';
+	  if (auth) {
+	    auth = encodeURIComponent(auth);
+	    auth = auth.replace(/%3A/i, ':');
+	    auth += '@';
+	  }
+
+	  var protocol = this.protocol || '',
+	      pathname = this.pathname || '',
+	      hash = this.hash || '',
+	      host = false,
+	      query = '';
+
+	  if (this.host) {
+	    host = auth + this.host;
+	  } else if (this.hostname) {
+	    host = auth + (this.hostname.indexOf(':') === -1 ?
+	        this.hostname :
+	        '[' + this.hostname + ']');
+	    if (this.port) {
+	      host += ':' + this.port;
+	    }
+	  }
+
+	  if (this.query &&
+	      util.isObject(this.query) &&
+	      Object.keys(this.query).length) {
+	    query = querystring.stringify(this.query);
+	  }
+
+	  var search = this.search || (query && ('?' + query)) || '';
+
+	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
+	  // unless they had them to begin with.
+	  if (this.slashes ||
+	      (!protocol || slashedProtocol[protocol]) && host !== false) {
+	    host = '//' + (host || '');
+	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+	  } else if (!host) {
+	    host = '';
+	  }
+
+	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+	  if (search && search.charAt(0) !== '?') search = '?' + search;
+
+	  pathname = pathname.replace(/[?#]/g, function(match) {
+	    return encodeURIComponent(match);
+	  });
+	  search = search.replace('#', '%23');
+
+	  return protocol + host + pathname + search + hash;
+	};
+
+	function urlResolve(source, relative) {
+	  return urlParse(source, false, true).resolve(relative);
+	}
+
+	Url.prototype.resolve = function(relative) {
+	  return this.resolveObject(urlParse(relative, false, true)).format();
+	};
+
+	function urlResolveObject(source, relative) {
+	  if (!source) return relative;
+	  return urlParse(source, false, true).resolveObject(relative);
+	}
+
+	Url.prototype.resolveObject = function(relative) {
+	  if (util.isString(relative)) {
+	    var rel = new Url();
+	    rel.parse(relative, false, true);
+	    relative = rel;
+	  }
+
+	  var result = new Url();
+	  var tkeys = Object.keys(this);
+	  for (var tk = 0; tk < tkeys.length; tk++) {
+	    var tkey = tkeys[tk];
+	    result[tkey] = this[tkey];
+	  }
+
+	  // hash is always overridden, no matter what.
+	  // even href="" will remove it.
+	  result.hash = relative.hash;
+
+	  // if the relative url is empty, then there's nothing left to do here.
+	  if (relative.href === '') {
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // hrefs like //foo/bar always cut to the protocol.
+	  if (relative.slashes && !relative.protocol) {
+	    // take everything except the protocol from relative
+	    var rkeys = Object.keys(relative);
+	    for (var rk = 0; rk < rkeys.length; rk++) {
+	      var rkey = rkeys[rk];
+	      if (rkey !== 'protocol')
+	        result[rkey] = relative[rkey];
+	    }
+
+	    //urlParse appends trailing / to urls like http://www.example.com
+	    if (slashedProtocol[result.protocol] &&
+	        result.hostname && !result.pathname) {
+	      result.path = result.pathname = '/';
+	    }
+
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (relative.protocol && relative.protocol !== result.protocol) {
+	    // if it's a known url protocol, then changing
+	    // the protocol does weird things
+	    // first, if it's not file:, then we MUST have a host,
+	    // and if there was a path
+	    // to begin with, then we MUST have a path.
+	    // if it is file:, then the host is dropped,
+	    // because that's known to be hostless.
+	    // anything else is assumed to be absolute.
+	    if (!slashedProtocol[relative.protocol]) {
+	      var keys = Object.keys(relative);
+	      for (var v = 0; v < keys.length; v++) {
+	        var k = keys[v];
+	        result[k] = relative[k];
+	      }
+	      result.href = result.format();
+	      return result;
+	    }
+
+	    result.protocol = relative.protocol;
+	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
+	      var relPath = (relative.pathname || '').split('/');
+	      while (relPath.length && !(relative.host = relPath.shift()));
+	      if (!relative.host) relative.host = '';
+	      if (!relative.hostname) relative.hostname = '';
+	      if (relPath[0] !== '') relPath.unshift('');
+	      if (relPath.length < 2) relPath.unshift('');
+	      result.pathname = relPath.join('/');
+	    } else {
+	      result.pathname = relative.pathname;
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    result.host = relative.host || '';
+	    result.auth = relative.auth;
+	    result.hostname = relative.hostname || relative.host;
+	    result.port = relative.port;
+	    // to support http.request
+	    if (result.pathname || result.search) {
+	      var p = result.pathname || '';
+	      var s = result.search || '';
+	      result.path = p + s;
+	    }
+	    result.slashes = result.slashes || relative.slashes;
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+	      isRelAbs = (
+	          relative.host ||
+	          relative.pathname && relative.pathname.charAt(0) === '/'
+	      ),
+	      mustEndAbs = (isRelAbs || isSourceAbs ||
+	                    (result.host && relative.pathname)),
+	      removeAllDots = mustEndAbs,
+	      srcPath = result.pathname && result.pathname.split('/') || [],
+	      relPath = relative.pathname && relative.pathname.split('/') || [],
+	      psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+	  // if the url is a non-slashed url, then relative
+	  // links like ../.. should be able
+	  // to crawl up to the hostname, as well.  This is strange.
+	  // result.protocol has already been set by now.
+	  // Later on, put the first path part into the host field.
+	  if (psychotic) {
+	    result.hostname = '';
+	    result.port = null;
+	    if (result.host) {
+	      if (srcPath[0] === '') srcPath[0] = result.host;
+	      else srcPath.unshift(result.host);
+	    }
+	    result.host = '';
+	    if (relative.protocol) {
+	      relative.hostname = null;
+	      relative.port = null;
+	      if (relative.host) {
+	        if (relPath[0] === '') relPath[0] = relative.host;
+	        else relPath.unshift(relative.host);
+	      }
+	      relative.host = null;
+	    }
+	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+	  }
+
+	  if (isRelAbs) {
+	    // it's absolute.
+	    result.host = (relative.host || relative.host === '') ?
+	                  relative.host : result.host;
+	    result.hostname = (relative.hostname || relative.hostname === '') ?
+	                      relative.hostname : result.hostname;
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    srcPath = relPath;
+	    // fall through to the dot-handling below.
+	  } else if (relPath.length) {
+	    // it's relative
+	    // throw away the existing file, and take the new path instead.
+	    if (!srcPath) srcPath = [];
+	    srcPath.pop();
+	    srcPath = srcPath.concat(relPath);
+	    result.search = relative.search;
+	    result.query = relative.query;
+	  } else if (!util.isNullOrUndefined(relative.search)) {
+	    // just pull out the search.
+	    // like href='?foo'.
+	    // Put this after the other two cases because it simplifies the booleans
+	    if (psychotic) {
+	      result.hostname = result.host = srcPath.shift();
+	      //occationaly the auth can get stuck only in host
+	      //this especially happens in cases like
+	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                       result.host.split('@') : false;
+	      if (authInHost) {
+	        result.auth = authInHost.shift();
+	        result.host = result.hostname = authInHost.shift();
+	      }
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    //to support http.request
+	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	      result.path = (result.pathname ? result.pathname : '') +
+	                    (result.search ? result.search : '');
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (!srcPath.length) {
+	    // no path at all.  easy.
+	    // we've already handled the other stuff above.
+	    result.pathname = null;
+	    //to support http.request
+	    if (result.search) {
+	      result.path = '/' + result.search;
+	    } else {
+	      result.path = null;
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // if a url ENDs in . or .., then it must get a trailing slash.
+	  // however, if it ends in anything else non-slashy,
+	  // then it must NOT get a trailing slash.
+	  var last = srcPath.slice(-1)[0];
+	  var hasTrailingSlash = (
+	      (result.host || relative.host || srcPath.length > 1) &&
+	      (last === '.' || last === '..') || last === '');
+
+	  // strip single dots, resolve double dots to parent dir
+	  // if the path tries to go above the root, `up` ends up > 0
+	  var up = 0;
+	  for (var i = srcPath.length; i >= 0; i--) {
+	    last = srcPath[i];
+	    if (last === '.') {
+	      srcPath.splice(i, 1);
+	    } else if (last === '..') {
+	      srcPath.splice(i, 1);
+	      up++;
+	    } else if (up) {
+	      srcPath.splice(i, 1);
+	      up--;
+	    }
+	  }
+
+	  // if the path is allowed to go above the root, restore leading ..s
+	  if (!mustEndAbs && !removeAllDots) {
+	    for (; up--; up) {
+	      srcPath.unshift('..');
+	    }
+	  }
+
+	  if (mustEndAbs && srcPath[0] !== '' &&
+	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+	    srcPath.unshift('');
+	  }
+
+	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+	    srcPath.push('');
+	  }
+
+	  var isAbsolute = srcPath[0] === '' ||
+	      (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+	  // put the host back
+	  if (psychotic) {
+	    result.hostname = result.host = isAbsolute ? '' :
+	                                    srcPath.length ? srcPath.shift() : '';
+	    //occationaly the auth can get stuck only in host
+	    //this especially happens in cases like
+	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                     result.host.split('@') : false;
+	    if (authInHost) {
+	      result.auth = authInHost.shift();
+	      result.host = result.hostname = authInHost.shift();
+	    }
+	  }
+
+	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+	  if (mustEndAbs && !isAbsolute) {
+	    srcPath.unshift('');
+	  }
+
+	  if (!srcPath.length) {
+	    result.pathname = null;
+	    result.path = null;
+	  } else {
+	    result.pathname = srcPath.join('/');
+	  }
+
+	  //to support request.http
+	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	    result.path = (result.pathname ? result.pathname : '') +
+	                  (result.search ? result.search : '');
+	  }
+	  result.auth = relative.auth || result.auth;
+	  result.slashes = result.slashes || relative.slashes;
+	  result.href = result.format();
+	  return result;
+	};
+
+	Url.prototype.parseHost = function() {
+	  var host = this.host;
+	  var port = portPattern.exec(host);
+	  if (port) {
+	    port = port[0];
+	    if (port !== ':') {
+	      this.port = port.substr(1);
+	    }
+	    host = host.substr(0, host.length - port.length);
+	  }
+	  if (host) this.hostname = host;
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * http://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.3.2',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else { // in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else { // in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	module.exports = function(module) {

+		if(!module.webpackPolyfill) {

+			module.deprecate = function() {};

+			module.paths = [];

+			// module.parent = undefined by default

+			module.children = [];

+			module.webpackPolyfill = 1;

+		}

+		return module;

+	}

+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+	'use strict';
+
+	module.exports = {
+	  isString: function(arg) {
+	    return typeof(arg) === 'string';
+	  },
+	  isObject: function(arg) {
+	    return typeof(arg) === 'object' && arg !== null;
+	  },
+	  isNull: function(arg) {
+	    return arg === null;
+	  },
+	  isNullOrUndefined: function(arg) {
+	    return arg == null;
+	  }
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	exports.decode = exports.parse = __webpack_require__(7);
+	exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	// If obj.hasOwnProperty has been overridden, then calling
+	// obj.hasOwnProperty(prop) will break.
+	// See: https://github.com/joyent/node/issues/1707
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	module.exports = function(qs, sep, eq, options) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  var obj = {};
+
+	  if (typeof qs !== 'string' || qs.length === 0) {
+	    return obj;
+	  }
+
+	  var regexp = /\+/g;
+	  qs = qs.split(sep);
+
+	  var maxKeys = 1000;
+	  if (options && typeof options.maxKeys === 'number') {
+	    maxKeys = options.maxKeys;
+	  }
+
+	  var len = qs.length;
+	  // maxKeys <= 0 means that we should not limit keys count
+	  if (maxKeys > 0 && len > maxKeys) {
+	    len = maxKeys;
+	  }
+
+	  for (var i = 0; i < len; ++i) {
+	    var x = qs[i].replace(regexp, '%20'),
+	        idx = x.indexOf(eq),
+	        kstr, vstr, k, v;
+
+	    if (idx >= 0) {
+	      kstr = x.substr(0, idx);
+	      vstr = x.substr(idx + 1);
+	    } else {
+	      kstr = x;
+	      vstr = '';
+	    }
+
+	    k = decodeURIComponent(kstr);
+	    v = decodeURIComponent(vstr);
+
+	    if (!hasOwnProperty(obj, k)) {
+	      obj[k] = v;
+	    } else if (Array.isArray(obj[k])) {
+	      obj[k].push(v);
+	    } else {
+	      obj[k] = [obj[k], v];
+	    }
+	  }
+
+	  return obj;
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var stringifyPrimitive = function(v) {
+	  switch (typeof v) {
+	    case 'string':
+	      return v;
+
+	    case 'boolean':
+	      return v ? 'true' : 'false';
+
+	    case 'number':
+	      return isFinite(v) ? v : '';
+
+	    default:
+	      return '';
+	  }
+	};
+
+	module.exports = function(obj, sep, eq, name) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  if (obj === null) {
+	    obj = undefined;
+	  }
+
+	  if (typeof obj === 'object') {
+	    return Object.keys(obj).map(function(k) {
+	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+	      if (Array.isArray(obj[k])) {
+	        return obj[k].map(function(v) {
+	          return ks + encodeURIComponent(stringifyPrimitive(v));
+	        }).join(sep);
+	      } else {
+	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+	      }
+	    }).join(sep);
+
+	  }
+
+	  if (!name) return '';
+	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
+	         encodeURIComponent(stringifyPrimitive(obj));
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	var formatRegExp = /%[sdj%]/g;
+	exports.format = function(f) {
+	  if (!isString(f)) {
+	    var objects = [];
+	    for (var i = 0; i < arguments.length; i++) {
+	      objects.push(inspect(arguments[i]));
+	    }
+	    return objects.join(' ');
+	  }
+
+	  var i = 1;
+	  var args = arguments;
+	  var len = args.length;
+	  var str = String(f).replace(formatRegExp, function(x) {
+	    if (x === '%%') return '%';
+	    if (i >= len) return x;
+	    switch (x) {
+	      case '%s': return String(args[i++]);
+	      case '%d': return Number(args[i++]);
+	      case '%j':
+	        try {
+	          return JSON.stringify(args[i++]);
+	        } catch (_) {
+	          return '[Circular]';
+	        }
+	      default:
+	        return x;
+	    }
+	  });
+	  for (var x = args[i]; i < len; x = args[++i]) {
+	    if (isNull(x) || !isObject(x)) {
+	      str += ' ' + x;
+	    } else {
+	      str += ' ' + inspect(x);
+	    }
+	  }
+	  return str;
+	};
+
+
+	// Mark that a method should not be used.
+	// Returns a modified function which warns once by default.
+	// If --no-deprecation is set, then it is a no-op.
+	exports.deprecate = function(fn, msg) {
+	  // Allow for deprecating things in the process of starting up.
+	  if (isUndefined(global.process)) {
+	    return function() {
+	      return exports.deprecate(fn, msg).apply(this, arguments);
+	    };
+	  }
+
+	  if (process.noDeprecation === true) {
+	    return fn;
+	  }
+
+	  var warned = false;
+	  function deprecated() {
+	    if (!warned) {
+	      if (process.throwDeprecation) {
+	        throw new Error(msg);
+	      } else if (process.traceDeprecation) {
+	        console.trace(msg);
+	      } else {
+	        console.error(msg);
+	      }
+	      warned = true;
+	    }
+	    return fn.apply(this, arguments);
+	  }
+
+	  return deprecated;
+	};
+
+
+	var debugs = {};
+	var debugEnviron;
+	exports.debuglog = function(set) {
+	  if (isUndefined(debugEnviron))
+	    debugEnviron = process.env.NODE_DEBUG || '';
+	  set = set.toUpperCase();
+	  if (!debugs[set]) {
+	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+	      var pid = process.pid;
+	      debugs[set] = function() {
+	        var msg = exports.format.apply(exports, arguments);
+	        console.error('%s %d: %s', set, pid, msg);
+	      };
+	    } else {
+	      debugs[set] = function() {};
+	    }
+	  }
+	  return debugs[set];
+	};
+
+
+	/**
+	 * Echos the value of a value. Trys to print the value out
+	 * in the best way possible given the different types.
+	 *
+	 * @param {Object} obj The object to print out.
+	 * @param {Object} opts Optional options object that alters the output.
+	 */
+	/* legacy: obj, showHidden, depth, colors*/
+	function inspect(obj, opts) {
+	  // default options
+	  var ctx = {
+	    seen: [],
+	    stylize: stylizeNoColor
+	  };
+	  // legacy...
+	  if (arguments.length >= 3) ctx.depth = arguments[2];
+	  if (arguments.length >= 4) ctx.colors = arguments[3];
+	  if (isBoolean(opts)) {
+	    // legacy...
+	    ctx.showHidden = opts;
+	  } else if (opts) {
+	    // got an "options" object
+	    exports._extend(ctx, opts);
+	  }
+	  // set default options
+	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+	  if (isUndefined(ctx.depth)) ctx.depth = 2;
+	  if (isUndefined(ctx.colors)) ctx.colors = false;
+	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+	  if (ctx.colors) ctx.stylize = stylizeWithColor;
+	  return formatValue(ctx, obj, ctx.depth);
+	}
+	exports.inspect = inspect;
+
+
+	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+	inspect.colors = {
+	  'bold' : [1, 22],
+	  'italic' : [3, 23],
+	  'underline' : [4, 24],
+	  'inverse' : [7, 27],
+	  'white' : [37, 39],
+	  'grey' : [90, 39],
+	  'black' : [30, 39],
+	  'blue' : [34, 39],
+	  'cyan' : [36, 39],
+	  'green' : [32, 39],
+	  'magenta' : [35, 39],
+	  'red' : [31, 39],
+	  'yellow' : [33, 39]
+	};
+
+	// Don't use 'blue' not visible on cmd.exe
+	inspect.styles = {
+	  'special': 'cyan',
+	  'number': 'yellow',
+	  'boolean': 'yellow',
+	  'undefined': 'grey',
+	  'null': 'bold',
+	  'string': 'green',
+	  'date': 'magenta',
+	  // "name": intentionally not styling
+	  'regexp': 'red'
+	};
+
+
+	function stylizeWithColor(str, styleType) {
+	  var style = inspect.styles[styleType];
+
+	  if (style) {
+	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+	           '\u001b[' + inspect.colors[style][1] + 'm';
+	  } else {
+	    return str;
+	  }
+	}
+
+
+	function stylizeNoColor(str, styleType) {
+	  return str;
+	}
+
+
+	function arrayToHash(array) {
+	  var hash = {};
+
+	  array.forEach(function(val, idx) {
+	    hash[val] = true;
+	  });
+
+	  return hash;
+	}
+
+
+	function formatValue(ctx, value, recurseTimes) {
+	  // Provide a hook for user-specified inspect functions.
+	  // Check that value is an object with an inspect function on it
+	  if (ctx.customInspect &&
+	      value &&
+	      isFunction(value.inspect) &&
+	      // Filter out the util module, it's inspect function is special
+	      value.inspect !== exports.inspect &&
+	      // Also filter out any prototype objects using the circular check.
+	      !(value.constructor && value.constructor.prototype === value)) {
+	    var ret = value.inspect(recurseTimes, ctx);
+	    if (!isString(ret)) {
+	      ret = formatValue(ctx, ret, recurseTimes);
+	    }
+	    return ret;
+	  }
+
+	  // Primitive types cannot have properties
+	  var primitive = formatPrimitive(ctx, value);
+	  if (primitive) {
+	    return primitive;
+	  }
+
+	  // Look up the keys of the object.
+	  var keys = Object.keys(value);
+	  var visibleKeys = arrayToHash(keys);
+
+	  if (ctx.showHidden) {
+	    keys = Object.getOwnPropertyNames(value);
+	  }
+
+	  // IE doesn't make error fields non-enumerable
+	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+	  if (isError(value)
+	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+	    return formatError(value);
+	  }
+
+	  // Some type of object without properties can be shortcutted.
+	  if (keys.length === 0) {
+	    if (isFunction(value)) {
+	      var name = value.name ? ': ' + value.name : '';
+	      return ctx.stylize('[Function' + name + ']', 'special');
+	    }
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    }
+	    if (isDate(value)) {
+	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
+	    }
+	    if (isError(value)) {
+	      return formatError(value);
+	    }
+	  }
+
+	  var base = '', array = false, braces = ['{', '}'];
+
+	  // Make Array say that they are Array
+	  if (isArray(value)) {
+	    array = true;
+	    braces = ['[', ']'];
+	  }
+
+	  // Make functions say that they are functions
+	  if (isFunction(value)) {
+	    var n = value.name ? ': ' + value.name : '';
+	    base = ' [Function' + n + ']';
+	  }
+
+	  // Make RegExps say that they are RegExps
+	  if (isRegExp(value)) {
+	    base = ' ' + RegExp.prototype.toString.call(value);
+	  }
+
+	  // Make dates with properties first say the date
+	  if (isDate(value)) {
+	    base = ' ' + Date.prototype.toUTCString.call(value);
+	  }
+
+	  // Make error with message first say the error
+	  if (isError(value)) {
+	    base = ' ' + formatError(value);
+	  }
+
+	  if (keys.length === 0 && (!array || value.length == 0)) {
+	    return braces[0] + base + braces[1];
+	  }
+
+	  if (recurseTimes < 0) {
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    } else {
+	      return ctx.stylize('[Object]', 'special');
+	    }
+	  }
+
+	  ctx.seen.push(value);
+
+	  var output;
+	  if (array) {
+	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+	  } else {
+	    output = keys.map(function(key) {
+	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+	    });
+	  }
+
+	  ctx.seen.pop();
+
+	  return reduceToSingleString(output, base, braces);
+	}
+
+
+	function formatPrimitive(ctx, value) {
+	  if (isUndefined(value))
+	    return ctx.stylize('undefined', 'undefined');
+	  if (isString(value)) {
+	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+	                                             .replace(/'/g, "\\'")
+	                                             .replace(/\\"/g, '"') + '\'';
+	    return ctx.stylize(simple, 'string');
+	  }
+	  if (isNumber(value))
+	    return ctx.stylize('' + value, 'number');
+	  if (isBoolean(value))
+	    return ctx.stylize('' + value, 'boolean');
+	  // For some reason typeof null is "object", so special case here.
+	  if (isNull(value))
+	    return ctx.stylize('null', 'null');
+	}
+
+
+	function formatError(value) {
+	  return '[' + Error.prototype.toString.call(value) + ']';
+	}
+
+
+	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+	  var output = [];
+	  for (var i = 0, l = value.length; i < l; ++i) {
+	    if (hasOwnProperty(value, String(i))) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          String(i), true));
+	    } else {
+	      output.push('');
+	    }
+	  }
+	  keys.forEach(function(key) {
+	    if (!key.match(/^\d+$/)) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          key, true));
+	    }
+	  });
+	  return output;
+	}
+
+
+	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+	  var name, str, desc;
+	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+	  if (desc.get) {
+	    if (desc.set) {
+	      str = ctx.stylize('[Getter/Setter]', 'special');
+	    } else {
+	      str = ctx.stylize('[Getter]', 'special');
+	    }
+	  } else {
+	    if (desc.set) {
+	      str = ctx.stylize('[Setter]', 'special');
+	    }
+	  }
+	  if (!hasOwnProperty(visibleKeys, key)) {
+	    name = '[' + key + ']';
+	  }
+	  if (!str) {
+	    if (ctx.seen.indexOf(desc.value) < 0) {
+	      if (isNull(recurseTimes)) {
+	        str = formatValue(ctx, desc.value, null);
+	      } else {
+	        str = formatValue(ctx, desc.value, recurseTimes - 1);
+	      }
+	      if (str.indexOf('\n') > -1) {
+	        if (array) {
+	          str = str.split('\n').map(function(line) {
+	            return '  ' + line;
+	          }).join('\n').substr(2);
+	        } else {
+	          str = '\n' + str.split('\n').map(function(line) {
+	            return '   ' + line;
+	          }).join('\n');
+	        }
+	      }
+	    } else {
+	      str = ctx.stylize('[Circular]', 'special');
+	    }
+	  }
+	  if (isUndefined(name)) {
+	    if (array && key.match(/^\d+$/)) {
+	      return str;
+	    }
+	    name = JSON.stringify('' + key);
+	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+	      name = name.substr(1, name.length - 2);
+	      name = ctx.stylize(name, 'name');
+	    } else {
+	      name = name.replace(/'/g, "\\'")
+	                 .replace(/\\"/g, '"')
+	                 .replace(/(^"|"$)/g, "'");
+	      name = ctx.stylize(name, 'string');
+	    }
+	  }
+
+	  return name + ': ' + str;
+	}
+
+
+	function reduceToSingleString(output, base, braces) {
+	  var numLinesEst = 0;
+	  var length = output.reduce(function(prev, cur) {
+	    numLinesEst++;
+	    if (cur.indexOf('\n') >= 0) numLinesEst++;
+	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+	  }, 0);
+
+	  if (length > 60) {
+	    return braces[0] +
+	           (base === '' ? '' : base + '\n ') +
+	           ' ' +
+	           output.join(',\n  ') +
+	           ' ' +
+	           braces[1];
+	  }
+
+	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+	}
+
+
+	// NOTE: These type checking functions intentionally don't use `instanceof`
+	// because it is fragile and can be easily faked with `Object.create()`.
+	function isArray(ar) {
+	  return Array.isArray(ar);
+	}
+	exports.isArray = isArray;
+
+	function isBoolean(arg) {
+	  return typeof arg === 'boolean';
+	}
+	exports.isBoolean = isBoolean;
+
+	function isNull(arg) {
+	  return arg === null;
+	}
+	exports.isNull = isNull;
+
+	function isNullOrUndefined(arg) {
+	  return arg == null;
+	}
+	exports.isNullOrUndefined = isNullOrUndefined;
+
+	function isNumber(arg) {
+	  return typeof arg === 'number';
+	}
+	exports.isNumber = isNumber;
+
+	function isString(arg) {
+	  return typeof arg === 'string';
+	}
+	exports.isString = isString;
+
+	function isSymbol(arg) {
+	  return typeof arg === 'symbol';
+	}
+	exports.isSymbol = isSymbol;
+
+	function isUndefined(arg) {
+	  return arg === void 0;
+	}
+	exports.isUndefined = isUndefined;
+
+	function isRegExp(re) {
+	  return isObject(re) && objectToString(re) === '[object RegExp]';
+	}
+	exports.isRegExp = isRegExp;
+
+	function isObject(arg) {
+	  return typeof arg === 'object' && arg !== null;
+	}
+	exports.isObject = isObject;
+
+	function isDate(d) {
+	  return isObject(d) && objectToString(d) === '[object Date]';
+	}
+	exports.isDate = isDate;
+
+	function isError(e) {
+	  return isObject(e) &&
+	      (objectToString(e) === '[object Error]' || e instanceof Error);
+	}
+	exports.isError = isError;
+
+	function isFunction(arg) {
+	  return typeof arg === 'function';
+	}
+	exports.isFunction = isFunction;
+
+	function isPrimitive(arg) {
+	  return arg === null ||
+	         typeof arg === 'boolean' ||
+	         typeof arg === 'number' ||
+	         typeof arg === 'string' ||
+	         typeof arg === 'symbol' ||  // ES6 symbol
+	         typeof arg === 'undefined';
+	}
+	exports.isPrimitive = isPrimitive;
+
+	exports.isBuffer = __webpack_require__(11);
+
+	function objectToString(o) {
+	  return Object.prototype.toString.call(o);
+	}
+
+
+	function pad(n) {
+	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+	}
+
+
+	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+	              'Oct', 'Nov', 'Dec'];
+
+	// 26 Feb 16:19:34
+	function timestamp() {
+	  var d = new Date();
+	  var time = [pad(d.getHours()),
+	              pad(d.getMinutes()),
+	              pad(d.getSeconds())].join(':');
+	  return [d.getDate(), months[d.getMonth()], time].join(' ');
+	}
+
+
+	// log is just a thin wrapper to console.log that prepends a timestamp
+	exports.log = function() {
+	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+	};
+
+
+	/**
+	 * Inherit the prototype methods from one constructor into another.
+	 *
+	 * The Function.prototype.inherits from lang.js rewritten as a standalone
+	 * function (not on Function.prototype). NOTE: If this file is to be loaded
+	 * during bootstrapping this function needs to be rewritten using some native
+	 * functions as prototype setup using normal JavaScript does not work as
+	 * expected during bootstrapping (see mirror.js in r114903).
+	 *
+	 * @param {function} ctor Constructor function which needs to inherit the
+	 *     prototype.
+	 * @param {function} superCtor Constructor function to inherit prototype from.
+	 */
+	exports.inherits = __webpack_require__(12);
+
+	exports._extend = function(origin, add) {
+	  // Don't do anything if add isn't an object
+	  if (!add || !isObject(add)) return origin;
+
+	  var keys = Object.keys(add);
+	  var i = keys.length;
+	  while (i--) {
+	    origin[keys[i]] = add[keys[i]];
+	  }
+	  return origin;
+	};
+
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	// shim for using process in browser
+	var process = module.exports = {};
+
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+
+
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+
+
+
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+
+	    var len = queue.length;
+	    while(len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+
+	function noop() {}
+
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+
+	process.listeners = function (name) { return [] }
+
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+
+	process.cwd = function () { return '/' };
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	module.exports = function isBuffer(arg) {
+	  return arg && typeof arg === 'object'
+	    && typeof arg.copy === 'function'
+	    && typeof arg.fill === 'function'
+	    && typeof arg.readUInt8 === 'function';
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	if (typeof Object.create === 'function') {
+	  // implementation from standard node.js 'util' module
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    ctor.prototype = Object.create(superCtor.prototype, {
+	      constructor: {
+	        value: ctor,
+	        enumerable: false,
+	        writable: true,
+	        configurable: true
+	      }
+	    });
+	  };
+	} else {
+	  // old school shim for old browsers
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    var TempCtor = function () {}
+	    TempCtor.prototype = superCtor.prototype
+	    ctor.prototype = new TempCtor()
+	    ctor.prototype.constructor = ctor
+	  }
+	}
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2018, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var psl = __webpack_require__(14);
+
+	function getPublicSuffix(domain) {
+	  return psl.get(domain);
+	}
+
+	exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+	'use strict';
+
+
+	var Punycode = __webpack_require__(15);
+
+
+	var internals = {};
+
+
+	//
+	// Read rules from file.
+	//
+	internals.rules = __webpack_require__(16).map(function (rule) {
+
+	  return {
+	    rule: rule,
+	    suffix: rule.replace(/^(\*\.|\!)/, ''),
+	    punySuffix: -1,
+	    wildcard: rule.charAt(0) === '*',
+	    exception: rule.charAt(0) === '!'
+	  };
+	});
+
+
+	//
+	// Check is given string ends with `suffix`.
+	//
+	internals.endsWith = function (str, suffix) {
+
+	  return str.indexOf(suffix, str.length - suffix.length) !== -1;
+	};
+
+
+	//
+	// Find rule for a given domain.
+	//
+	internals.findRule = function (domain) {
+
+	  var punyDomain = Punycode.toASCII(domain);
+	  return internals.rules.reduce(function (memo, rule) {
+
+	    if (rule.punySuffix === -1){
+	      rule.punySuffix = Punycode.toASCII(rule.suffix);
+	    }
+	    if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+	      return memo;
+	    }
+	    // This has been commented out as it never seems to run. This is because
+	    // sub tlds always appear after their parents and we never find a shorter
+	    // match.
+	    //if (memo) {
+	    //  var memoSuffix = Punycode.toASCII(memo.suffix);
+	    //  if (memoSuffix.length >= punySuffix.length) {
+	    //    return memo;
+	    //  }
+	    //}
+	    return rule;
+	  }, null);
+	};
+
+
+	//
+	// Error codes and messages.
+	//
+	exports.errorCodes = {
+	  DOMAIN_TOO_SHORT: 'Domain name too short.',
+	  DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+	  LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+	  LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+	  LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+	  LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+	  LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+	};
+
+
+	//
+	// Validate domain name and throw if not valid.
+	//
+	// From wikipedia:
+	//
+	// Hostnames are composed of series of labels concatenated with dots, as are all
+	// domain names. Each label must be between 1 and 63 characters long, and the
+	// entire hostname (including the delimiting dots) has a maximum of 255 chars.
+	//
+	// Allowed chars:
+	//
+	// * `a-z`
+	// * `0-9`
+	// * `-` but not as a starting or ending character
+	// * `.` as a separator for the textual portions of a domain name
+	//
+	// * http://en.wikipedia.org/wiki/Domain_name
+	// * http://en.wikipedia.org/wiki/Hostname
+	//
+	internals.validate = function (input) {
+
+	  // Before we can validate we need to take care of IDNs with unicode chars.
+	  var ascii = Punycode.toASCII(input);
+
+	  if (ascii.length < 1) {
+	    return 'DOMAIN_TOO_SHORT';
+	  }
+	  if (ascii.length > 255) {
+	    return 'DOMAIN_TOO_LONG';
+	  }
+
+	  // Check each part's length and allowed chars.
+	  var labels = ascii.split('.');
+	  var label;
+
+	  for (var i = 0; i < labels.length; ++i) {
+	    label = labels[i];
+	    if (!label.length) {
+	      return 'LABEL_TOO_SHORT';
+	    }
+	    if (label.length > 63) {
+	      return 'LABEL_TOO_LONG';
+	    }
+	    if (label.charAt(0) === '-') {
+	      return 'LABEL_STARTS_WITH_DASH';
+	    }
+	    if (label.charAt(label.length - 1) === '-') {
+	      return 'LABEL_ENDS_WITH_DASH';
+	    }
+	    if (!/^[a-z0-9\-]+$/.test(label)) {
+	      return 'LABEL_INVALID_CHARS';
+	    }
+	  }
+	};
+
+
+	//
+	// Public API
+	//
+
+
+	//
+	// Parse domain.
+	//
+	exports.parse = function (input) {
+
+	  if (typeof input !== 'string') {
+	    throw new TypeError('Domain name must be a string.');
+	  }
+
+	  // Force domain to lowercase.
+	  var domain = input.slice(0).toLowerCase();
+
+	  // Handle FQDN.
+	  // TODO: Simply remove trailing dot?
+	  if (domain.charAt(domain.length - 1) === '.') {
+	    domain = domain.slice(0, domain.length - 1);
+	  }
+
+	  // Validate and sanitise input.
+	  var error = internals.validate(domain);
+	  if (error) {
+	    return {
+	      input: input,
+	      error: {
+	        message: exports.errorCodes[error],
+	        code: error
+	      }
+	    };
+	  }
+
+	  var parsed = {
+	    input: input,
+	    tld: null,
+	    sld: null,
+	    domain: null,
+	    subdomain: null,
+	    listed: false
+	  };
+
+	  var domainParts = domain.split('.');
+
+	  // Non-Internet TLD
+	  if (domainParts[domainParts.length - 1] === 'local') {
+	    return parsed;
+	  }
+
+	  var handlePunycode = function () {
+
+	    if (!/xn--/.test(domain)) {
+	      return parsed;
+	    }
+	    if (parsed.domain) {
+	      parsed.domain = Punycode.toASCII(parsed.domain);
+	    }
+	    if (parsed.subdomain) {
+	      parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+	    }
+	    return parsed;
+	  };
+
+	  var rule = internals.findRule(domain);
+
+	  // Unlisted tld.
+	  if (!rule) {
+	    if (domainParts.length < 2) {
+	      return parsed;
+	    }
+	    parsed.tld = domainParts.pop();
+	    parsed.sld = domainParts.pop();
+	    parsed.domain = [parsed.sld, parsed.tld].join('.');
+	    if (domainParts.length) {
+	      parsed.subdomain = domainParts.pop();
+	    }
+	    return handlePunycode();
+	  }
+
+	  // At this point we know the public suffix is listed.
+	  parsed.listed = true;
+
+	  var tldParts = rule.suffix.split('.');
+	  var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+	  if (rule.exception) {
+	    privateParts.push(tldParts.shift());
+	  }
+
+	  parsed.tld = tldParts.join('.');
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  if (rule.wildcard) {
+	    tldParts.unshift(privateParts.pop());
+	    parsed.tld = tldParts.join('.');
+	  }
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  parsed.sld = privateParts.pop();
+	  parsed.domain = [parsed.sld,  parsed.tld].join('.');
+
+	  if (privateParts.length) {
+	    parsed.subdomain = privateParts.join('.');
+	  }
+
+	  return handlePunycode();
+	};
+
+
+	//
+	// Get domain.
+	//
+	exports.get = function (domain) {
+
+	  if (!domain) {
+	    return null;
+	  }
+	  return exports.parse(domain).domain || null;
+	};
+
+
+	//
+	// Check whether domain belongs to a known public suffix.
+	//
+	exports.isValid = function (domain) {
+
+	  var parsed = exports.parse(domain);
+	  return Boolean(parsed.domain && parsed.listed);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw new RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * https://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.4.1',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) {
+				// in Node.js, io.js, or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else {
+				// in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else {
+			// in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	/*jshint unused:false */
+
+	function Store() {
+	}
+	exports.Store = Store;
+
+	// Stores may be synchronous, but are still required to use a
+	// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
+	// API that converts from synchronous-callbacks to imperative style.
+	Store.prototype.synchronous = false;
+
+	Store.prototype.findCookie = function(domain, path, key, cb) {
+	  throw new Error('findCookie is not implemented');
+	};
+
+	Store.prototype.findCookies = function(domain, path, cb) {
+	  throw new Error('findCookies is not implemented');
+	};
+
+	Store.prototype.putCookie = function(cookie, cb) {
+	  throw new Error('putCookie is not implemented');
+	};
+
+	Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // recommended default implementation:
+	  // return this.putCookie(newCookie, cb);
+	  throw new Error('updateCookie is not implemented');
+	};
+
+	Store.prototype.removeCookie = function(domain, path, key, cb) {
+	  throw new Error('removeCookie is not implemented');
+	};
+
+	Store.prototype.removeCookies = function(domain, path, cb) {
+	  throw new Error('removeCookies is not implemented');
+	};
+
+	Store.prototype.getAllCookies = function(cb) {
+	  throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var Store = __webpack_require__(17).Store;
+	var permuteDomain = __webpack_require__(19).permuteDomain;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var util = __webpack_require__(9);
+
+	function MemoryCookieStore() {
+	  Store.call(this);
+	  this.idx = {};
+	}
+	util.inherits(MemoryCookieStore, Store);
+	exports.MemoryCookieStore = MemoryCookieStore;
+	MemoryCookieStore.prototype.idx = null;
+
+	// Since it's just a struct in RAM, this Store is synchronous
+	MemoryCookieStore.prototype.synchronous = true;
+
+	// force a default depth:
+	MemoryCookieStore.prototype.inspect = function() {
+	  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+	}
+
+	MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+	  if (!this.idx[domain]) {
+	    return cb(null,undefined);
+	  }
+	  if (!this.idx[domain][path]) {
+	    return cb(null,undefined);
+	  }
+	  return cb(null,this.idx[domain][path][key]||null);
+	};
+
+	MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+	  var results = [];
+	  if (!domain) {
+	    return cb(null,[]);
+	  }
+
+	  var pathMatcher;
+	  if (!path) {
+	    // null means "all paths"
+	    pathMatcher = function matchAll(domainIndex) {
+	      for (var curPath in domainIndex) {
+	        var pathIndex = domainIndex[curPath];
+	        for (var key in pathIndex) {
+	          results.push(pathIndex[key]);
+	        }
+	      }
+	    };
+
+	  } else {
+	    pathMatcher = function matchRFC(domainIndex) {
+	       //NOTE: we should use path-match algorithm from S5.1.4 here
+	       //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+	       Object.keys(domainIndex).forEach(function (cookiePath) {
+	         if (pathMatch(path, cookiePath)) {
+	           var pathIndex = domainIndex[cookiePath];
+
+	           for (var key in pathIndex) {
+	             results.push(pathIndex[key]);
+	           }
+	         }
+	       });
+	     };
+	  }
+
+	  var domains = permuteDomain(domain) || [domain];
+	  var idx = this.idx;
+	  domains.forEach(function(curDomain) {
+	    var domainIndex = idx[curDomain];
+	    if (!domainIndex) {
+	      return;
+	    }
+	    pathMatcher(domainIndex);
+	  });
+
+	  cb(null,results);
+	};
+
+	MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+	  if (!this.idx[cookie.domain]) {
+	    this.idx[cookie.domain] = {};
+	  }
+	  if (!this.idx[cookie.domain][cookie.path]) {
+	    this.idx[cookie.domain][cookie.path] = {};
+	  }
+	  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // updateCookie() may avoid updating cookies that are identical.  For example,
+	  // lastAccessed may not be important to some stores and an equality
+	  // comparison could exclude that field.
+	  this.putCookie(newCookie,cb);
+	};
+
+	MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+	  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+	    delete this.idx[domain][path][key];
+	  }
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+	  if (this.idx[domain]) {
+	    if (path) {
+	      delete this.idx[domain][path];
+	    } else {
+	      delete this.idx[domain];
+	    }
+	  }
+	  return cb(null);
+	};
+
+	MemoryCookieStore.prototype.getAllCookies = function(cb) {
+	  var cookies = [];
+	  var idx = this.idx;
+
+	  var domains = Object.keys(idx);
+	  domains.forEach(function(domain) {
+	    var paths = Object.keys(idx[domain]);
+	    paths.forEach(function(path) {
+	      var keys = Object.keys(idx[domain][path]);
+	      keys.forEach(function(key) {
+	        if (key !== null) {
+	          cookies.push(idx[domain][path][key]);
+	        }
+	      });
+	    });
+	  });
+
+	  // Sort by creationIndex so deserializing retains the creation order.
+	  // When implementing your own store, this SHOULD retain the order too
+	  cookies.sort(function(a,b) {
+	    return (a.creationIndex||0) - (b.creationIndex||0);
+	  });
+
+	  cb(null, cookies);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	var pubsuffix = __webpack_require__(13);
+
+	// Gives the permutation of all possible domainMatch()es of a given domain. The
+	// array is in shortest-to-longest order.  Handy for indexing.
+	function permuteDomain (domain) {
+	  var pubSuf = pubsuffix.getPublicSuffix(domain);
+	  if (!pubSuf) {
+	    return null;
+	  }
+	  if (pubSuf == domain) {
+	    return [domain];
+	  }
+
+	  var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+	  var parts = prefix.split('.').reverse();
+	  var cur = pubSuf;
+	  var permutations = [cur];
+	  while (parts.length) {
+	    cur = parts.shift() + '.' + cur;
+	    permutations.push(cur);
+	  }
+	  return permutations;
+	}
+
+	exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	/*
+	 * "A request-path path-matches a given cookie-path if at least one of the
+	 * following conditions holds:"
+	 */
+	function pathMatch (reqPath, cookiePath) {
+	  // "o  The cookie-path and the request-path are identical."
+	  if (cookiePath === reqPath) {
+	    return true;
+	  }
+
+	  var idx = reqPath.indexOf(cookiePath);
+	  if (idx === 0) {
+	    // "o  The cookie-path is a prefix of the request-path, and the last
+	    // character of the cookie-path is %x2F ("/")."
+	    if (cookiePath.substr(-1) === "/") {
+	      return true;
+	    }
+
+	    // " o  The cookie-path is a prefix of the request-path, and the first
+	    // character of the request-path that is not included in the cookie- path
+	    // is a %x2F ("/") character."
+	    if (reqPath.substr(cookiePath.length, 1) === "/") {
+	      return true;
+	    }
+	  }
+
+	  return false;
+	}
+
+	exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..8d9228a
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,106 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) {
+module.exports = function init(jsUtil) {
+  return {
+    parseUrl: parseUrl,
+    appendQueryParamsString: appendQueryParamsString,
+    serializeQueryParams: serializeQueryParams
+  }
+
+  function parseUrl(url) {
+    var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+    return match && {
+        protocol: match[1],
+        host: match[2],
+        hostname: match[3],
+        port: match[4] || '',
+        pathname: match[5],
+        search: match[6],
+        hash: match[7]
+    }
+  }
+
+  function appendQueryParamsString(url, params) {
+    if (!url.length || !params.length) {
+      return url;
+    }
+
+    var parsed = parseUrl(url);
+
+    return parsed.protocol
+      + '//'
+      + parsed.host
+      + parsed.pathname
+      + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+      + parsed.hash;
+  }
+
+  function serializeQueryParams(params, encode) {
+    return serializeObject('', params, encode);
+  }
+
+  function serializeObject(parentKey, object, encode) {
+    var parts = [];
+
+    for (var key in object) {
+      if (!object.hasOwnProperty(key)) {
+        continue;
+      }
+
+      var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+      if (jsUtil.getTypeOf(object[key]) === 'Array') {
+        parts.push(serializeArray(identifier, object[key], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+        parts.push(serializeObject(identifier, object[key], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeArray(parentKey, array, encode) {
+    var parts = [];
+
+    for (var i = 0; i < array.length; ++i) {
+      if (jsUtil.getTypeOf(array[i]) === 'Array') {
+        parts.push(serializeArray(parentKey + '[]', array[i], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+        parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeIdentifier(parentKey, key, encode) {
+    if (!parentKey.length) {
+      return encode ? encodeURIComponent(key) : key;
+    }
+
+    if (encode) {
+      return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+    } else {
+      return parentKey + '[' + key + ']';
+    }
+  }
+
+  function serializeValue(value, encode) {
+    if (encode) {
+      return encodeURIComponent(value);
+    } else {
+      return value;
+    }
+  }
+};
+
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3f614ec
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,188 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ *    var image = document.getElementById('myImage');
+ *    image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the  returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery.  The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified.  To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+        mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+    // XXX: commented out
+    // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ *     console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ *     alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+    exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..4f4b046
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,104 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+     * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+     * disable any image modifications (resize, quality change, cropping, etc.) due
+     * to implementation specific.
+     *
+     * @enum {number}
+     */
+    DestinationType: {
+        /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+        DATA_URL: 0,
+        /** Return file uri (content://media/external/images/media/2 for Android) */
+        FILE_URI: 1,
+        /** Return native uri (eg. asset-library://... for iOS) */
+        NATIVE_URI: 2
+    },
+    /**
+     * @enum {number}
+     */
+    EncodingType: {
+        /** Return JPEG encoded image */
+        JPEG: 0,
+        /** Return PNG encoded image */
+        PNG: 1
+    },
+    /**
+     * @enum {number}
+     */
+    MediaType: {
+        /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+        PICTURE: 0,
+        /** Allow selection of video only, ONLY RETURNS URL */
+        VIDEO: 1,
+        /** Allow selection from all media types */
+        ALLMEDIA: 2
+    },
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+     * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+     * change, cropping, etc.) due to implementation specific.
+     *
+     * @enum {number}
+     */
+    PictureSourceType: {
+        /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+        PHOTOLIBRARY: 0,
+        /** Take picture from camera */
+        CAMERA: 1,
+        /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+        SAVEDPHOTOALBUM: 2
+    },
+    /**
+     * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+     * @enum {number}
+     */
+    PopoverArrowDirection: {
+        ARROW_UP: 1,
+        ARROW_DOWN: 2,
+        ARROW_LEFT: 4,
+        ARROW_RIGHT: 8,
+        ARROW_ANY: 15
+    },
+    /**
+     * @enum {number}
+     */
+    Direction: {
+        /** Use the back-facing camera */
+        BACK: 0,
+        /** Use the front-facing camera */
+        FRONT: 1
+    }
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js
new file mode 100644
index 0000000..c970f55
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-camera.CameraPopoverHandle", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @ignore in favour of iOS' one
+ * A handle to an image picker popover.
+ */
+var CameraPopoverHandle = function () {
+    this.setPosition = function (popoverOptions) {
+        console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..81d7d20
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,55 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen.  Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..ae48e35
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+    this.available = false;
+    this.platform = null;
+    this.version = null;
+    this.uuid = null;
+    this.cordova = null;
+    this.model = null;
+    this.manufacturer = null;
+    this.isVirtual = null;
+    this.serial = null;
+
+    var me = this;
+
+    channel.onCordovaReady.subscribe(function () {
+        me.getInfo(function (info) {
+            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+            // TODO: CB-5105 native implementations should not return info.cordova
+            var buildLabel = cordova.version;
+            me.available = true;
+            me.platform = info.platform;
+            me.version = info.version;
+            me.uuid = info.uuid;
+            me.cordova = buildLabel;
+            me.model = info.model;
+            me.isVirtual = info.isVirtual;
+            me.manufacturer = info.manufacturer || 'unknown';
+            me.serial = info.serial || 'unknown';
+            channel.onCordovaInfoReady.fire();
+        }, function (e) {
+            me.available = false;
+            utils.alert('[ERROR] Error initializing Cordova: ' + e);
+        });
+    });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+    exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..bb676eb
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,120 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+    // add trailing slash if it is missing
+    if ((fullPath) && !/\/$/.test(fullPath)) {
+        fullPath += '/';
+    }
+    // add trailing slash if it is missing
+    if (nativeURL && !/\/$/.test(nativeURL)) {
+        nativeURL += '/';
+    }
+    DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+    return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var FileEntry = require('./FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..417c85f
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,75 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+    this.localURL = localURL || null;
+    this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+    // If we've already read and passed on this directory's entries, return an empty list.
+    if (this.hasReadEntries) {
+        successCallback([]);
+        return;
+    }
+    var reader = this;
+    var win = typeof successCallback !== 'function' ? null : function (result) {
+        var retVal = [];
+        for (var i = 0; i < result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('./DirectoryEntry'))();
+            } else if (result[i].isFile) {
+                entry = new (require('./FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+            entry.nativeURL = result[i].nativeURL;
+            retVal.push(entry);
+        }
+        reader.hasReadEntries = true;
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Entry.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..b296d99
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,263 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ * @param fileSystem
+ *            {FileSystem} the filesystem on which this entry resides
+ *            (readonly)
+ * @param nativeURL
+ *            {DOMString} an alternate URL which can be used by native
+ *            webview controls, for example media players.
+ *            (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+    this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function (entryMetadata) {
+        var metadata = new Metadata({
+            size: entryMetadata.size,
+            modificationTime: entryMetadata.lastModifiedDate
+        });
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+    // entry name
+    var name = newName || this.name;
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+        // entry name
+    var name = newName || this.name;
+    // success callback
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+    if (this.filesystem && this.filesystem.__format__) {
+        return this.filesystem.__format__(this.fullPath, this.nativeURL);
+    }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+    if (this.nativeURL) {
+        return this.nativeURL;
+    }
+    // fullPath attribute may contain the full URL in the case that
+    // toInternalURL fails.
+    return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var DirectoryEntry = require('./DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/File.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..c771786
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,81 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+    this.name = name || '';
+    this.localURL = localURL || null;
+    this.type = type || null;
+    this.lastModified = lastModifiedDate || null;
+    // For backwards compatibility, store the timestamp in lastModifiedDate as well
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..6651b55
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,95 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+    // remove trailing slash if it is present
+    if (fullPath && /\/$/.test(fullPath)) {
+        fullPath = fullPath.substring(0, fullPath.length - 1);
+    }
+    if (nativeURL && /\/$/.test(nativeURL)) {
+        nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+    }
+
+    FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+    this.file(function (filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.localURL === null || writer.localURL === '') {
+            if (errorCallback) {
+                errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+            }
+        } else {
+            if (successCallback) {
+                successCallback(writer);
+            }
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+    var localURL = this.toInternalURL();
+    var win = successCallback && function (f) {
+        var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileError.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..f378c38
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,49 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+    this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..5c03091
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,301 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._progress = null;
+    this._localURL = '';
+    this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+    return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+    return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+    return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+        return this._realReader[eventName] || null;
+    }, function (value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+    // Already loading something
+    if (reader.readyState === FileReader.LOADING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._progress = 0;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file.localURL === 'string') {
+        reader._localURL = file.localURL;
+    } else {
+        reader._localURL = '';
+        return true;
+    }
+
+    if (reader.onloadstart) {
+        reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+    if (readType === 'readAsDataURL') {
+        // Windows proxy does not support reading file slices as Data URLs
+        // so read the whole file at once.
+        CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+            // Calculate new chunk size for data URLs to be multiply of 3
+            // Otherwise concatenated base64 chunks won't be valid base64 data
+            FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+    }
+
+    if (typeof r !== 'undefined') {
+        accumulate(r);
+        this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+        if (typeof this.onprogress === 'function') {
+            this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+        }
+    }
+
+    if (typeof r === 'undefined' || this._progress < totalSize) {
+        var execArgs = [
+            this._localURL,
+            offset + this._progress,
+            offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+        if (encoding) {
+            execArgs.splice(1, 0, encoding);
+        }
+        exec(
+            readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+            readFailureCallback.bind(this),
+            'File', readType, execArgs);
+    } else {
+        this._readyState = FileReader.DONE;
+
+        if (typeof this.onload === 'function') {
+            this.onload(new ProgressEvent('load', {target: this}));
+        }
+
+        if (typeof this.onloadend === 'function') {
+            this.onloadend(new ProgressEvent('loadend', {target: this}));
+        }
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+    this._result = null;
+    this._error = new FileError(e);
+
+    if (typeof this.onerror === 'function') {
+        this.onerror(new ProgressEvent('error', {target: this}));
+    }
+
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+    if (origFileReader && !this._localURL) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target: this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding || 'UTF-8';
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+        var commaIndex = r.indexOf(',');
+        if (this._progress === 0) {
+            this._result = r;
+        } else {
+            this._result += r.substring(commaIndex + 1);
+        }
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+        var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+        resultArray.set(new Uint8Array(r), this._progress);
+        this._result = resultArray.buffer;
+    }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..ad9ea78
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,58 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+    this.name = name;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+    } else {
+        this.root = new DirectoryEntry(this.name, '/', this);
+    }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+    return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+    return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+    // Because # is a valid filename character, it must be encoded to prevent part of the
+    // path from being parsed as a URI fragment.
+    return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..6acd093
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,44 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String}   Name of file request parameter.
+ * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object}    Object with key: value params to send to the server.
+ * @param headers {Object}   Keys are header names, values are header values. Multiple
+ *                           headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+    this.fileKey = fileKey || null;
+    this.fileName = fileName || null;
+    this.mimeType = mimeType || null;
+    this.params = params || null;
+    this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..e3c3a74
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+    this.bytesSent = size;
+    this.responseCode = code;
+    this.response = content;
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..d48a089
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,327 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+    this.fileName = '';
+    this.length = 0;
+    if (file) {
+        this.localURL = file.localURL || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {'target': this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === 'function') {
+        this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+    var that = this;
+    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+    /* eslint-disable no-undef */
+    var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+    var isBinary;
+
+    // Check to see if the incoming data is a blob
+    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+        var fileReader = new FileReader();
+        /* eslint-enable no-undef */
+        fileReader.onload = function () {
+            // Call this method again, with the arraybuffer as argument
+            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+        };
+        fileReader.onerror = function () {
+            // DONE state
+            that.readyState = FileWriter.DONE;
+
+            // Save error
+            that.error = this.error;
+
+            // If onerror callback
+            if (typeof that.onerror === 'function') {
+                that.onerror(new ProgressEvent('error', {'target': that}));
+            }
+
+            // If onwriteend callback
+            if (typeof that.onwriteend === 'function') {
+                that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+            }
+        };
+
+        // WRITING state
+        this.readyState = FileWriter.WRITING;
+
+        if (supportsBinary) {
+            fileReader.readAsArrayBuffer(data);
+        } else {
+            fileReader.readAsText(data);
+        }
+        return;
+    }
+
+    // Mark data type for safer transport over the binary bridge
+    isBinary = supportsBinary && (data instanceof ArrayBuffer);
+    if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+        data = Array.apply(null, new Uint8Array(data));
+    }
+
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset && offset !== 0) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    // Offset is bigger than file size so set position
+    // to the end of the file.
+    } else if (offset > this.length) {
+        this.position = this.length;
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    } else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Flags.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..cdb12bb
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,39 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags (create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..4ce6848
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,26 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..22366e1
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+    if (typeof metadata === 'object') {
+        this.modificationTime = new Date(metadata.modificationTime);
+        this.size = metadata.size || 0;
+    } else if (typeof metadata === 'undefined') {
+        this.modificationTime = null;
+        this.size = 0;
+    } else {
+        /* Backwards compatiblity with platforms that only return a timestamp */
+        this.modificationTime = new Date(metadata);
+    }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..cbecdb1
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,70 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+    return function ProgressEvent (type, dict) {
+        this.type = type;
+        this.bubbles = false;
+        this.cancelBubble = false;
+        this.cancelable = false;
+        this.lengthComputable = false;
+        this.loaded = dict && dict.loaded ? dict.loaded : 0;
+        this.total = dict && dict.total ? dict.total : 0;
+        this.target = dict && dict.target ? dict.target : null;
+    };
+    // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/android/FileSystem.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/android/FileSystem.js
new file mode 100644
index 0000000..0124fa6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/android/FileSystem.js
@@ -0,0 +1,51 @@
+cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+FILESYSTEM_PROTOCOL = 'cdvfile'; // eslint-disable-line no-undef
+
+module.exports = {
+    __format__: function (fullPath, nativeUrl) {
+        var path;
+        var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
+        if (contentUrlMatch) {
+            // When available, use the path from a native content URL, which was already encoded by Android.
+            // This is necessary because JavaScript's encodeURI() does not encode as many characters as
+            // Android, which can result in permission exceptions when the encoding of a content URI
+            // doesn't match the string for which permission was originally granted.
+            path = nativeUrl.substring(contentUrlMatch[0].length - 1);
+        } else {
+            path = FileSystem.encodeURIPath(fullPath); // eslint-disable-line no-undef
+            if (!/^\//.test(path)) {
+                path = '/' + path;
+            }
+
+            var m = /\?.*/.exec(nativeUrl);
+            if (m) {
+                path += m[0];
+            }
+        }
+
+        return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path; // eslint-disable-line no-undef
+    }
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..c74fd9c
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+ */

+

+module.exports = function () {

+    // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and

+    // possibly a good flag to indicate that we're running in Chrome

+    return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;

+};

+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..4bfc0f6
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,65 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+    documentsDirectory: null,
+    // BlackBerry10: Files globally available to all apps
+    sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+    function after (paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems-roots.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
new file mode 100644
index 0000000..9351132
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
@@ -0,0 +1,47 @@
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+    function success (response) {
+        fsMap = {};
+        for (var i = 0; i < response.length; ++i) {
+            var fsRoot = response[i];
+            var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+            fsMap[fs.name] = fs;
+        }
+        callback(fsMap[name]);
+    }
+
+    if (fsMap) {
+        callback(fsMap[name]);
+    } else {
+        exec(success, null, 'File', 'requestAllFileSystems', []);
+    }
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..e61ceaf
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+    callback(null);
+};
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..7f65219
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,84 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // For browser platform: not all browsers use this file.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var FileError = require('./FileError');
+    var FileSystem = require('./FileSystem');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Request a file system in which to store application data.
+     * @param type  local file system type
+     * @param size  indicates how much storage space, in bytes, the application expects to need
+     * @param successCallback  invoked with a FileSystem object
+     * @param errorCallback  invoked if error occurs retrieving file system
+     */
+    var requestFileSystem = function (type, size, successCallback, errorCallback) {
+        argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+        var fail = function (code) {
+            if (errorCallback) {
+                errorCallback(new FileError(code));
+            }
+        };
+
+        if (type < 0) {
+            fail(FileError.SYNTAX_ERR);
+        } else {
+            // if successful, return a FileSystem object
+            var success = function (file_system) {
+                if (file_system) {
+                    if (successCallback) {
+                        fileSystems.getFs(file_system.name, function (fs) {
+                            // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                            if (!fs) {
+                                fs = new FileSystem(file_system.name, file_system.root);
+                            }
+                            successCallback(fs);
+                        });
+                    }
+                } else {
+                    // no FileSystem object returned
+                    fail(FileError.NOT_FOUND_ERR);
+                }
+            };
+            exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+        }
+    };
+
+    module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..73715bc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Look up file system Entry referred to by local URI.
+     * @param {DOMString} uri  URI referring to a local file or directory
+     * @param successCallback  invoked with Entry object corresponding to URI
+     * @param errorCallback    invoked if error occurs retrieving file system entry
+     */
+    module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+        argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+        // error callback
+        var fail = function (error) {
+            if (errorCallback) {
+                errorCallback(new FileError(error));
+            }
+        };
+        // sanity check for 'not:valid:filename' or '/not:valid:filename'
+        // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+        if (!uri || uri.split(':').length > 2) {
+            setTimeout(function () {
+                fail(FileError.ENCODING_ERR);
+            }, 0);
+            return;
+        }
+        // if successful, return either a file or directory entry
+        var success = function (entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+                    fileSystems.getFs(fsName, function (fs) {
+                        // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                        if (!fs) {
+                            fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+                        }
+                        var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+                        successCallback(result);
+                    });
+                }
+            } else {
+                // no Entry object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+        exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+    };
+
+    module.exports.resolveLocalFileSystemURI = function () {
+        console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+        module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+    };
+})();
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..3982139
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
+/*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "authenticate",
+    [params]
+  );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "isAvailable",
+    [{}]
+  );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..a3021c2
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,118 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // special patch to correctly work on Ripple emulator (CB-9760)
+    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+        module.exports = window.open.bind(window); // fallback to default window.open behaviour
+        return;
+    }
+
+    var exec = require('cordova/exec');
+    var channel = require('cordova/channel');
+    var modulemapper = require('cordova/modulemapper');
+    var urlutil = require('cordova/urlutil');
+
+    function InAppBrowser () {
+        this.channels = {
+            'loadstart': channel.create('loadstart'),
+            'loadstop': channel.create('loadstop'),
+            'loaderror': channel.create('loaderror'),
+            'exit': channel.create('exit'),
+            'customscheme': channel.create('customscheme')
+        };
+    }
+
+    InAppBrowser.prototype = {
+        _eventHandler: function (event) {
+            if (event && (event.type in this.channels)) {
+                this.channels[event.type].fire(event);
+            }
+        },
+        close: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'close', []);
+        },
+        show: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'show', []);
+        },
+        hide: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'hide', []);
+        },
+        addEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].subscribe(f);
+            }
+        },
+        removeEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].unsubscribe(f);
+            }
+        },
+
+        executeScript: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('executeScript requires exactly one of code or file to be specified');
+            }
+        },
+
+        insertCSS: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('insertCSS requires exactly one of code or file to be specified');
+            }
+        }
+    };
+
+    module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+        // Don't catch calls that write to existing frames (e.g. named iframes).
+        if (window.frames && window.frames[strWindowName]) {
+            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+            return origOpenFunc.apply(window, arguments);
+        }
+
+        strUrl = urlutil.makeAbsolute(strUrl);
+        var iab = new InAppBrowser();
+
+        callbacks = callbacks || {};
+        for (var callbackName in callbacks) {
+            iab.addEventListener(callbackName, callbacks[callbackName]);
+        }
+
+        var cb = function (eventname) {
+            iab._eventHandler(eventname);
+        };
+
+        strWindowFeatures = strWindowFeatures || '';
+
+        exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+        return iab;
+    };
+})();
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..2469e9e
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,344 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) {
+// This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+  switch (string) {
+    case '1':
+      return true;
+    case '0':
+      return false;
+    default:
+    throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+  }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+  return {
+    authorized: stringToBool(statusDictionary.authorized),
+    denied: stringToBool(statusDictionary.denied),
+    restricted: stringToBool(statusDictionary.restricted),
+    prepared: stringToBool(statusDictionary.prepared),
+    scanning: stringToBool(statusDictionary.scanning),
+    previewing: stringToBool(statusDictionary.previewing),
+    showing: stringToBool(statusDictionary.showing),
+    lightEnabled: stringToBool(statusDictionary.lightEnabled),
+    canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+    canEnableLight: stringToBool(statusDictionary.canEnableLight),
+    canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+    currentCamera: parseInt(statusDictionary.currentCamera)
+  };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+  var body = document.body;
+  if (body.style) {
+    body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+    body.style.backgroundImage = '';
+    setTimeout(function() {
+      body.style.backgroundColor = 'transparent';
+    }, 1);
+    if (body.parentNode && body.parentNode.style) {
+      body.parentNode.style.backgroundColor = 'transparent';
+      body.parentNode.style.backgroundImage = '';
+    }
+  }
+}
+
+function errorCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(error) {
+    var errorCode = parseInt(error);
+    var QRScannerError = {};
+    switch (errorCode) {
+      case 0:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner experienced an unexpected error.'
+        };
+        break;
+      case 1:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_DENIED',
+          code: 1,
+          _message: 'The user denied camera access.'
+        };
+        break;
+      case 2:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_RESTRICTED',
+          code: 2,
+          _message: 'Camera access is restricted.'
+        };
+        break;
+      case 3:
+        QRScannerError = {
+          name: 'BACK_CAMERA_UNAVAILABLE',
+          code: 3,
+          _message: 'The back camera is unavailable.'
+        };
+        break;
+      case 4:
+        QRScannerError = {
+          name: 'FRONT_CAMERA_UNAVAILABLE',
+          code: 4,
+          _message: 'The front camera is unavailable.'
+        };
+        break;
+      case 5:
+        QRScannerError = {
+          name: 'CAMERA_UNAVAILABLE',
+          code: 5,
+          _message: 'The camera is unavailable.'
+        };
+        break;
+      case 6:
+        QRScannerError = {
+          name: 'SCAN_CANCELED',
+          code: 6,
+          _message: 'Scan was canceled.'
+        };
+        break;
+      case 7:
+        QRScannerError = {
+          name: 'LIGHT_UNAVAILABLE',
+          code: 7,
+          _message: 'The device light is unavailable.'
+        };
+        break;
+      case 8:
+        // Open settings is only available on iOS 8.0+.
+        QRScannerError = {
+          name: 'OPEN_SETTINGS_UNAVAILABLE',
+          code: 8,
+          _message: 'The device is unable to open settings.'
+        };
+        break;
+      default:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner returned an invalid error code.'
+        };
+        break;
+    }
+    callback(QRScannerError);
+  };
+}
+
+function successCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    callback(null, convertStatus(statusDict));
+  };
+}
+
+function doneCallback(callback, clear) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    if (clear) {
+      clearBackground();
+    }
+    callback(convertStatus(statusDict));
+  };
+}
+
+return {
+  prepare: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+  },
+  destroy: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+  },
+  scan: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to scan method.');
+    }
+    var success = function(result) {
+      callback(null, result);
+    };
+    cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+  },
+  cancelScan: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+  },
+  show: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+  },
+  hide: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+  },
+  pausePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+  },
+  resumePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+  },
+  enableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+  },
+  disableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+  },
+  useCamera: function(index, callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+  },
+  useFrontCamera: function(callback) {
+    var frontCamera = 1;
+    if (callback) {
+      this.useCamera(frontCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+    }
+  },
+  useBackCamera: function(callback) {
+    var backCamera = 0;
+    if (callback) {
+      this.useCamera(backCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+    }
+  },
+  openSettings: function(callback) {
+    if (callback) {
+      cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+    }
+  },
+  getStatus: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to getStatus method.');
+    }
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+  }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
new file mode 100644
index 0000000..911ad50
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+*/

+

+var exec = require('cordova/exec');

+

+var splashscreen = {

+    show:function() {

+        exec(null, null, "SplashScreen", "show", []);

+    },

+    hide:function() {

+        exec(null, null, "SplashScreen", "hide", []);

+    }

+};

+

+module.exports = splashscreen;

+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..708186f
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,116 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+    "black": "#000000",
+    "darkGray": "#A9A9A9",
+    "lightGray": "#D3D3D3",
+    "white": "#FFFFFF",
+    "gray": "#808080",
+    "red": "#FF0000",
+    "green": "#00FF00",
+    "blue": "#0000FF",
+    "cyan": "#00FFFF",
+    "yellow": "#FFFF00",
+    "magenta": "#FF00FF",
+    "orange": "#FFA500",
+    "purple": "#800080",
+    "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+    isVisible: true,
+
+    overlaysWebView: function (doOverlay) {
+        exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+    },
+
+    styleDefault: function () {
+        // dark text ( to be used on a light background )
+        exec(null, null, "StatusBar", "styleDefault", []);
+    },
+
+    styleLightContent: function () {
+        // light text ( to be used on a dark background )
+        exec(null, null, "StatusBar", "styleLightContent", []);
+    },
+
+    styleBlackTranslucent: function () {
+        // #88000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+    },
+
+    styleBlackOpaque: function () {
+        // #FF000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackOpaque", []);
+    },
+
+    backgroundColorByName: function (colorname) {
+        return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+    },
+
+    backgroundColorByHexString: function (hexString) {
+        if (hexString.charAt(0) !== "#") {
+            hexString = "#" + hexString;
+        }
+
+        if (hexString.length === 4) {
+            var split = hexString.split("");
+            hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+        }
+
+        exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+    },
+
+    hide: function () {
+        exec(null, null, "StatusBar", "hide", []);
+        StatusBar.isVisible = false;
+    },
+
+    show: function () {
+        exec(null, null, "StatusBar", "show", []);
+        StatusBar.isVisible = true;
+    }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+    exec(function (res) {
+        if (typeof res == 'object') {
+            if (res.type == 'tap') {
+                cordova.fireWindowEvent('statusTap');
+            }
+        } else {
+            StatusBar.isVisible = res;
+        }
+    }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
new file mode 100644
index 0000000..9c935cb
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
@@ -0,0 +1,121 @@
+cordova.define("cordova-plugin-themeablebrowser.themeablebrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+function ThemeableBrowser() {
+   this.channels = {};
+}
+
+ThemeableBrowser.prototype = {
+    _eventHandler: function (event) {
+        if (event && (event.type in this.channels)) {
+            this.channels[event.type].fire(event);
+        }
+    },
+    close: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'close', []);
+        return this;
+    },
+    show: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'show', []);
+        return this;
+    },
+    reload: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'reload', []);
+        return this;
+    },
+    addEventListener: function (eventname,f) {
+        if (!(eventname in this.channels)) {
+            this.channels[eventname] = channel.create(eventname);
+        }
+        this.channels[eventname].subscribe(f);
+        return this;
+    },
+    removeEventListener: function(eventname, f) {
+        if (eventname in this.channels) {
+            this.channels[eventname].unsubscribe(f);
+        }
+        return this;
+    },
+
+    executeScript: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('executeScript requires exactly one of code or file to be specified');
+        }
+        return this;
+    },
+
+    insertCSS: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('insertCSS requires exactly one of code or file to be specified');
+        }
+        return this;
+    }
+};
+
+exports.open = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
+    // Don't catch calls that write to existing frames (e.g. named iframes).
+    if (window.frames && window.frames[strWindowName]) {
+        var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+        return origOpenFunc.apply(window, arguments);
+    }
+
+    strUrl = urlutil.makeAbsolute(strUrl);
+    var iab = new ThemeableBrowser();
+
+    callbacks = callbacks || {};
+    for (var callbackName in callbacks) {
+        iab.addEventListener(callbackName, callbacks[callbackName]);
+    }
+
+    var cb = function(eventname) {
+       iab._eventHandler(eventname);
+    };
+
+    strWindowFeatures = strWindowFeatures && JSON.stringify(strWindowFeatures);
+    // Slightly delay the actual native call to give the user a chance to
+    // register event listeners first, otherwise some warnings or errors may be missed.
+    setTimeout(function() {
+        exec(cb, cb, 'ThemeableBrowser', 'open', [strUrl, strWindowName, strWindowFeatures || '']);
+    }, 0);
+    return iab;
+};
+
+exports.EVT_ERR = 'ThemeableBrowserError';
+exports.EVT_WRN = 'ThemeableBrowserWarning';
+exports.ERR_CRITICAL = 'critical';
+exports.ERR_LOADFAIL = 'loadfail';
+exports.WRN_UNEXPECTED = 'unexpected';
+exports.WRN_UNDEFINED = 'undefined';
+});
diff --git a/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..38a3a85
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) {
+function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+  if (!window.plugins) {
+    window.plugins = {};
+  }
+
+  window.plugins.touchid = new TouchID();
+  return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});
diff --git a/platforms/android/app/src/main/assets/www/pwdset.html b/platforms/android/app/src/main/assets/www/pwdset.html
new file mode 100644
index 0000000..fc201aa
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/pwdset.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>设置登录密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">设置登录密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">登录密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd" placeholder="6位以上字符">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd" placeholder="请再次确认密码">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doRegister();" class="weui-btn weui-btn_primary">保存</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/pwdset.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/qrcode.html b/platforms/android/app/src/main/assets/www/qrcode.html
new file mode 100644
index 0000000..3391537
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/qrcode.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>付款码</title>
+</head>
+<body style="background: #fff"  >
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">付款码</div>
+    </header>
+    <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;margin-top: 50px;">
+        <div style="background: #fff;text-align: center;" id="qrcode"></div>
+    </div>
+    <p style="text-align: center;margin-top:20px;color:#999">请将二维码对准扫描设备</p>
+    <div style="padding: 30px;">
+        <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.refresh()">手动刷新二维码</div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/qrcode.min.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/qrcode.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/register.html b/platforms/android/app/src/main/assets/www/register.html
new file mode 100644
index 0000000..34e5998
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/register.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>注册绑定</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">注册</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" maxlength="11">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        <div>
+            <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+                <input id="agree" type="checkbox" class="weui-agree__checkbox" value="1">
+                <span class="weui-agree__text">
+                    我已阅读并同意
+                </span>
+            </label>
+            <a href="uxy.html" style="font-size: 13px;">《用户协议与隐私条款》</a>
+        </div>
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doRegister()">注册</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/register.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/scan.html b/platforms/android/app/src/main/assets/www/scan.html
new file mode 100644
index 0000000..80b62bb
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/scan.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>大理市民卡</title>
+</head>
+
+<body style="background: transparent none !important;">
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:app.goPage()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">扫一扫</div>
+        <a class="aui-pull-right aui-btn aui-btn-outlined">
+            <span class="aui-iconfont aui-icon-search" id="lightBtn" ></span>
+        </a>
+    </header>
+    <div class="qrscanner">
+        <div class="qrscanner-area">
+        </div>
+        <div class="through-line"></div>
+    </div>
+    <!--<div class="footer ">
+        <div class="align-center">
+            <button class="icon ion-flash" id="lightBtn"></button>
+        </div>
+    </div>-->
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/scan.js"></script>
diff --git a/platforms/android/app/src/main/assets/www/security.html b/platforms/android/app/src/main/assets/www/security.html
new file mode 100644
index 0000000..9cc54d3
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/security.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>账户安全</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账户安全</div>
+    </header>
+    <section class="aui-content aui-margin-b-15 aui-margin-t-10">
+        <ul class="aui-list aui-list-in aui-margin-t-10 ">
+            <li class="aui-list-item">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">登录密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+            <li class="aui-list-item">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">支付密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+        </ul>
+    </section>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/security.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/signxy.html b/platforms/android/app/src/main/assets/www/signxy.html
new file mode 100644
index 0000000..cb0f1ba
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/signxy.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>签约代扣免密支付协议</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">签约代扣免密支付协议</div>
+    </header>
+    <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:135px;left: 0;right: 0" id="content">
+        
+    </div>
+    <div class="weui-footer weui-footer_fixed-bottom" style="background: #fff;display: none;" id="btn">
+            <div style="margin-top: 10px;">
+                <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+                    <input id="agree" type="checkbox" class="weui-agree__checkbox" value="yes">
+                    <span class="weui-agree__text">
+                        我已阅读并同意该协议
+                    </span>
+                </label>
+            </div>
+            <section class="aui-content-padded" style="margin-top: 20px;">
+                <div class="aui-btn aui-btn-block aui-btn-info"  tapmode onclick="app.agreeXY()">签约代扣协议</div>
+            </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/signxy.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/uxy.html b/platforms/android/app/src/main/assets/www/uxy.html
new file mode 100644
index 0000000..319f8fc
--- /dev/null
+++ b/platforms/android/app/src/main/assets/www/uxy.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>用户协议与隐私条款</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="register.html">
+            <span class="aui-iconfont aui-icon-close"></span>
+        </a>
+        <div class="aui-title">用户协议与隐私条款</div>
+    </header>
+    <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:5px;left: 0;right: 0" id="content">
+本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。
+<br>
+1. 适用范围<br>
+
+(a) 在您注册本应用帐号时,您根据本应用要求提供的个人注册信息;<br>
+
+(b) 在您使用本应用网络服务,或访问本应用平台网页时,本应用自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;
+<br>
+(c) 本应用通过合法途径从商业伙伴处取得的用户个人数据。<br>
+
+您了解并同意,以下信息不适用本隐私权政策:<br>
+
+(a) 您在使用本应用平台提供的搜索服务时输入的关键字信息;<br>
+
+(b) 本应用收集到的您在本应用发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;<br>
+
+(c) 违反法律规定或违反本应用规则行为及本应用已对您采取的措施。<br>
+
+2. 信息使用<br>
+(a)本应用不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先得到您的许可,或该第三方和本应用(含本应用关联公司)单独或共同为您提供服务,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。
+<br>
+(b) 本应用亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。任何本应用平台用户如从事上述活动,一经发现,本应用有权立即终止与该用户的服务协议。
+<br>
+(c) 为服务用户的目的,本应用可能通过使用您的个人信息,向您提供您感兴趣的信息,包括但不限于向您发出产品和服务信息,或者与本应用合作伙伴共享信息以便他们向您发送有关其产品和服务的信息(后者需要您的事先同意)。
+<br>
+3. 信息披露<br>
+
+在如下情况下,本应用将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息:
+<br>
+(a) 经您事先同意,向第三方披露;
+<br>
+(b)为提供您所要求的产品和服务,而必须和第三方分享您的个人信息;
+<br>
+(c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;
+<br>
+(d) 如您出现违反中国有关法律、法规或者本应用服务协议或相关规则的情况,需要向第三方披露;
+<br>
+(e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;
+<br>
+(f) 在本应用平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,本应用有权决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决。
+<br>
+(g) 其它本应用根据法律、法规或者网站政策认为合适的披露。
+<br>
+4. 信息存储和交换
+<br>
+本应用收集的有关您的信息和资料将保存在本应用及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或本应用收集信息和资料所在地的境外并在境外被访问、存储和展示。
+<br>
+5. Cookie的使用
+<br>
+(a) 在您未拒绝接受cookies的情况下,本应用会在您的计算机上设定或取用cookies ,以便您能登录或使用依赖于cookies的本应用平台服务或功能。本应用使用cookies可为您提供更加周到的个性化服务,包括推广服务。
+<br>
+(b) 您有权选择接受或拒绝接受cookies。您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能无法登录或使用依赖于cookies的本应用网络服务或功能。
+<br>
+(c) 通过本应用所设cookies所取得的有关信息,将适用本政策。
+<br>
+6. 信息安全
+<br>
+(a) 本应用帐号均有安全保护功能,请妥善保管您的用户名及密码信息。本应用将通过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施,但同时也请您注意在信息网络上不存在“完善的安全措施”。
+<br>
+(b) 在使用本应用网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对
+<br>
+7.本隐私政策的更改
+<br>
+(a)如果决定更改隐私政策,我们会在本政策中、本公司网站中以及我们认为适当的位置发布这些更改,以便您了解我们如何收集、使用您的个人信息,哪些人可以访问这些信息,以及在什么情况下我们会透露这些信息。
+<br>
+(b)本公司保留随时修改本政策的权利,因此请经常查看。如对本政策作出重大更改,本公司会通过网站通知的形式告知。
+<br>
+方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,尤其是本应用用户名及密码发生泄露,请您立即联络本应用客服,以便本应用采取相应措施。
+<br>
+
+
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/uxy.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java b/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java
new file mode 100755
index 0000000..f2e37d7
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java
@@ -0,0 +1,793 @@
+package com.bitpay.cordova.qrscanner;
+
+import android.Manifest;
+import android.content.Intent;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.hardware.camera2.CameraAccessException;
+import android.net.Uri;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.ResultPoint;
+import com.journeyapps.barcodescanner.BarcodeCallback;
+import com.journeyapps.barcodescanner.BarcodeResult;
+import com.journeyapps.barcodescanner.BarcodeView;
+import com.journeyapps.barcodescanner.DefaultDecoderFactory;
+import com.journeyapps.barcodescanner.camera.CameraSettings;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.PermissionHelper;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import android.hardware.Camera;
+import android.provider.Settings;
+import android.support.v4.app.ActivityCompat;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+
+
+@SuppressWarnings("deprecation")
+public class QRScanner extends CordovaPlugin implements BarcodeCallback {
+
+    private CallbackContext callbackContext;
+    private boolean cameraClosing;
+    private static Boolean flashAvailable;
+    private boolean lightOn = false;
+    private boolean showing = false;
+    private boolean prepared = false;
+    private int currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
+    private String[] permissions = {Manifest.permission.CAMERA};
+    //Preview started or paused
+    private boolean previewing = false;
+    private BarcodeView  mBarcodeView;
+    private boolean switchFlashOn = false;
+    private boolean switchFlashOff = false;
+    private boolean cameraPreviewing;
+    private boolean scanning = false;
+    private CallbackContext nextScanCallback;
+    private boolean shouldScanAgain;
+    private boolean denied;
+    private boolean authorized;
+    private boolean restricted;
+    private boolean oneTime = true;
+    private boolean keepDenied = false;
+    private boolean appPausedWithActivePreview = false;
+    
+    static class QRScannerError {
+        private static final int UNEXPECTED_ERROR = 0,
+                CAMERA_ACCESS_DENIED = 1,
+                CAMERA_ACCESS_RESTRICTED = 2,
+                BACK_CAMERA_UNAVAILABLE = 3,
+                FRONT_CAMERA_UNAVAILABLE = 4,
+                CAMERA_UNAVAILABLE = 5,
+                SCAN_CANCELED = 6,
+                LIGHT_UNAVAILABLE = 7,
+                OPEN_SETTINGS_UNAVAILABLE = 8;
+    }
+
+    @Override
+    public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
+        this.callbackContext = callbackContext;
+        try {
+            if (action.equals("show")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        show(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("scan")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        scan(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("cancelScan")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        cancelScan(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("openSettings")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        openSettings(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("pausePreview")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        pausePreview(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("useCamera")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        switchCamera(callbackContext, args);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("resumePreview")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        resumePreview(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if(action.equals("hide")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        hide(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if (action.equals("enableLight")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        while (cameraClosing) {
+                            try {
+                                Thread.sleep(10);
+                            } catch (InterruptedException ignore) {
+                            }
+                        }
+                        switchFlashOn = true;
+                        if (hasFlash()) {
+                            if (!hasPermission()) {
+                                requestPermission(33);
+                            } else
+                                enableLight(callbackContext);
+                        } else {
+                            callbackContext.error(QRScannerError.LIGHT_UNAVAILABLE);
+                        }
+                    }
+                });
+                return true;
+            }
+            else if (action.equals("disableLight")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        switchFlashOff = true;
+                        if (hasFlash()) {
+                            if (!hasPermission()) {
+                                requestPermission(33);
+                            } else
+                                disableLight(callbackContext);
+                        } else {
+                            callbackContext.error(QRScannerError.LIGHT_UNAVAILABLE);
+                        }
+                    }
+                });
+                return true;
+            }
+            else if (action.equals("prepare")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        cordova.getActivity().runOnUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+                                try {
+                                    currentCameraId = args.getInt(0);
+                                } catch (JSONException e) {
+                                }
+                                prepare(callbackContext);
+                            }
+                        });
+                    }
+                });
+                return true;
+            }
+            else if (action.equals("destroy")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        destroy(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else if (action.equals("getStatus")) {
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        getStatus(callbackContext);
+                    }
+                });
+                return true;
+            }
+            else {
+                return false;
+            }
+        } catch (Exception e) {
+            callbackContext.error(QRScannerError.UNEXPECTED_ERROR);
+            return false;
+        }
+    }
+
+    @Override
+    public void onPause(boolean multitasking) {
+        if (previewing) {
+            this.appPausedWithActivePreview = true;
+            this.pausePreview(null);
+        }
+    }
+
+    @Override
+    public void onResume(boolean multitasking) {
+        if (this.appPausedWithActivePreview) {
+            this.appPausedWithActivePreview = false;
+            this.resumePreview(null);
+        }
+    }
+
+    private boolean hasFlash() {
+        if (flashAvailable == null) {
+            flashAvailable = false;
+            final PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+            for (final FeatureInfo feature : packageManager.getSystemAvailableFeatures()) {
+                if (PackageManager.FEATURE_CAMERA_FLASH.equalsIgnoreCase(feature.name)) {
+                    flashAvailable = true;
+                    break;
+                }
+            }
+        }
+        return flashAvailable;
+    }
+
+    private void switchFlash(boolean toggleLight, CallbackContext callbackContext) {
+        try {
+            if (hasFlash()) {
+                doswitchFlash(toggleLight, callbackContext);
+            } else {
+                callbackContext.error(QRScannerError.LIGHT_UNAVAILABLE);
+            }
+        } catch (Exception e) {
+            lightOn = false;
+            callbackContext.error(QRScannerError.LIGHT_UNAVAILABLE);
+        }
+    }
+
+    private String boolToNumberString(Boolean bool) {
+        if(bool)
+            return "1";
+        else
+            return "0";
+    }
+
+    private void doswitchFlash(final boolean toggleLight, final CallbackContext callbackContext) throws IOException, CameraAccessException {        //No flash for front facing cameras
+        if (getCurrentCameraId() == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            callbackContext.error(QRScannerError.LIGHT_UNAVAILABLE);
+            return;
+        }
+        if (!prepared) {
+            if (toggleLight)
+                lightOn = true;
+            else
+                lightOn = false;
+            prepare(callbackContext);
+        }
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (mBarcodeView != null) {
+                    mBarcodeView.setTorch(toggleLight);
+                    if (toggleLight)
+                        lightOn = true;
+                    else
+                        lightOn = false;
+                }
+                getStatus(callbackContext);
+            }
+        });
+    }
+
+    public int getCurrentCameraId() {
+        return this.currentCameraId;
+    }
+
+    private boolean canChangeCamera() {
+        int numCameras= Camera.getNumberOfCameras();
+        for(int i=0;i<numCameras;i++){
+            Camera.CameraInfo info = new Camera.CameraInfo();
+            Camera.getCameraInfo(i, info);
+            if(info.CAMERA_FACING_FRONT == info.facing){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void switchCamera(CallbackContext callbackContext, JSONArray args) {
+        int cameraId = 0;
+
+        try {
+            cameraId = args.getInt(0);
+        } catch (JSONException d) {
+            callbackContext.error(QRScannerError.UNEXPECTED_ERROR);
+        }
+        currentCameraId = cameraId;
+        if(scanning) {
+            scanning = false;
+            prepared = false;
+            if(cameraPreviewing) {
+                this.cordova.getActivity().runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        ((ViewGroup) mBarcodeView.getParent()).removeView(mBarcodeView);
+                        cameraPreviewing = false;
+                    }
+                });
+            }
+            closeCamera();
+            prepare(callbackContext);
+            scan(this.nextScanCallback);
+        }
+        else
+            prepare(callbackContext);
+    }
+
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+        oneTime = false;
+        if (requestCode == 33) {
+            // for each permission check if the user granted/denied them
+            // you may want to group the rationale in a single dialog,
+            // this is just an example
+            for (int i = 0; i < permissions.length; i++) {
+                String permission = permissions[i];
+                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
+                    boolean showRationale = ActivityCompat.shouldShowRequestPermissionRationale(cordova.getActivity(), permission);
+                    if (! showRationale) {
+                        // user denied flagging NEVER ASK AGAIN
+                        denied = true;
+                        authorized = false;
+                        callbackContext.error(QRScannerError.CAMERA_ACCESS_DENIED);
+                        return;
+                    } else {
+                        authorized = false;
+                        denied = false;
+                        callbackContext.error(QRScannerError.CAMERA_ACCESS_DENIED);
+                        return;
+                    }
+                } else if (grantResults[i] == PackageManager.PERMISSION_GRANTED){
+                    authorized = true;
+                    denied = false;
+                    switch (requestCode) {
+                        case 33:
+                            if(switchFlashOn && !scanning && !switchFlashOff)
+                                switchFlash(true, callbackContext);
+                            else if(switchFlashOff && !scanning)
+                                switchFlash(false, callbackContext);
+                            else {
+                                setupCamera(callbackContext);
+                                if(!scanning)
+                                    getStatus(callbackContext);
+                            }
+                            break;
+                    }
+                }
+                else {
+                    authorized = false;
+                    denied = false;
+                    restricted = false;
+                }
+            }
+        }
+    }
+
+    public boolean hasPermission() {
+        for(String p : permissions)
+        {
+            if(!PermissionHelper.hasPermission(this, p))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void requestPermission(int requestCode) {
+        PermissionHelper.requestPermissions(this, requestCode, permissions);
+    }
+
+    private void closeCamera() {
+        cameraClosing = true;
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (mBarcodeView != null) {
+                    mBarcodeView.pause();
+                }
+
+                cameraClosing = false;
+            }
+        });
+    }
+
+    private void makeOpaque() {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                webView.getView().setBackgroundColor(Color.TRANSPARENT);
+            }
+        });
+        showing = false;
+    }
+
+    private boolean hasCamera() {
+        if (this.cordova.getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean hasFrontCamera() {
+        if (this.cordova.getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)){
+            return true;
+        } else {
+            return false;
+        }
+    }
+    private void setupCamera(CallbackContext callbackContext) {
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Create our Preview view and set it as the content of our activity.
+                mBarcodeView = new BarcodeView(cordova.getActivity());
+
+                //Configure the decoder
+                ArrayList<BarcodeFormat> formatList = new ArrayList<BarcodeFormat>();
+                formatList.add(BarcodeFormat.QR_CODE);
+                mBarcodeView.setDecoderFactory(new DefaultDecoderFactory(formatList, null, null));
+
+                //Configure the camera (front/back)
+                CameraSettings settings = new CameraSettings();
+                settings.setRequestedCameraId(getCurrentCameraId());
+                mBarcodeView.setCameraSettings(settings);
+
+                FrameLayout.LayoutParams cameraPreviewParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
+                ((ViewGroup) webView.getView().getParent()).addView(mBarcodeView, cameraPreviewParams);
+
+                cameraPreviewing = true;
+                webView.getView().bringToFront();
+
+                mBarcodeView.resume();
+            }
+        });
+        prepared = true;
+        previewing = true;
+        if(shouldScanAgain)
+            scan(callbackContext);
+
+    }
+
+    @Override
+    public void barcodeResult(BarcodeResult barcodeResult) {
+        if (this.nextScanCallback == null) {
+            return;
+        }
+
+        if(barcodeResult.getText() != null) {
+            scanning = false;
+            this.nextScanCallback.success(barcodeResult.getText());
+            this.nextScanCallback = null;
+        }
+        else {
+            scan(this.nextScanCallback);
+        }
+    }
+
+    @Override
+    public void possibleResultPoints(List<ResultPoint> list) {
+    }
+
+    // ---- BEGIN EXTERNAL API ----
+    private void prepare(final CallbackContext callbackContext) {
+        if(!prepared) {
+            if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
+                if (hasCamera()) {
+                    if (!hasPermission()) {
+                        requestPermission(33);
+                    }
+                    else {
+                        setupCamera(callbackContext);
+                        if (!scanning)
+                            getStatus(callbackContext);
+                    }
+                }
+                else {
+                    callbackContext.error(QRScannerError.BACK_CAMERA_UNAVAILABLE);
+                }
+            }
+            else if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                if (hasFrontCamera()) {
+                    if (!hasPermission()) {
+                        requestPermission(33);
+                    }
+                    else {
+                        setupCamera(callbackContext);
+                        if (!scanning)
+                            getStatus(callbackContext);
+                    }
+                }
+                else {
+                    callbackContext.error(QRScannerError.FRONT_CAMERA_UNAVAILABLE);
+                }
+            }
+            else {
+                callbackContext.error(QRScannerError.CAMERA_UNAVAILABLE);
+            }
+        }
+        else {
+            prepared = false;
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mBarcodeView.pause();
+                }
+            });
+            if(cameraPreviewing) {
+                this.cordova.getActivity().runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        ((ViewGroup) mBarcodeView.getParent()).removeView(mBarcodeView);
+                        cameraPreviewing = false;
+                    }
+                });
+
+                previewing = true;
+                lightOn = false;
+            }
+            setupCamera(callbackContext);
+            getStatus(callbackContext);
+        }
+    }
+
+    private void scan(final CallbackContext callbackContext) {
+        scanning = true;
+        if (!prepared) {
+            shouldScanAgain = true;
+            if (hasCamera()) {
+                if (!hasPermission()) {
+                    requestPermission(33);
+                } else {
+                    setupCamera(callbackContext);
+                }
+            }
+        } else {
+            if(!previewing) {
+                this.cordova.getActivity().runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        if(mBarcodeView != null) {
+                            mBarcodeView.resume();
+                            previewing = true;
+                            if(switchFlashOn)
+                                lightOn = true;
+                        }
+                    }
+                });
+            }
+            shouldScanAgain = false;
+            this.nextScanCallback = callbackContext;
+            final BarcodeCallback b = this;
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (mBarcodeView != null) {
+                        mBarcodeView.decodeSingle(b);
+                    }
+                }
+            });
+        }
+    }
+
+    private void cancelScan(final CallbackContext callbackContext) {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                scanning = false;
+                if (mBarcodeView != null) {
+                    mBarcodeView.stopDecoding();
+                }
+            }
+        });
+        if(this.nextScanCallback != null)
+            this.nextScanCallback.error(QRScannerError.SCAN_CANCELED);
+        this.nextScanCallback = null;
+    }
+
+    private void show(final CallbackContext callbackContext) {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                webView.getView().setBackgroundColor(Color.argb(1, 0, 0, 0));
+                showing = true;
+                getStatus(callbackContext);
+            }
+        });
+    }
+
+    private void hide(final CallbackContext callbackContext) {
+        makeOpaque();
+        getStatus(callbackContext);
+    }
+
+    private void pausePreview(final CallbackContext callbackContext) {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if(mBarcodeView != null) {
+                    mBarcodeView.pause();
+                    previewing = false;
+                    if(lightOn)
+                        lightOn = false;
+                }
+                
+                if (callbackContext != null)
+                    getStatus(callbackContext);
+            }
+        });
+
+    }
+
+    private void resumePreview(final CallbackContext callbackContext) {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if(mBarcodeView != null) {
+                    mBarcodeView.resume();
+                    previewing = true;
+                    if(switchFlashOn)
+                        lightOn = true;
+                }
+                
+                if (callbackContext != null)
+                    getStatus(callbackContext);
+            }
+        });
+    }
+
+    private void enableLight(CallbackContext callbackContext) {
+        lightOn = true;
+        if(hasPermission())
+            switchFlash(true, callbackContext);
+        else callbackContext.error(QRScannerError.CAMERA_ACCESS_DENIED);
+    }
+
+    private void disableLight(CallbackContext callbackContext) {
+        lightOn = false;
+        switchFlashOn = false;
+        if(hasPermission())
+            switchFlash(false, callbackContext);
+        else callbackContext.error(QRScannerError.CAMERA_ACCESS_DENIED);
+    }
+
+    private void openSettings(CallbackContext callbackContext) {
+        oneTime = true;
+        if(denied)
+            keepDenied = true;
+        try {
+            denied = false;
+            authorized = false;
+            boolean shouldPrepare = prepared;
+            boolean shouldFlash = lightOn;
+            boolean shouldShow = showing;
+            if(prepared)
+                destroy(callbackContext);
+            lightOn = false;
+            Intent intent = new Intent();
+            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            Uri uri = Uri.fromParts("package", this.cordova.getActivity().getPackageName(), null);
+            intent.setData(uri);
+            this.cordova.getActivity().getApplicationContext().startActivity(intent);
+            getStatus(callbackContext);
+            if (shouldPrepare)
+                prepare(callbackContext);
+            if (shouldFlash)
+                enableLight(callbackContext);
+            if (shouldShow)
+                show(callbackContext);
+        } catch (Exception e) {
+            callbackContext.error(QRScannerError.OPEN_SETTINGS_UNAVAILABLE);
+        }
+
+    }
+
+    private void getStatus(CallbackContext callbackContext) {
+
+        if(oneTime) {
+            boolean authorizationStatus = hasPermission();
+
+            authorized = false;
+            if (authorizationStatus)
+                authorized = true;
+
+            if(keepDenied && !authorized)
+                denied = true;
+            else
+                denied = false;
+
+            //No applicable API
+            restricted = false;
+        }
+        boolean canOpenSettings = true;
+
+        boolean canEnableLight = hasFlash();
+
+        if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT)
+            canEnableLight = false;
+
+        HashMap status = new HashMap();
+        status.put("authorized",boolToNumberString(authorized));
+        status.put("denied",boolToNumberString(denied));
+        status.put("restricted",boolToNumberString(restricted));
+        status.put("prepared",boolToNumberString(prepared));
+        status.put("scanning",boolToNumberString(scanning));
+        status.put("previewing",boolToNumberString(previewing));
+        status.put("showing",boolToNumberString(showing));
+        status.put("lightEnabled",boolToNumberString(lightOn));
+        status.put("canOpenSettings",boolToNumberString(canOpenSettings));
+        status.put("canEnableLight",boolToNumberString(canEnableLight));
+        status.put("canChangeCamera",boolToNumberString(canChangeCamera()));
+        status.put("currentCamera",Integer.toString(getCurrentCameraId()));
+
+        JSONObject obj = new JSONObject(status);
+        PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
+        callbackContext.sendPluginResult(result);
+    }
+
+    private void destroy(CallbackContext callbackContext) {
+        prepared = false;
+        makeOpaque();
+        previewing = false;
+        if(scanning) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    scanning = false;
+                    if (mBarcodeView != null) {
+                        mBarcodeView.stopDecoding();
+                    }
+                }
+            });
+            this.nextScanCallback = null;
+        }
+
+        if(cameraPreviewing) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    ((ViewGroup) mBarcodeView.getParent()).removeView(mBarcodeView);
+                    cameraPreviewing = false;
+                }
+            });
+        }
+        if(currentCameraId != Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            if (lightOn)
+                switchFlash(false, callbackContext);
+        }
+        closeCamera();
+        currentCameraId = 0;
+        getStatus(callbackContext);
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/InAppChromeClient.java b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/InAppChromeClient.java
new file mode 100644
index 0000000..74456a4
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/InAppChromeClient.java
@@ -0,0 +1,132 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package com.initialxy.cordova.themeablebrowser;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.webkit.JsPromptResult;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.GeolocationPermissions.Callback;
+
+public class InAppChromeClient extends WebChromeClient {
+
+    private CordovaWebView webView;
+    private String LOG_TAG = "InAppChromeClient";
+    private long MAX_QUOTA = 100 * 1024 * 1024;
+
+    public InAppChromeClient(CordovaWebView webView) {
+        super();
+        this.webView = webView;
+    }
+    /**
+     * Handle database quota exceeded notification.
+     *
+     * @param url
+     * @param databaseIdentifier
+     * @param currentQuota
+     * @param estimatedSize
+     * @param totalUsedQuota
+     * @param quotaUpdater
+     */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
+    {
+        LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
+        quotaUpdater.updateQuota(MAX_QUOTA);
+    }
+
+    /**
+     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+     *
+     * @param origin
+     * @param callback
+     */
+    @Override
+    public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        callback.invoke(origin, true, false);
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * The prompt bridge provided for the ThemeableBrowser is capable of executing any
+     * oustanding callback belonging to the ThemeableBrowser plugin. Care has been
+     * taken that other callbacks cannot be triggered, and that no other code
+     * execution is possible.
+     *
+     * To trigger the bridge, the prompt default value should be of the form:
+     *
+     * gap-iab://<callbackId>
+     *
+     * where <callbackId> is the string id of the callback to trigger (something
+     * like "ThemeableBrowser0123456789")
+     *
+     * If present, the prompt message is expected to be a JSON-encoded value to
+     * pass to the callback. A JSON_EXCEPTION is returned if the JSON is invalid.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param defaultValue
+     * @param result
+     */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
+        // See if the prompt string uses the 'gap-iab' protocol. If so, the remainder should be the id of a callback to execute.
+        if (defaultValue != null && defaultValue.startsWith("gap")) {
+            if(defaultValue.startsWith("gap-iab://")) {
+                PluginResult scriptResult;
+                String scriptCallbackId = defaultValue.substring(10);
+                if (scriptCallbackId.startsWith("ThemeableBrowser")) {
+                    if(message == null || message.length() == 0) {
+                        scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray());
+                    } else {
+                        try {
+                            scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray(message));
+                        } catch(JSONException e) {
+                            scriptResult = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
+                        }
+                    }
+                    this.webView.sendPluginResult(scriptResult, scriptCallbackId);
+                    result.confirm("");
+                    return true;
+                }
+            }
+            else
+            {
+                // Anything else with a gap: prefix should get this message
+                LOG.w(LOG_TAG, "ThemeableBrowser does not support Cordova API calls: " + url + " " + defaultValue); 
+                result.cancel();
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowser.java b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowser.java
new file mode 100644
index 0000000..673e0d8
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowser.java
@@ -0,0 +1,1447 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package com.initialxy.cordova.themeablebrowser;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Browser;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.CookieManager;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginManager;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.Whitelist;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+@SuppressLint("SetJavaScriptEnabled")
+public class ThemeableBrowser extends CordovaPlugin {
+
+    private static final String NULL = "null";
+    protected static final String LOG_TAG = "ThemeableBrowser";
+    private static final String SELF = "_self";
+    private static final String SYSTEM = "_system";
+    // private static final String BLANK = "_blank";
+    private static final String EXIT_EVENT = "exit";
+    private static final String LOAD_START_EVENT = "loadstart";
+    private static final String LOAD_STOP_EVENT = "loadstop";
+    private static final String LOAD_ERROR_EVENT = "loaderror";
+
+    private static final String ALIGN_LEFT = "left";
+    private static final String ALIGN_RIGHT = "right";
+
+    private static final int TOOLBAR_DEF_HEIGHT = 44;
+    private static final int DISABLED_ALPHA = 127;  // 50% AKA 127/255.
+
+    private static final String EVT_ERR = "ThemeableBrowserError";
+    private static final String EVT_WRN = "ThemeableBrowserWarning";
+    private static final String ERR_CRITICAL = "critical";
+    private static final String ERR_LOADFAIL = "loadfail";
+    private static final String WRN_UNEXPECTED = "unexpected";
+    private static final String WRN_UNDEFINED = "undefined";
+
+    private ThemeableBrowserDialog dialog;
+    private WebView inAppWebView;
+    private EditText edittext;
+    private CallbackContext callbackContext;
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action          The action to execute.
+     * @param args            The exec() arguments, wrapped with some Cordova helpers.
+     * @param callbackContext The callback context used when calling back into JavaScript.
+     * @return
+     * @throws JSONException
+     */
+    public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
+        if (action.equals("open")) {
+            this.callbackContext = callbackContext;
+            final String url = args.getString(0);
+            String t = args.optString(1);
+            if (t == null || t.equals("") || t.equals(NULL)) {
+                t = SELF;
+            }
+            final String target = t;
+            final Options features = parseFeature(args.optString(2));
+
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    String result = "";
+                    // SELF
+                    if (SELF.equals(target)) {
+                        /* This code exists for compatibility between 3.x and 4.x versions of Cordova.
+                         * Previously the Config class had a static method, isUrlWhitelisted(). That
+                         * responsibility has been moved to the plugins, with an aggregating method in
+                         * PluginManager.
+                         */
+                        Boolean shouldAllowNavigation = null;
+                        if (url.startsWith("javascript:")) {
+                            shouldAllowNavigation = true;
+                        }
+                        if (shouldAllowNavigation == null) {
+                            shouldAllowNavigation = new Whitelist().isUrlWhiteListed(url);
+                        }
+                        if (shouldAllowNavigation == null) {
+                            try {
+                                Method gpm = webView.getClass().getMethod("getPluginManager");
+                                PluginManager pm = (PluginManager)gpm.invoke(webView);
+                                Method san = pm.getClass().getMethod("shouldAllowNavigation", String.class);
+                                shouldAllowNavigation = (Boolean)san.invoke(pm, url);
+                            } catch (NoSuchMethodException e) {
+                            } catch (IllegalAccessException e) {
+                            } catch (InvocationTargetException e) {
+                            }
+                        }
+                        // load in webview
+                        if (Boolean.TRUE.equals(shouldAllowNavigation)) {
+                            webView.loadUrl(url);
+                        }
+                        //Load the dialer
+                        else if (url.startsWith(WebView.SCHEME_TEL))
+                        {
+                            try {
+                                Intent intent = new Intent(Intent.ACTION_DIAL);
+                                intent.setData(Uri.parse(url));
+                                cordova.getActivity().startActivity(intent);
+                            } catch (android.content.ActivityNotFoundException e) {
+                                emitError(ERR_CRITICAL,
+                                        String.format("Error dialing %s: %s", url, e.toString()));
+                            }
+                        }
+                        // load in ThemeableBrowser
+                        else {
+                            result = showWebPage(url, features);
+                        }
+                    }
+                    // SYSTEM
+                    else if (SYSTEM.equals(target)) {
+                        result = openExternal(url);
+                    }
+                    // BLANK - or anything else
+                    else {
+                        result = showWebPage(url, features);
+                    }
+
+                    PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
+                    pluginResult.setKeepCallback(true);
+                    callbackContext.sendPluginResult(pluginResult);
+                }
+            });
+        }
+        else if (action.equals("close")) {
+            closeDialog();
+        }
+        else if (action.equals("injectScriptCode")) {
+            String jsWrapper = null;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId());
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectScriptFile")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('script'); c.src = %%s; c.onload = function() { prompt('', 'gap-iab://%s'); }; d.body.appendChild(c); })(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectStyleCode")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('style'); c.innerHTML = %%s; d.body.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectStyleFile")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%s; d.head.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("show")) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    dialog.show();
+                }
+            });
+            PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
+            pluginResult.setKeepCallback(true);
+            this.callbackContext.sendPluginResult(pluginResult);
+        }
+        else if (action.equals("reload")) {
+            if (inAppWebView != null) {
+                this.cordova.getActivity().runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        inAppWebView.reload();
+                    }
+                });
+            }
+        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Called when the view navigates.
+     */
+    @Override
+    public void onReset() {
+        closeDialog();
+    }
+
+    /**
+     * Called by AccelBroker when listener is to be shut down.
+     * Stop listener.
+     */
+    public void onDestroy() {
+        closeDialog();
+    }
+
+    /**
+     * Inject an object (script or style) into the ThemeableBrowser WebView.
+     *
+     * This is a helper method for the inject{Script|Style}{Code|File} API calls, which
+     * provides a consistent method for injecting JavaScript code into the document.
+     *
+     * If a wrapper string is supplied, then the source string will be JSON-encoded (adding
+     * quotes) and wrapped using string formatting. (The wrapper string should have a single
+     * '%s' marker)
+     *
+     * @param source      The source object (filename or script/style text) to inject into
+     *                    the document.
+     * @param jsWrapper   A JavaScript string to wrap the source string in, so that the object
+     *                    is properly injected, or null if the source string is JavaScript text
+     *                    which should be executed directly.
+     */
+    private void injectDeferredObject(String source, String jsWrapper) {
+        String scriptToInject;
+        if (jsWrapper != null) {
+            org.json.JSONArray jsonEsc = new org.json.JSONArray();
+            jsonEsc.put(source);
+            String jsonRepr = jsonEsc.toString();
+            String jsonSourceString = jsonRepr.substring(1, jsonRepr.length()-1);
+            scriptToInject = String.format(jsWrapper, jsonSourceString);
+        } else {
+            scriptToInject = source;
+        }
+        final String finalScriptToInject = scriptToInject;
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @SuppressLint("NewApi")
+            @Override
+            public void run() {
+                if (inAppWebView != null) {
+                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+                        // This action will have the side-effect of blurring the currently focused
+                        // element
+                        inAppWebView.loadUrl("javascript:" + finalScriptToInject);
+                    } else {
+                        inAppWebView.evaluateJavascript(finalScriptToInject, null);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Put the list of features into a hash map
+     *
+     * @param optString
+     * @return
+     */
+    private Options parseFeature(String optString) {
+        Options result = null;
+        if (optString != null && !optString.isEmpty()) {
+            try {
+                result = ThemeableBrowserUnmarshaller.JSONToObj(
+                        optString, Options.class);
+            } catch (Exception e) {
+                emitError(ERR_CRITICAL,
+                        String.format("Invalid JSON @s", e.toString()));
+            }
+        } else {
+            emitWarning(WRN_UNDEFINED,
+                    "No config was given, defaults will be used, "
+                    + "which is quite boring.");
+        }
+
+        if (result == null) {
+            result = new Options();
+        }
+
+        // Always show location, this property is overwritten.
+        result.location = true;
+
+        return result;
+    }
+
+    /**
+     * Display a new browser with the specified URL.
+     *
+     * @param url
+     * @return
+     */
+    public String openExternal(String url) {
+        try {
+            Intent intent = null;
+            intent = new Intent(Intent.ACTION_VIEW);
+            // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
+            // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
+            Uri uri = Uri.parse(url);
+            if ("file".equals(uri.getScheme())) {
+                intent.setDataAndType(uri, webView.getResourceApi().getMimeType(uri));
+            } else {
+                intent.setData(uri);
+            }
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, cordova.getActivity().getPackageName());
+            this.cordova.getActivity().startActivity(intent);
+            return "";
+        } catch (android.content.ActivityNotFoundException e) {
+            Log.d(LOG_TAG, "ThemeableBrowser: Error loading url "+url+":"+ e.toString());
+            return e.toString();
+        }
+    }
+
+    /**
+     * Closes the dialog
+     */
+    public void closeDialog() {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // The JS protects against multiple calls, so this should happen only when
+                // closeDialog() is called by other native code.
+                if (inAppWebView == null) {
+                    emitWarning(WRN_UNEXPECTED, "Close called but already closed.");
+                    return;
+                }
+
+                inAppWebView.setWebViewClient(new WebViewClient() {
+                    // NB: wait for about:blank before dismissing
+                    public void onPageFinished(WebView view, String url) {
+                        if (dialog != null) {
+                            dialog.dismiss();
+                        }
+
+                        // Clean up.
+                        dialog = null;
+                        inAppWebView = null;
+                        edittext = null;
+                        callbackContext = null;
+                    }
+                });
+
+                // NB: From SDK 19: "If you call methods on WebView from any
+                // thread other than your app's UI thread, it can cause
+                // unexpected results."
+                // http://developer.android.com/guide/webapps/migrating.html#Threads
+                inAppWebView.loadUrl("about:blank");
+
+                try {
+                    JSONObject obj = new JSONObject();
+                    obj.put("type", EXIT_EVENT);
+                    sendUpdate(obj, false);
+                } catch (JSONException ex) {
+                }
+            }
+        });
+    }
+
+    private void emitButtonEvent(Event event, String url) {
+        emitButtonEvent(event, url, null);
+    }
+
+    private void emitButtonEvent(Event event, String url, Integer index) {
+        if (event != null && event.event != null) {
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", event.event);
+                obj.put("url", url);
+                if (index != null) {
+                    obj.put("index", index.intValue());
+                }
+                sendUpdate(obj, true);
+            } catch (JSONException e) {
+                // Ignore, should never happen.
+            }
+        } else {
+            emitWarning(WRN_UNDEFINED,
+                    "Button clicked, but event property undefined. "
+                    + "No event will be raised.");
+        }
+    }
+
+    private void emitError(String code, String message) {
+        emitLog(EVT_ERR, code, message);
+    }
+
+    private void emitWarning(String code, String message) {
+        emitLog(EVT_WRN, code, message);
+    }
+
+    private void emitLog(String type, String code, String message) {
+        if (type != null) {
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", type);
+                obj.put("code", code);
+                obj.put("message", message);
+                sendUpdate(obj, true);
+            } catch (JSONException e) {
+                // Ignore, should never happen.
+            }
+        }
+    }
+
+    /**
+     * Checks to see if it is possible to go back one page in history, then does so.
+     */
+    public void goBack() {
+        if (this.inAppWebView != null && this.inAppWebView.canGoBack()) {
+            this.inAppWebView.goBack();
+        }
+    }
+
+    /**
+     * Can the web browser go back?
+     * @return boolean
+     */
+    public boolean canGoBack() {
+        return this.inAppWebView != null && this.inAppWebView.canGoBack();
+    }
+
+    /**
+     * Checks to see if it is possible to go forward one page in history, then does so.
+     */
+    private void goForward() {
+        if (this.inAppWebView != null && this.inAppWebView.canGoForward()) {
+            this.inAppWebView.goForward();
+        }
+    }
+
+    /**
+     * Navigate to the new page
+     *
+     * @param url to load
+     */
+    private void navigate(String url) {
+        InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
+
+        if (!url.startsWith("http") && !url.startsWith("file:")) {
+            this.inAppWebView.loadUrl("http://" + url);
+        } else {
+            this.inAppWebView.loadUrl(url);
+        }
+        this.inAppWebView.requestFocus();
+    }
+
+    private ThemeableBrowser getThemeableBrowser() {
+        return this;
+    }
+
+    /**
+     * Display a new browser with the specified URL.
+     *
+     * @param url
+     * @param features
+     * @return
+     */
+    public String showWebPage(final String url, final Options features) {
+        final CordovaWebView thatWebView = this.webView;
+
+        // Create dialog in new thread
+        Runnable runnable = new Runnable() {
+            @SuppressLint("NewApi")
+            public void run() {
+                // Let's create the main dialog
+                dialog = new ThemeableBrowserDialog(cordova.getActivity(),
+                        android.R.style.Theme_Black_NoTitleBar,
+                        features.hardwareback);
+                if (!features.disableAnimation) {
+                    dialog.getWindow().getAttributes().windowAnimations
+                            = android.R.style.Animation_Dialog;
+                }
+                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+                dialog.setCancelable(true);
+                dialog.setThemeableBrowser(getThemeableBrowser());
+
+                // Main container layout
+                ViewGroup main = null;
+
+                if (features.fullscreen) {
+                    main = new FrameLayout(cordova.getActivity());
+                } else {
+                    main = new LinearLayout(cordova.getActivity());
+                    ((LinearLayout) main).setOrientation(LinearLayout.VERTICAL);
+                }
+
+                // Toolbar layout
+                Toolbar toolbarDef = features.toolbar;
+                FrameLayout toolbar = new FrameLayout(cordova.getActivity());
+                toolbar.setBackgroundColor(hexStringToColor(
+                        toolbarDef != null && toolbarDef.color != null
+                                ? toolbarDef.color : "#ffffffff"));
+                toolbar.setLayoutParams(new ViewGroup.LayoutParams(
+                        LayoutParams.MATCH_PARENT,
+                        dpToPixels(toolbarDef != null
+                                ? toolbarDef.height : TOOLBAR_DEF_HEIGHT)));
+
+                if (toolbarDef != null
+                        && (toolbarDef.image != null || toolbarDef.wwwImage != null)) {
+                    try {
+                        Drawable background = getImage(toolbarDef.image
+                                , toolbarDef.wwwImage, toolbarDef.wwwImageDensity);
+                        setBackground(toolbar, background);
+                    } catch (Resources.NotFoundException e) {
+                        emitError(ERR_LOADFAIL,
+                                String.format("Image for toolbar, %s, failed to load",
+                                        toolbarDef.image));
+                    } catch (IOException ioe) {
+                        emitError(ERR_LOADFAIL,
+                                String.format("Image for toolbar, %s, failed to load",
+                                        toolbarDef.wwwImage));
+                    }
+                }
+
+                // Left Button Container layout
+                LinearLayout leftButtonContainer = new LinearLayout(cordova.getActivity());
+                FrameLayout.LayoutParams leftButtonContainerParams = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                leftButtonContainerParams.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
+                leftButtonContainer.setLayoutParams(leftButtonContainerParams);
+                leftButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
+
+                // Right Button Container layout
+                LinearLayout rightButtonContainer = new LinearLayout(cordova.getActivity());
+                FrameLayout.LayoutParams rightButtonContainerParams = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                rightButtonContainerParams.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
+                rightButtonContainer.setLayoutParams(rightButtonContainerParams);
+                rightButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
+
+                // Edit Text Box
+                edittext = new EditText(cordova.getActivity());
+                RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+                textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
+                textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
+                edittext.setLayoutParams(textLayoutParams);
+                edittext.setSingleLine(true);
+                edittext.setText(url);
+                edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
+                edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
+                edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
+                edittext.setOnKeyListener(new View.OnKeyListener() {
+                    public boolean onKey(View v, int keyCode, KeyEvent event) {
+                        // If the event is a key-down event on the "enter" button
+                        if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+                            navigate(edittext.getText().toString());
+                            return true;
+                        }
+                        return false;
+                    }
+                });
+
+                // Back button
+                final Button back = createButton(
+                    features.backButton,
+                    "back button",
+                    new View.OnClickListener() {
+                        public void onClick(View v) {
+                            emitButtonEvent(
+                                    features.backButton,
+                                    inAppWebView.getUrl());
+
+                            if (features.backButtonCanClose && !canGoBack()) {
+                                closeDialog();
+                            } else {
+                                goBack();
+                            }
+                        }
+                    }
+                );
+
+                if (back != null) {
+                    back.setEnabled(features.backButtonCanClose);
+                }
+
+                // Forward button
+                final Button forward = createButton(
+                    features.forwardButton,
+                    "forward button",
+                    new View.OnClickListener() {
+                        public void onClick(View v) {
+                            emitButtonEvent(
+                                    features.forwardButton,
+                                    inAppWebView.getUrl());
+
+                            goForward();
+                        }
+                    }
+                );
+
+                if (back != null) {
+                    back.setEnabled(false);
+                }
+
+
+                // Close/Done button
+                Button close = createButton(
+                    features.closeButton,
+                    "close button",
+                    new View.OnClickListener() {
+                        public void onClick(View v) {
+                            emitButtonEvent(
+                                    features.closeButton,
+                                    inAppWebView.getUrl());
+                            closeDialog();
+                        }
+                    }
+                );
+
+                // Menu button
+                Spinner menu = features.menu != null
+                        ? new MenuSpinner(cordova.getActivity()) : null;
+                if (menu != null) {
+                    menu.setLayoutParams(new LinearLayout.LayoutParams(
+                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+                    menu.setContentDescription("menu button");
+                    setButtonImages(menu, features.menu, DISABLED_ALPHA);
+
+                    // We are not allowed to use onClickListener for Spinner, so we will use
+                    // onTouchListener as a fallback.
+                    menu.setOnTouchListener(new View.OnTouchListener() {
+                        @Override
+                        public boolean onTouch(View v, MotionEvent event) {
+                            if (event.getAction() == MotionEvent.ACTION_UP) {
+                                emitButtonEvent(
+                                        features.menu,
+                                        inAppWebView.getUrl());
+                            }
+                            return false;
+                        }
+                    });
+
+                    if (features.menu.items != null) {
+                        HideSelectedAdapter<EventLabel> adapter
+                                = new HideSelectedAdapter<EventLabel>(
+                                cordova.getActivity(),
+                                android.R.layout.simple_spinner_item,
+                                features.menu.items);
+                        adapter.setDropDownViewResource(
+                                android.R.layout.simple_spinner_dropdown_item);
+                        menu.setAdapter(adapter);
+                        menu.setOnItemSelectedListener(
+                                new AdapterView.OnItemSelectedListener() {
+                                    @Override
+                                    public void onItemSelected(
+                                            AdapterView<?> adapterView,
+                                            View view, int i, long l) {
+                                        if (inAppWebView != null
+                                                && i < features.menu.items.length) {
+                                            emitButtonEvent(
+                                                    features.menu.items[i],
+                                                    inAppWebView.getUrl(), i);
+                                        }
+                                    }
+
+                                    @Override
+                                    public void onNothingSelected(
+                                            AdapterView<?> adapterView) {
+                                    }
+                                }
+                        );
+                    }
+                }
+
+                // Title
+                final TextView title = features.title != null
+                        ? new TextView(cordova.getActivity()) : null;
+                if (title != null) {
+                    FrameLayout.LayoutParams titleParams
+                            = new FrameLayout.LayoutParams(
+                            LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+                    titleParams.gravity = Gravity.CENTER;
+                    title.setLayoutParams(titleParams);
+                    title.setSingleLine();
+                    title.setEllipsize(TextUtils.TruncateAt.END);
+                    title.setGravity(Gravity.CENTER);
+                    title.setTextColor(hexStringToColor(
+                            features.title.color != null
+                                    ? features.title.color : "#000000ff"));
+                    if (features.title.staticText != null) {
+                        title.setText(features.title.staticText);
+                    }
+                }
+
+                // WebView
+                inAppWebView = new WebView(cordova.getActivity());
+                final ViewGroup.LayoutParams inAppWebViewParams = features.fullscreen
+                        ? new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
+                        : new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0);
+                if (!features.fullscreen) {
+                    ((LinearLayout.LayoutParams) inAppWebViewParams).weight = 1;
+                }
+                inAppWebView.setLayoutParams(inAppWebViewParams);
+                inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView));
+                WebViewClient client = new ThemeableBrowserClient(thatWebView, new PageLoadListener() {
+                    @Override
+                    public void onPageFinished(String url, boolean canGoBack, boolean canGoForward) {
+                        if (inAppWebView != null
+                                && title != null && features.title != null
+                                && features.title.staticText == null
+                                && features.title.showPageTitle) {
+                            title.setText(inAppWebView.getTitle());
+                        }
+
+                        if (back != null) {
+                            back.setEnabled(canGoBack || features.backButtonCanClose);
+                        }
+
+                        if (forward != null) {
+                            forward.setEnabled(canGoForward);
+                        }
+                    }
+                });
+                inAppWebView.setWebViewClient(client);
+                WebSettings settings = inAppWebView.getSettings();
+                settings.setJavaScriptEnabled(true);
+                settings.setJavaScriptCanOpenWindowsAutomatically(true);
+                settings.setBuiltInZoomControls(features.zoom);
+                settings.setDisplayZoomControls(false);
+                settings.setPluginState(android.webkit.WebSettings.PluginState.ON);
+
+                //Toggle whether this is enabled or not!
+                Bundle appSettings = cordova.getActivity().getIntent().getExtras();
+                boolean enableDatabase = appSettings == null || appSettings.getBoolean("ThemeableBrowserStorageEnabled", true);
+                if (enableDatabase) {
+                    String databasePath = cordova.getActivity().getApplicationContext().getDir("themeableBrowserDB", Context.MODE_PRIVATE).getPath();
+                    settings.setDatabasePath(databasePath);
+                    settings.setDatabaseEnabled(true);
+                }
+                settings.setDomStorageEnabled(true);
+
+                if (features.clearcache) {
+                    CookieManager.getInstance().removeAllCookie();
+                } else if (features.clearsessioncache) {
+                    CookieManager.getInstance().removeSessionCookie();
+                }
+
+                inAppWebView.loadUrl(url);
+                inAppWebView.getSettings().setLoadWithOverviewMode(true);
+                inAppWebView.getSettings().setUseWideViewPort(true);
+                inAppWebView.requestFocus();
+                inAppWebView.requestFocusFromTouch();
+
+                // Add buttons to either leftButtonsContainer or
+                // rightButtonsContainer according to user's alignment
+                // configuration.
+                int leftContainerWidth = 0;
+                int rightContainerWidth = 0;
+
+                if (features.customButtons != null) {
+                    for (int i = 0; i < features.customButtons.length; i++) {
+                        final BrowserButton buttonProps = features.customButtons[i];
+                        final int index = i;
+                        Button button = createButton(
+                            buttonProps,
+                            String.format("custom button at %d", i),
+                            new View.OnClickListener() {
+                                @Override
+                                public void onClick(View view) {
+                                    if (inAppWebView != null) {
+                                        emitButtonEvent(buttonProps,
+                                                inAppWebView.getUrl(), index);
+                                    }
+                                }
+                            }
+                        );
+
+                        if (ALIGN_RIGHT.equals(buttonProps.align)) {
+                            rightButtonContainer.addView(button);
+                            rightContainerWidth
+                                    += button.getLayoutParams().width;
+                        } else {
+                            leftButtonContainer.addView(button, 0);
+                            leftContainerWidth
+                                    += button.getLayoutParams().width;
+                        }
+                    }
+                }
+
+                // Back and forward buttons must be added with special ordering logic such
+                // that back button is always on the left of forward button if both buttons
+                // are on the same side.
+                if (forward != null && features.forwardButton != null
+                        && !ALIGN_RIGHT.equals(features.forwardButton.align)) {
+                    leftButtonContainer.addView(forward, 0);
+                    leftContainerWidth
+                            += forward.getLayoutParams().width;
+                }
+
+                if (back != null && features.backButton != null
+                        && ALIGN_RIGHT.equals(features.backButton.align)) {
+                    rightButtonContainer.addView(back);
+                    rightContainerWidth
+                            += back.getLayoutParams().width;
+                }
+
+                if (back != null && features.backButton != null
+                        && !ALIGN_RIGHT.equals(features.backButton.align)) {
+                    leftButtonContainer.addView(back, 0);
+                    leftContainerWidth
+                            += back.getLayoutParams().width;
+                }
+
+                if (forward != null && features.forwardButton != null
+                        && ALIGN_RIGHT.equals(features.forwardButton.align)) {
+                    rightButtonContainer.addView(forward);
+                    rightContainerWidth
+                            += forward.getLayoutParams().width;
+                }
+
+                if (menu != null) {
+                    if (features.menu != null
+                            && ALIGN_RIGHT.equals(features.menu.align)) {
+                        rightButtonContainer.addView(menu);
+                        rightContainerWidth
+                                += menu.getLayoutParams().width;
+                    } else {
+                        leftButtonContainer.addView(menu, 0);
+                        leftContainerWidth
+                                += menu.getLayoutParams().width;
+                    }
+                }
+
+                if (close != null) {
+                    if (features.closeButton != null
+                            && ALIGN_RIGHT.equals(features.closeButton.align)) {
+                        rightButtonContainer.addView(close);
+                        rightContainerWidth
+                                += close.getLayoutParams().width;
+                    } else {
+                        leftButtonContainer.addView(close, 0);
+                        leftContainerWidth
+                                += close.getLayoutParams().width;
+                    }
+                }
+
+                // Add the views to our toolbar
+                toolbar.addView(leftButtonContainer);
+                // Don't show address bar.
+                // toolbar.addView(edittext);
+                toolbar.addView(rightButtonContainer);
+
+                if (title != null) {
+                    int titleMargin = Math.max(
+                            leftContainerWidth, rightContainerWidth);
+
+                    FrameLayout.LayoutParams titleParams
+                            = (FrameLayout.LayoutParams) title.getLayoutParams();
+                    titleParams.setMargins(titleMargin, 0, titleMargin, 0);
+                    toolbar.addView(title);
+                }
+
+                if (features.fullscreen) {
+                    // If full screen mode, we have to add inAppWebView before adding toolbar.
+                    main.addView(inAppWebView);
+                }
+
+                // Don't add the toolbar if its been disabled
+                if (features.location) {
+                    // Add our toolbar to our main view/layout
+                    main.addView(toolbar);
+                }
+
+                if (!features.fullscreen) {
+                    // If not full screen, we add inAppWebView after adding toolbar.
+                    main.addView(inAppWebView);
+                }
+
+                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+                lp.copyFrom(dialog.getWindow().getAttributes());
+                lp.width = WindowManager.LayoutParams.MATCH_PARENT;
+                lp.height = WindowManager.LayoutParams.MATCH_PARENT;
+
+                dialog.setContentView(main);
+                dialog.show();
+                dialog.getWindow().setAttributes(lp);
+                // the goal of openhidden is to load the url and not display it
+                // Show() needs to be called to cause the URL to be loaded
+                if(features.hidden) {
+                    dialog.hide();
+                }
+            }
+        };
+        this.cordova.getActivity().runOnUiThread(runnable);
+        return "";
+    }
+
+    /**
+     * Convert our DIP units to Pixels
+     *
+     * @return int
+     */
+    private int dpToPixels(int dipValue) {
+        int value = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP,
+                (float) dipValue,
+                cordova.getActivity().getResources().getDisplayMetrics()
+        );
+
+        return value;
+    }
+
+    private int hexStringToColor(String hex) {
+        int result = 0;
+
+        if (hex != null && !hex.isEmpty()) {
+            if (hex.charAt(0) == '#') {
+                hex = hex.substring(1);
+            }
+
+            // No alpha, that's fine, we will just attach ff.
+            if (hex.length() < 8) {
+                hex += "ff";
+            }
+
+            result = (int) Long.parseLong(hex, 16);
+
+            // Almost done, but Android color code is in form of ARGB instead of
+            // RGBA, so we gotta shift it a bit.
+            int alpha = (result & 0xff) << 24;
+            result = result >> 8 & 0xffffff | alpha;
+        }
+
+        return result;
+    }
+
+    /**
+    * This is a rather unintuitive helper method to load images. The reason why this method exists
+    * is because due to some service limitations, one may not be able to add images to native
+    * resource bundle. So this method offers a way to load image from www contents instead.
+    * However loading from native resource bundle is already preferred over loading from www. So
+    * if name is given, then it simply loads from resource bundle and the other two parameters are
+    * ignored. If name is not given, then altPath is assumed to be a file path _under_ www and
+    * altDensity is the desired density of the given image file, because without native resource
+    * bundle, we can't tell what density the image is supposed to be so it needs to be given
+    * explicitly.
+    */
+    private Drawable getImage(String name, String altPath, double altDensity) throws IOException {
+        Drawable result = null;
+        Resources activityRes = cordova.getActivity().getResources();
+
+        if (name != null) {
+            int id = activityRes.getIdentifier(name, "drawable",
+                    cordova.getActivity().getPackageName());
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                result = activityRes.getDrawable(id);
+            } else {
+                result = activityRes.getDrawable(id, cordova.getActivity().getTheme());
+            }
+        } else if (altPath != null) {
+            File file = new File("www", altPath);
+            InputStream is = null;
+            try {
+                is = cordova.getActivity().getAssets().open(file.getPath());
+                Bitmap bitmap = BitmapFactory.decodeStream(is);
+                bitmap.setDensity((int) (DisplayMetrics.DENSITY_MEDIUM * altDensity));
+                result = new BitmapDrawable(activityRes, bitmap);
+            } finally {
+                // Make sure we close this input stream to prevent resource leak.
+                try {
+                    is.close();
+                } catch (Exception e) {}
+            }
+        }
+        return result;
+    }
+
+    private void setButtonImages(View view, BrowserButton buttonProps, int disabledAlpha) {
+        Drawable normalDrawable = null;
+        Drawable disabledDrawable = null;
+        Drawable pressedDrawable = null;
+
+        CharSequence description = view.getContentDescription();
+
+        if (buttonProps.image != null || buttonProps.wwwImage != null) {
+            try {
+                normalDrawable = getImage(buttonProps.image, buttonProps.wwwImage,
+                        buttonProps.wwwImageDensity);
+                ViewGroup.LayoutParams params = view.getLayoutParams();
+                params.width = normalDrawable.getIntrinsicWidth();
+                params.height = normalDrawable.getIntrinsicHeight();
+            } catch (Resources.NotFoundException e) {
+                emitError(ERR_LOADFAIL,
+                        String.format("Image for %s, %s, failed to load",
+                                description, buttonProps.image));
+            } catch (IOException ioe) {
+                emitError(ERR_LOADFAIL,
+                        String.format("Image for %s, %s, failed to load",
+                                description, buttonProps.wwwImage));
+            }
+        } else {
+            emitWarning(WRN_UNDEFINED,
+                    String.format("Image for %s is not defined. Button will not be shown",
+                            description));
+        }
+
+        if (buttonProps.imagePressed != null || buttonProps.wwwImagePressed != null) {
+            try {
+                pressedDrawable = getImage(buttonProps.imagePressed, buttonProps.wwwImagePressed,
+                        buttonProps.wwwImageDensity);
+            } catch (Resources.NotFoundException e) {
+                emitError(ERR_LOADFAIL,
+                        String.format("Pressed image for %s, %s, failed to load",
+                                description, buttonProps.imagePressed));
+            } catch (IOException e) {
+                emitError(ERR_LOADFAIL,
+                        String.format("Pressed image for %s, %s, failed to load",
+                                description, buttonProps.wwwImagePressed));
+            }
+        } else {
+            emitWarning(WRN_UNDEFINED,
+                    String.format("Pressed image for %s is not defined.",
+                            description));
+        }
+
+        if (normalDrawable != null) {
+            // Create the disabled state drawable by fading the normal state
+            // drawable. Drawable.setAlpha() stopped working above Android 4.4
+            // so we gotta bring out some bitmap magic. Credit goes to:
+            // http://stackoverflow.com/a/7477572
+            Bitmap enabledBitmap = ((BitmapDrawable) normalDrawable).getBitmap();
+            Bitmap disabledBitmap = Bitmap.createBitmap(
+                    normalDrawable.getIntrinsicWidth(),
+                    normalDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(disabledBitmap);
+
+            Paint paint = new Paint();
+            paint.setAlpha(disabledAlpha);
+            canvas.drawBitmap(enabledBitmap, 0, 0, paint);
+
+            Resources activityRes = cordova.getActivity().getResources();
+            disabledDrawable = new BitmapDrawable(activityRes, disabledBitmap);
+        }
+
+        StateListDrawable states = new StateListDrawable();
+        if (pressedDrawable != null) {
+            states.addState(
+                new int[] {
+                    android.R.attr.state_pressed
+                },
+                pressedDrawable
+            );
+        }
+        if (normalDrawable != null) {
+            states.addState(
+                new int[] {
+                    android.R.attr.state_enabled
+                },
+                normalDrawable
+            );
+        }
+        if (disabledDrawable != null) {
+            states.addState(
+                new int[] {},
+                disabledDrawable
+            );
+        }
+
+        setBackground(view, states);
+    }
+
+    private void setBackground(View view, Drawable drawable) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+            view.setBackgroundDrawable(drawable);
+        } else {
+            view.setBackground(drawable);
+        }
+    }
+
+    private Button createButton(BrowserButton buttonProps, String description,
+            View.OnClickListener listener) {
+        Button result = null;
+        if (buttonProps != null) {
+            result = new Button(cordova.getActivity());
+            result.setContentDescription(description);
+            result.setLayoutParams(new LinearLayout.LayoutParams(
+                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+            setButtonImages(result, buttonProps, DISABLED_ALPHA);
+            if (listener != null) {
+                result.setOnClickListener(listener);
+            }
+        } else {
+            emitWarning(WRN_UNDEFINED,
+                    String.format("%s is not defined. Button will not be shown.",
+                            description));
+        }
+        return result;
+    }
+
+    /**
+     * Create a new plugin success result and send it back to JavaScript
+     *
+     * @param obj a JSONObject contain event payload information
+     */
+    private void sendUpdate(JSONObject obj, boolean keepCallback) {
+        sendUpdate(obj, keepCallback, PluginResult.Status.OK);
+    }
+
+    /**
+     * Create a new plugin result and send it back to JavaScript
+     *
+     * @param obj a JSONObject contain event payload information
+     * @param status the status code to return to the JavaScript environment
+     */
+    private void sendUpdate(JSONObject obj, boolean keepCallback, PluginResult.Status status) {
+        if (callbackContext != null) {
+            PluginResult result = new PluginResult(status, obj);
+            result.setKeepCallback(keepCallback);
+            callbackContext.sendPluginResult(result);
+            if (!keepCallback) {
+                callbackContext = null;
+            }
+        }
+    }
+
+    public static interface PageLoadListener {
+        public void onPageFinished(String url, boolean canGoBack,
+                boolean canGoForward);
+    }
+
+    /**
+     * The webview client receives notifications about appView
+     */
+    public class ThemeableBrowserClient extends WebViewClient {
+        PageLoadListener callback;
+        CordovaWebView webView;
+
+        /**
+         * Constructor.
+         *
+         * @param webView
+         * @param callback
+         */
+        public ThemeableBrowserClient(CordovaWebView webView,
+                PageLoadListener callback) {
+            this.webView = webView;
+            this.callback = callback;
+        }
+
+        /**
+         * Override the URL that should be loaded
+         *
+         * This handles a small subset of all the URIs that would be encountered.
+         *
+         * @param webView
+         * @param url
+         */
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
+            if (url.startsWith(WebView.SCHEME_TEL)) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_DIAL);
+                    intent.setData(Uri.parse(url));
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
+                }
+            } else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:")) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+                    intent.setData(Uri.parse(url));
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    Log.e(LOG_TAG, "Error with " + url + ": " + e.toString());
+                }
+            }
+            // If sms:5551212?body=This is the message
+            else if (url.startsWith("sms:")) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+
+                    // Get address
+                    String address = null;
+                    int parmIndex = url.indexOf('?');
+                    if (parmIndex == -1) {
+                        address = url.substring(4);
+                    } else {
+                        address = url.substring(4, parmIndex);
+
+                        // If body, then set sms body
+                        Uri uri = Uri.parse(url);
+                        String query = uri.getQuery();
+                        if (query != null) {
+                            if (query.startsWith("body=")) {
+                                intent.putExtra("sms_body", query.substring(5));
+                            }
+                        }
+                    }
+                    intent.setData(Uri.parse("sms:" + address));
+                    intent.putExtra("address", address);
+                    intent.setType("vnd.android-dir/mms-sms");
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    Log.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
+                }
+            }
+            return false;
+        }
+
+
+        /*
+         * onPageStarted fires the LOAD_START_EVENT
+         *
+         * @param view
+         * @param url
+         * @param favicon
+         */
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            String newloc = "";
+            if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
+                newloc = url;
+            }
+            else
+            {
+                // Assume that everything is HTTP at this point, because if we don't specify,
+                // it really should be.  Complain loudly about this!!!
+                Log.e(LOG_TAG, "Possible Uncaught/Unknown URI");
+                newloc = "http://" + url;
+            }
+
+            // Update the UI if we haven't already
+            if (!newloc.equals(edittext.getText().toString())) {
+                edittext.setText(newloc);
+            }
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_START_EVENT);
+                obj.put("url", newloc);
+                sendUpdate(obj, true);
+            } catch (JSONException ex) {
+                Log.e(LOG_TAG, "URI passed in has caused a JSON error.");
+            }
+        }
+
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_STOP_EVENT);
+                obj.put("url", url);
+
+                sendUpdate(obj, true);
+
+                if (this.callback != null) {
+                    this.callback.onPageFinished(url, view.canGoBack(),
+                            view.canGoForward());
+                }
+            } catch (JSONException ex) {
+            }
+        }
+
+        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+            super.onReceivedError(view, errorCode, description, failingUrl);
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_ERROR_EVENT);
+                obj.put("url", failingUrl);
+                obj.put("code", errorCode);
+                obj.put("message", description);
+
+                sendUpdate(obj, true, PluginResult.Status.ERROR);
+            } catch (JSONException ex) {
+            }
+        }
+    }
+
+    /**
+     * Like Spinner but will always trigger onItemSelected even if a selected
+     * item is selected, and always ignore default selection.
+     */
+    public class MenuSpinner extends Spinner {
+        private OnItemSelectedListener listener;
+
+        public MenuSpinner(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void setSelection(int position) {
+            super.setSelection(position);
+
+            if (listener != null) {
+                listener.onItemSelected(null, this, position, 0);
+            }
+        }
+
+        @Override
+        public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+            this.listener = listener;
+        }
+    }
+
+    /**
+     * Extension of ArrayAdapter. The only difference is that it hides the
+     * selected text that's shown inside spinner.
+     * @param <T>
+     */
+    private static class HideSelectedAdapter<T> extends ArrayAdapter {
+
+        public HideSelectedAdapter(Context context, int resource, T[] objects) {
+            super(context, resource, objects);
+        }
+
+        public View getView (int position, View convertView, ViewGroup parent) {
+            View v = super.getView(position, convertView, parent);
+            v.setVisibility(View.GONE);
+            return v;
+        }
+    }
+
+
+    /**
+     * A class to hold parsed option properties.
+     */
+    private static class Options {
+        public boolean location = true;
+        public boolean hidden = false;
+        public boolean clearcache = false;
+        public boolean clearsessioncache = false;
+        public boolean zoom = true;
+        public boolean hardwareback = true;
+
+        public Toolbar toolbar;
+        public Title title;
+        public BrowserButton backButton;
+        public BrowserButton forwardButton;
+        public BrowserButton closeButton;
+        public BrowserMenu menu;
+        public BrowserButton[] customButtons;
+        public boolean backButtonCanClose;
+        public boolean disableAnimation;
+        public boolean fullscreen;
+    }
+
+    private static class Event {
+        public String event;
+    }
+
+    private static class EventLabel extends Event {
+        public String label;
+
+        public String toString() {
+            return label;
+        }
+    }
+
+    private static class BrowserButton extends Event {
+        public String image;
+        public String wwwImage;
+        public String imagePressed;
+        public String wwwImagePressed;
+        public double wwwImageDensity = 1;
+        public String align = ALIGN_LEFT;
+    }
+
+    private static class BrowserMenu extends BrowserButton {
+        public EventLabel[] items;
+    }
+
+    private static class Toolbar {
+        public int height = TOOLBAR_DEF_HEIGHT;
+        public String color;
+        public String image;
+        public String wwwImage;
+        public double wwwImageDensity = 1;
+    }
+
+    private static class Title {
+        public String color;
+        public String staticText;
+        public boolean showPageTitle;
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserDialog.java b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserDialog.java
new file mode 100644
index 0000000..210c258
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserDialog.java
@@ -0,0 +1,61 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package com.initialxy.cordova.themeablebrowser;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Created by Oliver on 22/11/2013.
+ */
+public class ThemeableBrowserDialog extends Dialog {
+    Context context;
+    ThemeableBrowser themeableBrowser = null;
+    boolean hardwareBack;
+
+    public ThemeableBrowserDialog(Context context, int theme,
+          boolean hardwareBack) {
+        super(context, theme);
+        this.context = context;
+        this.hardwareBack = hardwareBack;
+    }
+
+    public void setThemeableBrowser(ThemeableBrowser browser) {
+        this.themeableBrowser = browser;
+    }
+
+    public void onBackPressed () {
+        if (this.themeableBrowser == null) {
+            this.dismiss();
+        } else {
+            // better to go through in themeableBrowser because it does a clean
+            // up
+            if (this.hardwareBack && this.themeableBrowser.canGoBack()) {
+                this.themeableBrowser.goBack();
+            }  else {
+                this.themeableBrowser.closeDialog();
+            }
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserUnmarshaller.java b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserUnmarshaller.java
new file mode 100644
index 0000000..beff5d5
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/initialxy/cordova/themeablebrowser/ThemeableBrowserUnmarshaller.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2014 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.initialxy.cordova.themeablebrowser;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This is a simple and half decent JSON to POJO unmarshaller inspired by
+ * Jackson. It is only a unmarshaller without a marshaller. It is intended to
+ * parse JSON passed to a plugin as options to a POJO. It is nowhere as powerful
+ * as Jackson is, but for most use cases, it will do a pretty decent job since
+ * it is designed to be used for general purpose unmarshalling. This avoid
+ * having to import Jackson or JAXB for merely a Cordova plugin. ~350 lines
+ * isn't too big right?
+ */
+public class ThemeableBrowserUnmarshaller {
+    /**
+     * Runtime exception to notify type mismatch between expected class
+     * structure and JSON.
+     */
+    public static class TypeMismatchException extends RuntimeException {
+        public TypeMismatchException(Type expected, Type got) {
+            super(String.format("Expected %s but got %s.", expected, got));
+        }
+
+        public TypeMismatchException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Runtime exception to notify errors during class initialization.
+     */
+    public static class ClassInstantiationException extends RuntimeException {
+        public ClassInstantiationException(Class<?> cls) {
+            super(String.format("Failed to instantiate %s", cls));
+        }
+
+        public ClassInstantiationException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Runtime exception to notify parser errors.
+     */
+    public static class ParserException extends RuntimeException {
+        public ParserException(Exception e) {
+            super(e);
+        }
+    }
+
+    /**
+     * Given a JSON string, unmarhall it to an instance of the given class.
+     *
+     * @param json JSON string to unmarshall.
+     * @param cls Return an instance of this class. Must be either public class
+     *            or private static class. Inner class will not work.
+     * @param <T> Same type as cls.
+     * @return An instance of class given by cls.
+     * @throws com.initialxy.cordova.themeablebrowser.ThemeableBrowserUnmarshaller.TypeMismatchException
+     */
+    public static <T> T JSONToObj(String json, Class<T> cls) {
+        T result = null;
+
+        if (json != null && !json.isEmpty()) {
+            try {
+                JSONObject jsonObj = new JSONObject(json);
+                result = JSONToObj(jsonObj, cls);
+            } catch (JSONException e) {
+                throw new ParserException(e);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Given a JSONObject, unmarhall it to an instance of the given class.
+     *
+     * @param jsonObj JSON string to unmarshall.
+     * @param cls Return an instance of this class. Must be either public class
+     *            or private static class. Inner class will not work.
+     * @param <T> Same type as cls.
+     * @return An instance of class given by cls.
+     * @throws com.initialxy.cordova.themeablebrowser.ThemeableBrowserUnmarshaller.TypeMismatchException
+     */
+    public static <T> T JSONToObj(JSONObject jsonObj, Class<T> cls) {
+        T result = null;
+
+        try {
+            Constructor<T> constructor = cls.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            result = (T) constructor.newInstance();
+            Iterator<?> i = jsonObj.keys();
+
+            while (i.hasNext()) {
+                String k = (String) i.next();
+                Object val = jsonObj.get(k);
+
+                try {
+                    Field field = cls.getField(k);
+                    Object converted = valToType(val, field.getGenericType());
+
+                    if (converted == null) {
+                        if (!field.getType().isPrimitive()) {
+                            field.set(result, null);
+                        } else {
+                            throw new TypeMismatchException(String.format(
+                                    "Type %s cannot be set to null.",
+                                    field.getType()));
+                        }
+                    } else {
+                        if (converted instanceof List
+                                && field.getType()
+                                .isAssignableFrom(List.class)) {
+                            // Class can define their own favorite
+                            // implementation of List. In which case the field
+                            // still need to be defined as List, but it can be
+                            // initialized with a placeholder instance of any of
+                            // the List implementations (eg. ArrayList).
+                            Object existing = field.get(result);
+                            if (existing != null) {
+                                ((List<?>) existing).clear();
+
+                                // Just because I don't want javac to complain
+                                // about unsafe operations. So I'm gonna use
+                                // more reflection, HA!
+                                Method addAll = existing.getClass()
+                                        .getMethod("addAll", Collection.class);
+                                addAll.invoke(existing, converted);
+                            } else {
+                                field.set(result, converted);
+                            }
+                        } else {
+                            field.set(result, converted);
+                        }
+                    }
+                } catch (NoSuchFieldException e) {
+                    // Ignore.
+                } catch (IllegalAccessException e) {
+                    // Ignore.
+                } catch (IllegalArgumentException e) {
+                    // Ignore.
+                }
+            }
+        } catch (JSONException e) {
+            throw new ParserException(e);
+        } catch (NoSuchMethodException e) {
+            throw new ClassInstantiationException(
+                    "Failed to retrieve constructor for "
+                    + cls.toString() + ", make sure it's not an inner class.");
+        } catch (InstantiationException e) {
+            throw new ClassInstantiationException(cls);
+        } catch (IllegalAccessException e) {
+            throw new ClassInstantiationException(cls);
+        } catch (InvocationTargetException e) {
+            throw new ClassInstantiationException(cls);
+        }
+
+        return result;
+    }
+
+    /**
+     * Given an object extracted from JSONObject field, convert it to an
+     * appropriate object with type appropriate for given type so that it can be
+     * assigned to the associated field of the ummarshalled object. eg.
+     * JSONObject value from a JSONObject field probably needs to be
+     * unmarshalled to a class instance. Double from JSONObject may need to be
+     * converted to Float. etc.
+     *
+     * @param val Value extracted from JSONObject field.
+     * @param genericType Type to convert to. Must be generic type. ie. From
+     *                    field.getGenericType().
+     * @return Object of the given type so it can be assinged to field with
+     * field.set().
+     * @throws com.initialxy.cordova.themeablebrowser.ThemeableBrowserUnmarshaller.TypeMismatchException
+     */
+    private static Object valToType(Object val, Type genericType) {
+        Object result = null;
+        boolean isArray = false;
+
+        Class<?> rawType = null;
+        if (genericType instanceof ParameterizedType) {
+            rawType = (Class<?>) ((ParameterizedType) genericType).getRawType();
+        } else if (genericType instanceof GenericArrayType) {
+            rawType = List.class;
+            isArray = true;
+        } else {
+            rawType = (Class<?>) genericType;
+        }
+
+        isArray = isArray || rawType.isArray();
+ 
+        if (val != null && val != JSONObject.NULL) {
+            if (rawType.isAssignableFrom(String.class)) {
+                if (val instanceof String) {
+                    result = val;
+                } else {
+                    throw new TypeMismatchException(rawType, val.getClass());
+                }
+            } else if (isPrimitive(rawType)) {
+                result = convertToPrimitiveFieldObj(val, rawType);
+            } else if (isArray || rawType.isAssignableFrom(List.class)) {
+                if (val instanceof JSONArray) {
+                    Type itemType = getListItemType(genericType);
+                    result = JSONToList((JSONArray) val, itemType);
+
+                    if (isArray) {
+                        List<?> list = (List<?>) result;
+
+                        Class<?> itemClass = null;
+                        if (itemType instanceof ParameterizedType) {
+                            itemClass = (Class<?>) ((ParameterizedType) itemType).getRawType();
+                        } else {
+                            itemClass = (Class<?>) itemType;
+                        }
+
+                        result = Array.newInstance(itemClass, list.size());
+                        int cnt = 0;
+                        for (Object i : list) {
+                            Array.set(result, cnt, i);
+                            cnt += 1;
+                        }
+                    }
+                } else {
+                    throw new TypeMismatchException(
+                            JSONArray.class, val.getClass());
+                }
+            } else if (val instanceof JSONObject) {
+                result = JSONToObj((JSONObject) val, rawType);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Given a generic type representing a List or array, retrieve list or array
+     * item type.
+     *
+     * @param type
+     * @return
+     */
+    private static Type getListItemType(Type type) {
+        Type result = null;
+        
+        if (type instanceof GenericArrayType) {
+            result = ((GenericArrayType) type).getGenericComponentType();
+        } else if (type instanceof ParameterizedType){
+            result = ((ParameterizedType) type).getActualTypeArguments()[0];
+        } else {
+            result = ((Class<?>) type).getComponentType();
+        }
+
+        return result;
+    }
+
+    /**
+     * Given an JSONArray retrieved from JSONObject, and the destination item
+     * type, unmarshall this list to a List of given item type.
+     *
+     * @param jsonArr
+     * @param itemType
+     * @return
+     */
+    private static List<?> JSONToList(JSONArray jsonArr, Type itemType) {
+        List<Object> result = new ArrayList<Object>();
+
+        Class<?> rawType = null;
+        ParameterizedType pType = null;
+
+        if (itemType instanceof ParameterizedType) {
+            pType = (ParameterizedType) itemType;
+            rawType = (Class<?>) pType.getRawType();
+        } else {
+            rawType = (Class<?>) itemType;
+        }
+
+        int len = jsonArr.length();
+        for (int i = 0; i < len; i++) {
+            try {
+                Object item = jsonArr.get(i);
+                Object converted = valToType(item, itemType);
+                if (converted != null) {
+                    result.add(converted);
+                }
+            } catch (JSONException e) {
+                throw new ParserException(e);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Checks if given class is one of the primitive types or more importantly,
+     * one of the classes associated with a primitive type. eg. Integer, Double
+     * etc.
+     *
+     * @param cls
+     * @return
+     */
+    private static boolean isPrimitive(Class<?> cls) {
+        return cls.isPrimitive()
+                || cls.isAssignableFrom(Byte.class)
+                || cls.isAssignableFrom(Short.class)
+                || cls.isAssignableFrom(Integer.class)
+                || cls.isAssignableFrom(Long.class)
+                || cls.isAssignableFrom(Float.class)
+                || cls.isAssignableFrom(Double.class)
+                || cls.isAssignableFrom(Boolean.class)
+                || cls.isAssignableFrom(Character.class);
+    }
+
+    /**
+     * Gracefully convert given Object to given class given the precondition
+     * that both are primitives or one of the classes associated with
+     * primitives. eg. If val is of type Double and cls is of type int, return
+     * Integer type with appropriate value truncation so that it can be assigned
+     * to field with field.set().
+     *
+     * @param cls
+     * @param val
+     * @return
+     * @throws com.initialxy.cordova.themeablebrowser.ThemeableBrowserUnmarshaller.TypeMismatchException
+     */
+    private static Object convertToPrimitiveFieldObj(Object val, Class<?> cls) {
+        Class<?> valClass = val.getClass();
+        Object result = null;
+
+        try {
+            Method getter = null;
+            if (cls.isAssignableFrom(Byte.class)
+                    || cls.isAssignableFrom(Byte.TYPE)) {
+                getter = valClass.getMethod("byteValue");
+            } else if (cls.isAssignableFrom(Short.class)
+                    || cls.isAssignableFrom(Short.TYPE)) {
+                getter = valClass.getMethod("shortValue");
+            } else if (cls.isAssignableFrom(Integer.class)
+                    || cls.isAssignableFrom(Integer.TYPE)) {
+                getter = valClass.getMethod("intValue");
+            } else if (cls.isAssignableFrom(Long.class)
+                    || cls.isAssignableFrom(Long.TYPE)) {
+                getter = valClass.getMethod("longValue");
+            } else if (cls.isAssignableFrom(Float.class)
+                    || cls.isAssignableFrom(Float.TYPE)) {
+                getter = valClass.getMethod("floatValue");
+            } else if (cls.isAssignableFrom(Double.class)
+                    || cls.isAssignableFrom(Double.TYPE)) {
+                getter = valClass.getMethod("doubleValue");
+            } else if (cls.isAssignableFrom(Boolean.class)
+                    || cls.isAssignableFrom(Boolean.TYPE)) {
+                if (val instanceof Boolean) {
+                    result = val;
+                } else {
+                    throw new TypeMismatchException(cls, val.getClass());
+                }
+            } else if (cls.isAssignableFrom(Character.class)
+                    || cls.isAssignableFrom(Character.TYPE)) {
+                if (val instanceof String && ((String) val).length() == 1) {
+                    char c = ((String) val).charAt(0);
+                    result = Character.valueOf(c);
+                } else if (val instanceof String) {
+                    throw new TypeMismatchException(
+                            "Expected Character, "
+                            + "but received String with length other than 1.");
+                } else {
+                    throw new TypeMismatchException(String.format(
+                            "Expected Character, accept String, but got %s.",
+                            val.getClass()));
+                }
+            }
+
+            if (getter != null) {
+                result = getter.invoke(val);
+            }
+        } catch (NoSuchMethodException e) {
+            throw new TypeMismatchException(String.format(
+                    "Cannot convert %s to %s.", val.getClass(), cls));
+        } catch (SecurityException e) {
+            throw new TypeMismatchException(String.format(
+                    "Cannot convert %s to %s.", val.getClass(), cls));
+        } catch (IllegalAccessException e) {
+            throw new TypeMismatchException(String.format(
+                    "Cannot convert %s to %s.", val.getClass(), cls));
+        } catch (InvocationTargetException e) {
+            throw new TypeMismatchException(String.format(
+                    "Cannot convert %s to %s.", val.getClass(), cls));
+        }
+
+        return result;
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaClientAuth.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaClientAuth.java
new file mode 100644
index 0000000..b01ac93
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaClientAuth.java
@@ -0,0 +1,113 @@
+package com.silkimen.cordovahttp;
+
+import android.app.Activity;
+import android.content.Context;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+
+import org.apache.cordova.CallbackContext;
+
+import com.silkimen.http.KeyChainKeyManager;
+import com.silkimen.http.TLSConfiguration;
+
+class CordovaClientAuth implements Runnable, KeyChainAliasCallback {
+  private static final String TAG = "Cordova-Plugin-HTTP";
+
+  private String mode;
+  private String aliasString;
+  private byte[] rawPkcs;
+  private String pkcsPassword;
+  private Activity activity;
+  private Context context;
+  private TLSConfiguration tlsConfiguration;
+  private CallbackContext callbackContext;
+
+  public CordovaClientAuth(final String mode, final String aliasString, final byte[] rawPkcs,
+      final String pkcsPassword, final Activity activity, final Context context, final TLSConfiguration configContainer,
+      final CallbackContext callbackContext) {
+
+    this.mode = mode;
+    this.aliasString = aliasString;
+    this.rawPkcs = rawPkcs;
+    this.pkcsPassword = pkcsPassword;
+    this.activity = activity;
+    this.tlsConfiguration = configContainer;
+    this.context = context;
+    this.callbackContext = callbackContext;
+  }
+
+  @Override
+  public void run() {
+    if ("systemstore".equals(this.mode)) {
+      this.loadFromSystemStore();
+    } else if ("buffer".equals(this.mode)) {
+      this.loadFromBuffer();
+    } else {
+      this.disableClientAuth();
+    }
+  }
+
+  private void loadFromSystemStore() {
+    if (this.aliasString == null) {
+      KeyChain.choosePrivateKeyAlias(this.activity, this, null, null, null, -1, null);
+    } else {
+      this.alias(this.aliasString);
+    }
+  }
+
+  private void loadFromBuffer() {
+    try {
+      KeyStore keyStore = KeyStore.getInstance("PKCS12");
+      String keyManagerFactoryAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
+      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithm);
+      ByteArrayInputStream stream = new ByteArrayInputStream(this.rawPkcs);
+
+      keyStore.load(stream, this.pkcsPassword.toCharArray());
+      keyManagerFactory.init(keyStore, this.pkcsPassword.toCharArray());
+
+      this.tlsConfiguration.setKeyManagers(keyManagerFactory.getKeyManagers());
+      this.callbackContext.success();
+    } catch (Exception e) {
+      Log.e(TAG, "Couldn't load given PKCS12 container for authentication", e);
+      this.callbackContext.error("Couldn't load given PKCS12 container for authentication");
+    }
+  }
+
+  private void disableClientAuth() {
+    this.tlsConfiguration.setKeyManagers(null);
+    this.callbackContext.success();
+  }
+
+  @Override
+  public void alias(final String alias) {
+    try {
+      if (alias == null) {
+        throw new Exception("Couldn't get a consent for private key access");
+      }
+
+      PrivateKey key = KeyChain.getPrivateKey(this.context, alias);
+      X509Certificate[] chain = KeyChain.getCertificateChain(this.context, alias);
+      KeyManager keyManager = new KeyChainKeyManager(alias, key, chain);
+
+      this.tlsConfiguration.setKeyManagers(new KeyManager[] { keyManager });
+
+      this.callbackContext.success(alias);
+    } catch (Exception e) {
+      Log.e(TAG, "Couldn't load private key and certificate pair with given alias \"" + alias + "\" for authentication",
+          e);
+      this.callbackContext.error(
+          "Couldn't load private key and certificate pair with given alias \"" + alias + "\" for authentication");
+    }
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpBase.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpBase.java
new file mode 100644
index 0000000..011b0dc
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpBase.java
@@ -0,0 +1,180 @@
+package com.silkimen.cordovahttp;
+
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import java.nio.ByteBuffer;
+
+import javax.net.ssl.SSLException;
+
+import com.silkimen.http.HttpBodyDecoder;
+import com.silkimen.http.HttpRequest;
+import com.silkimen.http.HttpRequest.HttpRequestException;
+import com.silkimen.http.JsonUtils;
+import com.silkimen.http.OkConnectionFactory;
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.util.Log;
+
+abstract class CordovaHttpBase implements Runnable {
+  protected static final String TAG = "Cordova-Plugin-HTTP";
+
+  protected String method;
+  protected String url;
+  protected String serializer = "none";
+  protected String responseType;
+  protected Object data;
+  protected JSONObject headers;
+  protected int timeout;
+  protected boolean followRedirects;
+  protected TLSConfiguration tlsConfiguration;
+  protected CallbackContext callbackContext;
+
+  public CordovaHttpBase(String method, String url, String serializer, Object data, JSONObject headers, int timeout,
+      boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration,
+      CallbackContext callbackContext) {
+
+    this.method = method;
+    this.url = url;
+    this.serializer = serializer;
+    this.data = data;
+    this.headers = headers;
+    this.timeout = timeout;
+    this.followRedirects = followRedirects;
+    this.responseType = responseType;
+    this.tlsConfiguration = tlsConfiguration;
+    this.callbackContext = callbackContext;
+  }
+
+  public CordovaHttpBase(String method, String url, JSONObject headers, int timeout, boolean followRedirects,
+      String responseType, TLSConfiguration tlsConfiguration, CallbackContext callbackContext) {
+
+    this.method = method;
+    this.url = url;
+    this.headers = headers;
+    this.timeout = timeout;
+    this.followRedirects = followRedirects;
+    this.responseType = responseType;
+    this.tlsConfiguration = tlsConfiguration;
+    this.callbackContext = callbackContext;
+  }
+
+  @Override
+  public void run() {
+    CordovaHttpResponse response = new CordovaHttpResponse();
+
+    try {
+      HttpRequest request = this.createRequest();
+      this.prepareRequest(request);
+      this.sendBody(request);
+      this.processResponse(request, response);
+    } catch (HttpRequestException e) {
+      if (e.getCause() instanceof SSLException) {
+        response.setStatus(-2);
+        response.setErrorMessage("TLS connection could not be established: " + e.getMessage());
+        Log.w(TAG, "TLS connection could not be established", e);
+      } else if (e.getCause() instanceof UnknownHostException) {
+        response.setStatus(-3);
+        response.setErrorMessage("Host could not be resolved: " + e.getMessage());
+        Log.w(TAG, "Host could not be resolved", e);
+      } else if (e.getCause() instanceof SocketTimeoutException) {
+        response.setStatus(-4);
+        response.setErrorMessage("Request timed out: " + e.getMessage());
+        Log.w(TAG, "Request timed out", e);
+      } else {
+        response.setStatus(-1);
+        response.setErrorMessage("There was an error with the request: " + e.getCause().getMessage());
+        Log.w(TAG, "Generic request error", e);
+      }
+    } catch (Exception e) {
+      response.setStatus(-1);
+      response.setErrorMessage(e.getMessage());
+      Log.e(TAG, "An unexpected error occured", e);
+    }
+
+    try {
+      if (response.hasFailed()) {
+        this.callbackContext.error(response.toJSON());
+      } else {
+        this.callbackContext.success(response.toJSON());
+      }
+    } catch (JSONException e) {
+      Log.e(TAG, "An unexpected error occured while creating HTTP response object", e);
+    }
+  }
+
+  protected HttpRequest createRequest() throws JSONException {
+    return new HttpRequest(this.url, this.method);
+  }
+
+  protected void prepareRequest(HttpRequest request) throws JSONException, IOException {
+    request.followRedirects(this.followRedirects);
+    request.readTimeout(this.timeout);
+    request.acceptCharset("UTF-8");
+    request.uncompress(true);
+    request.setConnectionFactory(new OkConnectionFactory());
+
+    if (this.tlsConfiguration.getHostnameVerifier() != null) {
+      request.setHostnameVerifier(this.tlsConfiguration.getHostnameVerifier());
+    }
+
+    request.setSSLSocketFactory(this.tlsConfiguration.getTLSSocketFactory());
+
+    // setup content type before applying headers, so user can override it
+    this.setContentType(request);
+
+    request.headers(JsonUtils.getStringMap(this.headers));
+  }
+
+  protected void setContentType(HttpRequest request) {
+    if ("json".equals(this.serializer)) {
+      request.contentType("application/json", "UTF-8");
+    } else if ("utf8".equals(this.serializer)) {
+      request.contentType("text/plain", "UTF-8");
+    } else if ("urlencoded".equals(this.serializer)) {
+      // intentionally left blank, because content type is set in HttpRequest.form()
+    }
+  }
+
+  protected void sendBody(HttpRequest request) throws Exception {
+    if (this.data == null) {
+      return;
+    }
+
+    if ("json".equals(this.serializer)) {
+      request.send(this.data.toString());
+    } else if ("utf8".equals(this.serializer)) {
+      request.send(((JSONObject) this.data).getString("text"));
+    } else if ("urlencoded".equals(this.serializer)) {
+      request.form(JsonUtils.getObjectMap((JSONObject) this.data));
+    }
+  }
+
+  protected void processResponse(HttpRequest request, CordovaHttpResponse response) throws Exception {
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    request.receive(outputStream);
+
+    response.setStatus(request.code());
+    response.setUrl(request.url().toString());
+    response.setHeaders(request.headers());
+
+    if (request.code() >= 200 && request.code() < 300) {
+      if ("text".equals(this.responseType)) {
+        String decoded = HttpBodyDecoder.decodeBody(outputStream.toByteArray(), request.charset());
+        response.setBody(decoded);
+      } else {
+        response.setData(outputStream.toByteArray());
+      }
+    } else {
+      response.setErrorMessage(HttpBodyDecoder.decodeBody(outputStream.toByteArray(), request.charset()));
+    }
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpDownload.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpDownload.java
new file mode 100644
index 0000000..d89db82
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpDownload.java
@@ -0,0 +1,42 @@
+package com.silkimen.cordovahttp;
+
+import java.io.File;
+import java.net.URI;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
+
+import com.silkimen.http.HttpRequest;
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.file.FileUtils;
+import org.json.JSONObject;
+
+class CordovaHttpDownload extends CordovaHttpBase {
+  private String filePath;
+
+  public CordovaHttpDownload(String url, JSONObject headers, String filePath, int timeout, boolean followRedirects,
+      TLSConfiguration tlsConfiguration, CallbackContext callbackContext) {
+
+    super("GET", url, headers, timeout, followRedirects, "text", tlsConfiguration, callbackContext);
+    this.filePath = filePath;
+  }
+
+  @Override
+  protected void processResponse(HttpRequest request, CordovaHttpResponse response) throws Exception {
+    response.setStatus(request.code());
+    response.setUrl(request.url().toString());
+    response.setHeaders(request.headers());
+
+    if (request.code() >= 200 && request.code() < 300) {
+      File file = new File(new URI(this.filePath));
+      JSONObject fileEntry = FileUtils.getFilePlugin().getEntryForFile(file);
+
+      request.receive(file);
+      response.setFileEntry(fileEntry);
+    } else {
+      response.setErrorMessage("There was an error downloading the file");
+    }
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpOperation.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpOperation.java
new file mode 100644
index 0000000..5f17e5d
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpOperation.java
@@ -0,0 +1,25 @@
+package com.silkimen.cordovahttp;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
+
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+import org.json.JSONObject;
+
+class CordovaHttpOperation extends CordovaHttpBase {
+  public CordovaHttpOperation(String method, String url, String serializer, Object data, JSONObject headers,
+      int timeout, boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration,
+      CallbackContext callbackContext) {
+
+    super(method, url, serializer, data, headers, timeout, followRedirects, responseType, tlsConfiguration,
+        callbackContext);
+  }
+
+  public CordovaHttpOperation(String method, String url, JSONObject headers, int timeout, boolean followRedirects,
+      String responseType, TLSConfiguration tlsConfiguration, CallbackContext callbackContext) {
+
+    super(method, url, headers, timeout, followRedirects, responseType, tlsConfiguration, callbackContext);
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpPlugin.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpPlugin.java
new file mode 100644
index 0000000..b7ea1b3
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpPlugin.java
@@ -0,0 +1,167 @@
+package com.silkimen.cordovahttp;
+
+import java.security.KeyStore;
+
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.util.Log;
+import android.util.Base64;
+
+import javax.net.ssl.TrustManagerFactory;
+
+public class CordovaHttpPlugin extends CordovaPlugin {
+  private static final String TAG = "Cordova-Plugin-HTTP";
+
+  private TLSConfiguration tlsConfiguration;
+
+  @Override
+  public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+    super.initialize(cordova, webView);
+
+    this.tlsConfiguration = new TLSConfiguration();
+
+    try {
+      KeyStore store = KeyStore.getInstance("AndroidCAStore");
+      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+
+      store.load(null);
+      tmf.init(store);
+
+      this.tlsConfiguration.setHostnameVerifier(null);
+      this.tlsConfiguration.setTrustManagers(tmf.getTrustManagers());
+    } catch (Exception e) {
+      Log.e(TAG, "An error occured while loading system's CA certificates", e);
+    }
+  }
+
+  @Override
+  public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext)
+      throws JSONException {
+
+    if (action == null) {
+      return false;
+    }
+
+    if ("get".equals(action)) {
+      return this.executeHttpRequestWithoutData(action, args, callbackContext);
+    } else if ("head".equals(action)) {
+      return this.executeHttpRequestWithoutData(action, args, callbackContext);
+    } else if ("delete".equals(action)) {
+      return this.executeHttpRequestWithoutData(action, args, callbackContext);
+    } else if ("post".equals(action)) {
+      return this.executeHttpRequestWithData(action, args, callbackContext);
+    } else if ("put".equals(action)) {
+      return this.executeHttpRequestWithData(action, args, callbackContext);
+    } else if ("patch".equals(action)) {
+      return this.executeHttpRequestWithData(action, args, callbackContext);
+    } else if ("uploadFile".equals(action)) {
+      return this.uploadFile(args, callbackContext);
+    } else if ("downloadFile".equals(action)) {
+      return this.downloadFile(args, callbackContext);
+    } else if ("setServerTrustMode".equals(action)) {
+      return this.setServerTrustMode(args, callbackContext);
+    } else if ("setClientAuthMode".equals(action)) {
+      return this.setClientAuthMode(args, callbackContext);
+    } else {
+      return false;
+    }
+  }
+
+  private boolean executeHttpRequestWithoutData(final String method, final JSONArray args,
+      final CallbackContext callbackContext) throws JSONException {
+
+    String url = args.getString(0);
+    JSONObject headers = args.getJSONObject(1);
+    int timeout = args.getInt(2) * 1000;
+    boolean followRedirect = args.getBoolean(3);
+    String responseType = args.getString(4);
+
+    CordovaHttpOperation request = new CordovaHttpOperation(method.toUpperCase(), url, headers, timeout, followRedirect,
+        responseType, this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(request);
+
+    return true;
+  }
+
+  private boolean executeHttpRequestWithData(final String method, final JSONArray args,
+      final CallbackContext callbackContext) throws JSONException {
+
+    String url = args.getString(0);
+    Object data = args.get(1);
+    String serializer = args.getString(2);
+    JSONObject headers = args.getJSONObject(3);
+    int timeout = args.getInt(4) * 1000;
+    boolean followRedirect = args.getBoolean(5);
+    String responseType = args.getString(6);
+
+    CordovaHttpOperation request = new CordovaHttpOperation(method.toUpperCase(), url, serializer, data, headers,
+        timeout, followRedirect, responseType, this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(request);
+
+    return true;
+  }
+
+  private boolean uploadFile(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
+    String url = args.getString(0);
+    JSONObject headers = args.getJSONObject(1);
+    String filePath = args.getString(2);
+    String uploadName = args.getString(3);
+    int timeout = args.getInt(4) * 1000;
+    boolean followRedirect = args.getBoolean(5);
+    String responseType = args.getString(6);
+
+    CordovaHttpUpload upload = new CordovaHttpUpload(url, headers, filePath, uploadName, timeout, followRedirect,
+        responseType, this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(upload);
+
+    return true;
+  }
+
+  private boolean downloadFile(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
+    String url = args.getString(0);
+    JSONObject headers = args.getJSONObject(1);
+    String filePath = args.getString(2);
+    int timeout = args.getInt(3) * 1000;
+    boolean followRedirect = args.getBoolean(4);
+
+    CordovaHttpDownload download = new CordovaHttpDownload(url, headers, filePath, timeout, followRedirect,
+        this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(download);
+
+    return true;
+  }
+
+  private boolean setServerTrustMode(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
+    CordovaServerTrust runnable = new CordovaServerTrust(args.getString(0), this.cordova.getActivity(),
+        this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(runnable);
+
+    return true;
+  }
+
+  private boolean setClientAuthMode(final JSONArray args, final CallbackContext callbackContext) throws JSONException {
+    byte[] pkcs = args.isNull(2) ? null : Base64.decode(args.getString(2), Base64.DEFAULT);
+
+    CordovaClientAuth runnable = new CordovaClientAuth(args.getString(0), args.isNull(1) ? null : args.getString(1),
+        pkcs, args.getString(3), this.cordova.getActivity(), this.cordova.getActivity().getApplicationContext(),
+        this.tlsConfiguration, callbackContext);
+
+    cordova.getThreadPool().execute(runnable);
+
+    return true;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpResponse.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpResponse.java
new file mode 100644
index 0000000..e6051bf
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpResponse.java
@@ -0,0 +1,100 @@
+package com.silkimen.cordovahttp;
+
+import java.nio.ByteBuffer;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Base64;
+
+class CordovaHttpResponse {
+  private int status;
+  private String url;
+  private Map<String, List<String>> headers;
+  private String body;
+  private byte[] rawData;
+  private JSONObject fileEntry;
+  private boolean hasFailed;
+  private boolean isFileOperation;
+  private boolean isRawResponse;
+  private String error;
+
+  public void setStatus(int status) {
+    this.status = status;
+  }
+
+  public void setUrl(String url) {
+    this.url = url;
+  }
+
+  public void setHeaders(Map<String, List<String>> headers) {
+    this.headers = headers;
+  }
+
+  public void setBody(String body) {
+    this.body = body;
+  }
+
+  public void setData(byte[] rawData) {
+    this.isRawResponse = true;
+    this.rawData = rawData;
+  }
+
+  public void setFileEntry(JSONObject entry) {
+    this.isFileOperation = true;
+    this.fileEntry = entry;
+  }
+
+  public void setErrorMessage(String message) {
+    this.hasFailed = true;
+    this.error = message;
+  }
+
+  public boolean hasFailed() {
+    return this.hasFailed;
+  }
+
+  public JSONObject toJSON() throws JSONException {
+    JSONObject json = new JSONObject();
+
+    json.put("status", this.status);
+    json.put("url", this.url);
+
+    if (this.headers != null && !this.headers.isEmpty()) {
+      json.put("headers", new JSONObject(getFilteredHeaders()));
+    }
+
+    if (this.hasFailed) {
+      json.put("error", this.error);
+    } else if (this.isFileOperation) {
+      json.put("file", this.fileEntry);
+    } else if (this.isRawResponse) {
+      json.put("data", Base64.encodeToString(this.rawData, Base64.DEFAULT));
+    } else {
+      json.put("data", this.body);
+    }
+
+    return json;
+  }
+
+  private Map<String, String> getFilteredHeaders() throws JSONException {
+    Map<String, String> filteredHeaders = new HashMap<String, String>();
+
+    for (Map.Entry<String, List<String>> entry : this.headers.entrySet()) {
+      String key = entry.getKey();
+      List<String> value = entry.getValue();
+
+      if ((key != null) && (!value.isEmpty())) {
+        filteredHeaders.put(key.toLowerCase(), TextUtils.join(", ", value));
+      }
+    }
+
+    return filteredHeaders;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpUpload.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpUpload.java
new file mode 100644
index 0000000..9d74736
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaHttpUpload.java
@@ -0,0 +1,44 @@
+package com.silkimen.cordovahttp;
+
+import android.webkit.MimeTypeMap;
+
+import com.silkimen.http.HttpRequest;
+
+import java.io.File;
+import java.net.URI;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
+
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+import org.json.JSONObject;
+
+class CordovaHttpUpload extends CordovaHttpBase {
+  private String filePath;
+  private String uploadName;
+
+  public CordovaHttpUpload(String url, JSONObject headers, String filePath, String uploadName, int timeout,
+      boolean followRedirects, String responseType, TLSConfiguration tlsConfiguration,
+      CallbackContext callbackContext) {
+
+    super("POST", url, headers, timeout, followRedirects, responseType, tlsConfiguration, callbackContext);
+    this.filePath = filePath;
+    this.uploadName = uploadName;
+  }
+
+  @Override
+  protected void sendBody(HttpRequest request) throws Exception {
+    int filenameIndex = this.filePath.lastIndexOf('/');
+    String filename = this.filePath.substring(filenameIndex + 1);
+
+    int extIndex = this.filePath.lastIndexOf('.');
+    String ext = this.filePath.substring(extIndex + 1);
+
+    MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+    String mimeType = mimeTypeMap.getMimeTypeFromExtension(ext);
+
+    request.part(this.uploadName, filename, mimeType, new File(new URI(this.filePath)));
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaServerTrust.java b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaServerTrust.java
new file mode 100644
index 0000000..822079e
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/cordovahttp/CordovaServerTrust.java
@@ -0,0 +1,124 @@
+package com.silkimen.cordovahttp;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import com.silkimen.http.TLSConfiguration;
+
+import org.apache.cordova.CallbackContext;
+
+import android.app.Activity;
+import android.util.Log;
+import android.content.res.AssetManager;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+class CordovaServerTrust implements Runnable {
+  private static final String TAG = "Cordova-Plugin-HTTP";
+
+  private final TrustManager[] noOpTrustManagers;
+  private final HostnameVerifier noOpVerifier;
+
+  private String mode;
+  private Activity activity;
+  private TLSConfiguration tlsConfiguration;
+  private CallbackContext callbackContext;
+
+  public CordovaServerTrust(final String mode, final Activity activity, final TLSConfiguration configContainer,
+      final CallbackContext callbackContext) {
+
+    this.mode = mode;
+    this.activity = activity;
+    this.tlsConfiguration = configContainer;
+    this.callbackContext = callbackContext;
+
+    this.noOpTrustManagers = new TrustManager[] { new X509TrustManager() {
+      public X509Certificate[] getAcceptedIssuers() {
+        return new X509Certificate[0];
+      }
+
+      public void checkClientTrusted(X509Certificate[] chain, String authType) {
+        // intentionally left blank
+      }
+
+      public void checkServerTrusted(X509Certificate[] chain, String authType) {
+        // intentionally left blank
+      }
+    } };
+
+    this.noOpVerifier = new HostnameVerifier() {
+      public boolean verify(String hostname, SSLSession session) {
+        return true;
+      }
+    };
+  }
+
+  @Override
+  public void run() {
+    try {
+      if ("legacy".equals(this.mode)) {
+        this.tlsConfiguration.setHostnameVerifier(null);
+        this.tlsConfiguration.setTrustManagers(null);
+      } else if ("nocheck".equals(this.mode)) {
+        this.tlsConfiguration.setHostnameVerifier(this.noOpVerifier);
+        this.tlsConfiguration.setTrustManagers(this.noOpTrustManagers);
+      } else if ("pinned".equals(this.mode)) {
+        this.tlsConfiguration.setHostnameVerifier(null);
+        this.tlsConfiguration.setTrustManagers(this.getTrustManagers(this.getCertsFromBundle("www/certificates")));
+      } else {
+        this.tlsConfiguration.setHostnameVerifier(null);
+        this.tlsConfiguration.setTrustManagers(this.getTrustManagers(this.getCertsFromKeyStore("AndroidCAStore")));
+      }
+
+      callbackContext.success();
+    } catch (Exception e) {
+      Log.e(TAG, "An error occured while configuring SSL cert mode", e);
+      callbackContext.error("An error occured while configuring SSL cert mode");
+    }
+  }
+
+  private TrustManager[] getTrustManagers(KeyStore store) throws GeneralSecurityException {
+    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+    tmf.init(store);
+
+    return tmf.getTrustManagers();
+  }
+
+  private KeyStore getCertsFromBundle(String path) throws GeneralSecurityException, IOException {
+    AssetManager assetManager = this.activity.getAssets();
+    String[] files = assetManager.list(path);
+
+    CertificateFactory cf = CertificateFactory.getInstance("X.509");
+    String keyStoreType = KeyStore.getDefaultType();
+    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+
+    keyStore.load(null, null);
+
+    for (int i = 0; i < files.length; i++) {
+      int index = files[i].lastIndexOf('.');
+
+      if (index == -1 || !files[i].substring(index).equals(".cer")) {
+        continue;
+      }
+
+      keyStore.setCertificateEntry("CA" + i, cf.generateCertificate(assetManager.open(path + "/" + files[i])));
+    }
+
+    return keyStore;
+  }
+
+  private KeyStore getCertsFromKeyStore(String storeType) throws GeneralSecurityException, IOException {
+    KeyStore store = KeyStore.getInstance(storeType);
+    store.load(null);
+
+    return store;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/HttpBodyDecoder.java b/platforms/android/app/src/main/java/com/silkimen/http/HttpBodyDecoder.java
new file mode 100644
index 0000000..92d69e2
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/HttpBodyDecoder.java
@@ -0,0 +1,55 @@
+package com.silkimen.http;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+
+public class HttpBodyDecoder {
+  private static final String[] ACCEPTED_CHARSETS = new String[] { "UTF-8", "ISO-8859-1" };
+
+  public static String decodeBody(byte[] body, String charsetName)
+      throws CharacterCodingException, MalformedInputException {
+
+    return decodeBody(ByteBuffer.wrap(body), charsetName);
+  }
+
+  public static String decodeBody(ByteBuffer body, String charsetName)
+      throws CharacterCodingException, MalformedInputException {
+
+    if (charsetName == null) {
+      return tryDecodeByteBuffer(body);
+    } else {
+      return decodeByteBuffer(body, charsetName);
+    }
+  }
+
+  private static String tryDecodeByteBuffer(ByteBuffer buffer)
+      throws CharacterCodingException, MalformedInputException {
+
+    for (int i = 0; i < ACCEPTED_CHARSETS.length - 1; i++) {
+      try {
+        return decodeByteBuffer(buffer, ACCEPTED_CHARSETS[i]);
+      } catch (MalformedInputException e) {
+        continue;
+      } catch (CharacterCodingException e) {
+        continue;
+      }
+    }
+
+    return decodeBody(buffer, ACCEPTED_CHARSETS[ACCEPTED_CHARSETS.length - 1]);
+  }
+
+  private static String decodeByteBuffer(ByteBuffer buffer, String charsetName)
+      throws CharacterCodingException, MalformedInputException {
+
+    return createCharsetDecoder(charsetName).decode(buffer).toString();
+  }
+
+  private static CharsetDecoder createCharsetDecoder(String charsetName) {
+    return Charset.forName(charsetName).newDecoder().onMalformedInput(CodingErrorAction.REPORT)
+        .onUnmappableCharacter(CodingErrorAction.REPORT);
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/HttpRequest.java b/platforms/android/app/src/main/java/com/silkimen/http/HttpRequest.java
new file mode 100644
index 0000000..7e638bb
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/HttpRequest.java
@@ -0,0 +1,3095 @@
+/*
+ * Copyright (c) 2014 Kevin Sawicki <kevinsawicki@gmail.com>
+ * modified by contributors of cordova-plugin-advanced-http
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+package com.silkimen.http;
+
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static java.net.Proxy.Type.HTTP;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.security.AccessController;
+import java.security.GeneralSecurityException;
+import java.security.PrivilegedAction;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.zip.GZIPInputStream;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * A fluid interface for making HTTP requests using an underlying
+ * {@link HttpURLConnection} (or sub-class).
+ * <p>
+ * Each instance supports making a single request and cannot be reused for
+ * further requests.
+ */
+public class HttpRequest {
+
+  /**
+   * 'UTF-8' charset name
+   */
+  public static final String CHARSET_UTF8 = "UTF-8";
+
+  /**
+   * 'application/x-www-form-urlencoded' content type header value
+   */
+  public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
+
+  /**
+   * 'application/json' content type header value
+   */
+  public static final String CONTENT_TYPE_JSON = "application/json";
+
+  /**
+   * 'gzip' encoding header value
+   */
+  public static final String ENCODING_GZIP = "gzip";
+
+  /**
+   * 'Accept' header name
+   */
+  public static final String HEADER_ACCEPT = "Accept";
+
+  /**
+   * 'Accept-Charset' header name
+   */
+  public static final String HEADER_ACCEPT_CHARSET = "Accept-Charset";
+
+  /**
+   * 'Accept-Encoding' header name
+   */
+  public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
+
+  /**
+   * 'Authorization' header name
+   */
+  public static final String HEADER_AUTHORIZATION = "Authorization";
+
+  /**
+   * 'Cache-Control' header name
+   */
+  public static final String HEADER_CACHE_CONTROL = "Cache-Control";
+
+  /**
+   * 'Content-Encoding' header name
+   */
+  public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
+
+  /**
+   * 'Content-Length' header name
+   */
+  public static final String HEADER_CONTENT_LENGTH = "Content-Length";
+
+  /**
+   * 'Content-Type' header name
+   */
+  public static final String HEADER_CONTENT_TYPE = "Content-Type";
+
+  /**
+   * 'Date' header name
+   */
+  public static final String HEADER_DATE = "Date";
+
+  /**
+   * 'ETag' header name
+   */
+  public static final String HEADER_ETAG = "ETag";
+
+  /**
+   * 'Expires' header name
+   */
+  public static final String HEADER_EXPIRES = "Expires";
+
+  /**
+   * 'If-None-Match' header name
+   */
+  public static final String HEADER_IF_NONE_MATCH = "If-None-Match";
+
+  /**
+   * 'Last-Modified' header name
+   */
+  public static final String HEADER_LAST_MODIFIED = "Last-Modified";
+
+  /**
+   * 'Location' header name
+   */
+  public static final String HEADER_LOCATION = "Location";
+
+  /**
+   * 'Proxy-Authorization' header name
+   */
+  public static final String HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization";
+
+  /**
+   * 'Referer' header name
+   */
+  public static final String HEADER_REFERER = "Referer";
+
+  /**
+   * 'Server' header name
+   */
+  public static final String HEADER_SERVER = "Server";
+
+  /**
+   * 'User-Agent' header name
+   */
+  public static final String HEADER_USER_AGENT = "User-Agent";
+
+  /**
+   * 'DELETE' request method
+   */
+  public static final String METHOD_DELETE = "DELETE";
+
+  /**
+   * 'GET' request method
+   */
+  public static final String METHOD_GET = "GET";
+
+  /**
+   * 'HEAD' request method
+   */
+  public static final String METHOD_HEAD = "HEAD";
+
+  /**
+   * 'OPTIONS' options method
+   */
+  public static final String METHOD_OPTIONS = "OPTIONS";
+
+  /**
+   * 'POST' request method
+   */
+  public static final String METHOD_POST = "POST";
+
+  /**
+   * 'PUT' request method
+   */
+  public static final String METHOD_PUT = "PUT";
+
+  /**
+   * 'TRACE' request method
+   */
+  public static final String METHOD_TRACE = "TRACE";
+
+  /**
+   * 'charset' header value parameter
+   */
+  public static final String PARAM_CHARSET = "charset";
+
+  private static final String BOUNDARY = "00content0boundary00";
+
+  private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data; boundary=" + BOUNDARY;
+
+  private static final String CRLF = "\r\n";
+
+  private static final String[] EMPTY_STRINGS = new String[0];
+
+  private static String getValidCharset(final String charset) {
+    if (charset != null && charset.length() > 0)
+      return charset;
+    else
+      return CHARSET_UTF8;
+  }
+
+  private static StringBuilder addPathSeparator(final String baseUrl, final StringBuilder result) {
+    // Add trailing slash if the base URL doesn't have any path segments.
+    //
+    // The following test is checking for the last slash not being part of
+    // the protocol to host separator: '://'.
+    if (baseUrl.indexOf(':') + 2 == baseUrl.lastIndexOf('/'))
+      result.append('/');
+    return result;
+  }
+
+  private static StringBuilder addParamPrefix(final String baseUrl, final StringBuilder result) {
+    // Add '?' if missing and add '&' if params already exist in base url
+    final int queryStart = baseUrl.indexOf('?');
+    final int lastChar = result.length() - 1;
+    if (queryStart == -1)
+      result.append('?');
+    else if (queryStart < lastChar && baseUrl.charAt(lastChar) != '&')
+      result.append('&');
+    return result;
+  }
+
+  private static StringBuilder addParam(final Object key, Object value, final StringBuilder result) {
+    if (value != null && value.getClass().isArray())
+      value = arrayToList(value);
+
+    if (value instanceof Iterable<?>) {
+      Iterator<?> iterator = ((Iterable<?>) value).iterator();
+      while (iterator.hasNext()) {
+        result.append(key);
+        result.append("[]=");
+        Object element = iterator.next();
+        if (element != null)
+          result.append(element);
+        if (iterator.hasNext())
+          result.append("&");
+      }
+    } else {
+      result.append(key);
+      result.append("=");
+      if (value != null)
+        result.append(value);
+    }
+
+    return result;
+  }
+
+  /**
+   * Creates {@link HttpURLConnection HTTP connections} for {@link URL urls}.
+   */
+  public interface ConnectionFactory {
+    /**
+     * Open an {@link HttpURLConnection} for the specified {@link URL}.
+     *
+     * @throws IOException
+     */
+    HttpURLConnection create(URL url) throws IOException;
+
+    /**
+     * Open an {@link HttpURLConnection} for the specified {@link URL} and
+     * {@link Proxy}.
+     *
+     * @throws IOException
+     */
+    HttpURLConnection create(URL url, Proxy proxy) throws IOException;
+
+    /**
+     * A {@link ConnectionFactory} which uses the built-in
+     * {@link URL#openConnection()}
+     */
+    ConnectionFactory DEFAULT = new ConnectionFactory() {
+      public HttpURLConnection create(URL url) throws IOException {
+        return (HttpURLConnection) url.openConnection();
+      }
+
+      public HttpURLConnection create(URL url, Proxy proxy) throws IOException {
+        return (HttpURLConnection) url.openConnection(proxy);
+      }
+    };
+  }
+
+  private static ConnectionFactory CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
+
+  /**
+   * Specify the {@link ConnectionFactory} used to create new requests.
+   */
+  public static void setConnectionFactory(final ConnectionFactory connectionFactory) {
+    if (connectionFactory == null)
+      CONNECTION_FACTORY = ConnectionFactory.DEFAULT;
+    else
+      CONNECTION_FACTORY = connectionFactory;
+  }
+
+  /**
+   * Callback interface for reporting upload progress for a request.
+   */
+  public interface UploadProgress {
+    /**
+     * Callback invoked as data is uploaded by the request.
+     *
+     * @param uploaded The number of bytes already uploaded
+     * @param total    The total number of bytes that will be uploaded or -1 if the
+     *                 length is unknown.
+     */
+    void onUpload(long uploaded, long total);
+
+    UploadProgress DEFAULT = new UploadProgress() {
+      public void onUpload(long uploaded, long total) {
+      }
+    };
+  }
+
+  /**
+   * <p>
+   * Encodes and decodes to and from Base64 notation.
+   * </p>
+   * <p>
+   * I am placing this code in the Public Domain. Do with it as you will. This
+   * software comes with no guarantees or warranties but with plenty of
+   * well-wishing instead! Please visit
+   * <a href="http://iharder.net/base64">http://iharder.net/base64</a>
+   * periodically to check for updates or to contribute improvements.
+   * </p>
+   *
+   * @author Robert Harder
+   * @author rob@iharder.net
+   * @version 2.3.7
+   */
+  public static class Base64 {
+
+    /** The equals sign (=) as a byte. */
+    private final static byte EQUALS_SIGN = (byte) '=';
+
+    /** Preferred encoding. */
+    private final static String PREFERRED_ENCODING = "US-ASCII";
+
+    /** The 64 valid Base64 values. */
+    private final static byte[] _STANDARD_ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E',
+        (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
+        (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W',
+        (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
+        (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
+        (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x',
+        (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
+        (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
+
+    /** Defeats instantiation. */
+    private Base64() {
+    }
+
+    /**
+     * <p>
+     * Encodes up to three bytes of the array <var>source</var> and writes the
+     * resulting four Base64 bytes to <var>destination</var>. The source and
+     * destination arrays can be manipulated anywhere along their length by
+     * specifying <var>srcOffset</var> and <var>destOffset</var>. This method does
+     * not check to make sure your arrays are large enough to accomodate
+     * <var>srcOffset</var> + 3 for the <var>source</var> array or
+     * <var>destOffset</var> + 4 for the <var>destination</var> array. The actual
+     * number of significant bytes in your array is given by <var>numSigBytes</var>.
+     * </p>
+     * <p>
+     * This is the lowest level of the encoding methods with all possible
+     * parameters.
+     * </p>
+     *
+     * @param source      the array to convert
+     * @param srcOffset   the index where conversion begins
+     * @param numSigBytes the number of significant bytes in your array
+     * @param destination the array to hold the conversion
+     * @param destOffset  the index where output will be put
+     * @return the <var>destination</var> array
+     * @since 1.3
+     */
+    private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination,
+        int destOffset) {
+
+      byte[] ALPHABET = _STANDARD_ALPHABET;
+
+      int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
+          | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
+          | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
+
+      switch (numSigBytes) {
+      case 3:
+        destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+        destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+        destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+        destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
+        return destination;
+
+      case 2:
+        destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+        destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+        destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+        destination[destOffset + 3] = EQUALS_SIGN;
+        return destination;
+
+      case 1:
+        destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+        destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+        destination[destOffset + 2] = EQUALS_SIGN;
+        destination[destOffset + 3] = EQUALS_SIGN;
+        return destination;
+
+      default:
+        return destination;
+      }
+    }
+
+    /**
+     * Encode string as a byte array in Base64 annotation.
+     *
+     * @param string
+     * @return The Base64-encoded data as a string
+     */
+    public static String encode(String string) {
+      byte[] bytes;
+      try {
+        bytes = string.getBytes(PREFERRED_ENCODING);
+      } catch (UnsupportedEncodingException e) {
+        bytes = string.getBytes();
+      }
+      return encodeBytes(bytes);
+    }
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     *
+     * @param source The data to convert
+     * @return The Base64-encoded data as a String
+     * @throws NullPointerException     if source array is null
+     * @throws IllegalArgumentException if source array, offset, or length are
+     *                                  invalid
+     * @since 2.0
+     */
+    public static String encodeBytes(byte[] source) {
+      return encodeBytes(source, 0, source.length);
+    }
+
+    /**
+     * Encodes a byte array into Base64 notation.
+     *
+     * @param source The data to convert
+     * @param off    Offset in array where conversion should begin
+     * @param len    Length of data to convert
+     * @return The Base64-encoded data as a String
+     * @throws NullPointerException     if source array is null
+     * @throws IllegalArgumentException if source array, offset, or length are
+     *                                  invalid
+     * @since 2.0
+     */
+    public static String encodeBytes(byte[] source, int off, int len) {
+      byte[] encoded = encodeBytesToBytes(source, off, len);
+      try {
+        return new String(encoded, PREFERRED_ENCODING);
+      } catch (UnsupportedEncodingException uue) {
+        return new String(encoded);
+      }
+    }
+
+    /**
+     * Similar to {@link #encodeBytes(byte[], int, int)} but returns a byte array
+     * instead of instantiating a String. This is more efficient if you're working
+     * with I/O streams and have large data sets to encode.
+     *
+     *
+     * @param source The data to convert
+     * @param off    Offset in array where conversion should begin
+     * @param len    Length of data to convert
+     * @return The Base64-encoded data as a String if there is an error
+     * @throws NullPointerException     if source array is null
+     * @throws IllegalArgumentException if source array, offset, or length are
+     *                                  invalid
+     * @since 2.3.1
+     */
+    public static byte[] encodeBytesToBytes(byte[] source, int off, int len) {
+
+      if (source == null)
+        throw new NullPointerException("Cannot serialize a null array.");
+
+      if (off < 0)
+        throw new IllegalArgumentException("Cannot have negative offset: " + off);
+
+      if (len < 0)
+        throw new IllegalArgumentException("Cannot have length offset: " + len);
+
+      if (off + len > source.length)
+        throw new IllegalArgumentException(String
+            .format("Cannot have offset of %d and length of %d with array of length %d", off, len, source.length));
+
+      // Bytes needed for actual encoding
+      int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0);
+
+      byte[] outBuff = new byte[encLen];
+
+      int d = 0;
+      int e = 0;
+      int len2 = len - 2;
+      for (; d < len2; d += 3, e += 4)
+        encode3to4(source, d + off, 3, outBuff, e);
+
+      if (d < len) {
+        encode3to4(source, d + off, len - d, outBuff, e);
+        e += 4;
+      }
+
+      if (e <= outBuff.length - 1) {
+        byte[] finalOut = new byte[e];
+        System.arraycopy(outBuff, 0, finalOut, 0, e);
+        return finalOut;
+      } else
+        return outBuff;
+    }
+  }
+
+  /**
+   * HTTP request exception whose cause is always an {@link IOException}
+   */
+  public static class HttpRequestException extends RuntimeException {
+
+    private static final long serialVersionUID = -1170466989781746231L;
+
+    /**
+     * Create a new HttpRequestException with the given cause
+     *
+     * @param cause
+     */
+    public HttpRequestException(final IOException cause) {
+      super(cause);
+    }
+
+    /**
+     * Get {@link IOException} that triggered this request exception
+     *
+     * @return {@link IOException} cause
+     */
+    @Override
+    public IOException getCause() {
+      return (IOException) super.getCause();
+    }
+  }
+
+  /**
+   * Operation that handles executing a callback once complete and handling nested
+   * exceptions
+   *
+   * @param <V>
+   */
+  protected static abstract class Operation<V> implements Callable<V> {
+
+    /**
+     * Run operation
+     *
+     * @return result
+     * @throws HttpRequestException
+     * @throws IOException
+     */
+    protected abstract V run() throws HttpRequestException, IOException;
+
+    /**
+     * Operation complete callback
+     *
+     * @throws IOException
+     */
+    protected abstract void done() throws IOException;
+
+    public V call() throws HttpRequestException {
+      boolean thrown = false;
+      try {
+        return run();
+      } catch (HttpRequestException e) {
+        thrown = true;
+        throw e;
+      } catch (IOException e) {
+        thrown = true;
+        throw new HttpRequestException(e);
+      } finally {
+        try {
+          done();
+        } catch (IOException e) {
+          if (!thrown)
+            throw new HttpRequestException(e);
+        }
+      }
+    }
+  }
+
+  /**
+   * Class that ensures a {@link Closeable} gets closed with proper exception
+   * handling.
+   *
+   * @param <V>
+   */
+  protected static abstract class CloseOperation<V> extends Operation<V> {
+
+    private final Closeable closeable;
+
+    private final boolean ignoreCloseExceptions;
+
+    /**
+     * Create closer for operation
+     *
+     * @param closeable
+     * @param ignoreCloseExceptions
+     */
+    protected CloseOperation(final Closeable closeable, final boolean ignoreCloseExceptions) {
+      this.closeable = closeable;
+      this.ignoreCloseExceptions = ignoreCloseExceptions;
+    }
+
+    @Override
+    protected void done() throws IOException {
+      if (closeable instanceof Flushable)
+        ((Flushable) closeable).flush();
+      if (ignoreCloseExceptions)
+        try {
+          closeable.close();
+        } catch (IOException e) {
+          // Ignored
+        }
+      else
+        closeable.close();
+    }
+  }
+
+  /**
+   * Class that and ensures a {@link Flushable} gets flushed with proper exception
+   * handling.
+   *
+   * @param <V>
+   */
+  protected static abstract class FlushOperation<V> extends Operation<V> {
+
+    private final Flushable flushable;
+
+    /**
+     * Create flush operation
+     *
+     * @param flushable
+     */
+    protected FlushOperation(final Flushable flushable) {
+      this.flushable = flushable;
+    }
+
+    @Override
+    protected void done() throws IOException {
+      flushable.flush();
+    }
+  }
+
+  /**
+   * Request output stream
+   */
+  public static class RequestOutputStream extends BufferedOutputStream {
+
+    private final CharsetEncoder encoder;
+
+    /**
+     * Create request output stream
+     *
+     * @param stream
+     * @param charset
+     * @param bufferSize
+     */
+    public RequestOutputStream(final OutputStream stream, final String charset, final int bufferSize) {
+      super(stream, bufferSize);
+
+      encoder = Charset.forName(getValidCharset(charset)).newEncoder();
+    }
+
+    /**
+     * Write string to stream
+     *
+     * @param value
+     * @return this stream
+     * @throws IOException
+     */
+    public RequestOutputStream write(final String value) throws IOException {
+      final ByteBuffer bytes = encoder.encode(CharBuffer.wrap(value));
+
+      super.write(bytes.array(), 0, bytes.limit());
+
+      return this;
+    }
+  }
+
+  /**
+   * Represents array of any type as list of objects so we can easily iterate over
+   * it
+   *
+   * @param array of elements
+   * @return list with the same elements
+   */
+  private static List<Object> arrayToList(final Object array) {
+    if (array instanceof Object[])
+      return Arrays.asList((Object[]) array);
+
+    List<Object> result = new ArrayList<Object>();
+    // Arrays of the primitive types can't be cast to array of Object, so this:
+    if (array instanceof int[])
+      for (int value : (int[]) array)
+        result.add(value);
+    else if (array instanceof boolean[])
+      for (boolean value : (boolean[]) array)
+        result.add(value);
+    else if (array instanceof long[])
+      for (long value : (long[]) array)
+        result.add(value);
+    else if (array instanceof float[])
+      for (float value : (float[]) array)
+        result.add(value);
+    else if (array instanceof double[])
+      for (double value : (double[]) array)
+        result.add(value);
+    else if (array instanceof short[])
+      for (short value : (short[]) array)
+        result.add(value);
+    else if (array instanceof byte[])
+      for (byte value : (byte[]) array)
+        result.add(value);
+    else if (array instanceof char[])
+      for (char value : (char[]) array)
+        result.add(value);
+    return result;
+  }
+
+  /**
+   * Encode the given URL as an ASCII {@link String}
+   * <p>
+   * This method ensures the path and query segments of the URL are properly
+   * encoded such as ' ' characters being encoded to '%20' or any UTF-8 characters
+   * that are non-ASCII. No encoding of URLs is done by default by the
+   * {@link HttpRequest} constructors and so if URL encoding is needed this method
+   * should be called before calling the {@link HttpRequest} constructor.
+   *
+   * @param url
+   * @return encoded URL
+   * @throws HttpRequestException
+   */
+  public static String encode(final CharSequence url) throws HttpRequestException {
+    URL parsed;
+    try {
+      parsed = new URL(url.toString());
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+
+    String host = parsed.getHost();
+    int port = parsed.getPort();
+    if (port != -1)
+      host = host + ':' + Integer.toString(port);
+
+    try {
+      String encoded = new URI(parsed.getProtocol(), host, parsed.getPath(), parsed.getQuery(), null).toASCIIString();
+      int paramsStart = encoded.indexOf('?');
+      if (paramsStart > 0 && paramsStart + 1 < encoded.length())
+        encoded = encoded.substring(0, paramsStart + 1) + encoded.substring(paramsStart + 1).replace("+", "%2B");
+      return encoded;
+    } catch (URISyntaxException e) {
+      IOException io = new IOException("Parsing URI failed");
+      io.initCause(e);
+      throw new HttpRequestException(io);
+    }
+  }
+
+  /**
+   * Append given map as query parameters to the base URL
+   * <p>
+   * Each map entry's key will be a parameter name and the value's
+   * {@link Object#toString()} will be the parameter value.
+   *
+   * @param url
+   * @param params
+   * @return URL with appended query params
+   */
+  public static String append(final CharSequence url, final Map<?, ?> params) {
+    final String baseUrl = url.toString();
+    if (params == null || params.isEmpty())
+      return baseUrl;
+
+    final StringBuilder result = new StringBuilder(baseUrl);
+
+    addPathSeparator(baseUrl, result);
+    addParamPrefix(baseUrl, result);
+
+    Entry<?, ?> entry;
+    Iterator<?> iterator = params.entrySet().iterator();
+    entry = (Entry<?, ?>) iterator.next();
+    addParam(entry.getKey().toString(), entry.getValue(), result);
+
+    while (iterator.hasNext()) {
+      result.append('&');
+      entry = (Entry<?, ?>) iterator.next();
+      addParam(entry.getKey().toString(), entry.getValue(), result);
+    }
+
+    return result.toString();
+  }
+
+  /**
+   * Append given name/value pairs as query parameters to the base URL
+   * <p>
+   * The params argument is interpreted as a sequence of name/value pairs so the
+   * given number of params must be divisible by 2.
+   *
+   * @param url
+   * @param params name/value pairs
+   * @return URL with appended query params
+   */
+  public static String append(final CharSequence url, final Object... params) {
+    final String baseUrl = url.toString();
+    if (params == null || params.length == 0)
+      return baseUrl;
+
+    if (params.length % 2 != 0)
+      throw new IllegalArgumentException("Must specify an even number of parameter names/values");
+
+    final StringBuilder result = new StringBuilder(baseUrl);
+
+    addPathSeparator(baseUrl, result);
+    addParamPrefix(baseUrl, result);
+
+    addParam(params[0], params[1], result);
+
+    for (int i = 2; i < params.length; i += 2) {
+      result.append('&');
+      addParam(params[i], params[i + 1], result);
+    }
+
+    return result.toString();
+  }
+
+  /**
+   * Start a 'GET' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest get(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_GET);
+  }
+
+  /**
+   * Start a 'GET' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest get(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_GET);
+  }
+
+  /**
+   * Start a 'GET' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param params  The query parameters to include as part of the baseUrl
+   * @param encode  true to encode the full URL
+   *
+   * @see #append(CharSequence, Map)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest get(final CharSequence baseUrl, final Map<?, ?> params, final boolean encode) {
+    String url = append(baseUrl, params);
+    return get(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'GET' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param encode  true to encode the full URL
+   * @param params  the name/value query parameter pairs to include as part of the
+   *                baseUrl
+   *
+   * @see #append(CharSequence, Object...)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest get(final CharSequence baseUrl, final boolean encode, final Object... params) {
+    String url = append(baseUrl, params);
+    return get(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'POST' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest post(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_POST);
+  }
+
+  /**
+   * Start a 'POST' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest post(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_POST);
+  }
+
+  /**
+   * Start a 'POST' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param params  the query parameters to include as part of the baseUrl
+   * @param encode  true to encode the full URL
+   *
+   * @see #append(CharSequence, Map)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest post(final CharSequence baseUrl, final Map<?, ?> params, final boolean encode) {
+    String url = append(baseUrl, params);
+    return post(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'POST' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param encode  true to encode the full URL
+   * @param params  the name/value query parameter pairs to include as part of the
+   *                baseUrl
+   *
+   * @see #append(CharSequence, Object...)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest post(final CharSequence baseUrl, final boolean encode, final Object... params) {
+    String url = append(baseUrl, params);
+    return post(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'PUT' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest put(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_PUT);
+  }
+
+  /**
+   * Start a 'PUT' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest put(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_PUT);
+  }
+
+  /**
+   * Start a 'PUT' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param params  the query parameters to include as part of the baseUrl
+   * @param encode  true to encode the full URL
+   *
+   * @see #append(CharSequence, Map)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest put(final CharSequence baseUrl, final Map<?, ?> params, final boolean encode) {
+    String url = append(baseUrl, params);
+    return put(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'PUT' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param encode  true to encode the full URL
+   * @param params  the name/value query parameter pairs to include as part of the
+   *                baseUrl
+   *
+   * @see #append(CharSequence, Object...)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest put(final CharSequence baseUrl, final boolean encode, final Object... params) {
+    String url = append(baseUrl, params);
+    return put(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'DELETE' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest delete(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_DELETE);
+  }
+
+  /**
+   * Start a 'DELETE' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest delete(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_DELETE);
+  }
+
+  /**
+   * Start a 'DELETE' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param params  The query parameters to include as part of the baseUrl
+   * @param encode  true to encode the full URL
+   *
+   * @see #append(CharSequence, Map)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest delete(final CharSequence baseUrl, final Map<?, ?> params, final boolean encode) {
+    String url = append(baseUrl, params);
+    return delete(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'DELETE' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param encode  true to encode the full URL
+   * @param params  the name/value query parameter pairs to include as part of the
+   *                baseUrl
+   *
+   * @see #append(CharSequence, Object...)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest delete(final CharSequence baseUrl, final boolean encode, final Object... params) {
+    String url = append(baseUrl, params);
+    return delete(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'HEAD' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest head(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_HEAD);
+  }
+
+  /**
+   * Start a 'HEAD' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest head(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_HEAD);
+  }
+
+  /**
+   * Start a 'HEAD' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param params  The query parameters to include as part of the baseUrl
+   * @param encode  true to encode the full URL
+   *
+   * @see #append(CharSequence, Map)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest head(final CharSequence baseUrl, final Map<?, ?> params, final boolean encode) {
+    String url = append(baseUrl, params);
+    return head(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start a 'GET' request to the given URL along with the query params
+   *
+   * @param baseUrl
+   * @param encode  true to encode the full URL
+   * @param params  the name/value query parameter pairs to include as part of the
+   *                baseUrl
+   *
+   * @see #append(CharSequence, Object...)
+   * @see #encode(CharSequence)
+   *
+   * @return request
+   */
+  public static HttpRequest head(final CharSequence baseUrl, final boolean encode, final Object... params) {
+    String url = append(baseUrl, params);
+    return head(encode ? encode(url) : url);
+  }
+
+  /**
+   * Start an 'OPTIONS' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest options(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_OPTIONS);
+  }
+
+  /**
+   * Start an 'OPTIONS' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest options(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_OPTIONS);
+  }
+
+  /**
+   * Start a 'TRACE' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest trace(final CharSequence url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_TRACE);
+  }
+
+  /**
+   * Start a 'TRACE' request to the given URL
+   *
+   * @param url
+   * @return request
+   * @throws HttpRequestException
+   */
+  public static HttpRequest trace(final URL url) throws HttpRequestException {
+    return new HttpRequest(url, METHOD_TRACE);
+  }
+
+  /**
+   * Set the 'http.keepAlive' property to the given value.
+   * <p>
+   * This setting will apply to all requests.
+   *
+   * @param keepAlive
+   */
+  public static void keepAlive(final boolean keepAlive) {
+    setProperty("http.keepAlive", Boolean.toString(keepAlive));
+  }
+
+  /**
+   * Set the 'http.maxConnections' property to the given value.
+   * <p>
+   * This setting will apply to all requests.
+   *
+   * @param maxConnections
+   */
+  public static void maxConnections(final int maxConnections) {
+    setProperty("http.maxConnections", Integer.toString(maxConnections));
+  }
+
+  /**
+   * Set the 'http.proxyHost' and 'https.proxyHost' properties to the given host
+   * value.
+   * <p>
+   * This setting will apply to all requests.
+   *
+   * @param host
+   */
+  public static void proxyHost(final String host) {
+    setProperty("http.proxyHost", host);
+    setProperty("https.proxyHost", host);
+  }
+
+  /**
+   * Set the 'http.proxyPort' and 'https.proxyPort' properties to the given port
+   * number.
+   * <p>
+   * This setting will apply to all requests.
+   *
+   * @param port
+   */
+  public static void proxyPort(final int port) {
+    final String portValue = Integer.toString(port);
+    setProperty("http.proxyPort", portValue);
+    setProperty("https.proxyPort", portValue);
+  }
+
+  /**
+   * Set the 'http.nonProxyHosts' property to the given host values.
+   * <p>
+   * Hosts will be separated by a '|' character.
+   * <p>
+   * This setting will apply to all requests.
+   *
+   * @param hosts
+   */
+  public static void nonProxyHosts(final String... hosts) {
+    if (hosts != null && hosts.length > 0) {
+      StringBuilder separated = new StringBuilder();
+      int last = hosts.length - 1;
+      for (int i = 0; i < last; i++)
+        separated.append(hosts[i]).append('|');
+      separated.append(hosts[last]);
+      setProperty("http.nonProxyHosts", separated.toString());
+    } else
+      setProperty("http.nonProxyHosts", null);
+  }
+
+  /**
+   * Set property to given value.
+   * <p>
+   * Specifying a null value will cause the property to be cleared
+   *
+   * @param name
+   * @param value
+   * @return previous value
+   */
+  private static String setProperty(final String name, final String value) {
+    final PrivilegedAction<String> action;
+    if (value != null)
+      action = new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.setProperty(name, value);
+        }
+      };
+    else
+      action = new PrivilegedAction<String>() {
+
+        public String run() {
+          return System.clearProperty(name);
+        }
+      };
+    return AccessController.doPrivileged(action);
+  }
+
+  private HttpURLConnection connection = null;
+
+  private final URL url;
+
+  private final String requestMethod;
+
+  private RequestOutputStream output;
+
+  private boolean multipart;
+
+  private boolean form;
+
+  private boolean ignoreCloseExceptions = true;
+
+  private boolean uncompress = false;
+
+  private int bufferSize = 8192;
+
+  private long totalSize = -1;
+
+  private long totalWritten = 0;
+
+  private String httpProxyHost;
+
+  private int httpProxyPort;
+
+  private UploadProgress progress = UploadProgress.DEFAULT;
+
+  /**
+   * Create HTTP connection wrapper
+   *
+   * @param url    Remote resource URL.
+   * @param method HTTP request method (e.g., "GET", "POST").
+   * @throws HttpRequestException
+   */
+  public HttpRequest(final CharSequence url, final String method) throws HttpRequestException {
+    try {
+      this.url = new URL(url.toString());
+    } catch (MalformedURLException e) {
+      throw new HttpRequestException(e);
+    }
+    this.requestMethod = method;
+  }
+
+  /**
+   * Create HTTP connection wrapper
+   *
+   * @param url    Remote resource URL.
+   * @param method HTTP request method (e.g., "GET", "POST").
+   * @throws HttpRequestException
+   */
+  public HttpRequest(final URL url, final String method) throws HttpRequestException {
+    this.url = url;
+    this.requestMethod = method;
+  }
+
+  private Proxy createProxy() {
+    return new Proxy(HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort));
+  }
+
+  private HttpURLConnection createConnection() {
+    try {
+      final HttpURLConnection connection;
+      if (httpProxyHost != null)
+        connection = CONNECTION_FACTORY.create(url, createProxy());
+      else
+        connection = CONNECTION_FACTORY.create(url);
+      connection.setRequestMethod(requestMethod);
+      return connection;
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return method() + ' ' + url();
+  }
+
+  /**
+   * Get underlying connection
+   *
+   * @return connection
+   */
+  public HttpURLConnection getConnection() {
+    if (connection == null)
+      connection = createConnection();
+    return connection;
+  }
+
+  /**
+   * Set whether or not to ignore exceptions that occur from calling
+   * {@link Closeable#close()}
+   * <p>
+   * The default value of this setting is <code>true</code>
+   *
+   * @param ignore
+   * @return this request
+   */
+  public HttpRequest ignoreCloseExceptions(final boolean ignore) {
+    ignoreCloseExceptions = ignore;
+    return this;
+  }
+
+  /**
+   * Get whether or not exceptions thrown by {@link Closeable#close()} are ignored
+   *
+   * @return true if ignoring, false if throwing
+   */
+  public boolean ignoreCloseExceptions() {
+    return ignoreCloseExceptions;
+  }
+
+  /**
+   * Get the status code of the response
+   *
+   * @return the response code
+   * @throws HttpRequestException
+   */
+  public int code() throws HttpRequestException {
+    try {
+      closeOutput();
+      return getConnection().getResponseCode();
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Set the value of the given {@link AtomicInteger} to the status code of the
+   * response
+   *
+   * @param output
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest code(final AtomicInteger output) throws HttpRequestException {
+    output.set(code());
+    return this;
+  }
+
+  /**
+   * Is the response code a 200 OK?
+   *
+   * @return true if 200, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean ok() throws HttpRequestException {
+    return HTTP_OK == code();
+  }
+
+  /**
+   * Is the response code a 201 Created?
+   *
+   * @return true if 201, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean created() throws HttpRequestException {
+    return HTTP_CREATED == code();
+  }
+
+  /**
+   * Is the response code a 204 No Content?
+   *
+   * @return true if 204, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean noContent() throws HttpRequestException {
+    return HTTP_NO_CONTENT == code();
+  }
+
+  /**
+   * Is the response code a 500 Internal Server Error?
+   *
+   * @return true if 500, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean serverError() throws HttpRequestException {
+    return HTTP_INTERNAL_ERROR == code();
+  }
+
+  /**
+   * Is the response code a 400 Bad Request?
+   *
+   * @return true if 400, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean badRequest() throws HttpRequestException {
+    return HTTP_BAD_REQUEST == code();
+  }
+
+  /**
+   * Is the response code a 404 Not Found?
+   *
+   * @return true if 404, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean notFound() throws HttpRequestException {
+    return HTTP_NOT_FOUND == code();
+  }
+
+  /**
+   * Is the response code a 304 Not Modified?
+   *
+   * @return true if 304, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean notModified() throws HttpRequestException {
+    return HTTP_NOT_MODIFIED == code();
+  }
+
+  /**
+   * Get status message of the response
+   *
+   * @return message
+   * @throws HttpRequestException
+   */
+  public String message() throws HttpRequestException {
+    try {
+      closeOutput();
+      return getConnection().getResponseMessage();
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Disconnect the connection
+   *
+   * @return this request
+   */
+  public HttpRequest disconnect() {
+    getConnection().disconnect();
+    return this;
+  }
+
+  /**
+   * Set chunked streaming mode to the given size
+   *
+   * @param size
+   * @return this request
+   */
+  public HttpRequest chunk(final int size) {
+    getConnection().setChunkedStreamingMode(size);
+    return this;
+  }
+
+  /**
+   * Set the size used when buffering and copying between streams
+   * <p>
+   * This size is also used for send and receive buffers created for both char and
+   * byte arrays
+   * <p>
+   * The default buffer size is 8,192 bytes
+   *
+   * @param size
+   * @return this request
+   */
+  public HttpRequest bufferSize(final int size) {
+    if (size < 1)
+      throw new IllegalArgumentException("Size must be greater than zero");
+    bufferSize = size;
+    return this;
+  }
+
+  /**
+   * Get the configured buffer size
+   * <p>
+   * The default buffer size is 8,192 bytes
+   *
+   * @return buffer size
+   */
+  public int bufferSize() {
+    return bufferSize;
+  }
+
+  /**
+   * Set whether or not the response body should be automatically uncompressed
+   * when read from.
+   * <p>
+   * This will only affect requests that have the 'Content-Encoding' response
+   * header set to 'gzip'.
+   * <p>
+   * This causes all receive methods to use a {@link GZIPInputStream} when
+   * applicable so that higher level streams and readers can read the data
+   * uncompressed.
+   * <p>
+   * Setting this option does not cause any request headers to be set
+   * automatically so {@link #acceptGzipEncoding()} should be used in conjunction
+   * with this setting to tell the server to gzip the response.
+   *
+   * @param uncompress
+   * @return this request
+   */
+  public HttpRequest uncompress(final boolean uncompress) {
+    this.uncompress = uncompress;
+    return this;
+  }
+
+  /**
+   * Create byte array output stream
+   *
+   * @return stream
+   */
+  protected ByteArrayOutputStream byteStream() {
+    final int size = contentLength();
+    if (size > 0)
+      return new ByteArrayOutputStream(size);
+    else
+      return new ByteArrayOutputStream();
+  }
+
+  /**
+   * Get response as {@link String} in given character set
+   * <p>
+   * This will fall back to using the UTF-8 character set if the given charset is
+   * null
+   *
+   * @param charset
+   * @return string
+   * @throws HttpRequestException
+   */
+  public String body(final String charset) throws HttpRequestException {
+    final ByteArrayOutputStream output = byteStream();
+    try {
+      copy(buffer(), output);
+      return output.toString(getValidCharset(charset));
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Get response as {@link String} using character set returned from
+   * {@link #charset()}
+   *
+   * @return string
+   * @throws HttpRequestException
+   */
+  public String body() throws HttpRequestException {
+    return body(charset());
+  }
+
+  /**
+   * Get the response body as a {@link String} and set it as the value of the
+   * given reference.
+   *
+   * @param output
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest body(final AtomicReference<String> output) throws HttpRequestException {
+    output.set(body());
+    return this;
+  }
+
+  /**
+   * Get the response body as a {@link String} and set it as the value of the
+   * given reference.
+   *
+   * @param output
+   * @param charset
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest body(final AtomicReference<String> output, final String charset) throws HttpRequestException {
+    output.set(body(charset));
+    return this;
+  }
+
+  /**
+   * Is the response body empty?
+   *
+   * @return true if the Content-Length response header is 0, false otherwise
+   * @throws HttpRequestException
+   */
+  public boolean isBodyEmpty() throws HttpRequestException {
+    return contentLength() == 0;
+  }
+
+  /**
+   * Get response as byte array
+   *
+   * @return byte array
+   * @throws HttpRequestException
+   */
+  public byte[] bytes() throws HttpRequestException {
+    final ByteArrayOutputStream output = byteStream();
+    try {
+      copy(buffer(), output);
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return output.toByteArray();
+  }
+
+  /**
+   * Get response in a buffered stream
+   *
+   * @see #bufferSize(int)
+   * @return stream
+   * @throws HttpRequestException
+   */
+  public BufferedInputStream buffer() throws HttpRequestException {
+    return new BufferedInputStream(stream(), bufferSize);
+  }
+
+  /**
+   * Get stream to response body
+   *
+   * @return stream
+   * @throws HttpRequestException
+   */
+  public InputStream stream() throws HttpRequestException {
+    InputStream stream;
+    if (code() < HTTP_BAD_REQUEST)
+      try {
+        stream = getConnection().getInputStream();
+      } catch (IOException e) {
+        throw new HttpRequestException(e);
+      }
+    else {
+      stream = getConnection().getErrorStream();
+      if (stream == null)
+        try {
+          stream = getConnection().getInputStream();
+        } catch (IOException e) {
+          if (contentLength() > 0)
+            throw new HttpRequestException(e);
+          else
+            stream = new ByteArrayInputStream(new byte[0]);
+        }
+    }
+
+    if (!uncompress || !ENCODING_GZIP.equals(contentEncoding()))
+      return stream;
+    else
+      try {
+        return new GZIPInputStream(stream);
+      } catch (IOException e) {
+        throw new HttpRequestException(e);
+      }
+  }
+
+  /**
+   * Get reader to response body using given character set.
+   * <p>
+   * This will fall back to using the UTF-8 character set if the given charset is
+   * null
+   *
+   * @param charset
+   * @return reader
+   * @throws HttpRequestException
+   */
+  public InputStreamReader reader(final String charset) throws HttpRequestException {
+    try {
+      return new InputStreamReader(stream(), getValidCharset(charset));
+    } catch (UnsupportedEncodingException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Get reader to response body using the character set returned from
+   * {@link #charset()}
+   *
+   * @return reader
+   * @throws HttpRequestException
+   */
+  public InputStreamReader reader() throws HttpRequestException {
+    return reader(charset());
+  }
+
+  /**
+   * Get buffered reader to response body using the given character set r and the
+   * configured buffer size
+   *
+   *
+   * @see #bufferSize(int)
+   * @param charset
+   * @return reader
+   * @throws HttpRequestException
+   */
+  public BufferedReader bufferedReader(final String charset) throws HttpRequestException {
+    return new BufferedReader(reader(charset), bufferSize);
+  }
+
+  /**
+   * Get buffered reader to response body using the character set returned from
+   * {@link #charset()} and the configured buffer size
+   *
+   * @see #bufferSize(int)
+   * @return reader
+   * @throws HttpRequestException
+   */
+  public BufferedReader bufferedReader() throws HttpRequestException {
+    return bufferedReader(charset());
+  }
+
+  /**
+   * Stream response body to file
+   *
+   * @param file
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest receive(final File file) throws HttpRequestException {
+    final OutputStream output;
+    try {
+      output = new BufferedOutputStream(new FileOutputStream(file), bufferSize);
+    } catch (FileNotFoundException e) {
+      throw new HttpRequestException(e);
+    }
+    return new CloseOperation<HttpRequest>(output, ignoreCloseExceptions) {
+
+      @Override
+      protected HttpRequest run() throws HttpRequestException, IOException {
+        return receive(output);
+      }
+    }.call();
+  }
+
+  /**
+   * Stream response to given output stream
+   *
+   * @param output
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest receive(final OutputStream output) throws HttpRequestException {
+    try {
+      return copy(buffer(), output);
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Stream response to given print stream
+   *
+   * @param output
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest receive(final PrintStream output) throws HttpRequestException {
+    return receive((OutputStream) output);
+  }
+
+  /**
+   * Receive response into the given appendable
+   *
+   * @param appendable
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest receive(final Appendable appendable) throws HttpRequestException {
+    final BufferedReader reader = bufferedReader();
+    return new CloseOperation<HttpRequest>(reader, ignoreCloseExceptions) {
+
+      @Override
+      public HttpRequest run() throws IOException {
+        final CharBuffer buffer = CharBuffer.allocate(bufferSize);
+        int read;
+        while ((read = reader.read(buffer)) != -1) {
+          buffer.rewind();
+          appendable.append(buffer, 0, read);
+          buffer.rewind();
+        }
+        return HttpRequest.this;
+      }
+    }.call();
+  }
+
+  /**
+   * Receive response into the given writer
+   *
+   * @param writer
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest receive(final Writer writer) throws HttpRequestException {
+    final BufferedReader reader = bufferedReader();
+    return new CloseOperation<HttpRequest>(reader, ignoreCloseExceptions) {
+
+      @Override
+      public HttpRequest run() throws IOException {
+        return copy(reader, writer);
+      }
+    }.call();
+  }
+
+  /**
+   * Set read timeout on connection to given value
+   *
+   * @param timeout
+   * @return this request
+   */
+  public HttpRequest readTimeout(final int timeout) {
+    getConnection().setReadTimeout(timeout);
+    return this;
+  }
+
+  /**
+   * Set connect timeout on connection to given value
+   *
+   * @param timeout
+   * @return this request
+   */
+  public HttpRequest connectTimeout(final int timeout) {
+    getConnection().setConnectTimeout(timeout);
+    return this;
+  }
+
+  /**
+   * Set header name to given value
+   *
+   * @param name
+   * @param value
+   * @return this request
+   */
+  public HttpRequest header(final String name, final String value) {
+    getConnection().setRequestProperty(name, value);
+    return this;
+  }
+
+  /**
+   * Set header name to given value
+   *
+   * @param name
+   * @param value
+   * @return this request
+   */
+  public HttpRequest header(final String name, final Number value) {
+    return header(name, value != null ? value.toString() : null);
+  }
+
+  /**
+   * Set all headers found in given map where the keys are the header names and
+   * the values are the header values
+   *
+   * @param headers
+   * @return this request
+   */
+  public HttpRequest headers(final Map<String, String> headers) {
+    if (!headers.isEmpty())
+      for (Entry<String, String> header : headers.entrySet())
+        header(header);
+    return this;
+  }
+
+  /**
+   * Set header to have given entry's key as the name and value as the value
+   *
+   * @param header
+   * @return this request
+   */
+  public HttpRequest header(final Entry<String, String> header) {
+    return header(header.getKey(), header.getValue());
+  }
+
+  /**
+   * Get a response header
+   *
+   * @param name
+   * @return response header
+   * @throws HttpRequestException
+   */
+  public String header(final String name) throws HttpRequestException {
+    closeOutputQuietly();
+    return getConnection().getHeaderField(name);
+  }
+
+  /**
+   * Get all the response headers
+   *
+   * @return map of response header names to their value(s)
+   * @throws HttpRequestException
+   */
+  public Map<String, List<String>> headers() throws HttpRequestException {
+    closeOutputQuietly();
+    return getConnection().getHeaderFields();
+  }
+
+  /**
+   * Get a date header from the response falling back to returning -1 if the
+   * header is missing or parsing fails
+   *
+   * @param name
+   * @return date, -1 on failures
+   * @throws HttpRequestException
+   */
+  public long dateHeader(final String name) throws HttpRequestException {
+    return dateHeader(name, -1L);
+  }
+
+  /**
+   * Get a date header from the response falling back to returning the given
+   * default value if the header is missing or parsing fails
+   *
+   * @param name
+   * @param defaultValue
+   * @return date, default value on failures
+   * @throws HttpRequestException
+   */
+  public long dateHeader(final String name, final long defaultValue) throws HttpRequestException {
+    closeOutputQuietly();
+    return getConnection().getHeaderFieldDate(name, defaultValue);
+  }
+
+  /**
+   * Get an integer header from the response falling back to returning -1 if the
+   * header is missing or parsing fails
+   *
+   * @param name
+   * @return header value as an integer, -1 when missing or parsing fails
+   * @throws HttpRequestException
+   */
+  public int intHeader(final String name) throws HttpRequestException {
+    return intHeader(name, -1);
+  }
+
+  /**
+   * Get an integer header value from the response falling back to the given
+   * default value if the header is missing or if parsing fails
+   *
+   * @param name
+   * @param defaultValue
+   * @return header value as an integer, default value when missing or parsing
+   *         fails
+   * @throws HttpRequestException
+   */
+  public int intHeader(final String name, final int defaultValue) throws HttpRequestException {
+    closeOutputQuietly();
+    return getConnection().getHeaderFieldInt(name, defaultValue);
+  }
+
+  /**
+   * Get all values of the given header from the response
+   *
+   * @param name
+   * @return non-null but possibly empty array of {@link String} header values
+   */
+  public String[] headers(final String name) {
+    final Map<String, List<String>> headers = headers();
+    if (headers == null || headers.isEmpty())
+      return EMPTY_STRINGS;
+
+    final List<String> values = headers.get(name);
+    if (values != null && !values.isEmpty())
+      return values.toArray(new String[values.size()]);
+    else
+      return EMPTY_STRINGS;
+  }
+
+  /**
+   * Get parameter with given name from header value in response
+   *
+   * @param headerName
+   * @param paramName
+   * @return parameter value or null if missing
+   */
+  public String parameter(final String headerName, final String paramName) {
+    return getParam(header(headerName), paramName);
+  }
+
+  /**
+   * Get all parameters from header value in response
+   * <p>
+   * This will be all key=value pairs after the first ';' that are separated by a
+   * ';'
+   *
+   * @param headerName
+   * @return non-null but possibly empty map of parameter headers
+   */
+  public Map<String, String> parameters(final String headerName) {
+    return getParams(header(headerName));
+  }
+
+  /**
+   * Get parameter values from header value
+   *
+   * @param header
+   * @return parameter value or null if none
+   */
+  protected Map<String, String> getParams(final String header) {
+    if (header == null || header.length() == 0)
+      return Collections.emptyMap();
+
+    final int headerLength = header.length();
+    int start = header.indexOf(';') + 1;
+    if (start == 0 || start == headerLength)
+      return Collections.emptyMap();
+
+    int end = header.indexOf(';', start);
+    if (end == -1)
+      end = headerLength;
+
+    Map<String, String> params = new LinkedHashMap<String, String>();
+    while (start < end) {
+      int nameEnd = header.indexOf('=', start);
+      if (nameEnd != -1 && nameEnd < end) {
+        String name = header.substring(start, nameEnd).trim();
+        if (name.length() > 0) {
+          String value = header.substring(nameEnd + 1, end).trim();
+          int length = value.length();
+          if (length != 0)
+            if (length > 2 && '"' == value.charAt(0) && '"' == value.charAt(length - 1))
+              params.put(name, value.substring(1, length - 1));
+            else
+              params.put(name, value);
+        }
+      }
+
+      start = end + 1;
+      end = header.indexOf(';', start);
+      if (end == -1)
+        end = headerLength;
+    }
+
+    return params;
+  }
+
+  /**
+   * Get parameter value from header value
+   *
+   * @param value
+   * @param paramName
+   * @return parameter value or null if none
+   */
+  protected String getParam(final String value, final String paramName) {
+    if (value == null || value.length() == 0)
+      return null;
+
+    final int length = value.length();
+    int start = value.indexOf(';') + 1;
+    if (start == 0 || start == length)
+      return null;
+
+    int end = value.indexOf(';', start);
+    if (end == -1)
+      end = length;
+
+    while (start < end) {
+      int nameEnd = value.indexOf('=', start);
+      if (nameEnd != -1 && nameEnd < end && paramName.equals(value.substring(start, nameEnd).trim())) {
+        String paramValue = value.substring(nameEnd + 1, end).trim();
+        int valueLength = paramValue.length();
+        if (valueLength != 0)
+          if (valueLength > 2 && '"' == paramValue.charAt(0) && '"' == paramValue.charAt(valueLength - 1))
+            return paramValue.substring(1, valueLength - 1);
+          else
+            return paramValue;
+      }
+
+      start = end + 1;
+      end = value.indexOf(';', start);
+      if (end == -1)
+        end = length;
+    }
+
+    return null;
+  }
+
+  /**
+   * Get 'charset' parameter from 'Content-Type' response header
+   *
+   * @return charset or null if none
+   */
+  public String charset() {
+    return parameter(HEADER_CONTENT_TYPE, PARAM_CHARSET);
+  }
+
+  /**
+   * Set the 'User-Agent' header to given value
+   *
+   * @param userAgent
+   * @return this request
+   */
+  public HttpRequest userAgent(final String userAgent) {
+    return header(HEADER_USER_AGENT, userAgent);
+  }
+
+  /**
+   * Set the 'Referer' header to given value
+   *
+   * @param referer
+   * @return this request
+   */
+  public HttpRequest referer(final String referer) {
+    return header(HEADER_REFERER, referer);
+  }
+
+  /**
+   * Set value of {@link HttpURLConnection#setUseCaches(boolean)}
+   *
+   * @param useCaches
+   * @return this request
+   */
+  public HttpRequest useCaches(final boolean useCaches) {
+    getConnection().setUseCaches(useCaches);
+    return this;
+  }
+
+  /**
+   * Set the 'Accept-Encoding' header to given value
+   *
+   * @param acceptEncoding
+   * @return this request
+   */
+  public HttpRequest acceptEncoding(final String acceptEncoding) {
+    return header(HEADER_ACCEPT_ENCODING, acceptEncoding);
+  }
+
+  /**
+   * Set the 'Accept-Encoding' header to 'gzip'
+   *
+   * @see #uncompress(boolean)
+   * @return this request
+   */
+  public HttpRequest acceptGzipEncoding() {
+    return acceptEncoding(ENCODING_GZIP);
+  }
+
+  /**
+   * Set the 'Accept-Charset' header to given value
+   *
+   * @param acceptCharset
+   * @return this request
+   */
+  public HttpRequest acceptCharset(final String acceptCharset) {
+    return header(HEADER_ACCEPT_CHARSET, acceptCharset);
+  }
+
+  /**
+   * Get the 'Content-Encoding' header from the response
+   *
+   * @return this request
+   */
+  public String contentEncoding() {
+    return header(HEADER_CONTENT_ENCODING);
+  }
+
+  /**
+   * Get the 'Server' header from the response
+   *
+   * @return server
+   */
+  public String server() {
+    return header(HEADER_SERVER);
+  }
+
+  /**
+   * Get the 'Date' header from the response
+   *
+   * @return date value, -1 on failures
+   */
+  public long date() {
+    return dateHeader(HEADER_DATE);
+  }
+
+  /**
+   * Get the 'Cache-Control' header from the response
+   *
+   * @return cache control
+   */
+  public String cacheControl() {
+    return header(HEADER_CACHE_CONTROL);
+  }
+
+  /**
+   * Get the 'ETag' header from the response
+   *
+   * @return entity tag
+   */
+  public String eTag() {
+    return header(HEADER_ETAG);
+  }
+
+  /**
+   * Get the 'Expires' header from the response
+   *
+   * @return expires value, -1 on failures
+   */
+  public long expires() {
+    return dateHeader(HEADER_EXPIRES);
+  }
+
+  /**
+   * Get the 'Last-Modified' header from the response
+   *
+   * @return last modified value, -1 on failures
+   */
+  public long lastModified() {
+    return dateHeader(HEADER_LAST_MODIFIED);
+  }
+
+  /**
+   * Get the 'Location' header from the response
+   *
+   * @return location
+   */
+  public String location() {
+    return header(HEADER_LOCATION);
+  }
+
+  /**
+   * Set the 'Authorization' header to given value
+   *
+   * @param authorization
+   * @return this request
+   */
+  public HttpRequest authorization(final String authorization) {
+    return header(HEADER_AUTHORIZATION, authorization);
+  }
+
+  /**
+   * Set the 'Proxy-Authorization' header to given value
+   *
+   * @param proxyAuthorization
+   * @return this request
+   */
+  public HttpRequest proxyAuthorization(final String proxyAuthorization) {
+    return header(HEADER_PROXY_AUTHORIZATION, proxyAuthorization);
+  }
+
+  /**
+   * Set the 'Authorization' header to given values in Basic authentication format
+   *
+   * @param name
+   * @param password
+   * @return this request
+   */
+  public HttpRequest basic(final String name, final String password) {
+    return authorization("Basic " + Base64.encode(name + ':' + password));
+  }
+
+  /**
+   * Set the 'Proxy-Authorization' header to given values in Basic authentication
+   * format
+   *
+   * @param name
+   * @param password
+   * @return this request
+   */
+  public HttpRequest proxyBasic(final String name, final String password) {
+    return proxyAuthorization("Basic " + Base64.encode(name + ':' + password));
+  }
+
+  /**
+   * Set the 'If-Modified-Since' request header to the given value
+   *
+   * @param ifModifiedSince
+   * @return this request
+   */
+  public HttpRequest ifModifiedSince(final long ifModifiedSince) {
+    getConnection().setIfModifiedSince(ifModifiedSince);
+    return this;
+  }
+
+  /**
+   * Set the 'If-None-Match' request header to the given value
+   *
+   * @param ifNoneMatch
+   * @return this request
+   */
+  public HttpRequest ifNoneMatch(final String ifNoneMatch) {
+    return header(HEADER_IF_NONE_MATCH, ifNoneMatch);
+  }
+
+  /**
+   * Set the 'Content-Type' request header to the given value
+   *
+   * @param contentType
+   * @return this request
+   */
+  public HttpRequest contentType(final String contentType) {
+    return contentType(contentType, null);
+  }
+
+  /**
+   * Set the 'Content-Type' request header to the given value and charset
+   *
+   * @param contentType
+   * @param charset
+   * @return this request
+   */
+  public HttpRequest contentType(final String contentType, final String charset) {
+    if (charset != null && charset.length() > 0) {
+      final String separator = "; " + PARAM_CHARSET + '=';
+      return header(HEADER_CONTENT_TYPE, contentType + separator + charset);
+    } else
+      return header(HEADER_CONTENT_TYPE, contentType);
+  }
+
+  /**
+   * Get the 'Content-Type' header from the response
+   *
+   * @return response header value
+   */
+  public String contentType() {
+    return header(HEADER_CONTENT_TYPE);
+  }
+
+  /**
+   * Get the 'Content-Length' header from the response
+   *
+   * @return response header value
+   */
+  public int contentLength() {
+    return intHeader(HEADER_CONTENT_LENGTH);
+  }
+
+  /**
+   * Set the 'Content-Length' request header to the given value
+   *
+   * @param contentLength
+   * @return this request
+   */
+  public HttpRequest contentLength(final String contentLength) {
+    return contentLength(Integer.parseInt(contentLength));
+  }
+
+  /**
+   * Set the 'Content-Length' request header to the given value
+   *
+   * @param contentLength
+   * @return this request
+   */
+  public HttpRequest contentLength(final int contentLength) {
+    getConnection().setFixedLengthStreamingMode(contentLength);
+    return this;
+  }
+
+  /**
+   * Set the 'Accept' header to given value
+   *
+   * @param accept
+   * @return this request
+   */
+  public HttpRequest accept(final String accept) {
+    return header(HEADER_ACCEPT, accept);
+  }
+
+  /**
+   * Set the 'Accept' header to 'application/json'
+   *
+   * @return this request
+   */
+  public HttpRequest acceptJson() {
+    return accept(CONTENT_TYPE_JSON);
+  }
+
+  /**
+   * Copy from input stream to output stream
+   *
+   * @param input
+   * @param output
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest copy(final InputStream input, final OutputStream output) throws IOException {
+    return new CloseOperation<HttpRequest>(input, ignoreCloseExceptions) {
+
+      @Override
+      public HttpRequest run() throws IOException {
+        final byte[] buffer = new byte[bufferSize];
+        int read;
+        while ((read = input.read(buffer)) != -1) {
+          output.write(buffer, 0, read);
+          totalWritten += read;
+          progress.onUpload(totalWritten, totalSize);
+        }
+        return HttpRequest.this;
+      }
+    }.call();
+  }
+
+  /**
+   * Copy from reader to writer
+   *
+   * @param input
+   * @param output
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest copy(final Reader input, final Writer output) throws IOException {
+    return new CloseOperation<HttpRequest>(input, ignoreCloseExceptions) {
+
+      @Override
+      public HttpRequest run() throws IOException {
+        final char[] buffer = new char[bufferSize];
+        int read;
+        while ((read = input.read(buffer)) != -1) {
+          output.write(buffer, 0, read);
+          totalWritten += read;
+          progress.onUpload(totalWritten, -1);
+        }
+        return HttpRequest.this;
+      }
+    }.call();
+  }
+
+  /**
+   * Set the UploadProgress callback for this request
+   *
+   * @param callback
+   * @return this request
+   */
+  public HttpRequest progress(final UploadProgress callback) {
+    if (callback == null)
+      progress = UploadProgress.DEFAULT;
+    else
+      progress = callback;
+    return this;
+  }
+
+  private HttpRequest incrementTotalSize(final long size) {
+    if (totalSize == -1)
+      totalSize = 0;
+    totalSize += size;
+    return this;
+  }
+
+  /**
+   * Close output stream
+   *
+   * @return this request
+   * @throws HttpRequestException
+   * @throws IOException
+   */
+  protected HttpRequest closeOutput() throws IOException {
+    progress(null);
+    if (output == null)
+      return this;
+    if (multipart)
+      output.write(CRLF + "--" + BOUNDARY + "--" + CRLF);
+    if (ignoreCloseExceptions)
+      try {
+        output.close();
+      } catch (IOException ignored) {
+        // Ignored
+      }
+    else
+      output.close();
+    output = null;
+    return this;
+  }
+
+  /**
+   * Call {@link #closeOutput()} and re-throw a caught {@link IOException}s as an
+   * {@link HttpRequestException}
+   *
+   * @return this request
+   * @throws HttpRequestException
+   */
+  protected HttpRequest closeOutputQuietly() throws HttpRequestException {
+    try {
+      return closeOutput();
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Open output stream
+   *
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest openOutput() throws IOException {
+    if (output != null)
+      return this;
+    getConnection().setDoOutput(true);
+    final String charset = getParam(getConnection().getRequestProperty(HEADER_CONTENT_TYPE), PARAM_CHARSET);
+    output = new RequestOutputStream(getConnection().getOutputStream(), charset, bufferSize);
+    return this;
+  }
+
+  /**
+   * Start part of a multipart
+   *
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest startPart() throws IOException {
+    if (!multipart) {
+      multipart = true;
+      contentType(CONTENT_TYPE_MULTIPART).openOutput();
+      output.write("--" + BOUNDARY + CRLF);
+    } else
+      output.write(CRLF + "--" + BOUNDARY + CRLF);
+    return this;
+  }
+
+  /**
+   * Write part header
+   *
+   * @param name
+   * @param filename
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest writePartHeader(final String name, final String filename) throws IOException {
+    return writePartHeader(name, filename, null);
+  }
+
+  /**
+   * Write part header
+   *
+   * @param name
+   * @param filename
+   * @param contentType
+   * @return this request
+   * @throws IOException
+   */
+  protected HttpRequest writePartHeader(final String name, final String filename, final String contentType)
+      throws IOException {
+    final StringBuilder partBuffer = new StringBuilder();
+    partBuffer.append("form-data; name=\"").append(name);
+    if (filename != null)
+      partBuffer.append("\"; filename=\"").append(filename);
+    partBuffer.append('"');
+    partHeader("Content-Disposition", partBuffer.toString());
+    if (contentType != null)
+      partHeader(HEADER_CONTENT_TYPE, contentType);
+    return send(CRLF);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param part
+   * @return this request
+   */
+  public HttpRequest part(final String name, final String part) {
+    return part(name, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final String part) throws HttpRequestException {
+    return part(name, filename, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param contentType value of the Content-Type part header
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final String contentType, final String part)
+      throws HttpRequestException {
+    try {
+      startPart();
+      writePartHeader(name, filename, contentType);
+      output.write(part);
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return this;
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final Number part) throws HttpRequestException {
+    return part(name, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final Number part) throws HttpRequestException {
+    return part(name, filename, part != null ? part.toString() : null);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final File part) throws HttpRequestException {
+    return part(name, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final File part) throws HttpRequestException {
+    return part(name, filename, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param contentType value of the Content-Type part header
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final String contentType, final File part)
+      throws HttpRequestException {
+    final InputStream stream;
+    try {
+      stream = new BufferedInputStream(new FileInputStream(part));
+      incrementTotalSize(part.length());
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return part(name, filename, contentType, stream);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final InputStream part) throws HttpRequestException {
+    return part(name, null, null, part);
+  }
+
+  /**
+   * Write part of a multipart request to the request body
+   *
+   * @param name
+   * @param filename
+   * @param contentType value of the Content-Type part header
+   * @param part
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest part(final String name, final String filename, final String contentType, final InputStream part)
+      throws HttpRequestException {
+    try {
+      startPart();
+      writePartHeader(name, filename, contentType);
+      copy(part, output);
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return this;
+  }
+
+  /**
+   * Write a multipart header to the response body
+   *
+   * @param name
+   * @param value
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest partHeader(final String name, final String value) throws HttpRequestException {
+    return send(name).send(": ").send(value).send(CRLF);
+  }
+
+  /**
+   * Write contents of file to request body
+   *
+   * @param input
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest send(final File input) throws HttpRequestException {
+    final InputStream stream;
+    try {
+      stream = new BufferedInputStream(new FileInputStream(input));
+      incrementTotalSize(input.length());
+    } catch (FileNotFoundException e) {
+      throw new HttpRequestException(e);
+    }
+    return send(stream);
+  }
+
+  /**
+   * Write byte array to request body
+   *
+   * @param input
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest send(final byte[] input) throws HttpRequestException {
+    if (input != null)
+      incrementTotalSize(input.length);
+    return send(new ByteArrayInputStream(input));
+  }
+
+  /**
+   * Write stream to request body
+   * <p>
+   * The given stream will be closed once sending completes
+   *
+   * @param input
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest send(final InputStream input) throws HttpRequestException {
+    try {
+      openOutput();
+      copy(input, output);
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return this;
+  }
+
+  /**
+   * Write reader to request body
+   * <p>
+   * The given reader will be closed once sending completes
+   *
+   * @param input
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest send(final Reader input) throws HttpRequestException {
+    try {
+      openOutput();
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    final Writer writer = new OutputStreamWriter(output, output.encoder.charset());
+    return new FlushOperation<HttpRequest>(writer) {
+
+      @Override
+      protected HttpRequest run() throws IOException {
+        return copy(input, writer);
+      }
+    }.call();
+  }
+
+  /**
+   * Write char sequence to request body
+   * <p>
+   * The charset configured via {@link #contentType(String)} will be used and
+   * UTF-8 will be used if it is unset.
+   *
+   * @param value
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest send(final CharSequence value) throws HttpRequestException {
+    try {
+      openOutput();
+      output.write(value.toString());
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return this;
+  }
+
+  /**
+   * Create writer to request output stream
+   *
+   * @return writer
+   * @throws HttpRequestException
+   */
+  public OutputStreamWriter writer() throws HttpRequestException {
+    try {
+      openOutput();
+      return new OutputStreamWriter(output, output.encoder.charset());
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+  }
+
+  /**
+   * Write the values in the map as form data to the request body
+   * <p>
+   * The pairs specified will be URL-encoded in UTF-8 and sent with the
+   * 'application/x-www-form-urlencoded' content-type
+   *
+   * @param values
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Map<?, ?> values) throws HttpRequestException {
+    return form(values, CHARSET_UTF8);
+  }
+
+  /**
+   * Write the key and value in the entry as form data to the request body
+   * <p>
+   * The pair specified will be URL-encoded in UTF-8 and sent with the
+   * 'application/x-www-form-urlencoded' content-type
+   *
+   * @param entry
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Entry<?, ?> entry) throws HttpRequestException {
+    return form(entry, CHARSET_UTF8);
+  }
+
+  /**
+   * Write the key and value in the entry as form data to the request body
+   * <p>
+   * The pair specified will be URL-encoded and sent with the
+   * 'application/x-www-form-urlencoded' content-type
+   *
+   * @param entry
+   * @param charset
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Entry<?, ?> entry, final String charset) throws HttpRequestException {
+    return form(entry.getKey(), entry.getValue(), charset);
+  }
+
+  /**
+   * Write the name/value pair as form data to the request body
+   * <p>
+   * The pair specified will be URL-encoded in UTF-8 and sent with the
+   * 'application/x-www-form-urlencoded' content-type
+   *
+   * @param name
+   * @param value
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Object name, final Object value) throws HttpRequestException {
+    return form(name, value, CHARSET_UTF8);
+  }
+
+  /**
+   * Write the name/value pair as form data to the request body
+   * <p>
+   * The values specified will be URL-encoded and sent with the
+   * 'application/x-www-form-urlencoded' content-type
+   *
+   * @param name
+   * @param value
+   * @param charset
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Object name, final Object value, String charset) throws HttpRequestException {
+    final boolean first = !form;
+    if (first) {
+      contentType(CONTENT_TYPE_FORM, charset);
+      form = true;
+    }
+    charset = getValidCharset(charset);
+    try {
+      openOutput();
+      if (!first)
+        output.write('&');
+      output.write(URLEncoder.encode(name.toString(), charset));
+      output.write('=');
+      if (value != null)
+        output.write(URLEncoder.encode(value.toString(), charset));
+    } catch (IOException e) {
+      throw new HttpRequestException(e);
+    }
+    return this;
+  }
+
+  /**
+   * Write the values in the map as encoded form data to the request body
+   *
+   * @param values
+   * @param charset
+   * @return this request
+   * @throws HttpRequestException
+   */
+  public HttpRequest form(final Map<?, ?> values, final String charset) throws HttpRequestException {
+    if (!values.isEmpty())
+      for (Entry<?, ?> entry : values.entrySet())
+        form(entry, charset);
+    return this;
+  }
+
+  public HttpRequest setSSLSocketFactory(SSLSocketFactory socketFactory) throws HttpRequestException {
+    final HttpURLConnection connection = getConnection();
+    if (connection instanceof HttpsURLConnection)
+      ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory);
+    return this;
+  }
+
+  public HttpRequest setHostnameVerifier(HostnameVerifier verifier) {
+    final HttpURLConnection connection = getConnection();
+    if (connection instanceof HttpsURLConnection)
+      ((HttpsURLConnection) connection).setHostnameVerifier(verifier);
+    return this;
+  }
+
+  /**
+   * Get the {@link URL} of this request's connection
+   *
+   * @return request URL
+   */
+  public URL url() {
+    return getConnection().getURL();
+  }
+
+  /**
+   * Get the HTTP method of this request
+   *
+   * @return method
+   */
+  public String method() {
+    return getConnection().getRequestMethod();
+  }
+
+  /**
+   * Configure an HTTP proxy on this connection. Use
+   * {{@link #proxyBasic(String, String)} if this proxy requires basic
+   * authentication.
+   *
+   * @param proxyHost
+   * @param proxyPort
+   * @return this request
+   */
+  public HttpRequest useProxy(final String proxyHost, final int proxyPort) {
+    if (connection != null)
+      throw new IllegalStateException(
+          "The connection has already been created. This method must be called before reading or writing to the request.");
+
+    this.httpProxyHost = proxyHost;
+    this.httpProxyPort = proxyPort;
+    return this;
+  }
+
+  /**
+   * Set whether or not the underlying connection should follow redirects in the
+   * response.
+   *
+   * @param followRedirects - true fo follow redirects, false to not.
+   * @return this request
+   */
+  public HttpRequest followRedirects(final boolean followRedirects) {
+    getConnection().setInstanceFollowRedirects(followRedirects);
+    return this;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/JsonUtils.java b/platforms/android/app/src/main/java/com/silkimen/http/JsonUtils.java
new file mode 100644
index 0000000..72f1b48
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/JsonUtils.java
@@ -0,0 +1,58 @@
+package com.silkimen.http;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class JsonUtils {
+  public static HashMap<String, String> getStringMap(JSONObject object) throws JSONException {
+    HashMap<String, String> map = new HashMap<String, String>();
+
+    if (object == null) {
+      return map;
+    }
+
+    Iterator<?> i = object.keys();
+
+    while (i.hasNext()) {
+      String key = (String) i.next();
+      map.put(key, object.getString(key));
+    }
+    return map;
+  }
+
+  public static HashMap<String, Object> getObjectMap(JSONObject object) throws JSONException {
+    HashMap<String, Object> map = new HashMap<String, Object>();
+
+    if (object == null) {
+      return map;
+    }
+
+    Iterator<?> i = object.keys();
+
+    while (i.hasNext()) {
+      String key = (String) i.next();
+      Object value = object.get(key);
+
+      if (value instanceof JSONArray) {
+        map.put(key, getObjectList((JSONArray) value));
+      } else {
+        map.put(key, object.get(key));
+      }
+    }
+    return map;
+  }
+
+  public static ArrayList<Object> getObjectList(JSONArray array) throws JSONException {
+    ArrayList<Object> list = new ArrayList<Object>();
+
+    for (int i = 0; i < array.length(); i++) {
+      list.add(array.get(i));
+    }
+    return list;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/KeyChainKeyManager.java b/platforms/android/app/src/main/java/com/silkimen/http/KeyChainKeyManager.java
new file mode 100644
index 0000000..ecdaa38
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/KeyChainKeyManager.java
@@ -0,0 +1,57 @@
+package com.silkimen.http;
+
+import android.content.Context;
+import android.security.KeyChain;
+
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.X509ExtendedKeyManager;
+
+public class KeyChainKeyManager extends X509ExtendedKeyManager {
+  private final String alias;
+  private final X509Certificate[] chain;
+  private final PrivateKey key;
+
+  public KeyChainKeyManager(String alias, PrivateKey key, X509Certificate[] chain) {
+    this.alias = alias;
+    this.key = key;
+    this.chain = chain;
+  }
+
+  @Override
+  public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
+    return this.alias;
+  }
+
+  @Override
+  public X509Certificate[] getCertificateChain(String alias) {
+    return chain;
+  }
+
+  @Override
+  public PrivateKey getPrivateKey(String alias) {
+    return key;
+  }
+
+  @Override
+  public final String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
+    // not a client SSLSocket callback
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public final String[] getClientAliases(String keyType, Principal[] issuers) {
+    // not a client SSLSocket callback
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public final String[] getServerAliases(String keyType, Principal[] issuers) {
+    // not a client SSLSocket callback
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/OkConnectionFactory.java b/platforms/android/app/src/main/java/com/silkimen/http/OkConnectionFactory.java
new file mode 100644
index 0000000..c1a3ef1
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/OkConnectionFactory.java
@@ -0,0 +1,26 @@
+package com.silkimen.http;
+
+import okhttp3.OkHttpClient;
+import okhttp3.OkUrlFactory;
+
+import java.net.URL;
+import java.net.HttpURLConnection;
+import java.net.URLStreamHandler;
+import java.net.Proxy;
+
+public class OkConnectionFactory implements HttpRequest.ConnectionFactory {
+  private final OkHttpClient client = new OkHttpClient();
+
+  public HttpURLConnection create(URL url) {
+    OkUrlFactory urlFactory = new OkUrlFactory(this.client);
+
+    return (HttpURLConnection) urlFactory.open(url);
+  }
+
+  public HttpURLConnection create(URL url, Proxy proxy) {
+    OkHttpClient clientWithProxy = new OkHttpClient.Builder().proxy(proxy).build();
+    OkUrlFactory urlFactory = new OkUrlFactory(clientWithProxy);
+
+    return (HttpURLConnection) urlFactory.open(url);
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/TLSConfiguration.java b/platforms/android/app/src/main/java/com/silkimen/http/TLSConfiguration.java
new file mode 100644
index 0000000..c33df6c
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/TLSConfiguration.java
@@ -0,0 +1,63 @@
+package com.silkimen.http;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import com.silkimen.http.TLSSocketFactory;
+
+public class TLSConfiguration {
+  private TrustManager[] trustManagers;
+  private KeyManager[] keyManagers;
+  private HostnameVerifier hostnameVerifier;
+
+  private SSLSocketFactory socketFactory;
+
+  public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
+    this.hostnameVerifier = hostnameVerifier;
+  }
+
+  public void setKeyManagers(KeyManager[] keyManagers) {
+    this.keyManagers = keyManagers;
+    this.socketFactory = null;
+  }
+
+  public void setTrustManagers(TrustManager[] trustManagers) {
+    this.trustManagers = trustManagers;
+    this.socketFactory = null;
+  }
+
+  public HostnameVerifier getHostnameVerifier() {
+    return this.hostnameVerifier;
+  }
+
+  public SSLSocketFactory getTLSSocketFactory() throws IOException {
+    if (this.socketFactory != null) {
+      return this.socketFactory;
+    }
+
+    try {
+      SSLContext context = SSLContext.getInstance("TLS");
+
+      context.init(this.keyManagers, this.trustManagers, new SecureRandom());
+
+      if (android.os.Build.VERSION.SDK_INT < 20) {
+        this.socketFactory = new TLSSocketFactory(context);
+      } else {
+        this.socketFactory = context.getSocketFactory();
+      }
+
+      return this.socketFactory;
+    } catch (GeneralSecurityException e) {
+      IOException ioException = new IOException("Security exception occured while configuring TLS context");
+      ioException.initCause(e);
+      throw ioException;
+    }
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/silkimen/http/TLSSocketFactory.java b/platforms/android/app/src/main/java/com/silkimen/http/TLSSocketFactory.java
new file mode 100644
index 0000000..9bc75b1
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/silkimen/http/TLSSocketFactory.java
@@ -0,0 +1,63 @@
+package com.silkimen.http;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+public class TLSSocketFactory extends SSLSocketFactory {
+
+  private SSLSocketFactory delegate;
+
+  public TLSSocketFactory(SSLContext context) {
+    delegate = context.getSocketFactory();
+  }
+
+  @Override
+  public String[] getDefaultCipherSuites() {
+    return delegate.getDefaultCipherSuites();
+  }
+
+  @Override
+  public String[] getSupportedCipherSuites() {
+    return delegate.getSupportedCipherSuites();
+  }
+
+  @Override
+  public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
+    return enableTLSOnSocket(delegate.createSocket(socket, host, port, autoClose));
+  }
+
+  @Override
+  public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
+    return enableTLSOnSocket(delegate.createSocket(host, port));
+  }
+
+  @Override
+  public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+      throws IOException, UnknownHostException {
+    return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
+  }
+
+  @Override
+  public Socket createSocket(InetAddress host, int port) throws IOException {
+    return enableTLSOnSocket(delegate.createSocket(host, port));
+  }
+
+  @Override
+  public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
+      throws IOException {
+    return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
+  }
+
+  private Socket enableTLSOnSocket(Socket socket) {
+    if (socket != null && (socket instanceof SSLSocket)) {
+      ((SSLSocket) socket).setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" });
+    }
+    return socket;
+  }
+}
diff --git a/platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java b/platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java
new file mode 100644
index 0000000..c48c351
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java
@@ -0,0 +1,41 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+
+package com.supwisdom.dlapp;
+
+import android.os.Bundle;
+import org.apache.cordova.*;
+
+public class MainActivity extends CordovaActivity
+{
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+
+        // enable Cordova apps to be started in the background
+        Bundle extras = getIntent().getExtras();
+        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
+            moveTaskToBack(true);
+        }
+
+        // Set by <content src="index.html" /> in config.xml
+        loadUrl(launchUrl);
+    }
+}
diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java
new file mode 100644
index 0000000..32fd67c
--- /dev/null
+++ b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/Fingerprint.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) https://github.com/mjwheatley/cordova-plugin-android-fingerprint-auth
+ * Modifications copyright (C) 2016 Niklas Merz
+ *
+ * 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 de.niklasmerz.cordova.fingerprint;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaInterface;
+
+import android.annotation.TargetApi;
+import android.app.FragmentTransaction;
+import android.app.KeyguardManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.util.Base64;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Locale;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+@TargetApi(23)
+public class Fingerprint extends CordovaPlugin {
+
+    public static final String TAG = "Fingerprint";
+    public static String packageName;
+
+    private static final String DIALOG_FRAGMENT_TAG = "FpAuthDialog";
+    private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
+
+    KeyguardManager mKeyguardManager;
+    FingerprintAuthenticationDialogFragment mFragment;
+    public static KeyStore mKeyStore;
+    public static KeyGenerator mKeyGenerator;
+    public static Cipher mCipher;
+    private FingerprintManager mFingerPrintManager;
+
+    public static CallbackContext mCallbackContext;
+    public static PluginResult mPluginResult;
+
+    /**
+     * Alias for our key in the Android Key Store
+     */
+    private static String mClientId;
+    /**
+     * Used to encrypt token
+     */
+    private static String mClientSecret;
+
+    /**
+     * Options
+     */
+    private static boolean mDisableBackup = false;
+
+    /**
+     * Constructor.
+     */
+    public Fingerprint() {
+    }
+
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     *
+     * @param cordova The context of the main Activity.
+     * @param webView The CordovaWebView Cordova is running in.
+     */
+
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        super.initialize(cordova, webView);
+        Log.v(TAG, "Init Fingerprint");
+        packageName = cordova.getActivity().getApplicationContext().getPackageName();
+        mPluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+
+        if (android.os.Build.VERSION.SDK_INT < 23) {
+            return;
+        }
+
+        mKeyguardManager = cordova.getActivity().getSystemService(KeyguardManager.class);
+        mFingerPrintManager = cordova.getActivity().getApplicationContext()
+                .getSystemService(FingerprintManager.class);
+
+        try {
+            mKeyGenerator = KeyGenerator.getInstance(
+                    KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
+            mKeyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
+        } catch (NoSuchProviderException e) {
+            throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
+        } catch (KeyStoreException e) {
+            throw new RuntimeException("Failed to get an instance of KeyStore", e);
+        }
+
+        try {
+            mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+                    + KeyProperties.BLOCK_MODE_CBC + "/"
+                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Failed to get an instance of Cipher", e);
+        } catch (NoSuchPaddingException e) {
+            throw new RuntimeException("Failed to get an instance of Cipher", e);
+        }
+    }
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action          The action to execute.
+     * @param args            JSONArry of arguments for the plugin.
+     * @param callbackContext The callback id used when calling back into JavaScript.
+     * @return A PluginResult object with a status and message.
+     */
+    public boolean execute(final String action,
+                           JSONArray args,
+                           CallbackContext callbackContext) throws JSONException {
+        mCallbackContext = callbackContext;
+        Log.v(TAG, "Fingerprint action: " + action);
+        if (android.os.Build.VERSION.SDK_INT < 23) {
+            Log.e(TAG, "minimum SDK version 23 required");
+            mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+            mCallbackContext.error("minimum SDK version 23 required");
+            mCallbackContext.sendPluginResult(mPluginResult);
+            return true;
+        }
+
+        final JSONObject arg_object = args.getJSONObject(0);
+
+        if (action.equals("authenticate")) {
+            if (!arg_object.has("clientId") || !arg_object.has("clientSecret")) {
+                mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+                mCallbackContext.error("Missing required parameters");
+                mCallbackContext.sendPluginResult(mPluginResult);
+                return true;
+            }
+            mClientId = arg_object.getString("clientId");
+            mClientSecret = arg_object.getString("clientSecret");
+            if (arg_object.has("disableBackup")) {
+                mDisableBackup = arg_object.getBoolean("disableBackup");
+            }
+            // Set language
+            Resources res = cordova.getActivity().getResources();
+            // Change locale settings in the app.
+            DisplayMetrics dm = res.getDisplayMetrics();
+            Configuration conf = res.getConfiguration();
+            //Do not change locale
+            res.updateConfiguration(conf, dm);
+
+            if (isFingerprintAuthAvailable()) {
+                SecretKey key = getSecretKey();
+                boolean isCipherInit = true;
+                if (key == null) {
+                    if (createKey()) {
+                        key = getSecretKey();
+                    }
+                }
+                if (key != null && !initCipher()) {
+                    isCipherInit = false;
+                }
+                if (key != null) {
+                    cordova.getActivity().runOnUiThread(new Runnable() {
+                        public void run() {
+                            // Set up the crypto object for later. The object will be authenticated by use
+                            // of the fingerprint.
+                            mFragment = new FingerprintAuthenticationDialogFragment();
+                            Bundle bundle = new Bundle();
+                            bundle.putBoolean("disableBackup", mDisableBackup);
+                            mFragment.setArguments(bundle);
+
+                            if (initCipher()) {
+                                mFragment.setCancelable(false);
+                                // Show the fingerprint dialog. The user has the option to use the fingerprint with
+                                // crypto, or you can fall back to using a server-side verified password.
+                                mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
+                                FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
+                                transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
+                                transaction.commitAllowingStateLoss();
+                            } else {
+                                if (!mDisableBackup) {
+                                    // This happens if the lock screen has been disabled or or a fingerprint got
+                                    // enrolled. Thus show the dialog to authenticate with their password
+                                    mFragment.setCryptoObject(new FingerprintManager
+                                            .CryptoObject(mCipher));
+                                    mFragment.setStage(FingerprintAuthenticationDialogFragment
+                                            .Stage.NEW_FINGERPRINT_ENROLLED);
+                                    FragmentTransaction transaction = cordova.getActivity().getFragmentManager().beginTransaction();
+                                    transaction.add(mFragment, DIALOG_FRAGMENT_TAG);
+                                    transaction.commitAllowingStateLoss();
+                                } else {
+                                    mCallbackContext.error("Failed to init Cipher and backup disabled.");
+                                    mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+                                    mCallbackContext.sendPluginResult(mPluginResult);
+                                }
+                            }
+                        }
+                    });
+                    mPluginResult.setKeepCallback(true);
+                } else {
+                    mCallbackContext.sendPluginResult(mPluginResult);
+                }
+
+            } else {
+                mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+                mCallbackContext.error("Fingerprint authentication not available");
+                mCallbackContext.sendPluginResult(mPluginResult);
+            }
+            return true;
+        } else if (action.equals("isAvailable")) {
+            if(isFingerprintAuthAvailable() && mFingerPrintManager.isHardwareDetected() && mFingerPrintManager.hasEnrolledFingerprints()){
+              mPluginResult = new PluginResult(PluginResult.Status.OK, "finger");
+              mCallbackContext.success("finger");
+            }else{
+              mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+
+              if (mFingerPrintManager.isHardwareDetected() && !mFingerPrintManager.hasEnrolledFingerprints()) {
+                mCallbackContext.error("Fingerprint authentication not ready");
+              } else {
+                mCallbackContext.error("Fingerprint authentication not available");
+              }
+            }
+            mCallbackContext.sendPluginResult(mPluginResult);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isFingerprintAuthAvailable() {
+        return mFingerPrintManager.isHardwareDetected()
+                && mFingerPrintManager.hasEnrolledFingerprints();
+    }
+
+    /**
+     * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()}
+     * method.
+     *
+     * @return {@code true} if initialization is successful, {@code false} if the lock screen has
+     * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
+     * the key was generated.
+     */
+    private static boolean initCipher() {
+        boolean initCipher = false;
+        String errorMessage = "";
+        String initCipherExceptionErrorPrefix = "Failed to init Cipher: ";
+        try {
+            SecretKey key = getSecretKey();
+            mCipher.init(Cipher.ENCRYPT_MODE, key);
+            initCipher = true;
+        } catch (InvalidKeyException e) {
+            errorMessage = initCipherExceptionErrorPrefix + "InvalidKeyException: " + e.toString();
+            
+        }
+        if (!initCipher) {
+            Log.e(TAG, errorMessage);
+            createKey();
+        }
+        return initCipher;
+    }
+
+    private static SecretKey getSecretKey() {
+        String errorMessage = "";
+        String getSecretKeyExceptionErrorPrefix = "Failed to get SecretKey from KeyStore: ";
+        SecretKey key = null;
+        try {
+            mKeyStore.load(null);
+            key = (SecretKey) mKeyStore.getKey(mClientId, null);
+        } catch (KeyStoreException e) {
+            errorMessage = getSecretKeyExceptionErrorPrefix
+                    + "KeyStoreException: " + e.toString();;
+        } catch (CertificateException e) {
+            errorMessage = getSecretKeyExceptionErrorPrefix
+                    + "CertificateException: " + e.toString();;
+        } catch (UnrecoverableKeyException e) {
+            errorMessage = getSecretKeyExceptionErrorPrefix
+                    + "UnrecoverableKeyException: " + e.toString();;
+        } catch (IOException e) {
+            errorMessage = getSecretKeyExceptionErrorPrefix
+                    + "IOException: " + e.toString();;
+        } catch (NoSuchAlgorithmException e) {
+            errorMessage = getSecretKeyExceptionErrorPrefix
+                    + "NoSuchAlgorithmException: " + e.toString();;
+        }
+        if (key == null) {
+            Log.e(TAG, errorMessage);
+        }
+        return key;
+    }
+
+    /**
+     * Creates a symmetric key in the Android Key Store which can only be used after the user has
+     * authenticated with fingerprint.
+     */
+    public static boolean createKey() {
+        String errorMessage = "";
+        String createKeyExceptionErrorPrefix = "Failed to create key: ";
+        boolean isKeyCreated = false;
+        // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
+        // for your flow. Use of keys is necessary if you need to know if the set of
+        // enrolled fingerprints has changed.
+        try {
+            mKeyStore.load(null);
+            // Set the alias of the entry in Android KeyStore where the key will appear
+            // and the constrains (purposes) in the constructor of the Builder
+            mKeyGenerator.init(new KeyGenParameterSpec.Builder(mClientId,
+                    KeyProperties.PURPOSE_ENCRYPT |
+                            KeyProperties.PURPOSE_DECRYPT)
+                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
+                            // Require the user to authenticate with a fingerprint to authorize every use
+                            // of the key
+                    .setUserAuthenticationRequired(true)
+                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+                    .build());
+            mKeyGenerator.generateKey();
+            isKeyCreated = true;
+        } catch (NoSuchAlgorithmException e) {
+            errorMessage = createKeyExceptionErrorPrefix
+                    + "NoSuchAlgorithmException: " + e.toString();;
+        } catch (InvalidAlgorithmParameterException e) {
+            errorMessage = createKeyExceptionErrorPrefix
+                    + "InvalidAlgorithmParameterException: " + e.toString();;
+        } catch (CertificateException e) {
+            errorMessage = createKeyExceptionErrorPrefix
+                    + "CertificateException: " + e.toString();;
+        } catch (IOException e) {
+            errorMessage = createKeyExceptionErrorPrefix
+                    + "IOException: " + e.toString();;
+        }
+        if (!isKeyCreated) {
+            Log.e(TAG, errorMessage);
+            setPluginResultError(errorMessage);
+        }
+        return isKeyCreated;
+    }
+
+    public static void onAuthenticated(boolean withFingerprint) {
+        JSONObject resultJson = new JSONObject();
+        String errorMessage = "";
+        boolean createdResultJson = false;
+        try {
+
+            if (withFingerprint) {
+                // If the user has authenticated with fingerprint, verify that using cryptography and
+                // then return the encrypted token
+                byte[] encrypted = tryEncrypt();
+                resultJson.put("withFingerprint", Base64.encodeToString(encrypted, 0 /* flags */));
+            } else {
+                // Authentication happened with backup password.
+                resultJson.put("withPassword", true);
+
+                // if failed to init cipher because of InvalidKeyException, create new key
+                if (!initCipher()) {
+                    createKey();
+                }
+            }
+            createdResultJson = true;
+        } catch (BadPaddingException e) {
+            errorMessage = "Failed to encrypt the data with the generated key:" +
+                    " BadPaddingException:  " + e.getMessage();
+            Log.e(TAG, errorMessage);
+        } catch (IllegalBlockSizeException e) {
+            errorMessage = "Failed to encrypt the data with the generated key: " +
+                    "IllegalBlockSizeException: " + e.getMessage();
+            Log.e(TAG, errorMessage);
+        } catch (JSONException e) {
+            errorMessage = "Failed to set resultJson key value pair: " + e.getMessage();
+            Log.e(TAG, errorMessage);
+        }
+
+        if (createdResultJson) {
+            mCallbackContext.success(resultJson);
+            mPluginResult = new PluginResult(PluginResult.Status.OK);
+        } else {
+            mCallbackContext.error(errorMessage);
+            mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+        }
+        mCallbackContext.sendPluginResult(mPluginResult);
+    }
+
+    public static void onCancelled() {
+        mCallbackContext.error("Cancelled");
+    }
+
+    /**
+     * Tries to encrypt some data with the generated key in {@link #createKey} which is
+     * only works if the user has just authenticated via fingerprint.
+     */
+    private static byte[] tryEncrypt() throws BadPaddingException, IllegalBlockSizeException {
+        return mCipher.doFinal(mClientSecret.getBytes());
+    }
+
+    public static boolean setPluginResultError(String errorMessage) {
+        mCallbackContext.error(errorMessage);
+        mPluginResult = new PluginResult(PluginResult.Status.ERROR);
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java
new file mode 100644
index 0000000..54fb28d
--- /dev/null
+++ b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintAuthenticationDialogFragment.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * Modifications copyright (C) 2016 Niklas Merz
+ *
+ * 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 de.niklasmerz.cordova.fingerprint;
+
+import android.app.DialogFragment;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * A dialog which uses fingerprint APIs to authenticate the user, and falls back to password
+ * authentication if fingerprint is not available.
+ */
+public class FingerprintAuthenticationDialogFragment extends DialogFragment
+        implements FingerprintUiHelper.Callback {
+
+    private static final String TAG = "FingerprintAuthDialog";
+    private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
+
+    private Button mCancelButton;
+    private Button mSecondDialogButton;
+    private View mFingerprintContent;
+
+    private Stage mStage = Stage.FINGERPRINT;
+
+    private KeyguardManager mKeyguardManager;
+    private FingerprintManager.CryptoObject mCryptoObject;
+    private FingerprintUiHelper mFingerprintUiHelper;
+    FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder;
+
+    boolean disableBackup;
+
+    public FingerprintAuthenticationDialogFragment() {
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Do not create a new Fragment when the Activity is re-created such as orientation changes.
+        setRetainInstance(true);
+        setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Material_Light_Dialog);
+
+        mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
+        mFingerprintUiHelperBuilder = new FingerprintUiHelper.FingerprintUiHelperBuilder(
+                getContext(), getContext().getSystemService(FingerprintManager.class));
+
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        Bundle args = getArguments();
+        disableBackup = args.getBoolean("disableBackup");
+        Log.d(TAG, "disableBackup: " + disableBackup);
+
+        int fingerprint_auth_dialog_title_id = getResources()
+                .getIdentifier("fingerprint_auth_dialog_title", "string",
+                        Fingerprint.packageName);
+        getDialog().setTitle(getString(fingerprint_auth_dialog_title_id));
+        int fingerprint_dialog_container_id = getResources()
+                .getIdentifier("fingerprint_dialog_container", "layout",
+                        Fingerprint.packageName);
+        View v = inflater.inflate(fingerprint_dialog_container_id, container, false);
+        int cancel_button_id = getResources()
+                .getIdentifier("cancel_button", "id", Fingerprint.packageName);
+        mCancelButton = (Button) v.findViewById(cancel_button_id);
+        mCancelButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Fingerprint.onCancelled();
+                dismissAllowingStateLoss();
+            }
+        });
+
+        int second_dialog_button_id = getResources()
+                .getIdentifier("second_dialog_button", "id", Fingerprint.packageName);
+        mSecondDialogButton = (Button) v.findViewById(second_dialog_button_id);
+        if (disableBackup) {
+            mSecondDialogButton.setVisibility(View.GONE);
+        }
+        mSecondDialogButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                goToBackup();
+            }
+        });
+        int fingerprint_container_id = getResources()
+                .getIdentifier("fingerprint_container", "id", Fingerprint.packageName);
+        mFingerprintContent = v.findViewById(fingerprint_container_id);
+
+        int new_fingerprint_enrolled_description_id = getResources()
+                .getIdentifier("new_fingerprint_enrolled_description", "id",
+                        Fingerprint.packageName);
+
+        int fingerprint_icon_id = getResources()
+                .getIdentifier("fingerprint_icon", "id", Fingerprint.packageName);
+        int fingerprint_status_id = getResources()
+                .getIdentifier("fingerprint_status", "id", Fingerprint.packageName);
+        mFingerprintUiHelper = mFingerprintUiHelperBuilder.build(
+                (ImageView) v.findViewById(fingerprint_icon_id),
+                (TextView) v.findViewById(fingerprint_status_id), this);
+        updateStage();
+
+        // If fingerprint authentication is not available, switch immediately to the backup
+        // (password) screen.
+        if (!mFingerprintUiHelper.isFingerprintAuthAvailable()) {
+            goToBackup();
+        }
+        return v;
+    }
+
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mStage == Stage.FINGERPRINT) {
+            mFingerprintUiHelper.startListening(mCryptoObject);
+        }
+    }
+
+    public void setStage(Stage stage) {
+        mStage = stage;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mFingerprintUiHelper.stopListening();
+    }
+
+    /**
+     * Sets the crypto object to be passed in when authenticating with fingerprint.
+     */
+    public void setCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
+        mCryptoObject = cryptoObject;
+    }
+
+    /**
+     * Switches to backup (password) screen. This either can happen when fingerprint is not
+     * available or the user chooses to use the password authentication method by pressing the
+     * button. This can also happen when the user had too many fingerprint attempts.
+     */
+    private void goToBackup() {
+        if(disableBackup)
+        {
+            Fingerprint.onCancelled(); 
+            dismissAllowingStateLoss();
+        }
+        else{
+            mStage = Stage.BACKUP;
+            updateStage();
+        }
+    }
+
+    private void updateStage() {
+        int cancel_id = getResources()
+                .getIdentifier("fingerprint_cancel", "string", Fingerprint.packageName);
+        switch (mStage) {
+            case FINGERPRINT:
+                mCancelButton.setText(cancel_id);
+                int use_backup_id = getResources()
+                        .getIdentifier("fingerprint_use_backup", "string", Fingerprint.packageName);
+                mSecondDialogButton.setText(use_backup_id);
+                mFingerprintContent.setVisibility(View.VISIBLE);
+                break;
+            case NEW_FINGERPRINT_ENROLLED:
+                // Intentional fall through
+            case BACKUP:
+                if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
+
+                }
+                if (!mKeyguardManager.isKeyguardSecure()) {
+                    // Show a message that the user hasn't set up a lock screen.
+                    int secure_lock_screen_required_id = getResources()
+                            .getIdentifier("secure_lock_screen_required", "string",
+                                    Fingerprint.packageName);
+                    Toast.makeText(getContext(),
+                            getString(secure_lock_screen_required_id),
+                            Toast.LENGTH_LONG).show();
+                    return;
+                }
+                showAuthenticationScreen();
+                break;
+        }
+    }
+
+    private void showAuthenticationScreen() {
+        // Create the Confirm Credentials screen. You can customize the title and description. Or
+        // we will provide a generic one for you if you leave it null
+        Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
+        if (intent != null) {
+            startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
+            // Challenge completed, proceed with using cipher
+            if (resultCode == getActivity().RESULT_OK) {
+                Fingerprint.onAuthenticated(false /* used backup */);
+            } else {
+                // The user canceled or didn’t complete the lock screen
+                // operation. Go to error/cancellation flow.
+                Fingerprint.onCancelled();
+            }
+            dismissAllowingStateLoss();
+        }
+    }
+
+    @Override
+    public void onAuthenticated() {
+        // Callback from FingerprintUiHelper. Let the activity know that authentication was
+        // successful.
+        Fingerprint.onAuthenticated(true /* withFingerprint */);
+        dismissAllowingStateLoss();
+    }
+
+    @Override
+    public void onError() {
+        if(this.getActivity() != null)
+            goToBackup();
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        super.onCancel(dialog);
+        Fingerprint.onCancelled();
+    }
+
+    /**
+     * Enumeration to indicate which authentication method the user is trying to authenticate with.
+     */
+    public enum Stage {
+        FINGERPRINT,
+        NEW_FINGERPRINT_ENROLLED,
+        BACKUP
+    }
+}
diff --git a/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java
new file mode 100644
index 0000000..e1402c5
--- /dev/null
+++ b/platforms/android/app/src/main/java/de/niklasmerz/cordova/fingerprint/FingerprintUiHelper.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * Modifications copyright (C) 2016 Niklas Merz
+ *
+ * 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 de.niklasmerz.cordova.fingerprint;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.CancellationSignal;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+
+/**
+ * Small helper class to manage text/icon around fingerprint authentication UI.
+ */
+@TargetApi(23)
+public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
+
+    static final long ERROR_TIMEOUT_MILLIS = 1600;
+    static final long SUCCESS_DELAY_MILLIS = 1300;
+
+    private final Context mContext;
+    private final FingerprintManager mFingerprintManager;
+    private final ImageView mIcon;
+    private final TextView mErrorTextView;
+    private final Callback mCallback;
+    private CancellationSignal mCancellationSignal;
+
+    boolean mSelfCancelled;
+
+    /**
+     * Builder class for {@link FingerprintUiHelper} in which injected fields from Dagger
+     * holds its fields and takes other arguments in the {@link #build} method.
+     */
+    public static class FingerprintUiHelperBuilder {
+        private final FingerprintManager mFingerPrintManager;
+        private final Context mContext;
+
+        public FingerprintUiHelperBuilder(Context context, FingerprintManager fingerprintManager) {
+            mFingerPrintManager = fingerprintManager;
+            mContext = context;
+        }
+
+        public FingerprintUiHelper build(ImageView icon, TextView errorTextView, Callback callback) {
+            return new FingerprintUiHelper(mContext, mFingerPrintManager, icon, errorTextView,
+                    callback);
+        }
+    }
+
+    /**
+     * Constructor for {@link FingerprintUiHelper}. This method is expected to be called from
+     * only the {@link FingerprintUiHelperBuilder} class.
+     */
+    private FingerprintUiHelper(Context context, FingerprintManager fingerprintManager,
+            ImageView icon, TextView errorTextView, Callback callback) {
+        mFingerprintManager = fingerprintManager;
+        mIcon = icon;
+        mErrorTextView = errorTextView;
+        mCallback = callback;
+        mContext = context;
+    }
+
+    public boolean isFingerprintAuthAvailable() {
+        return mFingerprintManager.isHardwareDetected()
+                && mFingerprintManager.hasEnrolledFingerprints();
+    }
+
+    public void startListening(FingerprintManager.CryptoObject cryptoObject) {
+        if (!isFingerprintAuthAvailable()) {
+            return;
+        }
+        mCancellationSignal = new CancellationSignal();
+        mSelfCancelled = false;
+        mFingerprintManager
+                .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
+
+        int ic_fp_40px_id = mContext.getResources()
+                .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
+        mIcon.setImageResource(ic_fp_40px_id);
+    }
+
+    public void stopListening() {
+        if (mCancellationSignal != null) {
+            mSelfCancelled = true;
+            mCancellationSignal.cancel();
+            mCancellationSignal = null;
+        }
+    }
+
+    @Override
+    public void onAuthenticationError(int errMsgId, CharSequence errString) {
+        if (!mSelfCancelled) {
+            showError(errString);
+            mIcon.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onError();
+                }
+            }, ERROR_TIMEOUT_MILLIS);
+        }
+    }
+
+    @Override
+    public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+        showError(helpString);
+    }
+
+    @Override
+    public void onAuthenticationFailed() {
+        int fingerprint_not_recognized_id = mContext.getResources()
+                .getIdentifier("fingerprint_not_recognized", "string", Fingerprint.packageName);
+        showError(mIcon.getResources().getString(
+                fingerprint_not_recognized_id));
+    }
+
+    @Override
+    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
+        mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+        int ic_fingerprint_success_id = mContext.getResources()
+                .getIdentifier("ic_fingerprint_success", "drawable", Fingerprint.packageName);
+        mIcon.setImageResource(ic_fingerprint_success_id);
+        int success_color_id = mContext.getResources()
+                .getIdentifier("success_color", "color", Fingerprint.packageName);
+        mErrorTextView.setTextColor(
+                mErrorTextView.getResources().getColor(success_color_id, null));
+        int fingerprint_success_id = mContext.getResources()
+                .getIdentifier("fingerprint_success", "string", Fingerprint.packageName);
+        mErrorTextView.setText(
+                mErrorTextView.getResources().getString(fingerprint_success_id));
+        mIcon.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mCallback.onAuthenticated();
+            }
+        }, SUCCESS_DELAY_MILLIS);
+    }
+
+    private void showError(CharSequence error) {
+        int ic_fingerprint_error_id = mContext.getResources()
+                .getIdentifier("ic_fingerprint_error", "drawable", Fingerprint.packageName);
+        mIcon.setImageResource(ic_fingerprint_error_id);
+        mErrorTextView.setText(error);
+        int warning_color_id = mContext.getResources()
+                .getIdentifier("warning_color", "color", Fingerprint.packageName);
+        mErrorTextView.setTextColor(
+                mErrorTextView.getResources().getColor(warning_color_id, null));
+        mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+        mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
+    }
+
+    Runnable mResetErrorTextRunnable = new Runnable() {
+        @Override
+        public void run() {
+            int hint_color_id = mContext.getResources()
+                    .getIdentifier("hint_color", "color", Fingerprint.packageName);
+            mErrorTextView.setTextColor(
+                    mErrorTextView.getResources().getColor(hint_color_id, null));
+            int fingerprint_hint_id = mContext.getResources()
+                    .getIdentifier("fingerprint_hint", "string", Fingerprint.packageName);
+            mErrorTextView.setText(
+                    mErrorTextView.getResources().getString(fingerprint_hint_id));
+            int ic_fp_40px_id = mContext.getResources()
+                    .getIdentifier("ic_fp_40px", "drawable", Fingerprint.packageName);
+            mIcon.setImageResource(ic_fp_40px_id);
+        }
+    };
+
+    public interface Callback {
+
+        void onAuthenticated();
+
+        void onError();
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java
new file mode 100644
index 0000000..fbe8470
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/camera/CameraLauncher.java
@@ -0,0 +1,1407 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.camera;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.cordova.BuildHelper;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PermissionHelper;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.media.MediaScannerConnection;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.support.v4.content.FileProvider;
+import android.util.Base64;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+/**
+ * This class launches the camera view, allows the user to take a picture, closes the camera view,
+ * and returns the captured image.  When the camera view is closed, the screen displayed before
+ * the camera view was shown is redisplayed.
+ */
+public class CameraLauncher extends CordovaPlugin implements MediaScannerConnectionClient {
+
+    private static final int DATA_URL = 0;              // Return base64 encoded string
+    private static final int FILE_URI = 1;              // Return file uri (content://media/external/images/media/2 for Android)
+    private static final int NATIVE_URI = 2;                    // On Android, this is the same as FILE_URI
+
+    private static final int PHOTOLIBRARY = 0;          // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
+    private static final int CAMERA = 1;                // Take picture from camera
+    private static final int SAVEDPHOTOALBUM = 2;       // Choose image from picture library (same as PHOTOLIBRARY for Android)
+
+    private static final int PICTURE = 0;               // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
+    private static final int VIDEO = 1;                 // allow selection of video only, ONLY RETURNS URL
+    private static final int ALLMEDIA = 2;              // allow selection from all media types
+
+    private static final int JPEG = 0;                  // Take a picture of type JPEG
+    private static final int PNG = 1;                   // Take a picture of type PNG
+    private static final String GET_PICTURE = "Get Picture";
+    private static final String GET_VIDEO = "Get Video";
+    private static final String GET_All = "Get All";
+
+    public static final int PERMISSION_DENIED_ERROR = 20;
+    public static final int TAKE_PIC_SEC = 0;
+    public static final int SAVE_TO_ALBUM_SEC = 1;
+
+    private static final String LOG_TAG = "CameraLauncher";
+
+    //Where did this come from?
+    private static final int CROP_CAMERA = 100;
+
+    private int mQuality;                   // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
+    private int targetWidth;                // desired width of the image
+    private int targetHeight;               // desired height of the image
+    private CordovaUri imageUri;            // Uri of captured image
+    private int encodingType;               // Type of encoding to use
+    private int mediaType;                  // What type of media to retrieve
+    private int destType;                   // Source type (needs to be saved for the permission handling)
+    private int srcType;                    // Destination type (needs to be saved for permission handling)
+    private boolean saveToPhotoAlbum;       // Should the picture be saved to the device's photo album
+    private boolean correctOrientation;     // Should the pictures orientation be corrected
+    private boolean orientationCorrected;   // Has the picture's orientation been corrected
+    private boolean allowEdit;              // Should we allow the user to crop the image.
+
+    protected final static String[] permissions = { Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE };
+
+    public CallbackContext callbackContext;
+    private int numPics;
+
+    private MediaScannerConnection conn;    // Used to update gallery app with newly-written files
+    private Uri scanMe;                     // Uri of image to be added to content store
+    private Uri croppedUri;
+    private ExifHelper exifData;            // Exif data from source
+    private String applicationId;
+
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action            The action to execute.
+     * @param args              JSONArry of arguments for the plugin.
+     * @param callbackContext   The callback id used when calling back into JavaScript.
+     * @return                  A PluginResult object with a status and message.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+        this.callbackContext = callbackContext;
+        //Adding an API to CoreAndroid to get the BuildConfigValue
+        //This allows us to not make this a breaking change to embedding
+        this.applicationId = (String) BuildHelper.getBuildConfigValue(cordova.getActivity(), "APPLICATION_ID");
+        this.applicationId = preferences.getString("applicationId", this.applicationId);
+
+
+        if (action.equals("takePicture")) {
+            this.srcType = CAMERA;
+            this.destType = FILE_URI;
+            this.saveToPhotoAlbum = false;
+            this.targetHeight = 0;
+            this.targetWidth = 0;
+            this.encodingType = JPEG;
+            this.mediaType = PICTURE;
+            this.mQuality = 50;
+
+            //Take the values from the arguments if they're not already defined (this is tricky)
+            this.destType = args.getInt(1);
+            this.srcType = args.getInt(2);
+            this.mQuality = args.getInt(0);
+            this.targetWidth = args.getInt(3);
+            this.targetHeight = args.getInt(4);
+            this.encodingType = args.getInt(5);
+            this.mediaType = args.getInt(6);
+            this.allowEdit = args.getBoolean(7);
+            this.correctOrientation = args.getBoolean(8);
+            this.saveToPhotoAlbum = args.getBoolean(9);
+
+            // If the user specifies a 0 or smaller width/height
+            // make it -1 so later comparisons succeed
+            if (this.targetWidth < 1) {
+                this.targetWidth = -1;
+            }
+            if (this.targetHeight < 1) {
+                this.targetHeight = -1;
+            }
+
+            // We don't return full-quality PNG files. The camera outputs a JPEG
+            // so requesting it as a PNG provides no actual benefit
+            if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
+                    !this.correctOrientation && this.encodingType == PNG && this.srcType == CAMERA) {
+                this.encodingType = JPEG;
+            }
+
+            try {
+                if (this.srcType == CAMERA) {
+                    this.callTakePicture(destType, encodingType);
+                }
+                else if ((this.srcType == PHOTOLIBRARY) || (this.srcType == SAVEDPHOTOALBUM)) {
+                    // FIXME: Stop always requesting the permission
+                    if(!PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
+                        PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
+                    } else {
+                        this.getImage(this.srcType, destType, encodingType);
+                    }
+                }
+            }
+            catch (IllegalArgumentException e)
+            {
+                callbackContext.error("Illegal Argument Exception");
+                PluginResult r = new PluginResult(PluginResult.Status.ERROR);
+                callbackContext.sendPluginResult(r);
+                return true;
+            }
+
+            PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
+            r.setKeepCallback(true);
+            callbackContext.sendPluginResult(r);
+
+            return true;
+        }
+        return false;
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+
+    private String getTempDirectoryPath() {
+        File cache = null;
+
+        // SD Card Mounted
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            cache = cordova.getActivity().getExternalCacheDir();
+        }
+        // Use internal storage
+        else {
+            cache = cordova.getActivity().getCacheDir();
+        }
+
+        // Create the cache directory if it doesn't exist
+        cache.mkdirs();
+        return cache.getAbsolutePath();
+    }
+
+    /**
+     * Take a picture with the camera.
+     * When an image is captured or the camera view is cancelled, the result is returned
+     * in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult.
+     *
+     * The image can either be returned as a base64 string or a URI that points to the file.
+     * To display base64 string in an img tag, set the source to:
+     *      img.src="data:image/jpeg;base64,"+result;
+     * or to display URI in an img tag
+     *      img.src=result;
+     *
+     * @param returnType        Set the type of image to return.
+     * @param encodingType           Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
+     */
+    public void callTakePicture(int returnType, int encodingType) {
+        boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
+                && PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+        boolean takePicturePermission = PermissionHelper.hasPermission(this, Manifest.permission.CAMERA);
+
+        // CB-10120: The CAMERA permission does not need to be requested unless it is declared
+        // in AndroidManifest.xml. This plugin does not declare it, but others may and so we must
+        // check the package info to determine if the permission is present.
+
+        if (!takePicturePermission) {
+            takePicturePermission = true;
+            try {
+                PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+                String[] permissionsInPackage = packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
+                if (permissionsInPackage != null) {
+                    for (String permission : permissionsInPackage) {
+                        if (permission.equals(Manifest.permission.CAMERA)) {
+                            takePicturePermission = false;
+                            break;
+                        }
+                    }
+                }
+            } catch (NameNotFoundException e) {
+                // We are requesting the info for our package, so this should
+                // never be caught
+            }
+        }
+
+        if (takePicturePermission && saveAlbumPermission) {
+            takePicture(returnType, encodingType);
+        } else if (saveAlbumPermission && !takePicturePermission) {
+            PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
+        } else if (!saveAlbumPermission && takePicturePermission) {
+            PermissionHelper.requestPermissions(this, TAKE_PIC_SEC,
+                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
+        } else {
+            PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions);
+        }
+    }
+
+    public void takePicture(int returnType, int encodingType)
+    {
+        // Save the number of images currently on disk for later
+        this.numPics = queryImgDB(whichContentStore()).getCount();
+
+        // Let's use the intent and see what happens
+        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+
+        // Specify file so that large image is captured and returned
+        File photo = createCaptureFile(encodingType);
+        this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(),
+                applicationId + ".provider",
+                photo));
+        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri());
+        //We can write to this URI, this will hopefully allow us to write files to get to the next step
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        if (this.cordova != null) {
+            // Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code)
+            PackageManager mPm = this.cordova.getActivity().getPackageManager();
+            if(intent.resolveActivity(mPm) != null)
+            {
+
+                this.cordova.startActivityForResult((CordovaPlugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
+            }
+            else
+            {
+                LOG.d(LOG_TAG, "Error: You don't have a default camera.  Your device may not be CTS complaint.");
+            }
+        }
+//        else
+//            LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
+    }
+
+    /**
+     * Create a file in the applications temporary directory based upon the supplied encoding.
+     *
+     * @param encodingType of the image to be taken
+     * @return a File object pointing to the temporary picture
+     */
+    private File createCaptureFile(int encodingType) {
+        return createCaptureFile(encodingType, "");
+    }
+
+    /**
+     * Create a file in the applications temporary directory based upon the supplied encoding.
+     *
+     * @param encodingType of the image to be taken
+     * @param fileName or resultant File object.
+     * @return a File object pointing to the temporary picture
+     */
+    private File createCaptureFile(int encodingType, String fileName) {
+        if (fileName.isEmpty()) {
+            fileName = ".Pic";
+        }
+
+        if (encodingType == JPEG) {
+            fileName = fileName + ".jpg";
+        } else if (encodingType == PNG) {
+            fileName = fileName + ".png";
+        } else {
+            throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
+        }
+
+        return new File(getTempDirectoryPath(), fileName);
+    }
+
+
+
+    /**
+     * Get image from photo library.
+     *
+     * @param srcType           The album to get image from.
+     * @param returnType        Set the type of image to return.
+     * @param encodingType
+     */
+    // TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
+    // TODO: Images from kitkat filechooser not going into crop function
+    public void getImage(int srcType, int returnType, int encodingType) {
+        Intent intent = new Intent();
+        String title = GET_PICTURE;
+        croppedUri = null;
+        if (this.mediaType == PICTURE) {
+            intent.setType("image/*");
+            if (this.allowEdit) {
+                intent.setAction(Intent.ACTION_PICK);
+                intent.putExtra("crop", "true");
+                if (targetWidth > 0) {
+                    intent.putExtra("outputX", targetWidth);
+                }
+                if (targetHeight > 0) {
+                    intent.putExtra("outputY", targetHeight);
+                }
+                if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
+                    intent.putExtra("aspectX", 1);
+                    intent.putExtra("aspectY", 1);
+                }
+                File photo = createCaptureFile(JPEG);
+                croppedUri = Uri.fromFile(photo);
+                intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, croppedUri);
+            } else {
+                intent.setAction(Intent.ACTION_GET_CONTENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+            }
+        } else if (this.mediaType == VIDEO) {
+            intent.setType("video/*");
+            title = GET_VIDEO;
+            intent.setAction(Intent.ACTION_GET_CONTENT);
+            intent.addCategory(Intent.CATEGORY_OPENABLE);
+        } else if (this.mediaType == ALLMEDIA) {
+            // I wanted to make the type 'image/*, video/*' but this does not work on all versions
+            // of android so I had to go with the wildcard search.
+            intent.setType("*/*");
+            title = GET_All;
+            intent.setAction(Intent.ACTION_GET_CONTENT);
+            intent.addCategory(Intent.CATEGORY_OPENABLE);
+        }
+        if (this.cordova != null) {
+            this.cordova.startActivityForResult((CordovaPlugin) this, Intent.createChooser(intent,
+                    new String(title)), (srcType + 1) * 16 + returnType + 1);
+        }
+    }
+
+
+  /**
+   * Brings up the UI to perform crop on passed image URI
+   *
+   * @param picUri
+   */
+  private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
+    try {
+        Intent cropIntent = new Intent("com.android.camera.action.CROP");
+        // indicate image type and Uri
+        cropIntent.setDataAndType(picUri, "image/*");
+        // set crop properties
+        cropIntent.putExtra("crop", "true");
+
+
+        // indicate output X and Y
+        if (targetWidth > 0) {
+          cropIntent.putExtra("outputX", targetWidth);
+        }
+        if (targetHeight > 0) {
+          cropIntent.putExtra("outputY", targetHeight);
+        }
+        if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
+          cropIntent.putExtra("aspectX", 1);
+          cropIntent.putExtra("aspectY", 1);
+        }
+        // create new file handle to get full resolution crop
+        croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+        cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        cropIntent.putExtra("output", croppedUri);
+
+
+        // start the activity - we handle returning in onActivityResult
+
+        if (this.cordova != null) {
+            this.cordova.startActivityForResult((CordovaPlugin) this,
+                cropIntent, CROP_CAMERA + destType);
+        }
+    } catch (ActivityNotFoundException anfe) {
+      LOG.e(LOG_TAG, "Crop operation not supported on this device");
+      try {
+          processResultFromCamera(destType, cameraIntent);
+      }
+      catch (IOException e)
+      {
+          e.printStackTrace();
+          LOG.e(LOG_TAG, "Unable to write to file");
+      }
+    }
+  }
+
+    /**
+     * Applies all needed transformation to the image received from the camera.
+     *
+     * @param destType          In which form should we return the image
+     * @param intent            An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+     */
+    private void processResultFromCamera(int destType, Intent intent) throws IOException {
+        int rotate = 0;
+
+        // Create an ExifHelper to save the exif data that is lost during compression
+        ExifHelper exif = new ExifHelper();
+
+        String sourcePath = (this.allowEdit && this.croppedUri != null) ?
+                FileHelper.stripFileProtocol(this.croppedUri.toString()) :
+                this.imageUri.getFilePath();
+
+
+        if (this.encodingType == JPEG) {
+            try {
+                //We don't support PNG, so let's not pretend we do
+                exif.createInFile(sourcePath);
+                exif.readExifData();
+                rotate = exif.getOrientation();
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        Bitmap bitmap = null;
+        Uri galleryUri = null;
+
+        // CB-5479 When this option is given the unchanged image should be saved
+        // in the gallery and the modified image is saved in the temporary
+        // directory
+        if (this.saveToPhotoAlbum) {
+            galleryUri = Uri.fromFile(new File(getPicturesPath()));
+
+            if (this.allowEdit && this.croppedUri != null) {
+                writeUncompressedImage(croppedUri, galleryUri);
+            } else {
+                Uri imageUri = this.imageUri.getFileUri();
+                writeUncompressedImage(imageUri, galleryUri);
+            }
+
+            refreshGallery(galleryUri);
+        }
+
+        // If sending base64 image back
+        if (destType == DATA_URL) {
+            bitmap = getScaledAndRotatedBitmap(sourcePath);
+
+            if (bitmap == null) {
+                // Try to get the bitmap from intent.
+                bitmap = (Bitmap) intent.getExtras().get("data");
+            }
+
+            // Double-check the bitmap.
+            if (bitmap == null) {
+                LOG.d(LOG_TAG, "I either have a null image path or bitmap");
+                this.failPicture("Unable to create bitmap!");
+                return;
+            }
+
+
+            this.processPicture(bitmap, this.encodingType);
+
+            if (!this.saveToPhotoAlbum) {
+                checkForDuplicateImage(DATA_URL);
+            }
+        }
+
+        // If sending filename back
+        else if (destType == FILE_URI || destType == NATIVE_URI) {
+            // If all this is true we shouldn't compress the image.
+            if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
+                    !this.correctOrientation) {
+
+                // If we saved the uncompressed photo to the album, we can just
+                // return the URI we already created
+                if (this.saveToPhotoAlbum) {
+                    this.callbackContext.success(galleryUri.toString());
+                } else {
+                    Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+
+                    if (this.allowEdit && this.croppedUri != null) {
+                        Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
+                        writeUncompressedImage(croppedUri, uri);
+                    } else {
+                        Uri imageUri = this.imageUri.getFileUri();
+                        writeUncompressedImage(imageUri, uri);
+                    }
+
+                    this.callbackContext.success(uri.toString());
+                }
+            } else {
+                Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+                bitmap = getScaledAndRotatedBitmap(sourcePath);
+
+                // Double-check the bitmap.
+                if (bitmap == null) {
+                    LOG.d(LOG_TAG, "I either have a null image path or bitmap");
+                    this.failPicture("Unable to create bitmap!");
+                    return;
+                }
+
+
+                // Add compressed version of captured image to returned media store Uri
+                OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
+                CompressFormat compressFormat = encodingType == JPEG ?
+                        CompressFormat.JPEG :
+                        CompressFormat.PNG;
+
+                bitmap.compress(compressFormat, this.mQuality, os);
+                os.close();
+
+                // Restore exif data to file
+                if (this.encodingType == JPEG) {
+                    String exifPath;
+                    exifPath = uri.getPath();
+                    //We just finished rotating it by an arbitrary orientation, just make sure it's normal
+                    if(rotate != ExifInterface.ORIENTATION_NORMAL)
+                        exif.resetOrientation();
+                    exif.createOutFile(exifPath);
+                    exif.writeExifData();
+                }
+
+                // Send Uri back to JavaScript for viewing image
+                this.callbackContext.success(uri.toString());
+
+            }
+        } else {
+            throw new IllegalStateException();
+        }
+
+        this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap);
+        bitmap = null;
+    }
+
+    private String getPicturesPath() {
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+        File storageDir = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        storageDir.mkdirs();
+        String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName;
+        return galleryPath;
+    }
+
+    private void refreshGallery(Uri contentUri) {
+        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+        mediaScanIntent.setData(contentUri);
+        this.cordova.getActivity().sendBroadcast(mediaScanIntent);
+    }
+
+    /**
+     * Converts output image format int value to string value of mime type.
+     * @param outputFormat int Output format of camera API.
+     *                     Must be value of either JPEG or PNG constant
+     * @return String String value of mime type or empty string if mime type is not supported
+     */
+    private String getMimetypeForFormat(int outputFormat) {
+        if (outputFormat == PNG) return "image/png";
+        if (outputFormat == JPEG) return "image/jpeg";
+        return "";
+    }
+
+
+    private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
+        // Some content: URIs do not map to file paths (e.g. picasa).
+        String realPath = FileHelper.getRealPath(uri, this.cordova);
+
+        // Get filename from uri
+        String fileName = realPath != null ?
+                realPath.substring(realPath.lastIndexOf('/') + 1) :
+                "modified." + (this.encodingType == JPEG ? "jpg" : "png");
+
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        //String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+        String modifiedPath = getTempDirectoryPath() + "/" + fileName;
+
+        OutputStream os = new FileOutputStream(modifiedPath);
+        CompressFormat compressFormat = this.encodingType == JPEG ?
+                CompressFormat.JPEG :
+                CompressFormat.PNG;
+
+        bitmap.compress(compressFormat, this.mQuality, os);
+        os.close();
+
+        if (exifData != null && this.encodingType == JPEG) {
+            try {
+                if (this.correctOrientation && this.orientationCorrected) {
+                    exifData.resetOrientation();
+                }
+                exifData.createOutFile(modifiedPath);
+                exifData.writeExifData();
+                exifData = null;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return modifiedPath;
+    }
+
+
+    /**
+     * Applies all needed transformation to the image received from the gallery.
+     *
+     * @param destType In which form should we return the image
+     * @param intent   An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+     */
+    private void processResultFromGallery(int destType, Intent intent) {
+        Uri uri = intent.getData();
+        if (uri == null) {
+            if (croppedUri != null) {
+                uri = croppedUri;
+            } else {
+                this.failPicture("null data from photo library");
+                return;
+            }
+        }
+        int rotate = 0;
+
+        String fileLocation = FileHelper.getRealPath(uri, this.cordova);
+        LOG.d(LOG_TAG, "File locaton is: " + fileLocation);
+
+        // If you ask for video or all media type you will automatically get back a file URI
+        // and there will be no attempt to resize any returned data
+        if (this.mediaType != PICTURE) {
+            this.callbackContext.success(fileLocation);
+        }
+        else {
+            String uriString = uri.toString();
+            // Get the path to the image. Makes loading so much easier.
+            String mimeType = FileHelper.getMimeType(uriString, this.cordova);
+
+            // This is a special case to just return the path as no scaling,
+            // rotating, nor compressing needs to be done
+            if (this.targetHeight == -1 && this.targetWidth == -1 &&
+                    (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation &&
+                    mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
+            {
+                this.callbackContext.success(uriString);
+            } else {
+                // If we don't have a valid image so quit.
+                if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) {
+                    LOG.d(LOG_TAG, "I either have a null image path or bitmap");
+                    this.failPicture("Unable to retrieve path to picture!");
+                    return;
+                }
+                Bitmap bitmap = null;
+                try {
+                    bitmap = getScaledAndRotatedBitmap(uriString);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                if (bitmap == null) {
+                    LOG.d(LOG_TAG, "I either have a null image path or bitmap");
+                    this.failPicture("Unable to create bitmap!");
+                    return;
+                }
+
+                // If sending base64 image back
+                if (destType == DATA_URL) {
+                    this.processPicture(bitmap, this.encodingType);
+                }
+
+                // If sending filename back
+                else if (destType == FILE_URI || destType == NATIVE_URI) {
+                    // Did we modify the image?
+                    if ( (this.targetHeight > 0 && this.targetWidth > 0) ||
+                            (this.correctOrientation && this.orientationCorrected) ||
+                            !mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
+                    {
+                        try {
+                            String modifiedPath = this.outputModifiedBitmap(bitmap, uri);
+                            // The modified image is cached by the app in order to get around this and not have to delete you
+                            // application cache I'm adding the current system time to the end of the file url.
+                            this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis());
+
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            this.failPicture("Error retrieving image.");
+                        }
+                    } else {
+                        this.callbackContext.success(fileLocation);
+                    }
+                }
+                if (bitmap != null) {
+                    bitmap.recycle();
+                    bitmap = null;
+                }
+                System.gc();
+            }
+        }
+    }
+
+    /**
+     * Called when the camera view exits.
+     *
+     * @param requestCode The request code originally supplied to startActivityForResult(),
+     *                    allowing you to identify who this result came from.
+     * @param resultCode  The integer result code returned by the child activity through its setResult().
+     * @param intent      An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+     */
+    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+
+        // Get src and dest types from request code for a Camera Activity
+        int srcType = (requestCode / 16) - 1;
+        int destType = (requestCode % 16) - 1;
+
+        // If Camera Crop
+        if (requestCode >= CROP_CAMERA) {
+            if (resultCode == Activity.RESULT_OK) {
+
+                // Because of the inability to pass through multiple intents, this hack will allow us
+                // to pass arcane codes back.
+                destType = requestCode - CROP_CAMERA;
+                try {
+                    processResultFromCamera(destType, intent);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    LOG.e(LOG_TAG, "Unable to write to file");
+                }
+
+            }// If cancelled
+            else if (resultCode == Activity.RESULT_CANCELED) {
+                this.failPicture("No Image Selected");
+            }
+
+            // If something else
+            else {
+                this.failPicture("Did not complete!");
+            }
+        }
+        // If CAMERA
+        else if (srcType == CAMERA) {
+            // If image available
+            if (resultCode == Activity.RESULT_OK) {
+                try {
+                    if (this.allowEdit) {
+                        Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
+                                applicationId + ".provider",
+                                createCaptureFile(this.encodingType));
+                        performCrop(tmpFile, destType, intent);
+                    } else {
+                        this.processResultFromCamera(destType, intent);
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    this.failPicture("Error capturing image.");
+                }
+            }
+
+            // If cancelled
+            else if (resultCode == Activity.RESULT_CANCELED) {
+                this.failPicture("No Image Selected");
+            }
+
+            // If something else
+            else {
+                this.failPicture("Did not complete!");
+            }
+        }
+        // If retrieving photo from library
+        else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
+            if (resultCode == Activity.RESULT_OK && intent != null) {
+                final Intent i = intent;
+                final int finalDestType = destType;
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        processResultFromGallery(finalDestType, i);
+                    }
+                });
+            } else if (resultCode == Activity.RESULT_CANCELED) {
+                this.failPicture("No Image Selected");
+            } else {
+                this.failPicture("Selection did not complete!");
+            }
+        }
+    }
+
+    private int exifToDegrees(int exifOrientation) {
+        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
+            return 90;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
+            return 180;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
+            return 270;
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Write an inputstream to local disk
+     *
+     * @param fis - The InputStream to write
+     * @param dest - Destination on disk to write to
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeUncompressedImage(InputStream fis, Uri dest) throws FileNotFoundException,
+            IOException {
+        OutputStream os = null;
+        try {
+            os = this.cordova.getActivity().getContentResolver().openOutputStream(dest);
+            byte[] buffer = new byte[4096];
+            int len;
+            while ((len = fis.read(buffer)) != -1) {
+                os.write(buffer, 0, len);
+            }
+            os.flush();
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    LOG.d(LOG_TAG, "Exception while closing output stream.");
+                }
+            }
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                }
+            }
+        }
+    }
+    /**
+     * In the special case where the default width, height and quality are unchanged
+     * we just write the file out to disk saving the expensive Bitmap.compress function.
+     *
+     * @param src
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException,
+            IOException {
+
+        FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString()));
+        writeUncompressedImage(fis, dest);
+
+    }
+
+    /**
+     * Create entry in media store for image
+     *
+     * @return uri
+     */
+    private Uri getUriFromMediaStore() {
+        ContentValues values = new ContentValues();
+        values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
+        Uri uri;
+        try {
+            uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+        } catch (RuntimeException e) {
+            LOG.d(LOG_TAG, "Can't write to external media storage.");
+            try {
+                uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
+            } catch (RuntimeException ex) {
+                LOG.d(LOG_TAG, "Can't write to internal media storage.");
+                return null;
+            }
+        }
+        return uri;
+    }
+
+    /**
+     * Return a scaled and rotated bitmap based on the target width and height
+     *
+     * @param imageUrl
+     * @return
+     * @throws IOException
+     */
+    private Bitmap getScaledAndRotatedBitmap(String imageUrl) throws IOException {
+        // If no new width or height were specified, and orientation is not needed return the original bitmap
+        if (this.targetWidth <= 0 && this.targetHeight <= 0 && !(this.correctOrientation)) {
+            InputStream fileStream = null;
+            Bitmap image = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
+                image = BitmapFactory.decodeStream(fileStream);
+            }  catch (OutOfMemoryError e) {
+                callbackContext.error(e.getLocalizedMessage());
+            } catch (Exception e){
+                callbackContext.error(e.getLocalizedMessage());
+            }
+            finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+            return image;
+        }
+
+
+        /*  Copy the inputstream to a temporary file on the device.
+            We then use this temporary file to determine the width/height/orientation.
+            This is the only way to determine the orientation of the photo coming from 3rd party providers (Google Drive, Dropbox,etc)
+            This also ensures we create a scaled bitmap with the correct orientation
+
+             We delete the temporary file once we are done
+         */
+        File localFile = null;
+        Uri galleryUri = null;
+        int rotate = 0;
+        try {
+            InputStream fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
+            if (fileStream != null) {
+                // Generate a temporary file
+                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+                String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+                localFile = new File(getTempDirectoryPath() + fileName);
+                galleryUri = Uri.fromFile(localFile);
+                writeUncompressedImage(fileStream, galleryUri);
+                try {
+                    String mimeType = FileHelper.getMimeType(imageUrl.toString(), cordova);
+                    if ("image/jpeg".equalsIgnoreCase(mimeType)) {
+                        //  ExifInterface doesn't like the file:// prefix
+                        String filePath = galleryUri.toString().replace("file://", "");
+                        // read exifData of source
+                        exifData = new ExifHelper();
+                        exifData.createInFile(filePath);
+                        // Use ExifInterface to pull rotation information
+                        if (this.correctOrientation) {
+                            ExifInterface exif = new ExifInterface(filePath);
+                            rotate = exifToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED));
+                        }
+                    }
+                } catch (Exception oe) {
+                    LOG.w(LOG_TAG,"Unable to read Exif data: "+ oe.toString());
+                    rotate = 0;
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString());
+            return null;
+        }
+
+
+
+        try {
+            // figure out the original width and height of the image
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            options.inJustDecodeBounds = true;
+            InputStream fileStream = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
+                BitmapFactory.decodeStream(fileStream, null, options);
+            } finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+
+
+            //CB-2292: WTF? Why is the width null?
+            if (options.outWidth == 0 || options.outHeight == 0) {
+                return null;
+            }
+
+            // User didn't specify output dimensions, but they need orientation
+            if (this.targetWidth <= 0 && this.targetHeight <= 0) {
+                this.targetWidth = options.outWidth;
+                this.targetHeight = options.outHeight;
+            }
+
+            // Setup target width/height based on orientation
+            int rotatedWidth, rotatedHeight;
+            boolean rotated= false;
+            if (rotate == 90 || rotate == 270) {
+                rotatedWidth = options.outHeight;
+                rotatedHeight = options.outWidth;
+                rotated = true;
+            } else {
+                rotatedWidth = options.outWidth;
+                rotatedHeight = options.outHeight;
+            }
+
+            // determine the correct aspect ratio
+            int[] widthHeight = calculateAspectRatio(rotatedWidth, rotatedHeight);
+
+
+            // Load in the smallest bitmap possible that is closest to the size we want
+            options.inJustDecodeBounds = false;
+            options.inSampleSize = calculateSampleSize(rotatedWidth, rotatedHeight,  widthHeight[0], widthHeight[1]);
+            Bitmap unscaledBitmap = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
+                unscaledBitmap = BitmapFactory.decodeStream(fileStream, null, options);
+            } finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+            if (unscaledBitmap == null) {
+                return null;
+            }
+
+            int scaledWidth = (!rotated) ? widthHeight[0] : widthHeight[1];
+            int scaledHeight = (!rotated) ? widthHeight[1] : widthHeight[0];
+
+            Bitmap scaledBitmap = Bitmap.createScaledBitmap(unscaledBitmap, scaledWidth, scaledHeight, true);
+            if (scaledBitmap != unscaledBitmap) {
+                unscaledBitmap.recycle();
+                unscaledBitmap = null;
+            }
+            if (this.correctOrientation && (rotate != 0)) {
+                Matrix matrix = new Matrix();
+                matrix.setRotate(rotate);
+                try {
+                    scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
+                    this.orientationCorrected = true;
+                } catch (OutOfMemoryError oom) {
+                    this.orientationCorrected = false;
+                }
+            }
+            return scaledBitmap;
+        }
+        finally {
+            // delete the temporary copy
+            if (localFile != null) {
+                localFile.delete();
+            }
+        }
+
+    }
+
+    /**
+     * Maintain the aspect ratio so the resulting image does not look smooshed
+     *
+     * @param origWidth
+     * @param origHeight
+     * @return
+     */
+    public int[] calculateAspectRatio(int origWidth, int origHeight) {
+        int newWidth = this.targetWidth;
+        int newHeight = this.targetHeight;
+
+        // If no new width or height were specified return the original bitmap
+        if (newWidth <= 0 && newHeight <= 0) {
+            newWidth = origWidth;
+            newHeight = origHeight;
+        }
+        // Only the width was specified
+        else if (newWidth > 0 && newHeight <= 0) {
+            newHeight = (int)((double)(newWidth / (double)origWidth) * origHeight);
+        }
+        // only the height was specified
+        else if (newWidth <= 0 && newHeight > 0) {
+            newWidth = (int)((double)(newHeight / (double)origHeight) * origWidth);
+        }
+        // If the user specified both a positive width and height
+        // (potentially different aspect ratio) then the width or height is
+        // scaled so that the image fits while maintaining aspect ratio.
+        // Alternatively, the specified width and height could have been
+        // kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
+        // would result in whitespace in the new image.
+        else {
+            double newRatio = newWidth / (double) newHeight;
+            double origRatio = origWidth / (double) origHeight;
+
+            if (origRatio > newRatio) {
+                newHeight = (newWidth * origHeight) / origWidth;
+            } else if (origRatio < newRatio) {
+                newWidth = (newHeight * origWidth) / origHeight;
+            }
+        }
+
+        int[] retval = new int[2];
+        retval[0] = newWidth;
+        retval[1] = newHeight;
+        return retval;
+    }
+
+    /**
+     * Figure out what ratio we can load our image into memory at while still being bigger than
+     * our desired width and height
+     *
+     * @param srcWidth
+     * @param srcHeight
+     * @param dstWidth
+     * @param dstHeight
+     * @return
+     */
+    public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
+        final float srcAspect = (float) srcWidth / (float) srcHeight;
+        final float dstAspect = (float) dstWidth / (float) dstHeight;
+
+        if (srcAspect > dstAspect) {
+            return srcWidth / dstWidth;
+        } else {
+            return srcHeight / dstHeight;
+        }
+    }
+
+    /**
+     * Creates a cursor that can be used to determine how many images we have.
+     *
+     * @return a cursor
+     */
+    private Cursor queryImgDB(Uri contentStore) {
+        return this.cordova.getActivity().getContentResolver().query(
+                contentStore,
+                new String[]{MediaStore.Images.Media._ID},
+                null,
+                null,
+                null);
+    }
+
+    /**
+     * Cleans up after picture taking. Checking for duplicates and that kind of stuff.
+     *
+     * @param newImage
+     */
+    private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) {
+        if (bitmap != null) {
+            bitmap.recycle();
+        }
+
+        // Clean up initial camera-written image file.
+        (new File(FileHelper.stripFileProtocol(oldImage.toString()))).delete();
+
+        checkForDuplicateImage(imageType);
+        // Scan for the gallery to update pic refs in gallery
+        if (this.saveToPhotoAlbum && newImage != null) {
+            this.scanForGallery(newImage);
+        }
+
+        System.gc();
+    }
+
+    /**
+     * Used to find out if we are in a situation where the Camera Intent adds to images
+     * to the content store. If we are using a FILE_URI and the number of images in the DB
+     * increases by 2 we have a duplicate, when using a DATA_URL the number is 1.
+     *
+     * @param type FILE_URI or DATA_URL
+     */
+    private void checkForDuplicateImage(int type) {
+        int diff = 1;
+        Uri contentStore = whichContentStore();
+        Cursor cursor = queryImgDB(contentStore);
+        int currentNumOfImages = cursor.getCount();
+
+        if (type == FILE_URI && this.saveToPhotoAlbum) {
+            diff = 2;
+        }
+
+        // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
+        if ((currentNumOfImages - numPics) == diff) {
+            cursor.moveToLast();
+            int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID)));
+            if (diff == 2) {
+                id--;
+            }
+            Uri uri = Uri.parse(contentStore + "/" + id);
+            this.cordova.getActivity().getContentResolver().delete(uri, null, null);
+            cursor.close();
+        }
+    }
+
+    /**
+     * Determine if we are storing the images in internal or external storage
+     *
+     * @return Uri
+     */
+    private Uri whichContentStore() {
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            return android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+        } else {
+            return android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI;
+        }
+    }
+
+    /**
+     * Compress bitmap using jpeg, convert to Base64 encoded string, and return to JavaScript.
+     *
+     * @param bitmap
+     */
+    public void processPicture(Bitmap bitmap, int encodingType) {
+        ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
+        CompressFormat compressFormat = encodingType == JPEG ?
+                CompressFormat.JPEG :
+                CompressFormat.PNG;
+
+        try {
+            if (bitmap.compress(compressFormat, mQuality, jpeg_data)) {
+                byte[] code = jpeg_data.toByteArray();
+                byte[] output = Base64.encode(code, Base64.NO_WRAP);
+                String js_out = new String(output);
+                this.callbackContext.success(js_out);
+                js_out = null;
+                output = null;
+                code = null;
+            }
+        } catch (Exception e) {
+            this.failPicture("Error compressing image.");
+        }
+        jpeg_data = null;
+    }
+
+    /**
+     * Send error message to JavaScript.
+     *
+     * @param err
+     */
+    public void failPicture(String err) {
+        this.callbackContext.error(err);
+    }
+
+    private void scanForGallery(Uri newImage) {
+        this.scanMe = newImage;
+        if (this.conn != null) {
+            this.conn.disconnect();
+        }
+        this.conn = new MediaScannerConnection(this.cordova.getActivity().getApplicationContext(), this);
+        conn.connect();
+    }
+
+    public void onMediaScannerConnected() {
+        try {
+            this.conn.scanFile(this.scanMe.toString(), "image/*");
+        } catch (java.lang.IllegalStateException e) {
+            LOG.e(LOG_TAG, "Can't scan file in MediaScanner after taking picture");
+        }
+
+    }
+
+    public void onScanCompleted(String path, Uri uri) {
+        this.conn.disconnect();
+    }
+
+
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+        for (int r : grantResults) {
+            if (r == PackageManager.PERMISSION_DENIED) {
+                this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
+                return;
+            }
+        }
+        switch (requestCode) {
+            case TAKE_PIC_SEC:
+                takePicture(this.destType, this.encodingType);
+                break;
+            case SAVE_TO_ALBUM_SEC:
+                this.getImage(this.srcType, this.destType, this.encodingType);
+                break;
+        }
+    }
+
+    /**
+     * Taking or choosing a picture launches another Activity, so we need to implement the
+     * save/restore APIs to handle the case where the CordovaActivity is killed by the OS
+     * before we get the launched Activity's result.
+     */
+    public Bundle onSaveInstanceState() {
+        Bundle state = new Bundle();
+        state.putInt("destType", this.destType);
+        state.putInt("srcType", this.srcType);
+        state.putInt("mQuality", this.mQuality);
+        state.putInt("targetWidth", this.targetWidth);
+        state.putInt("targetHeight", this.targetHeight);
+        state.putInt("encodingType", this.encodingType);
+        state.putInt("mediaType", this.mediaType);
+        state.putInt("numPics", this.numPics);
+        state.putBoolean("allowEdit", this.allowEdit);
+        state.putBoolean("correctOrientation", this.correctOrientation);
+        state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
+
+        if (this.croppedUri != null) {
+            state.putString("croppedUri", this.croppedUri.toString());
+        }
+
+        if (this.imageUri != null) {
+            state.putString("imageUri", this.imageUri.getFileUri().toString());
+        }
+
+        return state;
+    }
+
+    public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
+        this.destType = state.getInt("destType");
+        this.srcType = state.getInt("srcType");
+        this.mQuality = state.getInt("mQuality");
+        this.targetWidth = state.getInt("targetWidth");
+        this.targetHeight = state.getInt("targetHeight");
+        this.encodingType = state.getInt("encodingType");
+        this.mediaType = state.getInt("mediaType");
+        this.numPics = state.getInt("numPics");
+        this.allowEdit = state.getBoolean("allowEdit");
+        this.correctOrientation = state.getBoolean("correctOrientation");
+        this.saveToPhotoAlbum = state.getBoolean("saveToPhotoAlbum");
+
+        if (state.containsKey("croppedUri")) {
+            this.croppedUri = Uri.parse(state.getString("croppedUri"));
+        }
+
+        if (state.containsKey("imageUri")) {
+            //I have no idea what type of URI is being passed in
+            this.imageUri = new CordovaUri(Uri.parse(state.getString("imageUri")));
+        }
+
+        this.callbackContext = callbackContext;
+    }
+
+ /*
+  * This is dirty, but it does the job.
+  *
+  * Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
+  * and since we actually need the Camera to create the file for us most of the time, we don't
+  * actually write the file, just generate the location based on a timestamp, we need to get it
+  * back from the Intent.
+  *
+  * However, the FilesProvider preserves the path, so we can at least write to it from here, since
+  * we own the context in this case.
+ */
+
+    private String getFileNameFromUri(Uri uri) {
+        String fullUri = uri.toString();
+        String partial_path = fullUri.split("external_files")[1];
+        File external_storage = Environment.getExternalStorageDirectory();
+        String path = external_storage.getAbsolutePath() + partial_path;
+        return path;
+
+    }
+
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java
new file mode 100644
index 0000000..5c2224d
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/camera/CordovaUri.java
@@ -0,0 +1,104 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.camera;
+
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.support.v4.content.FileProvider;
+
+import java.io.File;
+
+/*
+ * This class exists because Andorid FilesProvider doesn't work on Android 4.4.4 and below and throws
+ * weird errors.  I'm not sure why writing to shared cache directories is somehow verboten, but it is
+ * and this error is irritating for a Compatibility library to have.
+ *
+ */
+
+public class CordovaUri {
+
+    private Uri androidUri;
+    private String fileName;
+    private Uri fileUri;
+
+    /*
+     * We always expect a FileProvider string to be passed in for the file that we create
+     *
+     */
+    CordovaUri (Uri inputUri)
+    {
+        //Determine whether the file is a content or file URI
+        if(inputUri.getScheme().equals("content"))
+        {
+            androidUri = inputUri;
+            fileName = getFileNameFromUri(androidUri);
+            fileUri = Uri.parse("file://" + fileName);
+        }
+        else
+        {
+            fileUri = inputUri;
+            fileName = FileHelper.stripFileProtocol(inputUri.toString());
+        }
+    }
+
+    public Uri getFileUri()
+    {
+        return fileUri;
+    }
+
+    public String getFilePath()
+    {
+        return fileName;
+    }
+
+    /*
+     * This only gets called by takePicture
+     */
+
+    public Uri getCorrectUri()
+    {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+            return androidUri;
+        else
+            return fileUri;
+    }
+
+ /*
+  * This is dirty, but it does the job.
+  *
+  * Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
+  * and since we actually need the Camera to create the file for us most of the time, we don't
+  * actually write the file, just generate the location based on a timestamp, we need to get it
+  * back from the Intent.
+  *
+  * However, the FilesProvider preserves the path, so we can at least write to it from here, since
+  * we own the context in this case.
+ */
+
+    private String getFileNameFromUri(Uri uri) {
+        String fullUri = uri.toString();
+        String partial_path = fullUri.split("external_files")[1];
+        File external_storage = Environment.getExternalStorageDirectory();
+        String path = external_storage.getAbsolutePath() + partial_path;
+        return path;
+
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java
new file mode 100644
index 0000000..5160a2f
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/camera/ExifHelper.java
@@ -0,0 +1,185 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.camera;
+
+import java.io.IOException;
+
+import android.media.ExifInterface;
+
+public class ExifHelper {
+    private String aperture = null;
+    private String datetime = null;
+    private String exposureTime = null;
+    private String flash = null;
+    private String focalLength = null;
+    private String gpsAltitude = null;
+    private String gpsAltitudeRef = null;
+    private String gpsDateStamp = null;
+    private String gpsLatitude = null;
+    private String gpsLatitudeRef = null;
+    private String gpsLongitude = null;
+    private String gpsLongitudeRef = null;
+    private String gpsProcessingMethod = null;
+    private String gpsTimestamp = null;
+    private String iso = null;
+    private String make = null;
+    private String model = null;
+    private String orientation = null;
+    private String whiteBalance = null;
+
+    private ExifInterface inFile = null;
+    private ExifInterface outFile = null;
+
+    /**
+     * The file before it is compressed
+     *
+     * @param filePath
+     * @throws IOException
+     */
+    public void createInFile(String filePath) throws IOException {
+        this.inFile = new ExifInterface(filePath);
+    }
+
+    /**
+     * The file after it has been compressed
+     *
+     * @param filePath
+     * @throws IOException
+     */
+    public void createOutFile(String filePath) throws IOException {
+        this.outFile = new ExifInterface(filePath);
+    }
+
+    /**
+     * Reads all the EXIF data from the input file.
+     */
+    public void readExifData() {
+        this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE);
+        this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME);
+        this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
+        this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH);
+        this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
+        this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
+        this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
+        this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
+        this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
+        this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
+        this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
+        this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
+        this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
+        this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
+        this.iso = inFile.getAttribute(ExifInterface.TAG_ISO);
+        this.make = inFile.getAttribute(ExifInterface.TAG_MAKE);
+        this.model = inFile.getAttribute(ExifInterface.TAG_MODEL);
+        this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION);
+        this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
+    }
+
+    /**
+     * Writes the previously stored EXIF data to the output file.
+     *
+     * @throws IOException
+     */
+    public void writeExifData() throws IOException {
+        // Don't try to write to a null file
+        if (this.outFile == null) {
+            return;
+        }
+
+        if (this.aperture != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture);
+        }
+        if (this.datetime != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime);
+        }
+        if (this.exposureTime != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime);
+        }
+        if (this.flash != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash);
+        }
+        if (this.focalLength != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength);
+        }
+        if (this.gpsAltitude != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude);
+        }
+        if (this.gpsAltitudeRef != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef);
+        }
+        if (this.gpsDateStamp != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp);
+        }
+        if (this.gpsLatitude != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude);
+        }
+        if (this.gpsLatitudeRef != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef);
+        }
+        if (this.gpsLongitude != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude);
+        }
+        if (this.gpsLongitudeRef != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef);
+        }
+        if (this.gpsProcessingMethod != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod);
+        }
+        if (this.gpsTimestamp != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp);
+        }
+        if (this.iso != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso);
+        }
+        if (this.make != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make);
+        }
+        if (this.model != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model);
+        }
+        if (this.orientation != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation);
+        }
+        if (this.whiteBalance != null) {
+            this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance);
+        }
+
+        this.outFile.saveAttributes();
+    }
+
+    public int getOrientation() {
+        int o = Integer.parseInt(this.orientation);
+
+        if (o == ExifInterface.ORIENTATION_NORMAL) {
+            return 0;
+        } else if (o == ExifInterface.ORIENTATION_ROTATE_90) {
+            return 90;
+        } else if (o == ExifInterface.ORIENTATION_ROTATE_180) {
+            return 180;
+        } else if (o == ExifInterface.ORIENTATION_ROTATE_270) {
+            return 270;
+        } else {
+            return 0;
+        }
+    }
+
+    public void resetOrientation() {
+        this.orientation = "" + ExifInterface.ORIENTATION_NORMAL;
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java
new file mode 100644
index 0000000..ccc5e3e
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileHelper.java
@@ -0,0 +1,319 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+         http://www.apache.org/licenses/LICENSE-2.0
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.camera;
+
+import android.annotation.SuppressLint;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.webkit.MimeTypeMap;
+
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.LOG;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+public class FileHelper {
+    private static final String LOG_TAG = "FileUtils";
+    private static final String _DATA = "_data";
+
+    /**
+     * Returns the real path of the given URI string.
+     * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
+     *
+     * @param uriString the URI string of the audio/image/video
+     * @param cordova the current application context
+     * @return the full path to the file
+     */
+    @SuppressWarnings("deprecation")
+    public static String getRealPath(Uri uri, CordovaInterface cordova) {
+        String realPath = null;
+
+        if (Build.VERSION.SDK_INT < 11)
+            realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri);
+
+        // SDK >= 11
+        else
+            realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri);
+
+        return realPath;
+    }
+
+    /**
+     * Returns the real path of the given URI.
+     * If the given URI is a content:// URI, the real path is retrieved from the media store.
+     *
+     * @param uri the URI of the audio/image/video
+     * @param cordova the current application context
+     * @return the full path to the file
+     */
+    public static String getRealPath(String uriString, CordovaInterface cordova) {
+        return FileHelper.getRealPath(Uri.parse(uriString), cordova);
+    }
+
+    @SuppressLint("NewApi")
+    public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) {
+
+        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+        // DocumentProvider
+        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+
+            // ExternalStorageProvider
+            if (isExternalStorageDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    return Environment.getExternalStorageDirectory() + "/" + split[1];
+                }
+
+                // TODO handle non-primary volumes
+            }
+            // DownloadsProvider
+            else if (isDownloadsDocument(uri)) {
+
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(
+                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+                return getDataColumn(context, contentUri, null, null);
+            }
+            // MediaProvider
+            else if (isMediaDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[] {
+                        split[1]
+                };
+
+                return getDataColumn(context, contentUri, selection, selectionArgs);
+            }
+        }
+        // MediaStore (and general)
+        else if ("content".equalsIgnoreCase(uri.getScheme())) {
+
+            // Return the remote address
+            if (isGooglePhotosUri(uri))
+                return uri.getLastPathSegment();
+
+            return getDataColumn(context, uri, null, null);
+        }
+        // File
+        else if ("file".equalsIgnoreCase(uri.getScheme())) {
+            return uri.getPath();
+        }
+
+        return null;
+    }
+
+    public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
+        String[] proj = { MediaStore.Images.Media.DATA };
+        String result = null;
+
+        try {
+            Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
+            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+            cursor.moveToFirst();
+            result = cursor.getString(column_index);
+
+        } catch (Exception e) {
+            result = null;
+        }
+        return result;
+    }
+
+    /**
+     * Returns an input stream based on given URI string.
+     *
+     * @param uriString the URI string from which to obtain the input stream
+     * @param cordova the current application context
+     * @return an input stream into the data at the given URI or null if given an invalid URI string
+     * @throws IOException
+     */
+    public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova)
+            throws IOException {
+        InputStream returnValue = null;
+        if (uriString.startsWith("content")) {
+            Uri uri = Uri.parse(uriString);
+            returnValue = cordova.getActivity().getContentResolver().openInputStream(uri);
+        } else if (uriString.startsWith("file://")) {
+            int question = uriString.indexOf("?");
+            if (question > -1) {
+                uriString = uriString.substring(0, question);
+            }
+            if (uriString.startsWith("file:///android_asset/")) {
+                Uri uri = Uri.parse(uriString);
+                String relativePath = uri.getPath().substring(15);
+                returnValue = cordova.getActivity().getAssets().open(relativePath);
+            } else {
+                // might still be content so try that first
+                try {
+                    returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString));
+                } catch (Exception e) {
+                    returnValue = null;
+                }
+                if (returnValue == null) {
+                    returnValue = new FileInputStream(getRealPath(uriString, cordova));
+                }
+            }
+        } else {
+            returnValue = new FileInputStream(uriString);
+        }
+        return returnValue;
+    }
+
+    /**
+     * Removes the "file://" prefix from the given URI string, if applicable.
+     * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
+     *
+     * @param uriString the URI string to operate on
+     * @return a path without the "file://" prefix
+     */
+    public static String stripFileProtocol(String uriString) {
+        if (uriString.startsWith("file://")) {
+            uriString = uriString.substring(7);
+        }
+        return uriString;
+    }
+
+    public static String getMimeTypeForExtension(String path) {
+        String extension = path;
+        int lastDot = extension.lastIndexOf('.');
+        if (lastDot != -1) {
+            extension = extension.substring(lastDot + 1);
+        }
+        // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
+        extension = extension.toLowerCase(Locale.getDefault());
+        if (extension.equals("3ga")) {
+            return "audio/3gpp";
+        }
+        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+    }
+    
+    /**
+     * Returns the mime type of the data specified by the given URI string.
+     *
+     * @param uriString the URI string of the data
+     * @return the mime type of the specified data
+     */
+    public static String getMimeType(String uriString, CordovaInterface cordova) {
+        String mimeType = null;
+
+        Uri uri = Uri.parse(uriString);
+        if (uriString.startsWith("content://")) {
+            mimeType = cordova.getActivity().getContentResolver().getType(uri);
+        } else {
+            mimeType = getMimeTypeForExtension(uri.getPath());
+        }
+
+        return mimeType;
+    }
+
+    /**
+     * Get the value of the data column for this Uri. This is useful for
+     * MediaStore Uris, and other file-based ContentProviders.
+     *
+     * @param context The context.
+     * @param uri The Uri to query.
+     * @param selection (Optional) Filter used in the query.
+     * @param selectionArgs (Optional) Selection arguments used in the query.
+     * @return The value of the _data column, which is typically a file path.
+     * @author paulburke
+     */
+    public static String getDataColumn(Context context, Uri uri, String selection,
+                                       String[] selectionArgs) {
+
+        Cursor cursor = null;
+        final String column = "_data";
+        final String[] projection = {
+                column
+        };
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+
+                final int column_index = cursor.getColumnIndexOrThrow(column);
+                return cursor.getString(column_index);
+            }
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (cursor != null)
+                cursor.close();
+        }
+        return null;
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is ExternalStorageProvider.
+     * @author paulburke
+     */
+    public static boolean isExternalStorageDocument(Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is DownloadsProvider.
+     * @author paulburke
+     */
+    public static boolean isDownloadsDocument(Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is MediaProvider.
+     * @author paulburke
+     */
+    public static boolean isMediaDocument(Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is Google Photos.
+     */
+    public static boolean isGooglePhotosUri(Uri uri) {
+        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java
new file mode 100644
index 0000000..336f93c
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/camera/FileProvider.java
@@ -0,0 +1,21 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.camera;
+
+public class FileProvider extends android.support.v4.content.FileProvider {}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java b/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java
new file mode 100644
index 0000000..e9efcb4
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java
@@ -0,0 +1,174 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.device;
+
+import java.util.TimeZone;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaInterface;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.provider.Settings;
+
+public class Device extends CordovaPlugin {
+    public static final String TAG = "Device";
+
+    public static String platform;                            // Device OS
+    public static String uuid;                                // Device UUID
+
+    private static final String ANDROID_PLATFORM = "Android";
+    private static final String AMAZON_PLATFORM = "amazon-fireos";
+    private static final String AMAZON_DEVICE = "Amazon";
+
+    /**
+     * Constructor.
+     */
+    public Device() {
+    }
+
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     *
+     * @param cordova The context of the main Activity.
+     * @param webView The CordovaWebView Cordova is running in.
+     */
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        super.initialize(cordova, webView);
+        Device.uuid = getUuid();
+    }
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action            The action to execute.
+     * @param args              JSONArry of arguments for the plugin.
+     * @param callbackContext   The callback id used when calling back into JavaScript.
+     * @return                  True if the action was valid, false if not.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+        if ("getDeviceInfo".equals(action)) {
+            JSONObject r = new JSONObject();
+            r.put("uuid", Device.uuid);
+            r.put("version", this.getOSVersion());
+            r.put("platform", this.getPlatform());
+            r.put("model", this.getModel());
+            r.put("manufacturer", this.getManufacturer());
+	        r.put("isVirtual", this.isVirtual());
+            r.put("serial", this.getSerialNumber());
+            callbackContext.success(r);
+        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+
+    /**
+     * Get the OS name.
+     *
+     * @return
+     */
+    public String getPlatform() {
+        String platform;
+        if (isAmazonDevice()) {
+            platform = AMAZON_PLATFORM;
+        } else {
+            platform = ANDROID_PLATFORM;
+        }
+        return platform;
+    }
+
+    /**
+     * Get the device's Universally Unique Identifier (UUID).
+     *
+     * @return
+     */
+    public String getUuid() {
+        String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
+        return uuid;
+    }
+
+    public String getModel() {
+        String model = android.os.Build.MODEL;
+        return model;
+    }
+
+    public String getProductName() {
+        String productname = android.os.Build.PRODUCT;
+        return productname;
+    }
+
+    public String getManufacturer() {
+        String manufacturer = android.os.Build.MANUFACTURER;
+        return manufacturer;
+    }
+
+    public String getSerialNumber() {
+        String serial = android.os.Build.SERIAL;
+        return serial;
+    }
+
+    /**
+     * Get the OS version.
+     *
+     * @return
+     */
+    public String getOSVersion() {
+        String osversion = android.os.Build.VERSION.RELEASE;
+        return osversion;
+    }
+
+    public String getSDKVersion() {
+        @SuppressWarnings("deprecation")
+        String sdkversion = android.os.Build.VERSION.SDK;
+        return sdkversion;
+    }
+
+    public String getTimeZoneID() {
+        TimeZone tz = TimeZone.getDefault();
+        return (tz.getID());
+    }
+
+    /**
+     * Function to check if the device is manufactured by Amazon
+     *
+     * @return
+     */
+    public boolean isAmazonDevice() {
+        if (android.os.Build.MANUFACTURER.equals(AMAZON_DEVICE)) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean isVirtual() {
+	return android.os.Build.FINGERPRINT.contains("generic") ||
+	    android.os.Build.PRODUCT.contains("sdk");
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java
new file mode 100644
index 0000000..b035c40
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java
@@ -0,0 +1,294 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import android.content.res.AssetManager;
+import android.net.Uri;
+
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.LOG;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class AssetFilesystem extends Filesystem {
+
+    private final AssetManager assetManager;
+
+    // A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
+    // See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
+    private static Object listCacheLock = new Object();
+    private static boolean listCacheFromFile;
+    private static Map<String, String[]> listCache;
+    private static Map<String, Long> lengthCache;
+
+    private static final String LOG_TAG = "AssetFilesystem";
+
+    private void lazyInitCaches() {
+        synchronized (listCacheLock) {
+            if (listCache == null) {
+                ObjectInputStream ois = null;
+                try {
+                    ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
+                    listCache = (Map<String, String[]>) ois.readObject();
+                    lengthCache = (Map<String, Long>) ois.readObject();
+                    listCacheFromFile = true;
+                } catch (ClassNotFoundException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                    // Asset manifest won't exist if the gradle hook isn't set up correctly.
+                } finally {
+                    if (ois != null) {
+                        try {
+                            ois.close();
+                        } catch (IOException e) {
+                            LOG.d(LOG_TAG, e.getLocalizedMessage());
+                        }
+                    }
+                }
+                if (listCache == null) {
+                    LOG.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
+                    listCache = new HashMap<String, String[]>();
+                }
+            }
+        }
+    }
+
+    private String[] listAssets(String assetPath) throws IOException {
+        if (assetPath.startsWith("/")) {
+            assetPath = assetPath.substring(1);
+        }
+        if (assetPath.endsWith("/")) {
+            assetPath = assetPath.substring(0, assetPath.length() - 1);
+        }
+        lazyInitCaches();
+        String[] ret = listCache.get(assetPath);
+        if (ret == null) {
+            if (listCacheFromFile) {
+                ret = new String[0];
+            } else {
+                ret = assetManager.list(assetPath);
+                listCache.put(assetPath, ret);
+            }
+        }
+        return ret;
+    }
+
+    private long getAssetSize(String assetPath) throws FileNotFoundException {
+        if (assetPath.startsWith("/")) {
+            assetPath = assetPath.substring(1);
+        }
+        lazyInitCaches();
+        if (lengthCache != null) {
+            Long ret = lengthCache.get(assetPath);
+            if (ret == null) {
+                throw new FileNotFoundException("Asset not found: " + assetPath);
+            }
+            return ret;
+        }
+        CordovaResourceApi.OpenForReadResult offr = null;
+        try {
+            offr = resourceApi.openForRead(nativeUriForFullPath(assetPath));
+            long length = offr.length;
+            if (length < 0) {
+                // available() doesn't always yield the file size, but for assets it does.
+                length = offr.inputStream.available();
+            }
+            return length;
+        } catch (IOException e) {
+            FileNotFoundException fnfe = new FileNotFoundException("File not found: " + assetPath);
+            fnfe.initCause(e);
+            throw fnfe;
+        } finally {
+            if (offr != null) {
+                try {
+                    offr.inputStream.close();
+                } catch (IOException e) {
+                    LOG.d(LOG_TAG, e.getLocalizedMessage());
+                }
+            }
+        }
+    }
+
+    public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
+        super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
+        this.assetManager = assetManager;
+	}
+
+    @Override
+    public Uri toNativeUri(LocalFilesystemURL inputURL) {
+        return nativeUriForFullPath(inputURL.path);
+    }
+
+    @Override
+    public LocalFilesystemURL toLocalUri(Uri inputURL) {
+        if (!"file".equals(inputURL.getScheme())) {
+            return null;
+        }
+        File f = new File(inputURL.getPath());
+        // Removes and duplicate /s (e.g. file:///a//b/c)
+        Uri resolvedUri = Uri.fromFile(f);
+        String rootUriNoTrailingSlash = rootUri.getEncodedPath();
+        rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
+        if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
+            return null;
+        }
+        String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
+        // Strip leading slash
+        if (!subPath.isEmpty()) {
+            subPath = subPath.substring(1);
+        }
+        Uri.Builder b = new Uri.Builder()
+            .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+            .authority("localhost")
+            .path(name);
+        if (!subPath.isEmpty()) {
+            b.appendEncodedPath(subPath);
+        }
+        if (isDirectory(subPath) || inputURL.getPath().endsWith("/")) {
+            // Add trailing / for directories.
+            b.appendEncodedPath("");
+        }
+        return LocalFilesystemURL.parse(b.build());
+    }
+
+    private boolean isDirectory(String assetPath) {
+        try {
+            return listAssets(assetPath).length != 0;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        String pathNoSlashes = inputURL.path.substring(1);
+        if (pathNoSlashes.endsWith("/")) {
+            pathNoSlashes = pathNoSlashes.substring(0, pathNoSlashes.length() - 1);
+        }
+
+        String[] files;
+        try {
+            files = listAssets(pathNoSlashes);
+        } catch (IOException e) {
+            FileNotFoundException fnfe = new FileNotFoundException();
+            fnfe.initCause(e);
+            throw fnfe;
+        }
+
+        LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
+        for (int i = 0; i < files.length; ++i) {
+            entries[i] = localUrlforFullPath(new File(inputURL.path, files[i]).getPath());
+        }
+        return entries;
+	}
+
+    @Override
+    public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+                                         String path, JSONObject options, boolean directory)
+            throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+        if (options != null && options.optBoolean("create")) {
+            throw new UnsupportedOperationException("Assets are read-only");
+        }
+
+        // Check whether the supplied path is absolute or relative
+        if (directory && !path.endsWith("/")) {
+            path += "/";
+        }
+
+        LocalFilesystemURL requestedURL;
+        if (path.startsWith("/")) {
+            requestedURL = localUrlforFullPath(normalizePath(path));
+        } else {
+            requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
+        }
+
+        // Throws a FileNotFoundException if it doesn't exist.
+        getFileMetadataForLocalURL(requestedURL);
+
+        boolean isDir = isDirectory(requestedURL.path);
+        if (directory && !isDir) {
+            throw new TypeMismatchException("path doesn't exist or is file");
+        } else if (!directory && isDir) {
+            throw new TypeMismatchException("path doesn't exist or is directory");
+        }
+
+        // Return the directory
+        return makeEntryForURL(requestedURL);
+    }
+
+    @Override
+	public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        JSONObject metadata = new JSONObject();
+        long size = inputURL.isDirectory ? 0 : getAssetSize(inputURL.path);
+        try {
+        	metadata.put("size", size);
+        	metadata.put("type", inputURL.isDirectory ? "text/directory" : resourceApi.getMimeType(toNativeUri(inputURL)));
+        	metadata.put("name", new File(inputURL.path).getName());
+        	metadata.put("fullPath", inputURL.path);
+        	metadata.put("lastModifiedDate", 0);
+        } catch (JSONException e) {
+            return null;
+        }
+        return metadata;
+	}
+
+	@Override
+	public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+		return false;
+	}
+
+    @Override
+    long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset, boolean isBinary) throws NoModificationAllowedException, IOException {
+        throw new NoModificationAllowedException("Assets are read-only");
+    }
+
+    @Override
+    long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException, NoModificationAllowedException {
+        throw new NoModificationAllowedException("Assets are read-only");
+    }
+
+    @Override
+    String filesystemPathForURL(LocalFilesystemURL url) {
+        return new File(rootUri.getPath(), url.path).toString();
+    }
+
+    @Override
+    LocalFilesystemURL URLforFilesystemPath(String path) {
+        return null;
+    }
+
+    @Override
+    boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException {
+        throw new NoModificationAllowedException("Assets are read-only");
+    }
+
+    @Override
+    boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
+        throw new NoModificationAllowedException("Assets are read-only");
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java
new file mode 100644
index 0000000..6b983c0
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java
@@ -0,0 +1,223 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ContentFilesystem extends Filesystem {
+
+    private final Context context;
+
+	public ContentFilesystem(Context context, CordovaResourceApi resourceApi) {
+		super(Uri.parse("content://"), "content", resourceApi);
+        this.context = context;
+	}
+
+    @Override
+    public Uri toNativeUri(LocalFilesystemURL inputURL) {
+        String authorityAndPath = inputURL.uri.getEncodedPath().substring(this.name.length() + 2);
+        if (authorityAndPath.length() < 2) {
+            return null;
+        }
+        String ret = "content://" + authorityAndPath;
+        String query = inputURL.uri.getEncodedQuery();
+        if (query != null) {
+            ret += '?' + query;
+        }
+        String frag = inputURL.uri.getEncodedFragment();
+        if (frag != null) {
+            ret += '#' + frag;
+        }
+        return Uri.parse(ret);
+    }
+
+    @Override
+    public LocalFilesystemURL toLocalUri(Uri inputURL) {
+        if (!"content".equals(inputURL.getScheme())) {
+            return null;
+        }
+        String subPath = inputURL.getEncodedPath();
+        if (subPath.length() > 0) {
+            subPath = subPath.substring(1);
+        }
+        Uri.Builder b = new Uri.Builder()
+            .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+            .authority("localhost")
+            .path(name)
+            .appendPath(inputURL.getAuthority());
+        if (subPath.length() > 0) {
+            b.appendEncodedPath(subPath);
+        }
+        Uri localUri = b.encodedQuery(inputURL.getEncodedQuery())
+            .encodedFragment(inputURL.getEncodedFragment())
+            .build();
+        return LocalFilesystemURL.parse(localUri);
+    }
+
+    @Override
+	public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+			String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
+        throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead.");
+	}
+
+	@Override
+	public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL)
+			throws NoModificationAllowedException {
+        Uri contentUri = toNativeUri(inputURL);
+		try {
+            context.getContentResolver().delete(contentUri, null, null);
+		} catch (UnsupportedOperationException t) {
+			// Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator.
+			// The ContentResolver applies only when the file was registered in the
+			// first case, which is generally only the case with images.
+            NoModificationAllowedException nmae = new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri);
+            nmae.initCause(t);
+            throw nmae;
+		}
+        return true;
+	}
+
+	@Override
+	public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL)
+			throws NoModificationAllowedException {
+		throw new NoModificationAllowedException("Cannot remove content url");
+	}
+
+    @Override
+    public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead.");
+    }
+
+	@Override
+	public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        long size = -1;
+        long lastModified = 0;
+        Uri nativeUri = toNativeUri(inputURL);
+        String mimeType = resourceApi.getMimeType(nativeUri);
+        Cursor cursor = openCursorForURL(nativeUri);
+        try {
+            if (cursor != null && cursor.moveToFirst()) {
+                Long sizeForCursor = resourceSizeForCursor(cursor);
+                if (sizeForCursor != null) {
+                    size = sizeForCursor.longValue();
+                }
+                Long modified = lastModifiedDateForCursor(cursor);
+                if (modified != null)
+                    lastModified = modified.longValue();
+            } else {
+                // Some content providers don't support cursors at all!
+                CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri);
+                size = offr.length;
+            }
+        } catch (IOException e) {
+            FileNotFoundException fnfe = new FileNotFoundException();
+            fnfe.initCause(e);
+            throw fnfe;
+        } finally {
+        	if (cursor != null)
+        		cursor.close();
+        }
+
+        JSONObject metadata = new JSONObject();
+        try {
+        	metadata.put("size", size);
+        	metadata.put("type", mimeType);
+        	metadata.put("name", name);
+        	metadata.put("fullPath", inputURL.path);
+        	metadata.put("lastModifiedDate", lastModified);
+        } catch (JSONException e) {
+        	return null;
+        }
+        return metadata;
+	}
+
+	@Override
+	public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
+			int offset, boolean isBinary) throws NoModificationAllowedException {
+        throw new NoModificationAllowedException("Couldn't write to file given its content URI");
+    }
+	@Override
+	public long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
+			throws NoModificationAllowedException {
+        throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
+	}
+
+	protected Cursor openCursorForURL(Uri nativeUri) {
+        ContentResolver contentResolver = context.getContentResolver();
+        try {
+            return contentResolver.query(nativeUri, null, null, null, null);
+        } catch (UnsupportedOperationException e) {
+            return null;
+        }
+	}
+
+	private Long resourceSizeForCursor(Cursor cursor) {
+        int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
+        if (columnIndex != -1) {
+            String sizeStr = cursor.getString(columnIndex);
+            if (sizeStr != null) {
+            	return Long.parseLong(sizeStr);
+            }
+        }
+        return null;
+	}
+	
+	protected Long lastModifiedDateForCursor(Cursor cursor) {
+        int columnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED);
+        if (columnIndex == -1) {
+            columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
+        }
+        if (columnIndex != -1) {
+            String dateStr = cursor.getString(columnIndex);
+            if (dateStr != null) {
+                return Long.parseLong(dateStr);
+            }
+        }
+        return null;
+	}
+
+    @Override
+    public String filesystemPathForURL(LocalFilesystemURL url) {
+        File f = resourceApi.mapUriToFile(toNativeUri(url));
+        return f == null ? null : f.getAbsolutePath();
+    }
+
+	@Override
+	public LocalFilesystemURL URLforFilesystemPath(String path) {
+		// Returns null as we don't support reverse mapping back to content:// URLs
+		return null;
+	}
+
+	@Override
+	public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+		return true;
+	}
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java b/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java
new file mode 100644
index 0000000..07af5ea
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java
@@ -0,0 +1,134 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.file;
+
+import android.os.Environment;
+import android.os.StatFs;
+
+import java.io.File;
+
+/**
+ * This class provides file directory utilities.
+ * All file operations are performed on the SD card.
+ *
+ * It is used by the FileUtils class.
+ */
+public class DirectoryManager {
+
+    @SuppressWarnings("unused")
+    private static final String LOG_TAG = "DirectoryManager";
+
+    /**
+     * Determine if a file or directory exists.
+     * @param name				The name of the file to check.
+     * @return					T=exists, F=not found
+     */
+    public static boolean testFileExists(String name) {
+        boolean status;
+
+        // If SD card exists
+        if ((testSaveLocationExists()) && (!name.equals(""))) {
+            File path = Environment.getExternalStorageDirectory();
+            File newPath = constructFilePaths(path.toString(), name);
+            status = newPath.exists();
+        }
+        // If no SD card
+        else {
+            status = false;
+        }
+        return status;
+    }
+
+    /**
+     * Get the free space in external storage
+     *
+     * @return 		Size in KB or -1 if not available
+     */
+    public static long getFreeExternalStorageSpace() {
+        String status = Environment.getExternalStorageState();
+        long freeSpaceInBytes = 0;
+
+        // Check if external storage exists
+        if (status.equals(Environment.MEDIA_MOUNTED)) {
+            freeSpaceInBytes = getFreeSpaceInBytes(Environment.getExternalStorageDirectory().getPath());
+        } else {
+            // If no external storage then return -1
+            return -1;
+        }
+
+        return freeSpaceInBytes / 1024;
+    }
+
+    /**
+     * Given a path return the number of free bytes in the filesystem containing the path.
+     *
+     * @param path to the file system
+     * @return free space in bytes
+     */
+    public static long getFreeSpaceInBytes(String path) {
+        try {
+            StatFs stat = new StatFs(path);
+            long blockSize = stat.getBlockSize();
+            long availableBlocks = stat.getAvailableBlocks();
+            return availableBlocks * blockSize;
+        } catch (IllegalArgumentException e) {
+            // The path was invalid. Just return 0 free bytes.
+            return 0;
+        }
+    }
+
+    /**
+     * Determine if SD card exists.
+     *
+     * @return				T=exists, F=not found
+     */
+    public static boolean testSaveLocationExists() {
+        String sDCardStatus = Environment.getExternalStorageState();
+        boolean status;
+
+        // If SD card is mounted
+        if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
+            status = true;
+        }
+
+        // If no SD card
+        else {
+            status = false;
+        }
+        return status;
+    }
+
+    /**
+     * Create a new file object from two file paths.
+     *
+     * @param file1			Base file path
+     * @param file2			Remaining file path
+     * @return				File object
+     */
+    private static File constructFilePaths (String file1, String file2) {
+        File newPath;
+        if (file2.startsWith(file1)) {
+            newPath = new File(file2);
+        }
+        else {
+            newPath = new File(file1 + "/" + file2);
+        }
+        return newPath;
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java
new file mode 100644
index 0000000..e9e1653
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java
@@ -0,0 +1,29 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class EncodingException extends Exception {
+
+    public EncodingException(String message) {
+        super(message);
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java
new file mode 100644
index 0000000..5c4d83d
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java
@@ -0,0 +1,29 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class FileExistsException extends Exception {
+
+    public FileExistsException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java b/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java
new file mode 100644
index 0000000..1d6e61f
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java
@@ -0,0 +1,1225 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.util.Base64;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PermissionHelper;
+import org.apache.cordova.PluginResult;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * This class provides file and directory services to JavaScript.
+ */
+public class FileUtils extends CordovaPlugin {
+    private static final String LOG_TAG = "FileUtils";
+
+    public static int NOT_FOUND_ERR = 1;
+    public static int SECURITY_ERR = 2;
+    public static int ABORT_ERR = 3;
+
+    public static int NOT_READABLE_ERR = 4;
+    public static int ENCODING_ERR = 5;
+    public static int NO_MODIFICATION_ALLOWED_ERR = 6;
+    public static int INVALID_STATE_ERR = 7;
+    public static int SYNTAX_ERR = 8;
+    public static int INVALID_MODIFICATION_ERR = 9;
+    public static int QUOTA_EXCEEDED_ERR = 10;
+    public static int TYPE_MISMATCH_ERR = 11;
+    public static int PATH_EXISTS_ERR = 12;
+
+    /*
+     * Permission callback codes
+     */
+
+    public static final int ACTION_GET_FILE = 0;
+    public static final int ACTION_WRITE = 1;
+    public static final int ACTION_GET_DIRECTORY = 2;
+
+    public static final int WRITE = 3;
+    public static final int READ = 4;
+
+    public static int UNKNOWN_ERR = 1000;
+
+    private boolean configured = false;
+
+    private PendingRequests pendingRequests;
+
+
+
+    /*
+     * We need both read and write when accessing the storage, I think.
+     */
+
+    private String [] permissions = {
+            Manifest.permission.READ_EXTERNAL_STORAGE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE };
+
+    // This field exists only to support getEntry, below, which has been deprecated
+    private static FileUtils filePlugin;
+
+    private interface FileOp {
+        void run(JSONArray args) throws Exception;
+    }
+
+    private ArrayList<Filesystem> filesystems;
+
+    public void registerFilesystem(Filesystem fs) {
+    	if (fs != null && filesystemForName(fs.name)== null) {
+    		this.filesystems.add(fs);
+    	}
+    }
+
+    private Filesystem filesystemForName(String name) {
+    	for (Filesystem fs:filesystems) {
+    		if (fs != null && fs.name != null && fs.name.equals(name)) {
+    			return fs;
+    		}
+    	}
+    	return null;
+    }
+
+    protected String[] getExtraFileSystemsPreference(Activity activity) {
+        String fileSystemsStr = preferences.getString("androidextrafilesystems", "files,files-external,documents,sdcard,cache,cache-external,assets,root");
+        return fileSystemsStr.split(",");
+    }
+
+    protected void registerExtraFileSystems(String[] filesystems, HashMap<String, String> availableFileSystems) {
+        HashSet<String> installedFileSystems = new HashSet<String>();
+
+        /* Register filesystems in order */
+        for (String fsName : filesystems) {
+            if (!installedFileSystems.contains(fsName)) {
+                String fsRoot = availableFileSystems.get(fsName);
+                if (fsRoot != null) {
+                    File newRoot = new File(fsRoot);
+                    if (newRoot.mkdirs() || newRoot.isDirectory()) {
+                        registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
+                        installedFileSystems.add(fsName);
+                    } else {
+                       LOG.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
+                    }
+                } else {
+                    LOG.d(LOG_TAG, "Unrecognized extra filesystem identifier: " + fsName);
+                }
+            }
+        }
+    }
+
+    protected HashMap<String, String> getAvailableFileSystems(Activity activity) {
+        Context context = activity.getApplicationContext();
+        HashMap<String, String> availableFileSystems = new HashMap<String,String>();
+
+        availableFileSystems.put("files", context.getFilesDir().getAbsolutePath());
+        availableFileSystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath());
+        availableFileSystems.put("cache", context.getCacheDir().getAbsolutePath());
+        availableFileSystems.put("root", "/");
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+          try {
+            availableFileSystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath());
+            availableFileSystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath());
+            availableFileSystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath());
+          }
+          catch(NullPointerException e) {
+              LOG.d(LOG_TAG, "External storage unavailable, check to see if USB Mass Storage Mode is on");
+          }
+        }
+
+        return availableFileSystems;
+    }
+
+    @Override
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+    	super.initialize(cordova, webView);
+    	this.filesystems = new ArrayList<Filesystem>();
+        this.pendingRequests = new PendingRequests();
+
+    	String tempRoot = null;
+    	String persistentRoot = null;
+
+    	Activity activity = cordova.getActivity();
+    	String packageName = activity.getPackageName();
+
+        String location = preferences.getString("androidpersistentfilelocation", "internal");
+
+    	tempRoot = activity.getCacheDir().getAbsolutePath();
+    	if ("internal".equalsIgnoreCase(location)) {
+    		persistentRoot = activity.getFilesDir().getAbsolutePath() + "/files/";
+    		this.configured = true;
+    	} else if ("compatibility".equalsIgnoreCase(location)) {
+    		/*
+    		 *  Fall-back to compatibility mode -- this is the logic implemented in
+    		 *  earlier versions of this plugin, and should be maintained here so
+    		 *  that apps which were originally deployed with older versions of the
+    		 *  plugin can continue to provide access to files stored under those
+    		 *  versions.
+    		 */
+    		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+    			persistentRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
+    			tempRoot = Environment.getExternalStorageDirectory().getAbsolutePath() +
+    					"/Android/data/" + packageName + "/cache/";
+    		} else {
+    			persistentRoot = "/data/data/" + packageName;
+    		}
+    		this.configured = true;
+    	}
+
+    	if (this.configured) {
+			// Create the directories if they don't exist.
+			File tmpRootFile = new File(tempRoot);
+            File persistentRootFile = new File(persistentRoot);
+            tmpRootFile.mkdirs();
+            persistentRootFile.mkdirs();
+
+    		// Register initial filesystems
+    		// Note: The temporary and persistent filesystems need to be the first two
+    		// registered, so that they will match window.TEMPORARY and window.PERSISTENT,
+    		// per spec.
+    		this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
+    		this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
+    		this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
+            this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));
+
+            registerExtraFileSystems(getExtraFileSystemsPreference(activity), getAvailableFileSystems(activity));
+
+    		// Initialize static plugin reference for deprecated getEntry method
+    		if (filePlugin == null) {
+    			FileUtils.filePlugin = this;
+    		}
+    	} else {
+    		LOG.e(LOG_TAG, "File plugin configuration error: Please set AndroidPersistentFileLocation in config.xml to one of \"internal\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
+    		activity.finish();
+    	}
+    }
+
+    public static FileUtils getFilePlugin() {
+		return filePlugin;
+	}
+
+	private Filesystem filesystemForURL(LocalFilesystemURL localURL) {
+    	if (localURL == null) return null;
+    	return filesystemForName(localURL.fsName);
+    }
+
+    @Override
+    public Uri remapUri(Uri uri) {
+        // Remap only cdvfile: URLs (not content:).
+        if (!LocalFilesystemURL.FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
+            return null;
+        }
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		return null;
+        	}
+        	String path = fs.filesystemPathForURL(inputURL);
+        	if (path != null) {
+        		return Uri.parse("file://" + fs.filesystemPathForURL(inputURL));
+        	}
+        	return null;
+        } catch (IllegalArgumentException e) {
+        	return null;
+        }
+    }
+
+    public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
+        if (!configured) {
+            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
+            return true;
+        }
+        if (action.equals("testSaveLocationExists")) {
+            threadhelper(new FileOp() {
+                public void run(JSONArray args) {
+                    boolean b = DirectoryManager.testSaveLocationExists();
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("getFreeDiskSpace")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) {
+                    // The getFreeDiskSpace plugin API is not documented, but some apps call it anyway via exec().
+                    // For compatibility it always returns free space in the primary external storage, and
+                    // does NOT fallback to internal store if external storage is unavailable.
+                    long l = DirectoryManager.getFreeExternalStorageSpace();
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l));
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("testFileExists")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException {
+                    String fname=args.getString(0);
+                    boolean b = DirectoryManager.testFileExists(fname);
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("testDirectoryExists")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException {
+                    String fname=args.getString(0);
+                    boolean b = DirectoryManager.testFileExists(fname);
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("readAsText")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, MalformedURLException {
+                    String encoding = args.getString(1);
+                    int start = args.getInt(2);
+                    int end = args.getInt(3);
+                    String fname=args.getString(0);
+                    readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("readAsDataURL")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, MalformedURLException  {
+                    int start = args.getInt(1);
+                    int end = args.getInt(2);
+                    String fname=args.getString(0);
+                    readFileAs(fname, start, end, callbackContext, null, -1);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("readAsArrayBuffer")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, MalformedURLException  {
+                    int start = args.getInt(1);
+                    int end = args.getInt(2);
+                    String fname=args.getString(0);
+                    readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("readAsBinaryString")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, MalformedURLException  {
+                    int start = args.getInt(1);
+                    int end = args.getInt(2);
+                    String fname=args.getString(0);
+                    readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("write")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+                    String fname=args.getString(0);
+                    String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
+                    String data=args.getString(1);
+                    int offset=args.getInt(2);
+                    Boolean isBinary=args.getBoolean(3);
+
+                    if(needPermission(nativeURL, WRITE)) {
+                        getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
+                    }
+                    else {
+                        long fileSize = write(fname, data, offset, isBinary);
+                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+                    }
+
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("truncate")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+                    String fname=args.getString(0);
+                    int offset=args.getInt(1);
+                    long fileSize = truncateFile(fname, offset);
+                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("requestAllFileSystems")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws IOException, JSONException {
+                    callbackContext.success(requestAllFileSystems());
+                }
+            }, rawArgs, callbackContext);
+        } else if (action.equals("requestAllPaths")) {
+            cordova.getThreadPool().execute(
+                    new Runnable() {
+                        public void run() {
+                        	try {
+					callbackContext.success(requestAllPaths());
+				} catch (JSONException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+                        }
+                    }
+            );
+        } else if (action.equals("requestFileSystem")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException {
+                    int fstype = args.getInt(0);
+                    long requiredSize = args.optLong(1);
+                    requestFileSystem(fstype, requiredSize, callbackContext);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("resolveLocalFileSystemURI")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws IOException, JSONException {
+                    String fname=args.getString(0);
+                    JSONObject obj = resolveLocalFileSystemURI(fname);
+                    callbackContext.success(obj);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("getFileMetadata")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+                    String fname=args.getString(0);
+                    JSONObject obj = getFileMetadata(fname);
+                    callbackContext.success(obj);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("getParent")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, IOException {
+                    String fname=args.getString(0);
+                    JSONObject obj = getParent(fname);
+                    callbackContext.success(obj);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("getDirectory")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                    String dirname = args.getString(0);
+                    String path = args.getString(1);
+                    String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
+                    boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
+
+                    if(containsCreate && needPermission(nativeURL, WRITE)) {
+                        getWritePermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
+                    }
+                    else if(!containsCreate && needPermission(nativeURL, READ)) {
+                        getReadPermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
+                    }
+                    else {
+                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
+                        callbackContext.success(obj);
+                    }
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("getFile")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                    String dirname = args.getString(0);
+                    String path = args.getString(1);
+                    String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
+                    boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
+
+                    if(containsCreate && needPermission(nativeURL, WRITE)) {
+                        getWritePermission(rawArgs, ACTION_GET_FILE, callbackContext);
+                    }
+                    else if(!containsCreate && needPermission(nativeURL, READ)) {
+                        getReadPermission(rawArgs, ACTION_GET_FILE, callbackContext);
+                    }
+                    else {
+                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
+                        callbackContext.success(obj);
+                    }
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("remove")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
+                    String fname=args.getString(0);
+                    boolean success = remove(fname);
+                    if (success) {
+                        callbackContext.success();
+                    } else {
+                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+                    }
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("removeRecursively")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, FileExistsException, MalformedURLException, NoModificationAllowedException {
+                    String fname=args.getString(0);
+                    boolean success = removeRecursively(fname);
+                    if (success) {
+                        callbackContext.success();
+                    } else {
+                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+                    }
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("moveTo")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+                    String fname=args.getString(0);
+                    String newParent=args.getString(1);
+                    String newName=args.getString(2);
+                    JSONObject entry = transferTo(fname, newParent, newName, true);
+                    callbackContext.success(entry);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("copyTo")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+                    String fname=args.getString(0);
+                    String newParent=args.getString(1);
+                    String newName=args.getString(2);
+                    JSONObject entry = transferTo(fname, newParent, newName, false);
+                    callbackContext.success(entry);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("readEntries")) {
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+                    String fname=args.getString(0);
+                    JSONArray entries = readEntries(fname);
+                    callbackContext.success(entries);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else if (action.equals("_getLocalFilesystemPath")) {
+            // Internal method for testing: Get the on-disk location of a local filesystem url.
+            // [Currently used for testing file-transfer]
+            threadhelper( new FileOp( ){
+                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
+                    String localURLstr = args.getString(0);
+                    String fname = filesystemPathForURL(localURLstr);
+                    callbackContext.success(fname);
+                }
+            }, rawArgs, callbackContext);
+        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    private void getReadPermission(String rawArgs, int action, CallbackContext callbackContext) {
+        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE);
+    }
+
+    private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
+        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
+        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+    }
+
+    private boolean hasReadPermission() {
+        return PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
+    }
+
+    private boolean hasWritePermission() {
+        return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+    }
+
+    private boolean needPermission(String nativeURL, int permissionType) throws JSONException {
+        JSONObject j = requestAllPaths();
+        ArrayList<String> allowedStorageDirectories = new ArrayList<String>();
+        allowedStorageDirectories.add(j.getString("applicationDirectory"));
+        allowedStorageDirectories.add(j.getString("applicationStorageDirectory"));
+        if(j.has("externalApplicationStorageDirectory")) {
+            allowedStorageDirectories.add(j.getString("externalApplicationStorageDirectory"));
+        }
+
+        if(permissionType == READ && hasReadPermission()) {
+            return false;
+        }
+        else if(permissionType == WRITE && hasWritePermission()) {
+            return false;
+        }
+
+        // Permission required if the native url lies outside the allowed storage directories
+        for(String directory : allowedStorageDirectories) {
+            if(nativeURL.startsWith(directory)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
+        LocalFilesystemURL localURL = null;
+
+        // Try all installed filesystems. Return the best matching URL
+        // (determined by the shortest resulting URL)
+        for (Filesystem fs : filesystems) {
+            LocalFilesystemURL url = fs.toLocalUri(nativeUri);
+            if (url != null) {
+                // A shorter fullPath implies that the filesystem is a better
+                // match for the local path than the previous best.
+                if (localURL == null || (url.uri.toString().length() < localURL.toString().length())) {
+                    localURL = url;
+                }
+            }
+        }
+        return localURL;
+    }
+
+    /*
+     * These two native-only methods can be used by other plugins to translate between
+     * device file system paths and URLs. By design, there is no direct JavaScript
+     * interface to these methods.
+     */
+
+    public String filesystemPathForURL(String localURLstr) throws MalformedURLException {
+        try {
+            LocalFilesystemURL inputURL = LocalFilesystemURL.parse(localURLstr);
+            Filesystem fs = this.filesystemForURL(inputURL);
+            if (fs == null) {
+                throw new MalformedURLException("No installed handlers for this URL");
+            }
+            return fs.filesystemPathForURL(inputURL);
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+    public LocalFilesystemURL filesystemURLforLocalPath(String localPath) {
+        LocalFilesystemURL localURL = null;
+        int shortestFullPath = 0;
+
+        // Try all installed filesystems. Return the best matching URL
+        // (determined by the shortest resulting URL)
+        for (Filesystem fs: filesystems) {
+            LocalFilesystemURL url = fs.URLforFilesystemPath(localPath);
+            if (url != null) {
+                // A shorter fullPath implies that the filesystem is a better
+                // match for the local path than the previous best.
+                if (localURL == null || (url.path.length() < shortestFullPath)) {
+                    localURL = url;
+                    shortestFullPath = url.path.length();
+                }
+            }
+        }
+        return localURL;
+    }
+
+
+	/* helper to execute functions async and handle the result codes
+     *
+     */
+    private void threadhelper(final FileOp f, final String rawArgs, final CallbackContext callbackContext){
+        cordova.getThreadPool().execute(new Runnable() {
+            public void run() {
+                try {
+                    JSONArray args = new JSONArray(rawArgs);
+                    f.run(args);
+                } catch ( Exception e) {
+                    if( e instanceof EncodingException){
+                        callbackContext.error(FileUtils.ENCODING_ERR);
+                    } else if(e instanceof FileNotFoundException) {
+                        callbackContext.error(FileUtils.NOT_FOUND_ERR);
+                    } else if(e instanceof FileExistsException) {
+                        callbackContext.error(FileUtils.PATH_EXISTS_ERR);
+                    } else if(e instanceof NoModificationAllowedException ) {
+                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
+                    } else if(e instanceof InvalidModificationException ) {
+                        callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
+                    } else if(e instanceof MalformedURLException ) {
+                        callbackContext.error(FileUtils.ENCODING_ERR);
+                    } else if(e instanceof IOException ) {
+                        callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
+                    } else if(e instanceof EncodingException ) {
+                        callbackContext.error(FileUtils.ENCODING_ERR);
+                    } else if(e instanceof TypeMismatchException ) {
+                        callbackContext.error(FileUtils.TYPE_MISMATCH_ERR);
+                    } else if(e instanceof JSONException ) {
+                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+                    } else if (e instanceof SecurityException) {
+                        callbackContext.error(FileUtils.SECURITY_ERR);
+                    } else {
+                        e.printStackTrace();
+                    	callbackContext.error(FileUtils.UNKNOWN_ERR);
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Allows the user to look up the Entry for a file or directory referred to by a local URI.
+     *
+     * @param uriString of the file/directory to look up
+     * @return a JSONObject representing a Entry from the filesystem
+     * @throws MalformedURLException if the url is not valid
+     * @throws FileNotFoundException if the file does not exist
+     * @throws IOException if the user can't read the file
+     * @throws JSONException
+     */
+    private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
+        if (uriString == null) {
+            throw new MalformedURLException("Unrecognized filesystem URL");
+        }
+        Uri uri = Uri.parse(uriString);
+        boolean isNativeUri = false;
+
+        LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
+        if (inputURL == null) {
+            /* Check for file://, content:// urls */
+            inputURL = resolveNativeUri(uri);
+            isNativeUri = true;
+        }
+
+        try {
+            Filesystem fs = this.filesystemForURL(inputURL);
+            if (fs == null) {
+                throw new MalformedURLException("No installed handlers for this URL");
+            }
+            if (fs.exists(inputURL)) {
+                if (!isNativeUri) {
+                    // If not already resolved as native URI, resolve to a native URI and back to
+                    // fix the terminating slash based on whether the entry is a directory or file.
+                    inputURL = fs.toLocalUri(fs.toNativeUri(inputURL));
+                }
+
+                return fs.getEntryForLocalURL(inputURL);
+            }
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+        throw new FileNotFoundException();
+    }
+
+    /**
+     * Read the list of files from this directory.
+     *
+     * @return a JSONArray containing JSONObjects that represent Entry objects.
+     * @throws FileNotFoundException if the directory is not found.
+     * @throws JSONException
+     * @throws MalformedURLException
+     */
+    private JSONArray readEntries(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.readEntriesAtLocalURL(inputURL);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+    /**
+     * A setup method that handles the move/copy of files/directories
+     *
+     * @param newName for the file directory to be called, if null use existing file name
+     * @param move if false do a copy, if true do a move
+     * @return a Entry object
+     * @throws NoModificationAllowedException
+     * @throws IOException
+     * @throws InvalidModificationException
+     * @throws EncodingException
+     * @throws JSONException
+     * @throws FileExistsException
+     */
+    private JSONObject transferTo(String srcURLstr, String destURLstr, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
+        if (srcURLstr == null || destURLstr == null) {
+            // either no source or no destination provided
+        	throw new FileNotFoundException();
+        }
+
+        LocalFilesystemURL srcURL = LocalFilesystemURL.parse(srcURLstr);
+        LocalFilesystemURL destURL = LocalFilesystemURL.parse(destURLstr);
+
+        Filesystem srcFs = this.filesystemForURL(srcURL);
+        Filesystem destFs = this.filesystemForURL(destURL);
+
+        // Check for invalid file name
+        if (newName != null && newName.contains(":")) {
+            throw new EncodingException("Bad file name");
+        }
+
+        return destFs.copyFileToURL(destURL, newName, srcFs, srcURL, move);
+    }
+
+    /**
+     * Deletes a directory and all of its contents, if any. In the event of an error
+     * [e.g. trying to delete a directory that contains a file that cannot be removed],
+     * some of the contents of the directory may be deleted.
+     * It is an error to attempt to delete the root directory of a filesystem.
+     *
+     * @return a boolean representing success of failure
+     * @throws FileExistsException
+     * @throws NoModificationAllowedException
+     * @throws MalformedURLException
+     */
+    private boolean removeRecursively(String baseURLstr) throws FileExistsException, NoModificationAllowedException, MalformedURLException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	// You can't delete the root directory.
+        	if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
+        		throw new NoModificationAllowedException("You can't delete the root directory");
+        	}
+
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.recursiveRemoveFileAtLocalURL(inputURL);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+
+    /**
+     * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
+     * It is an error to attempt to delete the root directory of a filesystem.
+     *
+     * @return a boolean representing success of failure
+     * @throws NoModificationAllowedException
+     * @throws InvalidModificationException
+     * @throws MalformedURLException
+     */
+    private boolean remove(String baseURLstr) throws NoModificationAllowedException, InvalidModificationException, MalformedURLException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	// You can't delete the root directory.
+        	if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
+
+        		throw new NoModificationAllowedException("You can't delete the root directory");
+        	}
+
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.removeFileAtLocalURL(inputURL);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+    /**
+     * Creates or looks up a file.
+     *
+     * @param baseURLstr base directory
+     * @param path file/directory to lookup or create
+     * @param options specify whether to create or not
+     * @param directory if true look up directory, if false look up file
+     * @return a Entry object
+     * @throws FileExistsException
+     * @throws IOException
+     * @throws TypeMismatchException
+     * @throws EncodingException
+     * @throws JSONException
+     */
+    private JSONObject getFile(String baseURLstr, String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.getFileForLocalURL(inputURL, path, options, directory);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+
+    }
+
+    /**
+     * Look up the parent DirectoryEntry containing this Entry.
+     * If this Entry is the root of its filesystem, its parent is itself.
+     */
+    private JSONObject getParent(String baseURLstr) throws JSONException, IOException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.getParentForLocalURL(inputURL);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+    /**
+     * Returns a File that represents the current state of the file that this FileEntry represents.
+     *
+     * @return returns a JSONObject represent a W3C File object
+     */
+    private JSONObject getFileMetadata(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+        	return fs.getFileMetadataForLocalURL(inputURL);
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+    /**
+     * Requests a filesystem in which to store application data.
+     *
+     * @param type of file system requested
+     * @param requiredSize required free space in the file system in bytes
+     * @param callbackContext context for returning the result or error
+     * @throws JSONException
+     */
+    private void requestFileSystem(int type, long requiredSize, final CallbackContext callbackContext) throws JSONException {
+        Filesystem rootFs = null;
+        try {
+            rootFs = this.filesystems.get(type);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Pass null through
+        }
+        if (rootFs == null) {
+            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR));
+        } else {
+            // If a nonzero required size was specified, check that the retrieved filesystem has enough free space.
+            long availableSize = 0;
+            if (requiredSize > 0) {
+                availableSize = rootFs.getFreeSpaceInBytes();
+            }
+
+            if (availableSize < requiredSize) {
+                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR));
+            } else {
+                JSONObject fs = new JSONObject();
+                fs.put("name", rootFs.name);
+                fs.put("root", rootFs.getRootEntry());
+                callbackContext.success(fs);
+            }
+        }
+    }
+
+    /**
+     * Requests a filesystem in which to store application data.
+     *
+     * @return a JSONObject representing the file system
+     */
+    private JSONArray requestAllFileSystems() throws IOException, JSONException {
+        JSONArray ret = new JSONArray();
+        for (Filesystem fs : filesystems) {
+            ret.put(fs.getRootEntry());
+        }
+        return ret;
+    }
+
+    private static String toDirUrl(File f) {
+        return Uri.fromFile(f).toString() + '/';
+    }
+
+    private JSONObject requestAllPaths() throws JSONException {
+        Context context = cordova.getActivity();
+        JSONObject ret = new JSONObject();
+        ret.put("applicationDirectory", "file:///android_asset/");
+        ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
+        ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
+        ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+          try {
+            ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
+            ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
+            ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
+            ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
+          }
+          catch(NullPointerException e) {
+            /* If external storage is unavailable, context.getExternal* returns null */
+              LOG.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
+          }
+        }
+        return ret;
+    }
+
+   /**
+     * Returns a JSON object representing the given File. Internal APIs should be modified
+     * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
+     *
+     * @param file the File to convert
+     * @return a JSON representation of the given File
+     * @throws JSONException
+     */
+    public JSONObject getEntryForFile(File file) throws JSONException {
+        JSONObject entry;
+
+        for (Filesystem fs : filesystems) {
+             entry = fs.makeEntryForFile(file);
+             if (entry != null) {
+                 return entry;
+             }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a JSON object representing the given File. Deprecated, as this is only used by
+     * FileTransfer, and because it is a static method that should really be an instance method,
+     * since it depends on the actual filesystem roots in use. Internal APIs should be modified
+     * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
+     *
+     * @param file the File to convert
+     * @return a JSON representation of the given File
+     * @throws JSONException
+     */
+    @Deprecated
+    public static JSONObject getEntry(File file) throws JSONException {
+ 		if (getFilePlugin() != null) {
+             return getFilePlugin().getEntryForFile(file);
+		}
+		return null;
+    }
+
+    /**
+     * Read the contents of a file.
+     * This is done in a background thread; the result is sent to the callback.
+     *
+     * @param start             Start position in the file.
+     * @param end               End position to stop at (exclusive).
+     * @param callbackContext   The context through which to send the result.
+     * @param encoding          The encoding to return contents as.  Typical value is UTF-8. (see http://www.iana.org/assignments/character-sets)
+     * @param resultType        The desired type of data to send to the callback.
+     * @return                  Contents of file.
+     */
+    public void readFileAs(final String srcURLstr, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) throws MalformedURLException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+
+            fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
+                public void handleData(InputStream inputStream, String contentType) {
+            		try {
+                        ByteArrayOutputStream os = new ByteArrayOutputStream();
+                        final int BUFFER_SIZE = 8192;
+                        byte[] buffer = new byte[BUFFER_SIZE];
+
+                        for (;;) {
+                            int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+                            if (bytesRead <= 0) {
+                                break;
+                            }
+                            os.write(buffer, 0, bytesRead);
+                        }
+
+            			PluginResult result;
+            			switch (resultType) {
+            			case PluginResult.MESSAGE_TYPE_STRING:
+                            result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
+            				break;
+            			case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+                            result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
+            				break;
+            			case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+                            result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
+            				break;
+            			default: // Base64.
+                        byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
+            			String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
+            			result = new PluginResult(PluginResult.Status.OK, s);
+            			}
+
+            			callbackContext.sendPluginResult(result);
+            		} catch (IOException e) {
+            			LOG.d(LOG_TAG, e.getLocalizedMessage());
+            			callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
+                    }
+            	}
+            });
+
+
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        } catch (FileNotFoundException e) {
+        	callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_FOUND_ERR));
+        } catch (IOException e) {
+        	LOG.d(LOG_TAG, e.getLocalizedMessage());
+        	callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
+        }
+    }
+
+
+    /**
+     * Write contents of file.
+     *
+     * @param data				The contents of the file.
+     * @param offset			The position to begin writing the file.
+     * @param isBinary          True if the file contents are base64-encoded binary data
+     */
+    /**/
+    public long write(String srcURLstr, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+
+            long x = fs.writeToFileAtURL(inputURL, data, offset, isBinary); LOG.d("TEST",srcURLstr + ": "+x); return x;
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+
+    }
+
+    /**
+     * Truncate the file to size
+     */
+    private long truncateFile(String srcURLstr, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
+        try {
+        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
+        	Filesystem fs = this.filesystemForURL(inputURL);
+        	if (fs == null) {
+        		throw new MalformedURLException("No installed handlers for this URL");
+        	}
+
+            return fs.truncateFileAtURL(inputURL, size);
+        } catch (IllegalArgumentException e) {
+            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
+            mue.initCause(e);
+        	throw mue;
+        }
+    }
+
+
+    /*
+     * Handle the response
+     */
+
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+
+        final PendingRequests.Request req = pendingRequests.getAndRemove(requestCode);
+        if (req != null) {
+            for(int r:grantResults)
+            {
+                if(r == PackageManager.PERMISSION_DENIED)
+                {
+                    req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
+                    return;
+                }
+            }
+            switch(req.getAction())
+            {
+                case ACTION_GET_FILE:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                            String dirname = args.getString(0);
+
+                            String path = args.getString(1);
+                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
+                            req.getCallbackContext().success(obj);
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+                case ACTION_GET_DIRECTORY:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+                            String dirname = args.getString(0);
+
+                            String path = args.getString(1);
+                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
+                            req.getCallbackContext().success(obj);
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+                case ACTION_WRITE:
+                    threadhelper( new FileOp( ){
+                        public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
+                            String fname=args.getString(0);
+                            String data=args.getString(1);
+                            int offset=args.getInt(2);
+                            Boolean isBinary=args.getBoolean(3);
+                            long fileSize = write(fname, data, offset, isBinary);
+                            req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
+                        }
+                    }, req.getRawArgs(), req.getCallbackContext());
+                    break;
+            }
+        } else {
+           LOG.d(LOG_TAG, "Received permission callback for unknown request code");
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java
new file mode 100644
index 0000000..c69d3bd
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java
@@ -0,0 +1,331 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import android.net.Uri;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public abstract class Filesystem {
+
+    protected final Uri rootUri;
+    protected final CordovaResourceApi resourceApi;
+    public final String name;
+    private JSONObject rootEntry;
+
+    public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi) {
+        this.rootUri = rootUri;
+        this.name = name;
+        this.resourceApi = resourceApi;
+    }
+
+    public interface ReadFileCallback {
+		public void handleData(InputStream inputStream, String contentType) throws IOException;
+	}
+
+    public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
+        try {
+            String path = inputURL.path;
+            int end = path.endsWith("/") ? 1 : 0;
+            String[] parts = path.substring(0, path.length() - end).split("/+");
+            String fileName = parts[parts.length - 1];
+
+            JSONObject entry = new JSONObject();
+            entry.put("isFile", !inputURL.isDirectory);
+            entry.put("isDirectory", inputURL.isDirectory);
+            entry.put("name", fileName);
+            entry.put("fullPath", path);
+            // The file system can't be specified, as it would lead to an infinite loop,
+            // but the filesystem name can be.
+            entry.put("filesystemName", inputURL.fsName);
+            // Backwards compatibility
+            entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);
+
+            String nativeUrlStr = nativeURL.toString();
+            if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
+                nativeUrlStr += "/";
+            }
+            entry.put("nativeURL", nativeUrlStr);
+            return entry;
+        } catch (JSONException e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
+    public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
+        Uri nativeUri = toNativeUri(inputURL);
+        return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
+    }
+
+    public JSONObject makeEntryForNativeUri(Uri nativeUri) {
+        LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
+        return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
+    }
+
+    public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
+        return makeEntryForURL(inputURL);
+    }
+
+    public JSONObject makeEntryForFile(File file) {
+        return makeEntryForNativeUri(Uri.fromFile(file));
+    }
+
+    abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
+			JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
+
+	abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
+
+	abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
+
+	abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+    public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        LocalFilesystemURL[] children = listChildren(inputURL);
+        JSONArray entries = new JSONArray();
+        if (children != null) {
+            for (LocalFilesystemURL url : children) {
+                entries.put(makeEntryForURL(url));
+            }
+        }
+        return entries;
+    }
+
+	abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
+
+    public Uri getRootUri() {
+        return rootUri;
+    }
+
+    public boolean exists(LocalFilesystemURL inputURL) {
+        try {
+            getFileMetadataForLocalURL(inputURL);
+        } catch (FileNotFoundException e) {
+            return false;
+        }
+        return true;
+    }
+
+    public Uri nativeUriForFullPath(String fullPath) {
+        Uri ret = null;
+        if (fullPath != null) {
+            String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
+            if (encodedPath.startsWith("/")) {
+                encodedPath = encodedPath.substring(1);
+            }
+            ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
+        }
+        return ret;
+    }
+
+    public LocalFilesystemURL localUrlforFullPath(String fullPath) {
+        Uri nativeUri = nativeUriForFullPath(fullPath);
+        if (nativeUri != null) {
+            return toLocalUri(nativeUri);
+        }
+        return null;
+    }
+
+    /**
+     * Removes multiple repeated //s, and collapses processes ../s.
+     */
+    protected static String normalizePath(String rawPath) {
+        // If this is an absolute path, trim the leading "/" and replace it later
+        boolean isAbsolutePath = rawPath.startsWith("/");
+        if (isAbsolutePath) {
+            rawPath = rawPath.replaceFirst("/+", "");
+        }
+        ArrayList<String> components = new ArrayList<String>(Arrays.asList(rawPath.split("/+")));
+        for (int index = 0; index < components.size(); ++index) {
+            if (components.get(index).equals("..")) {
+                components.remove(index);
+                if (index > 0) {
+                    components.remove(index-1);
+                    --index;
+                }
+            }
+        }
+        StringBuilder normalizedPath = new StringBuilder();
+        for(String component: components) {
+            normalizedPath.append("/");
+            normalizedPath.append(component);
+        }
+        if (isAbsolutePath) {
+            return normalizedPath.toString();
+        } else {
+            return normalizedPath.toString().substring(1);
+        }
+    }
+
+    /**
+     * Gets the free space in bytes available on this filesystem.
+     * Subclasses may override this method to return nonzero free space.
+     */
+    public long getFreeSpaceInBytes() {
+        return 0;
+    }
+
+    public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
+    public abstract LocalFilesystemURL toLocalUri(Uri inputURL);
+
+    public JSONObject getRootEntry() {
+        if (rootEntry == null) {
+            rootEntry = makeEntryForNativeUri(rootUri);
+        }
+        return rootEntry;
+    }
+
+	public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
+        Uri parentUri = inputURL.uri;
+        String parentPath = new File(inputURL.uri.getPath()).getParent();
+        if (!"/".equals(parentPath)) {
+            parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
+		}
+		return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
+	}
+
+    protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
+        // I know this looks weird but it is to work around a JSON bug.
+        if ("null".equals(newName) || "".equals(newName)) {
+            newName = srcURL.uri.getLastPathSegment();;
+        }
+
+        String newDest = destURL.uri.toString();
+        if (newDest.endsWith("/")) {
+            newDest = newDest + newName;
+        } else {
+            newDest = newDest + "/" + newName;
+        }
+        if (isDirectory) {
+            newDest += '/';
+        }
+        return LocalFilesystemURL.parse(newDest);
+    }
+
+	/* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
+	 * the destination URL on this filesystem, optionally with a new filename.
+	 * If move is true, then this method should either perform an atomic move operation
+	 * or remove the source file when finished.
+	 */
+    public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
+            Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
+        // First, check to see that we can do it
+        if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+            throw new NoModificationAllowedException("Cannot move file at source URL");
+        }
+        final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
+
+        Uri srcNativeUri = srcFs.toNativeUri(srcURL);
+
+        CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
+        OutputStream os = null;
+        try {
+            os = getOutputStreamForURL(destination);
+        } catch (IOException e) {
+            ofrr.inputStream.close();
+            throw e;
+        }
+        // Closes streams.
+        resourceApi.copyResource(ofrr, os);
+
+        if (move) {
+            srcFs.removeFileAtLocalURL(srcURL);
+        }
+        return getEntryForLocalURL(destination);
+    }
+
+    public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
+        return resourceApi.openOutputStream(toNativeUri(inputURL));
+    }
+
+    public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
+                              ReadFileCallback readFileCallback) throws IOException {
+        CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
+        if (end < 0) {
+            end = ofrr.length;
+        }
+        long numBytesToRead = end - start;
+        try {
+            if (start > 0) {
+                ofrr.inputStream.skip(start);
+            }
+            InputStream inputStream = ofrr.inputStream;
+            if (end < ofrr.length) {
+                inputStream = new LimitedInputStream(inputStream, numBytesToRead);
+            }
+            readFileCallback.handleData(inputStream, ofrr.mimeType);
+        } finally {
+            ofrr.inputStream.close();
+        }
+    }
+
+	abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
+			boolean isBinary) throws NoModificationAllowedException, IOException;
+
+	abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
+			throws IOException, NoModificationAllowedException;
+
+	// This method should return null if filesystem urls cannot be mapped to paths
+	abstract String filesystemPathForURL(LocalFilesystemURL url);
+
+	abstract LocalFilesystemURL URLforFilesystemPath(String path);
+
+	abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
+
+    protected class LimitedInputStream extends FilterInputStream {
+        long numBytesToRead;
+        public LimitedInputStream(InputStream in, long numBytesToRead) {
+            super(in);
+            this.numBytesToRead = numBytesToRead;
+        }
+        @Override
+        public int read() throws IOException {
+            if (numBytesToRead <= 0) {
+                return -1;
+            }
+            numBytesToRead--;
+            return in.read();
+        }
+        @Override
+        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+            if (numBytesToRead <= 0) {
+                return -1;
+            }
+            int bytesToRead = byteCount;
+            if (byteCount > numBytesToRead) {
+                bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
+            }
+            int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
+            numBytesToRead -= numBytesRead;
+            return numBytesRead;
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java
new file mode 100644
index 0000000..8f6bec5
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java
@@ -0,0 +1,30 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+
+package org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class InvalidModificationException extends Exception {
+
+    public InvalidModificationException(String message) {
+        super(message);
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java
new file mode 100644
index 0000000..051f994
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java
@@ -0,0 +1,513 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import org.apache.cordova.CordovaResourceApi;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Build;
+import android.os.Environment;
+import android.util.Base64;
+import android.net.Uri;
+import android.content.Context;
+import android.content.Intent;
+
+import java.nio.charset.Charset;
+
+public class LocalFilesystem extends Filesystem {
+    private final Context context;
+
+    public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
+        super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
+        this.context = context;
+    }
+
+    public String filesystemPathForFullPath(String fullPath) {
+	    return new File(rootUri.getPath(), fullPath).toString();
+	}
+
+	@Override
+	public String filesystemPathForURL(LocalFilesystemURL url) {
+		return filesystemPathForFullPath(url.path);
+	}
+
+	private String fullPathForFilesystemPath(String absolutePath) {
+		if (absolutePath != null && absolutePath.startsWith(rootUri.getPath())) {
+			return absolutePath.substring(rootUri.getPath().length() - 1);
+		}
+		return null;
+	}
+
+    @Override
+    public Uri toNativeUri(LocalFilesystemURL inputURL) {
+        return nativeUriForFullPath(inputURL.path);
+    }
+
+    @Override
+    public LocalFilesystemURL toLocalUri(Uri inputURL) {
+        if (!"file".equals(inputURL.getScheme())) {
+            return null;
+        }
+        File f = new File(inputURL.getPath());
+        // Removes and duplicate /s (e.g. file:///a//b/c)
+        Uri resolvedUri = Uri.fromFile(f);
+        String rootUriNoTrailingSlash = rootUri.getEncodedPath();
+        rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
+        if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
+            return null;
+        }
+        String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
+        // Strip leading slash
+        if (!subPath.isEmpty()) {
+            subPath = subPath.substring(1);
+        }
+        Uri.Builder b = new Uri.Builder()
+            .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
+            .authority("localhost")
+            .path(name);
+        if (!subPath.isEmpty()) {
+            b.appendEncodedPath(subPath);
+        }
+        if (f.isDirectory()) {
+            // Add trailing / for directories.
+            b.appendEncodedPath("");
+        }
+        return LocalFilesystemURL.parse(b.build());
+    }
+
+	@Override
+	public LocalFilesystemURL URLforFilesystemPath(String path) {
+	    return localUrlforFullPath(fullPathForFilesystemPath(path));
+	}
+
+	@Override
+	public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
+			String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
+        boolean create = false;
+        boolean exclusive = false;
+
+        if (options != null) {
+            create = options.optBoolean("create");
+            if (create) {
+                exclusive = options.optBoolean("exclusive");
+            }
+        }
+
+        // Check for a ":" character in the file to line up with BB and iOS
+        if (path.contains(":")) {
+            throw new EncodingException("This path has an invalid \":\" in it.");
+        }
+
+        LocalFilesystemURL requestedURL;
+
+        // Check whether the supplied path is absolute or relative
+        if (directory && !path.endsWith("/")) {
+            path += "/";
+        }
+        if (path.startsWith("/")) {
+        	requestedURL = localUrlforFullPath(normalizePath(path));
+        } else {
+        	requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
+        }
+
+        File fp = new File(this.filesystemPathForURL(requestedURL));
+
+        if (create) {
+            if (exclusive && fp.exists()) {
+                throw new FileExistsException("create/exclusive fails");
+            }
+            if (directory) {
+                fp.mkdir();
+            } else {
+                fp.createNewFile();
+            }
+            if (!fp.exists()) {
+                throw new FileExistsException("create fails");
+            }
+        }
+        else {
+            if (!fp.exists()) {
+                throw new FileNotFoundException("path does not exist");
+            }
+            if (directory) {
+                if (fp.isFile()) {
+                    throw new TypeMismatchException("path doesn't exist or is file");
+                }
+            } else {
+                if (fp.isDirectory()) {
+                    throw new TypeMismatchException("path doesn't exist or is directory");
+                }
+            }
+        }
+
+        // Return the directory
+        return makeEntryForURL(requestedURL);
+	}
+
+	@Override
+	public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException {
+
+        File fp = new File(filesystemPathForURL(inputURL));
+
+        // You can't delete a directory that is not empty
+        if (fp.isDirectory() && fp.list().length > 0) {
+            throw new InvalidModificationException("You can't delete a directory that is not empty.");
+        }
+
+        return fp.delete();
+	}
+
+    @Override
+    public boolean exists(LocalFilesystemURL inputURL) {
+        File fp = new File(filesystemPathForURL(inputURL));
+        return fp.exists();
+    }
+
+    @Override
+    public long getFreeSpaceInBytes() {
+        return DirectoryManager.getFreeSpaceInBytes(rootUri.getPath());
+    }
+
+    @Override
+	public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException {
+        File directory = new File(filesystemPathForURL(inputURL));
+    	return removeDirRecursively(directory);
+	}
+
+	protected boolean removeDirRecursively(File directory) throws FileExistsException {
+        if (directory.isDirectory()) {
+            for (File file : directory.listFiles()) {
+                removeDirRecursively(file);
+            }
+        }
+
+        if (!directory.delete()) {
+            throw new FileExistsException("could not delete: " + directory.getName());
+        } else {
+            return true;
+        }
+	}
+
+    @Override
+    public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        File fp = new File(filesystemPathForURL(inputURL));
+
+        if (!fp.exists()) {
+            // The directory we are listing doesn't exist so we should fail.
+            throw new FileNotFoundException();
+        }
+
+        File[] files = fp.listFiles();
+        if (files == null) {
+            // inputURL is a directory
+            return null;
+        }
+        LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
+        for (int i = 0; i < files.length; i++) {
+            entries[i] = URLforFilesystemPath(files[i].getPath());
+        }
+
+        return entries;
+	}
+
+	@Override
+	public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
+        File file = new File(filesystemPathForURL(inputURL));
+
+        if (!file.exists()) {
+            throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
+        }
+
+        JSONObject metadata = new JSONObject();
+        try {
+            // Ensure that directories report a size of 0
+        	metadata.put("size", file.isDirectory() ? 0 : file.length());
+        	metadata.put("type", resourceApi.getMimeType(Uri.fromFile(file)));
+        	metadata.put("name", file.getName());
+        	metadata.put("fullPath", inputURL.path);
+        	metadata.put("lastModifiedDate", file.lastModified());
+        } catch (JSONException e) {
+        	return null;
+        }
+        return metadata;
+	}
+
+    private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
+        if (move) {
+            String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+            if (realSrcPath != null) {
+                File srcFile = new File(realSrcPath);
+                if (srcFile.renameTo(destFile)) {
+                    return;
+                }
+                // Trying to rename the file failed.  Possibly because we moved across file system on the device.
+            }
+        }
+
+        CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
+        copyResource(offr, new FileOutputStream(destFile));
+
+        if (move) {
+            srcFs.removeFileAtLocalURL(srcURL);
+        }
+    }
+
+    private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
+        if (move) {
+            String realSrcPath = srcFs.filesystemPathForURL(srcURL);
+            if (realSrcPath != null) {
+                File srcDir = new File(realSrcPath);
+                // If the destination directory already exists and is empty then delete it.  This is according to spec.
+                if (dstDir.exists()) {
+                    if (dstDir.list().length > 0) {
+                        throw new InvalidModificationException("directory is not empty");
+                    }
+                    dstDir.delete();
+                }
+                // Try to rename the directory
+                if (srcDir.renameTo(dstDir)) {
+                    return;
+                }
+                // Trying to rename the file failed.  Possibly because we moved across file system on the device.
+            }
+        }
+
+        if (dstDir.exists()) {
+            if (dstDir.list().length > 0) {
+                throw new InvalidModificationException("directory is not empty");
+            }
+        } else {
+            if (!dstDir.mkdir()) {
+                // If we can't create the directory then fail
+                throw new NoModificationAllowedException("Couldn't create the destination directory");
+            }
+        }
+
+        LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
+        for (LocalFilesystemURL childLocalUrl : children) {
+            File target = new File(dstDir, new File(childLocalUrl.path).getName());
+            if (childLocalUrl.isDirectory) {
+                copyDirectory(srcFs, childLocalUrl, target, false);
+            } else {
+                copyFile(srcFs, childLocalUrl, target, false);
+            }
+        }
+
+        if (move) {
+            srcFs.recursiveRemoveFileAtLocalURL(srcURL);
+        }
+    }
+
+	@Override
+	public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
+			Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
+
+		// Check to see if the destination directory exists
+        String newParent = this.filesystemPathForURL(destURL);
+        File destinationDir = new File(newParent);
+        if (!destinationDir.exists()) {
+            // The destination does not exist so we should fail.
+            throw new FileNotFoundException("The source does not exist");
+        }
+
+        // Figure out where we should be copying to
+        final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
+
+        Uri dstNativeUri = toNativeUri(destinationURL);
+        Uri srcNativeUri = srcFs.toNativeUri(srcURL);
+        // Check to see if source and destination are the same file
+        if (dstNativeUri.equals(srcNativeUri)) {
+            throw new InvalidModificationException("Can't copy onto itself");
+        }
+
+        if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
+            throw new InvalidModificationException("Source URL is read-only (cannot move)");
+        }
+
+        File destFile = new File(dstNativeUri.getPath());
+        if (destFile.exists()) {
+            if (!srcURL.isDirectory && destFile.isDirectory()) {
+                throw new InvalidModificationException("Can't copy/move a file to an existing directory");
+            } else if (srcURL.isDirectory && destFile.isFile()) {
+                throw new InvalidModificationException("Can't copy/move a directory to an existing file");
+            }
+        }
+
+        if (srcURL.isDirectory) {
+            // E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
+            if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
+                throw new InvalidModificationException("Can't copy directory into itself");
+            }
+            copyDirectory(srcFs, srcURL, destFile, move);
+        } else {
+            copyFile(srcFs, srcURL, destFile, move);
+        }
+        return makeEntryForURL(destinationURL);
+	}
+
+	@Override
+	public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
+			int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
+
+        boolean append = false;
+        if (offset > 0) {
+            this.truncateFileAtURL(inputURL, offset);
+            append = true;
+        }
+
+        byte[] rawData;
+        if (isBinary) {
+            rawData = Base64.decode(data, Base64.DEFAULT);
+        } else {
+            rawData = data.getBytes(Charset.defaultCharset());
+        }
+        ByteArrayInputStream in = new ByteArrayInputStream(rawData);
+        try
+        {
+        	byte buff[] = new byte[rawData.length];
+            String absolutePath = filesystemPathForURL(inputURL);
+            FileOutputStream out = new FileOutputStream(absolutePath, append);
+            try {
+            	in.read(buff, 0, buff.length);
+            	out.write(buff, 0, rawData.length);
+            	out.flush();
+            } finally {
+            	// Always close the output
+            	out.close();
+            }
+            if (isPublicDirectory(absolutePath)) {
+                broadcastNewFile(Uri.fromFile(new File(absolutePath)));
+            }
+        }
+        catch (NullPointerException e)
+        {
+            // This is a bug in the Android implementation of the Java Stack
+            NoModificationAllowedException realException = new NoModificationAllowedException(inputURL.toString());
+            realException.initCause(e);
+            throw realException;
+        }
+
+        return rawData.length;
+	}
+
+    private boolean isPublicDirectory(String absolutePath) {
+        // TODO: should expose a way to scan app's private files (maybe via a flag).
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            // Lollipop has a bug where SD cards are null.
+            for (File f : context.getExternalMediaDirs()) {
+                if(f != null && absolutePath.startsWith(f.getAbsolutePath())) {
+                    return true;
+                }
+            }
+        }
+
+        String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
+        return absolutePath.startsWith(extPath);
+    }
+
+     /**
+     * Send broadcast of new file so files appear over MTP
+     */
+    private void broadcastNewFile(Uri nativeUri) {
+        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, nativeUri);
+        context.sendBroadcast(intent);
+    }
+
+	@Override
+	public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException {
+        File file = new File(filesystemPathForURL(inputURL));
+
+        if (!file.exists()) {
+            throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
+        }
+
+        RandomAccessFile raf = new RandomAccessFile(filesystemPathForURL(inputURL), "rw");
+        try {
+            if (raf.length() >= size) {
+                FileChannel channel = raf.getChannel();
+                channel.truncate(size);
+                return size;
+            }
+
+            return raf.length();
+        } finally {
+            raf.close();
+        }
+
+
+	}
+
+	@Override
+	public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
+		String path = filesystemPathForURL(inputURL);
+		File file = new File(path);
+		return file.exists();
+	}
+
+    // This is a copy & paste from CordovaResource API that is required since CordovaResourceApi
+    // has a bug pre-4.0.0.
+    // TODO: Once cordova-android@4.0.0 is released, delete this copy and make the plugin depend on
+    // 4.0.0 with an engine tag.
+    private static void copyResource(CordovaResourceApi.OpenForReadResult input, OutputStream outputStream) throws IOException {
+        try {
+            InputStream inputStream = input.inputStream;
+            if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
+                FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
+                FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
+                long offset = 0;
+                long length = input.length;
+                if (input.assetFd != null) {
+                    offset = input.assetFd.getStartOffset();
+                }
+                // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
+                // position first.
+                inChannel.position(offset);
+                outChannel.transferFrom(inChannel, 0, length);
+            } else {
+                final int BUFFER_SIZE = 8192;
+                byte[] buffer = new byte[BUFFER_SIZE];
+
+                for (;;) {
+                    int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
+
+                    if (bytesRead <= 0) {
+                        break;
+                    }
+                    outputStream.write(buffer, 0, bytesRead);
+                }
+            }
+        } finally {
+            input.inputStream.close();
+            if (outputStream != null) {
+                outputStream.close();
+            }
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java
new file mode 100644
index 0000000..b96b6ee
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java
@@ -0,0 +1,64 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+ */
+package org.apache.cordova.file;
+
+import android.net.Uri;
+
+public class LocalFilesystemURL {
+	
+	public static final String FILESYSTEM_PROTOCOL = "cdvfile";
+
+    public final Uri uri;
+    public final String fsName;
+    public final String path;
+    public final boolean isDirectory;
+
+	private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) {
+		this.uri = uri;
+        this.fsName = fsName;
+        this.path = fsPath;
+        this.isDirectory = isDirectory;
+	}
+
+    public static LocalFilesystemURL parse(Uri uri) {
+        if (!FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
+            return null;
+        }
+        String path = uri.getPath();
+        if (path.length() < 1) {
+            return null;
+        }
+        int firstSlashIdx = path.indexOf('/', 1);
+        if (firstSlashIdx < 0) {
+            return null;
+        }
+        String fsName = path.substring(1, firstSlashIdx);
+        path = path.substring(firstSlashIdx);
+        boolean isDirectory = path.charAt(path.length() - 1) == '/';
+        return new LocalFilesystemURL(uri, fsName, path, isDirectory);
+    }
+
+    public static LocalFilesystemURL parse(String uri) {
+        return parse(Uri.parse(uri));
+    }
+
+    public String toString() {
+        return uri.toString();
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java
new file mode 100644
index 0000000..627eafb
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java
@@ -0,0 +1,29 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class NoModificationAllowedException extends Exception {
+
+    public NoModificationAllowedException(String message) {
+        super(message);
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java b/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java
new file mode 100644
index 0000000..23d6d73
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java
@@ -0,0 +1,94 @@
+/*

+       Licensed to the Apache Software Foundation (ASF) under one

+       or more contributor license agreements.  See the NOTICE file

+       distributed with this work for additional information

+       regarding copyright ownership.  The ASF licenses this file

+       to you under the Apache License, Version 2.0 (the

+       "License"); you may not use this file except in compliance

+       with the License.  You may obtain a copy of the License at

+

+         http://www.apache.org/licenses/LICENSE-2.0

+

+       Unless required by applicable law or agreed to in writing,

+       software distributed under the License is distributed on an

+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+       KIND, either express or implied.  See the License for the

+       specific language governing permissions and limitations

+       under the License.

+*/

+package org.apache.cordova.file;

+

+import android.util.SparseArray;

+

+import org.apache.cordova.CallbackContext;

+

+/**

+ * Holds pending runtime permission requests

+ */

+class PendingRequests {

+    private int currentReqId = 0;

+    private SparseArray<Request> requests = new SparseArray<Request>();

+

+    /**

+     * Creates a request and adds it to the array of pending requests. Each created request gets a

+     * unique result code for use with requestPermission()

+     * @param rawArgs           The raw arguments passed to the plugin

+     * @param action            The action this request corresponds to (get file, etc.)

+     * @param callbackContext   The CallbackContext for this plugin call

+     * @return                  The request code that can be used to retrieve the Request object

+     */

+    public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext)  {

+        Request req = new Request(rawArgs, action, callbackContext);

+        requests.put(req.requestCode, req);

+        return req.requestCode;

+    }

+

+    /**

+     * Gets the request corresponding to this request code and removes it from the pending requests

+     * @param requestCode   The request code for the desired request

+     * @return              The request corresponding to the given request code or null if such a

+     *                      request is not found

+     */

+    public synchronized Request getAndRemove(int requestCode) {

+        Request result = requests.get(requestCode);

+        requests.remove(requestCode);

+        return result;

+    }

+

+    /**

+     * Holds the options and CallbackContext for a call made to the plugin.

+     */

+    public class Request {

+

+        // Unique int used to identify this request in any Android permission callback

+        private int requestCode;

+

+        // Action to be performed after permission request result

+        private int action;

+

+        // Raw arguments passed to plugin

+        private String rawArgs;

+

+        // The callback context for this plugin request

+        private CallbackContext callbackContext;

+

+        private Request(String rawArgs, int action, CallbackContext callbackContext) {

+            this.rawArgs = rawArgs;

+            this.action = action;

+            this.callbackContext = callbackContext;

+            this.requestCode = currentReqId ++;

+        }

+

+        public int getAction() {

+            return this.action;

+        }

+

+        public String getRawArgs() {

+            return rawArgs;

+        }

+

+        public CallbackContext getCallbackContext() {

+            return callbackContext;

+        }

+    }

+}

diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java
new file mode 100644
index 0000000..1315f9a
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java
@@ -0,0 +1,30 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+
+package org.apache.cordova.file;
+
+@SuppressWarnings("serial")
+public class TypeMismatchException extends Exception {
+
+    public TypeMismatchException(String message) {
+        super(message);
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java
new file mode 100644
index 0000000..9b3388c
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java
@@ -0,0 +1,1259 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.inappbrowser;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Browser;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.InputType;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.HttpAuthHandler;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaHttpAuthHandler;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginManager;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+@SuppressLint("SetJavaScriptEnabled")
+public class InAppBrowser extends CordovaPlugin {
+
+    private static final String NULL = "null";
+    protected static final String LOG_TAG = "InAppBrowser";
+    private static final String SELF = "_self";
+    private static final String SYSTEM = "_system";
+    private static final String EXIT_EVENT = "exit";
+    private static final String LOCATION = "location";
+    private static final String ZOOM = "zoom";
+    private static final String HIDDEN = "hidden";
+    private static final String LOAD_START_EVENT = "loadstart";
+    private static final String LOAD_STOP_EVENT = "loadstop";
+    private static final String LOAD_ERROR_EVENT = "loaderror";
+    private static final String CLEAR_ALL_CACHE = "clearcache";
+    private static final String CLEAR_SESSION_CACHE = "clearsessioncache";
+    private static final String HARDWARE_BACK_BUTTON = "hardwareback";
+    private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction";
+    private static final String SHOULD_PAUSE = "shouldPauseOnSuspend";
+    private static final Boolean DEFAULT_HARDWARE_BACK = true;
+    private static final String USER_WIDE_VIEW_PORT = "useWideViewPort";
+    private static final String TOOLBAR_COLOR = "toolbarcolor";
+    private static final String CLOSE_BUTTON_CAPTION = "closebuttoncaption";
+    private static final String CLOSE_BUTTON_COLOR = "closebuttoncolor";
+    private static final String HIDE_NAVIGATION = "hidenavigationbuttons";
+    private static final String NAVIGATION_COLOR = "navigationbuttoncolor";
+    private static final String HIDE_URL = "hideurlbar";
+    private static final String FOOTER = "footer";
+    private static final String FOOTER_COLOR = "footercolor";
+
+    private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
+
+    private InAppBrowserDialog dialog;
+    private WebView inAppWebView;
+    private EditText edittext;
+    private CallbackContext callbackContext;
+    private boolean showLocationBar = true;
+    private boolean showZoomControls = true;
+    private boolean openWindowHidden = false;
+    private boolean clearAllCache = false;
+    private boolean clearSessionCache = false;
+    private boolean hadwareBackButton = true;
+    private boolean mediaPlaybackRequiresUserGesture = false;
+    private boolean shouldPauseInAppBrowser = false;
+    private boolean useWideViewPort = true;
+    private ValueCallback<Uri> mUploadCallback;
+    private ValueCallback<Uri[]> mUploadCallbackLollipop;
+    private final static int FILECHOOSER_REQUESTCODE = 1;
+    private final static int FILECHOOSER_REQUESTCODE_LOLLIPOP = 2;
+    private String closeButtonCaption = "";
+    private String closeButtonColor = "";
+    private int toolbarColor = android.graphics.Color.LTGRAY;
+    private boolean hideNavigationButtons = false;
+    private String navigationButtonColor = "";
+    private boolean hideUrlBar = false;
+    private boolean showFooter = false;
+    private String footerColor = "";
+    private String[] allowedSchemes;
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action the action to execute.
+     * @param args JSONArry of arguments for the plugin.
+     * @param callbackContext the callbackContext used when calling back into JavaScript.
+     * @return A PluginResult object with a status and message.
+     */
+    public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
+        if (action.equals("open")) {
+            this.callbackContext = callbackContext;
+            final String url = args.getString(0);
+            String t = args.optString(1);
+            if (t == null || t.equals("") || t.equals(NULL)) {
+                t = SELF;
+            }
+            final String target = t;
+            final HashMap<String, String> features = parseFeature(args.optString(2));
+
+            LOG.d(LOG_TAG, "target = " + target);
+
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    String result = "";
+                    // SELF
+                    if (SELF.equals(target)) {
+                        LOG.d(LOG_TAG, "in self");
+                        /* This code exists for compatibility between 3.x and 4.x versions of Cordova.
+                         * Previously the Config class had a static method, isUrlWhitelisted(). That
+                         * responsibility has been moved to the plugins, with an aggregating method in
+                         * PluginManager.
+                         */
+                        Boolean shouldAllowNavigation = null;
+                        if (url.startsWith("javascript:")) {
+                            shouldAllowNavigation = true;
+                        }
+                        if (shouldAllowNavigation == null) {
+                            try {
+                                Method iuw = Config.class.getMethod("isUrlWhiteListed", String.class);
+                                shouldAllowNavigation = (Boolean)iuw.invoke(null, url);
+                            } catch (NoSuchMethodException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            } catch (IllegalAccessException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            } catch (InvocationTargetException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            }
+                        }
+                        if (shouldAllowNavigation == null) {
+                            try {
+                                Method gpm = webView.getClass().getMethod("getPluginManager");
+                                PluginManager pm = (PluginManager)gpm.invoke(webView);
+                                Method san = pm.getClass().getMethod("shouldAllowNavigation", String.class);
+                                shouldAllowNavigation = (Boolean)san.invoke(pm, url);
+                            } catch (NoSuchMethodException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            } catch (IllegalAccessException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            } catch (InvocationTargetException e) {
+                                LOG.d(LOG_TAG, e.getLocalizedMessage());
+                            }
+                        }
+                        // load in webview
+                        if (Boolean.TRUE.equals(shouldAllowNavigation)) {
+                            LOG.d(LOG_TAG, "loading in webview");
+                            webView.loadUrl(url);
+                        }
+                        //Load the dialer
+                        else if (url.startsWith(WebView.SCHEME_TEL))
+                        {
+                            try {
+                                LOG.d(LOG_TAG, "loading in dialer");
+                                Intent intent = new Intent(Intent.ACTION_DIAL);
+                                intent.setData(Uri.parse(url));
+                                cordova.getActivity().startActivity(intent);
+                            } catch (android.content.ActivityNotFoundException e) {
+                                LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
+                            }
+                        }
+                        // load in InAppBrowser
+                        else {
+                            LOG.d(LOG_TAG, "loading in InAppBrowser");
+                            result = showWebPage(url, features);
+                        }
+                    }
+                    // SYSTEM
+                    else if (SYSTEM.equals(target)) {
+                        LOG.d(LOG_TAG, "in system");
+                        result = openExternal(url);
+                    }
+                    // BLANK - or anything else
+                    else {
+                        LOG.d(LOG_TAG, "in blank");
+                        result = showWebPage(url, features);
+                    }
+
+                    PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
+                    pluginResult.setKeepCallback(true);
+                    callbackContext.sendPluginResult(pluginResult);
+                }
+            });
+        }
+        else if (action.equals("close")) {
+            closeDialog();
+        }
+        else if (action.equals("injectScriptCode")) {
+            String jsWrapper = null;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(){prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')})()", callbackContext.getCallbackId());
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectScriptFile")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('script'); c.src = %%s; c.onload = function() { prompt('', 'gap-iab://%s'); }; d.body.appendChild(c); })(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectStyleCode")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('style'); c.innerHTML = %%s; d.body.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("injectStyleFile")) {
+            String jsWrapper;
+            if (args.getBoolean(1)) {
+                jsWrapper = String.format("(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%s; d.head.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
+            } else {
+                jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document)";
+            }
+            injectDeferredObject(args.getString(0), jsWrapper);
+        }
+        else if (action.equals("show")) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    dialog.show();
+                }
+            });
+            PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
+            pluginResult.setKeepCallback(true);
+            this.callbackContext.sendPluginResult(pluginResult);
+        }
+        else if (action.equals("hide")) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    dialog.hide();
+                }
+            });
+            PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
+            pluginResult.setKeepCallback(true);
+            this.callbackContext.sendPluginResult(pluginResult);
+        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Called when the view navigates.
+     */
+    @Override
+    public void onReset() {
+        closeDialog();
+    }
+
+    /**
+     * Called when the system is about to start resuming a previous activity.
+     */
+    @Override
+    public void onPause(boolean multitasking) {
+        if (shouldPauseInAppBrowser) {
+            inAppWebView.onPause();
+        }
+    }
+
+    /**
+     * Called when the activity will start interacting with the user.
+     */
+    @Override
+    public void onResume(boolean multitasking) {
+        if (shouldPauseInAppBrowser) {
+            inAppWebView.onResume();
+        }
+    }
+
+    /**
+     * Called by AccelBroker when listener is to be shut down.
+     * Stop listener.
+     */
+    public void onDestroy() {
+        closeDialog();
+    }
+
+    /**
+     * Inject an object (script or style) into the InAppBrowser WebView.
+     *
+     * This is a helper method for the inject{Script|Style}{Code|File} API calls, which
+     * provides a consistent method for injecting JavaScript code into the document.
+     *
+     * If a wrapper string is supplied, then the source string will be JSON-encoded (adding
+     * quotes) and wrapped using string formatting. (The wrapper string should have a single
+     * '%s' marker)
+     *
+     * @param source      The source object (filename or script/style text) to inject into
+     *                    the document.
+     * @param jsWrapper   A JavaScript string to wrap the source string in, so that the object
+     *                    is properly injected, or null if the source string is JavaScript text
+     *                    which should be executed directly.
+     */
+    private void injectDeferredObject(String source, String jsWrapper) {
+        if (inAppWebView!=null) {
+            String scriptToInject;
+            if (jsWrapper != null) {
+                org.json.JSONArray jsonEsc = new org.json.JSONArray();
+                jsonEsc.put(source);
+                String jsonRepr = jsonEsc.toString();
+                String jsonSourceString = jsonRepr.substring(1, jsonRepr.length()-1);
+                scriptToInject = String.format(jsWrapper, jsonSourceString);
+            } else {
+                scriptToInject = source;
+            }
+            final String finalScriptToInject = scriptToInject;
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @SuppressLint("NewApi")
+                @Override
+                public void run() {
+                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+                        // This action will have the side-effect of blurring the currently focused element
+                        inAppWebView.loadUrl("javascript:" + finalScriptToInject);
+                    } else {
+                        inAppWebView.evaluateJavascript(finalScriptToInject, null);
+                    }
+                }
+            });
+        } else {
+            LOG.d(LOG_TAG, "Can't inject code into the system browser");
+        }
+    }
+
+    /**
+     * Put the list of features into a hash map
+     *
+     * @param optString
+     * @return
+     */
+    private HashMap<String, String> parseFeature(String optString) {
+        if (optString.equals(NULL)) {
+            return null;
+        } else {
+            HashMap<String, String> map = new HashMap<String, String>();
+            StringTokenizer features = new StringTokenizer(optString, ",");
+            StringTokenizer option;
+            while(features.hasMoreElements()) {
+                option = new StringTokenizer(features.nextToken(), "=");
+                if (option.hasMoreElements()) {
+                    String key = option.nextToken();
+                    String value = option.nextToken();
+                    if (!customizableOptions.contains(key)){
+                        value = value.equals("yes") || value.equals("no") ? value : "yes";
+                    }
+                    map.put(key, value);
+                }
+            }
+            return map;
+        }
+    }
+
+    /**
+     * Display a new browser with the specified URL.
+     *
+     * @param url the url to load.
+     * @return "" if ok, or error message.
+     */
+    public String openExternal(String url) {
+        try {
+            Intent intent = null;
+            intent = new Intent(Intent.ACTION_VIEW);
+            // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
+            // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
+            Uri uri = Uri.parse(url);
+            if ("file".equals(uri.getScheme())) {
+                intent.setDataAndType(uri, webView.getResourceApi().getMimeType(uri));
+            } else {
+                intent.setData(uri);
+            }
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, cordova.getActivity().getPackageName());
+            this.cordova.getActivity().startActivity(intent);
+            return "";
+            // not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
+        } catch (java.lang.RuntimeException e) {
+            LOG.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
+            return e.toString();
+        }
+    }
+
+    /**
+     * Closes the dialog
+     */
+    public void closeDialog() {
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final WebView childView = inAppWebView;
+                // The JS protects against multiple calls, so this should happen only when
+                // closeDialog() is called by other native code.
+                if (childView == null) {
+                    return;
+                }
+
+                childView.setWebViewClient(new WebViewClient() {
+                    // NB: wait for about:blank before dismissing
+                    public void onPageFinished(WebView view, String url) {
+                        if (dialog != null) {
+                            dialog.dismiss();
+                            dialog = null;
+                        }
+                    }
+                });
+                // NB: From SDK 19: "If you call methods on WebView from any thread
+                // other than your app's UI thread, it can cause unexpected results."
+                // http://developer.android.com/guide/webapps/migrating.html#Threads
+                childView.loadUrl("about:blank");
+
+                try {
+                    JSONObject obj = new JSONObject();
+                    obj.put("type", EXIT_EVENT);
+                    sendUpdate(obj, false);
+                } catch (JSONException ex) {
+                    LOG.d(LOG_TAG, "Should never happen");
+                }
+            }
+        });
+    }
+
+    /**
+     * Checks to see if it is possible to go back one page in history, then does so.
+     */
+    public void goBack() {
+        if (this.inAppWebView.canGoBack()) {
+            this.inAppWebView.goBack();
+        }
+    }
+
+    /**
+     * Can the web browser go back?
+     * @return boolean
+     */
+    public boolean canGoBack() {
+        return this.inAppWebView.canGoBack();
+    }
+
+    /**
+     * Has the user set the hardware back button to go back
+     * @return boolean
+     */
+    public boolean hardwareBack() {
+        return hadwareBackButton;
+    }
+
+    /**
+     * Checks to see if it is possible to go forward one page in history, then does so.
+     */
+    private void goForward() {
+        if (this.inAppWebView.canGoForward()) {
+            this.inAppWebView.goForward();
+        }
+    }
+
+    /**
+     * Navigate to the new page
+     *
+     * @param url to load
+     */
+    private void navigate(String url) {
+        InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
+
+        if (!url.startsWith("http") && !url.startsWith("file:")) {
+            this.inAppWebView.loadUrl("http://" + url);
+        } else {
+            this.inAppWebView.loadUrl(url);
+        }
+        this.inAppWebView.requestFocus();
+    }
+
+
+    /**
+     * Should we show the location bar?
+     *
+     * @return boolean
+     */
+    private boolean getShowLocationBar() {
+        return this.showLocationBar;
+    }
+
+    private InAppBrowser getInAppBrowser(){
+        return this;
+    }
+
+    /**
+     * Display a new browser with the specified URL.
+     *
+     * @param url the url to load.
+     * @param features jsonObject
+     */
+    public String showWebPage(final String url, HashMap<String, String> features) {
+        // Determine if we should hide the location bar.
+        showLocationBar = true;
+        showZoomControls = true;
+        openWindowHidden = false;
+        mediaPlaybackRequiresUserGesture = false;
+
+        if (features != null) {
+            String show = features.get(LOCATION);
+            if (show != null) {
+                showLocationBar = show.equals("yes") ? true : false;
+            }
+            if(showLocationBar) {
+                String hideNavigation = features.get(HIDE_NAVIGATION);
+                String hideUrl = features.get(HIDE_URL);
+                if(hideNavigation != null) hideNavigationButtons = hideNavigation.equals("yes") ? true : false;
+                if(hideUrl != null) hideUrlBar = hideUrl.equals("yes") ? true : false;
+            }
+            String zoom = features.get(ZOOM);
+            if (zoom != null) {
+                showZoomControls = zoom.equals("yes") ? true : false;
+            }
+            String hidden = features.get(HIDDEN);
+            if (hidden != null) {
+                openWindowHidden = hidden.equals("yes") ? true : false;
+            }
+            String hardwareBack = features.get(HARDWARE_BACK_BUTTON);
+            if (hardwareBack != null) {
+                hadwareBackButton = hardwareBack.equals("yes") ? true : false;
+            } else {
+                hadwareBackButton = DEFAULT_HARDWARE_BACK;
+            }
+            String mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION);
+            if (mediaPlayback != null) {
+                mediaPlaybackRequiresUserGesture = mediaPlayback.equals("yes") ? true : false;
+            }
+            String cache = features.get(CLEAR_ALL_CACHE);
+            if (cache != null) {
+                clearAllCache = cache.equals("yes") ? true : false;
+            } else {
+                cache = features.get(CLEAR_SESSION_CACHE);
+                if (cache != null) {
+                    clearSessionCache = cache.equals("yes") ? true : false;
+                }
+            }
+            String shouldPause = features.get(SHOULD_PAUSE);
+            if (shouldPause != null) {
+                shouldPauseInAppBrowser = shouldPause.equals("yes") ? true : false;
+            }
+            String wideViewPort = features.get(USER_WIDE_VIEW_PORT);
+            if (wideViewPort != null ) {
+                useWideViewPort = wideViewPort.equals("yes") ? true : false;
+            }
+            String closeButtonCaptionSet = features.get(CLOSE_BUTTON_CAPTION);
+            if (closeButtonCaptionSet != null) {
+                closeButtonCaption = closeButtonCaptionSet;
+            }
+            String closeButtonColorSet = features.get(CLOSE_BUTTON_COLOR);
+            if (closeButtonColorSet != null) {
+                closeButtonColor = closeButtonColorSet;
+            }
+            String toolbarColorSet = features.get(TOOLBAR_COLOR);
+            if (toolbarColorSet != null) {
+                toolbarColor = android.graphics.Color.parseColor(toolbarColorSet);
+            }
+            String navigationButtonColorSet = features.get(NAVIGATION_COLOR);
+            if (navigationButtonColorSet != null) {
+                navigationButtonColor = navigationButtonColorSet;
+            }
+            String showFooterSet = features.get(FOOTER);
+            if (showFooterSet != null) {
+                showFooter = showFooterSet.equals("yes") ? true : false;
+            }
+            String footerColorSet = features.get(FOOTER_COLOR);
+            if (footerColorSet != null) {
+                footerColor = footerColorSet;
+            }
+        }
+
+        final CordovaWebView thatWebView = this.webView;
+
+        // Create dialog in new thread
+        Runnable runnable = new Runnable() {
+            /**
+             * Convert our DIP units to Pixels
+             *
+             * @return int
+             */
+            private int dpToPixels(int dipValue) {
+                int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
+                        (float) dipValue,
+                        cordova.getActivity().getResources().getDisplayMetrics()
+                );
+
+                return value;
+            }
+
+            private View createCloseButton(int id){
+                View _close;
+                Resources activityRes = cordova.getActivity().getResources();
+
+                if (closeButtonCaption != "") {
+                    // Use TextView for text
+                    TextView close = new TextView(cordova.getActivity());
+                    close.setText(closeButtonCaption);
+                    close.setTextSize(20);
+                    if (closeButtonColor != "") close.setTextColor(android.graphics.Color.parseColor(closeButtonColor));
+                    close.setGravity(android.view.Gravity.CENTER_VERTICAL);
+                    close.setPadding(this.dpToPixels(10), 0, this.dpToPixels(10), 0);
+                    _close = close;
+                }
+                else {
+                    ImageButton close = new ImageButton(cordova.getActivity());
+                    int closeResId = activityRes.getIdentifier("ic_action_remove", "drawable", cordova.getActivity().getPackageName());
+                    Drawable closeIcon = activityRes.getDrawable(closeResId);
+                    if (closeButtonColor != "") close.setColorFilter(android.graphics.Color.parseColor(closeButtonColor));
+                    close.setImageDrawable(closeIcon);
+                    close.setScaleType(ImageView.ScaleType.FIT_CENTER);
+                    if (Build.VERSION.SDK_INT >= 16)
+                        close.getAdjustViewBounds();
+
+                    _close = close;
+                }
+
+                RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+                closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+                _close.setLayoutParams(closeLayoutParams);
+
+                if (Build.VERSION.SDK_INT >= 16)
+                    _close.setBackground(null);
+                else
+                    _close.setBackgroundDrawable(null);
+
+                _close.setContentDescription("Close Button");
+                _close.setId(Integer.valueOf(id));
+                _close.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        closeDialog();
+                    }
+                });
+
+                return _close;
+            }
+
+            @SuppressLint("NewApi")
+            public void run() {
+
+                // CB-6702 InAppBrowser hangs when opening more than one instance
+                if (dialog != null) {
+                    dialog.dismiss();
+                };
+
+                // Let's create the main dialog
+                dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
+                dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
+                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+                dialog.setCancelable(true);
+                dialog.setInAppBroswer(getInAppBrowser());
+
+                // Main container layout
+                LinearLayout main = new LinearLayout(cordova.getActivity());
+                main.setOrientation(LinearLayout.VERTICAL);
+
+                // Toolbar layout
+                RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
+                //Please, no more black!
+                toolbar.setBackgroundColor(toolbarColor);
+                toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44)));
+                toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
+                toolbar.setHorizontalGravity(Gravity.LEFT);
+                toolbar.setVerticalGravity(Gravity.TOP);
+
+                // Action Button Container layout
+                RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
+                actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+                actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
+                actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
+                actionButtonContainer.setId(Integer.valueOf(1));
+
+                // Back button
+                ImageButton back = new ImageButton(cordova.getActivity());
+                RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+                backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
+                back.setLayoutParams(backLayoutParams);
+                back.setContentDescription("Back Button");
+                back.setId(Integer.valueOf(2));
+                Resources activityRes = cordova.getActivity().getResources();
+                int backResId = activityRes.getIdentifier("ic_action_previous_item", "drawable", cordova.getActivity().getPackageName());
+                Drawable backIcon = activityRes.getDrawable(backResId);
+                if (navigationButtonColor != "") back.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
+                if (Build.VERSION.SDK_INT >= 16)
+                    back.setBackground(null);
+                else
+                    back.setBackgroundDrawable(null);
+                back.setImageDrawable(backIcon);
+                back.setScaleType(ImageView.ScaleType.FIT_CENTER);
+                back.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10));
+                if (Build.VERSION.SDK_INT >= 16)
+                    back.getAdjustViewBounds();
+
+                back.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        goBack();
+                    }
+                });
+
+                // Forward button
+                ImageButton forward = new ImageButton(cordova.getActivity());
+                RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+                forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
+                forward.setLayoutParams(forwardLayoutParams);
+                forward.setContentDescription("Forward Button");
+                forward.setId(Integer.valueOf(3));
+                int fwdResId = activityRes.getIdentifier("ic_action_next_item", "drawable", cordova.getActivity().getPackageName());
+                Drawable fwdIcon = activityRes.getDrawable(fwdResId);
+                if (navigationButtonColor != "") forward.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
+                if (Build.VERSION.SDK_INT >= 16)
+                    forward.setBackground(null);
+                else
+                    forward.setBackgroundDrawable(null);
+                forward.setImageDrawable(fwdIcon);
+                forward.setScaleType(ImageView.ScaleType.FIT_CENTER);
+                forward.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10));
+                if (Build.VERSION.SDK_INT >= 16)
+                    forward.getAdjustViewBounds();
+
+                forward.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        goForward();
+                    }
+                });
+
+                // Edit Text Box
+                edittext = new EditText(cordova.getActivity());
+                RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+                textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
+                textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
+                edittext.setLayoutParams(textLayoutParams);
+                edittext.setId(Integer.valueOf(4));
+                edittext.setSingleLine(true);
+                edittext.setText(url);
+                edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
+                edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
+                edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
+                edittext.setOnKeyListener(new View.OnKeyListener() {
+                    public boolean onKey(View v, int keyCode, KeyEvent event) {
+                        // If the event is a key-down event on the "enter" button
+                        if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+                            navigate(edittext.getText().toString());
+                            return true;
+                        }
+                        return false;
+                    }
+                });
+
+
+                // Header Close/Done button
+                View close = createCloseButton(5);
+                toolbar.addView(close);
+
+                // Footer
+                RelativeLayout footer = new RelativeLayout(cordova.getActivity());
+                int _footerColor;
+                if(footerColor != ""){
+                    _footerColor = Color.parseColor(footerColor);
+                }else{
+                    _footerColor = android.graphics.Color.LTGRAY;
+                }
+                footer.setBackgroundColor(_footerColor);
+                RelativeLayout.LayoutParams footerLayout = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44));
+                footerLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
+                footer.setLayoutParams(footerLayout);
+                if (closeButtonCaption != "") footer.setPadding(this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8));
+                footer.setHorizontalGravity(Gravity.LEFT);
+                footer.setVerticalGravity(Gravity.BOTTOM);
+
+                View footerClose = createCloseButton(7);
+                footer.addView(footerClose);
+
+
+                // WebView
+                inAppWebView = new WebView(cordova.getActivity());
+                inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+                inAppWebView.setId(Integer.valueOf(6));
+                // File Chooser Implemented ChromeClient
+                inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView) {
+                    // For Android 5.0+
+                    public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
+                    {
+                        LOG.d(LOG_TAG, "File Chooser 5.0+");
+                        // If callback exists, finish it.
+                        if(mUploadCallbackLollipop != null) {
+                            mUploadCallbackLollipop.onReceiveValue(null);
+                        }
+                        mUploadCallbackLollipop = filePathCallback;
+
+                        // Create File Chooser Intent
+                        Intent content = new Intent(Intent.ACTION_GET_CONTENT);
+                        content.addCategory(Intent.CATEGORY_OPENABLE);
+                        content.setType("*/*");
+
+                        // Run cordova startActivityForResult
+                        cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE_LOLLIPOP);
+                        return true;
+                    }
+
+                    // For Android 4.1+
+                    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
+                    {
+                        LOG.d(LOG_TAG, "File Chooser 4.1+");
+                        // Call file chooser for Android 3.0+
+                        openFileChooser(uploadMsg, acceptType);
+                    }
+
+                    // For Android 3.0+
+                    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType)
+                    {
+                        LOG.d(LOG_TAG, "File Chooser 3.0+");
+                        mUploadCallback = uploadMsg;
+                        Intent content = new Intent(Intent.ACTION_GET_CONTENT);
+                        content.addCategory(Intent.CATEGORY_OPENABLE);
+
+                        // run startActivityForResult
+                        cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE);
+                    }
+
+                });
+                WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
+                inAppWebView.setWebViewClient(client);
+                WebSettings settings = inAppWebView.getSettings();
+                settings.setJavaScriptEnabled(true);
+                settings.setJavaScriptCanOpenWindowsAutomatically(true);
+                settings.setBuiltInZoomControls(showZoomControls);
+                settings.setPluginState(android.webkit.WebSettings.PluginState.ON);
+
+                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                    settings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture);
+                }
+
+                String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
+                String appendUserAgent = preferences.getString("AppendUserAgent", null);
+
+                if (overrideUserAgent != null) {
+                    settings.setUserAgentString(overrideUserAgent);
+                }
+                if (appendUserAgent != null) {
+                    settings.setUserAgentString(settings.getUserAgentString() + appendUserAgent);
+                }
+
+                //Toggle whether this is enabled or not!
+                Bundle appSettings = cordova.getActivity().getIntent().getExtras();
+                boolean enableDatabase = appSettings == null ? true : appSettings.getBoolean("InAppBrowserStorageEnabled", true);
+                if (enableDatabase) {
+                    String databasePath = cordova.getActivity().getApplicationContext().getDir("inAppBrowserDB", Context.MODE_PRIVATE).getPath();
+                    settings.setDatabasePath(databasePath);
+                    settings.setDatabaseEnabled(true);
+                }
+                settings.setDomStorageEnabled(true);
+
+                if (clearAllCache) {
+                    CookieManager.getInstance().removeAllCookie();
+                } else if (clearSessionCache) {
+                    CookieManager.getInstance().removeSessionCookie();
+                }
+
+                // Enable Thirdparty Cookies on >=Android 5.0 device
+                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+                    CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
+                }
+
+                inAppWebView.loadUrl(url);
+                inAppWebView.setId(Integer.valueOf(6));
+                inAppWebView.getSettings().setLoadWithOverviewMode(true);
+                inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);
+                inAppWebView.requestFocus();
+                inAppWebView.requestFocusFromTouch();
+
+                // Add the back and forward buttons to our action button container layout
+                actionButtonContainer.addView(back);
+                actionButtonContainer.addView(forward);
+
+                // Add the views to our toolbar if they haven't been disabled
+                if (!hideNavigationButtons) toolbar.addView(actionButtonContainer);
+                if (!hideUrlBar) toolbar.addView(edittext);
+
+                // Don't add the toolbar if its been disabled
+                if (getShowLocationBar()) {
+                    // Add our toolbar to our main view/layout
+                    main.addView(toolbar);
+                }
+
+                // Add our webview to our main view/layout
+                RelativeLayout webViewLayout = new RelativeLayout(cordova.getActivity());
+                webViewLayout.addView(inAppWebView);
+                main.addView(webViewLayout);
+
+                // Don't add the footer unless it's been enabled
+                if (showFooter) {
+                    webViewLayout.addView(footer);
+                }
+
+                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+                lp.copyFrom(dialog.getWindow().getAttributes());
+                lp.width = WindowManager.LayoutParams.MATCH_PARENT;
+                lp.height = WindowManager.LayoutParams.MATCH_PARENT;
+
+                dialog.setContentView(main);
+                dialog.show();
+                dialog.getWindow().setAttributes(lp);
+                // the goal of openhidden is to load the url and not display it
+                // Show() needs to be called to cause the URL to be loaded
+                if(openWindowHidden) {
+                    dialog.hide();
+                }
+            }
+        };
+        this.cordova.getActivity().runOnUiThread(runnable);
+        return "";
+    }
+
+    /**
+     * Create a new plugin success result and send it back to JavaScript
+     *
+     * @param obj a JSONObject contain event payload information
+     */
+    private void sendUpdate(JSONObject obj, boolean keepCallback) {
+        sendUpdate(obj, keepCallback, PluginResult.Status.OK);
+    }
+
+    /**
+     * Create a new plugin result and send it back to JavaScript
+     *
+     * @param obj a JSONObject contain event payload information
+     * @param status the status code to return to the JavaScript environment
+     */
+    private void sendUpdate(JSONObject obj, boolean keepCallback, PluginResult.Status status) {
+        if (callbackContext != null) {
+            PluginResult result = new PluginResult(status, obj);
+            result.setKeepCallback(keepCallback);
+            callbackContext.sendPluginResult(result);
+            if (!keepCallback) {
+                callbackContext = null;
+            }
+        }
+    }
+
+    /**
+     * Receive File Data from File Chooser
+     *
+     * @param requestCode the requested code from chromeclient
+     * @param resultCode the result code returned from android system
+     * @param intent the data from android file chooser
+     */
+    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        // For Android >= 5.0
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            LOG.d(LOG_TAG, "onActivityResult (For Android >= 5.0)");
+            // If RequestCode or Callback is Invalid
+            if(requestCode != FILECHOOSER_REQUESTCODE_LOLLIPOP || mUploadCallbackLollipop == null) {
+                super.onActivityResult(requestCode, resultCode, intent);
+                return;
+            }
+            mUploadCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
+            mUploadCallbackLollipop = null;
+        }
+        // For Android < 5.0
+        else {
+            LOG.d(LOG_TAG, "onActivityResult (For Android < 5.0)");
+            // If RequestCode or Callback is Invalid
+            if(requestCode != FILECHOOSER_REQUESTCODE || mUploadCallback == null) {
+                super.onActivityResult(requestCode, resultCode, intent);
+                return;
+            }
+
+            if (null == mUploadCallback) return;
+            Uri result = intent == null || resultCode != cordova.getActivity().RESULT_OK ? null : intent.getData();
+
+            mUploadCallback.onReceiveValue(result);
+            mUploadCallback = null;
+        }
+    }
+
+    /**
+     * The webview client receives notifications about appView
+     */
+    public class InAppBrowserClient extends WebViewClient {
+        EditText edittext;
+        CordovaWebView webView;
+
+        /**
+         * Constructor.
+         *
+         * @param webView
+         * @param mEditText
+         */
+        public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
+            this.webView = webView;
+            this.edittext = mEditText;
+        }
+
+        /**
+         * Override the URL that should be loaded
+         *
+         * This handles a small subset of all the URIs that would be encountered.
+         *
+         * @param webView
+         * @param url
+         */
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
+            if (url.startsWith(WebView.SCHEME_TEL)) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_DIAL);
+                    intent.setData(Uri.parse(url));
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
+                }
+            } else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:") || url.startsWith("intent:")) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+                    intent.setData(Uri.parse(url));
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(LOG_TAG, "Error with " + url + ": " + e.toString());
+                }
+            }
+            // If sms:5551212?body=This is the message
+            else if (url.startsWith("sms:")) {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+
+                    // Get address
+                    String address = null;
+                    int parmIndex = url.indexOf('?');
+                    if (parmIndex == -1) {
+                        address = url.substring(4);
+                    } else {
+                        address = url.substring(4, parmIndex);
+
+                        // If body, then set sms body
+                        Uri uri = Uri.parse(url);
+                        String query = uri.getQuery();
+                        if (query != null) {
+                            if (query.startsWith("body=")) {
+                                intent.putExtra("sms_body", query.substring(5));
+                            }
+                        }
+                    }
+                    intent.setData(Uri.parse("sms:" + address));
+                    intent.putExtra("address", address);
+                    intent.setType("vnd.android-dir/mms-sms");
+                    cordova.getActivity().startActivity(intent);
+                    return true;
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
+                }
+            }
+            // Test for whitelisted custom scheme names like mycoolapp:// or twitteroauthresponse:// (Twitter Oauth Response)
+            else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^[a-z]*://.*?$")) {
+                if (allowedSchemes == null) {
+                    String allowed = preferences.getString("AllowedSchemes", "");
+                    allowedSchemes = allowed.split(",");
+                }
+                if (allowedSchemes != null) {
+                    for (String scheme : allowedSchemes) {
+                        if (url.startsWith(scheme)) {
+                            try {
+                                JSONObject obj = new JSONObject();
+                                obj.put("type", "customscheme");
+                                obj.put("url", url);
+                                sendUpdate(obj, true);
+                                return true;
+                            } catch (JSONException ex) {
+                                LOG.e(LOG_TAG, "Custom Scheme URI passed in has caused a JSON error.");
+                            }
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+
+
+        /*
+         * onPageStarted fires the LOAD_START_EVENT
+         *
+         * @param view
+         * @param url
+         * @param favicon
+         */
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            String newloc = "";
+            if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
+                newloc = url;
+            }
+            else
+            {
+                // Assume that everything is HTTP at this point, because if we don't specify,
+                // it really should be.  Complain loudly about this!!!
+                LOG.e(LOG_TAG, "Possible Uncaught/Unknown URI");
+                newloc = "http://" + url;
+            }
+
+            // Update the UI if we haven't already
+            if (!newloc.equals(edittext.getText().toString())) {
+                edittext.setText(newloc);
+            }
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_START_EVENT);
+                obj.put("url", newloc);
+                sendUpdate(obj, true);
+            } catch (JSONException ex) {
+                LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
+            }
+        }
+
+
+
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+
+            // CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+                CookieManager.getInstance().flush();
+            } else {
+                CookieSyncManager.getInstance().sync();
+            }
+
+            // https://issues.apache.org/jira/browse/CB-11248
+            view.clearFocus();
+            view.requestFocus();
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_STOP_EVENT);
+                obj.put("url", url);
+
+                sendUpdate(obj, true);
+            } catch (JSONException ex) {
+                LOG.d(LOG_TAG, "Should never happen");
+            }
+        }
+
+        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+            super.onReceivedError(view, errorCode, description, failingUrl);
+
+            try {
+                JSONObject obj = new JSONObject();
+                obj.put("type", LOAD_ERROR_EVENT);
+                obj.put("url", failingUrl);
+                obj.put("code", errorCode);
+                obj.put("message", description);
+
+                sendUpdate(obj, true, PluginResult.Status.ERROR);
+            } catch (JSONException ex) {
+                LOG.d(LOG_TAG, "Should never happen");
+            }
+        }
+
+        /**
+         * On received http auth request.
+         */
+        @Override
+        public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
+
+            // Check if there is some plugin which can resolve this auth challenge
+            PluginManager pluginManager = null;
+            try {
+                Method gpm = webView.getClass().getMethod("getPluginManager");
+                pluginManager = (PluginManager)gpm.invoke(webView);
+            } catch (NoSuchMethodException e) {
+                LOG.d(LOG_TAG, e.getLocalizedMessage());
+            } catch (IllegalAccessException e) {
+                LOG.d(LOG_TAG, e.getLocalizedMessage());
+            } catch (InvocationTargetException e) {
+                LOG.d(LOG_TAG, e.getLocalizedMessage());
+            }
+
+            if (pluginManager == null) {
+                try {
+                    Field pmf = webView.getClass().getField("pluginManager");
+                    pluginManager = (PluginManager)pmf.get(webView);
+                } catch (NoSuchFieldException e) {
+                    LOG.d(LOG_TAG, e.getLocalizedMessage());
+                } catch (IllegalAccessException e) {
+                    LOG.d(LOG_TAG, e.getLocalizedMessage());
+                }
+            }
+
+            if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(webView, new CordovaHttpAuthHandler(handler), host, realm)) {
+                return;
+            }
+
+            // By default handle 401 like we'd normally do!
+            super.onReceivedHttpAuthRequest(view, handler, host, realm);
+        }
+    }
+}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java
new file mode 100644
index 0000000..e7b212f
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java
@@ -0,0 +1,57 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.inappbrowser;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Created by Oliver on 22/11/2013.
+ */
+public class InAppBrowserDialog extends Dialog {
+    Context context;
+    InAppBrowser inAppBrowser = null;
+
+    public InAppBrowserDialog(Context context, int theme) {
+        super(context, theme);
+        this.context = context;
+    }
+
+    public void setInAppBroswer(InAppBrowser browser) {
+        this.inAppBrowser = browser;
+    }
+
+    public void onBackPressed () {
+        if (this.inAppBrowser == null) {
+            this.dismiss();
+        } else {
+            // better to go through the in inAppBrowser
+            // because it does a clean up
+            if (this.inAppBrowser.hardwareBack() && this.inAppBrowser.canGoBack()) {
+                this.inAppBrowser.goBack();
+            }  else {
+                this.inAppBrowser.closeDialog();
+            }
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java
new file mode 100644
index 0000000..a2145e6
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java
@@ -0,0 +1,133 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+package org.apache.cordova.inappbrowser;
+
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.webkit.JsPromptResult;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.webkit.GeolocationPermissions.Callback;
+
+public class InAppChromeClient extends WebChromeClient {
+
+    private CordovaWebView webView;
+    private String LOG_TAG = "InAppChromeClient";
+    private long MAX_QUOTA = 100 * 1024 * 1024;
+
+    public InAppChromeClient(CordovaWebView webView) {
+        super();
+        this.webView = webView;
+    }
+    /**
+     * Handle database quota exceeded notification.
+     *
+     * @param url
+     * @param databaseIdentifier
+     * @param currentQuota
+     * @param estimatedSize
+     * @param totalUsedQuota
+     * @param quotaUpdater
+     */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
+    {
+        LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
+        quotaUpdater.updateQuota(MAX_QUOTA);
+    }
+
+    /**
+     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+     *
+     * @param origin
+     * @param callback
+     */
+    @Override
+    public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        callback.invoke(origin, true, false);
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * The prompt bridge provided for the InAppBrowser is capable of executing any
+     * oustanding callback belonging to the InAppBrowser plugin. Care has been
+     * taken that other callbacks cannot be triggered, and that no other code
+     * execution is possible.
+     *
+     * To trigger the bridge, the prompt default value should be of the form:
+     *
+     * gap-iab://<callbackId>
+     *
+     * where <callbackId> is the string id of the callback to trigger (something
+     * like "InAppBrowser0123456789")
+     *
+     * If present, the prompt message is expected to be a JSON-encoded value to
+     * pass to the callback. A JSON_EXCEPTION is returned if the JSON is invalid.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param defaultValue
+     * @param result
+     */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
+        // See if the prompt string uses the 'gap-iab' protocol. If so, the remainder should be the id of a callback to execute.
+        if (defaultValue != null && defaultValue.startsWith("gap")) {
+            if(defaultValue.startsWith("gap-iab://")) {
+                PluginResult scriptResult;
+                String scriptCallbackId = defaultValue.substring(10);
+                if (scriptCallbackId.startsWith("InAppBrowser")) {
+                    if(message == null || message.length() == 0) {
+                        scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray());
+                    } else {
+                        try {
+                            scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray(message));
+                        } catch(JSONException e) {
+                            scriptResult = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
+                        }
+                    }
+                    this.webView.sendPluginResult(scriptResult, scriptCallbackId);
+                    result.confirm("");
+                    return true;
+                }
+            }
+            else
+            {
+                // Anything else with a gap: prefix should get this message
+                LOG.w(LOG_TAG, "InAppBrowser does not support Cordova API calls: " + url + " " + defaultValue); 
+                result.cancel();
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java b/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java
new file mode 100644
index 0000000..714c30e
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/statusbar/StatusBar.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+package org.apache.cordova.statusbar;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Build;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaArgs;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+import java.util.Arrays;
+
+public class StatusBar extends CordovaPlugin {
+    private static final String TAG = "StatusBar";
+
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     *
+     * @param cordova The context of the main Activity.
+     * @param webView The CordovaWebView Cordova is running in.
+     */
+    @Override
+    public void initialize(final CordovaInterface cordova, CordovaWebView webView) {
+        LOG.v(TAG, "StatusBar: initialization");
+        super.initialize(cordova, webView);
+
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially
+                // by the Cordova.
+                Window window = cordova.getActivity().getWindow();
+                window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+
+                // Read 'StatusBarBackgroundColor' from config.xml, default is #000000.
+                setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000"));
+
+                // Read 'StatusBarStyle' from config.xml, default is 'lightcontent'.
+                setStatusBarStyle(preferences.getString("StatusBarStyle", "lightcontent"));
+            }
+        });
+    }
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @param action            The action to execute.
+     * @param args              JSONArry of arguments for the plugin.
+     * @param callbackContext   The callback id used when calling back into JavaScript.
+     * @return                  True if the action was valid, false otherwise.
+     */
+    @Override
+    public boolean execute(final String action, final CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
+        LOG.v(TAG, "Executing action: " + action);
+        final Activity activity = this.cordova.getActivity();
+        final Window window = activity.getWindow();
+
+        if ("_ready".equals(action)) {
+            boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
+            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible));
+            return true;
+        }
+
+        if ("show".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
+                    // use KitKat here to be aligned with "Fullscreen"  preference
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                        int uiOptions = window.getDecorView().getSystemUiVisibility();
+                        uiOptions &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+                        uiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
+
+                        window.getDecorView().setSystemUiVisibility(uiOptions);
+                    }
+
+                    // CB-11197 We still need to update LayoutParams to force status bar
+                    // to be hidden when entering e.g. text fields
+                    window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+                }
+            });
+            return true;
+        }
+
+        if ("hide".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    // SYSTEM_UI_FLAG_FULLSCREEN is available since JellyBean, but we
+                    // use KitKat here to be aligned with "Fullscreen"  preference
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                        int uiOptions = window.getDecorView().getSystemUiVisibility()
+                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                                | View.SYSTEM_UI_FLAG_FULLSCREEN;
+
+                        window.getDecorView().setSystemUiVisibility(uiOptions);
+                    }
+
+                    // CB-11197 We still need to update LayoutParams to force status bar
+                    // to be hidden when entering e.g. text fields
+                    window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+                }
+            });
+            return true;
+        }
+
+        if ("backgroundColorByHexString".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        setStatusBarBackgroundColor(args.getString(0));
+                    } catch (JSONException ignore) {
+                        LOG.e(TAG, "Invalid hexString argument, use f.i. '#777777'");
+                    }
+                }
+            });
+            return true;
+        }
+
+        if ("overlaysWebView".equals(action)) {
+            if (Build.VERSION.SDK_INT >= 21) {
+                this.cordova.getActivity().runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            setStatusBarTransparent(args.getBoolean(0));
+                        } catch (JSONException ignore) {
+                            LOG.e(TAG, "Invalid boolean argument");
+                        }
+                    }
+                });
+                return true;
+            }
+            else return args.getBoolean(0) == false;
+        }
+
+        if ("styleDefault".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    setStatusBarStyle("default");
+                }
+            });
+            return true;
+        }
+
+        if ("styleLightContent".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    setStatusBarStyle("lightcontent");
+                }
+            });
+            return true;
+        }
+
+        if ("styleBlackTranslucent".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    setStatusBarStyle("blacktranslucent");
+                }
+            });
+            return true;
+        }
+
+        if ("styleBlackOpaque".equals(action)) {
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    setStatusBarStyle("blackopaque");
+                }
+            });
+            return true;
+        }
+
+        return false;
+    }
+
+    private void setStatusBarBackgroundColor(final String colorPref) {
+        if (Build.VERSION.SDK_INT >= 21) {
+            if (colorPref != null && !colorPref.isEmpty()) {
+                final Window window = cordova.getActivity().getWindow();
+                // Method and constants not available on all SDKs but we want to be able to compile this code with any SDK
+                window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+                window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+                try {
+                    // Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21
+                    window.getClass().getMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref));
+                } catch (IllegalArgumentException ignore) {
+                    LOG.e(TAG, "Invalid hexString argument, use f.i. '#999999'");
+                } catch (Exception ignore) {
+                    // this should not happen, only in case Android removes this method in a version > 21
+                    LOG.w(TAG, "Method window.setStatusBarColor not found for SDK level " + Build.VERSION.SDK_INT);
+                }
+            }
+        }
+    }
+
+    private void setStatusBarTransparent(final boolean transparent) {
+        if (Build.VERSION.SDK_INT >= 21) {
+            final Window window = cordova.getActivity().getWindow();
+            if (transparent) {
+                window.getDecorView().setSystemUiVisibility(
+                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+                window.setStatusBarColor(Color.TRANSPARENT);
+            }
+            else {
+                window.getDecorView().setSystemUiVisibility(
+                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                                | View.SYSTEM_UI_FLAG_VISIBLE);
+            }
+        }
+    }
+
+    private void setStatusBarStyle(final String style) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (style != null && !style.isEmpty()) {
+                View decorView = cordova.getActivity().getWindow().getDecorView();
+                int uiOptions = decorView.getSystemUiVisibility();
+
+                String[] darkContentStyles = {
+                    "default",
+                };
+
+                String[] lightContentStyles = {
+                    "lightcontent",
+                    "blacktranslucent",
+                    "blackopaque",
+                };
+
+                if (Arrays.asList(darkContentStyles).contains(style.toLowerCase())) {
+                    decorView.setSystemUiVisibility(uiOptions | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+                    return;
+                }
+
+                if (Arrays.asList(lightContentStyles).contains(style.toLowerCase())) {
+                    decorView.setSystemUiVisibility(uiOptions & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+                    return;
+                }
+
+                LOG.e(TAG, "Invalid style, must be either 'default', 'lightcontent' or the deprecated 'blacktranslucent' and 'blackopaque'");
+            }
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java b/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java
new file mode 100644
index 0000000..3656788
--- /dev/null
+++ b/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java
@@ -0,0 +1,161 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+package org.apache.cordova.whitelist;
+
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.ConfigXmlParser;
+import org.apache.cordova.LOG;
+import org.apache.cordova.Whitelist;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+
+public class WhitelistPlugin extends CordovaPlugin {
+    private static final String LOG_TAG = "WhitelistPlugin";
+    private Whitelist allowedNavigations;
+    private Whitelist allowedIntents;
+    private Whitelist allowedRequests;
+
+    // Used when instantiated via reflection by PluginManager
+    public WhitelistPlugin() {
+    }
+    // These can be used by embedders to allow Java-configuration of whitelists.
+    public WhitelistPlugin(Context context) {
+        this(new Whitelist(), new Whitelist(), null);
+        new CustomConfigXmlParser().parse(context);
+    }
+    public WhitelistPlugin(XmlPullParser xmlParser) {
+        this(new Whitelist(), new Whitelist(), null);
+        new CustomConfigXmlParser().parse(xmlParser);
+    }
+    public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
+        if (allowedRequests == null) {
+            allowedRequests = new Whitelist();
+            allowedRequests.addWhiteListEntry("file:///*", false);
+            allowedRequests.addWhiteListEntry("data:*", false);
+        }
+        this.allowedNavigations = allowedNavigations;
+        this.allowedIntents = allowedIntents;
+        this.allowedRequests = allowedRequests;
+    }
+    @Override
+    public void pluginInitialize() {
+        if (allowedNavigations == null) {
+            allowedNavigations = new Whitelist();
+            allowedIntents = new Whitelist();
+            allowedRequests = new Whitelist();
+            new CustomConfigXmlParser().parse(webView.getContext());
+        }
+    }
+
+    private class CustomConfigXmlParser extends ConfigXmlParser {
+        @Override
+        public void handleStartTag(XmlPullParser xml) {
+            String strNode = xml.getName();
+            if (strNode.equals("content")) {
+                String startPage = xml.getAttributeValue(null, "src");
+                allowedNavigations.addWhiteListEntry(startPage, false);
+            } else if (strNode.equals("allow-navigation")) {
+                String origin = xml.getAttributeValue(null, "href");
+                if ("*".equals(origin)) {
+                    allowedNavigations.addWhiteListEntry("http://*/*", false);
+                    allowedNavigations.addWhiteListEntry("https://*/*", false);
+                    allowedNavigations.addWhiteListEntry("data:*", false);
+                } else {
+                    allowedNavigations.addWhiteListEntry(origin, false);
+                }
+            } else if (strNode.equals("allow-intent")) {
+                String origin = xml.getAttributeValue(null, "href");
+                allowedIntents.addWhiteListEntry(origin, false);
+            } else if (strNode.equals("access")) {
+                String origin = xml.getAttributeValue(null, "origin");
+                String subdomains = xml.getAttributeValue(null, "subdomains");
+                boolean external = (xml.getAttributeValue(null, "launch-external") != null);
+                if (origin != null) {
+                    if (external) {
+                        LOG.w(LOG_TAG, "Found <access launch-external> within config.xml. Please use <allow-intent> instead.");
+                        allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
+                    } else {
+                        if ("*".equals(origin)) {
+                            allowedRequests.addWhiteListEntry("http://*/*", false);
+                            allowedRequests.addWhiteListEntry("https://*/*", false);
+                        } else {
+                            allowedRequests.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
+                        }
+                    }
+                }
+            }
+        }
+        @Override
+        public void handleEndTag(XmlPullParser xml) {
+        }
+    }
+
+    @Override
+    public Boolean shouldAllowNavigation(String url) {
+        if (allowedNavigations.isUrlWhiteListed(url)) {
+            return true;
+        }
+        return null; // Default policy
+    }
+
+    @Override
+    public Boolean shouldAllowRequest(String url) {
+        if (Boolean.TRUE == shouldAllowNavigation(url)) {
+            return true;
+        }
+        if (allowedRequests.isUrlWhiteListed(url)) {
+            return true;
+        }
+        return null; // Default policy
+    }
+
+    @Override
+    public Boolean shouldOpenExternalUrl(String url) {
+        if (allowedIntents.isUrlWhiteListed(url)) {
+            return true;
+        }
+        return null; // Default policy
+    }
+
+    public Whitelist getAllowedNavigations() {
+        return allowedNavigations;
+    }
+
+    public void setAllowedNavigations(Whitelist allowedNavigations) {
+        this.allowedNavigations = allowedNavigations;
+    }
+
+    public Whitelist getAllowedIntents() {
+        return allowedIntents;
+    }
+
+    public void setAllowedIntents(Whitelist allowedIntents) {
+        this.allowedIntents = allowedIntents;
+    }
+
+    public Whitelist getAllowedRequests() {
+        return allowedRequests;
+    }
+
+    public void setAllowedRequests(Whitelist allowedRequests) {
+        this.allowedRequests = allowedRequests;
+    }
+}
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/back.png b/platforms/android/app/src/main/res/drawable-hdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/close.png b/platforms/android/app/src/main/res/drawable-hdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png
new file mode 100644
index 0000000..fa469d8
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png
new file mode 100644
index 0000000..e861ecc
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png
new file mode 100644
index 0000000..f889617
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png
new file mode 100644
index 0000000..48ebd8a
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/ic_fp_40px.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/icon.png b/platforms/android/app/src/main/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..4edb4c6
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png
new file mode 100644
index 0000000..2c913c6
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png
new file mode 100644
index 0000000..99733ed
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png
new file mode 100644
index 0000000..08f9099
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png
new file mode 100644
index 0000000..67cf009
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png
new file mode 100644
index 0000000..40edb57
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png
new file mode 100644
index 0000000..4e1b40c
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-ldpi/icon.png b/platforms/android/app/src/main/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..0508de6
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/back.png b/platforms/android/app/src/main/res/drawable-mdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/close.png b/platforms/android/app/src/main/res/drawable-mdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png
new file mode 100644
index 0000000..47365a3
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png
new file mode 100644
index 0000000..4ad2df4
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png
new file mode 100644
index 0000000..e84853e
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png
new file mode 100644
index 0000000..122f442
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/ic_fp_40px.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/icon.png b/platforms/android/app/src/main/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..ed81661
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png b/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png
new file mode 100644
index 0000000..40bf934
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-nodpi/android_robot.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png
new file mode 100644
index 0000000..d7c1408
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png
new file mode 100644
index 0000000..d600ced
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png
new file mode 100644
index 0000000..2b19050
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png
new file mode 100644
index 0000000..a64fa6d
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png
new file mode 100644
index 0000000..81e6fe0
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png
new file mode 100644
index 0000000..e26e482
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/back.png b/platforms/android/app/src/main/res/drawable-xhdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/close.png b/platforms/android/app/src/main/res/drawable-xhdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png
new file mode 100644
index 0000000..5f30474
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png
new file mode 100644
index 0000000..ed8ac91
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png
new file mode 100644
index 0000000..4cd0458
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..e1c9590
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/ic_fp_40px.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/icon.png b/platforms/android/app/src/main/res/drawable-xhdpi/icon.png
new file mode 100644
index 0000000..b764a7e
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/back.png b/platforms/android/app/src/main/res/drawable-xxhdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/close.png b/platforms/android/app/src/main/res/drawable-xxhdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png
new file mode 100644
index 0000000..51479d8
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png
new file mode 100644
index 0000000..bc8ff12
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png
new file mode 100644
index 0000000..331c545
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..f7e8724
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_fp_40px.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/icon.png b/platforms/android/app/src/main/res/drawable-xxhdpi/icon.png
new file mode 100644
index 0000000..3c7efa4
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png b/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png
new file mode 100644
index 0000000..0fb8545
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxxhdpi/ic_fp_40px.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable-xxxhdpi/icon.png b/platforms/android/app/src/main/res/drawable-xxxhdpi/icon.png
new file mode 100644
index 0000000..8c027a7
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable-xxxhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml b/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml
new file mode 100644
index 0000000..be46116
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable/ic_fingerprint_error.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="40.0dp"
+        android:height="40.0dp"
+        android:viewportWidth="40.0"
+        android:viewportHeight="40.0">
+    <path
+        android:pathData="M20.0,0.0C8.96,0.0 0.0,8.95 0.0,20.0s8.96,20.0 20.0,20.0c11.04,0.0 20.0,-8.95 20.0,-20.0S31.04,0.0 20.0,0.0z"
+        android:fillColor="#F4511E"/>
+    <path
+        android:pathData="M21.33,29.33l-2.67,0.0l0.0,-2.67l2.67,0.0L21.33,29.33zM21.33,22.67l-2.67,0.0l0.0,-12.0l2.67,0.0L21.33,22.67z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml b/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml
new file mode 100644
index 0000000..261f3e7
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable/ic_fingerprint_success.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="40.0dp"
+        android:height="40.0dp"
+        android:viewportWidth="40.0"
+        android:viewportHeight="40.0">
+    <path
+        android:pathData="M20.0,20.0m-20.0,0.0a20.0,20.0 0.0,1.0 1.0,40.0 0.0a20.0,20.0 0.0,1.0 1.0,-40.0 0.0"
+        android:fillColor="#009688"/>
+    <path
+        android:pathData="M11.2,21.41l1.63,-1.619999 4.17,4.169998 10.59,-10.589999 1.619999,1.63 -12.209999,12.209999z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/platforms/android/app/src/main/res/drawable/icon.png b/platforms/android/app/src/main/res/drawable/icon.png
new file mode 100644
index 0000000..b764a7e
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml b/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml
new file mode 100644
index 0000000..0c6face
--- /dev/null
+++ b/platforms/android/app/src/main/res/layout/fingerprint_dialog_container.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <include layout="@layout/fingerprint_dialog_content" />
+
+    </FrameLayout>
+
+    <LinearLayout
+        android:id="@+id/buttonPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        android:gravity="bottom"
+        style="?android:attr/buttonBarStyle">
+
+        <Space
+            android:id="@+id/spacer"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" />
+        <Button
+            android:id="@+id/cancel_button"
+            style="?android:attr/buttonBarNegativeButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+
+        <Button
+            android:id="@+id/second_dialog_button"
+            style="?android:attr/buttonBarPositiveButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/layout/fingerprint_dialog_content.xml b/platforms/android/app/src/main/res/layout/fingerprint_dialog_content.xml
new file mode 100644
index 0000000..3929eba
--- /dev/null
+++ b/platforms/android/app/src/main/res/layout/fingerprint_dialog_content.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/fingerprint_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="8dp"
+    android:paddingStart="24dp"
+    android:paddingEnd="24dp"
+    android:paddingTop="16dp">
+
+    <TextView
+        android:id="@+id/fingerprint_description"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentTop="true"
+        android:text="@string/fingerprint_description"
+        android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+        android:textColor="?android:attr/textColorSecondary"/>
+
+
+    <ImageView
+        android:id="@+id/fingerprint_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_below="@+id/fingerprint_description"
+        android:layout_marginTop="20dp"
+        android:src="@drawable/ic_fp_40px" />
+
+    <TextView
+        android:id="@+id/fingerprint_status"
+        style="@android:style/TextAppearance.Material.Body1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@+id/fingerprint_icon"
+        android:layout_alignTop="@+id/fingerprint_icon"
+        android:layout_marginStart="16dp"
+        android:layout_toEndOf="@+id/fingerprint_icon"
+        android:gravity="center_vertical"
+        android:text="@string/fingerprint_hint"
+        android:textColor="@color/hint_color" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi-v26/back.png b/platforms/android/app/src/main/res/mipmap-hdpi-v26/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi-v26/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi-v26/close.png b/platforms/android/app/src/main/res/mipmap-hdpi-v26/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi-v26/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..021da86
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..5384261
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi/back.png b/platforms/android/app/src/main/res/mipmap-hdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi/close.png b/platforms/android/app/src/main/res/mipmap-hdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..5384261
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi/icon.png b/platforms/android/app/src/main/res/mipmap-hdpi/icon.png
new file mode 100644
index 0000000..4edb4c6
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-hdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..da47a97
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..203223a
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-ldpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-ldpi/ic_launcher.png
new file mode 100644
index 0000000..c5fcaeb
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-ldpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi/icon.png b/platforms/android/app/src/main/res/mipmap-ldpi/icon.png
new file mode 100644
index 0000000..0508de6
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-ldpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi-v26/back.png b/platforms/android/app/src/main/res/mipmap-mdpi-v26/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi-v26/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi-v26/close.png b/platforms/android/app/src/main/res/mipmap-mdpi-v26/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi-v26/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..74e56e5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..8ca658e
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi/back.png b/platforms/android/app/src/main/res/mipmap-mdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi/close.png b/platforms/android/app/src/main/res/mipmap-mdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..a18167b
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi/icon.png b/platforms/android/app/src/main/res/mipmap-mdpi/icon.png
new file mode 100644
index 0000000..ed81661
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-mdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..d0cb62d
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..ae324f2
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi/back.png b/platforms/android/app/src/main/res/mipmap-xhdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi/close.png b/platforms/android/app/src/main/res/mipmap-xhdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..9e3eec3
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png
new file mode 100644
index 0000000..b764a7e
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..ec38d40
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..7983ef4
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi/back.png b/platforms/android/app/src/main/res/mipmap-xxhdpi/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi/close.png b/platforms/android/app/src/main/res/mipmap-xxhdpi/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..a569289
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png
new file mode 100644
index 0000000..3c7efa4
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher.xml b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..be31618
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_launcher_background" />
+    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_background.png b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_background.png
new file mode 100644
index 0000000..d652c08
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_background.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png
new file mode 100644
index 0000000..6857bef
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..3c322f2
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png
new file mode 100644
index 0000000..8c027a7
--- /dev/null
+++ b/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/values-da/fpauth-strings.xml b/platforms/android/app/src/main/res/values-da/fpauth-strings.xml
new file mode 100644
index 0000000..346666f
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-da/fpauth-strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="fingerprint_cancel">Annuller</string>
+    <string name="fingerprint_use_backup">Brug backup</string>
+    <string name="fingerprint_auth_dialog_title">Fingeraftryk Login</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Bekræft fingeraftryk for at fortsætte</string>
+    <string name="fingerprint_hint">Rør sensor</string>
+    <string name="fingerprint_not_recognized">Fingeraftryk ikke genkendt. Prøv igen.</string>
+    <string name="fingerprint_success">Fingeraftryk godkendt</string>
+    <string name="new_fingerprint_enrolled_description">Et nyt fingeraftryk blev tilføjet til denne enhed så din adgangskode er krævet.</string>
+    <string name="secure_lock_screen_required">Sikring af skærmlås krævet!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-de/fpauth-strings.xml b/platforms/android/app/src/main/res/values-de/fpauth-strings.xml
new file mode 100644
index 0000000..d5b6bd2
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-de/fpauth-strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<resources>
+    <string name="fingerprint_cancel">Abbrechen</string>
+    <string name="fingerprint_use_backup">Passwort</string>
+    <string name="fingerprint_auth_dialog_title">Authentifizierung</string>
+    <string name="fingerprint_ok">OK</string>
+    <string name="fingerprint_description">Fingerabdruck bestätigen</string>
+    <string name="fingerprint_hint">Fingerabdrucksensor</string>
+    <string name="fingerprint_not_recognized">Fingerabdruck nicht erkannt. Versuchen Sie es erneut</string>
+    <string name="fingerprint_success">Authentifiziert</string>
+    <string name="new_fingerprint_enrolled_description">Ein neuer Fingerabdruck wurde gespeichert. Bitte geben Sie ihr Passwort ein.</string>
+    <string name="secure_lock_screen_required">Passwortgeschützter Sperrbildschirm benötigt</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-el/fpauth-strings.xml b/platforms/android/app/src/main/res/values-el/fpauth-strings.xml
new file mode 100644
index 0000000..1dcfcdb
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-el/fpauth-strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="fingerprint_cancel">Ακύρωση</string>
+    <string name="fingerprint_use_backup">Χρήση αρχείου</string>
+    <string name="fingerprint_auth_dialog_title">Ελεγχος αποτυπώματος</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Επιβεβαίωση αποτυπώματος</string>
+    <string name="fingerprint_hint">Αιθηστήρας αφής</string>
+    <string name="fingerprint_not_recognized">Σφάλμα. Προσπαθήστε ξανά</string>
+    <string name="fingerprint_success">Σωστό αποτύπωμα</string>
+    <string name="new_fingerprint_enrolled_description">Νεο αποτύπωμα προστέθηκε , απαιτείται ο κωδικός σας.</string>
+    <string name="secure_lock_screen_required">Απαιτείται κλειδωμα οθόνης</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-es/fpauth-strings.xml b/platforms/android/app/src/main/res/values-es/fpauth-strings.xml
new file mode 100644
index 0000000..25bdbb2
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-es/fpauth-strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<resources>
+    <string name="fingerprint_cancel">Cancelar</string>
+    <string name="fingerprint_use_backup">El Respaldo</string>
+    <string name="fingerprint_auth_dialog_title">Autenticación de Huellas Digitales</string>
+    <string name="fingerprint_ok">De Acuerdo</string>
+    <string name="fingerprint_description">Confirmar la huella digital para continuar</string>
+    <string name="fingerprint_hint">Sensor tactil</string>
+    <string name="fingerprint_not_recognized">No se reconoce la huella digital. Inténtalo de nuevo.</string>
+    <string name="fingerprint_success">Reconocido de huella dactilar</string>
+    <string name="new_fingerprint_enrolled_description">Una nueva huella digital fue agregada a este dispositivo, por lo que se requiere la contraseña.</string>
+    <string name="secure_lock_screen_required">¡Requiere pantalla de bloqueo seguro!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-fr/fpauth-strings.xml b/platforms/android/app/src/main/res/values-fr/fpauth-strings.xml
new file mode 100644
index 0000000..4b9d3eb
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-fr/fpauth-strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<resources>
+    <string name="fingerprint_cancel">Annuler</string>
+    <string name="fingerprint_use_backup">Utiliser la sauvegarde</string>
+    <string name="fingerprint_auth_dialog_title">Authentification par empreinte digitale</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Confirmer l\'empreinte pour continuer</string>
+    <string name="fingerprint_hint">Toucher le capteur</string>
+    <string name="fingerprint_not_recognized">Empreinte non reconnue. Essayer à nouveau.</string>
+    <string name="fingerprint_success">Empreinte reconnue</string>
+    <string name="new_fingerprint_enrolled_description">Une nouvelle empreinte digitale a été ajoutée à ce dispositif, de sorte que votre mot de passe est nécessaire.</string>
+    <string name="secure_lock_screen_required">Écran de verrouillage sécurisé nécessaire!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-it/fpauth-strings.xml b/platforms/android/app/src/main/res/values-it/fpauth-strings.xml
new file mode 100644
index 0000000..a226ff8
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-it/fpauth-strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="fingerprint_cancel">Cancella</string>
+    <string name="fingerprint_use_backup">Usa backup</string>
+    <string name="fingerprint_auth_dialog_title">Autenticazione impronta digitale</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Conferma l\'impronta digitale per continuare</string>
+    <string name="fingerprint_hint">Sensore Touch</string>
+    <string name="fingerprint_not_recognized">Impronta digitale non riconosciuta. Riprova.</string>
+    <string name="fingerprint_success">Impronta digitale riconosciuta</string>
+    <string name="new_fingerprint_enrolled_description">Una nuova impronta è stata aggiunta a questo dispositivo, quindi è necessaria la tua password</string>
+    <string name="secure_lock_screen_required">Blocco schermo richiesto!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-nl/fpauth-strings.xml b/platforms/android/app/src/main/res/values-nl/fpauth-strings.xml
new file mode 100644
index 0000000..e44731c
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-nl/fpauth-strings.xml
@@ -0,0 +1,12 @@
+<resources>
+    <string name="fingerprint_cancel">Annuleer</string>
+    <string name="fingerprint_use_backup">Back-up gebruiken</string>
+    <string name="fingerprint_auth_dialog_title">Authenticatie met vingerafdruk</string>
+    <string name="fingerprint_ok">OK</string>
+    <string name="fingerprint_description">Vingerafdruk bevestigen om verder te gaan</string>
+    <string name="fingerprint_hint">Aanraaksensor</string>
+    <string name="fingerprint_not_recognized">Vingerafdruk niet herkend.Opnieuw proberen.</string>
+    <string name="fingerprint_success">Vingerafdruk herkend</string>
+    <string name="new_fingerprint_enrolled_description">Er werd een nieuwe vingerafdruk aan dit apparaat toegevoegd, waardoor uw wachtwoord is vereist.</string>
+    <string name="secure_lock_screen_required">Beveiligd vergrendelingsscherm vereist!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-pt/fpauth-strings.xml b/platforms/android/app/src/main/res/values-pt/fpauth-strings.xml
new file mode 100644
index 0000000..7c3e581
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-pt/fpauth-strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="fingerprint_cancel">Cancelar</string>
+    <string name="fingerprint_use_backup">Use o backup</string>
+    <string name="fingerprint_auth_dialog_title">Autenticação de impressão digital</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Confirme a impressão digital para continuar</string>
+    <string name="fingerprint_hint">Sensor de toque</string>
+    <string name="fingerprint_not_recognized">impressão digital não reconhecida. Tente novamente.</string>
+    <string name="fingerprint_success">impressão digital reconhecida</string>
+    <string name="new_fingerprint_enrolled_description">Uma nova impressão digital foi adicionada a este dispositivo, é necessário o seu código</string>
+    <string name="secure_lock_screen_required">É necessário um ecrã de bloqueio seguro!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-zh-rTW/fpauth-strings.xml b/platforms/android/app/src/main/res/values-zh-rTW/fpauth-strings.xml
new file mode 100644
index 0000000..c8345a3
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-zh-rTW/fpauth-strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <string name="fingerprint_cancel">取消</string>
+  <string name="fingerprint_use_backup">使用手勢密碼</string>
+  <string name="fingerprint_auth_dialog_title">指紋識別</string>
+  <string name="fingerprint_ok">確認</string><string name="fingerprint_description">指紋識別</string>
+  <string name="fingerprint_hint">請觸摸指紋識別傳感器</string>
+  <string name="fingerprint_not_recognized">指紋無法識別,請再試一次</string>
+  <string name="fingerprint_success">指紋識別成功</string>
+  <string name="new_fingerprint_enrolled_description">添加一個新的指紋,需要設置密碼</string>
+  <string name="secure_lock_screen_required">需要安全鎖屏</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values-zh/fpauth-strings.xml b/platforms/android/app/src/main/res/values-zh/fpauth-strings.xml
new file mode 100644
index 0000000..54d38b7
--- /dev/null
+++ b/platforms/android/app/src/main/res/values-zh/fpauth-strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <string name="fingerprint_cancel">取消</string>
+  <string name="fingerprint_use_backup">使用手势密码</string>
+  <string name="fingerprint_auth_dialog_title">指纹识别</string>
+  <string name="fingerprint_ok">确认</string><string name="fingerprint_description">指纹识别</string>
+  <string name="fingerprint_hint">请触摸指纹识传感器</string>
+  <string name="fingerprint_not_recognized">指纹无法识别,请再试一次</string>
+  <string name="fingerprint_success">指纹识别成功</string>
+  <string name="new_fingerprint_enrolled_description">添加一个新的指纹,需要设置密码</string>
+  <string name="secure_lock_screen_required">需要安全锁屏</string>
+</resources>
\ No newline at end of file
diff --git a/platforms/android/app/src/main/res/values/fpauth-colors.xml b/platforms/android/app/src/main/res/values/fpauth-colors.xml
new file mode 100644
index 0000000..a24f3c8
--- /dev/null
+++ b/platforms/android/app/src/main/res/values/fpauth-colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<resources>
+    <color name="warning_color">#f4511e</color>
+    <color name="hint_color">#42000000</color>
+    <color name="success_color">#009688</color>
+</resources>
diff --git a/platforms/android/app/src/main/res/values/fpauth-strings.xml b/platforms/android/app/src/main/res/values/fpauth-strings.xml
new file mode 100644
index 0000000..00cc755
--- /dev/null
+++ b/platforms/android/app/src/main/res/values/fpauth-strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<resources>
+    <string name="fingerprint_cancel">Cancel</string>
+    <string name="fingerprint_use_backup">Use backup</string>
+    <string name="fingerprint_auth_dialog_title">Fingerprint Authentication</string>
+    <string name="fingerprint_ok">Ok</string>
+    <string name="fingerprint_description">Confirm fingerprint to continue</string>
+    <string name="fingerprint_hint">Touch sensor</string>
+    <string name="fingerprint_not_recognized">Fingerprint not recognized. Try again.</string>
+    <string name="fingerprint_success">Fingerprint recognized</string>
+    <string name="new_fingerprint_enrolled_description">A new fingerprint was added to this device, so your password is required.</string>
+    <string name="secure_lock_screen_required">Secure lock screen required!</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/values/strings.xml b/platforms/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..d4d339a
--- /dev/null
+++ b/platforms/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='utf-8'?>
+<resources>
+    <string name="app_name">dlapp</string>
+    <string name="launcher_name">@string/app_name</string>
+    <string name="activity_name">@string/launcher_name</string>
+</resources>
diff --git a/platforms/android/app/src/main/res/xml/camera_provider_paths.xml b/platforms/android/app/src/main/res/xml/camera_provider_paths.xml
new file mode 100644
index 0000000..2db87bd
--- /dev/null
+++ b/platforms/android/app/src/main/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/platforms/android/app/src/main/res/xml/config.xml b/platforms/android/app/src/main/res/xml/config.xml
new file mode 100644
index 0000000..3be6168
--- /dev/null
+++ b/platforms/android/app/src/main/res/xml/config.xml
@@ -0,0 +1,69 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <feature name="Fingerprint">
+        <param name="android-package" value="de.niklasmerz.cordova.fingerprint.Fingerprint" />
+    </feature>
+    <feature name="Whitelist">
+        <param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="File">
+        <param name="android-package" value="org.apache.cordova.file.FileUtils" />
+        <param name="onload" value="true" />
+    </feature>
+    <allow-navigation href="cdvfile:*" />
+    <feature name="CordovaHttpPlugin">
+        <param name="android-package" value="com.silkimen.cordovahttp.CordovaHttpPlugin" />
+    </feature>
+    <feature name="StatusBar">
+        <param name="android-package" value="org.apache.cordova.statusbar.StatusBar" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="QRScanner">
+        <param name="android-package" value="com.bitpay.cordova.qrscanner.QRScanner" />
+    </feature>
+    <feature name="Camera">
+        <param name="android-package" value="org.apache.cordova.camera.CameraLauncher" />
+    </feature>
+    <feature name="InAppBrowser">
+        <param name="android-package" value="org.apache.cordova.inappbrowser.InAppBrowser" />
+    </feature>
+    <feature name="Device">
+        <param name="android-package" value="org.apache.cordova.device.Device" />
+    </feature>
+    <feature name="ThemeableBrowser">
+        <param name="android-package" value="com.initialxy.cordova.themeablebrowser.ThemeableBrowser" />
+    </feature>
+    <name>dlapp</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <allow-intent href="http://*/*" />
+    <allow-intent href="https://*/*" />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*" />
+    <allow-intent href="geo:*" />
+    <allow-navigation href="http://*/*" />
+    <allow-navigation href="https://*/*" />
+    <allow-navigation href="data:*" />
+    <access origin="http://ip*" />
+    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+        <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+    </edit-config>
+    <allow-intent href="market:*" />
+    <preference name="loglevel" value="DEBUG" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="SplashScreenDelay" value="0" />
+    <preference name="ErrorUrl" value="error.html" />
+    <preference name="Orientation" value="portrait" />
+    <preference name="UseSwiftLanguageVersion" value="4.0" />
+    <preference name="DisallowOverscroll" value="true" />
+    <preference name="UIWebViewBounce" value="false" />
+    <preference name="BackupWebStorage" value="local" />
+</widget>
diff --git a/platforms/android/build.gradle b/platforms/android/build.gradle
new file mode 100644
index 0000000..bea8a74
--- /dev/null
+++ b/platforms/android/build.gradle
@@ -0,0 +1,52 @@
+/* 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.
+*/
+
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+
+        classpath 'com.android.tools.build:gradle:3.3.0'
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    //This replaces project.properties w.r.t. build settings
+    project.ext {
+      defaultBuildToolsVersion="28.0.3" //String
+      defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4
+      defaultTargetSdkVersion=28 //Integer - We ALWAYS target the latest by default
+      defaultCompileSdkVersion=28 //Integer - We ALWAYS compile with the latest by default
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle b/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle
new file mode 100644
index 0000000..df682e7
--- /dev/null
+++ b/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle
@@ -0,0 +1,12 @@
+repositories {
+    jcenter()
+}
+
+dependencies {
+    compile 'com.journeyapps:zxing-android-embedded:3.3.0'
+    compile 'com.android.support:appcompat-v7:23.1.0'
+}
+
+android {
+    buildToolsVersion '23.0.2' // Older versions may give compile errors
+}
\ No newline at end of file
diff --git a/platforms/android/cordova/Api.js b/platforms/android/cordova/Api.js
new file mode 100644
index 0000000..be6b76b
--- /dev/null
+++ b/platforms/android/cordova/Api.js
@@ -0,0 +1,370 @@
+/**
+    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.
+*/
+
+var path = require('path');
+var Q = require('q');
+
+var AndroidProject = require('./lib/AndroidProject');
+var PluginManager = require('cordova-common').PluginManager;
+
+var CordovaLogger = require('cordova-common').CordovaLogger;
+var selfEvents = require('cordova-common').events;
+
+var PLATFORM = 'android';
+
+function setupEvents (externalEventEmitter) {
+    if (externalEventEmitter) {
+        // This will make the platform internal events visible outside
+        selfEvents.forwardEventsTo(externalEventEmitter);
+        return externalEventEmitter;
+    }
+
+    // There is no logger if external emitter is not present,
+    // so attach a console logger
+    CordovaLogger.get().subscribe(selfEvents);
+    return selfEvents;
+}
+
+/**
+ * Class, that acts as abstraction over particular platform. Encapsulates the
+ *   platform's properties and methods.
+ *
+ * Platform that implements own PlatformApi instance _should implement all
+ *   prototype methods_ of this class to be fully compatible with cordova-lib.
+ *
+ * The PlatformApi instance also should define the following field:
+ *
+ * * platform: String that defines a platform name.
+ */
+function Api (platform, platformRootDir, events) {
+    this.platform = PLATFORM;
+    this.root = path.resolve(__dirname, '..');
+
+    setupEvents(events);
+
+    const appMain = path.join(this.root, 'app', 'src', 'main');
+    const appRes = path.join(appMain, 'res');
+
+    this.locations = {
+        root: this.root,
+        www: path.join(appMain, 'assets', 'www'),
+        res: appRes,
+        platformWww: path.join(this.root, 'platform_www'),
+        configXml: path.join(appRes, 'xml', 'config.xml'),
+        defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'),
+        strings: path.join(appRes, 'values', 'strings.xml'),
+        manifest: path.join(appMain, 'AndroidManifest.xml'),
+        build: path.join(this.root, 'build'),
+        javaSrc: path.join(appMain, 'java'),
+        // NOTE: Due to platformApi spec we need to return relative paths here
+        cordovaJs: 'bin/templates/project/assets/www/cordova.js',
+        cordovaJsSrc: 'cordova-js-src'
+    };
+}
+
+/**
+ * Installs platform to specified directory and creates a platform project.
+ *
+ * @param  {String}  destination Destination directory, where insatll platform to
+ * @param  {ConfigParser}  [config] ConfgiParser instance, used to retrieve
+ *   project creation options, such as package id and project name.
+ * @param  {Object}  [options]  An options object. The most common options are:
+ * @param  {String}  [options.customTemplate]  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  [options.link]  Flag that indicates that platform's
+ *   sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ *   logging purposes. If no EventEmitter provided, all events will be logged to
+ *   console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+Api.createPlatform = function (destination, config, options, events) {
+    events = setupEvents(events);
+    var result;
+    try {
+        result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
+            var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+            return new PlatformApi(PLATFORM, destination, events);
+        });
+    } catch (e) {
+        events.emit('error', 'createPlatform is not callable from the android project API.');
+        throw (e);
+    }
+    return result;
+};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param  {String}  destination Destination directory, where platform installed
+ * @param  {Object}  [options]  An options object. The most common options are:
+ * @param  {String}  [options.customTemplate]  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  [options.link]  Flag that indicates that platform's
+ *   sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ *   logging purposes. If no EventEmitter provided, all events will be logged to
+ *   console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+Api.updatePlatform = function (destination, options, events) {
+    events = setupEvents(events);
+    var result;
+    try {
+        result = require('../../lib/create').update(destination, options, events).then(function (destination) {
+            var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+            return new PlatformApi('android', destination, events);
+        });
+    } catch (e) {
+        events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
+        throw (e);
+    }
+    return result;
+};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return  {CordovaPlatform}  A structure that contains the description of
+ *   platform's file structure and other properties of platform.
+ */
+Api.prototype.getPlatformInfo = function () {
+    var result = {};
+    result.locations = this.locations;
+    result.root = this.root;
+    result.name = this.platform;
+    result.version = require('./version');
+    result.projectConfig = this._config;
+
+    return result;
+};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ *   configuration. This method is required for CLI workflow and will be called
+ *   each time before build, so the changes, made to app configuration and www
+ *   code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to platform
+ *   (contains project's www location and ConfigParser instance for project's
+ *   config).
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.prepare = function (cordovaProject, prepareOptions) {
+    return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions);
+};
+
+/**
+ * Installs a new plugin into platform. This method only copies non-www files
+ *   (sources, libs, etc.) to platform. It also doesn't resolves the
+ *   dependencies of plugin. Both of handling of www files, such as assets and
+ *   js-files and resolving dependencies are the responsibility of caller.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  installOptions  An options object. Possible options below:
+ * @param  {Boolean}  installOptions.link: Flag that specifies that plugin
+ *   sources will be symlinked to app's directory instead of copying (if
+ *   possible).
+ * @param  {Object}  installOptions.variables  An object that represents
+ *   variables that will be used to install plugin. See more details on plugin
+ *   variables in documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.addPlugin = function (plugin, installOptions) {
+    var project = AndroidProject.getProjectFile(this.root);
+    var self = this;
+
+    installOptions = installOptions || {};
+    installOptions.variables = installOptions.variables || {};
+    // Add PACKAGE_NAME variable into vars
+    if (!installOptions.variables.PACKAGE_NAME) {
+        installOptions.variables.PACKAGE_NAME = project.getPackageName();
+    }
+
+    return Q().then(function () {
+        return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
+    }).then(function () {
+        if (plugin.getFrameworks(this.platform).length === 0) return;
+        selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
+        // This should pick the correct builder, not just get gradle
+        require('./lib/builders/builders').getBuilder().prepBuildFiles();
+    }.bind(this))
+        // CB-11022 Return truthy value to prevent running prepare after
+        .thenResolve(true);
+};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ *   id, caller shoud take care of managing/storing PluginInfo instances for
+ *   future uninstalls.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+    var project = AndroidProject.getProjectFile(this.root);
+
+    if (uninstallOptions && uninstallOptions.usePlatformWww === true) {
+        uninstallOptions.usePlatformWww = false;
+    }
+
+    return PluginManager.get(this.platform, this.locations, project)
+        .removePlugin(plugin, uninstallOptions)
+        .then(function () {
+            if (plugin.getFrameworks(this.platform).length === 0) return;
+
+            selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
+            require('./lib/builders/builders').getBuilder().prepBuildFiles();
+        }.bind(this))
+        // CB-11022 Return truthy value to prevent running prepare after
+        .thenResolve(true);
+};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param  {Object}  buildOptions  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return {Promise<Object[]>} A promise either fulfilled with an array of build
+ *   artifacts (application packages) if package was built successfully,
+ *   or rejected with CordovaError. The resultant build artifact objects is not
+ *   strictly typed and may conatin arbitrary set of fields as in sample below.
+ *
+ *     {
+ *         architecture: 'x86',
+ *         buildType: 'debug',
+ *         path: '/path/to/build',
+ *         type: 'app'
+ *     }
+ *
+ * The return value in most cases will contain only one item but in some cases
+ *   there could be multiple items in output array, e.g. when multiple
+ *   arhcitectures is specified.
+ */
+Api.prototype.build = function (buildOptions) {
+    var self = this;
+
+    return require('./lib/check_reqs').run().then(function () {
+        return require('./lib/build').run.call(self, buildOptions);
+    }).then(function (buildResults) {
+        // Cast build result to array of build artifacts
+        return buildResults.apkPaths.map(function (apkPath) {
+            return {
+                buildType: buildResults.buildType,
+                buildMethod: buildResults.buildMethod,
+                path: apkPath,
+                type: 'apk'
+            };
+        });
+    });
+};
+
+/**
+ * Builds an application package for current platform and runs it on
+ *   specified/default device. If no 'device'/'emulator'/'target' options are
+ *   specified, then tries to run app on default device if connected, otherwise
+ *   runs the app on emulator.
+ *
+ * @param   {Object}  runOptions  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ *   successfully, or rejected with CordovaError.
+ */
+Api.prototype.run = function (runOptions) {
+    var self = this;
+    return require('./lib/check_reqs').run().then(function () {
+        return require('./lib/run').run.call(self, runOptions);
+    });
+};
+
+/**
+ * Cleans out the build artifacts from platform's directory, and also
+ * cleans out the platform www directory if called without options specified.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError.
+ */
+Api.prototype.clean = function (cleanOptions) {
+    var self = this;
+    // This will lint, checking for null won't
+    if (typeof cleanOptions === 'undefined') {
+        cleanOptions = {};
+    }
+
+    return require('./lib/check_reqs').run().then(function () {
+        return require('./lib/build').runClean.call(self, cleanOptions);
+    }).then(function () {
+        return require('./lib/prepare').clean.call(self, cleanOptions);
+    });
+};
+
+/**
+ * Performs a requirements check for current platform. Each platform defines its
+ *   own set of requirements, which should be resolved before platform can be
+ *   built successfully.
+ *
+ * @return  {Promise<Requirement[]>}  Promise, resolved with set of Requirement
+ *   objects for current platform.
+ */
+Api.prototype.requirements = function () {
+    return require('./lib/check_reqs').check_all();
+};
+
+module.exports = Api;
diff --git a/platforms/android/cordova/android_sdk_version b/platforms/android/cordova/android_sdk_version
new file mode 100755
index 0000000..c4082f1
--- /dev/null
+++ b/platforms/android/cordova/android_sdk_version
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var android_sdk = require('./lib/android_sdk');
+
+android_sdk.print_newest_available_sdk_target().done(null, function (err) {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/platforms/android/cordova/android_sdk_version.bat b/platforms/android/cordova/android_sdk_version.bat
new file mode 100644
index 0000000..a6bc104
--- /dev/null
+++ b/platforms/android/cordova/android_sdk_version.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0android_sdk_version"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'android_sdk_version' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/android/cordova/build b/platforms/android/cordova/build
new file mode 100755
index 0000000..d703547
--- /dev/null
+++ b/platforms/android/cordova/build
@@ -0,0 +1,51 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var args = process.argv;
+var Api = require('./Api');
+var nopt = require('nopt');
+var path = require('path');
+
+// Support basic help commands
+if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(args[2]) >= 0) {
+    require('./lib/build').help();
+}
+
+// Do some basic argument parsing
+var buildOpts = nopt({
+    'verbose': Boolean,
+    'silent': Boolean,
+    'debug': Boolean,
+    'release': Boolean,
+    'nobuild': Boolean,
+    'buildConfig': path
+}, { 'd': '--verbose' });
+
+// Make buildOptions compatible with PlatformApi build method spec
+buildOpts.argv = buildOpts.argv.original;
+
+require('./loggingHelper').adjustLoggerLevel(buildOpts);
+
+new Api().build(buildOpts)
+    .catch(function (err) {
+        console.error(err.stack);
+        process.exit(2);
+    });
diff --git a/platforms/android/cordova/build.bat b/platforms/android/cordova/build.bat
new file mode 100644
index 0000000..46e966a
--- /dev/null
+++ b/platforms/android/cordova/build.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0build"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/check_reqs b/platforms/android/cordova/check_reqs
new file mode 100755
index 0000000..e0c1c44
--- /dev/null
+++ b/platforms/android/cordova/check_reqs
@@ -0,0 +1,32 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var check_reqs = require('./lib/check_reqs');
+
+check_reqs.run().done(
+    function success () {
+        console.log('Looks like your environment fully supports cordova-android development!');
+    },
+    function fail (err) {
+        console.log(err);
+        process.exit(2);
+    }
+);
diff --git a/platforms/android/cordova/check_reqs.bat b/platforms/android/cordova/check_reqs.bat
new file mode 100644
index 0000000..846dfa1
--- /dev/null
+++ b/platforms/android/cordova/check_reqs.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0check_reqs"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/android/cordova/clean b/platforms/android/cordova/clean
new file mode 100755
index 0000000..9db5847
--- /dev/null
+++ b/platforms/android/cordova/clean
@@ -0,0 +1,51 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var Api = require('./Api');
+var path = require('path');
+var nopt = require('nopt');
+
+// Support basic help commands
+if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
+    console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
+    console.log('Cleans the project directory.');
+    process.exit(0);
+}
+
+// Do some basic argument parsing
+var opts = nopt({
+    'verbose': Boolean,
+    'silent': Boolean
+}, { 'd': '--verbose' });
+
+// Make buildOptions compatible with PlatformApi clean method spec
+opts.argv = opts.argv.original;
+
+// Skip cleaning prepared files when not invoking via cordova CLI.
+opts.noPrepare = true;
+
+require('./loggingHelper').adjustLoggerLevel(opts);
+
+new Api().clean(opts)
+    .catch(function (err) {
+        console.error(err.stack);
+        process.exit(2);
+    });
diff --git a/platforms/android/cordova/clean.bat b/platforms/android/cordova/clean.bat
new file mode 100644
index 0000000..445ef6e
--- /dev/null
+++ b/platforms/android/cordova/clean.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0clean"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/defaults.xml b/platforms/android/cordova/defaults.xml
new file mode 100644
index 0000000..5286ab9
--- /dev/null
+++ b/platforms/android/cordova/defaults.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<widget xmlns     = "http://www.w3.org/ns/widgets"
+        id        = "io.cordova.helloCordova"
+        version   = "2.0.0">
+
+    <!-- Preferences for Android -->
+    <preference name="loglevel" value="DEBUG" />
+</widget>
diff --git a/platforms/android/cordova/lib/Adb.js b/platforms/android/cordova/lib/Adb.js
new file mode 100644
index 0000000..b6ad8f1
--- /dev/null
+++ b/platforms/android/cordova/lib/Adb.js
@@ -0,0 +1,101 @@
+/**
+    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.
+*/
+
+var Q = require('q');
+var os = require('os');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+var Adb = {};
+
+function isDevice (line) {
+    return line.match(/\w+\tdevice/) && !line.match(/emulator/);
+}
+
+function isEmulator (line) {
+    return line.match(/device/) && line.match(/emulator/);
+}
+
+/**
+ * Lists available/connected devices and emulators
+ *
+ * @param   {Object}   opts            Various options
+ * @param   {Boolean}  opts.emulators  Specifies whether this method returns
+ *   emulators only
+ *
+ * @return  {Promise<String[]>}        list of available/connected
+ *   devices/emulators
+ */
+Adb.devices = function (opts) {
+    return spawn('adb', ['devices'], { cwd: os.tmpdir() }).then(function (output) {
+        return output.split('\n').filter(function (line) {
+            // Filter out either real devices or emulators, depending on options
+            return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
+        }).map(function (line) {
+            return line.replace(/\tdevice/, '').replace('\r', '');
+        });
+    });
+};
+
+Adb.install = function (target, packagePath, opts) {
+    events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
+    var args = ['-s', target, 'install'];
+    if (opts && opts.replace) args.push('-r');
+    return spawn('adb', args.concat(packagePath), { cwd: os.tmpdir() }).then(function (output) {
+        // 'adb install' seems to always returns no error, even if installation fails
+        // so we catching output to detect installation failure
+        if (output.match(/Failure/)) {
+            if (output.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
+                output += '\n\n' + 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
+                    ' or sign and deploy the unsigned apk manually using Android tools.';
+            } else if (output.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
+                output += '\n\n' + 'You\'re trying to install apk with a lower versionCode that is already installed.' +
+                    '\nEither uninstall an app or increment the versionCode.';
+            }
+
+            return Q.reject(new CordovaError('Failed to install apk to device: ' + output));
+        }
+    });
+};
+
+Adb.uninstall = function (target, packageId) {
+    events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...');
+    return spawn('adb', ['-s', target, 'uninstall', packageId], { cwd: os.tmpdir() });
+};
+
+Adb.shell = function (target, shellCommand) {
+    events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
+    var args = ['-s', target, 'shell'];
+    shellCommand = shellCommand.split(/\s+/);
+    return spawn('adb', args.concat(shellCommand), { cwd: os.tmpdir() }).catch(function (output) {
+        return Q.reject(new CordovaError('Failed to execute shell command "' +
+            shellCommand + '"" on device: ' + output));
+    });
+};
+
+Adb.start = function (target, activityName) {
+    events.emit('verbose', 'Starting application "' + activityName + '" on target ' + target + '...');
+    return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch(function (output) {
+        return Q.reject(new CordovaError('Failed to start application "' +
+            activityName + '"" on device: ' + output));
+    });
+};
+
+module.exports = Adb;
diff --git a/platforms/android/cordova/lib/AndroidManifest.js b/platforms/android/cordova/lib/AndroidManifest.js
new file mode 100644
index 0000000..4fe1c2b
--- /dev/null
+++ b/platforms/android/cordova/lib/AndroidManifest.js
@@ -0,0 +1,156 @@
+/**
+    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.
+*/
+
+var fs = require('fs');
+var et = require('elementtree');
+var xml = require('cordova-common').xmlHelpers;
+
+var DEFAULT_ORIENTATION = 'default';
+
+/** Wraps an AndroidManifest file */
+function AndroidManifest (path) {
+    this.path = path;
+    this.doc = xml.parseElementtreeSync(path);
+    if (this.doc.getroot().tag !== 'manifest') {
+        throw new Error('AndroidManifest at ' + path + ' has incorrect root node name (expected "manifest")');
+    }
+}
+
+AndroidManifest.prototype.getVersionName = function () {
+    return this.doc.getroot().attrib['android:versionName'];
+};
+
+AndroidManifest.prototype.setVersionName = function (versionName) {
+    this.doc.getroot().attrib['android:versionName'] = versionName;
+    return this;
+};
+
+AndroidManifest.prototype.getVersionCode = function () {
+    return this.doc.getroot().attrib['android:versionCode'];
+};
+
+AndroidManifest.prototype.setVersionCode = function (versionCode) {
+    this.doc.getroot().attrib['android:versionCode'] = versionCode;
+    return this;
+};
+
+AndroidManifest.prototype.getPackageId = function () {
+    return this.doc.getroot().attrib['package'];
+};
+
+AndroidManifest.prototype.setPackageId = function (pkgId) {
+    this.doc.getroot().attrib['package'] = pkgId;
+    return this;
+};
+
+AndroidManifest.prototype.getActivity = function () {
+    var activity = this.doc.getroot().find('./application/activity');
+    return {
+        getName: function () {
+            return activity.attrib['android:name'];
+        },
+        setName: function (name) {
+            if (!name) {
+                delete activity.attrib['android:name'];
+            } else {
+                activity.attrib['android:name'] = name;
+            }
+            return this;
+        },
+        getOrientation: function () {
+            return activity.attrib['android:screenOrientation'];
+        },
+        setOrientation: function (orientation) {
+            if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) {
+                delete activity.attrib['android:screenOrientation'];
+            } else {
+                activity.attrib['android:screenOrientation'] = orientation;
+            }
+            return this;
+        },
+        getLaunchMode: function () {
+            return activity.attrib['android:launchMode'];
+        },
+        setLaunchMode: function (launchMode) {
+            if (!launchMode) {
+                delete activity.attrib['android:launchMode'];
+            } else {
+                activity.attrib['android:launchMode'] = launchMode;
+            }
+            return this;
+        }
+    };
+};
+
+['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion'].forEach(function (sdkPrefName) {
+    // Copy variable reference to avoid closure issues
+    var prefName = sdkPrefName;
+
+    AndroidManifest.prototype['get' + capitalize(prefName)] = function () {
+        var usesSdk = this.doc.getroot().find('./uses-sdk');
+        return usesSdk && usesSdk.attrib['android:' + prefName];
+    };
+
+    AndroidManifest.prototype['set' + capitalize(prefName)] = function (prefValue) {
+        var usesSdk = this.doc.getroot().find('./uses-sdk');
+
+        if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
+            usesSdk = new et.Element('uses-sdk');
+            this.doc.getroot().append(usesSdk);
+        }
+
+        if (prefValue) {
+            usesSdk.attrib['android:' + prefName] = prefValue;
+        }
+
+        return this;
+    };
+});
+
+AndroidManifest.prototype.getDebuggable = function () {
+    return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
+};
+
+AndroidManifest.prototype.setDebuggable = function (value) {
+    var application = this.doc.getroot().find('./application');
+    if (value) {
+        application.attrib['android:debuggable'] = 'true';
+    } else {
+        // The default value is "false", so we can remove attribute at all.
+        delete application.attrib['android:debuggable'];
+    }
+    return this;
+};
+
+/**
+ * Writes manifest to disk syncronously. If filename is specified, then manifest
+ *   will be written to that file
+ *
+ * @param   {String}  [destPath]  File to write manifest to. If omitted,
+ *   manifest will be written to file it has been read from.
+ */
+AndroidManifest.prototype.write = function (destPath) {
+    fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8');
+};
+
+module.exports = AndroidManifest;
+
+function capitalize (str) {
+    return str.charAt(0).toUpperCase() + str.slice(1);
+}
diff --git a/platforms/android/cordova/lib/AndroidProject.js b/platforms/android/cordova/lib/AndroidProject.js
new file mode 100644
index 0000000..3c2586a
--- /dev/null
+++ b/platforms/android/cordova/lib/AndroidProject.js
@@ -0,0 +1,202 @@
+/**
+    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.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var properties_parser = require('properties-parser');
+var AndroidManifest = require('./AndroidManifest');
+var pluginHandlers = require('./pluginHandlers');
+
+var projectFileCache = {};
+
+function addToPropertyList (projectProperties, key, value) {
+    var i = 1;
+    while (projectProperties.get(key + '.' + i)) { i++; }
+
+    projectProperties.set(key + '.' + i, value);
+    projectProperties.dirty = true;
+}
+
+function removeFromPropertyList (projectProperties, key, value) {
+    var i = 1;
+    var currentValue;
+    while ((currentValue = projectProperties.get(key + '.' + i))) {
+        if (currentValue === value) {
+            while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
+                projectProperties.set(key + '.' + i, currentValue);
+                i++;
+            }
+            projectProperties.set(key + '.' + i);
+            break;
+        }
+        i++;
+    }
+    projectProperties.dirty = true;
+}
+
+function getRelativeLibraryPath (parentDir, subDir) {
+    var libraryPath = path.relative(parentDir, subDir);
+    return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
+}
+
+function AndroidProject (projectDir) {
+    this._propertiesEditors = {};
+    this._subProjectDirs = {};
+    this._dirty = false;
+    this.projectDir = projectDir;
+    this.platformWww = path.join(this.projectDir, 'platform_www');
+    this.www = path.join(this.projectDir, 'app/src/main/assets/www');
+}
+
+AndroidProject.getProjectFile = function (projectDir) {
+    if (!projectFileCache[projectDir]) {
+        projectFileCache[projectDir] = new AndroidProject(projectDir);
+    }
+
+    return projectFileCache[projectDir];
+};
+
+AndroidProject.purgeCache = function (projectDir) {
+    if (projectDir) {
+        delete projectFileCache[projectDir];
+    } else {
+        projectFileCache = {};
+    }
+};
+
+/**
+ * Reads the package name out of the Android Manifest file
+ *
+ * @param   {String}  projectDir  The absolute path to the directory containing the project
+ *
+ * @return  {String}              The name of the package
+ */
+AndroidProject.prototype.getPackageName = function () {
+    var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
+    return new AndroidManifest(manifestPath).getPackageId();
+};
+
+AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, src) {
+    // All custom subprojects are prefixed with the last portion of the package id.
+    // This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
+    var packageName = this.getPackageName();
+    var lastDotIndex = packageName.lastIndexOf('.');
+    var prefix = packageName.substring(lastDotIndex + 1);
+    var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
+    return subRelativeDir;
+};
+
+AndroidProject.prototype.addSubProject = function (parentDir, subDir) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var subProjectFile = path.resolve(subDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    // TODO: Setting the target needs to happen only for pre-3.7.0 projects
+    if (fs.existsSync(subProjectFile)) {
+        var subProperties = this._getPropertiesFile(subProjectFile);
+        subProperties.set('target', parentProperties.get('target'));
+        subProperties.dirty = true;
+        this._subProjectDirs[subDir] = true;
+    }
+    addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
+
+    this._dirty = true;
+};
+
+AndroidProject.prototype.removeSubProject = function (parentDir, subDir) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
+    delete this._subProjectDirs[subDir];
+    this._dirty = true;
+};
+
+AndroidProject.prototype.addGradleReference = function (parentDir, subDir) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
+    this._dirty = true;
+};
+
+AndroidProject.prototype.removeGradleReference = function (parentDir, subDir) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
+    this._dirty = true;
+};
+
+AndroidProject.prototype.addSystemLibrary = function (parentDir, value) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    addToPropertyList(parentProperties, 'cordova.system.library', value);
+    this._dirty = true;
+};
+
+AndroidProject.prototype.removeSystemLibrary = function (parentDir, value) {
+    var parentProjectFile = path.resolve(parentDir, 'project.properties');
+    var parentProperties = this._getPropertiesFile(parentProjectFile);
+    removeFromPropertyList(parentProperties, 'cordova.system.library', value);
+    this._dirty = true;
+};
+
+AndroidProject.prototype.write = function () {
+    if (!this._dirty) {
+        return;
+    }
+    this._dirty = false;
+
+    for (var filename in this._propertiesEditors) {
+        var editor = this._propertiesEditors[filename];
+        if (editor.dirty) {
+            fs.writeFileSync(filename, editor.toString());
+            editor.dirty = false;
+        }
+    }
+};
+
+AndroidProject.prototype._getPropertiesFile = function (filename) {
+    if (!this._propertiesEditors[filename]) {
+        if (fs.existsSync(filename)) {
+            this._propertiesEditors[filename] = properties_parser.createEditor(filename);
+        } else {
+            this._propertiesEditors[filename] = properties_parser.createEditor();
+        }
+    }
+
+    return this._propertiesEditors[filename];
+};
+
+AndroidProject.prototype.getInstaller = function (type) {
+    return pluginHandlers.getInstaller(type);
+};
+
+AndroidProject.prototype.getUninstaller = function (type) {
+    return pluginHandlers.getUninstaller(type);
+};
+
+/*
+ * This checks if an Android project is clean or has old build artifacts
+ */
+
+AndroidProject.prototype.isClean = function () {
+    var build_path = path.join(this.projectDir, 'build');
+    // If the build directory doesn't exist, it's clean
+    return !(fs.existsSync(build_path));
+};
+
+module.exports = AndroidProject;
diff --git a/platforms/android/cordova/lib/android_sdk.js b/platforms/android/cordova/lib/android_sdk.js
new file mode 100755
index 0000000..1c0ab20
--- /dev/null
+++ b/platforms/android/cordova/lib/android_sdk.js
@@ -0,0 +1,101 @@
+/*
+       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.
+*/
+
+var superspawn = require('cordova-common').superspawn;
+
+var suffix_number_regex = /(\d+)$/;
+// Used for sorting Android targets, example strings to sort:
+//   android-19
+//   android-L
+//   Google Inc.:Google APIs:20
+//   Google Inc.:Glass Development Kit Preview:20
+// The idea is to sort based on largest "suffix" number - meaning the bigger
+// the number at the end, the more recent the target, the closer to the
+// start of the array.
+function sort_by_largest_numerical_suffix (a, b) {
+    var suffix_a = a.match(suffix_number_regex);
+    var suffix_b = b.match(suffix_number_regex);
+    if (suffix_a && suffix_b) {
+        // If the two targets being compared have suffixes, return less than
+        // zero, or greater than zero, based on which suffix is larger.
+        return (parseInt(suffix_a[1]) > parseInt(suffix_b[1]) ? -1 : 1);
+    } else {
+        // If no suffix numbers were detected, leave the order as-is between
+        // elements a and b.
+        return 0;
+    }
+}
+
+module.exports.print_newest_available_sdk_target = function () {
+    return module.exports.list_targets().then(function (targets) {
+        targets.sort(sort_by_largest_numerical_suffix);
+        console.log(targets[0]);
+    });
+};
+
+module.exports.version_string_to_api_level = {
+    '4.0': 14,
+    '4.0.3': 15,
+    '4.1': 16,
+    '4.2': 17,
+    '4.3': 18,
+    '4.4': 19,
+    '4.4W': 20,
+    '5.0': 21,
+    '5.1': 22,
+    '6.0': 23,
+    '7.0': 24,
+    '7.1.1': 25,
+    '8.0': 26
+};
+
+function parse_targets (output) {
+    var target_out = output.split('\n');
+    var targets = [];
+    for (var i = target_out.length - 1; i >= 0; i--) {
+        if (target_out[i].match(/id:/)) { // if "id:" is in the line...
+            targets.push(target_out[i].match(/"(.+)"/)[1]); // .. match whatever is in quotes.
+        }
+    }
+    return targets;
+}
+
+module.exports.list_targets_with_android = function () {
+    return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
+};
+
+module.exports.list_targets_with_avdmanager = function () {
+    return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
+};
+
+module.exports.list_targets = function () {
+    return module.exports.list_targets_with_avdmanager().catch(function (err) {
+        // If there's an error, like avdmanager could not be found, we can try
+        // as a last resort, to run `android`, in case this is a super old
+        // SDK installation.
+        if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
+            return module.exports.list_targets_with_android();
+        } else throw err;
+    }).then(function (targets) {
+        if (targets.length === 0) {
+            return Promise.reject(new Error('No android targets (SDKs) installed!'));
+        }
+        return targets;
+    });
+};
diff --git a/platforms/android/cordova/lib/build.js b/platforms/android/cordova/lib/build.js
new file mode 100644
index 0000000..2f0ba69
--- /dev/null
+++ b/platforms/android/cordova/lib/build.js
@@ -0,0 +1,278 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var Q = require('q');
+var path = require('path');
+var fs = require('fs');
+var nopt = require('nopt');
+
+var Adb = require('./Adb');
+
+var builders = require('./builders/builders');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+module.exports.parseBuildOptions = parseOpts;
+function parseOpts (options, resolvedTarget, projectRoot) {
+    options = options || {};
+    options.argv = nopt({
+        prepenv: Boolean,
+        versionCode: String,
+        minSdkVersion: String,
+        gradleArg: [String, Array],
+        keystore: path,
+        alias: String,
+        storePassword: String,
+        password: String,
+        keystoreType: String
+    }, {}, options.argv, 0);
+
+    // Android Studio Build method is the default
+    var ret = {
+        buildType: options.release ? 'release' : 'debug',
+        prepEnv: options.argv.prepenv,
+        arch: resolvedTarget && resolvedTarget.arch,
+        extraArgs: []
+    };
+
+    if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
+    if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
+    if (options.argv.gradleArg) {
+        ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
+    }
+
+    var packageArgs = {};
+
+    if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
+
+    ['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (flagName) {
+        if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
+    });
+
+    var buildConfig = options.buildConfig;
+
+    // If some values are not specified as command line arguments - use build config to supplement them.
+    // Command line arguemnts have precedence over build config.
+    if (buildConfig) {
+        if (!fs.existsSync(buildConfig)) {
+            throw new Error('Specified build config file does not exist: ' + buildConfig);
+        }
+        events.emit('log', 'Reading build config file: ' + path.resolve(buildConfig));
+        var buildjson = fs.readFileSync(buildConfig, 'utf8');
+        var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
+        if (config.android && config.android[ret.buildType]) {
+            var androidInfo = config.android[ret.buildType];
+            if (androidInfo.keystore && !packageArgs.keystore) {
+                if (androidInfo.keystore.substr(0, 1) === '~') {
+                    androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1);
+                }
+                packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
+                events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore);
+            }
+
+            ['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (key) {
+                packageArgs[key] = packageArgs[key] || androidInfo[key];
+            });
+        }
+    }
+
+    if (packageArgs.keystore && packageArgs.alias) {
+        ret.packageInfo = new PackageInfo(packageArgs.keystore, packageArgs.alias, packageArgs.storePassword,
+            packageArgs.password, packageArgs.keystoreType);
+    }
+
+    if (!ret.packageInfo) {
+        if (Object.keys(packageArgs).length > 0) {
+            events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
+        }
+    }
+
+    return ret;
+}
+
+/*
+ * Builds the project with the specifed options
+ * Returns a promise.
+ */
+module.exports.runClean = function (options) {
+    var opts = parseOpts(options, null, this.root);
+    var builder = builders.getBuilder();
+
+    return builder.prepEnv(opts).then(function () {
+        return builder.clean(opts);
+    });
+};
+
+/**
+ * Builds the project with the specifed options.
+ *
+ * @param   {BuildOptions}  options      A set of options. See PlatformApi.build
+ *   method documentation for reference.
+ * @param   {Object}  optResolvedTarget  A deployment target. Used to pass
+ *   target architecture from upstream 'run' call. TODO: remove this option in
+ *   favor of setting buildOptions.archs field.
+ *
+ * @return  {Promise<Object>}            Promise, resolved with built packages
+ *   information.
+ */
+module.exports.run = function (options, optResolvedTarget) {
+    var opts = parseOpts(options, optResolvedTarget, this.root);
+    var builder = builders.getBuilder();
+
+    return builder.prepEnv(opts).then(function () {
+        if (opts.prepEnv) {
+            events.emit('verbose', 'Build file successfully prepared.');
+            return;
+        }
+        return builder.build(opts).then(function () {
+            var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
+            events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
+            return {
+                apkPaths: apkPaths,
+                buildType: opts.buildType
+            };
+        });
+    });
+};
+
+/*
+ * Detects the architecture of a device/emulator
+ * Returns "arm" or "x86".
+ */
+module.exports.detectArchitecture = function (target) {
+    function helper () {
+        return Adb.shell(target, 'cat /proc/cpuinfo').then(function (output) {
+            return /intel/i.exec(output) ? 'x86' : 'arm';
+        });
+    }
+    // It sometimes happens (at least on OS X), that this command will hang forever.
+    // To fix it, either unplug & replug device, or restart adb server.
+    return helper().timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.')).then(null, function (err) {
+        if (/timed out/.exec('' + err)) {
+            // adb kill-server doesn't seem to do the trick.
+            // Could probably find a x-platform version of killall, but I'm not actually
+            // sure that this scenario even happens on non-OSX machines.
+            events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
+            return spawn('killall', ['adb']).then(function () {
+                return helper().then(null, function () {
+                    // The double kill is sadly often necessary, at least on mac.
+                    events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
+                    return spawn('killall', ['adb']).then(function () {
+                        return helper().then(null, function () {
+                            return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
+                        });
+                    });
+                });
+            }, function () {
+                // For non-killall OS's.
+                return Q.reject(err);
+            });
+        }
+        throw err;
+    });
+};
+
+module.exports.findBestApkForArchitecture = function (buildResults, arch) {
+    var paths = buildResults.apkPaths.filter(function (p) {
+        var apkName = path.basename(p);
+        if (buildResults.buildType === 'debug') {
+            return /-debug/.exec(apkName);
+        }
+        return !/-debug/.exec(apkName);
+    });
+    var archPattern = new RegExp('-' + arch);
+    var hasArchPattern = /-x86|-arm/;
+    for (var i = 0; i < paths.length; ++i) {
+        var apkName = path.basename(paths[i]);
+        if (hasArchPattern.exec(apkName)) {
+            if (archPattern.exec(apkName)) {
+                return paths[i];
+            }
+        } else {
+            return paths[i];
+        }
+    }
+    throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
+};
+
+function PackageInfo (keystore, alias, storePassword, password, keystoreType) {
+    this.keystore = {
+        'name': 'key.store',
+        'value': keystore
+    };
+    this.alias = {
+        'name': 'key.alias',
+        'value': alias
+    };
+    if (storePassword) {
+        this.storePassword = {
+            'name': 'key.store.password',
+            'value': storePassword
+        };
+    }
+    if (password) {
+        this.password = {
+            'name': 'key.alias.password',
+            'value': password
+        };
+    }
+    if (keystoreType) {
+        this.keystoreType = {
+            'name': 'key.store.type',
+            'value': keystoreType
+        };
+    }
+}
+
+PackageInfo.prototype = {
+    toProperties: function () {
+        var self = this;
+        var result = '';
+        Object.keys(self).forEach(function (key) {
+            result += self[key].name;
+            result += '=';
+            result += self[key].value.replace(/\\/g, '\\\\');
+            result += '\n';
+        });
+        return result;
+    }
+};
+
+module.exports.help = function () {
+    console.log('Usage: ' + path.relative(process.cwd(), path.join('../build')) + ' [flags] [Signed APK flags]');
+    console.log('Flags:');
+    console.log('    \'--debug\': will build project in debug mode (default)');
+    console.log('    \'--release\': will build project for release');
+    console.log('    \'--nobuild\': will skip build process (useful when using run command)');
+    console.log('    \'--prepenv\': don\'t build, but copy in build scripts where necessary');
+    console.log('    \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs.');
+    console.log('    \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs.');
+    console.log('    \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
+    console.log('');
+    console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');
+    console.log('    \'--keystore=<path to keystore>\': Key store used to build a signed archive. (Required)');
+    console.log('    \'--alias=\': Alias for the key store. (Required)');
+    console.log('    \'--storePassword=\': Password for the key store. (Optional - prompted)');
+    console.log('    \'--password=\': Password for the key. (Optional - prompted)');
+    console.log('    \'--keystoreType\': Type of the keystore. (Optional)');
+    process.exit(0);
+};
diff --git a/platforms/android/cordova/lib/builders/ProjectBuilder.js b/platforms/android/cordova/lib/builders/ProjectBuilder.js
new file mode 100644
index 0000000..94e26a0
--- /dev/null
+++ b/platforms/android/cordova/lib/builders/ProjectBuilder.js
@@ -0,0 +1,370 @@
+/*
+       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.
+*/
+/* eslint no-self-assign: 0 */
+/* eslint no-unused-vars: 0 */
+
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var spawn = require('cordova-common').superspawn.spawn;
+var events = require('cordova-common').events;
+var CordovaError = require('cordova-common').CordovaError;
+var check_reqs = require('../check_reqs');
+
+const MARKER = 'YOUR CHANGES WILL BE ERASED!';
+const SIGNING_PROPERTIES = '-signing.properties';
+const TEMPLATE =
+    '# This file is automatically generated.\n' +
+    '# Do not modify this file -- ' + MARKER + '\n';
+
+class ProjectBuilder {
+    constructor (rootDirectory) {
+        this.root = rootDirectory || path.resolve(__dirname, '../../..');
+        this.binDir = path.join(this.root, 'app', 'build', 'outputs', 'apk');
+    }
+
+    getArgs (cmd, opts) {
+        if (cmd === 'release') {
+            cmd = 'cdvBuildRelease';
+        } else if (cmd === 'debug') {
+            cmd = 'cdvBuildDebug';
+        }
+
+        let args = [cmd, '-b', path.join(this.root, 'build.gradle')];
+
+        if (opts.arch) {
+            args.push('-PcdvBuildArch=' + opts.arch);
+        }
+
+        args.push.apply(args, opts.extraArgs);
+
+        return args;
+    }
+
+    /*
+    * This returns a promise
+    */
+    runGradleWrapper (gradle_cmd) {
+        var gradlePath = path.join(this.root, 'gradlew');
+        var wrapperGradle = path.join(this.root, 'wrapper.gradle');
+        if (fs.existsSync(gradlePath)) {
+            // Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
+        } else {
+            return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], { stdio: 'inherit' });
+        }
+    }
+
+    readProjectProperties () {
+        function findAllUniq (data, r) {
+            var s = {};
+            var m;
+            while ((m = r.exec(data))) {
+                s[m[1]] = 1;
+            }
+            return Object.keys(s);
+        }
+
+        var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
+        return {
+            libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
+            gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
+            systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
+        };
+    }
+
+    extractRealProjectNameFromManifest () {
+        var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
+        var manifestData = fs.readFileSync(manifestPath, 'utf8');
+        var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
+        if (!m) {
+            throw new CordovaError('Could not find package name in ' + manifestPath);
+        }
+
+        var packageName = m[1];
+        var lastDotIndex = packageName.lastIndexOf('.');
+        return packageName.substring(lastDotIndex + 1);
+    }
+
+    // Makes the project buildable, minus the gradle wrapper.
+    prepBuildFiles () {
+        // Update the version of build.gradle in each dependent library.
+        var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
+        var propertiesObj = this.readProjectProperties();
+        var subProjects = propertiesObj.libs;
+
+        // Check and copy the gradle file into the subproject
+        // Called by the loop before this function def
+
+        var checkAndCopy = function (subProject, root) {
+            var subProjectGradle = path.join(root, subProject, 'build.gradle');
+            // This is the future-proof way of checking if a file exists
+            // This must be synchronous to satisfy a Travis test
+            try {
+                fs.accessSync(subProjectGradle, fs.F_OK);
+            } catch (e) {
+                shell.cp('-f', pluginBuildGradle, subProjectGradle);
+            }
+        };
+
+        for (var i = 0; i < subProjects.length; ++i) {
+            if (subProjects[i] !== 'CordovaLib') {
+                checkAndCopy(subProjects[i], this.root);
+            }
+        }
+        var name = this.extractRealProjectNameFromManifest();
+        // Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
+        var settingsGradlePaths = subProjects.map(function (p) {
+            var realDir = p.replace(/[/\\]/g, ':');
+            var libName = realDir.replace(name + '-', '');
+            var str = 'include ":' + libName + '"\n';
+            if (realDir.indexOf(name + '-') !== -1) {
+                str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n';
+            }
+            return str;
+        });
+
+        fs.writeFileSync(path.join(this.root, 'settings.gradle'),
+            '// GENERATED FILE - DO NOT EDIT\n' +
+            'include ":"\n' + settingsGradlePaths.join(''));
+
+        // Update dependencies within build.gradle.
+        var buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
+        var depsList = '';
+        var root = this.root;
+        var insertExclude = function (p) {
+            var gradlePath = path.join(root, p, 'build.gradle');
+            var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
+            if (projectGradleFile.indexOf('CordovaLib') !== -1) {
+                depsList += '{\n        exclude module:("CordovaLib")\n    }\n';
+            } else {
+                depsList += '\n';
+            }
+        };
+        subProjects.forEach(function (p) {
+            events.emit('log', 'Subproject Path: ' + p);
+            var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
+            if (libName !== 'app') {
+                depsList += '    implementation(project(path: ":' + libName + '"))';
+                insertExclude(p);
+            }
+        });
+        // For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
+        var SYSTEM_LIBRARY_MAPPINGS = [
+            [/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
+            [/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
+        ];
+
+        propertiesObj.systemLibs.forEach(function (p) {
+            var mavenRef;
+            // It's already in gradle form if it has two ':'s
+            if (/:.*:/.exec(p)) {
+                mavenRef = p;
+            } else {
+                for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
+                    var pair = SYSTEM_LIBRARY_MAPPINGS[i];
+                    if (pair[0].exec(p)) {
+                        mavenRef = p.replace(pair[0], pair[1]);
+                        break;
+                    }
+                }
+                if (!mavenRef) {
+                    throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
+                }
+            }
+            depsList += '    implementation "' + mavenRef + '"\n';
+        });
+
+        buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + '    $2');
+        var includeList = '';
+
+        propertiesObj.gradleIncludes.forEach(function (includePath) {
+            includeList += 'apply from: "../' + includePath + '"\n';
+        });
+        buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
+        // This needs to be stored in the app gradle, not the root grade
+        fs.writeFileSync(path.join(this.root, 'app', 'build.gradle'), buildGradle);
+    }
+
+    prepEnv (opts) {
+        var self = this;
+        return check_reqs.check_gradle()
+            .then(function (gradlePath) {
+                return self.runGradleWrapper(gradlePath);
+            }).then(function () {
+                return self.prepBuildFiles();
+            }).then(function () {
+                // If the gradle distribution URL is set, make sure it points to version we want.
+                // If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
+                // For some reason, using ^ and $ don't work.  This does the job, though.
+                var distributionUrlRegex = /distributionUrl.*zip/;
+                var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-4.10.3-all.zip';
+                var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
+                shell.chmod('u+w', gradleWrapperPropertiesPath);
+                shell.sed('-i', distributionUrlRegex, 'distributionUrl=' + distributionUrl, gradleWrapperPropertiesPath);
+
+                var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
+                var propertiesFilePath = path.join(self.root, propertiesFile);
+                if (opts.packageInfo) {
+                    fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
+                } else if (isAutoGenerated(propertiesFilePath)) {
+                    shell.rm('-f', propertiesFilePath);
+                }
+            });
+    }
+
+    /*
+    * Builds the project with gradle.
+    * Returns a promise.
+    */
+    build (opts) {
+        var wrapper = path.join(this.root, 'gradlew');
+        var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
+
+        return spawn(wrapper, args, { stdio: 'pipe' })
+            .progress(function (stdio) {
+                if (stdio.stderr) {
+                    /*
+                    * Workaround for the issue with Java printing some unwanted information to
+                    * stderr instead of stdout.
+                    * This function suppresses 'Picked up _JAVA_OPTIONS' message from being
+                    * printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
+                    * explanation.
+                    */
+                    var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
+                    if (suppressThisLine) {
+                        return;
+                    }
+                    process.stderr.write(stdio.stderr);
+                } else {
+                    process.stdout.write(stdio.stdout);
+                }
+            }).catch(function (error) {
+                if (error.toString().indexOf('failed to find target with hash string') >= 0) {
+                    return check_reqs.check_android_target(error).then(function () {
+                        // If due to some odd reason - check_android_target succeeds
+                        // we should still fail here.
+                        return Q.reject(error);
+                    });
+                }
+                return Q.reject(error);
+            });
+    }
+
+    clean (opts) {
+        var builder = this;
+        var wrapper = path.join(this.root, 'gradlew');
+        var args = builder.getArgs('clean', opts);
+        return Q().then(function () {
+            return spawn(wrapper, args, { stdio: 'inherit' });
+        })
+            .then(function () {
+                shell.rm('-rf', path.join(builder.root, 'out'));
+
+                ['debug', 'release'].forEach(function (config) {
+                    var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
+                    if (isAutoGenerated(propertiesFilePath)) {
+                        shell.rm('-f', propertiesFilePath);
+                    }
+                });
+            });
+    }
+
+    findOutputApks (build_type, arch) {
+        return findOutputApksHelper(this.binDir, build_type, arch).sort(apkSorter);
+    }
+
+    fetchBuildResults (build_type, arch) {
+        return {
+            apkPaths: this.findOutputApks(build_type, arch),
+            buildType: build_type
+        };
+    }
+}
+
+module.exports = ProjectBuilder;
+
+function apkSorter (fileA, fileB) {
+    // De-prioritize arch specific builds
+    var archSpecificRE = /-x86|-arm/;
+    if (archSpecificRE.exec(fileA)) {
+        return 1;
+    } else if (archSpecificRE.exec(fileB)) {
+        return -1;
+    }
+
+    // De-prioritize unsigned builds
+    var unsignedRE = /-unsigned/;
+    if (unsignedRE.exec(fileA)) {
+        return 1;
+    } else if (unsignedRE.exec(fileB)) {
+        return -1;
+    }
+
+    var timeDiff = fs.statSync(fileB).mtime - fs.statSync(fileA).mtime;
+    return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
+}
+
+function findOutputApksHelper (dir, build_type, arch) {
+    var shellSilent = shell.config.silent;
+    shell.config.silent = true;
+
+    // list directory recursively
+    var ret = shell.ls('-R', dir).map(function (file) {
+        // ls does not include base directory
+        return path.join(dir, file);
+    }).filter(function (file) {
+        // find all APKs
+        return file.match(/\.apk?$/i);
+    }).filter(function (candidate) {
+        var apkName = path.basename(candidate);
+        // Need to choose between release and debug .apk.
+        if (build_type === 'debug') {
+            return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
+        }
+        if (build_type === 'release') {
+            return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
+        }
+        return true;
+    }).sort(apkSorter);
+
+    shellSilent = shellSilent;
+
+    if (ret.length === 0) {
+        return ret;
+    }
+    // Assume arch-specific build if newest apk has -x86 or -arm.
+    var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
+    // And show only arch-specific ones (or non-arch-specific)
+    ret = ret.filter(function (p) {
+        return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
+    });
+
+    if (archSpecific && ret.length > 1 && arch) {
+        ret = ret.filter(function (p) {
+            return path.basename(p).indexOf('-' + arch) !== -1;
+        });
+    }
+
+    return ret;
+}
+
+function isAutoGenerated (file) {
+    return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
+}
diff --git a/platforms/android/cordova/lib/builders/builders.js b/platforms/android/cordova/lib/builders/builders.js
new file mode 100644
index 0000000..42fc19d
--- /dev/null
+++ b/platforms/android/cordova/lib/builders/builders.js
@@ -0,0 +1,34 @@
+/*
+    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.
+*/
+
+const CordovaError = require('cordova-common').CordovaError;
+
+/**
+ * Helper method that instantiates and returns a builder for specified build type.
+ *
+ * @return {Builder} A builder instance for specified build type.
+ */
+module.exports.getBuilder = function () {
+    try {
+        const Builder = require('./ProjectBuilder');
+        return new Builder();
+    } catch (err) {
+        throw new CordovaError('Failed to instantiate ProjectBuilder builder: ' + err);
+    }
+};
diff --git a/platforms/android/cordova/lib/check_reqs.js b/platforms/android/cordova/lib/check_reqs.js
new file mode 100644
index 0000000..6435e01
--- /dev/null
+++ b/platforms/android/cordova/lib/check_reqs.js
@@ -0,0 +1,436 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var shelljs = require('shelljs');
+var child_process = require('child_process');
+var Q = require('q');
+var path = require('path');
+var fs = require('fs');
+var os = require('os');
+var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
+var PROJECT_ROOT = path.join(__dirname, '..', '..');
+var CordovaError = require('cordova-common').CordovaError;
+var superspawn = require('cordova-common').superspawn;
+var android_sdk = require('./android_sdk');
+
+function forgivingWhichSync (cmd) {
+    try {
+        return fs.realpathSync(shelljs.which(cmd));
+    } catch (e) {
+        return '';
+    }
+}
+
+module.exports.isWindows = function () {
+    return (os.platform() === 'win32');
+};
+
+module.exports.isDarwin = function () {
+    return (os.platform() === 'darwin');
+};
+
+// Get valid target from framework/project.properties if run from this repo
+// Otherwise get target from project.properties file within a generated cordova-android project
+module.exports.get_target = function () {
+    function extractFromFile (filePath) {
+        var target = shelljs.grep(/\btarget=/, filePath);
+        if (!target) {
+            throw new Error('Could not find android target within: ' + filePath);
+        }
+        return target.split('=')[1].trim();
+    }
+    var repo_file = path.join(REPO_ROOT, 'framework', 'project.properties');
+    if (fs.existsSync(repo_file)) {
+        return extractFromFile(repo_file);
+    }
+    var project_file = path.join(PROJECT_ROOT, 'project.properties');
+    if (fs.existsSync(project_file)) {
+        // if no target found, we're probably in a project and project.properties is in PROJECT_ROOT.
+        return extractFromFile(project_file);
+    }
+    throw new Error('Could not find android target in either ' + repo_file + ' nor ' + project_file);
+};
+
+// Returns a promise. Called only by build and clean commands.
+module.exports.check_ant = function () {
+    return superspawn.spawn('ant', ['-version']).then(function (output) {
+        // Parse Ant version from command output
+        return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
+    }).catch(function (err) {
+        if (err) {
+            throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
+        }
+    });
+};
+
+module.exports.get_gradle_wrapper = function () {
+    var androidStudioPath;
+    var i = 0;
+    var foundStudio = false;
+    var program_dir;
+    // OK, This hack only works on Windows, not on Mac OS or Linux.  We will be deleting this eventually!
+    if (module.exports.isWindows()) {
+
+        var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
+        // console.log('result.stdout =' + result.stdout.toString());
+        // console.log('result.stderr =' + result.stderr.toString());
+
+        if (result.stderr.toString().length > 0) {
+            var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
+            if (fs.existsSync(androidPath)) {
+                program_dir = fs.readdirSync(androidPath);
+                while (i < program_dir.length && !foundStudio) {
+                    if (program_dir[i].startsWith('Android Studio')) {
+                        foundStudio = true;
+                        androidStudioPath = path.join(process.env['ProgramFiles'], 'Android', program_dir[i], 'gradle');
+                    } else { ++i; }
+                }
+            }
+        } else {
+            // console.log('got android studio path from registry');
+            // remove the (os independent) new line char at the end of stdout
+            // add gradle to match the above.
+            androidStudioPath = path.join(result.stdout.toString().split('\r\n')[0], 'gradle');
+        }
+    }
+
+    if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
+        var dirs = fs.readdirSync(androidStudioPath);
+        if (dirs[0].split('-')[0] === 'gradle') {
+            return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
+        }
+    } else {
+        // OK, let's try to check for Gradle!
+        return forgivingWhichSync('gradle');
+    }
+};
+
+// Returns a promise. Called only by build and clean commands.
+module.exports.check_gradle = function () {
+    var sdkDir = process.env['ANDROID_HOME'];
+    var d = Q.defer();
+    if (!sdkDir) {
+        return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
+            'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
+    }
+
+    var gradlePath = module.exports.get_gradle_wrapper();
+    if (gradlePath.length !== 0) { d.resolve(gradlePath); } else {
+        d.reject(new CordovaError('Could not find an installed version of Gradle either in Android Studio,\n' +
+                                'or on your system to install the gradle wrapper. Please include gradle \n' +
+                                'in your path, or install Android Studio'));
+    }
+    return d.promise;
+};
+
+// Returns a promise.
+module.exports.check_java = function () {
+    var javacPath = forgivingWhichSync('javac');
+    var hasJavaHome = !!process.env['JAVA_HOME'];
+    return Q().then(function () {
+        if (hasJavaHome) {
+            // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
+            if (!javacPath) {
+                process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
+            }
+        } else {
+            if (javacPath) {
+                // OS X has a command for finding JAVA_HOME.
+                var find_java = '/usr/libexec/java_home';
+                var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
+                if (fs.existsSync(find_java)) {
+                    return superspawn.spawn(find_java).then(function (stdout) {
+                        process.env['JAVA_HOME'] = stdout.trim();
+                    }).catch(function (err) {
+                        if (err) {
+                            throw new CordovaError(default_java_error_msg);
+                        }
+                    });
+                } else {
+                    // See if we can derive it from javac's location.
+                    // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
+                    var maybeJavaHome = path.dirname(path.dirname(javacPath));
+                    if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
+                        process.env['JAVA_HOME'] = maybeJavaHome;
+                    } else {
+                        throw new CordovaError(default_java_error_msg);
+                    }
+                }
+            } else if (module.exports.isWindows()) {
+                // Try to auto-detect java in the default install paths.
+                var oldSilent = shelljs.config.silent;
+                shelljs.config.silent = true;
+                var firstJdkDir =
+                    shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
+                    shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
+                    shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
+                shelljs.config.silent = oldSilent;
+                if (firstJdkDir) {
+                    // shelljs always uses / in paths.
+                    firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
+                    if (!javacPath) {
+                        process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
+                    }
+                    process.env['JAVA_HOME'] = firstJdkDir;
+                }
+            }
+        }
+    }).then(function () {
+        return Q.denodeify(child_process.exec)('javac -version')
+            .then(outputs => {
+                // outputs contains two entries: stdout and stderr
+                // Java <= 8 writes version info to stderr, Java >= 9 to stdout
+                const output = outputs.join('').trim();
+                const match = /javac\s+([\d.]+)/i.exec(output);
+                return match && match[1];
+            }, () => {
+                var msg =
+                'Failed to run "javac -version", make sure that you have a JDK version 8 installed.\n' +
+                'You can get it from the following location:\n' +
+                'https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html';
+                if (process.env['JAVA_HOME']) {
+                    msg += '\n\n';
+                    msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'];
+                }
+                throw new CordovaError(msg);
+            });
+    });
+};
+
+// Returns a promise.
+module.exports.check_android = function () {
+    return Q().then(function () {
+        var androidCmdPath = forgivingWhichSync('android');
+        var adbInPath = forgivingWhichSync('adb');
+        var avdmanagerInPath = forgivingWhichSync('avdmanager');
+        var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
+        function maybeSetAndroidHome (value) {
+            if (!hasAndroidHome && fs.existsSync(value)) {
+                hasAndroidHome = true;
+                process.env['ANDROID_HOME'] = value;
+            }
+        }
+        // First ensure ANDROID_HOME is set
+        // If we have no hints (nothing in PATH), try a few default locations
+        if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) {
+            if (process.env['ANDROID_SDK_ROOT']) {
+                // Quick fix to set ANDROID_HOME according to ANDROID_SDK_ROOT
+                // if ANDROID_HOME is **not** defined and
+                // ANDROID_SDK_ROOT **is** defined
+                // according to environment variables as documented in:
+                // https://developer.android.com/studio/command-line/variables
+                maybeSetAndroidHome(path.join(process.env['ANDROID_SDK_ROOT']));
+            }
+            if (module.exports.isWindows()) {
+                // Android Studio 1.0 installer
+                maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
+                maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
+                // Android Studio pre-1.0 installer
+                maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
+                maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
+                // Stand-alone installer
+                maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
+                maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
+            } else if (module.exports.isDarwin()) {
+                // Android Studio 1.0 installer
+                maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
+                // Android Studio pre-1.0 installer
+                maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
+                // Stand-alone zip file that user might think to put under /Applications
+                maybeSetAndroidHome('/Applications/android-sdk-macosx');
+                maybeSetAndroidHome('/Applications/android-sdk');
+            }
+            if (process.env['HOME']) {
+                // Stand-alone zip file that user might think to put under their home directory
+                maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
+                maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
+            }
+        }
+        if (!hasAndroidHome) {
+            // If we dont have ANDROID_HOME, but we do have some tools on the PATH, try to infer from the tooling PATH.
+            var parentDir, grandParentDir;
+            if (androidCmdPath) {
+                parentDir = path.dirname(androidCmdPath);
+                grandParentDir = path.dirname(parentDir);
+                if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
+                    maybeSetAndroidHome(grandParentDir);
+                } else {
+                    throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
+                        'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
+                        'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools directory.');
+                }
+            }
+            if (adbInPath) {
+                parentDir = path.dirname(adbInPath);
+                grandParentDir = path.dirname(parentDir);
+                if (path.basename(parentDir) === 'platform-tools') {
+                    maybeSetAndroidHome(grandParentDir);
+                } else {
+                    throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
+                        'Detected \'adb\' command at ' + parentDir + ' but no \'platform-tools\' directory found near.\n' +
+                        'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'platform-tools directory.');
+                }
+            }
+            if (avdmanagerInPath) {
+                parentDir = path.dirname(avdmanagerInPath);
+                grandParentDir = path.dirname(parentDir);
+                if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
+                    maybeSetAndroidHome(path.dirname(grandParentDir));
+                } else {
+                    throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
+                        'Detected \'avdmanager\' command at ' + parentDir + ' but no \'tools' + path.sep + 'bin\' directory found near.\n' +
+                        'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools' + path.sep + 'bin directory.');
+                }
+            }
+        }
+        if (!process.env['ANDROID_HOME']) {
+            throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
+                'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
+        }
+        if (!fs.existsSync(process.env['ANDROID_HOME'])) {
+            throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
+                '\nTry update it manually to point to valid SDK directory.');
+        }
+        // Next let's make sure relevant parts of the SDK tooling is in our PATH
+        if (hasAndroidHome && !androidCmdPath) {
+            process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
+        }
+        if (hasAndroidHome && !adbInPath) {
+            process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
+        }
+        if (hasAndroidHome && !avdmanagerInPath) {
+            process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools', 'bin');
+        }
+        return hasAndroidHome;
+    });
+};
+
+// TODO: is this actually needed?
+module.exports.getAbsoluteAndroidCmd = function () {
+    var cmd = forgivingWhichSync('android');
+    if (cmd.length === 0) {
+        cmd = forgivingWhichSync('sdkmanager');
+    }
+    if (module.exports.isWindows()) {
+        return '"' + cmd + '"';
+    }
+    return cmd.replace(/(\s)/g, '\\$1');
+};
+
+module.exports.check_android_target = function (originalError) {
+    // valid_target can look like:
+    //   android-19
+    //   android-L
+    //   Google Inc.:Google APIs:20
+    //   Google Inc.:Glass Development Kit Preview:20
+    var desired_api_level = module.exports.get_target();
+    return android_sdk.list_targets().then(function (targets) {
+        if (targets.indexOf(desired_api_level) >= 0) {
+            return targets;
+        }
+        var androidCmd = module.exports.getAbsoluteAndroidCmd();
+        var msg = 'Please install Android target / API level: "' + desired_api_level + '".\n\n' +
+            'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
+            'You will require:\n' +
+            '1. "SDK Platform" for API level ' + desired_api_level + '\n' +
+            '2. "Android SDK Platform-tools (latest)\n' +
+            '3. "Android SDK Build-tools" (latest)';
+        if (originalError) {
+            msg = originalError + '\n' + msg;
+        }
+        throw new CordovaError(msg);
+    });
+};
+
+// Returns a promise.
+module.exports.run = function () {
+    return Q.all([this.check_java(), this.check_android()]).then(function (values) {
+        console.log('Checking Java JDK and Android SDK versions');
+        console.log('ANDROID_SDK_ROOT=' + process.env['ANDROID_SDK_ROOT'] + ' (recommended setting)');
+        console.log('ANDROID_HOME=' + process.env['ANDROID_HOME'] + ' (DEPRECATED)');
+
+        if (!String(values[0]).startsWith('1.8.')) {
+            throw new CordovaError(
+                'Requirements check failed for JDK 8 (\'1.8.*\')! Detected version: ' + values[0] + '\n' +
+                'Check your ANDROID_SDK_ROOT / JAVA_HOME / PATH environment variables.'
+            );
+        }
+
+        if (!values[1]) {
+            throw new CordovaError('Requirements check failed for Android SDK! Android SDK was not detected.');
+        }
+    });
+};
+
+/**
+ * Object thar represents one of requirements for current platform.
+ * @param {String} id         The unique identifier for this requirements.
+ * @param {String} name       The name of requirements. Human-readable field.
+ * @param {String} version    The version of requirement installed. In some cases could be an array of strings
+ *                            (for example, check_android_target returns an array of android targets installed)
+ * @param {Boolean} installed Indicates whether the requirement is installed or not
+ */
+var Requirement = function (id, name, version, installed) {
+    this.id = id;
+    this.name = name;
+    this.installed = installed || false;
+    this.metadata = {
+        version: version
+    };
+};
+
+/**
+ * Methods that runs all checks one by one and returns a result of checks
+ * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
+ *
+ * @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
+ */
+module.exports.check_all = function () {
+
+    var requirements = [
+        new Requirement('java', 'Java JDK'),
+        new Requirement('androidSdk', 'Android SDK'),
+        new Requirement('androidTarget', 'Android target'),
+        new Requirement('gradle', 'Gradle')
+    ];
+
+    var checkFns = [
+        this.check_java,
+        this.check_android,
+        this.check_android_target,
+        this.check_gradle
+    ];
+
+    // Then execute requirement checks one-by-one
+    return checkFns.reduce(function (promise, checkFn, idx) {
+        // Update each requirement with results
+        var requirement = requirements[idx];
+        return promise.then(checkFn).then(function (version) {
+            requirement.installed = true;
+            requirement.metadata.version = version;
+        }, function (err) {
+            requirement.metadata.reason = err instanceof Error ? err.message : err;
+        });
+    }, Q()).then(function () {
+        // When chain is completed, return requirements array to upstream API
+        return requirements;
+    });
+};
diff --git a/platforms/android/cordova/lib/config/GradlePropertiesParser.js b/platforms/android/cordova/lib/config/GradlePropertiesParser.js
new file mode 100644
index 0000000..b45c0a6
--- /dev/null
+++ b/platforms/android/cordova/lib/config/GradlePropertiesParser.js
@@ -0,0 +1,104 @@
+/**
+    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.
+*/
+
+let fs = require('fs');
+let path = require('path');
+let propertiesParser = require('properties-parser');
+let events = require('cordova-common').events;
+
+class GradlePropertiesParser {
+    /**
+    * Loads and Edits Gradle Properties File.
+    *
+    * @param {String} platformDir is the path of the Android platform directory
+    */
+    constructor (platformDir) {
+        this._defaults = {
+            // 10 seconds -> 6 seconds
+            'org.gradle.daemon': 'true',
+
+            // to allow dex in process
+            'org.gradle.jvmargs': '-Xmx2048m',
+
+            // allow NDK to be used - required by Gradle 1.5 plugin
+            'android.useDeprecatedNdk': 'true'
+
+            // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
+            // 'org.gradle.parallel': 'true'
+        };
+
+        this.gradleFilePath = path.join(platformDir, 'gradle.properties');
+    }
+
+    configure (userConfigs) {
+        events.emit('verbose', '[Gradle Properties] Preparing Configuration');
+
+        this._initializeEditor();
+
+        events.emit('verbose', '[Gradle Properties] Appending default configuration properties');
+        this._configureProperties(this._defaults);
+
+        events.emit('verbose', '[Gradle Properties] Appending custom configuration properties');
+        this._configureProperties(userConfigs);
+
+        this._save();
+    }
+
+    /**
+     * Initialize the properties editor for parsing, setting, etc.
+     */
+    _initializeEditor () {
+        // Touch empty gradle.properties file if missing.
+        if (!fs.existsSync(this.gradleFilePath)) {
+            events.emit('verbose', '[Gradle Properties] File missing, creating file with Cordova defaults.');
+            fs.writeFileSync(this.gradleFilePath, '', 'utf-8');
+        }
+
+        // Create an editor for parsing, getting, and setting configurations.
+        this.gradleFile = propertiesParser.createEditor(this.gradleFilePath);
+    }
+
+    /**
+     * Validate that defaults or user configuration properties are set and
+     * set the missing items.
+     */
+    _configureProperties (properties) {
+        // Iterate though the properties and set only if missing.
+        Object.keys(properties).forEach(key => {
+            let value = this.gradleFile.get(key);
+
+            if (!value) {
+                events.emit('verbose', `[Gradle Properties] Appending configuration item: ${key}=${properties[key]}`);
+                this.gradleFile.set(key, properties[key]);
+            } else if (value !== properties[key]) {
+                events.emit('info', `[Gradle Properties] Detected Gradle property "${key}" with the value of "${value}", Cordova's recommended value is "${properties[key]}"`);
+            }
+        });
+    }
+
+    /**
+     * Saves any changes that has been made to the properties file.
+     */
+    _save () {
+        events.emit('verbose', '[Gradle Properties] Updating and Saving File');
+        this.gradleFile.save();
+    }
+}
+
+module.exports = GradlePropertiesParser;
diff --git a/platforms/android/cordova/lib/device.js b/platforms/android/cordova/lib/device.js
new file mode 100644
index 0000000..1559e9b
--- /dev/null
+++ b/platforms/android/cordova/lib/device.js
@@ -0,0 +1,111 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var build = require('./build');
+var path = require('path');
+var Adb = require('./Adb');
+var AndroidManifest = require('./AndroidManifest');
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+var events = require('cordova-common').events;
+
+/**
+ * Returns a promise for the list of the device ID's found
+ * @param lookHarder When true, try restarting adb if no devices are found.
+ */
+module.exports.list = function (lookHarder) {
+    return Adb.devices().then(function (list) {
+        if (list.length === 0 && lookHarder) {
+            // adb kill-server doesn't seem to do the trick.
+            // Could probably find a x-platform version of killall, but I'm not actually
+            // sure that this scenario even happens on non-OSX machines.
+            return spawn('killall', ['adb']).then(function () {
+                events.emit('verbose', 'Restarting adb to see if more devices are detected.');
+                return Adb.devices();
+            }, function () {
+                // For non-killall OS's.
+                return list;
+            });
+        }
+        return list;
+    });
+};
+
+module.exports.resolveTarget = function (target) {
+    return this.list(true).then(function (device_list) {
+        if (!device_list || !device_list.length) {
+            return Promise.reject(new CordovaError('Failed to deploy to device, no devices found.'));
+        }
+        // default device
+        target = target || device_list[0];
+
+        if (device_list.indexOf(target) < 0) {
+            return Promise.reject(new CordovaError('ERROR: Unable to find target \'' + target + '\'.'));
+        }
+
+        return build.detectArchitecture(target).then(function (arch) {
+            return { target: target, arch: arch, isEmulator: false };
+        });
+    });
+};
+
+/*
+ * Installs a previously built application on the device
+ * and launches it.
+ * Returns a promise.
+ */
+module.exports.install = function (target, buildResults) {
+    return Promise.resolve().then(function () {
+        if (target && typeof target === 'object') {
+            return target;
+        }
+        return module.exports.resolveTarget(target);
+    }).then(function (resolvedTarget) {
+        var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
+        var manifest = new AndroidManifest(path.join(__dirname, '../../app/src/main/AndroidManifest.xml'));
+        var pkgName = manifest.getPackageId();
+        var launchName = pkgName + '/.' + manifest.getActivity().getName();
+        events.emit('log', 'Using apk: ' + apk_path);
+        events.emit('log', 'Package name: ' + pkgName);
+
+        return Adb.install(resolvedTarget.target, apk_path, { replace: true }).catch(function (error) {
+            // CB-9557 CB-10157 only uninstall and reinstall app if the one that
+            // is already installed on device was signed w/different certificate
+            if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
+
+            events.emit('warn', 'Uninstalling app from device and reinstalling it again because the ' +
+                'installed app already signed with different key');
+
+            // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
+            // or the app doesn't installed at all, so no error catching needed.
+            return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
+                return Adb.install(resolvedTarget.target, apk_path, { replace: true });
+            });
+        }).then(function () {
+            // unlock screen
+            return Adb.shell(resolvedTarget.target, 'input keyevent 82');
+        }).then(function () {
+            return Adb.start(resolvedTarget.target, launchName);
+        }).then(function () {
+            events.emit('log', 'LAUNCH SUCCESS');
+        });
+    });
+};
diff --git a/platforms/android/cordova/lib/emulator.js b/platforms/android/cordova/lib/emulator.js
new file mode 100644
index 0000000..fcdc170
--- /dev/null
+++ b/platforms/android/cordova/lib/emulator.js
@@ -0,0 +1,530 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var android_versions = require('android-versions');
+var retry = require('./retry');
+var build = require('./build');
+var path = require('path');
+var Adb = require('./Adb');
+var AndroidManifest = require('./AndroidManifest');
+var events = require('cordova-common').events;
+var superspawn = require('cordova-common').superspawn;
+var CordovaError = require('cordova-common').CordovaError;
+var shelljs = require('shelljs');
+var android_sdk = require('./android_sdk');
+var check_reqs = require('./check_reqs');
+
+var os = require('os');
+var fs = require('fs');
+var child_process = require('child_process');
+
+// constants
+var ONE_SECOND = 1000; // in milliseconds
+var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
+var INSTALL_COMMAND_TIMEOUT = 5 * ONE_MINUTE; // in milliseconds
+var NUM_INSTALL_RETRIES = 3;
+var CHECK_BOOTED_INTERVAL = 3 * ONE_SECOND; // in milliseconds
+var EXEC_KILL_SIGNAL = 'SIGKILL';
+
+function forgivingWhichSync (cmd) {
+    try {
+        return fs.realpathSync(shelljs.which(cmd));
+    } catch (e) {
+        return '';
+    }
+}
+
+module.exports.list_images_using_avdmanager = function () {
+    return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
+        var response = output.split('\n');
+        var emulator_list = [];
+        for (var i = 1; i < response.length; i++) {
+            // To return more detailed information use img_obj
+            var img_obj = {};
+            if (response[i].match(/Name:\s/)) {
+                img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
+                if (response[i + 1].match(/Device:\s/)) {
+                    i++;
+                    img_obj['device'] = response[i].split('Device: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/Path:\s/)) {
+                    i++;
+                    img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/Target:\s/)) {
+                    i++;
+                    if (response[i + 1].match(/ABI:\s/)) {
+                        img_obj['abi'] = response[i + 1].split('ABI: ')[1].replace('\r', '');
+                    }
+                    // This next conditional just aims to match the old output of `android list avd`
+                    // We do so so that we don't have to change the logic when parsing for the
+                    // best emulator target to spawn (see below in `best_image`)
+                    // This allows us to transitionally support both `android` and `avdmanager` binaries,
+                    // depending on what SDK version the user has
+                    if (response[i + 1].match(/Based\son:\s/)) {
+                        img_obj['target'] = response[i + 1].split('Based on:')[1];
+                        if (img_obj['target'].match(/Tag\/ABI:\s/)) {
+                            img_obj['target'] = img_obj['target'].split('Tag/ABI:')[0].replace('\r', '').trim();
+                            if (img_obj['target'].indexOf('(') > -1) {
+                                img_obj['target'] = img_obj['target'].substr(0, img_obj['target'].indexOf('(') - 1).trim();
+                            }
+                        }
+                        var version_string = img_obj['target'].replace(/Android\s+/, '');
+
+                        var api_level = android_sdk.version_string_to_api_level[version_string];
+                        if (api_level) {
+                            img_obj['target'] += ' (API level ' + api_level + ')';
+                        }
+                    }
+                }
+                if (response[i + 1].match(/Skin:\s/)) {
+                    i++;
+                    img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
+                }
+
+                emulator_list.push(img_obj);
+            }
+            /* To just return a list of names use this
+            if (response[i].match(/Name:\s/)) {
+                emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
+            } */
+
+        }
+        return emulator_list;
+    });
+};
+
+module.exports.list_images_using_android = function () {
+    return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
+        var response = output.split('\n');
+        var emulator_list = [];
+        for (var i = 1; i < response.length; i++) {
+            // To return more detailed information use img_obj
+            var img_obj = {};
+            if (response[i].match(/Name:\s/)) {
+                img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
+                if (response[i + 1].match(/Device:\s/)) {
+                    i++;
+                    img_obj['device'] = response[i].split('Device: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/Path:\s/)) {
+                    i++;
+                    img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/\(API\slevel\s/) || (response[i + 2] && response[i + 2].match(/\(API\slevel\s/))) {
+                    i++;
+                    var secondLine = response[i + 1].match(/\(API\slevel\s/) ? response[i + 1] : '';
+                    img_obj['target'] = (response[i] + secondLine).split('Target: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/ABI:\s/)) {
+                    i++;
+                    img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
+                }
+                if (response[i + 1].match(/Skin:\s/)) {
+                    i++;
+                    img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
+                }
+
+                emulator_list.push(img_obj);
+            }
+            /* To just return a list of names use this
+            if (response[i].match(/Name:\s/)) {
+                emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
+            } */
+
+        }
+        return emulator_list;
+    });
+};
+
+/**
+ * Returns a Promise for a list of emulator images in the form of objects
+ * {
+       name   : <emulator_name>,
+       device : <device>,
+       path   : <path_to_emulator_image>,
+       target : <api_target>,
+       abi    : <cpu>,
+       skin   : <skin>
+   }
+ */
+module.exports.list_images = function () {
+    return Promise.resolve().then(function () {
+        if (forgivingWhichSync('avdmanager')) {
+            return module.exports.list_images_using_avdmanager();
+        } else if (forgivingWhichSync('android')) {
+            return module.exports.list_images_using_android();
+        } else {
+            return Promise.reject(new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?'));
+        }
+    }).then(function (avds) {
+        // In case we're missing the Android OS version string from the target description, add it.
+        return avds.map(function (avd) {
+            if (avd.target && avd.target.indexOf('Android API') > -1 && avd.target.indexOf('API level') < 0) {
+                var api_level = avd.target.match(/\d+/);
+                if (api_level) {
+                    var level = android_versions.get(api_level);
+                    if (level) {
+                        avd.target = 'Android ' + level.semver + ' (API level ' + api_level + ')';
+                    }
+                }
+            }
+            return avd;
+        });
+    });
+};
+
+/**
+ * Will return the closest avd to the projects target
+ * or undefined if no avds exist.
+ * Returns a promise.
+ */
+module.exports.best_image = function () {
+    return this.list_images().then(function (images) {
+        // Just return undefined if there is no images
+        if (images.length === 0) return;
+
+        var closest = 9999;
+        var best = images[0];
+        var project_target = parseInt(check_reqs.get_target().replace('android-', ''));
+        for (var i in images) {
+            var target = images[i].target;
+            if (target && target.indexOf('API level') > -1) {
+                var num = parseInt(target.split('(API level ')[1].replace(')', ''));
+                if (num === project_target) {
+                    return images[i];
+                } else if (project_target - num < closest && project_target > num) {
+                    closest = project_target - num;
+                    best = images[i];
+                }
+            }
+        }
+        return best;
+    });
+};
+
+// Returns a promise.
+module.exports.list_started = function () {
+    return Adb.devices({ emulators: true });
+};
+
+// Returns a promise.
+// TODO: we should remove this, there's a more robust method under android_sdk.js
+module.exports.list_targets = function () {
+    return superspawn.spawn('android', ['list', 'targets'], { cwd: os.tmpdir() }).then(function (output) {
+        var target_out = output.split('\n');
+        var targets = [];
+        for (var i = target_out.length; i >= 0; i--) {
+            if (target_out[i].match(/id:/)) {
+                targets.push(targets[i].split(' ')[1]);
+            }
+        }
+        return targets;
+    });
+};
+
+/*
+ * Gets unused port for android emulator, between 5554 and 5584
+ * Returns a promise.
+ */
+module.exports.get_available_port = function () {
+    var self = this;
+
+    return self.list_started().then(function (emulators) {
+        for (var p = 5584; p >= 5554; p -= 2) {
+            if (emulators.indexOf('emulator-' + p) === -1) {
+                events.emit('verbose', 'Found available port: ' + p);
+                return p;
+            }
+        }
+        throw new CordovaError('Could not find an available avd port');
+    });
+};
+
+/*
+ * Starts an emulator with the given ID,
+ * and returns the started ID of that emulator.
+ * If no ID is given it will use the first image available,
+ * if no image is available it will error out (maybe create one?).
+ * If no boot timeout is given or the value is negative it will wait forever for
+ * the emulator to boot
+ *
+ * Returns a promise.
+ */
+module.exports.start = function (emulator_ID, boot_timeout) {
+    var self = this;
+
+    return Promise.resolve().then(function () {
+        if (emulator_ID) return Promise.resolve(emulator_ID);
+
+        return self.best_image().then(function (best) {
+            if (best && best.name) {
+                events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
+                return best.name;
+            }
+
+            var androidCmd = check_reqs.getAbsoluteAndroidCmd();
+            return Promise.reject(new CordovaError('No emulator images (avds) found.\n' +
+                '1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
+                '2. Create an AVD by running: ' + androidCmd + ' avd\n' +
+                'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
+        });
+    }).then(function (emulatorId) {
+        return self.get_available_port().then(function (port) {
+            // Figure out the directory the emulator binary runs in, and set the cwd to that directory.
+            // Workaround for https://code.google.com/p/android/issues/detail?id=235461
+            var emulator_dir = path.dirname(shelljs.which('emulator'));
+            var args = ['-avd', emulatorId, '-port', port];
+            // Don't wait for it to finish, since the emulator will probably keep running for a long time.
+            child_process
+                .spawn('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
+                .unref();
+
+            // wait for emulator to start
+            events.emit('log', 'Waiting for emulator to start...');
+            return self.wait_for_emulator(port);
+        });
+    }).then(function (emulatorId) {
+        if (!emulatorId) { return Promise.reject(new CordovaError('Failed to start emulator')); }
+
+        // wait for emulator to boot up
+        process.stdout.write('Waiting for emulator to boot (this may take a while)...');
+        return self.wait_for_boot(emulatorId, boot_timeout).then(function (success) {
+            if (success) {
+                events.emit('log', 'BOOT COMPLETE');
+                // unlock screen
+                return Adb.shell(emulatorId, 'input keyevent 82').then(function () {
+                    // return the new emulator id for the started emulators
+                    return emulatorId;
+                });
+            } else {
+                // We timed out waiting for the boot to happen
+                return null;
+            }
+        });
+    });
+};
+
+/*
+ * Waits for an emulator to boot on a given port.
+ * Returns this emulator's ID in a promise.
+ */
+module.exports.wait_for_emulator = function (port) {
+    var self = this;
+    return Promise.resolve().then(function () {
+        var emulator_id = 'emulator-' + port;
+        return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
+            if (output.indexOf('1') >= 0) {
+                return emulator_id;
+            }
+            return self.wait_for_emulator(port);
+        }, function (error) {
+            if ((error && error.message &&
+            (error.message.indexOf('not found') > -1)) ||
+            (error.message.indexOf('device offline') > -1) ||
+            (error.message.indexOf('device still connecting') > -1) ||
+            (error.message.indexOf('device still authorizing') > -1)) {
+                // emulator not yet started, continue waiting
+                return self.wait_for_emulator(port);
+            } else {
+                // something unexpected has happened
+                throw error;
+            }
+        });
+    });
+};
+
+/*
+ * Waits for the core android process of the emulator to start. Returns a
+ * promise that resolves to a boolean indicating success. Not specifying a
+ * time_remaining or passing a negative value will cause it to wait forever
+ */
+module.exports.wait_for_boot = function (emulator_id, time_remaining) {
+    var self = this;
+    return Adb.shell(emulator_id, 'ps').then(function (output) {
+        if (output.match(/android\.process\.acore/)) {
+            return true;
+        } else if (time_remaining === 0) {
+            return false;
+        } else {
+            process.stdout.write('.');
+
+            return new Promise(resolve => {
+                const delay = time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL;
+
+                setTimeout(() => {
+                    const updated_time = time_remaining >= 0 ? Math.max(time_remaining - CHECK_BOOTED_INTERVAL, 0) : time_remaining;
+                    resolve(self.wait_for_boot(emulator_id, updated_time));
+                }, delay);
+            });
+        }
+    });
+};
+
+/*
+ * Create avd
+ * TODO : Enter the stdin input required to complete the creation of an avd.
+ * Returns a promise.
+ */
+module.exports.create_image = function (name, target) {
+    console.log('Creating new avd named ' + name);
+    if (target) {
+        return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
+            console.error('ERROR : Failed to create emulator image : ');
+            console.error(' Do you have the latest android targets including ' + target + '?');
+            console.error(error);
+        });
+    } else {
+        console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
+        // TODO: there's a more robust method for finding targets in android_sdk.js
+        return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
+            // TODO: This seems like another error case, even though it always happens.
+            console.error('ERROR : Unable to create an avd emulator, no targets found.');
+            console.error('Ensure you have targets available by running the "android" command');
+            return Promise.reject(new CordovaError());
+        }, function (error) {
+            console.error('ERROR : Failed to create emulator image : ');
+            console.error(error);
+        });
+    }
+};
+
+module.exports.resolveTarget = function (target) {
+    return this.list_started().then(function (emulator_list) {
+        if (emulator_list.length < 1) {
+            return Promise.reject(new CordovaError('No running Android emulators found, please start an emulator before deploying your project.'));
+        }
+
+        // default emulator
+        target = target || emulator_list[0];
+        if (emulator_list.indexOf(target) < 0) {
+            return Promise.reject(new CordovaError('Unable to find target \'' + target + '\'. Failed to deploy to emulator.'));
+        }
+
+        return build.detectArchitecture(target).then(function (arch) {
+            return { target: target, arch: arch, isEmulator: true };
+        });
+    });
+};
+
+/*
+ * Installs a previously built application on the emulator and launches it.
+ * If no target is specified, then it picks one.
+ * If no started emulators are found, error out.
+ * Returns a promise.
+ */
+module.exports.install = function (givenTarget, buildResults) {
+
+    var target;
+    // We need to find the proper path to the Android Manifest
+    const manifestPath = path.join(__dirname, '..', '..', 'app', 'src', 'main', 'AndroidManifest.xml');
+    const manifest = new AndroidManifest(manifestPath);
+    const pkgName = manifest.getPackageId();
+
+    // resolve the target emulator
+    return Promise.resolve().then(function () {
+        if (givenTarget && typeof givenTarget === 'object') {
+            return givenTarget;
+        } else {
+            return module.exports.resolveTarget(givenTarget);
+        }
+
+    // set the resolved target
+    }).then(function (resolvedTarget) {
+        target = resolvedTarget;
+
+    // install the app
+    }).then(function () {
+        // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
+        // or the app doesn't installed at all, so no error catching needed.
+        return Promise.resolve().then(function () {
+
+            var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
+            var execOptions = {
+                cwd: os.tmpdir(),
+                timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
+                killSignal: EXEC_KILL_SIGNAL
+            };
+
+            events.emit('log', 'Using apk: ' + apk_path);
+            events.emit('log', 'Package name: ' + pkgName);
+            events.emit('verbose', 'Installing app on emulator...');
+
+            // A special function to call adb install in specific environment w/ specific options.
+            // Introduced as a part of fix for http://issues.apache.org/jira/browse/CB-9119
+            // to workaround sporadic emulator hangs
+            function adbInstallWithOptions (target, apk, opts) {
+                events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...');
+
+                var command = 'adb -s ' + target + ' install -r "' + apk + '"';
+                return new Promise(function (resolve, reject) {
+                    child_process.exec(command, opts, function (err, stdout, stderr) {
+                        if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
+                        // adb does not return an error code even if installation fails. Instead it puts a specific
+                        // message to stdout, so we have to use RegExp matching to detect installation failure.
+                        else if (/Failure/.test(stdout)) {
+                            if (stdout.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
+                                stdout += 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
+                                    ' or sign and deploy the unsigned apk manually using Android tools.';
+                            } else if (stdout.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
+                                stdout += 'You\'re trying to install apk with a lower versionCode that is already installed.' +
+                                    '\nEither uninstall an app or increment the versionCode.';
+                            }
+
+                            reject(new CordovaError('Failed to install apk to emulator: ' + stdout));
+                        } else resolve(stdout);
+                    });
+                });
+            }
+
+            function installPromise () {
+                return adbInstallWithOptions(target.target, apk_path, execOptions).catch(function (error) {
+                    // CB-9557 CB-10157 only uninstall and reinstall app if the one that
+                    // is already installed on device was signed w/different certificate
+                    if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
+
+                    events.emit('warn', 'Uninstalling app from device and reinstalling it because the ' +
+                        'currently installed app was signed with different key');
+
+                    // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
+                    // or the app doesn't installed at all, so no error catching needed.
+                    return Adb.uninstall(target.target, pkgName).then(function () {
+                        return adbInstallWithOptions(target.target, apk_path, execOptions);
+                    });
+                });
+            }
+
+            return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise).then(function (output) {
+                events.emit('log', 'INSTALL SUCCESS');
+            });
+        });
+    // unlock screen
+    }).then(function () {
+
+        events.emit('verbose', 'Unlocking screen...');
+        return Adb.shell(target.target, 'input keyevent 82');
+    }).then(function () {
+        Adb.start(target.target, pkgName + '/.' + manifest.getActivity().getName());
+    // report success or failure
+    }).then(function (output) {
+        events.emit('log', 'LAUNCH SUCCESS');
+    });
+};
diff --git a/platforms/android/cordova/lib/getASPath.bat b/platforms/android/cordova/lib/getASPath.bat
new file mode 100644
index 0000000..14dad43
--- /dev/null
+++ b/platforms/android/cordova/lib/getASPath.bat
@@ -0,0 +1,3 @@
+@ECHO OFF
+for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
+ECHO %ASPath%
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/install-device b/platforms/android/cordova/lib/install-device
new file mode 100755
index 0000000..0387388
--- /dev/null
+++ b/platforms/android/cordova/lib/install-device
@@ -0,0 +1,42 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var device = require('./device');
+var args = process.argv;
+
+if (args.length > 2) {
+    var install_target;
+    if (args[2].substring(0, 9) === '--target=') {
+        install_target = args[2].substring(9, args[2].length);
+        device.install(install_target).catch(function (err) {
+            console.error('ERROR: ' + err);
+            process.exit(2);
+        });
+    } else {
+        console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
+        process.exit(2);
+    }
+} else {
+    device.install().catch(function (err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+}
diff --git a/platforms/android/cordova/lib/install-device.bat b/platforms/android/cordova/lib/install-device.bat
new file mode 100644
index 0000000..109b470
--- /dev/null
+++ b/platforms/android/cordova/lib/install-device.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0install-device"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/install-emulator b/platforms/android/cordova/lib/install-emulator
new file mode 100755
index 0000000..2d46dbe
--- /dev/null
+++ b/platforms/android/cordova/lib/install-emulator
@@ -0,0 +1,38 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var emulator = require('./emulator');
+var args = process.argv;
+
+var install_target;
+if (args.length > 2) {
+    if (args[2].substring(0, 9) === '--target=') {
+        install_target = args[2].substring(9, args[2].length);
+    } else {
+        console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
+        process.exit(2);
+    }
+}
+
+emulator.install(install_target).catch(function (err) {
+    console.error('ERROR: ' + err);
+    process.exit(2);
+});
diff --git a/platforms/android/cordova/lib/install-emulator.bat b/platforms/android/cordova/lib/install-emulator.bat
new file mode 100644
index 0000000..a28c23a
--- /dev/null
+++ b/platforms/android/cordova/lib/install-emulator.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0install-emulator"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/list-devices b/platforms/android/cordova/lib/list-devices
new file mode 100755
index 0000000..339c665
--- /dev/null
+++ b/platforms/android/cordova/lib/list-devices
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var devices = require('./device');
+
+// Usage support for when args are given
+require('./check_reqs').check_android().then(function () {
+    devices.list().then(function (device_list) {
+        device_list && device_list.forEach(function (dev) {
+            console.log(dev);
+        });
+    }, function (err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+});
diff --git a/platforms/android/cordova/lib/list-devices.bat b/platforms/android/cordova/lib/list-devices.bat
new file mode 100644
index 0000000..ad5f03e
--- /dev/null
+++ b/platforms/android/cordova/lib/list-devices.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0list-devices"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/list-emulator-images b/platforms/android/cordova/lib/list-emulator-images
new file mode 100755
index 0000000..03cfb19
--- /dev/null
+++ b/platforms/android/cordova/lib/list-emulator-images
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var emulators = require('./emulator');
+
+// Usage support for when args are given
+require('./check_reqs').check_android().then(function () {
+    emulators.list_images().then(function (emulator_list) {
+        emulator_list && emulator_list.forEach(function (emu) {
+            console.log(emu.name);
+        });
+    }, function (err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+});
diff --git a/platforms/android/cordova/lib/list-emulator-images.bat b/platforms/android/cordova/lib/list-emulator-images.bat
new file mode 100644
index 0000000..616ffb7
--- /dev/null
+++ b/platforms/android/cordova/lib/list-emulator-images.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0list-emulator-images"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO. 
+    ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/android/cordova/lib/list-started-emulators b/platforms/android/cordova/lib/list-started-emulators
new file mode 100755
index 0000000..2a83e03
--- /dev/null
+++ b/platforms/android/cordova/lib/list-started-emulators
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var emulators = require('./emulator');
+
+// Usage support for when args are given
+require('./check_reqs').check_android().then(function () {
+    emulators.list_started().then(function (emulator_list) {
+        emulator_list && emulator_list.forEach(function (emu) {
+            console.log(emu);
+        });
+    }, function (err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+});
diff --git a/platforms/android/cordova/lib/list-started-emulators.bat b/platforms/android/cordova/lib/list-started-emulators.bat
new file mode 100644
index 0000000..eed02a5
--- /dev/null
+++ b/platforms/android/cordova/lib/list-started-emulators.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0list-started-emulators"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/log.js b/platforms/android/cordova/lib/log.js
new file mode 100644
index 0000000..ec69f8c
--- /dev/null
+++ b/platforms/android/cordova/lib/log.js
@@ -0,0 +1,56 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var path = require('path');
+var os = require('os');
+var Q = require('q');
+var child_process = require('child_process');
+var ROOT = path.join(__dirname, '..', '..');
+
+/*
+ * Starts running logcat in the shell.
+ * Returns a promise.
+ */
+module.exports.run = function () {
+    var d = Q.defer();
+    var adb = child_process.spawn('adb', ['logcat'], { cwd: os.tmpdir() });
+
+    adb.stdout.on('data', function (data) {
+        var lines = data ? data.toString().split('\n') : [];
+        var out = lines.filter(function (x) { return x.indexOf('nativeGetEnabledTags') < 0; });
+        console.log(out.join('\n'));
+    });
+
+    adb.stderr.on('data', console.error);
+    adb.on('close', function (code) {
+        if (code > 0) {
+            d.reject('Failed to run logcat command.');
+        } else d.resolve();
+    });
+
+    return d.promise;
+};
+
+module.exports.help = function () {
+    console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'log')));
+    console.log('Gives the logcat output on the command line.');
+    process.exit(0);
+};
diff --git a/platforms/android/cordova/lib/plugin-build.gradle b/platforms/android/cordova/lib/plugin-build.gradle
new file mode 100644
index 0000000..032b870
--- /dev/null
+++ b/platforms/android/cordova/lib/plugin-build.gradle
@@ -0,0 +1,69 @@
+/* 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.
+*/
+
+// GENERATED FILE! DO NOT EDIT!
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    // Switch the Android Gradle plugin version requirement depending on the
+    // installed version of Gradle. This dependency is documented at
+    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
+    // and https://issues.apache.org/jira/browse/CB-8143
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.0.0+'
+    }
+}
+
+apply plugin: 'com.android.library'
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: '*.jar')
+    debugCompile project(path: ":CordovaLib", configuration: "debug")
+    releaseCompile project(path: ":CordovaLib", configuration: "release")
+}
+
+android {
+    compileSdkVersion cdvCompileSdkVersion
+    buildToolsVersion cdvBuildToolsVersion
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_6
+        targetCompatibility JavaVersion.VERSION_1_6
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            resources.srcDirs = ['src']
+            aidl.srcDirs = ['src']
+            renderscript.srcDirs = ['src']
+            res.srcDirs = ['res']
+            assets.srcDirs = ['assets']
+            jniLibs.srcDirs = ['libs']
+        }
+    }
+}
+
+if (file('build-extras.gradle').exists()) {
+    apply from: 'build-extras.gradle'
+}
diff --git a/platforms/android/cordova/lib/pluginHandlers.js b/platforms/android/cordova/lib/pluginHandlers.js
new file mode 100644
index 0000000..6d1a733
--- /dev/null
+++ b/platforms/android/cordova/lib/pluginHandlers.js
@@ -0,0 +1,334 @@
+/*
+ * 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.
+ *
+*/
+
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+var CordovaError = require('cordova-common').CordovaError;
+
+var handlers = {
+    'source-file': {
+        install: function (obj, plugin, project, options) {
+            if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
+            if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
+
+            var dest = getInstallDestination(obj);
+
+            if (options && options.force) {
+                copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
+            } else {
+                copyNewFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
+            }
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var dest = getInstallDestination(obj);
+
+            // TODO: Add Koltin extension to uninstall, since they are handled like Java files
+            if (obj.src.endsWith('java')) {
+                deleteJava(project.projectDir, dest);
+            } else {
+                // Just remove the file, not the whole parent directory
+                removeFile(project.projectDir, dest);
+            }
+        }
+    },
+    'lib-file': {
+        install: function (obj, plugin, project, options) {
+            var dest = path.join('app/libs', path.basename(obj.src));
+            copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var dest = path.join('app/libs', path.basename(obj.src));
+            removeFile(project.projectDir, dest);
+        }
+    },
+    'resource-file': {
+        install: function (obj, plugin, project, options) {
+            var dest = path.join('app', 'src', 'main', obj.target);
+            copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var dest = path.join('app', 'src', 'main', obj.target);
+            removeFile(project.projectDir, dest);
+        }
+    },
+    'framework': {
+        install: function (obj, plugin, project, options) {
+            var src = obj.src;
+            if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
+
+            events.emit('verbose', 'Installing Android library: ' + src);
+            var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
+            var subDir;
+
+            if (obj.custom) {
+                var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
+                copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, !!(options && options.link));
+                subDir = path.resolve(project.projectDir, subRelativeDir);
+            } else {
+                obj.type = 'sys';
+                subDir = src;
+            }
+
+            if (obj.type === 'gradleReference') {
+                project.addGradleReference(parentDir, subDir);
+            } else if (obj.type === 'sys') {
+                project.addSystemLibrary(parentDir, subDir);
+            } else {
+                project.addSubProject(parentDir, subDir);
+            }
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var src = obj.src;
+            if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
+
+            events.emit('verbose', 'Uninstalling Android library: ' + src);
+            var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
+            var subDir;
+
+            if (obj.custom) {
+                var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
+                removeFile(project.projectDir, subRelativeDir);
+                subDir = path.resolve(project.projectDir, subRelativeDir);
+                // If it's the last framework in the plugin, remove the parent directory.
+                var parDir = path.dirname(subDir);
+                if (fs.existsSync(parDir) && fs.readdirSync(parDir).length === 0) {
+                    fs.rmdirSync(parDir);
+                }
+            } else {
+                obj.type = 'sys';
+                subDir = src;
+            }
+
+            if (obj.type === 'gradleReference') {
+                project.removeGradleReference(parentDir, subDir);
+            } else if (obj.type === 'sys') {
+                project.removeSystemLibrary(parentDir, subDir);
+            } else {
+                project.removeSubProject(parentDir, subDir);
+            }
+        }
+    },
+    asset: {
+        install: function (obj, plugin, project, options) {
+            if (!obj.src) {
+                throw new CordovaError(generateAttributeError('src', 'asset', plugin.id));
+            }
+            if (!obj.target) {
+                throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
+            }
+
+            copyFile(plugin.dir, obj.src, project.www, obj.target);
+            if (options && options.usePlatformWww) {
+                // CB-11022 copy file to both directories if usePlatformWww is specified
+                copyFile(plugin.dir, obj.src, project.platformWww, obj.target);
+            }
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var target = obj.target || obj.src;
+
+            if (!target) throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
+
+            removeFileF(path.resolve(project.www, target));
+            removeFileF(path.resolve(project.www, 'plugins', plugin.id));
+            if (options && options.usePlatformWww) {
+                // CB-11022 remove file from both directories if usePlatformWww is specified
+                removeFileF(path.resolve(project.platformWww, target));
+                removeFileF(path.resolve(project.platformWww, 'plugins', plugin.id));
+            }
+        }
+    },
+    'js-module': {
+        install: function (obj, plugin, project, options) {
+            // Copy the plugin's files into the www directory.
+            var moduleSource = path.resolve(plugin.dir, obj.src);
+            var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
+
+            // Read in the file, prepend the cordova.define, and write it back out.
+            var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+            if (moduleSource.match(/.*\.json$/)) {
+                scriptContent = 'module.exports = ' + scriptContent;
+            }
+            scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
+
+            var wwwDest = path.resolve(project.www, 'plugins', plugin.id, obj.src);
+            shell.mkdir('-p', path.dirname(wwwDest));
+            fs.writeFileSync(wwwDest, scriptContent, 'utf-8');
+
+            if (options && options.usePlatformWww) {
+                // CB-11022 copy file to both directories if usePlatformWww is specified
+                var platformWwwDest = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
+                shell.mkdir('-p', path.dirname(platformWwwDest));
+                fs.writeFileSync(platformWwwDest, scriptContent, 'utf-8');
+            }
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
+            removeFileAndParents(project.www, pluginRelativePath);
+            if (options && options.usePlatformWww) {
+                // CB-11022 remove file from both directories if usePlatformWww is specified
+                removeFileAndParents(project.platformWww, pluginRelativePath);
+            }
+        }
+    }
+};
+
+module.exports.getInstaller = function (type) {
+    if (handlers[type] && handlers[type].install) {
+        return handlers[type].install;
+    }
+
+    events.emit('verbose', '<' + type + '> is not supported for android plugins');
+};
+
+module.exports.getUninstaller = function (type) {
+    if (handlers[type] && handlers[type].uninstall) {
+        return handlers[type].uninstall;
+    }
+
+    events.emit('verbose', '<' + type + '> is not supported for android plugins');
+};
+
+function copyFile (plugin_dir, src, project_dir, dest, link) {
+    src = path.resolve(plugin_dir, src);
+    if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
+
+    // check that src path is inside plugin directory
+    var real_path = fs.realpathSync(src);
+    var real_plugin_path = fs.realpathSync(plugin_dir);
+    if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
+
+    dest = path.resolve(project_dir, dest);
+
+    // check that dest path is located in project directory
+    if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
+
+    shell.mkdir('-p', path.dirname(dest));
+    if (link) {
+        symlinkFileOrDirTree(src, dest);
+    } else if (fs.statSync(src).isDirectory()) {
+        // XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
+        shell.cp('-Rf', src + '/*', dest);
+    } else {
+        shell.cp('-f', src, dest);
+    }
+}
+
+// Same as copy file but throws error if target exists
+function copyNewFile (plugin_dir, src, project_dir, dest, link) {
+    var target_path = path.resolve(project_dir, dest);
+    if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
+
+    copyFile(plugin_dir, src, project_dir, dest, !!link);
+}
+
+function symlinkFileOrDirTree (src, dest) {
+    if (fs.existsSync(dest)) {
+        shell.rm('-Rf', dest);
+    }
+
+    if (fs.statSync(src).isDirectory()) {
+        shell.mkdir('-p', dest);
+        fs.readdirSync(src).forEach(function (entry) {
+            symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
+        });
+    } else {
+        fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
+    }
+}
+
+// checks if file exists and then deletes. Error if doesn't exist
+function removeFile (project_dir, src) {
+    var file = path.resolve(project_dir, src);
+    shell.rm('-Rf', file);
+}
+
+// deletes file/directory without checking
+function removeFileF (file) {
+    shell.rm('-Rf', file);
+}
+
+// Sometimes we want to remove some java, and prune any unnecessary empty directories
+function deleteJava (project_dir, destFile) {
+    removeFileAndParents(project_dir, destFile, 'src');
+}
+
+function removeFileAndParents (baseDir, destFile, stopper) {
+    stopper = stopper || '.';
+    var file = path.resolve(baseDir, destFile);
+    if (!fs.existsSync(file)) return;
+
+    removeFileF(file);
+
+    // check if directory is empty
+    var curDir = path.dirname(file);
+
+    while (curDir !== path.resolve(baseDir, stopper)) {
+        if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
+            fs.rmdirSync(curDir);
+            curDir = path.resolve(curDir, '..');
+        } else {
+            // directory not empty...do nothing
+            break;
+        }
+    }
+}
+
+function generateAttributeError (attribute, element, id) {
+    return 'Required attribute "' + attribute + '" not specified in <' + element + '> element from plugin: ' + id;
+}
+
+function getInstallDestination (obj) {
+    var APP_MAIN_PREFIX = 'app/src/main';
+    var PATH_SEPARATOR = '/';
+
+    var PATH_SEP_MATCH = '\\' + PATH_SEPARATOR;
+    var PATH_SEP_OR_EOL_MATCH = '(\\' + PATH_SEPARATOR + '|$)';
+
+    var appReg = new RegExp('^app' + PATH_SEP_OR_EOL_MATCH);
+    var libsReg = new RegExp('^libs' + PATH_SEP_OR_EOL_MATCH);
+    var srcReg = new RegExp('^src' + PATH_SEP_OR_EOL_MATCH);
+    var srcMainReg = new RegExp('^src' + PATH_SEP_MATCH + 'main' + PATH_SEP_OR_EOL_MATCH);
+
+    if (appReg.test(obj.targetDir)) {
+        // If any source file is using the new app directory structure,
+        // don't penalize it
+        return path.join(obj.targetDir, path.basename(obj.src));
+    } else {
+        // Plugin using deprecated target directory structure (GH-580)
+        if (obj.src.endsWith('.java')) {
+            return path.join(APP_MAIN_PREFIX, 'java', obj.targetDir.replace(srcReg, ''),
+                path.basename(obj.src));
+        } else if (obj.src.endsWith('.aidl')) {
+            return path.join(APP_MAIN_PREFIX, 'aidl', obj.targetDir.replace(srcReg, ''),
+                path.basename(obj.src));
+        } else if (libsReg.test(obj.targetDir)) {
+            if (obj.src.endsWith('.so')) {
+                return path.join(APP_MAIN_PREFIX, 'jniLibs', obj.targetDir.replace(libsReg, ''),
+                    path.basename(obj.src));
+            } else {
+                return path.join('app', obj.targetDir, path.basename(obj.src));
+            }
+        } else if (srcMainReg.test(obj.targetDir)) {
+            return path.join('app', obj.targetDir, path.basename(obj.src));
+        }
+
+        // For all other source files not using the new app directory structure,
+        // add 'app/src/main' to the targetDir
+        return path.join(APP_MAIN_PREFIX, obj.targetDir, path.basename(obj.src));
+    }
+}
diff --git a/platforms/android/cordova/lib/prepare.js b/platforms/android/cordova/lib/prepare.js
new file mode 100644
index 0000000..49e0a7d
--- /dev/null
+++ b/platforms/android/cordova/lib/prepare.js
@@ -0,0 +1,701 @@
+/**
+    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.
+*/
+/* eslint no-useless-escape: 0 */
+
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+var AndroidManifest = require('./AndroidManifest');
+var checkReqs = require('./check_reqs');
+var xmlHelpers = require('cordova-common').xmlHelpers;
+var CordovaError = require('cordova-common').CordovaError;
+var ConfigParser = require('cordova-common').ConfigParser;
+var FileUpdater = require('cordova-common').FileUpdater;
+var PlatformJson = require('cordova-common').PlatformJson;
+var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
+var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
+
+const GradlePropertiesParser = require('./config/GradlePropertiesParser');
+
+module.exports.prepare = function (cordovaProject, options) {
+    var self = this;
+
+    var platformJson = PlatformJson.load(this.locations.root, this.platform);
+    var munger = new PlatformMunger(this.platform, this.locations.root, platformJson, new PluginInfoProvider());
+
+    this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
+
+    // Get the min SDK version from config.xml
+    const minSdkVersion = this._config.getPreference('android-minSdkVersion', 'android');
+
+    let gradlePropertiesUserConfig = {};
+    if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = minSdkVersion;
+
+    let gradlePropertiesParser = new GradlePropertiesParser(this.locations.root);
+    gradlePropertiesParser.configure(gradlePropertiesUserConfig);
+
+    // Update own www dir with project's www assets and plugins' assets and js-files
+    return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
+        // update project according to config.xml changes.
+        return updateProjectAccordingTo(self._config, self.locations);
+    }).then(function () {
+        updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
+        updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
+        updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
+    }).then(function () {
+        events.emit('verbose', 'Prepared android project successfully');
+    });
+};
+
+module.exports.clean = function (options) {
+    // A cordovaProject isn't passed into the clean() function, because it might have
+    // been called from the platform shell script rather than the CLI. Check for the
+    // noPrepare option passed in by the non-CLI clean script. If that's present, or if
+    // there's no config.xml found at the project root, then don't clean prepared files.
+    var projectRoot = path.resolve(this.root, '../..');
+    if ((options && options.noPrepare) || !fs.existsSync(this.locations.configXml) ||
+            !fs.existsSync(this.locations.configXml)) {
+        return Q();
+    }
+
+    var projectConfig = new ConfigParser(this.locations.configXml);
+
+    var self = this;
+    return Q().then(function () {
+        cleanWww(projectRoot, self.locations);
+        cleanIcons(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
+        cleanSplashes(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
+        cleanFileResources(projectRoot, projectConfig, path.relative(projectRoot, self.locations.root));
+    });
+};
+
+/**
+ * Updates config files in project based on app's config.xml and config munge,
+ *   generated by plugins.
+ *
+ * @param   {ConfigParser}   sourceConfig  A project's configuration that will
+ *   be merged into platform's config.xml
+ * @param   {ConfigChanges}  configMunger  An initialized ConfigChanges instance
+ *   for this platform.
+ * @param   {Object}         locations     A map of locations for this platform
+ *
+ * @return  {ConfigParser}                 An instance of ConfigParser, that
+ *   represents current project's configuration. When returned, the
+ *   configuration is already dumped to appropriate config.xml file.
+ */
+function updateConfigFilesFrom (sourceConfig, configMunger, locations) {
+    events.emit('verbose', 'Generating platform-specific config.xml from defaults for android at ' + locations.configXml);
+
+    // First cleanup current config and merge project's one into own
+    // Overwrite platform config.xml with defaults.xml.
+    shell.cp('-f', locations.defaultConfigXml, locations.configXml);
+
+    // Then apply config changes from global munge to all config files
+    // in project (including project's config)
+    configMunger.reapply_global_munge().save_all();
+
+    events.emit('verbose', 'Merging project\'s config.xml into platform-specific android config.xml');
+    // Merge changes from app's config.xml into platform's one
+    var config = new ConfigParser(locations.configXml);
+    xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
+        config.doc.getroot(), 'android', /* clobber= */true);
+
+    config.write();
+    return config;
+}
+
+/**
+ * Logs all file operations via the verbose event stream, indented.
+ */
+function logFileOp (message) {
+    events.emit('verbose', '  ' + message);
+}
+
+/**
+ * Updates platform 'www' directory by replacing it with contents of
+ *   'platform_www' and app www. Also copies project's overrides' folder into
+ *   the platform 'www' folder
+ *
+ * @param   {Object}  cordovaProject    An object which describes cordova project.
+ * @param   {Object}  destinations      An object that contains destination
+ *   paths for www files.
+ */
+function updateWww (cordovaProject, destinations) {
+    var sourceDirs = [
+        path.relative(cordovaProject.root, cordovaProject.locations.www),
+        path.relative(cordovaProject.root, destinations.platformWww)
+    ];
+
+    // If project contains 'merges' for our platform, use them as another overrides
+    var merges_path = path.join(cordovaProject.root, 'merges', 'android');
+    if (fs.existsSync(merges_path)) {
+        events.emit('verbose', 'Found "merges/android" folder. Copying its contents into the android project.');
+        sourceDirs.push(path.join('merges', 'android'));
+    }
+
+    var targetDir = path.relative(cordovaProject.root, destinations.www);
+    events.emit(
+        'verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+    FileUpdater.mergeAndUpdateDir(
+        sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+/**
+ * Cleans all files from the platform 'www' directory.
+ */
+function cleanWww (projectRoot, locations) {
+    var targetDir = path.relative(projectRoot, locations.www);
+    events.emit('verbose', 'Cleaning ' + targetDir);
+
+    // No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
+    FileUpdater.mergeAndUpdateDir(
+        [], targetDir, { rootDir: projectRoot, all: true }, logFileOp);
+}
+
+/**
+ * Updates project structure and AndroidManifest according to project's configuration.
+ *
+ * @param   {ConfigParser}  platformConfig  A project's configuration that will
+ *   be used to update project
+ * @param   {Object}  locations       A map of locations for this platform
+ */
+function updateProjectAccordingTo (platformConfig, locations) {
+    // Update app name by editing res/values/strings.xml
+    var strings = xmlHelpers.parseElementtreeSync(locations.strings);
+
+    var name = platformConfig.name();
+    strings.find('string[@name="app_name"]').text = name.replace(/\'/g, '\\\'');
+
+    var shortName = platformConfig.shortName && platformConfig.shortName();
+    if (shortName && shortName !== name) {
+        strings.find('string[@name="launcher_name"]').text = shortName.replace(/\'/g, '\\\'');
+    }
+
+    fs.writeFileSync(locations.strings, strings.write({ indent: 4 }), 'utf-8');
+    events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings);
+
+    // Java packages cannot support dashes
+    var androidPkgName = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
+
+    var manifest = new AndroidManifest(locations.manifest);
+    var manifestId = manifest.getPackageId();
+
+    manifest.getActivity()
+        .setOrientation(platformConfig.getPreference('orientation'))
+        .setLaunchMode(findAndroidLaunchModePreference(platformConfig));
+
+    manifest.setVersionName(platformConfig.version())
+        .setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
+        .setPackageId(androidPkgName)
+        .setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
+        .setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
+        .setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
+        .write();
+
+    // Java file paths shouldn't be hard coded
+    var javaPattern = path.join(locations.javaSrc, manifestId.replace(/\./g, '/'), '*.java');
+    var java_files = shell.ls(javaPattern).filter(function (f) {
+        return shell.grep(/extends\s+CordovaActivity/g, f);
+    });
+
+    if (java_files.length === 0) {
+        throw new CordovaError('No Java files found that extend CordovaActivity.');
+    } else if (java_files.length > 1) {
+        events.emit('log', 'Multiple candidate Java files that extend CordovaActivity found. Guessing at the first one, ' + java_files[0]);
+    }
+
+    var destFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(java_files[0]));
+    shell.mkdir('-p', path.dirname(destFile));
+    shell.sed(/package [\w\.]*;/, 'package ' + androidPkgName + ';', java_files[0]).to(destFile);
+    events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + destFile);
+
+    var removeOrigPkg = checkReqs.isWindows() || checkReqs.isDarwin() ?
+        manifestId.toUpperCase() !== androidPkgName.toUpperCase() :
+        manifestId !== androidPkgName;
+
+    if (removeOrigPkg) {
+        // If package was name changed we need to remove old java with main activity
+        shell.rm('-Rf', java_files[0]);
+        // remove any empty directories
+        var currentDir = path.dirname(java_files[0]);
+        var sourcesRoot = path.resolve(locations.root, 'src');
+        while (currentDir !== sourcesRoot) {
+            if (fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {
+                fs.rmdirSync(currentDir);
+                currentDir = path.resolve(currentDir, '..');
+            } else {
+                break;
+            }
+        }
+    }
+}
+
+// Consturct the default value for versionCode as
+// PATCH + MINOR * 100 + MAJOR * 10000
+// see http://developer.android.com/tools/publishing/versioning.html
+function default_versionCode (version) {
+    var nums = version.split('-')[0].split('.');
+    var versionCode = 0;
+    if (+nums[0]) {
+        versionCode += +nums[0] * 10000;
+    }
+    if (+nums[1]) {
+        versionCode += +nums[1] * 100;
+    }
+    if (+nums[2]) {
+        versionCode += +nums[2];
+    }
+
+    events.emit('verbose', 'android-versionCode not found in config.xml. Generating a code based on version in config.xml (' + version + '): ' + versionCode);
+    return versionCode;
+}
+
+function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
+    if (/\.9\.png$/.test(sourceName)) {
+        name = name.replace(/\.png$/, '.9.png');
+    }
+    var resourcePath = path.join(resourcesDir, (density ? type + '-' + density : type), name);
+    return resourcePath;
+}
+
+function getAdaptiveImageResourcePath (resourcesDir, type, density, name, sourceName) {
+    if (/\.9\.png$/.test(sourceName)) {
+        name = name.replace(/\.png$/, '.9.png');
+    }
+    var resourcePath = path.join(resourcesDir, (density ? type + '-' + density + '-v26' : type), name);
+    return resourcePath;
+}
+
+function updateSplashes (cordovaProject, platformResourcesDir) {
+    var resources = cordovaProject.projectConfig.getSplashScreens('android');
+
+    // if there are "splash" elements in config.xml
+    if (resources.length === 0) {
+        events.emit('verbose', 'This app does not have splash screens defined');
+        return;
+    }
+
+    var resourceMap = mapImageResources(cordovaProject.root, platformResourcesDir, 'drawable', 'screen.png');
+
+    var hadMdpi = false;
+    resources.forEach(function (resource) {
+        if (!resource.density) {
+            return;
+        }
+        if (resource.density === 'mdpi') {
+            hadMdpi = true;
+        }
+        var targetPath = getImageResourcePath(
+            platformResourcesDir, 'drawable', resource.density, 'screen.png', path.basename(resource.src));
+        resourceMap[targetPath] = resource.src;
+    });
+
+    // There's no "default" drawable, so assume default == mdpi.
+    if (!hadMdpi && resources.defaultResource) {
+        var targetPath = getImageResourcePath(
+            platformResourcesDir, 'drawable', 'mdpi', 'screen.png', path.basename(resources.defaultResource.src));
+        resourceMap[targetPath] = resources.defaultResource.src;
+    }
+
+    events.emit('verbose', 'Updating splash screens at ' + platformResourcesDir);
+    FileUpdater.updatePaths(
+        resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
+    var resources = projectConfig.getSplashScreens('android');
+    if (resources.length > 0) {
+        var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'drawable', 'screen.png');
+        events.emit('verbose', 'Cleaning splash screens at ' + platformResourcesDir);
+
+        // No source paths are specified in the map, so updatePaths() will delete the target files.
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+    }
+}
+
+function updateIcons (cordovaProject, platformResourcesDir) {
+    let icons = cordovaProject.projectConfig.getIcons('android');
+
+    // Skip if there are no app defined icons in config.xml
+    if (icons.length === 0) {
+        events.emit('verbose', 'This app does not have launcher icons defined');
+        return;
+    }
+
+    // 1. loop icons determin if there is an error in the setup.
+    // 2. during initial loop, also setup for legacy support.
+    let errorMissingAttributes = [];
+    let errorLegacyIconNeeded = [];
+    let hasAdaptive = false;
+    icons.forEach((icon, key) => {
+        if (
+            (icon.background && !icon.foreground)
+            || (!icon.background && icon.foreground)
+            || (!icon.background && !icon.foreground && !icon.src)
+        ) {
+            errorMissingAttributes.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
+        }
+
+        if (icon.foreground) {
+            hasAdaptive = true;
+
+            if (
+                !icon.src
+                && (
+                    icon.foreground.startsWith('@color')
+                    || path.extname(path.basename(icon.foreground)) === '.xml'
+                )
+            ) {
+                errorLegacyIconNeeded.push(icon.density ? icon.density : 'size=' + (icon.height || icon.width));
+            } else if (!icon.src) {
+                icons[key].src = icon.foreground;
+            }
+        }
+    });
+
+    let errorMessage = [];
+    if (errorMissingAttributes.length > 0) {
+        errorMessage.push('One of the following attributes are set but missing the other for the density type: ' + errorMissingAttributes.join(', ') + '. Please ensure that all require attributes are defined.');
+    }
+
+    if (errorLegacyIconNeeded.length > 0) {
+        errorMessage.push('For the following icons with the density of: ' + errorLegacyIconNeeded.join(', ') + ', adaptive foreground with a defined color or vector can not be used as a standard fallback icon for older Android devices. To support older Android environments, please provide a value for the src attribute.');
+    }
+
+    if (errorMessage.length > 0) {
+        throw new CordovaError(errorMessage.join(' '));
+    }
+
+    let resourceMap = Object.assign(
+        {},
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
+        mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
+    );
+
+    let preparedIcons = prepareIcons(icons);
+
+    if (hasAdaptive) {
+        resourceMap = updateIconResourceForAdaptive(preparedIcons, resourceMap, platformResourcesDir);
+    }
+
+    resourceMap = updateIconResourceForLegacy(preparedIcons, resourceMap, platformResourcesDir);
+
+    events.emit('verbose', 'Updating icons at ' + platformResourcesDir);
+    FileUpdater.updatePaths(resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+function updateIconResourceForAdaptive (preparedIcons, resourceMap, platformResourcesDir) {
+    let android_icons = preparedIcons.android_icons;
+    let default_icon = preparedIcons.default_icon;
+
+    // The source paths for icons and splashes are relative to
+    // project's config.xml location, so we use it as base path.
+    let background;
+    let foreground;
+    let targetPathBackground;
+    let targetPathForeground;
+
+    for (let density in android_icons) {
+        let backgroundVal = '@mipmap/ic_launcher_background';
+        let foregroundVal = '@mipmap/ic_launcher_foreground';
+
+        background = android_icons[density].background;
+        foreground = android_icons[density].foreground;
+
+        if (background.startsWith('@color')) {
+            // Colors Use Case
+            backgroundVal = background; // Example: @color/background_foobar_1
+        } else if (path.extname(path.basename(background)) === '.xml') {
+            // Vector Use Case
+            targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.xml', path.basename(android_icons[density].background));
+            resourceMap[targetPathBackground] = android_icons[density].background;
+        } else if (path.extname(path.basename(background)) === '.png') {
+            // Images Use Case
+            targetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_background.png', path.basename(android_icons[density].background));
+            resourceMap[targetPathBackground] = android_icons[density].background;
+        }
+
+        if (foreground.startsWith('@color')) {
+            // Colors Use Case
+            foregroundVal = foreground;
+        } else if (path.extname(path.basename(foreground)) === '.xml') {
+            // Vector Use Case
+            targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.xml', path.basename(android_icons[density].foreground));
+            resourceMap[targetPathForeground] = android_icons[density].foreground;
+        } else if (path.extname(path.basename(foreground)) === '.png') {
+            // Images Use Case
+            targetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher_foreground.png', path.basename(android_icons[density].foreground));
+            resourceMap[targetPathForeground] = android_icons[density].foreground;
+        }
+
+        // create an XML for DPI and set color
+        const icLauncherTemplate = `<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="` + backgroundVal + `" />
+    <foreground android:drawable="` + foregroundVal + `" />
+</adaptive-icon>`;
+
+        let launcherXmlPath = path.join(platformResourcesDir, 'mipmap-' + density + '-v26', 'ic_launcher.xml');
+
+        // Remove the XML from the resourceMap so the file does not get removed.
+        delete resourceMap[launcherXmlPath];
+
+        fs.writeFileSync(path.resolve(launcherXmlPath), icLauncherTemplate);
+    }
+
+    // There's no "default" drawable, so assume default == mdpi.
+    if (default_icon && !android_icons.mdpi) {
+        let defaultTargetPathBackground;
+        let defaultTargetPathForeground;
+
+        if (background.startsWith('@color')) {
+            // Colors Use Case
+            targetPathBackground = default_icon.background;
+        } else if (path.extname(path.basename(background)) === '.xml') {
+            // Vector Use Case
+            defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.xml', path.basename(default_icon.background));
+            resourceMap[defaultTargetPathBackground] = default_icon.background;
+        } else if (path.extname(path.basename(background)) === '.png') {
+            // Images Use Case
+            defaultTargetPathBackground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_background.png', path.basename(default_icon.background));
+            resourceMap[defaultTargetPathBackground] = default_icon.background;
+        }
+
+        if (foreground.startsWith('@color')) {
+            // Colors Use Case
+            targetPathForeground = default_icon.foreground;
+        } else if (path.extname(path.basename(foreground)) === '.xml') {
+            // Vector Use Case
+            defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.xml', path.basename(default_icon.foreground));
+            resourceMap[defaultTargetPathForeground] = default_icon.foreground;
+        } else if (path.extname(path.basename(foreground)) === '.png') {
+            // Images Use Case
+            defaultTargetPathForeground = getAdaptiveImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher_foreground.png', path.basename(default_icon.foreground));
+            resourceMap[defaultTargetPathForeground] = default_icon.foreground;
+        }
+    }
+
+    return resourceMap;
+}
+
+function updateIconResourceForLegacy (preparedIcons, resourceMap, platformResourcesDir) {
+    let android_icons = preparedIcons.android_icons;
+    let default_icon = preparedIcons.default_icon;
+
+    // The source paths for icons and splashes are relative to
+    // project's config.xml location, so we use it as base path.
+    for (var density in android_icons) {
+        var targetPath = getImageResourcePath(platformResourcesDir, 'mipmap', density, 'ic_launcher.png', path.basename(android_icons[density].src));
+        resourceMap[targetPath] = android_icons[density].src;
+    }
+
+    // There's no "default" drawable, so assume default == mdpi.
+    if (default_icon && !android_icons.mdpi) {
+        var defaultTargetPath = getImageResourcePath(platformResourcesDir, 'mipmap', 'mdpi', 'ic_launcher.png', path.basename(default_icon.src));
+        resourceMap[defaultTargetPath] = default_icon.src;
+    }
+
+    return resourceMap;
+}
+
+function prepareIcons (icons) {
+    // http://developer.android.com/design/style/iconography.html
+    const SIZE_TO_DENSITY_MAP = {
+        36: 'ldpi',
+        48: 'mdpi',
+        72: 'hdpi',
+        96: 'xhdpi',
+        144: 'xxhdpi',
+        192: 'xxxhdpi'
+    };
+
+    let android_icons = {};
+    let default_icon;
+
+    // find the best matching icon for a given density or size
+    // @output android_icons
+    var parseIcon = function (icon, icon_size) {
+        // do I have a platform icon for that density already
+        var density = icon.density || SIZE_TO_DENSITY_MAP[icon_size];
+        if (!density) {
+            // invalid icon defition ( or unsupported size)
+            return;
+        }
+        var previous = android_icons[density];
+        if (previous && previous.platform) {
+            return;
+        }
+        android_icons[density] = icon;
+    };
+
+    // iterate over all icon elements to find the default icon and call parseIcon
+    for (var i = 0; i < icons.length; i++) {
+        var icon = icons[i];
+        var size = icon.width;
+
+        if (!size) {
+            size = icon.height;
+        }
+
+        if (!size && !icon.density) {
+            if (default_icon) {
+                let found = {};
+                let favor = {};
+
+                // populating found icon.
+                if (icon.background && icon.foreground) {
+                    found.background = icon.background;
+                    found.foreground = icon.foreground;
+                }
+                if (icon.src) {
+                    found.src = icon.src;
+                }
+
+                if (default_icon.background && default_icon.foreground) {
+                    favor.background = default_icon.background;
+                    favor.foreground = default_icon.foreground;
+                }
+                if (default_icon.src) {
+                    favor.src = default_icon.src;
+                }
+
+                events.emit('verbose', 'Found extra default icon: ' + JSON.stringify(found) + ' and ignoring in favor of ' + JSON.stringify(favor) + '.');
+            } else {
+                default_icon = icon;
+            }
+        } else {
+            parseIcon(icon, size);
+        }
+    }
+
+    return {
+        android_icons: android_icons,
+        default_icon: default_icon
+    };
+}
+
+function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
+    var icons = projectConfig.getIcons('android');
+
+    // Skip if there are no app defined icons in config.xml
+    if (icons.length === 0) {
+        events.emit('verbose', 'This app does not have launcher icons defined');
+        return;
+    }
+
+    let resourceMap = Object.assign(
+        {},
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.png'),
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.png'),
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.png'),
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_foreground.xml'),
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher_background.xml'),
+        mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'ic_launcher.xml')
+    );
+
+    events.emit('verbose', 'Cleaning icons at ' + platformResourcesDir);
+
+    // No source paths are specified in the map, so updatePaths() will delete the target files.
+    FileUpdater.updatePaths(resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+}
+
+/**
+ * Gets a map containing resources of a specified name from all drawable folders in a directory.
+ */
+function mapImageResources (rootDir, subDir, type, resourceName) {
+    var pathMap = {};
+    shell.ls(path.join(rootDir, subDir, type + '-*')).forEach(function (drawableFolder) {
+        var imagePath = path.join(subDir, path.basename(drawableFolder), resourceName);
+        pathMap[imagePath] = null;
+    });
+    return pathMap;
+}
+
+function updateFileResources (cordovaProject, platformDir) {
+    var files = cordovaProject.projectConfig.getFileResources('android');
+
+    // if there are resource-file elements in config.xml
+    if (files.length === 0) {
+        events.emit('verbose', 'This app does not have additional resource files defined');
+        return;
+    }
+
+    var resourceMap = {};
+    files.forEach(function (res) {
+        var targetPath = path.join(platformDir, res.target);
+        resourceMap[targetPath] = res.src;
+    });
+
+    events.emit('verbose', 'Updating resource files at ' + platformDir);
+    FileUpdater.updatePaths(
+        resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+function cleanFileResources (projectRoot, projectConfig, platformDir) {
+    var files = projectConfig.getFileResources('android', true);
+    if (files.length > 0) {
+        events.emit('verbose', 'Cleaning resource files at ' + platformDir);
+
+        var resourceMap = {};
+        files.forEach(function (res) {
+            var filePath = path.join(platformDir, res.target);
+            resourceMap[filePath] = null;
+        });
+
+        FileUpdater.updatePaths(
+            resourceMap, {
+                rootDir: projectRoot, all: true }, logFileOp);
+    }
+}
+
+/**
+ * Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
+ *   preference value and warns if it doesn't seems to be valid
+ *
+ * @param   {ConfigParser}  platformConfig  A configParser instance for
+ *   platform.
+ *
+ * @return  {String}                  Preference's value from config.xml or
+ *   default value, if there is no such preference. The default value is
+ *   'singleTop'
+ */
+function findAndroidLaunchModePreference (platformConfig) {
+    var launchMode = platformConfig.getPreference('AndroidLaunchMode');
+    if (!launchMode) {
+        // Return a default value
+        return 'singleTop';
+    }
+
+    var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
+    var valid = expectedValues.indexOf(launchMode) >= 0;
+    if (!valid) {
+        // Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
+        events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
+            launchMode + '. Expected values are: ' + expectedValues.join(', '));
+    }
+
+    return launchMode;
+}
diff --git a/platforms/android/cordova/lib/retry.js b/platforms/android/cordova/lib/retry.js
new file mode 100644
index 0000000..b2b9a44
--- /dev/null
+++ b/platforms/android/cordova/lib/retry.js
@@ -0,0 +1,64 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+'use strict';
+
+var events = require('cordova-common').events;
+
+/*
+ * Retry a promise-returning function a number of times, propagating its
+ * results on success or throwing its error on a failed final attempt.
+ *
+ * @arg {Number}   attemptsLeft    - The number of times to retry the passed call.
+ * @arg {Function} promiseFunction - A function that returns a promise.
+ * @arg {...}                      - Arguments to pass to promiseFunction.
+ *
+ * @returns {Promise}
+ */
+module.exports.retryPromise = function (attemptsLeft, promiseFunction) {
+
+    // NOTE:
+    //      get all trailing arguments, by skipping the first two (attemptsLeft and
+    //      promiseFunction) because they shouldn't get passed to promiseFunction
+    var promiseFunctionArguments = Array.prototype.slice.call(arguments, 2);
+
+    return promiseFunction.apply(undefined, promiseFunctionArguments).then(
+        // on success pass results through
+        function onFulfilled (value) {
+            return value;
+        },
+
+        // on rejection either retry, or throw the error
+        function onRejected (error) {
+            attemptsLeft -= 1;
+
+            if (attemptsLeft < 1) {
+                throw error;
+            }
+
+            events.emit('verbose', 'A retried call failed. Retrying ' + attemptsLeft + ' more time(s).');
+
+            // retry call self again with the same arguments, except attemptsLeft is now lower
+            var fullArguments = [attemptsLeft, promiseFunction].concat(promiseFunctionArguments);
+            return module.exports.retryPromise.apply(undefined, fullArguments);
+        }
+    );
+};
diff --git a/platforms/android/cordova/lib/run.js b/platforms/android/cordova/lib/run.js
new file mode 100644
index 0000000..221467b
--- /dev/null
+++ b/platforms/android/cordova/lib/run.js
@@ -0,0 +1,131 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var path = require('path');
+var emulator = require('./emulator');
+var device = require('./device');
+var Q = require('q');
+var events = require('cordova-common').events;
+
+function getInstallTarget (runOptions) {
+    var install_target;
+    if (runOptions.target) {
+        install_target = runOptions.target;
+    } else if (runOptions.device) {
+        install_target = '--device';
+    } else if (runOptions.emulator) {
+        install_target = '--emulator';
+    }
+
+    return install_target;
+}
+
+/**
+ * Runs the application on a device if available. If no device is found, it will
+ *   use a started emulator. If no started emulators are found it will attempt
+ *   to start an avd. If no avds are found it will error out.
+ *
+ * @param   {Object}  runOptions  various run/build options. See Api.js build/run
+ *   methods for reference.
+ *
+ * @return  {Promise}
+ */
+module.exports.run = function (runOptions) {
+    runOptions = runOptions || {};
+
+    var self = this;
+    var install_target = getInstallTarget(runOptions);
+
+    return Q().then(function () {
+        if (!install_target) {
+            // no target given, deploy to device if available, otherwise use the emulator.
+            return device.list().then(function (device_list) {
+                if (device_list.length > 0) {
+                    events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
+                    install_target = device_list[0];
+                } else {
+                    events.emit('warn', 'No target specified and no devices found, deploying to emulator');
+                    install_target = '--emulator';
+                }
+            });
+        }
+    }).then(function () {
+        if (install_target === '--device') {
+            return device.resolveTarget(null);
+        } else if (install_target === '--emulator') {
+            // Give preference to any already started emulators. Else, start one.
+            return emulator.list_started().then(function (started) {
+                return started && started.length > 0 ? started[0] : emulator.start();
+            }).then(function (emulatorId) {
+                return emulator.resolveTarget(emulatorId);
+            });
+        }
+        // They specified a specific device/emulator ID.
+        return device.list().then(function (devices) {
+            if (devices.indexOf(install_target) > -1) {
+                return device.resolveTarget(install_target);
+            }
+            return emulator.list_started().then(function (started_emulators) {
+                if (started_emulators.indexOf(install_target) > -1) {
+                    return emulator.resolveTarget(install_target);
+                }
+                return emulator.list_images().then(function (avds) {
+                    // if target emulator isn't started, then start it.
+                    for (var avd in avds) {
+                        if (avds[avd].name === install_target) {
+                            return emulator.start(install_target).then(function (emulatorId) {
+                                return emulator.resolveTarget(emulatorId);
+                            });
+                        }
+                    }
+                    return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
+                });
+            });
+        });
+    }).then(function (resolvedTarget) {
+        return new Promise((resolve) => {
+            const builder = require('./builders/builders').getBuilder();
+            const buildOptions = require('./build').parseBuildOptions(runOptions, null, self.root);
+            resolve(builder.fetchBuildResults(buildOptions.buildType, buildOptions.arch));
+        }).then(function (buildResults) {
+            if (resolvedTarget && resolvedTarget.isEmulator) {
+                return emulator.wait_for_boot(resolvedTarget.target).then(function () {
+                    return emulator.install(resolvedTarget, buildResults);
+                });
+            }
+
+            return device.install(resolvedTarget, buildResults);
+        });
+    });
+};
+
+module.exports.help = function () {
+    console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]) + ' [options]');
+    console.log('Build options :');
+    console.log('    --debug : Builds project in debug mode');
+    console.log('    --release : Builds project in release mode');
+    console.log('    --nobuild : Runs the currently built project without recompiling');
+    console.log('Deploy options :');
+    console.log('    --device : Will deploy the built project to a device');
+    console.log('    --emulator : Will deploy the built project to an emulator if one exists');
+    console.log('    --target=<target_id> : Installs to the target with the specified id.');
+    process.exit(0);
+};
diff --git a/platforms/android/cordova/lib/start-emulator b/platforms/android/cordova/lib/start-emulator
new file mode 100755
index 0000000..20c92b7
--- /dev/null
+++ b/platforms/android/cordova/lib/start-emulator
@@ -0,0 +1,38 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var emulator = require('./emulator');
+var args = process.argv;
+
+var install_target;
+if (args.length > 2) {
+    if (args[2].substring(0, 9) === '--target=') {
+        install_target = args[2].substring(9, args[2].length);
+    } else {
+        console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
+        process.exit(2);
+    }
+}
+
+emulator.start(install_target).catch(function (err) {
+    console.error('ERROR: ' + err);
+    process.exit(2);
+});
diff --git a/platforms/android/cordova/lib/start-emulator.bat b/platforms/android/cordova/lib/start-emulator.bat
new file mode 100644
index 0000000..6c237ea
--- /dev/null
+++ b/platforms/android/cordova/lib/start-emulator.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0start-emulator"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/log b/platforms/android/cordova/log
new file mode 100755
index 0000000..6829f28
--- /dev/null
+++ b/platforms/android/cordova/log
@@ -0,0 +1,36 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var log = require('./lib/log');
+var reqs = require('./lib/check_reqs');
+var args = process.argv;
+
+// Usage support for when args are given
+if (args.length > 2) {
+    log.help();
+} else {
+    reqs.run().done(function () {
+        return log.run();
+    }, function (err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+}
diff --git a/platforms/android/cordova/log.bat b/platforms/android/cordova/log.bat
new file mode 100644
index 0000000..4b2b434
--- /dev/null
+++ b/platforms/android/cordova/log.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0log"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'log' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/loggingHelper.js b/platforms/android/cordova/loggingHelper.js
new file mode 100644
index 0000000..32b2ee0
--- /dev/null
+++ b/platforms/android/cordova/loggingHelper.js
@@ -0,0 +1,18 @@
+var CordovaLogger = require('cordova-common').CordovaLogger;
+
+module.exports = {
+    adjustLoggerLevel: function (opts) {
+        if (opts instanceof Array) {
+            opts.silent = opts.indexOf('--silent') !== -1;
+            opts.verbose = opts.indexOf('--verbose') !== -1;
+        }
+
+        if (opts.silent) {
+            CordovaLogger.get().setLevel('error');
+        }
+
+        if (opts.verbose) {
+            CordovaLogger.get().setLevel('verbose');
+        }
+    }
+};
diff --git a/platforms/android/cordova/run b/platforms/android/cordova/run
new file mode 100755
index 0000000..a3d6f53
--- /dev/null
+++ b/platforms/android/cordova/run
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var Api = require('./Api');
+var nopt = require('nopt');
+var path = require('path');
+
+// Support basic help commands
+if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
+    require('./lib/run').help();
+}
+
+// Do some basic argument parsing
+var runOpts = nopt({
+    'verbose': Boolean,
+    'silent': Boolean,
+    'debug': Boolean,
+    'release': Boolean,
+    'nobuild': Boolean,
+    'buildConfig': path,
+    'archs': String,
+    'device': Boolean,
+    'emulator': Boolean,
+    'target': String
+}, { 'd': '--verbose' });
+
+// Make runOptions compatible with PlatformApi run method spec
+runOpts.argv = runOpts.argv.remain;
+
+require('./loggingHelper').adjustLoggerLevel(runOpts);
+
+new Api().run(runOpts)
+    .catch(function (err) {
+        console.error(err, err.stack);
+        process.exit(2);
+    });
diff --git a/platforms/android/cordova/run.bat b/platforms/android/cordova/run.bat
new file mode 100644
index 0000000..b0bc28b
--- /dev/null
+++ b/platforms/android/cordova/run.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0run"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'run' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/android/cordova/version b/platforms/android/cordova/version
new file mode 100755
index 0000000..299fce6
--- /dev/null
+++ b/platforms/android/cordova/version
@@ -0,0 +1,29 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+// Coho updates this line:
+var VERSION = "8.0.0";
+
+module.exports.version = VERSION;
+
+if (!module.parent) {
+    console.log(VERSION);
+}
diff --git a/platforms/android/cordova/version.bat b/platforms/android/cordova/version.bat
new file mode 100644
index 0000000..3610c17
--- /dev/null
+++ b/platforms/android/cordova/version.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0version"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/android/gradle.properties b/platforms/android/gradle.properties
new file mode 100644
index 0000000..11bc459
--- /dev/null
+++ b/platforms/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.daemon=true
+org.gradle.jvmargs=-Xmx2048m
+android.useDeprecatedNdk=true
\ No newline at end of file
diff --git a/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js b/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js
new file mode 100644
index 0000000..2e9aa67
--- /dev/null
+++ b/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js
@@ -0,0 +1,36 @@
+/*
+ * 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.
+*/
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
diff --git a/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js b/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js
new file mode 100644
index 0000000..f7fb6bc
--- /dev/null
+++ b/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js
@@ -0,0 +1,35 @@
+/*
+ * 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.
+*/
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
diff --git a/platforms/android/platform_www/cordova-js-src/exec.js b/platforms/android/platform_www/cordova-js-src/exec.js
new file mode 100644
index 0000000..39e8c97
--- /dev/null
+++ b/platforms/android/platform_www/cordova-js-src/exec.js
@@ -0,0 +1,286 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1
+    },
+    nativeToJsModes = {
+        // Polls for messages using the JS->Native bridge.
+        POLLING: 0,
+        // For LOAD_URL to be viable, it would need to have a work-around for
+        // the bug where the soft-keyboard gets dismissed when a message is sent.
+        LOAD_URL: 1,
+        // For the ONLINE_EVENT to be viable, it would need to intercept all event
+        // listeners (both through addEventListener and window.ononline) as well
+        // as set the navigator property itself.
+        ONLINE_EVENT: 2,
+        EVAL_BRIDGE: 3
+    },
+    jsToNativeBridgeMode,  // Set lazily.
+    nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
+    pollEnabled = false,
+    bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
+
+function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
+    // Set default bridge modes if they have not already been set.
+    // By default, we use the failsafe, since addJavascriptInterface breaks too often
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    }
+
+    // If args is not provided, default to an empty array
+    args = args || [];
+
+    // Process any ArrayBuffers in the args into a string.
+    for (var i = 0; i < args.length; i++) {
+        if (utils.typeName(args[i]) == 'ArrayBuffer') {
+            args[i] = base64.fromArrayBuffer(args[i]);
+        }
+    }
+
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
+
+    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    } else if (msgs) {
+        messagesFromNative.push(msgs);
+        // Always process async to avoid exceptions messing up stack.
+        nextTick(processMessages);
+    }
+}
+
+androidExec.init = function() {
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
+
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+    if (msgs) {
+        messagesFromNative.push(msgs);
+        // Process sync since we know we're already top-of-stack.
+        processMessages();
+    }
+}
+
+function pollingTimerFunc() {
+    if (pollEnabled) {
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
+    }
+}
+
+function hookOnlineApis() {
+    function proxyEvent(e) {
+        cordova.fireWindowEvent(e.type);
+    }
+    // The network module takes care of firing online and offline events.
+    // It currently fires them only on document though, so we bridge them
+    // to window here (while first listening for exec()-releated online/offline
+    // events).
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+    cordova.addWindowEventHandler('online');
+    cordova.addWindowEventHandler('offline');
+    document.addEventListener('online', proxyEvent, false);
+    document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+        mode = jsToNativeModes.PROMPT;
+    }
+    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
+    jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
+        pollEnabled = false;
+    }
+
+    nativeToJsBridgeMode = mode;
+    // Tell the native side to switch modes.
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
+
+    if (mode == nativeToJsModes.POLLING) {
+        pollEnabled = true;
+        setTimeout(pollingTimerFunc, 1);
+    }
+};
+
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        payload.push(base64.toArrayBuffer(data));
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    var firstChar = message.charAt(0);
+    if (firstChar == 'J') {
+        // This is deprecated on the .java side. It doesn't work with CSP enabled.
+        eval(message.slice(1));
+    } else if (firstChar == 'S' || firstChar == 'F') {
+        var success = firstChar == 'S';
+        var keepCallback = message.charAt(1) == '1';
+        var spaceIdx = message.indexOf(' ', 2);
+        var status = +message.slice(2, spaceIdx);
+        var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+        var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+        var payloadMessage = message.slice(nextSpaceIdx + 1);
+        var payload = [];
+        buildPayload(payload, payloadMessage);
+        cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+    } else {
+        console.log("processMessage failed: invalid message: " + JSON.stringify(message));
+    }
+}
+
+function processMessages() {
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (messagesFromNative.length === 0) {
+        return;
+    }
+    isProcessing = true;
+    try {
+        var msg = popMessageFromQueue();
+        // The Java side can send a * message to indicate that it
+        // still has messages waiting to be retrieved.
+        if (msg == '*' && messagesFromNative.length === 0) {
+            nextTick(pollOnce);
+            return;
+        }
+        processMessage(msg);
+    } finally {
+        isProcessing = false;
+        if (messagesFromNative.length > 0) {
+            nextTick(processMessages);
+        }
+    }
+}
+
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
+module.exports = androidExec;
diff --git a/platforms/android/platform_www/cordova-js-src/platform.js b/platforms/android/platform_www/cordova-js-src/platform.js
new file mode 100644
index 0000000..2bfd024
--- /dev/null
+++ b/platforms/android/platform_www/cordova-js-src/platform.js
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+    id: 'android',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
+
+        // Get the shared secret needed to use the bridge.
+        exec.init();
+
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+        var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+        // Inject a listener for the backbutton on the document.
+        var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+        backButtonChannel.onHasSubscribersChange = function() {
+            // If we just attached the first handler or detached the last handler,
+            // let native know we need to override the back button.
+            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
+        };
+
+        // Add hardware MENU and SEARCH button handlers
+        cordova.addDocumentEventHandler('menubutton');
+        cordova.addDocumentEventHandler('searchbutton');
+
+        function bindButtonChannel(buttonName) {
+            // generic button bind used for volumeup/volumedown buttons
+            var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+            volumeButtonChannel.onHasSubscribersChange = function() {
+                exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
+            };
+        }
+        // Inject a listener for the volume buttons on the document.
+        bindButtonChannel('volumeup');
+        bindButtonChannel('volumedown');
+
+        // The resume event is not "sticky", but it is possible that the event
+        // will contain the result of a plugin call. We need to ensure that the
+        // plugin result is delivered even after the event is fired (CB-10498)
+        var cordovaAddEventListener = document.addEventListener;
+
+        document.addEventListener = function(evt, handler, capture) {
+            cordovaAddEventListener(evt, handler, capture);
+
+            if (evt === 'resume' && lastResumeEvent) {
+                handler(lastResumeEvent);
+            }
+        };
+
+        // Let native code know we are all done on the JS side.
+        // Native code will then un-hide the WebView.
+        channel.onCordovaReady.subscribe(function() {
+            exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+            exec(null, null, APP_PLUGIN_NAME, "show", []);
+        });
+    }
+};
+
+function onMessageFromNative(msg) {
+    var cordova = require('cordova');
+    var action = msg.action;
+
+    switch (action)
+    {
+        // Button events
+        case 'backbutton':
+        case 'menubutton':
+        case 'searchbutton':
+        // App life cycle events
+        case 'pause':
+        // Volume events
+        case 'volumedownbutton':
+        case 'volumeupbutton':
+            cordova.fireDocumentEvent(action);
+            break;
+        case 'resume':
+            if(arguments.length > 1 && msg.pendingResult) {
+                if(arguments.length === 2) {
+                    msg.pendingResult.result = arguments[1];
+                } else {
+                    // The plugin returned a multipart message
+                    var res = [];
+                    for(var i = 1; i < arguments.length; i++) {
+                        res.push(arguments[i]);
+                    }
+                    msg.pendingResult.result = res;
+                }
+
+                // Save the plugin result so that it can be delivered to the js
+                // even if they miss the initial firing of the event
+                lastResumeEvent = msg;
+            }
+            cordova.fireDocumentEvent(action, msg);
+            break;
+        default:
+            throw new Error('Unknown event action ' + action);
+    }
+}
diff --git a/platforms/android/platform_www/cordova-js-src/plugin/android/app.js b/platforms/android/platform_www/cordova-js-src/plugin/android/app.js
new file mode 100644
index 0000000..22cf96e
--- /dev/null
+++ b/platforms/android/platform_www/cordova-js-src/plugin/android/app.js
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
+    },
+
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
+    },
+
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
+    },
+
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
+    },
+
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
+    },
+
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
+    },
+
+    /**
+    * Override the default behavior of the Android volume button.
+    * If overridden, when the volume button is pressed, the "volume[up|down]button"
+    * JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "volume[up|down]button" event, this is automatically done.
+    *
+    * @param button          volumeup, volumedown
+    * @param override        T=override, F=cancel override
+    */
+    overrideButton:function(button, override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
+    },
+
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
+    }
+};
diff --git a/platforms/android/platform_www/cordova.js b/platforms/android/platform_www/cordova.js
new file mode 100644
index 0000000..0f2d2e6
--- /dev/null
+++ b/platforms/android/platform_www/cordova.js
@@ -0,0 +1,1908 @@
+// Platform: android
+// 882658ab17740dbdece764e68c1f1f1f44fe3f9d
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '8.0.0';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+            'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+var cordova = require('cordova'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
+    jsToNativeModes = {
+        PROMPT: 0,
+        JS_OBJECT: 1
+    },
+    nativeToJsModes = {
+        // Polls for messages using the JS->Native bridge.
+        POLLING: 0,
+        // For LOAD_URL to be viable, it would need to have a work-around for
+        // the bug where the soft-keyboard gets dismissed when a message is sent.
+        LOAD_URL: 1,
+        // For the ONLINE_EVENT to be viable, it would need to intercept all event
+        // listeners (both through addEventListener and window.ononline) as well
+        // as set the navigator property itself.
+        ONLINE_EVENT: 2,
+        EVAL_BRIDGE: 3
+    },
+    jsToNativeBridgeMode,  // Set lazily.
+    nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
+    pollEnabled = false,
+    bridgeSecret = -1;
+
+var messagesFromNative = [];
+var isProcessing = false;
+var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
+var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
+
+function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
+    // Set default bridge modes if they have not already been set.
+    // By default, we use the failsafe, since addJavascriptInterface breaks too often
+    if (jsToNativeBridgeMode === undefined) {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    }
+
+    // If args is not provided, default to an empty array
+    args = args || [];
+
+    // Process any ArrayBuffers in the args into a string.
+    for (var i = 0; i < args.length; i++) {
+        if (utils.typeName(args[i]) == 'ArrayBuffer') {
+            args[i] = base64.fromArrayBuffer(args[i]);
+        }
+    }
+
+    var callbackId = service + cordova.callbackId++,
+        argsJson = JSON.stringify(args);
+    if (success || fail) {
+        cordova.callbacks[callbackId] = {success:success, fail:fail};
+    }
+
+    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+    } else if (msgs) {
+        messagesFromNative.push(msgs);
+        // Always process async to avoid exceptions messing up stack.
+        nextTick(processMessages);
+    }
+}
+
+androidExec.init = function() {
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
+
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
+    if (msgs) {
+        messagesFromNative.push(msgs);
+        // Process sync since we know we're already top-of-stack.
+        processMessages();
+    }
+}
+
+function pollingTimerFunc() {
+    if (pollEnabled) {
+        pollOnce();
+        setTimeout(pollingTimerFunc, 50);
+    }
+}
+
+function hookOnlineApis() {
+    function proxyEvent(e) {
+        cordova.fireWindowEvent(e.type);
+    }
+    // The network module takes care of firing online and offline events.
+    // It currently fires them only on document though, so we bridge them
+    // to window here (while first listening for exec()-releated online/offline
+    // events).
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
+    cordova.addWindowEventHandler('online');
+    cordova.addWindowEventHandler('offline');
+    document.addEventListener('online', proxyEvent, false);
+    document.addEventListener('offline', proxyEvent, false);
+}
+
+hookOnlineApis();
+
+androidExec.jsToNativeModes = jsToNativeModes;
+androidExec.nativeToJsModes = nativeToJsModes;
+
+androidExec.setJsToNativeBridgeMode = function(mode) {
+    if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
+        mode = jsToNativeModes.PROMPT;
+    }
+    nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
+    jsToNativeBridgeMode = mode;
+};
+
+androidExec.setNativeToJsBridgeMode = function(mode) {
+    if (mode == nativeToJsBridgeMode) {
+        return;
+    }
+    if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
+        pollEnabled = false;
+    }
+
+    nativeToJsBridgeMode = mode;
+    // Tell the native side to switch modes.
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
+
+    if (mode == nativeToJsModes.POLLING) {
+        pollEnabled = true;
+        setTimeout(pollingTimerFunc, 1);
+    }
+};
+
+function buildPayload(payload, message) {
+    var payloadKind = message.charAt(0);
+    if (payloadKind == 's') {
+        payload.push(message.slice(1));
+    } else if (payloadKind == 't') {
+        payload.push(true);
+    } else if (payloadKind == 'f') {
+        payload.push(false);
+    } else if (payloadKind == 'N') {
+        payload.push(null);
+    } else if (payloadKind == 'n') {
+        payload.push(+message.slice(1));
+    } else if (payloadKind == 'A') {
+        var data = message.slice(1);
+        payload.push(base64.toArrayBuffer(data));
+    } else if (payloadKind == 'S') {
+        payload.push(window.atob(message.slice(1)));
+    } else if (payloadKind == 'M') {
+        var multipartMessages = message.slice(1);
+        while (multipartMessages !== "") {
+            var spaceIdx = multipartMessages.indexOf(' ');
+            var msgLen = +multipartMessages.slice(0, spaceIdx);
+            var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
+            multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
+            buildPayload(payload, multipartMessage);
+        }
+    } else {
+        payload.push(JSON.parse(message));
+    }
+}
+
+// Processes a single message, as encoded by NativeToJsMessageQueue.java.
+function processMessage(message) {
+    var firstChar = message.charAt(0);
+    if (firstChar == 'J') {
+        // This is deprecated on the .java side. It doesn't work with CSP enabled.
+        eval(message.slice(1));
+    } else if (firstChar == 'S' || firstChar == 'F') {
+        var success = firstChar == 'S';
+        var keepCallback = message.charAt(1) == '1';
+        var spaceIdx = message.indexOf(' ', 2);
+        var status = +message.slice(2, spaceIdx);
+        var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
+        var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
+        var payloadMessage = message.slice(nextSpaceIdx + 1);
+        var payload = [];
+        buildPayload(payload, payloadMessage);
+        cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
+    } else {
+        console.log("processMessage failed: invalid message: " + JSON.stringify(message));
+    }
+}
+
+function processMessages() {
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (messagesFromNative.length === 0) {
+        return;
+    }
+    isProcessing = true;
+    try {
+        var msg = popMessageFromQueue();
+        // The Java side can send a * message to indicate that it
+        // still has messages waiting to be retrieved.
+        if (msg == '*' && messagesFromNative.length === 0) {
+            nextTick(pollOnce);
+            return;
+        }
+        processMessage(msg);
+    } finally {
+        isProcessing = false;
+        if (messagesFromNative.length > 0) {
+            nextTick(processMessages);
+        }
+    }
+}
+
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
+module.exports = androidExec;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+// The last resume event that was received that had the result of a plugin call.
+var lastResumeEvent = null;
+
+module.exports = {
+    id: 'android',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
+            cordova = require('cordova'),
+            exec = require('cordova/exec'),
+            modulemapper = require('cordova/modulemapper');
+
+        // Get the shared secret needed to use the bridge.
+        exec.init();
+
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+
+        var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+        // Inject a listener for the backbutton on the document.
+        var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
+        backButtonChannel.onHasSubscribersChange = function() {
+            // If we just attached the first handler or detached the last handler,
+            // let native know we need to override the back button.
+            exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
+        };
+
+        // Add hardware MENU and SEARCH button handlers
+        cordova.addDocumentEventHandler('menubutton');
+        cordova.addDocumentEventHandler('searchbutton');
+
+        function bindButtonChannel(buttonName) {
+            // generic button bind used for volumeup/volumedown buttons
+            var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
+            volumeButtonChannel.onHasSubscribersChange = function() {
+                exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
+            };
+        }
+        // Inject a listener for the volume buttons on the document.
+        bindButtonChannel('volumeup');
+        bindButtonChannel('volumedown');
+
+        // The resume event is not "sticky", but it is possible that the event
+        // will contain the result of a plugin call. We need to ensure that the
+        // plugin result is delivered even after the event is fired (CB-10498)
+        var cordovaAddEventListener = document.addEventListener;
+
+        document.addEventListener = function(evt, handler, capture) {
+            cordovaAddEventListener(evt, handler, capture);
+
+            if (evt === 'resume' && lastResumeEvent) {
+                handler(lastResumeEvent);
+            }
+        };
+
+        // Let native code know we are all done on the JS side.
+        // Native code will then un-hide the WebView.
+        channel.onCordovaReady.subscribe(function() {
+            exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
+            exec(null, null, APP_PLUGIN_NAME, "show", []);
+        });
+    }
+};
+
+function onMessageFromNative(msg) {
+    var cordova = require('cordova');
+    var action = msg.action;
+
+    switch (action)
+    {
+        // Button events
+        case 'backbutton':
+        case 'menubutton':
+        case 'searchbutton':
+        // App life cycle events
+        case 'pause':
+        // Volume events
+        case 'volumedownbutton':
+        case 'volumeupbutton':
+            cordova.fireDocumentEvent(action);
+            break;
+        case 'resume':
+            if(arguments.length > 1 && msg.pendingResult) {
+                if(arguments.length === 2) {
+                    msg.pendingResult.result = arguments[1];
+                } else {
+                    // The plugin returned a multipart message
+                    var res = [];
+                    for(var i = 1; i < arguments.length; i++) {
+                        res.push(arguments[i]);
+                    }
+                    msg.pendingResult.result = res;
+                }
+
+                // Save the plugin result so that it can be delivered to the js
+                // even if they miss the initial firing of the event
+                lastResumeEvent = msg;
+            }
+            cordova.fireDocumentEvent(action, msg);
+            break;
+        default:
+            throw new Error('Unknown event action ' + action);
+    }
+}
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-android/cordova-js-src/plugin/android/app.js
+define("cordova/plugin/android/app", function(require, exports, module) {
+
+var exec = require('cordova/exec');
+var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
+
+module.exports = {
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
+    },
+
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
+    },
+
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
+    },
+
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
+    },
+
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
+    },
+
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
+    },
+
+    /**
+    * Override the default behavior of the Android volume button.
+    * If overridden, when the volume button is pressed, the "volume[up|down]button"
+    * JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "volume[up|down]button" event, this is automatically done.
+    *
+    * @param button          volumeup, volumedown
+    * @param override        T=override, F=cancel override
+    */
+    overrideButton:function(button, override) {
+        exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
+    },
+
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
+    }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/android/platform_www/cordova_plugins.js b/platforms/android/platform_www/cordova_plugins.js
new file mode 100644
index 0000000..049ccd6
--- /dev/null
+++ b/platforms/android/platform_www/cordova_plugins.js
@@ -0,0 +1,339 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+  module.exports = [
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.androidFileSystem",
+      "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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-inappbrowser.inappbrowser",
+      "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+      "pluginId": "cordova-plugin-inappbrowser",
+      "clobbers": [
+        "cordova.InAppBrowser.open",
+        "window.open"
+      ]
+    },
+    {
+      "id": "cordova-plugin-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ];
+  module.exports.metadata = {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  };
+});
\ No newline at end of file
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..5faece0
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,23 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) {
+/*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..e7cdb39
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,73 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) {
+module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+  var storeKey = '__advancedHttpCookieStore__';
+
+  var store = new WebStorageCookieStore(storage, storeKey);
+  var cookieJar = new ToughCookie.CookieJar(store);
+
+  return {
+    setCookieFromString: setCookieFromString,
+    setCookie: setCookie,
+    getCookieString: getCookieString,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies
+  };
+
+  function splitCookieString(cookieStr) {
+    var cookieParts = cookieStr.split(',');
+    var splitCookies = [];
+    var processedCookie = null;
+
+    for (var i = 0; i < cookieParts.length; ++i) {
+      if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+        processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+        i++;
+      } else {
+        processedCookie = cookieParts[i];
+      }
+
+      processedCookie = processedCookie.trim();
+      splitCookies.push(processedCookie);
+    }
+
+    return splitCookies;
+  }
+
+  function setCookieFromString(url, cookieStr) {
+    if (!cookieStr) return;
+
+    var cookies = splitCookieString(cookieStr);
+
+    for (var i = 0; i < cookies.length; ++i) {
+      cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+    }
+  }
+
+  function setCookie(url, cookie, options) {
+    options = options || {};
+    options.ignoreError = false;
+    cookieJar.setCookieSync(cookie, url, options);
+  }
+
+  function getCookieString(url) {
+    return cookieJar.getCookieStringSync(url);
+  }
+
+  function clearCookies() {
+    window.localStorage.removeItem(storeKey);
+  }
+
+  function removeCookies(url, cb) {
+    cookieJar.getCookies(url, function (error, cookies) {
+      if (!cookies || cookies.length === 0) {
+        return cb(null, []);
+      }
+
+      var domain = cookies[0].domain;
+
+      cookieJar.store.removeCookies(domain, null, cb);
+    });
+  }
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..5e85416
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,11 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) {
+var globalConfigs = {
+  headers: {},
+  serializer: 'urlencoded',
+  followRedirect: true,
+  timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..855e84c
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,353 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) {
+module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+  var validSerializers = ['urlencoded', 'json', 'utf8'];
+  var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+  var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+  var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+  var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+  var interface = {
+    b64EncodeUnicode: b64EncodeUnicode,
+    checkSerializer: checkSerializer,
+    checkSSLCertMode: checkSSLCertMode,
+    checkClientAuthMode: checkClientAuthMode,
+    checkClientAuthOptions: checkClientAuthOptions,
+    checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+    checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+    checkTimeoutValue: checkTimeoutValue,
+    checkFollowRedirectValue: checkFollowRedirectValue,
+    injectCookieHandler: injectCookieHandler,
+    injectRawResponseHandler: injectRawResponseHandler,
+    injectFileEntryHandler: injectFileEntryHandler,
+    getMergedHeaders: getMergedHeaders,
+    getProcessedData: getProcessedData,
+    handleMissingCallbacks: handleMissingCallbacks,
+    handleMissingOptions: handleMissingOptions
+  };
+
+  // expose all functions for testing purposes
+  if (init.debug) {
+    interface.mergeHeaders = mergeHeaders;
+    interface.checkForValidStringValue = checkForValidStringValue;
+    interface.checkKeyValuePairObject = checkKeyValuePairObject;
+    interface.checkHttpMethod = checkHttpMethod;
+    interface.checkResponseType = checkResponseType;
+    interface.checkHeadersObject = checkHeadersObject;
+    interface.checkParamsObject = checkParamsObject;
+    interface.resolveCookieString = resolveCookieString;
+    interface.createFileEntry = createFileEntry;
+    interface.getCookieHeader = getCookieHeader;
+    interface.getMatchingHostHeaders = getMatchingHostHeaders;
+    interface.getAllowedDataTypes = getAllowedDataTypes;
+  }
+
+  return interface;
+
+  // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+  function b64EncodeUnicode(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode('0x' + p1);
+    }));
+  }
+
+  function mergeHeaders(globalHeaders, localHeaders) {
+    var globalKeys = Object.keys(globalHeaders);
+    var key;
+
+    for (var i = 0; i < globalKeys.length; i++) {
+      key = globalKeys[i];
+
+      if (!localHeaders.hasOwnProperty(key)) {
+        localHeaders[key] = globalHeaders[key];
+      }
+    }
+
+    return localHeaders;
+  }
+
+  function checkForValidStringValue(list, value, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    value = value.trim().toLowerCase();
+
+    if (list.indexOf(value) === -1) {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    return value;
+  }
+
+  function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(obj) !== 'Object') {
+      throw new Error(onInvalidValueMessage);
+    }
+
+    var keys = Object.keys(obj);
+
+    for (var i = 0; i < keys.length; i++) {
+      if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+        throw new Error(onInvalidValueMessage);
+      }
+    }
+
+    return obj;
+  }
+
+  function checkHttpMethod(method) {
+    return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+  }
+
+  function checkResponseType(type) {
+    return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+  }
+
+  function checkSerializer(serializer) {
+    return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+  }
+
+  function checkSSLCertMode(mode) {
+    return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+  }
+
+  function checkClientAuthMode(mode) {
+    return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+  }
+
+  function checkClientAuthOptions(mode, options) {
+    options = options || {};
+
+    // none
+    if (mode === validClientAuthModes[0]) {
+      return {
+        alias: null,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    if (jsUtil.getTypeOf(options) !== 'Object') {
+      throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+    }
+
+    // systemstore
+    if (mode === validClientAuthModes[1]) {
+      if (jsUtil.getTypeOf(options.alias) !== 'String'
+        && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+      }
+
+      return {
+        alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    // buffer
+    if (mode === validClientAuthModes[2]) {
+      if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+      }
+
+      if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+      }
+
+      return {
+        alias: null,
+        rawPkcs: options.rawPkcs,
+        pkcsPassword: options.pkcsPassword
+      }
+    }
+  }
+
+  function checkForBlacklistedHeaderKey(key) {
+    if (key.toLowerCase() === 'cookie') {
+      throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+    }
+
+    return key;
+  }
+
+  function checkForInvalidHeaderValue(value) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(messages.INVALID_HEADERS_VALUE);
+    }
+
+    return value;
+  }
+
+  function checkTimeoutValue(timeout) {
+    if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+      throw new Error(messages.INVALID_TIMEOUT_VALUE);
+    }
+
+    return timeout;
+  }
+
+  function checkFollowRedirectValue(follow) {
+    if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+      throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+    }
+
+    return follow;
+  }
+
+  function checkHeadersObject(headers) {
+    return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+  }
+
+  function checkParamsObject(params) {
+    return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+  }
+
+  function resolveCookieString(headers) {
+    var keys = Object.keys(headers || {});
+
+    for (var i = 0; i < keys.length; ++i) {
+      if (keys[i].match(/^set-cookie$/i)) {
+        return headers[keys[i]];
+      }
+    }
+
+    return null;
+  }
+
+  function createFileEntry(rawEntry) {
+    var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+    entry.isDirectory = rawEntry.isDirectory;
+    entry.isFile = rawEntry.isFile;
+    entry.name = rawEntry.name;
+    entry.fullPath = rawEntry.fullPath;
+    entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+    entry.nativeURL = rawEntry.nativeURL;
+
+    return entry;
+  }
+
+  function injectCookieHandler(url, cb) {
+    return function (response) {
+      cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+      cb(response);
+    }
+  }
+
+  function injectRawResponseHandler(responseType, cb) {
+    return function (response) {
+      var dataType = jsUtil.getTypeOf(response.data);
+
+      // don't need post-processing if it's already binary type (on browser platform)
+      if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+        return cb(response);
+      }
+
+      // arraybuffer
+      if (responseType === validResponseTypes[1]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        response.data = buffer;
+      }
+
+      // blob
+      if (responseType === validResponseTypes[2]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        var type = response.headers['content-type'] || '';
+        var blob = new Blob([ buffer ], { type: type });
+        response.data = blob;
+      }
+
+      cb(response);
+    }
+  }
+
+  function injectFileEntryHandler(cb) {
+    return function (response) {
+      cb(createFileEntry(response.file));
+    }
+  }
+
+  function getCookieHeader(url) {
+    var cookieString = cookieHandler.getCookieString(url);
+
+    if (cookieString.length) {
+      return { Cookie: cookieHandler.getCookieString(url) };
+    }
+
+    return {};
+  }
+
+  function getMatchingHostHeaders(url, headersList) {
+    var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+    var domain = matches && matches[1];
+
+    return headersList[domain] || null;
+  }
+
+  function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+    var globalHeaders = predefinedHeaders['*'] || {};
+    var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+    var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+    mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+    mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+    return mergedHeaders;
+  }
+
+  function getAllowedDataTypes(dataSerializer) {
+    switch (dataSerializer) {
+      case 'utf8':
+        return ['String'];
+      case 'urlencoded':
+        return ['Object'];
+      default:
+        return ['Array', 'Object'];
+    }
+  }
+
+  function getProcessedData(data, dataSerializer) {
+    var currentDataType = jsUtil.getTypeOf(data);
+    var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+    if (allowedDataTypes.indexOf(currentDataType) === -1) {
+      throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+    }
+
+    if (dataSerializer === 'utf8') {
+      data = { text: data };
+    }
+
+    return data;
+  }
+
+  function handleMissingCallbacks(successFn, failFn) {
+    if (jsUtil.getTypeOf(successFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_SUCCESS);
+    }
+
+    if (jsUtil.getTypeOf(failFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_FAIL);
+    }
+  }
+
+  function handleMissingOptions(options, globals) {
+    options = options || {};
+
+    return {
+      method: checkHttpMethod(options.method || validHttpMethods[0]),
+      responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+      serializer: checkSerializer(options.serializer || globals.serializer),
+      timeout: checkTimeoutValue(options.timeout || globals.timeout),
+      followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+      headers: checkHeadersObject(options.headers || {}),
+      params: checkParamsObject(options.params || {}),
+      data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+      filePath: options.filePath || '',
+      name: options.name || ''
+    };
+  }
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..cbe1c51
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) {
+module.exports = {
+  // typeof is not working reliably in JS
+  getTypeOf: function (object) {
+    switch (Object.prototype.toString.call(object)) {
+      case '[object Array]':
+        return 'Array';
+      case '[object Blob]':
+        return 'Blob';
+      case '[object ArrayBuffer]':
+        return 'ArrayBuffer';
+      case '[object Boolean]':
+        return 'Boolean';
+      case '[object Function]':
+        return 'Function';
+      case '[object Null]':
+        return 'Null';
+      case '[object Number]':
+        return 'Number';
+      case '[object Object]':
+        return 'Object';
+      case '[object String]':
+        return 'String';
+      case '[object Undefined]':
+        return 'Undefined';
+      default:
+        return 'Unknown';
+    }
+  }
+}
+
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..800c6b7
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,184 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) {
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+  function WebStorageCookieStore(storage, storeKey) {
+    ToughCookie.Store.call(this);
+    this._storage = storage;
+    this._storeKey = storeKey || '__cookieStore__';
+    this.synchronous = true;
+  }
+
+  WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+  WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+    var cookie = _.get(store, [domain, path, key], null);
+
+    callback(null, ToughCookie.Cookie.fromJSON(cookie));
+  };
+
+  WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+    if (!domain) {
+      callback(null, []);
+      return;
+    }
+
+    var that = this;
+    var cookies = [];
+    var store = this._readStore();
+    var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+    domains.forEach(function (domain) {
+      if (!store[domain]) {
+        return;
+      }
+
+      var matchingPaths = Object.keys(store[domain]);
+
+      if (path != null) {
+        matchingPaths = matchingPaths.filter(function (cookiePath) {
+          return that._isOnPath(cookiePath, path);
+        });
+      }
+
+      matchingPaths.forEach(function (path) {
+        Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    callback(null, cookies);
+  };
+
+  /**
+   * Returns whether `cookiePath` is on the given `urlPath`
+   */
+  WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+    if (!cookiePath) {
+      return false;
+    }
+
+    if (cookiePath === urlPath) {
+      return true;
+    }
+
+    if (urlPath.indexOf(cookiePath) !== 0) {
+      return false;
+    }
+
+    if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+      return false;
+    }
+
+    return true;
+  };
+
+  WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+    var store = this._readStore();
+
+    _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+    this.putCookie(newCookie, callback);
+  };
+
+
+  WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+
+    _.unset(store, [domain, path, key]);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+    var store = this._readStore();
+
+    if (path == null) {
+      _.unset(store, [domain]);
+    } else {
+      _.unset(store, [domain, path]);
+    }
+
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+    var cookies = [];
+    var store = this._readStore();
+
+    Object.keys(store).forEach(function (domain) {
+      Object.keys(store[domain]).forEach(function (path) {
+        Array.protype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    cookies.sort(function (c1, c2) {
+      return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+    });
+
+    callback(null, cookies);
+  };
+
+  WebStorageCookieStore.prototype._readStore = function () {
+    var json = this._storage.getItem(this._storeKey);
+
+    if (json !== null) {
+      try {
+        return JSON.parse(json);
+      } catch (e) { }
+    }
+
+    return {};
+  };
+
+  WebStorageCookieStore.prototype._writeStore = function (store) {
+    this._storage.setItem(this._storeKey, JSON.stringify(store));
+  };
+
+  return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..f35be77
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) {
+/**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..13efb2b
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) {
+module.exports = {
+  ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+  DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+  INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+  INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+  INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+  INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+  INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+  INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+  INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+  INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+  INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+  INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+  INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+  INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+  INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+  MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+  MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a77c8e0
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,202 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) {
+module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+  const publicInterface = {
+    getBasicAuthHeader: getBasicAuthHeader,
+    useBasicAuth: useBasicAuth,
+    getHeaders: getHeaders,
+    setHeader: setHeader,
+    getDataSerializer: getDataSerializer,
+    setDataSerializer: setDataSerializer,
+    setCookie: setCookie,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies,
+    getCookieString: getCookieString,
+    getRequestTimeout: getRequestTimeout,
+    setRequestTimeout: setRequestTimeout,
+    getFollowRedirect: getFollowRedirect,
+    setFollowRedirect: setFollowRedirect,
+    // @DEPRECATED
+    disableRedirect: disableRedirect,
+    // @DEPRECATED
+    setSSLCertMode: setServerTrustMode,
+    setServerTrustMode: setServerTrustMode,
+    setClientAuthMode: setClientAuthMode,
+    sendRequest: sendRequest,
+    post: post,
+    get: get,
+    put: put,
+    patch: patch,
+    delete: del,
+    head: head,
+    uploadFile: uploadFile,
+    downloadFile: downloadFile
+  };
+
+  function getBasicAuthHeader(username, password) {
+    return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+  }
+
+  function useBasicAuth(username, password) {
+    this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+  }
+
+  function getHeaders(host) {
+    return globalConfigs.headers[host || '*'] || null;
+  }
+
+  function setHeader() {
+    // this one is for being backward compatible
+    var host = '*';
+    var header = arguments[0];
+    var value = arguments[1];
+
+    if (arguments.length === 3) {
+      host = arguments[0];
+      header = arguments[1];
+      value = arguments[2];
+    }
+
+    helpers.checkForBlacklistedHeaderKey(header);
+    helpers.checkForInvalidHeaderValue(value);
+
+    globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+    globalConfigs.headers[host][header] = value;
+  }
+
+  function getDataSerializer() {
+    return globalConfigs.serializer;
+  }
+
+  function setDataSerializer(serializer) {
+    globalConfigs.serializer = helpers.checkSerializer(serializer);
+  }
+
+  function setCookie(url, cookie, options) {
+    cookieHandler.setCookie(url, cookie, options);
+  }
+
+  function clearCookies() {
+    cookieHandler.clearCookies();
+  }
+
+  function removeCookies(url, callback) {
+    cookieHandler.removeCookies(url, callback);
+  }
+
+  function getCookieString(url) {
+    return cookieHandler.getCookieString(url);
+  }
+
+  function getRequestTimeout() {
+    return globalConfigs.timeout;
+  }
+
+  function setRequestTimeout(timeout) {
+    globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+  }
+
+  function getFollowRedirect() {
+    return globalConfigs.followRedirect;
+  }
+
+  function setFollowRedirect(follow) {
+    globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+  }
+
+  // @DEPRECATED
+  function disableRedirect(disable, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    setFollowRedirect(!disable);
+    success();
+  }
+
+  function setServerTrustMode(mode, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+  }
+
+  function setClientAuthMode() {
+    var mode = arguments[0];
+    var options = null;
+    var success = arguments[1];
+    var failure = arguments[2];
+
+    if (arguments.length === 4) {
+      options = arguments[1];
+      success = arguments[2];
+      failure = arguments[3];
+    }
+
+    mode = helpers.checkClientAuthMode(mode);
+    options = helpers.checkClientAuthOptions(mode, options);
+
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+  }
+
+  function sendRequest(url, options, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    options = helpers.handleMissingOptions(options, globalConfigs);
+    url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+    var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+    var onFail = helpers.injectCookieHandler(url, failure);
+    var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+    switch (options.method) {
+      case 'post':
+      case 'put':
+      case 'patch':
+        var data = helpers.getProcessedData(options.data, options.serializer);
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+      case 'upload':
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+      case 'download':
+        var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+        return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+      default:
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+    }
+  }
+
+  function post(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+  };
+
+  function get(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+  };
+
+  function put(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+  }
+
+  function patch(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+  }
+
+  function del(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+  }
+
+  function head(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+  }
+
+  function uploadFile(url, params, headers, filePath, name, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+  }
+
+  function downloadFile(url, params, headers, filePath, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+  }
+
+  return publicInterface;
+}
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..bd8ab68
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5091 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) {
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["ToughCookie"] = factory();
+	else
+		root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var net = __webpack_require__(1);
+	var urlParse = __webpack_require__(2).parse;
+	var util = __webpack_require__(9);
+	var pubsuffix = __webpack_require__(13);
+	var Store = __webpack_require__(17).Store;
+	var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var VERSION = __webpack_require__(21).version;
+
+	var punycode;
+	try {
+	  punycode = __webpack_require__(15);
+	} catch(e) {
+	  console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+	}
+
+	// From RFC6265 S4.1.1
+	// note that it excludes \x3B ";"
+	var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+	var CONTROL_CHARS = /[\x00-\x1F]/;
+
+	// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+	// the "relaxed" mode, see:
+	// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+	var TERMINATORS = ['\n', '\r', '\0'];
+
+	// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+	// Note ';' is \x3B
+	var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+	// date-time parsing constants (RFC6265 S5.1.1)
+
+	var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+	var MONTH_TO_NUM = {
+	  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+	  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+	};
+	var NUM_TO_MONTH = [
+	  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+	];
+	var NUM_TO_DAY = [
+	  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+	];
+
+	var MAX_TIME = 2147483647000; // 31-bit max
+	var MIN_TIME = 0; // 31-bit min
+
+	/*
+	 * Parses a Natural number (i.e., non-negative integer) with either the
+	 *    <min>*<max>DIGIT ( non-digit *OCTET )
+	 * or
+	 *    <min>*<max>DIGIT
+	 * grammar (RFC6265 S5.1.1).
+	 *
+	 * The "trailingOK" boolean controls if the grammar accepts a
+	 * "( non-digit *OCTET )" trailer.
+	 */
+	function parseDigits(token, minDigits, maxDigits, trailingOK) {
+	  var count = 0;
+	  while (count < token.length) {
+	    var c = token.charCodeAt(count);
+	    // "non-digit = %x00-2F / %x3A-FF"
+	    if (c <= 0x2F || c >= 0x3A) {
+	      break;
+	    }
+	    count++;
+	  }
+
+	  // constrain to a minimum and maximum number of digits.
+	  if (count < minDigits || count > maxDigits) {
+	    return null;
+	  }
+
+	  if (!trailingOK && count != token.length) {
+	    return null;
+	  }
+
+	  return parseInt(token.substr(0,count), 10);
+	}
+
+	function parseTime(token) {
+	  var parts = token.split(':');
+	  var result = [0,0,0];
+
+	  /* RF6256 S5.1.1:
+	   *      time            = hms-time ( non-digit *OCTET )
+	   *      hms-time        = time-field ":" time-field ":" time-field
+	   *      time-field      = 1*2DIGIT
+	   */
+
+	  if (parts.length !== 3) {
+	    return null;
+	  }
+
+	  for (var i = 0; i < 3; i++) {
+	    // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+	    // followed by "( non-digit *OCTET )" so therefore the last time-field can
+	    // have a trailer
+	    var trailingOK = (i == 2);
+	    var num = parseDigits(parts[i], 1, 2, trailingOK);
+	    if (num === null) {
+	      return null;
+	    }
+	    result[i] = num;
+	  }
+
+	  return result;
+	}
+
+	function parseMonth(token) {
+	  token = String(token).substr(0,3).toLowerCase();
+	  var num = MONTH_TO_NUM[token];
+	  return num >= 0 ? num : null;
+	}
+
+	/*
+	 * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+	 */
+	function parseDate(str) {
+	  if (!str) {
+	    return;
+	  }
+
+	  /* RFC6265 S5.1.1:
+	   * 2. Process each date-token sequentially in the order the date-tokens
+	   * appear in the cookie-date
+	   */
+	  var tokens = str.split(DATE_DELIM);
+	  if (!tokens) {
+	    return;
+	  }
+
+	  var hour = null;
+	  var minute = null;
+	  var second = null;
+	  var dayOfMonth = null;
+	  var month = null;
+	  var year = null;
+
+	  for (var i=0; i<tokens.length; i++) {
+	    var token = tokens[i].trim();
+	    if (!token.length) {
+	      continue;
+	    }
+
+	    var result;
+
+	    /* 2.1. If the found-time flag is not set and the token matches the time
+	     * production, set the found-time flag and set the hour- value,
+	     * minute-value, and second-value to the numbers denoted by the digits in
+	     * the date-token, respectively.  Skip the remaining sub-steps and continue
+	     * to the next date-token.
+	     */
+	    if (second === null) {
+	      result = parseTime(token);
+	      if (result) {
+	        hour = result[0];
+	        minute = result[1];
+	        second = result[2];
+	        continue;
+	      }
+	    }
+
+	    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+	     * the day-of-month production, set the found-day-of- month flag and set
+	     * the day-of-month-value to the number denoted by the date-token.  Skip
+	     * the remaining sub-steps and continue to the next date-token.
+	     */
+	    if (dayOfMonth === null) {
+	      // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 1, 2, true);
+	      if (result !== null) {
+	        dayOfMonth = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.3. If the found-month flag is not set and the date-token matches the
+	     * month production, set the found-month flag and set the month-value to
+	     * the month denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (month === null) {
+	      result = parseMonth(token);
+	      if (result !== null) {
+	        month = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.4. If the found-year flag is not set and the date-token matches the
+	     * year production, set the found-year flag and set the year-value to the
+	     * number denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (year === null) {
+	      // "year = 2*4DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 2, 4, true);
+	      if (result !== null) {
+	        year = result;
+	        /* From S5.1.1:
+	         * 3.  If the year-value is greater than or equal to 70 and less
+	         * than or equal to 99, increment the year-value by 1900.
+	         * 4.  If the year-value is greater than or equal to 0 and less
+	         * than or equal to 69, increment the year-value by 2000.
+	         */
+	        if (year >= 70 && year <= 99) {
+	          year += 1900;
+	        } else if (year >= 0 && year <= 69) {
+	          year += 2000;
+	        }
+	      }
+	    }
+	  }
+
+	  /* RFC 6265 S5.1.1
+	   * "5. Abort these steps and fail to parse the cookie-date if:
+	   *     *  at least one of the found-day-of-month, found-month, found-
+	   *        year, or found-time flags is not set,
+	   *     *  the day-of-month-value is less than 1 or greater than 31,
+	   *     *  the year-value is less than 1601,
+	   *     *  the hour-value is greater than 23,
+	   *     *  the minute-value is greater than 59, or
+	   *     *  the second-value is greater than 59.
+	   *     (Note that leap seconds cannot be represented in this syntax.)"
+	   *
+	   * So, in order as above:
+	   */
+	  if (
+	    dayOfMonth === null || month === null || year === null || second === null ||
+	    dayOfMonth < 1 || dayOfMonth > 31 ||
+	    year < 1601 ||
+	    hour > 23 ||
+	    minute > 59 ||
+	    second > 59
+	  ) {
+	    return;
+	  }
+
+	  return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+	}
+
+	function formatDate(date) {
+	  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+	  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+	  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+	  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+	  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+	    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+	    h+':'+m+':'+s+' GMT';
+	}
+
+	// S5.1.2 Canonicalized Host Names
+	function canonicalDomain(str) {
+	  if (str == null) {
+	    return null;
+	  }
+	  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+	  // convert to IDN if any non-ASCII characters
+	  if (punycode && /[^\u0001-\u007f]/.test(str)) {
+	    str = punycode.toASCII(str);
+	  }
+
+	  return str.toLowerCase();
+	}
+
+	// S5.1.3 Domain Matching
+	function domainMatch(str, domStr, canonicalize) {
+	  if (str == null || domStr == null) {
+	    return null;
+	  }
+	  if (canonicalize !== false) {
+	    str = canonicalDomain(str);
+	    domStr = canonicalDomain(domStr);
+	  }
+
+	  /*
+	   * "The domain string and the string are identical. (Note that both the
+	   * domain string and the string will have been canonicalized to lower case at
+	   * this point)"
+	   */
+	  if (str == domStr) {
+	    return true;
+	  }
+
+	  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+	  /* "* The string is a host name (i.e., not an IP address)." */
+	  if (net.isIP(str)) {
+	    return false;
+	  }
+
+	  /* "* The domain string is a suffix of the string" */
+	  var idx = str.indexOf(domStr);
+	  if (idx <= 0) {
+	    return false; // it's a non-match (-1) or prefix (0)
+	  }
+
+	  // e.g "a.b.c".indexOf("b.c") === 2
+	  // 5 === 3+2
+	  if (str.length !== domStr.length + idx) { // it's not a suffix
+	    return false;
+	  }
+
+	  /* "* The last character of the string that is not included in the domain
+	  * string is a %x2E (".") character." */
+	  if (str.substr(idx-1,1) !== '.') {
+	    return false;
+	  }
+
+	  return true;
+	}
+
+
+	// RFC6265 S5.1.4 Paths and Path-Match
+
+	/*
+	 * "The user agent MUST use an algorithm equivalent to the following algorithm
+	 * to compute the default-path of a cookie:"
+	 *
+	 * Assumption: the path (and not query part or absolute uri) is passed in.
+	 */
+	function defaultPath(path) {
+	  // "2. If the uri-path is empty or if the first character of the uri-path is not
+	  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+	  if (!path || path.substr(0,1) !== "/") {
+	    return "/";
+	  }
+
+	  // "3. If the uri-path contains no more than one %x2F ("/") character, output
+	  // %x2F ("/") and skip the remaining step."
+	  if (path === "/") {
+	    return path;
+	  }
+
+	  var rightSlash = path.lastIndexOf("/");
+	  if (rightSlash === 0) {
+	    return "/";
+	  }
+
+	  // "4. Output the characters of the uri-path from the first character up to,
+	  // but not including, the right-most %x2F ("/")."
+	  return path.slice(0, rightSlash);
+	}
+
+	function trimTerminator(str) {
+	  for (var t = 0; t < TERMINATORS.length; t++) {
+	    var terminatorIdx = str.indexOf(TERMINATORS[t]);
+	    if (terminatorIdx !== -1) {
+	      str = str.substr(0,terminatorIdx);
+	    }
+	  }
+
+	  return str;
+	}
+
+	function parseCookiePair(cookiePair, looseMode) {
+	  cookiePair = trimTerminator(cookiePair);
+
+	  var firstEq = cookiePair.indexOf('=');
+	  if (looseMode) {
+	    if (firstEq === 0) { // '=' is immediately at start
+	      cookiePair = cookiePair.substr(1);
+	      firstEq = cookiePair.indexOf('='); // might still need to split on '='
+	    }
+	  } else { // non-loose mode
+	    if (firstEq <= 0) { // no '=' or is at start
+	      return; // needs to have non-empty "cookie-name"
+	    }
+	  }
+
+	  var cookieName, cookieValue;
+	  if (firstEq <= 0) {
+	    cookieName = "";
+	    cookieValue = cookiePair.trim();
+	  } else {
+	    cookieName = cookiePair.substr(0, firstEq).trim();
+	    cookieValue = cookiePair.substr(firstEq+1).trim();
+	  }
+
+	  if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+	    return;
+	  }
+
+	  var c = new Cookie();
+	  c.key = cookieName;
+	  c.value = cookieValue;
+	  return c;
+	}
+
+	function parse(str, options) {
+	  if (!options || typeof options !== 'object') {
+	    options = {};
+	  }
+	  str = str.trim();
+
+	  // We use a regex to parse the "name-value-pair" part of S5.2
+	  var firstSemi = str.indexOf(';'); // S5.2 step 1
+	  var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+	  var c = parseCookiePair(cookiePair, !!options.loose);
+	  if (!c) {
+	    return;
+	  }
+
+	  if (firstSemi === -1) {
+	    return c;
+	  }
+
+	  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+	  // (including the %x3B (";") in question)." plus later on in the same section
+	  // "discard the first ";" and trim".
+	  var unparsed = str.slice(firstSemi + 1).trim();
+
+	  // "If the unparsed-attributes string is empty, skip the rest of these
+	  // steps."
+	  if (unparsed.length === 0) {
+	    return c;
+	  }
+
+	  /*
+	   * S5.2 says that when looping over the items "[p]rocess the attribute-name
+	   * and attribute-value according to the requirements in the following
+	   * subsections" for every item.  Plus, for many of the individual attributes
+	   * in S5.3 it says to use the "attribute-value of the last attribute in the
+	   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
+	   * the previous value.
+	   */
+	  var cookie_avs = unparsed.split(';');
+	  while (cookie_avs.length) {
+	    var av = cookie_avs.shift().trim();
+	    if (av.length === 0) { // happens if ";;" appears
+	      continue;
+	    }
+	    var av_sep = av.indexOf('=');
+	    var av_key, av_value;
+
+	    if (av_sep === -1) {
+	      av_key = av;
+	      av_value = null;
+	    } else {
+	      av_key = av.substr(0,av_sep);
+	      av_value = av.substr(av_sep+1);
+	    }
+
+	    av_key = av_key.trim().toLowerCase();
+
+	    if (av_value) {
+	      av_value = av_value.trim();
+	    }
+
+	    switch(av_key) {
+	    case 'expires': // S5.2.1
+	      if (av_value) {
+	        var exp = parseDate(av_value);
+	        // "If the attribute-value failed to parse as a cookie date, ignore the
+	        // cookie-av."
+	        if (exp) {
+	          // over and underflow not realistically a concern: V8's getTime() seems to
+	          // store something larger than a 32-bit time_t (even with 32-bit node)
+	          c.expires = exp;
+	        }
+	      }
+	      break;
+
+	    case 'max-age': // S5.2.2
+	      if (av_value) {
+	        // "If the first character of the attribute-value is not a DIGIT or a "-"
+	        // character ...[or]... If the remainder of attribute-value contains a
+	        // non-DIGIT character, ignore the cookie-av."
+	        if (/^-?[0-9]+$/.test(av_value)) {
+	          var delta = parseInt(av_value, 10);
+	          // "If delta-seconds is less than or equal to zero (0), let expiry-time
+	          // be the earliest representable date and time."
+	          c.setMaxAge(delta);
+	        }
+	      }
+	      break;
+
+	    case 'domain': // S5.2.3
+	      // "If the attribute-value is empty, the behavior is undefined.  However,
+	      // the user agent SHOULD ignore the cookie-av entirely."
+	      if (av_value) {
+	        // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+	        // (".") character."
+	        var domain = av_value.trim().replace(/^\./, '');
+	        if (domain) {
+	          // "Convert the cookie-domain to lower case."
+	          c.domain = domain.toLowerCase();
+	        }
+	      }
+	      break;
+
+	    case 'path': // S5.2.4
+	      /*
+	       * "If the attribute-value is empty or if the first character of the
+	       * attribute-value is not %x2F ("/"):
+	       *   Let cookie-path be the default-path.
+	       * Otherwise:
+	       *   Let cookie-path be the attribute-value."
+	       *
+	       * We'll represent the default-path as null since it depends on the
+	       * context of the parsing.
+	       */
+	      c.path = av_value && av_value[0] === "/" ? av_value : null;
+	      break;
+
+	    case 'secure': // S5.2.5
+	      /*
+	       * "If the attribute-name case-insensitively matches the string "Secure",
+	       * the user agent MUST append an attribute to the cookie-attribute-list
+	       * with an attribute-name of Secure and an empty attribute-value."
+	       */
+	      c.secure = true;
+	      break;
+
+	    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+	      c.httpOnly = true;
+	      break;
+
+	    default:
+	      c.extensions = c.extensions || [];
+	      c.extensions.push(av);
+	      break;
+	    }
+	  }
+
+	  return c;
+	}
+
+	// avoid the V8 deoptimization monster!
+	function jsonParse(str) {
+	  var obj;
+	  try {
+	    obj = JSON.parse(str);
+	  } catch (e) {
+	    return e;
+	  }
+	  return obj;
+	}
+
+	function fromJSON(str) {
+	  if (!str) {
+	    return null;
+	  }
+
+	  var obj;
+	  if (typeof str === 'string') {
+	    obj = jsonParse(str);
+	    if (obj instanceof Error) {
+	      return null;
+	    }
+	  } else {
+	    // assume it's an Object
+	    obj = str;
+	  }
+
+	  var c = new Cookie();
+	  for (var i=0; i<Cookie.serializableProperties.length; i++) {
+	    var prop = Cookie.serializableProperties[i];
+	    if (obj[prop] === undefined ||
+	        obj[prop] === Cookie.prototype[prop])
+	    {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (obj[prop] === null) {
+	        c[prop] = null;
+	      } else {
+	        c[prop] = obj[prop] == "Infinity" ?
+	          "Infinity" : new Date(obj[prop]);
+	      }
+	    } else {
+	      c[prop] = obj[prop];
+	    }
+	  }
+
+	  return c;
+	}
+
+	/* Section 5.4 part 2:
+	 * "*  Cookies with longer paths are listed before cookies with
+	 *     shorter paths.
+	 *
+	 *  *  Among cookies that have equal-length path fields, cookies with
+	 *     earlier creation-times are listed before cookies with later
+	 *     creation-times."
+	 */
+
+	function cookieCompare(a,b) {
+	  var cmp = 0;
+
+	  // descending for length: b CMP a
+	  var aPathLen = a.path ? a.path.length : 0;
+	  var bPathLen = b.path ? b.path.length : 0;
+	  cmp = bPathLen - aPathLen;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // ascending for time: a CMP b
+	  var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+	  var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+	  cmp = aTime - bTime;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // break ties for the same millisecond (precision of JavaScript's clock)
+	  cmp = a.creationIndex - b.creationIndex;
+
+	  return cmp;
+	}
+
+	// Gives the permutation of all possible pathMatch()es of a given path. The
+	// array is in longest-to-shortest order.  Handy for indexing.
+	function permutePath(path) {
+	  if (path === '/') {
+	    return ['/'];
+	  }
+	  if (path.lastIndexOf('/') === path.length-1) {
+	    path = path.substr(0,path.length-1);
+	  }
+	  var permutations = [path];
+	  while (path.length > 1) {
+	    var lindex = path.lastIndexOf('/');
+	    if (lindex === 0) {
+	      break;
+	    }
+	    path = path.substr(0,lindex);
+	    permutations.push(path);
+	  }
+	  permutations.push('/');
+	  return permutations;
+	}
+
+	function getCookieContext(url) {
+	  if (url instanceof Object) {
+	    return url;
+	  }
+	  // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+	  // Therefore, we will just skip decoding for such URIs.
+	  try {
+	    url = decodeURI(url);
+	  }
+	  catch(err) {
+	    // Silently swallow error
+	  }
+
+	  return urlParse(url);
+	}
+
+	function Cookie(options) {
+	  options = options || {};
+
+	  Object.keys(options).forEach(function(prop) {
+	    if (Cookie.prototype.hasOwnProperty(prop) &&
+	        Cookie.prototype[prop] !== options[prop] &&
+	        prop.substr(0,1) !== '_')
+	    {
+	      this[prop] = options[prop];
+	    }
+	  }, this);
+
+	  this.creation = this.creation || new Date();
+
+	  // used to break creation ties in cookieCompare():
+	  Object.defineProperty(this, 'creationIndex', {
+	    configurable: false,
+	    enumerable: false, // important for assert.deepEqual checks
+	    writable: true,
+	    value: ++Cookie.cookiesCreated
+	  });
+	}
+
+	Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+	Cookie.parse = parse;
+	Cookie.fromJSON = fromJSON;
+
+	Cookie.prototype.key = "";
+	Cookie.prototype.value = "";
+
+	// the order in which the RFC has them:
+	Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+	Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+	Cookie.prototype.domain = null;
+	Cookie.prototype.path = null;
+	Cookie.prototype.secure = false;
+	Cookie.prototype.httpOnly = false;
+	Cookie.prototype.extensions = null;
+
+	// set by the CookieJar:
+	Cookie.prototype.hostOnly = null; // boolean when set
+	Cookie.prototype.pathIsDefault = null; // boolean when set
+	Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+	Cookie.prototype.lastAccessed = null; // Date when set
+	Object.defineProperty(Cookie.prototype, 'creationIndex', {
+	  configurable: true,
+	  enumerable: false,
+	  writable: true,
+	  value: 0
+	});
+
+	Cookie.serializableProperties = Object.keys(Cookie.prototype)
+	  .filter(function(prop) {
+	    return !(
+	      Cookie.prototype[prop] instanceof Function ||
+	      prop === 'creationIndex' ||
+	      prop.substr(0,1) === '_'
+	    );
+	  });
+
+	Cookie.prototype.inspect = function inspect() {
+	  var now = Date.now();
+	  return 'Cookie="'+this.toString() +
+	    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+	    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+	    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+	    '"';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+	}
+
+	Cookie.prototype.toJSON = function() {
+	  var obj = {};
+
+	  var props = Cookie.serializableProperties;
+	  for (var i=0; i<props.length; i++) {
+	    var prop = props[i];
+	    if (this[prop] === Cookie.prototype[prop]) {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (this[prop] === null) {
+	        obj[prop] = null;
+	      } else {
+	        obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+	          "Infinity" : this[prop].toISOString();
+	      }
+	    } else if (prop === 'maxAge') {
+	      if (this[prop] !== null) {
+	        // again, intentionally not ===
+	        obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+	          this[prop].toString() : this[prop];
+	      }
+	    } else {
+	      if (this[prop] !== Cookie.prototype[prop]) {
+	        obj[prop] = this[prop];
+	      }
+	    }
+	  }
+
+	  return obj;
+	};
+
+	Cookie.prototype.clone = function() {
+	  return fromJSON(this.toJSON());
+	};
+
+	Cookie.prototype.validate = function validate() {
+	  if (!COOKIE_OCTETS.test(this.value)) {
+	    return false;
+	  }
+	  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+	    return false;
+	  }
+	  if (this.maxAge != null && this.maxAge <= 0) {
+	    return false; // "Max-Age=" non-zero-digit *DIGIT
+	  }
+	  if (this.path != null && !PATH_VALUE.test(this.path)) {
+	    return false;
+	  }
+
+	  var cdomain = this.cdomain();
+	  if (cdomain) {
+	    if (cdomain.match(/\.$/)) {
+	      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+	    }
+	    var suffix = pubsuffix.getPublicSuffix(cdomain);
+	    if (suffix == null) { // it's a public suffix
+	      return false;
+	    }
+	  }
+	  return true;
+	};
+
+	Cookie.prototype.setExpires = function setExpires(exp) {
+	  if (exp instanceof Date) {
+	    this.expires = exp;
+	  } else {
+	    this.expires = parseDate(exp) || "Infinity";
+	  }
+	};
+
+	Cookie.prototype.setMaxAge = function setMaxAge(age) {
+	  if (age === Infinity || age === -Infinity) {
+	    this.maxAge = age.toString(); // so JSON.stringify() works
+	  } else {
+	    this.maxAge = age;
+	  }
+	};
+
+	// gives Cookie header format
+	Cookie.prototype.cookieString = function cookieString() {
+	  var val = this.value;
+	  if (val == null) {
+	    val = '';
+	  }
+	  if (this.key === '') {
+	    return val;
+	  }
+	  return this.key+'='+val;
+	};
+
+	// gives Set-Cookie header format
+	Cookie.prototype.toString = function toString() {
+	  var str = this.cookieString();
+
+	  if (this.expires != Infinity) {
+	    if (this.expires instanceof Date) {
+	      str += '; Expires='+formatDate(this.expires);
+	    } else {
+	      str += '; Expires='+this.expires;
+	    }
+	  }
+
+	  if (this.maxAge != null && this.maxAge != Infinity) {
+	    str += '; Max-Age='+this.maxAge;
+	  }
+
+	  if (this.domain && !this.hostOnly) {
+	    str += '; Domain='+this.domain;
+	  }
+	  if (this.path) {
+	    str += '; Path='+this.path;
+	  }
+
+	  if (this.secure) {
+	    str += '; Secure';
+	  }
+	  if (this.httpOnly) {
+	    str += '; HttpOnly';
+	  }
+	  if (this.extensions) {
+	    this.extensions.forEach(function(ext) {
+	      str += '; '+ext;
+	    });
+	  }
+
+	  return str;
+	};
+
+	// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	// S5.3 says to give the "latest representable date" for which we use Infinity
+	// For "expired" we use 0
+	Cookie.prototype.TTL = function TTL(now) {
+	  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+	   * attribute, the Max-Age attribute has precedence and controls the
+	   * expiration date of the cookie.
+	   * (Concurs with S5.3 step 3)
+	   */
+	  if (this.maxAge != null) {
+	    return this.maxAge<=0 ? 0 : this.maxAge*1000;
+	  }
+
+	  var expires = this.expires;
+	  if (expires != Infinity) {
+	    if (!(expires instanceof Date)) {
+	      expires = parseDate(expires) || Infinity;
+	    }
+
+	    if (expires == Infinity) {
+	      return Infinity;
+	    }
+
+	    return expires.getTime() - (now || Date.now());
+	  }
+
+	  return Infinity;
+	};
+
+	// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	Cookie.prototype.expiryTime = function expiryTime(now) {
+	  if (this.maxAge != null) {
+	    var relativeTo = now || this.creation || new Date();
+	    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+	    return relativeTo.getTime() + age;
+	  }
+
+	  if (this.expires == Infinity) {
+	    return Infinity;
+	  }
+	  return this.expires.getTime();
+	};
+
+	// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere), except it returns a Date
+	Cookie.prototype.expiryDate = function expiryDate(now) {
+	  var millisec = this.expiryTime(now);
+	  if (millisec == Infinity) {
+	    return new Date(MAX_TIME);
+	  } else if (millisec == -Infinity) {
+	    return new Date(MIN_TIME);
+	  } else {
+	    return new Date(millisec);
+	  }
+	};
+
+	// This replaces the "persistent-flag" parts of S5.3 step 3
+	Cookie.prototype.isPersistent = function isPersistent() {
+	  return (this.maxAge != null || this.expires != Infinity);
+	};
+
+	// Mostly S5.1.2 and S5.2.3:
+	Cookie.prototype.cdomain =
+	Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+	  if (this.domain == null) {
+	    return null;
+	  }
+	  return canonicalDomain(this.domain);
+	};
+
+	function CookieJar(store, options) {
+	  if (typeof options === "boolean") {
+	    options = {rejectPublicSuffixes: options};
+	  } else if (options == null) {
+	    options = {};
+	  }
+	  if (options.rejectPublicSuffixes != null) {
+	    this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+	  }
+	  if (options.looseMode != null) {
+	    this.enableLooseMode = options.looseMode;
+	  }
+
+	  if (!store) {
+	    store = new MemoryCookieStore();
+	  }
+	  this.store = store;
+	}
+	CookieJar.prototype.store = null;
+	CookieJar.prototype.rejectPublicSuffixes = true;
+	CookieJar.prototype.enableLooseMode = false;
+	var CAN_BE_SYNC = [];
+
+	CAN_BE_SYNC.push('setCookie');
+	CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+	  var err;
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var loose = this.enableLooseMode;
+	  if (options.loose != null) {
+	    loose = options.loose;
+	  }
+
+	  // S5.3 step 1
+	  if (!(cookie instanceof Cookie)) {
+	    cookie = Cookie.parse(cookie, { loose: loose });
+	  }
+	  if (!cookie) {
+	    err = new Error("Cookie failed to parse");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  // S5.3 step 2
+	  var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+	  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+	  // S5.3 step 4: NOOP; domain is null by default
+
+	  // S5.3 step 5: public suffixes
+	  if (this.rejectPublicSuffixes && cookie.domain) {
+	    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+	    if (suffix == null) { // e.g. "com"
+	      err = new Error("Cookie has domain set to a public suffix");
+	      return cb(options.ignoreError ? null : err);
+	    }
+	  }
+
+	  // S5.3 step 6:
+	  if (cookie.domain) {
+	    if (!domainMatch(host, cookie.cdomain(), false)) {
+	      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+	      return cb(options.ignoreError ? null : err);
+	    }
+
+	    if (cookie.hostOnly == null) { // don't reset if already set
+	      cookie.hostOnly = false;
+	    }
+
+	  } else {
+	    cookie.hostOnly = true;
+	    cookie.domain = host;
+	  }
+
+	  //S5.2.4 If the attribute-value is empty or if the first character of the
+	  //attribute-value is not %x2F ("/"):
+	  //Let cookie-path be the default-path.
+	  if (!cookie.path || cookie.path[0] !== '/') {
+	    cookie.path = defaultPath(context.pathname);
+	    cookie.pathIsDefault = true;
+	  }
+
+	  // S5.3 step 8: NOOP; secure attribute
+	  // S5.3 step 9: NOOP; httpOnly attribute
+
+	  // S5.3 step 10
+	  if (options.http === false && cookie.httpOnly) {
+	    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  var store = this.store;
+
+	  if (!store.updateCookie) {
+	    store.updateCookie = function(oldCookie, newCookie, cb) {
+	      this.putCookie(newCookie, cb);
+	    };
+	  }
+
+	  function withCookie(err, oldCookie) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    var next = function(err) {
+	      if (err) {
+	        return cb(err);
+	      } else {
+	        cb(null, cookie);
+	      }
+	    };
+
+	    if (oldCookie) {
+	      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+	      // domain, and path as the newly created cookie:"
+	      if (options.http === false && oldCookie.httpOnly) { // step 11.2
+	        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+	        return cb(options.ignoreError ? null : err);
+	      }
+	      cookie.creation = oldCookie.creation; // step 11.3
+	      cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+	      cookie.lastAccessed = now;
+	      // Step 11.4 (delete cookie) is implied by just setting the new one:
+	      store.updateCookie(oldCookie, cookie, next); // step 12
+
+	    } else {
+	      cookie.creation = cookie.lastAccessed = now;
+	      store.putCookie(cookie, next); // step 12
+	    }
+	  }
+
+	  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+	};
+
+	// RFC6365 S5.4
+	CAN_BE_SYNC.push('getCookies');
+	CookieJar.prototype.getCookies = function(url, options, cb) {
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var path = context.pathname || '/';
+
+	  var secure = options.secure;
+	  if (secure == null && context.protocol &&
+	      (context.protocol == 'https:' || context.protocol == 'wss:'))
+	  {
+	    secure = true;
+	  }
+
+	  var http = options.http;
+	  if (http == null) {
+	    http = true;
+	  }
+
+	  var now = options.now || Date.now();
+	  var expireCheck = options.expire !== false;
+	  var allPaths = !!options.allPaths;
+	  var store = this.store;
+
+	  function matchingCookie(c) {
+	    // "Either:
+	    //   The cookie's host-only-flag is true and the canonicalized
+	    //   request-host is identical to the cookie's domain.
+	    // Or:
+	    //   The cookie's host-only-flag is false and the canonicalized
+	    //   request-host domain-matches the cookie's domain."
+	    if (c.hostOnly) {
+	      if (c.domain != host) {
+	        return false;
+	      }
+	    } else {
+	      if (!domainMatch(host, c.domain, false)) {
+	        return false;
+	      }
+	    }
+
+	    // "The request-uri's path path-matches the cookie's path."
+	    if (!allPaths && !pathMatch(path, c.path)) {
+	      return false;
+	    }
+
+	    // "If the cookie's secure-only-flag is true, then the request-uri's
+	    // scheme must denote a "secure" protocol"
+	    if (c.secure && !secure) {
+	      return false;
+	    }
+
+	    // "If the cookie's http-only-flag is true, then exclude the cookie if the
+	    // cookie-string is being generated for a "non-HTTP" API"
+	    if (c.httpOnly && !http) {
+	      return false;
+	    }
+
+	    // deferred from S5.3
+	    // non-RFC: allow retention of expired cookies by choice
+	    if (expireCheck && c.expiryTime() <= now) {
+	      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+	      return false;
+	    }
+
+	    return true;
+	  }
+
+	  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    cookies = cookies.filter(matchingCookie);
+
+	    // sorting of S5.4 part 2
+	    if (options.sort !== false) {
+	      cookies = cookies.sort(cookieCompare);
+	    }
+
+	    // S5.4 part 3
+	    var now = new Date();
+	    cookies.forEach(function(c) {
+	      c.lastAccessed = now;
+	    });
+	    // TODO persist lastAccessed
+
+	    cb(null,cookies);
+	  });
+	};
+
+	CAN_BE_SYNC.push('getCookieString');
+	CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies
+	        .sort(cookieCompare)
+	        .map(function(c){
+	          return c.cookieString();
+	        })
+	        .join('; '));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('getSetCookieStrings');
+	CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies.map(function(c){
+	        return c.toString();
+	      }));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('serialize');
+	CookieJar.prototype.serialize = function(cb) {
+	  var type = this.store.constructor.name;
+	  if (type === 'Object') {
+	    type = null;
+	  }
+
+	  // update README.md "Serialization Format" if you change this, please!
+	  var serialized = {
+	    // The version of tough-cookie that serialized this jar. Generally a good
+	    // practice since future versions can make data import decisions based on
+	    // known past behavior. When/if this matters, use `semver`.
+	    version: 'tough-cookie@'+VERSION,
+
+	    // add the store type, to make humans happy:
+	    storeType: type,
+
+	    // CookieJar configuration:
+	    rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+	    // this gets filled from getAllCookies:
+	    cookies: []
+	  };
+
+	  if (!(this.store.getAllCookies &&
+	        typeof this.store.getAllCookies === 'function'))
+	  {
+	    return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+	  }
+
+	  this.store.getAllCookies(function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    serialized.cookies = cookies.map(function(cookie) {
+	      // convert to serialized 'raw' cookies
+	      cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+	      // Remove the index so new ones get assigned during deserialization
+	      delete cookie.creationIndex;
+
+	      return cookie;
+	    });
+
+	    return cb(null, serialized);
+	  });
+	};
+
+	// well-known name that JSON.stringify calls
+	CookieJar.prototype.toJSON = function() {
+	  return this.serializeSync();
+	};
+
+	// use the class method CookieJar.deserialize instead of calling this directly
+	CAN_BE_SYNC.push('_importCookies');
+	CookieJar.prototype._importCookies = function(serialized, cb) {
+	  var jar = this;
+	  var cookies = serialized.cookies;
+	  if (!cookies || !Array.isArray(cookies)) {
+	    return cb(new Error('serialized jar has no cookies array'));
+	  }
+	  cookies = cookies.slice(); // do not modify the original
+
+	  function putNext(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    if (!cookies.length) {
+	      return cb(err, jar);
+	    }
+
+	    var cookie;
+	    try {
+	      cookie = fromJSON(cookies.shift());
+	    } catch (e) {
+	      return cb(e);
+	    }
+
+	    if (cookie === null) {
+	      return putNext(null); // skip this cookie
+	    }
+
+	    jar.store.putCookie(cookie, putNext);
+	  }
+
+	  putNext();
+	};
+
+	CookieJar.deserialize = function(strOrObj, store, cb) {
+	  if (arguments.length !== 3) {
+	    // store is optional
+	    cb = store;
+	    store = null;
+	  }
+
+	  var serialized;
+	  if (typeof strOrObj === 'string') {
+	    serialized = jsonParse(strOrObj);
+	    if (serialized instanceof Error) {
+	      return cb(serialized);
+	    }
+	  } else {
+	    serialized = strOrObj;
+	  }
+
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+	  jar._importCookies(serialized, function(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    cb(null, jar);
+	  });
+	};
+
+	CookieJar.deserializeSync = function(strOrObj, store) {
+	  var serialized = typeof strOrObj === 'string' ?
+	    JSON.parse(strOrObj) : strOrObj;
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+	  // catch this mistake early:
+	  if (!jar.store.synchronous) {
+	    throw new Error('CookieJar store is not synchronous; use async API instead.');
+	  }
+
+	  jar._importCookiesSync(serialized);
+	  return jar;
+	};
+	CookieJar.fromJSON = CookieJar.deserializeSync;
+
+	CAN_BE_SYNC.push('clone');
+	CookieJar.prototype.clone = function(newStore, cb) {
+	  if (arguments.length === 1) {
+	    cb = newStore;
+	    newStore = null;
+	  }
+
+	  this.serialize(function(err,serialized) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    CookieJar.deserialize(newStore, serialized, cb);
+	  });
+	};
+
+	// Use a closure to provide a true imperative API for synchronous stores.
+	function syncWrap(method) {
+	  return function() {
+	    if (!this.store.synchronous) {
+	      throw new Error('CookieJar store is not synchronous; use async API instead.');
+	    }
+
+	    var args = Array.prototype.slice.call(arguments);
+	    var syncErr, syncResult;
+	    args.push(function syncCb(err, result) {
+	      syncErr = err;
+	      syncResult = result;
+	    });
+	    this[method].apply(this, args);
+
+	    if (syncErr) {
+	      throw syncErr;
+	    }
+	    return syncResult;
+	  };
+	}
+
+	// wrap all declared CAN_BE_SYNC methods in the sync wrapper
+	CAN_BE_SYNC.forEach(function(method) {
+	  CookieJar.prototype[method+'Sync'] = syncWrap(method);
+	});
+
+	exports.CookieJar = CookieJar;
+	exports.Cookie = Cookie;
+	exports.Store = Store;
+	exports.MemoryCookieStore = MemoryCookieStore;
+	exports.parseDate = parseDate;
+	exports.formatDate = formatDate;
+	exports.parse = parse;
+	exports.fromJSON = fromJSON;
+	exports.domainMatch = domainMatch;
+	exports.defaultPath = defaultPath;
+	exports.pathMatch = pathMatch;
+	exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+	exports.cookieCompare = cookieCompare;
+	exports.permuteDomain = __webpack_require__(19).permuteDomain;
+	exports.permutePath = permutePath;
+	exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+	/*
+	* Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+	* Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+	*/
+
+	var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+	var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+	function isIPv4(hostOrIp) {
+	  return hostOrIp.match(patternIPv4) ? true : false;
+	}
+
+	function isIPv6(hostOrIp) {
+	  return hostOrIp.match(patternIPv6) ? true : false;
+	}
+
+	function isIP(hostOrIp) {
+	  if (isIPv4(hostOrIp)) {
+	    return 4;
+	  }
+
+	  if (isIPv6(hostOrIp)) {
+	    return 6;
+	  }
+
+	  return 0;
+	}
+
+	module.exports = {
+	  isIPv4: isIPv4,
+	  isIPv6: isIPv6,
+	  isIP: isIP
+	};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var punycode = __webpack_require__(3);
+	var util = __webpack_require__(5);
+
+	exports.parse = urlParse;
+	exports.resolve = urlResolve;
+	exports.resolveObject = urlResolveObject;
+	exports.format = urlFormat;
+
+	exports.Url = Url;
+
+	function Url() {
+	  this.protocol = null;
+	  this.slashes = null;
+	  this.auth = null;
+	  this.host = null;
+	  this.port = null;
+	  this.hostname = null;
+	  this.hash = null;
+	  this.search = null;
+	  this.query = null;
+	  this.pathname = null;
+	  this.path = null;
+	  this.href = null;
+	}
+
+	// Reference: RFC 3986, RFC 1808, RFC 2396
+
+	// define these here so at least they only have to be
+	// compiled once on the first module load.
+	var protocolPattern = /^([a-z0-9.+-]+:)/i,
+	    portPattern = /:[0-9]*$/,
+
+	    // Special case for a simple path URL
+	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+	    // RFC 2396: characters reserved for delimiting URLs.
+	    // We actually just auto-escape these.
+	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+	    // RFC 2396: characters not allowed for various reasons.
+	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
+	    autoEscape = ['\''].concat(unwise),
+	    // Characters that are never ever allowed in a hostname.
+	    // Note that any invalid chars are also handled, but these
+	    // are the ones that are *expected* to be seen, so we fast-path
+	    // them.
+	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+	    hostEndingChars = ['/', '?', '#'],
+	    hostnameMaxLen = 255,
+	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+	    // protocols that can allow "unsafe" and "unwise" chars.
+	    unsafeProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that never have a hostname.
+	    hostlessProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that always contain a // bit.
+	    slashedProtocol = {
+	      'http': true,
+	      'https': true,
+	      'ftp': true,
+	      'gopher': true,
+	      'file': true,
+	      'http:': true,
+	      'https:': true,
+	      'ftp:': true,
+	      'gopher:': true,
+	      'file:': true
+	    },
+	    querystring = __webpack_require__(6);
+
+	function urlParse(url, parseQueryString, slashesDenoteHost) {
+	  if (url && util.isObject(url) && url instanceof Url) return url;
+
+	  var u = new Url;
+	  u.parse(url, parseQueryString, slashesDenoteHost);
+	  return u;
+	}
+
+	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+	  if (!util.isString(url)) {
+	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+	  }
+
+	  // Copy chrome, IE, opera backslash-handling behavior.
+	  // Back slashes before the query string get converted to forward slashes
+	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
+	  var queryIndex = url.indexOf('?'),
+	      splitter =
+	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+	      uSplit = url.split(splitter),
+	      slashRegex = /\\/g;
+	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
+	  url = uSplit.join(splitter);
+
+	  var rest = url;
+
+	  // trim before proceeding.
+	  // This is to support parse stuff like "  http://foo.com  \n"
+	  rest = rest.trim();
+
+	  if (!slashesDenoteHost && url.split('#').length === 1) {
+	    // Try fast path regexp
+	    var simplePath = simplePathPattern.exec(rest);
+	    if (simplePath) {
+	      this.path = rest;
+	      this.href = rest;
+	      this.pathname = simplePath[1];
+	      if (simplePath[2]) {
+	        this.search = simplePath[2];
+	        if (parseQueryString) {
+	          this.query = querystring.parse(this.search.substr(1));
+	        } else {
+	          this.query = this.search.substr(1);
+	        }
+	      } else if (parseQueryString) {
+	        this.search = '';
+	        this.query = {};
+	      }
+	      return this;
+	    }
+	  }
+
+	  var proto = protocolPattern.exec(rest);
+	  if (proto) {
+	    proto = proto[0];
+	    var lowerProto = proto.toLowerCase();
+	    this.protocol = lowerProto;
+	    rest = rest.substr(proto.length);
+	  }
+
+	  // figure out if it's got a host
+	  // user@server is *always* interpreted as a hostname, and url
+	  // resolution will treat //foo/bar as host=foo,path=bar because that's
+	  // how the browser resolves relative URLs.
+	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+	    var slashes = rest.substr(0, 2) === '//';
+	    if (slashes && !(proto && hostlessProtocol[proto])) {
+	      rest = rest.substr(2);
+	      this.slashes = true;
+	    }
+	  }
+
+	  if (!hostlessProtocol[proto] &&
+	      (slashes || (proto && !slashedProtocol[proto]))) {
+
+	    // there's a hostname.
+	    // the first instance of /, ?, ;, or # ends the host.
+	    //
+	    // If there is an @ in the hostname, then non-host chars *are* allowed
+	    // to the left of the last @ sign, unless some host-ending character
+	    // comes *before* the @-sign.
+	    // URLs are obnoxious.
+	    //
+	    // ex:
+	    // http://a@b@c/ => user:a@b host:c
+	    // http://a@b?@c => user:a host:c path:/?@c
+
+	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+	    // Review our test case against browsers more comprehensively.
+
+	    // find the first instance of any hostEndingChars
+	    var hostEnd = -1;
+	    for (var i = 0; i < hostEndingChars.length; i++) {
+	      var hec = rest.indexOf(hostEndingChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+
+	    // at this point, either we have an explicit point where the
+	    // auth portion cannot go past, or the last @ char is the decider.
+	    var auth, atSign;
+	    if (hostEnd === -1) {
+	      // atSign can be anywhere.
+	      atSign = rest.lastIndexOf('@');
+	    } else {
+	      // atSign must be in auth portion.
+	      // http://a@b/c@d => host:b auth:a path:/c@d
+	      atSign = rest.lastIndexOf('@', hostEnd);
+	    }
+
+	    // Now we have a portion which is definitely the auth.
+	    // Pull that off.
+	    if (atSign !== -1) {
+	      auth = rest.slice(0, atSign);
+	      rest = rest.slice(atSign + 1);
+	      this.auth = decodeURIComponent(auth);
+	    }
+
+	    // the host is the remaining to the left of the first non-host char
+	    hostEnd = -1;
+	    for (var i = 0; i < nonHostChars.length; i++) {
+	      var hec = rest.indexOf(nonHostChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+	    // if we still have not hit it, then the entire thing is a host.
+	    if (hostEnd === -1)
+	      hostEnd = rest.length;
+
+	    this.host = rest.slice(0, hostEnd);
+	    rest = rest.slice(hostEnd);
+
+	    // pull out port.
+	    this.parseHost();
+
+	    // we've indicated that there is a hostname,
+	    // so even if it's empty, it has to be present.
+	    this.hostname = this.hostname || '';
+
+	    // if hostname begins with [ and ends with ]
+	    // assume that it's an IPv6 address.
+	    var ipv6Hostname = this.hostname[0] === '[' &&
+	        this.hostname[this.hostname.length - 1] === ']';
+
+	    // validate a little.
+	    if (!ipv6Hostname) {
+	      var hostparts = this.hostname.split(/\./);
+	      for (var i = 0, l = hostparts.length; i < l; i++) {
+	        var part = hostparts[i];
+	        if (!part) continue;
+	        if (!part.match(hostnamePartPattern)) {
+	          var newpart = '';
+	          for (var j = 0, k = part.length; j < k; j++) {
+	            if (part.charCodeAt(j) > 127) {
+	              // we replace non-ASCII char with a temporary placeholder
+	              // we need this to make sure size of hostname is not
+	              // broken by replacing non-ASCII by nothing
+	              newpart += 'x';
+	            } else {
+	              newpart += part[j];
+	            }
+	          }
+	          // we test again with ASCII char only
+	          if (!newpart.match(hostnamePartPattern)) {
+	            var validParts = hostparts.slice(0, i);
+	            var notHost = hostparts.slice(i + 1);
+	            var bit = part.match(hostnamePartStart);
+	            if (bit) {
+	              validParts.push(bit[1]);
+	              notHost.unshift(bit[2]);
+	            }
+	            if (notHost.length) {
+	              rest = '/' + notHost.join('.') + rest;
+	            }
+	            this.hostname = validParts.join('.');
+	            break;
+	          }
+	        }
+	      }
+	    }
+
+	    if (this.hostname.length > hostnameMaxLen) {
+	      this.hostname = '';
+	    } else {
+	      // hostnames are always lower case.
+	      this.hostname = this.hostname.toLowerCase();
+	    }
+
+	    if (!ipv6Hostname) {
+	      // IDNA Support: Returns a punycoded representation of "domain".
+	      // It only converts parts of the domain name that
+	      // have non-ASCII characters, i.e. it doesn't matter if
+	      // you call it with a domain that already is ASCII-only.
+	      this.hostname = punycode.toASCII(this.hostname);
+	    }
+
+	    var p = this.port ? ':' + this.port : '';
+	    var h = this.hostname || '';
+	    this.host = h + p;
+	    this.href += this.host;
+
+	    // strip [ and ] from the hostname
+	    // the host field still retains them, though
+	    if (ipv6Hostname) {
+	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+	      if (rest[0] !== '/') {
+	        rest = '/' + rest;
+	      }
+	    }
+	  }
+
+	  // now rest is set to the post-host stuff.
+	  // chop off any delim chars.
+	  if (!unsafeProtocol[lowerProto]) {
+
+	    // First, make 100% sure that any "autoEscape" chars get
+	    // escaped, even if encodeURIComponent doesn't think they
+	    // need to be.
+	    for (var i = 0, l = autoEscape.length; i < l; i++) {
+	      var ae = autoEscape[i];
+	      if (rest.indexOf(ae) === -1)
+	        continue;
+	      var esc = encodeURIComponent(ae);
+	      if (esc === ae) {
+	        esc = escape(ae);
+	      }
+	      rest = rest.split(ae).join(esc);
+	    }
+	  }
+
+
+	  // chop off from the tail first.
+	  var hash = rest.indexOf('#');
+	  if (hash !== -1) {
+	    // got a fragment string.
+	    this.hash = rest.substr(hash);
+	    rest = rest.slice(0, hash);
+	  }
+	  var qm = rest.indexOf('?');
+	  if (qm !== -1) {
+	    this.search = rest.substr(qm);
+	    this.query = rest.substr(qm + 1);
+	    if (parseQueryString) {
+	      this.query = querystring.parse(this.query);
+	    }
+	    rest = rest.slice(0, qm);
+	  } else if (parseQueryString) {
+	    // no query string, but parseQueryString still requested
+	    this.search = '';
+	    this.query = {};
+	  }
+	  if (rest) this.pathname = rest;
+	  if (slashedProtocol[lowerProto] &&
+	      this.hostname && !this.pathname) {
+	    this.pathname = '/';
+	  }
+
+	  //to support http.request
+	  if (this.pathname || this.search) {
+	    var p = this.pathname || '';
+	    var s = this.search || '';
+	    this.path = p + s;
+	  }
+
+	  // finally, reconstruct the href based on what has been validated.
+	  this.href = this.format();
+	  return this;
+	};
+
+	// format a parsed object into a url string
+	function urlFormat(obj) {
+	  // ensure it's an object, and not a string url.
+	  // If it's an obj, this is a no-op.
+	  // this way, you can call url_format() on strings
+	  // to clean up potentially wonky urls.
+	  if (util.isString(obj)) obj = urlParse(obj);
+	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+	  return obj.format();
+	}
+
+	Url.prototype.format = function() {
+	  var auth = this.auth || '';
+	  if (auth) {
+	    auth = encodeURIComponent(auth);
+	    auth = auth.replace(/%3A/i, ':');
+	    auth += '@';
+	  }
+
+	  var protocol = this.protocol || '',
+	      pathname = this.pathname || '',
+	      hash = this.hash || '',
+	      host = false,
+	      query = '';
+
+	  if (this.host) {
+	    host = auth + this.host;
+	  } else if (this.hostname) {
+	    host = auth + (this.hostname.indexOf(':') === -1 ?
+	        this.hostname :
+	        '[' + this.hostname + ']');
+	    if (this.port) {
+	      host += ':' + this.port;
+	    }
+	  }
+
+	  if (this.query &&
+	      util.isObject(this.query) &&
+	      Object.keys(this.query).length) {
+	    query = querystring.stringify(this.query);
+	  }
+
+	  var search = this.search || (query && ('?' + query)) || '';
+
+	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
+	  // unless they had them to begin with.
+	  if (this.slashes ||
+	      (!protocol || slashedProtocol[protocol]) && host !== false) {
+	    host = '//' + (host || '');
+	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+	  } else if (!host) {
+	    host = '';
+	  }
+
+	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+	  if (search && search.charAt(0) !== '?') search = '?' + search;
+
+	  pathname = pathname.replace(/[?#]/g, function(match) {
+	    return encodeURIComponent(match);
+	  });
+	  search = search.replace('#', '%23');
+
+	  return protocol + host + pathname + search + hash;
+	};
+
+	function urlResolve(source, relative) {
+	  return urlParse(source, false, true).resolve(relative);
+	}
+
+	Url.prototype.resolve = function(relative) {
+	  return this.resolveObject(urlParse(relative, false, true)).format();
+	};
+
+	function urlResolveObject(source, relative) {
+	  if (!source) return relative;
+	  return urlParse(source, false, true).resolveObject(relative);
+	}
+
+	Url.prototype.resolveObject = function(relative) {
+	  if (util.isString(relative)) {
+	    var rel = new Url();
+	    rel.parse(relative, false, true);
+	    relative = rel;
+	  }
+
+	  var result = new Url();
+	  var tkeys = Object.keys(this);
+	  for (var tk = 0; tk < tkeys.length; tk++) {
+	    var tkey = tkeys[tk];
+	    result[tkey] = this[tkey];
+	  }
+
+	  // hash is always overridden, no matter what.
+	  // even href="" will remove it.
+	  result.hash = relative.hash;
+
+	  // if the relative url is empty, then there's nothing left to do here.
+	  if (relative.href === '') {
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // hrefs like //foo/bar always cut to the protocol.
+	  if (relative.slashes && !relative.protocol) {
+	    // take everything except the protocol from relative
+	    var rkeys = Object.keys(relative);
+	    for (var rk = 0; rk < rkeys.length; rk++) {
+	      var rkey = rkeys[rk];
+	      if (rkey !== 'protocol')
+	        result[rkey] = relative[rkey];
+	    }
+
+	    //urlParse appends trailing / to urls like http://www.example.com
+	    if (slashedProtocol[result.protocol] &&
+	        result.hostname && !result.pathname) {
+	      result.path = result.pathname = '/';
+	    }
+
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (relative.protocol && relative.protocol !== result.protocol) {
+	    // if it's a known url protocol, then changing
+	    // the protocol does weird things
+	    // first, if it's not file:, then we MUST have a host,
+	    // and if there was a path
+	    // to begin with, then we MUST have a path.
+	    // if it is file:, then the host is dropped,
+	    // because that's known to be hostless.
+	    // anything else is assumed to be absolute.
+	    if (!slashedProtocol[relative.protocol]) {
+	      var keys = Object.keys(relative);
+	      for (var v = 0; v < keys.length; v++) {
+	        var k = keys[v];
+	        result[k] = relative[k];
+	      }
+	      result.href = result.format();
+	      return result;
+	    }
+
+	    result.protocol = relative.protocol;
+	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
+	      var relPath = (relative.pathname || '').split('/');
+	      while (relPath.length && !(relative.host = relPath.shift()));
+	      if (!relative.host) relative.host = '';
+	      if (!relative.hostname) relative.hostname = '';
+	      if (relPath[0] !== '') relPath.unshift('');
+	      if (relPath.length < 2) relPath.unshift('');
+	      result.pathname = relPath.join('/');
+	    } else {
+	      result.pathname = relative.pathname;
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    result.host = relative.host || '';
+	    result.auth = relative.auth;
+	    result.hostname = relative.hostname || relative.host;
+	    result.port = relative.port;
+	    // to support http.request
+	    if (result.pathname || result.search) {
+	      var p = result.pathname || '';
+	      var s = result.search || '';
+	      result.path = p + s;
+	    }
+	    result.slashes = result.slashes || relative.slashes;
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+	      isRelAbs = (
+	          relative.host ||
+	          relative.pathname && relative.pathname.charAt(0) === '/'
+	      ),
+	      mustEndAbs = (isRelAbs || isSourceAbs ||
+	                    (result.host && relative.pathname)),
+	      removeAllDots = mustEndAbs,
+	      srcPath = result.pathname && result.pathname.split('/') || [],
+	      relPath = relative.pathname && relative.pathname.split('/') || [],
+	      psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+	  // if the url is a non-slashed url, then relative
+	  // links like ../.. should be able
+	  // to crawl up to the hostname, as well.  This is strange.
+	  // result.protocol has already been set by now.
+	  // Later on, put the first path part into the host field.
+	  if (psychotic) {
+	    result.hostname = '';
+	    result.port = null;
+	    if (result.host) {
+	      if (srcPath[0] === '') srcPath[0] = result.host;
+	      else srcPath.unshift(result.host);
+	    }
+	    result.host = '';
+	    if (relative.protocol) {
+	      relative.hostname = null;
+	      relative.port = null;
+	      if (relative.host) {
+	        if (relPath[0] === '') relPath[0] = relative.host;
+	        else relPath.unshift(relative.host);
+	      }
+	      relative.host = null;
+	    }
+	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+	  }
+
+	  if (isRelAbs) {
+	    // it's absolute.
+	    result.host = (relative.host || relative.host === '') ?
+	                  relative.host : result.host;
+	    result.hostname = (relative.hostname || relative.hostname === '') ?
+	                      relative.hostname : result.hostname;
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    srcPath = relPath;
+	    // fall through to the dot-handling below.
+	  } else if (relPath.length) {
+	    // it's relative
+	    // throw away the existing file, and take the new path instead.
+	    if (!srcPath) srcPath = [];
+	    srcPath.pop();
+	    srcPath = srcPath.concat(relPath);
+	    result.search = relative.search;
+	    result.query = relative.query;
+	  } else if (!util.isNullOrUndefined(relative.search)) {
+	    // just pull out the search.
+	    // like href='?foo'.
+	    // Put this after the other two cases because it simplifies the booleans
+	    if (psychotic) {
+	      result.hostname = result.host = srcPath.shift();
+	      //occationaly the auth can get stuck only in host
+	      //this especially happens in cases like
+	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                       result.host.split('@') : false;
+	      if (authInHost) {
+	        result.auth = authInHost.shift();
+	        result.host = result.hostname = authInHost.shift();
+	      }
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    //to support http.request
+	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	      result.path = (result.pathname ? result.pathname : '') +
+	                    (result.search ? result.search : '');
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (!srcPath.length) {
+	    // no path at all.  easy.
+	    // we've already handled the other stuff above.
+	    result.pathname = null;
+	    //to support http.request
+	    if (result.search) {
+	      result.path = '/' + result.search;
+	    } else {
+	      result.path = null;
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // if a url ENDs in . or .., then it must get a trailing slash.
+	  // however, if it ends in anything else non-slashy,
+	  // then it must NOT get a trailing slash.
+	  var last = srcPath.slice(-1)[0];
+	  var hasTrailingSlash = (
+	      (result.host || relative.host || srcPath.length > 1) &&
+	      (last === '.' || last === '..') || last === '');
+
+	  // strip single dots, resolve double dots to parent dir
+	  // if the path tries to go above the root, `up` ends up > 0
+	  var up = 0;
+	  for (var i = srcPath.length; i >= 0; i--) {
+	    last = srcPath[i];
+	    if (last === '.') {
+	      srcPath.splice(i, 1);
+	    } else if (last === '..') {
+	      srcPath.splice(i, 1);
+	      up++;
+	    } else if (up) {
+	      srcPath.splice(i, 1);
+	      up--;
+	    }
+	  }
+
+	  // if the path is allowed to go above the root, restore leading ..s
+	  if (!mustEndAbs && !removeAllDots) {
+	    for (; up--; up) {
+	      srcPath.unshift('..');
+	    }
+	  }
+
+	  if (mustEndAbs && srcPath[0] !== '' &&
+	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+	    srcPath.unshift('');
+	  }
+
+	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+	    srcPath.push('');
+	  }
+
+	  var isAbsolute = srcPath[0] === '' ||
+	      (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+	  // put the host back
+	  if (psychotic) {
+	    result.hostname = result.host = isAbsolute ? '' :
+	                                    srcPath.length ? srcPath.shift() : '';
+	    //occationaly the auth can get stuck only in host
+	    //this especially happens in cases like
+	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                     result.host.split('@') : false;
+	    if (authInHost) {
+	      result.auth = authInHost.shift();
+	      result.host = result.hostname = authInHost.shift();
+	    }
+	  }
+
+	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+	  if (mustEndAbs && !isAbsolute) {
+	    srcPath.unshift('');
+	  }
+
+	  if (!srcPath.length) {
+	    result.pathname = null;
+	    result.path = null;
+	  } else {
+	    result.pathname = srcPath.join('/');
+	  }
+
+	  //to support request.http
+	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	    result.path = (result.pathname ? result.pathname : '') +
+	                  (result.search ? result.search : '');
+	  }
+	  result.auth = relative.auth || result.auth;
+	  result.slashes = result.slashes || relative.slashes;
+	  result.href = result.format();
+	  return result;
+	};
+
+	Url.prototype.parseHost = function() {
+	  var host = this.host;
+	  var port = portPattern.exec(host);
+	  if (port) {
+	    port = port[0];
+	    if (port !== ':') {
+	      this.port = port.substr(1);
+	    }
+	    host = host.substr(0, host.length - port.length);
+	  }
+	  if (host) this.hostname = host;
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * http://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.3.2',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else { // in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else { // in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	module.exports = function(module) {

+		if(!module.webpackPolyfill) {

+			module.deprecate = function() {};

+			module.paths = [];

+			// module.parent = undefined by default

+			module.children = [];

+			module.webpackPolyfill = 1;

+		}

+		return module;

+	}

+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+	'use strict';
+
+	module.exports = {
+	  isString: function(arg) {
+	    return typeof(arg) === 'string';
+	  },
+	  isObject: function(arg) {
+	    return typeof(arg) === 'object' && arg !== null;
+	  },
+	  isNull: function(arg) {
+	    return arg === null;
+	  },
+	  isNullOrUndefined: function(arg) {
+	    return arg == null;
+	  }
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	exports.decode = exports.parse = __webpack_require__(7);
+	exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	// If obj.hasOwnProperty has been overridden, then calling
+	// obj.hasOwnProperty(prop) will break.
+	// See: https://github.com/joyent/node/issues/1707
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	module.exports = function(qs, sep, eq, options) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  var obj = {};
+
+	  if (typeof qs !== 'string' || qs.length === 0) {
+	    return obj;
+	  }
+
+	  var regexp = /\+/g;
+	  qs = qs.split(sep);
+
+	  var maxKeys = 1000;
+	  if (options && typeof options.maxKeys === 'number') {
+	    maxKeys = options.maxKeys;
+	  }
+
+	  var len = qs.length;
+	  // maxKeys <= 0 means that we should not limit keys count
+	  if (maxKeys > 0 && len > maxKeys) {
+	    len = maxKeys;
+	  }
+
+	  for (var i = 0; i < len; ++i) {
+	    var x = qs[i].replace(regexp, '%20'),
+	        idx = x.indexOf(eq),
+	        kstr, vstr, k, v;
+
+	    if (idx >= 0) {
+	      kstr = x.substr(0, idx);
+	      vstr = x.substr(idx + 1);
+	    } else {
+	      kstr = x;
+	      vstr = '';
+	    }
+
+	    k = decodeURIComponent(kstr);
+	    v = decodeURIComponent(vstr);
+
+	    if (!hasOwnProperty(obj, k)) {
+	      obj[k] = v;
+	    } else if (Array.isArray(obj[k])) {
+	      obj[k].push(v);
+	    } else {
+	      obj[k] = [obj[k], v];
+	    }
+	  }
+
+	  return obj;
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var stringifyPrimitive = function(v) {
+	  switch (typeof v) {
+	    case 'string':
+	      return v;
+
+	    case 'boolean':
+	      return v ? 'true' : 'false';
+
+	    case 'number':
+	      return isFinite(v) ? v : '';
+
+	    default:
+	      return '';
+	  }
+	};
+
+	module.exports = function(obj, sep, eq, name) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  if (obj === null) {
+	    obj = undefined;
+	  }
+
+	  if (typeof obj === 'object') {
+	    return Object.keys(obj).map(function(k) {
+	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+	      if (Array.isArray(obj[k])) {
+	        return obj[k].map(function(v) {
+	          return ks + encodeURIComponent(stringifyPrimitive(v));
+	        }).join(sep);
+	      } else {
+	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+	      }
+	    }).join(sep);
+
+	  }
+
+	  if (!name) return '';
+	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
+	         encodeURIComponent(stringifyPrimitive(obj));
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	var formatRegExp = /%[sdj%]/g;
+	exports.format = function(f) {
+	  if (!isString(f)) {
+	    var objects = [];
+	    for (var i = 0; i < arguments.length; i++) {
+	      objects.push(inspect(arguments[i]));
+	    }
+	    return objects.join(' ');
+	  }
+
+	  var i = 1;
+	  var args = arguments;
+	  var len = args.length;
+	  var str = String(f).replace(formatRegExp, function(x) {
+	    if (x === '%%') return '%';
+	    if (i >= len) return x;
+	    switch (x) {
+	      case '%s': return String(args[i++]);
+	      case '%d': return Number(args[i++]);
+	      case '%j':
+	        try {
+	          return JSON.stringify(args[i++]);
+	        } catch (_) {
+	          return '[Circular]';
+	        }
+	      default:
+	        return x;
+	    }
+	  });
+	  for (var x = args[i]; i < len; x = args[++i]) {
+	    if (isNull(x) || !isObject(x)) {
+	      str += ' ' + x;
+	    } else {
+	      str += ' ' + inspect(x);
+	    }
+	  }
+	  return str;
+	};
+
+
+	// Mark that a method should not be used.
+	// Returns a modified function which warns once by default.
+	// If --no-deprecation is set, then it is a no-op.
+	exports.deprecate = function(fn, msg) {
+	  // Allow for deprecating things in the process of starting up.
+	  if (isUndefined(global.process)) {
+	    return function() {
+	      return exports.deprecate(fn, msg).apply(this, arguments);
+	    };
+	  }
+
+	  if (process.noDeprecation === true) {
+	    return fn;
+	  }
+
+	  var warned = false;
+	  function deprecated() {
+	    if (!warned) {
+	      if (process.throwDeprecation) {
+	        throw new Error(msg);
+	      } else if (process.traceDeprecation) {
+	        console.trace(msg);
+	      } else {
+	        console.error(msg);
+	      }
+	      warned = true;
+	    }
+	    return fn.apply(this, arguments);
+	  }
+
+	  return deprecated;
+	};
+
+
+	var debugs = {};
+	var debugEnviron;
+	exports.debuglog = function(set) {
+	  if (isUndefined(debugEnviron))
+	    debugEnviron = process.env.NODE_DEBUG || '';
+	  set = set.toUpperCase();
+	  if (!debugs[set]) {
+	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+	      var pid = process.pid;
+	      debugs[set] = function() {
+	        var msg = exports.format.apply(exports, arguments);
+	        console.error('%s %d: %s', set, pid, msg);
+	      };
+	    } else {
+	      debugs[set] = function() {};
+	    }
+	  }
+	  return debugs[set];
+	};
+
+
+	/**
+	 * Echos the value of a value. Trys to print the value out
+	 * in the best way possible given the different types.
+	 *
+	 * @param {Object} obj The object to print out.
+	 * @param {Object} opts Optional options object that alters the output.
+	 */
+	/* legacy: obj, showHidden, depth, colors*/
+	function inspect(obj, opts) {
+	  // default options
+	  var ctx = {
+	    seen: [],
+	    stylize: stylizeNoColor
+	  };
+	  // legacy...
+	  if (arguments.length >= 3) ctx.depth = arguments[2];
+	  if (arguments.length >= 4) ctx.colors = arguments[3];
+	  if (isBoolean(opts)) {
+	    // legacy...
+	    ctx.showHidden = opts;
+	  } else if (opts) {
+	    // got an "options" object
+	    exports._extend(ctx, opts);
+	  }
+	  // set default options
+	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+	  if (isUndefined(ctx.depth)) ctx.depth = 2;
+	  if (isUndefined(ctx.colors)) ctx.colors = false;
+	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+	  if (ctx.colors) ctx.stylize = stylizeWithColor;
+	  return formatValue(ctx, obj, ctx.depth);
+	}
+	exports.inspect = inspect;
+
+
+	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+	inspect.colors = {
+	  'bold' : [1, 22],
+	  'italic' : [3, 23],
+	  'underline' : [4, 24],
+	  'inverse' : [7, 27],
+	  'white' : [37, 39],
+	  'grey' : [90, 39],
+	  'black' : [30, 39],
+	  'blue' : [34, 39],
+	  'cyan' : [36, 39],
+	  'green' : [32, 39],
+	  'magenta' : [35, 39],
+	  'red' : [31, 39],
+	  'yellow' : [33, 39]
+	};
+
+	// Don't use 'blue' not visible on cmd.exe
+	inspect.styles = {
+	  'special': 'cyan',
+	  'number': 'yellow',
+	  'boolean': 'yellow',
+	  'undefined': 'grey',
+	  'null': 'bold',
+	  'string': 'green',
+	  'date': 'magenta',
+	  // "name": intentionally not styling
+	  'regexp': 'red'
+	};
+
+
+	function stylizeWithColor(str, styleType) {
+	  var style = inspect.styles[styleType];
+
+	  if (style) {
+	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+	           '\u001b[' + inspect.colors[style][1] + 'm';
+	  } else {
+	    return str;
+	  }
+	}
+
+
+	function stylizeNoColor(str, styleType) {
+	  return str;
+	}
+
+
+	function arrayToHash(array) {
+	  var hash = {};
+
+	  array.forEach(function(val, idx) {
+	    hash[val] = true;
+	  });
+
+	  return hash;
+	}
+
+
+	function formatValue(ctx, value, recurseTimes) {
+	  // Provide a hook for user-specified inspect functions.
+	  // Check that value is an object with an inspect function on it
+	  if (ctx.customInspect &&
+	      value &&
+	      isFunction(value.inspect) &&
+	      // Filter out the util module, it's inspect function is special
+	      value.inspect !== exports.inspect &&
+	      // Also filter out any prototype objects using the circular check.
+	      !(value.constructor && value.constructor.prototype === value)) {
+	    var ret = value.inspect(recurseTimes, ctx);
+	    if (!isString(ret)) {
+	      ret = formatValue(ctx, ret, recurseTimes);
+	    }
+	    return ret;
+	  }
+
+	  // Primitive types cannot have properties
+	  var primitive = formatPrimitive(ctx, value);
+	  if (primitive) {
+	    return primitive;
+	  }
+
+	  // Look up the keys of the object.
+	  var keys = Object.keys(value);
+	  var visibleKeys = arrayToHash(keys);
+
+	  if (ctx.showHidden) {
+	    keys = Object.getOwnPropertyNames(value);
+	  }
+
+	  // IE doesn't make error fields non-enumerable
+	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+	  if (isError(value)
+	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+	    return formatError(value);
+	  }
+
+	  // Some type of object without properties can be shortcutted.
+	  if (keys.length === 0) {
+	    if (isFunction(value)) {
+	      var name = value.name ? ': ' + value.name : '';
+	      return ctx.stylize('[Function' + name + ']', 'special');
+	    }
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    }
+	    if (isDate(value)) {
+	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
+	    }
+	    if (isError(value)) {
+	      return formatError(value);
+	    }
+	  }
+
+	  var base = '', array = false, braces = ['{', '}'];
+
+	  // Make Array say that they are Array
+	  if (isArray(value)) {
+	    array = true;
+	    braces = ['[', ']'];
+	  }
+
+	  // Make functions say that they are functions
+	  if (isFunction(value)) {
+	    var n = value.name ? ': ' + value.name : '';
+	    base = ' [Function' + n + ']';
+	  }
+
+	  // Make RegExps say that they are RegExps
+	  if (isRegExp(value)) {
+	    base = ' ' + RegExp.prototype.toString.call(value);
+	  }
+
+	  // Make dates with properties first say the date
+	  if (isDate(value)) {
+	    base = ' ' + Date.prototype.toUTCString.call(value);
+	  }
+
+	  // Make error with message first say the error
+	  if (isError(value)) {
+	    base = ' ' + formatError(value);
+	  }
+
+	  if (keys.length === 0 && (!array || value.length == 0)) {
+	    return braces[0] + base + braces[1];
+	  }
+
+	  if (recurseTimes < 0) {
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    } else {
+	      return ctx.stylize('[Object]', 'special');
+	    }
+	  }
+
+	  ctx.seen.push(value);
+
+	  var output;
+	  if (array) {
+	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+	  } else {
+	    output = keys.map(function(key) {
+	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+	    });
+	  }
+
+	  ctx.seen.pop();
+
+	  return reduceToSingleString(output, base, braces);
+	}
+
+
+	function formatPrimitive(ctx, value) {
+	  if (isUndefined(value))
+	    return ctx.stylize('undefined', 'undefined');
+	  if (isString(value)) {
+	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+	                                             .replace(/'/g, "\\'")
+	                                             .replace(/\\"/g, '"') + '\'';
+	    return ctx.stylize(simple, 'string');
+	  }
+	  if (isNumber(value))
+	    return ctx.stylize('' + value, 'number');
+	  if (isBoolean(value))
+	    return ctx.stylize('' + value, 'boolean');
+	  // For some reason typeof null is "object", so special case here.
+	  if (isNull(value))
+	    return ctx.stylize('null', 'null');
+	}
+
+
+	function formatError(value) {
+	  return '[' + Error.prototype.toString.call(value) + ']';
+	}
+
+
+	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+	  var output = [];
+	  for (var i = 0, l = value.length; i < l; ++i) {
+	    if (hasOwnProperty(value, String(i))) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          String(i), true));
+	    } else {
+	      output.push('');
+	    }
+	  }
+	  keys.forEach(function(key) {
+	    if (!key.match(/^\d+$/)) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          key, true));
+	    }
+	  });
+	  return output;
+	}
+
+
+	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+	  var name, str, desc;
+	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+	  if (desc.get) {
+	    if (desc.set) {
+	      str = ctx.stylize('[Getter/Setter]', 'special');
+	    } else {
+	      str = ctx.stylize('[Getter]', 'special');
+	    }
+	  } else {
+	    if (desc.set) {
+	      str = ctx.stylize('[Setter]', 'special');
+	    }
+	  }
+	  if (!hasOwnProperty(visibleKeys, key)) {
+	    name = '[' + key + ']';
+	  }
+	  if (!str) {
+	    if (ctx.seen.indexOf(desc.value) < 0) {
+	      if (isNull(recurseTimes)) {
+	        str = formatValue(ctx, desc.value, null);
+	      } else {
+	        str = formatValue(ctx, desc.value, recurseTimes - 1);
+	      }
+	      if (str.indexOf('\n') > -1) {
+	        if (array) {
+	          str = str.split('\n').map(function(line) {
+	            return '  ' + line;
+	          }).join('\n').substr(2);
+	        } else {
+	          str = '\n' + str.split('\n').map(function(line) {
+	            return '   ' + line;
+	          }).join('\n');
+	        }
+	      }
+	    } else {
+	      str = ctx.stylize('[Circular]', 'special');
+	    }
+	  }
+	  if (isUndefined(name)) {
+	    if (array && key.match(/^\d+$/)) {
+	      return str;
+	    }
+	    name = JSON.stringify('' + key);
+	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+	      name = name.substr(1, name.length - 2);
+	      name = ctx.stylize(name, 'name');
+	    } else {
+	      name = name.replace(/'/g, "\\'")
+	                 .replace(/\\"/g, '"')
+	                 .replace(/(^"|"$)/g, "'");
+	      name = ctx.stylize(name, 'string');
+	    }
+	  }
+
+	  return name + ': ' + str;
+	}
+
+
+	function reduceToSingleString(output, base, braces) {
+	  var numLinesEst = 0;
+	  var length = output.reduce(function(prev, cur) {
+	    numLinesEst++;
+	    if (cur.indexOf('\n') >= 0) numLinesEst++;
+	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+	  }, 0);
+
+	  if (length > 60) {
+	    return braces[0] +
+	           (base === '' ? '' : base + '\n ') +
+	           ' ' +
+	           output.join(',\n  ') +
+	           ' ' +
+	           braces[1];
+	  }
+
+	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+	}
+
+
+	// NOTE: These type checking functions intentionally don't use `instanceof`
+	// because it is fragile and can be easily faked with `Object.create()`.
+	function isArray(ar) {
+	  return Array.isArray(ar);
+	}
+	exports.isArray = isArray;
+
+	function isBoolean(arg) {
+	  return typeof arg === 'boolean';
+	}
+	exports.isBoolean = isBoolean;
+
+	function isNull(arg) {
+	  return arg === null;
+	}
+	exports.isNull = isNull;
+
+	function isNullOrUndefined(arg) {
+	  return arg == null;
+	}
+	exports.isNullOrUndefined = isNullOrUndefined;
+
+	function isNumber(arg) {
+	  return typeof arg === 'number';
+	}
+	exports.isNumber = isNumber;
+
+	function isString(arg) {
+	  return typeof arg === 'string';
+	}
+	exports.isString = isString;
+
+	function isSymbol(arg) {
+	  return typeof arg === 'symbol';
+	}
+	exports.isSymbol = isSymbol;
+
+	function isUndefined(arg) {
+	  return arg === void 0;
+	}
+	exports.isUndefined = isUndefined;
+
+	function isRegExp(re) {
+	  return isObject(re) && objectToString(re) === '[object RegExp]';
+	}
+	exports.isRegExp = isRegExp;
+
+	function isObject(arg) {
+	  return typeof arg === 'object' && arg !== null;
+	}
+	exports.isObject = isObject;
+
+	function isDate(d) {
+	  return isObject(d) && objectToString(d) === '[object Date]';
+	}
+	exports.isDate = isDate;
+
+	function isError(e) {
+	  return isObject(e) &&
+	      (objectToString(e) === '[object Error]' || e instanceof Error);
+	}
+	exports.isError = isError;
+
+	function isFunction(arg) {
+	  return typeof arg === 'function';
+	}
+	exports.isFunction = isFunction;
+
+	function isPrimitive(arg) {
+	  return arg === null ||
+	         typeof arg === 'boolean' ||
+	         typeof arg === 'number' ||
+	         typeof arg === 'string' ||
+	         typeof arg === 'symbol' ||  // ES6 symbol
+	         typeof arg === 'undefined';
+	}
+	exports.isPrimitive = isPrimitive;
+
+	exports.isBuffer = __webpack_require__(11);
+
+	function objectToString(o) {
+	  return Object.prototype.toString.call(o);
+	}
+
+
+	function pad(n) {
+	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+	}
+
+
+	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+	              'Oct', 'Nov', 'Dec'];
+
+	// 26 Feb 16:19:34
+	function timestamp() {
+	  var d = new Date();
+	  var time = [pad(d.getHours()),
+	              pad(d.getMinutes()),
+	              pad(d.getSeconds())].join(':');
+	  return [d.getDate(), months[d.getMonth()], time].join(' ');
+	}
+
+
+	// log is just a thin wrapper to console.log that prepends a timestamp
+	exports.log = function() {
+	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+	};
+
+
+	/**
+	 * Inherit the prototype methods from one constructor into another.
+	 *
+	 * The Function.prototype.inherits from lang.js rewritten as a standalone
+	 * function (not on Function.prototype). NOTE: If this file is to be loaded
+	 * during bootstrapping this function needs to be rewritten using some native
+	 * functions as prototype setup using normal JavaScript does not work as
+	 * expected during bootstrapping (see mirror.js in r114903).
+	 *
+	 * @param {function} ctor Constructor function which needs to inherit the
+	 *     prototype.
+	 * @param {function} superCtor Constructor function to inherit prototype from.
+	 */
+	exports.inherits = __webpack_require__(12);
+
+	exports._extend = function(origin, add) {
+	  // Don't do anything if add isn't an object
+	  if (!add || !isObject(add)) return origin;
+
+	  var keys = Object.keys(add);
+	  var i = keys.length;
+	  while (i--) {
+	    origin[keys[i]] = add[keys[i]];
+	  }
+	  return origin;
+	};
+
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	// shim for using process in browser
+	var process = module.exports = {};
+
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+
+
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+
+
+
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+
+	    var len = queue.length;
+	    while(len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+
+	function noop() {}
+
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+
+	process.listeners = function (name) { return [] }
+
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+
+	process.cwd = function () { return '/' };
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	module.exports = function isBuffer(arg) {
+	  return arg && typeof arg === 'object'
+	    && typeof arg.copy === 'function'
+	    && typeof arg.fill === 'function'
+	    && typeof arg.readUInt8 === 'function';
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	if (typeof Object.create === 'function') {
+	  // implementation from standard node.js 'util' module
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    ctor.prototype = Object.create(superCtor.prototype, {
+	      constructor: {
+	        value: ctor,
+	        enumerable: false,
+	        writable: true,
+	        configurable: true
+	      }
+	    });
+	  };
+	} else {
+	  // old school shim for old browsers
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    var TempCtor = function () {}
+	    TempCtor.prototype = superCtor.prototype
+	    ctor.prototype = new TempCtor()
+	    ctor.prototype.constructor = ctor
+	  }
+	}
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2018, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var psl = __webpack_require__(14);
+
+	function getPublicSuffix(domain) {
+	  return psl.get(domain);
+	}
+
+	exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+	'use strict';
+
+
+	var Punycode = __webpack_require__(15);
+
+
+	var internals = {};
+
+
+	//
+	// Read rules from file.
+	//
+	internals.rules = __webpack_require__(16).map(function (rule) {
+
+	  return {
+	    rule: rule,
+	    suffix: rule.replace(/^(\*\.|\!)/, ''),
+	    punySuffix: -1,
+	    wildcard: rule.charAt(0) === '*',
+	    exception: rule.charAt(0) === '!'
+	  };
+	});
+
+
+	//
+	// Check is given string ends with `suffix`.
+	//
+	internals.endsWith = function (str, suffix) {
+
+	  return str.indexOf(suffix, str.length - suffix.length) !== -1;
+	};
+
+
+	//
+	// Find rule for a given domain.
+	//
+	internals.findRule = function (domain) {
+
+	  var punyDomain = Punycode.toASCII(domain);
+	  return internals.rules.reduce(function (memo, rule) {
+
+	    if (rule.punySuffix === -1){
+	      rule.punySuffix = Punycode.toASCII(rule.suffix);
+	    }
+	    if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+	      return memo;
+	    }
+	    // This has been commented out as it never seems to run. This is because
+	    // sub tlds always appear after their parents and we never find a shorter
+	    // match.
+	    //if (memo) {
+	    //  var memoSuffix = Punycode.toASCII(memo.suffix);
+	    //  if (memoSuffix.length >= punySuffix.length) {
+	    //    return memo;
+	    //  }
+	    //}
+	    return rule;
+	  }, null);
+	};
+
+
+	//
+	// Error codes and messages.
+	//
+	exports.errorCodes = {
+	  DOMAIN_TOO_SHORT: 'Domain name too short.',
+	  DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+	  LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+	  LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+	  LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+	  LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+	  LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+	};
+
+
+	//
+	// Validate domain name and throw if not valid.
+	//
+	// From wikipedia:
+	//
+	// Hostnames are composed of series of labels concatenated with dots, as are all
+	// domain names. Each label must be between 1 and 63 characters long, and the
+	// entire hostname (including the delimiting dots) has a maximum of 255 chars.
+	//
+	// Allowed chars:
+	//
+	// * `a-z`
+	// * `0-9`
+	// * `-` but not as a starting or ending character
+	// * `.` as a separator for the textual portions of a domain name
+	//
+	// * http://en.wikipedia.org/wiki/Domain_name
+	// * http://en.wikipedia.org/wiki/Hostname
+	//
+	internals.validate = function (input) {
+
+	  // Before we can validate we need to take care of IDNs with unicode chars.
+	  var ascii = Punycode.toASCII(input);
+
+	  if (ascii.length < 1) {
+	    return 'DOMAIN_TOO_SHORT';
+	  }
+	  if (ascii.length > 255) {
+	    return 'DOMAIN_TOO_LONG';
+	  }
+
+	  // Check each part's length and allowed chars.
+	  var labels = ascii.split('.');
+	  var label;
+
+	  for (var i = 0; i < labels.length; ++i) {
+	    label = labels[i];
+	    if (!label.length) {
+	      return 'LABEL_TOO_SHORT';
+	    }
+	    if (label.length > 63) {
+	      return 'LABEL_TOO_LONG';
+	    }
+	    if (label.charAt(0) === '-') {
+	      return 'LABEL_STARTS_WITH_DASH';
+	    }
+	    if (label.charAt(label.length - 1) === '-') {
+	      return 'LABEL_ENDS_WITH_DASH';
+	    }
+	    if (!/^[a-z0-9\-]+$/.test(label)) {
+	      return 'LABEL_INVALID_CHARS';
+	    }
+	  }
+	};
+
+
+	//
+	// Public API
+	//
+
+
+	//
+	// Parse domain.
+	//
+	exports.parse = function (input) {
+
+	  if (typeof input !== 'string') {
+	    throw new TypeError('Domain name must be a string.');
+	  }
+
+	  // Force domain to lowercase.
+	  var domain = input.slice(0).toLowerCase();
+
+	  // Handle FQDN.
+	  // TODO: Simply remove trailing dot?
+	  if (domain.charAt(domain.length - 1) === '.') {
+	    domain = domain.slice(0, domain.length - 1);
+	  }
+
+	  // Validate and sanitise input.
+	  var error = internals.validate(domain);
+	  if (error) {
+	    return {
+	      input: input,
+	      error: {
+	        message: exports.errorCodes[error],
+	        code: error
+	      }
+	    };
+	  }
+
+	  var parsed = {
+	    input: input,
+	    tld: null,
+	    sld: null,
+	    domain: null,
+	    subdomain: null,
+	    listed: false
+	  };
+
+	  var domainParts = domain.split('.');
+
+	  // Non-Internet TLD
+	  if (domainParts[domainParts.length - 1] === 'local') {
+	    return parsed;
+	  }
+
+	  var handlePunycode = function () {
+
+	    if (!/xn--/.test(domain)) {
+	      return parsed;
+	    }
+	    if (parsed.domain) {
+	      parsed.domain = Punycode.toASCII(parsed.domain);
+	    }
+	    if (parsed.subdomain) {
+	      parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+	    }
+	    return parsed;
+	  };
+
+	  var rule = internals.findRule(domain);
+
+	  // Unlisted tld.
+	  if (!rule) {
+	    if (domainParts.length < 2) {
+	      return parsed;
+	    }
+	    parsed.tld = domainParts.pop();
+	    parsed.sld = domainParts.pop();
+	    parsed.domain = [parsed.sld, parsed.tld].join('.');
+	    if (domainParts.length) {
+	      parsed.subdomain = domainParts.pop();
+	    }
+	    return handlePunycode();
+	  }
+
+	  // At this point we know the public suffix is listed.
+	  parsed.listed = true;
+
+	  var tldParts = rule.suffix.split('.');
+	  var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+	  if (rule.exception) {
+	    privateParts.push(tldParts.shift());
+	  }
+
+	  parsed.tld = tldParts.join('.');
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  if (rule.wildcard) {
+	    tldParts.unshift(privateParts.pop());
+	    parsed.tld = tldParts.join('.');
+	  }
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  parsed.sld = privateParts.pop();
+	  parsed.domain = [parsed.sld,  parsed.tld].join('.');
+
+	  if (privateParts.length) {
+	    parsed.subdomain = privateParts.join('.');
+	  }
+
+	  return handlePunycode();
+	};
+
+
+	//
+	// Get domain.
+	//
+	exports.get = function (domain) {
+
+	  if (!domain) {
+	    return null;
+	  }
+	  return exports.parse(domain).domain || null;
+	};
+
+
+	//
+	// Check whether domain belongs to a known public suffix.
+	//
+	exports.isValid = function (domain) {
+
+	  var parsed = exports.parse(domain);
+	  return Boolean(parsed.domain && parsed.listed);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw new RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * https://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.4.1',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) {
+				// in Node.js, io.js, or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else {
+				// in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else {
+			// in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	/*jshint unused:false */
+
+	function Store() {
+	}
+	exports.Store = Store;
+
+	// Stores may be synchronous, but are still required to use a
+	// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
+	// API that converts from synchronous-callbacks to imperative style.
+	Store.prototype.synchronous = false;
+
+	Store.prototype.findCookie = function(domain, path, key, cb) {
+	  throw new Error('findCookie is not implemented');
+	};
+
+	Store.prototype.findCookies = function(domain, path, cb) {
+	  throw new Error('findCookies is not implemented');
+	};
+
+	Store.prototype.putCookie = function(cookie, cb) {
+	  throw new Error('putCookie is not implemented');
+	};
+
+	Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // recommended default implementation:
+	  // return this.putCookie(newCookie, cb);
+	  throw new Error('updateCookie is not implemented');
+	};
+
+	Store.prototype.removeCookie = function(domain, path, key, cb) {
+	  throw new Error('removeCookie is not implemented');
+	};
+
+	Store.prototype.removeCookies = function(domain, path, cb) {
+	  throw new Error('removeCookies is not implemented');
+	};
+
+	Store.prototype.getAllCookies = function(cb) {
+	  throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var Store = __webpack_require__(17).Store;
+	var permuteDomain = __webpack_require__(19).permuteDomain;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var util = __webpack_require__(9);
+
+	function MemoryCookieStore() {
+	  Store.call(this);
+	  this.idx = {};
+	}
+	util.inherits(MemoryCookieStore, Store);
+	exports.MemoryCookieStore = MemoryCookieStore;
+	MemoryCookieStore.prototype.idx = null;
+
+	// Since it's just a struct in RAM, this Store is synchronous
+	MemoryCookieStore.prototype.synchronous = true;
+
+	// force a default depth:
+	MemoryCookieStore.prototype.inspect = function() {
+	  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+	}
+
+	MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+	  if (!this.idx[domain]) {
+	    return cb(null,undefined);
+	  }
+	  if (!this.idx[domain][path]) {
+	    return cb(null,undefined);
+	  }
+	  return cb(null,this.idx[domain][path][key]||null);
+	};
+
+	MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+	  var results = [];
+	  if (!domain) {
+	    return cb(null,[]);
+	  }
+
+	  var pathMatcher;
+	  if (!path) {
+	    // null means "all paths"
+	    pathMatcher = function matchAll(domainIndex) {
+	      for (var curPath in domainIndex) {
+	        var pathIndex = domainIndex[curPath];
+	        for (var key in pathIndex) {
+	          results.push(pathIndex[key]);
+	        }
+	      }
+	    };
+
+	  } else {
+	    pathMatcher = function matchRFC(domainIndex) {
+	       //NOTE: we should use path-match algorithm from S5.1.4 here
+	       //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+	       Object.keys(domainIndex).forEach(function (cookiePath) {
+	         if (pathMatch(path, cookiePath)) {
+	           var pathIndex = domainIndex[cookiePath];
+
+	           for (var key in pathIndex) {
+	             results.push(pathIndex[key]);
+	           }
+	         }
+	       });
+	     };
+	  }
+
+	  var domains = permuteDomain(domain) || [domain];
+	  var idx = this.idx;
+	  domains.forEach(function(curDomain) {
+	    var domainIndex = idx[curDomain];
+	    if (!domainIndex) {
+	      return;
+	    }
+	    pathMatcher(domainIndex);
+	  });
+
+	  cb(null,results);
+	};
+
+	MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+	  if (!this.idx[cookie.domain]) {
+	    this.idx[cookie.domain] = {};
+	  }
+	  if (!this.idx[cookie.domain][cookie.path]) {
+	    this.idx[cookie.domain][cookie.path] = {};
+	  }
+	  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // updateCookie() may avoid updating cookies that are identical.  For example,
+	  // lastAccessed may not be important to some stores and an equality
+	  // comparison could exclude that field.
+	  this.putCookie(newCookie,cb);
+	};
+
+	MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+	  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+	    delete this.idx[domain][path][key];
+	  }
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+	  if (this.idx[domain]) {
+	    if (path) {
+	      delete this.idx[domain][path];
+	    } else {
+	      delete this.idx[domain];
+	    }
+	  }
+	  return cb(null);
+	};
+
+	MemoryCookieStore.prototype.getAllCookies = function(cb) {
+	  var cookies = [];
+	  var idx = this.idx;
+
+	  var domains = Object.keys(idx);
+	  domains.forEach(function(domain) {
+	    var paths = Object.keys(idx[domain]);
+	    paths.forEach(function(path) {
+	      var keys = Object.keys(idx[domain][path]);
+	      keys.forEach(function(key) {
+	        if (key !== null) {
+	          cookies.push(idx[domain][path][key]);
+	        }
+	      });
+	    });
+	  });
+
+	  // Sort by creationIndex so deserializing retains the creation order.
+	  // When implementing your own store, this SHOULD retain the order too
+	  cookies.sort(function(a,b) {
+	    return (a.creationIndex||0) - (b.creationIndex||0);
+	  });
+
+	  cb(null, cookies);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	var pubsuffix = __webpack_require__(13);
+
+	// Gives the permutation of all possible domainMatch()es of a given domain. The
+	// array is in shortest-to-longest order.  Handy for indexing.
+	function permuteDomain (domain) {
+	  var pubSuf = pubsuffix.getPublicSuffix(domain);
+	  if (!pubSuf) {
+	    return null;
+	  }
+	  if (pubSuf == domain) {
+	    return [domain];
+	  }
+
+	  var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+	  var parts = prefix.split('.').reverse();
+	  var cur = pubSuf;
+	  var permutations = [cur];
+	  while (parts.length) {
+	    cur = parts.shift() + '.' + cur;
+	    permutations.push(cur);
+	  }
+	  return permutations;
+	}
+
+	exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	/*
+	 * "A request-path path-matches a given cookie-path if at least one of the
+	 * following conditions holds:"
+	 */
+	function pathMatch (reqPath, cookiePath) {
+	  // "o  The cookie-path and the request-path are identical."
+	  if (cookiePath === reqPath) {
+	    return true;
+	  }
+
+	  var idx = reqPath.indexOf(cookiePath);
+	  if (idx === 0) {
+	    // "o  The cookie-path is a prefix of the request-path, and the last
+	    // character of the cookie-path is %x2F ("/")."
+	    if (cookiePath.substr(-1) === "/") {
+	      return true;
+	    }
+
+	    // " o  The cookie-path is a prefix of the request-path, and the first
+	    // character of the request-path that is not included in the cookie- path
+	    // is a %x2F ("/") character."
+	    if (reqPath.substr(cookiePath.length, 1) === "/") {
+	      return true;
+	    }
+	  }
+
+	  return false;
+	}
+
+	exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..8d9228a
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,106 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) {
+module.exports = function init(jsUtil) {
+  return {
+    parseUrl: parseUrl,
+    appendQueryParamsString: appendQueryParamsString,
+    serializeQueryParams: serializeQueryParams
+  }
+
+  function parseUrl(url) {
+    var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+    return match && {
+        protocol: match[1],
+        host: match[2],
+        hostname: match[3],
+        port: match[4] || '',
+        pathname: match[5],
+        search: match[6],
+        hash: match[7]
+    }
+  }
+
+  function appendQueryParamsString(url, params) {
+    if (!url.length || !params.length) {
+      return url;
+    }
+
+    var parsed = parseUrl(url);
+
+    return parsed.protocol
+      + '//'
+      + parsed.host
+      + parsed.pathname
+      + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+      + parsed.hash;
+  }
+
+  function serializeQueryParams(params, encode) {
+    return serializeObject('', params, encode);
+  }
+
+  function serializeObject(parentKey, object, encode) {
+    var parts = [];
+
+    for (var key in object) {
+      if (!object.hasOwnProperty(key)) {
+        continue;
+      }
+
+      var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+      if (jsUtil.getTypeOf(object[key]) === 'Array') {
+        parts.push(serializeArray(identifier, object[key], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+        parts.push(serializeObject(identifier, object[key], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeArray(parentKey, array, encode) {
+    var parts = [];
+
+    for (var i = 0; i < array.length; ++i) {
+      if (jsUtil.getTypeOf(array[i]) === 'Array') {
+        parts.push(serializeArray(parentKey + '[]', array[i], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+        parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeIdentifier(parentKey, key, encode) {
+    if (!parentKey.length) {
+      return encode ? encodeURIComponent(key) : key;
+    }
+
+    if (encode) {
+      return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+    } else {
+      return parentKey + '[' + key + ']';
+    }
+  }
+
+  function serializeValue(value, encode) {
+    if (encode) {
+      return encodeURIComponent(value);
+    } else {
+      return value;
+    }
+  }
+};
+
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3f614ec
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,188 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ *    var image = document.getElementById('myImage');
+ *    image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the  returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery.  The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified.  To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+        mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+    // XXX: commented out
+    // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ *     console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ *     alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+    exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..4f4b046
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,104 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+     * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+     * disable any image modifications (resize, quality change, cropping, etc.) due
+     * to implementation specific.
+     *
+     * @enum {number}
+     */
+    DestinationType: {
+        /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+        DATA_URL: 0,
+        /** Return file uri (content://media/external/images/media/2 for Android) */
+        FILE_URI: 1,
+        /** Return native uri (eg. asset-library://... for iOS) */
+        NATIVE_URI: 2
+    },
+    /**
+     * @enum {number}
+     */
+    EncodingType: {
+        /** Return JPEG encoded image */
+        JPEG: 0,
+        /** Return PNG encoded image */
+        PNG: 1
+    },
+    /**
+     * @enum {number}
+     */
+    MediaType: {
+        /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+        PICTURE: 0,
+        /** Allow selection of video only, ONLY RETURNS URL */
+        VIDEO: 1,
+        /** Allow selection from all media types */
+        ALLMEDIA: 2
+    },
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+     * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+     * change, cropping, etc.) due to implementation specific.
+     *
+     * @enum {number}
+     */
+    PictureSourceType: {
+        /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+        PHOTOLIBRARY: 0,
+        /** Take picture from camera */
+        CAMERA: 1,
+        /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+        SAVEDPHOTOALBUM: 2
+    },
+    /**
+     * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+     * @enum {number}
+     */
+    PopoverArrowDirection: {
+        ARROW_UP: 1,
+        ARROW_DOWN: 2,
+        ARROW_LEFT: 4,
+        ARROW_RIGHT: 8,
+        ARROW_ANY: 15
+    },
+    /**
+     * @enum {number}
+     */
+    Direction: {
+        /** Use the back-facing camera */
+        BACK: 0,
+        /** Use the front-facing camera */
+        FRONT: 1
+    }
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js
new file mode 100644
index 0000000..c970f55
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverHandle.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-camera.CameraPopoverHandle", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @ignore in favour of iOS' one
+ * A handle to an image picker popover.
+ */
+var CameraPopoverHandle = function () {
+    this.setPosition = function (popoverOptions) {
+        console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..81d7d20
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,55 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen.  Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-device/www/device.js b/platforms/android/platform_www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..ae48e35
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+    this.available = false;
+    this.platform = null;
+    this.version = null;
+    this.uuid = null;
+    this.cordova = null;
+    this.model = null;
+    this.manufacturer = null;
+    this.isVirtual = null;
+    this.serial = null;
+
+    var me = this;
+
+    channel.onCordovaReady.subscribe(function () {
+        me.getInfo(function (info) {
+            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+            // TODO: CB-5105 native implementations should not return info.cordova
+            var buildLabel = cordova.version;
+            me.available = true;
+            me.platform = info.platform;
+            me.version = info.version;
+            me.uuid = info.uuid;
+            me.cordova = buildLabel;
+            me.model = info.model;
+            me.isVirtual = info.isVirtual;
+            me.manufacturer = info.manufacturer || 'unknown';
+            me.serial = info.serial || 'unknown';
+            channel.onCordovaInfoReady.fire();
+        }, function (e) {
+            me.available = false;
+            utils.alert('[ERROR] Error initializing Cordova: ' + e);
+        });
+    });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+    exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..bb676eb
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,120 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+    // add trailing slash if it is missing
+    if ((fullPath) && !/\/$/.test(fullPath)) {
+        fullPath += '/';
+    }
+    // add trailing slash if it is missing
+    if (nativeURL && !/\/$/.test(nativeURL)) {
+        nativeURL += '/';
+    }
+    DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+    return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var FileEntry = require('./FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..417c85f
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,75 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+    this.localURL = localURL || null;
+    this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+    // If we've already read and passed on this directory's entries, return an empty list.
+    if (this.hasReadEntries) {
+        successCallback([]);
+        return;
+    }
+    var reader = this;
+    var win = typeof successCallback !== 'function' ? null : function (result) {
+        var retVal = [];
+        for (var i = 0; i < result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('./DirectoryEntry'))();
+            } else if (result[i].isFile) {
+                entry = new (require('./FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+            entry.nativeURL = result[i].nativeURL;
+            retVal.push(entry);
+        }
+        reader.hasReadEntries = true;
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/Entry.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..b296d99
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,263 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ * @param fileSystem
+ *            {FileSystem} the filesystem on which this entry resides
+ *            (readonly)
+ * @param nativeURL
+ *            {DOMString} an alternate URL which can be used by native
+ *            webview controls, for example media players.
+ *            (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+    this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function (entryMetadata) {
+        var metadata = new Metadata({
+            size: entryMetadata.size,
+            modificationTime: entryMetadata.lastModifiedDate
+        });
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+    // entry name
+    var name = newName || this.name;
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+        // entry name
+    var name = newName || this.name;
+    // success callback
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+    if (this.filesystem && this.filesystem.__format__) {
+        return this.filesystem.__format__(this.fullPath, this.nativeURL);
+    }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+    if (this.nativeURL) {
+        return this.nativeURL;
+    }
+    // fullPath attribute may contain the full URL in the case that
+    // toInternalURL fails.
+    return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var DirectoryEntry = require('./DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/File.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..c771786
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,81 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+    this.name = name || '';
+    this.localURL = localURL || null;
+    this.type = type || null;
+    this.lastModified = lastModifiedDate || null;
+    // For backwards compatibility, store the timestamp in lastModifiedDate as well
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..6651b55
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,95 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+    // remove trailing slash if it is present
+    if (fullPath && /\/$/.test(fullPath)) {
+        fullPath = fullPath.substring(0, fullPath.length - 1);
+    }
+    if (nativeURL && /\/$/.test(nativeURL)) {
+        nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+    }
+
+    FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+    this.file(function (filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.localURL === null || writer.localURL === '') {
+            if (errorCallback) {
+                errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+            }
+        } else {
+            if (successCallback) {
+                successCallback(writer);
+            }
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+    var localURL = this.toInternalURL();
+    var win = successCallback && function (f) {
+        var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileError.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..f378c38
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,49 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+    this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..5c03091
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,301 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._progress = null;
+    this._localURL = '';
+    this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+    return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+    return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+    return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+        return this._realReader[eventName] || null;
+    }, function (value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+    // Already loading something
+    if (reader.readyState === FileReader.LOADING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._progress = 0;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file.localURL === 'string') {
+        reader._localURL = file.localURL;
+    } else {
+        reader._localURL = '';
+        return true;
+    }
+
+    if (reader.onloadstart) {
+        reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+    if (readType === 'readAsDataURL') {
+        // Windows proxy does not support reading file slices as Data URLs
+        // so read the whole file at once.
+        CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+            // Calculate new chunk size for data URLs to be multiply of 3
+            // Otherwise concatenated base64 chunks won't be valid base64 data
+            FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+    }
+
+    if (typeof r !== 'undefined') {
+        accumulate(r);
+        this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+        if (typeof this.onprogress === 'function') {
+            this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+        }
+    }
+
+    if (typeof r === 'undefined' || this._progress < totalSize) {
+        var execArgs = [
+            this._localURL,
+            offset + this._progress,
+            offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+        if (encoding) {
+            execArgs.splice(1, 0, encoding);
+        }
+        exec(
+            readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+            readFailureCallback.bind(this),
+            'File', readType, execArgs);
+    } else {
+        this._readyState = FileReader.DONE;
+
+        if (typeof this.onload === 'function') {
+            this.onload(new ProgressEvent('load', {target: this}));
+        }
+
+        if (typeof this.onloadend === 'function') {
+            this.onloadend(new ProgressEvent('loadend', {target: this}));
+        }
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+    this._result = null;
+    this._error = new FileError(e);
+
+    if (typeof this.onerror === 'function') {
+        this.onerror(new ProgressEvent('error', {target: this}));
+    }
+
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+    if (origFileReader && !this._localURL) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target: this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding || 'UTF-8';
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+        var commaIndex = r.indexOf(',');
+        if (this._progress === 0) {
+            this._result = r;
+        } else {
+            this._result += r.substring(commaIndex + 1);
+        }
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+        var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+        resultArray.set(new Uint8Array(r), this._progress);
+        this._result = resultArray.buffer;
+    }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..ad9ea78
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,58 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+    this.name = name;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+    } else {
+        this.root = new DirectoryEntry(this.name, '/', this);
+    }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+    return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+    return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+    // Because # is a valid filename character, it must be encoded to prevent part of the
+    // path from being parsed as a URI fragment.
+    return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..6acd093
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,44 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String}   Name of file request parameter.
+ * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object}    Object with key: value params to send to the server.
+ * @param headers {Object}   Keys are header names, values are header values. Multiple
+ *                           headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+    this.fileKey = fileKey || null;
+    this.fileName = fileName || null;
+    this.mimeType = mimeType || null;
+    this.params = params || null;
+    this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..e3c3a74
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+    this.bytesSent = size;
+    this.responseCode = code;
+    this.response = content;
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..d48a089
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,327 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+    this.fileName = '';
+    this.length = 0;
+    if (file) {
+        this.localURL = file.localURL || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {'target': this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === 'function') {
+        this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+    var that = this;
+    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+    /* eslint-disable no-undef */
+    var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+    var isBinary;
+
+    // Check to see if the incoming data is a blob
+    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+        var fileReader = new FileReader();
+        /* eslint-enable no-undef */
+        fileReader.onload = function () {
+            // Call this method again, with the arraybuffer as argument
+            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+        };
+        fileReader.onerror = function () {
+            // DONE state
+            that.readyState = FileWriter.DONE;
+
+            // Save error
+            that.error = this.error;
+
+            // If onerror callback
+            if (typeof that.onerror === 'function') {
+                that.onerror(new ProgressEvent('error', {'target': that}));
+            }
+
+            // If onwriteend callback
+            if (typeof that.onwriteend === 'function') {
+                that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+            }
+        };
+
+        // WRITING state
+        this.readyState = FileWriter.WRITING;
+
+        if (supportsBinary) {
+            fileReader.readAsArrayBuffer(data);
+        } else {
+            fileReader.readAsText(data);
+        }
+        return;
+    }
+
+    // Mark data type for safer transport over the binary bridge
+    isBinary = supportsBinary && (data instanceof ArrayBuffer);
+    if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+        data = Array.apply(null, new Uint8Array(data));
+    }
+
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset && offset !== 0) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    // Offset is bigger than file size so set position
+    // to the end of the file.
+    } else if (offset > this.length) {
+        this.position = this.length;
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    } else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/Flags.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..cdb12bb
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,39 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags (create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..4ce6848
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,26 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..22366e1
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+    if (typeof metadata === 'object') {
+        this.modificationTime = new Date(metadata.modificationTime);
+        this.size = metadata.size || 0;
+    } else if (typeof metadata === 'undefined') {
+        this.modificationTime = null;
+        this.size = 0;
+    } else {
+        /* Backwards compatiblity with platforms that only return a timestamp */
+        this.modificationTime = new Date(metadata);
+    }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..cbecdb1
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,70 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+    return function ProgressEvent (type, dict) {
+        this.type = type;
+        this.bubbles = false;
+        this.cancelBubble = false;
+        this.cancelable = false;
+        this.lengthComputable = false;
+        this.loaded = dict && dict.loaded ? dict.loaded : 0;
+        this.total = dict && dict.total ? dict.total : 0;
+        this.target = dict && dict.target ? dict.target : null;
+    };
+    // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/android/FileSystem.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/android/FileSystem.js
new file mode 100644
index 0000000..0124fa6
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/android/FileSystem.js
@@ -0,0 +1,51 @@
+cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+FILESYSTEM_PROTOCOL = 'cdvfile'; // eslint-disable-line no-undef
+
+module.exports = {
+    __format__: function (fullPath, nativeUrl) {
+        var path;
+        var contentUrlMatch = /^content:\/\//.exec(nativeUrl);
+        if (contentUrlMatch) {
+            // When available, use the path from a native content URL, which was already encoded by Android.
+            // This is necessary because JavaScript's encodeURI() does not encode as many characters as
+            // Android, which can result in permission exceptions when the encoding of a content URI
+            // doesn't match the string for which permission was originally granted.
+            path = nativeUrl.substring(contentUrlMatch[0].length - 1);
+        } else {
+            path = FileSystem.encodeURIPath(fullPath); // eslint-disable-line no-undef
+            if (!/^\//.test(path)) {
+                path = '/' + path;
+            }
+
+            var m = /\?.*/.exec(nativeUrl);
+            if (m) {
+                path += m[0];
+            }
+        }
+
+        return FILESYSTEM_PROTOCOL + '://localhost/' + this.name + path; // eslint-disable-line no-undef
+    }
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..c74fd9c
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+ */

+

+module.exports = function () {

+    // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and

+    // possibly a good flag to indicate that we're running in Chrome

+    return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;

+};

+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..4bfc0f6
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,65 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+    documentsDirectory: null,
+    // BlackBerry10: Files globally available to all apps
+    sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+    function after (paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
new file mode 100644
index 0000000..9351132
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
@@ -0,0 +1,47 @@
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+    function success (response) {
+        fsMap = {};
+        for (var i = 0; i < response.length; ++i) {
+            var fsRoot = response[i];
+            var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+            fsMap[fs.name] = fs;
+        }
+        callback(fsMap[name]);
+    }
+
+    if (fsMap) {
+        callback(fsMap[name]);
+    } else {
+        exec(success, null, 'File', 'requestAllFileSystems', []);
+    }
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..e61ceaf
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+    callback(null);
+};
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..7f65219
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,84 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // For browser platform: not all browsers use this file.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var FileError = require('./FileError');
+    var FileSystem = require('./FileSystem');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Request a file system in which to store application data.
+     * @param type  local file system type
+     * @param size  indicates how much storage space, in bytes, the application expects to need
+     * @param successCallback  invoked with a FileSystem object
+     * @param errorCallback  invoked if error occurs retrieving file system
+     */
+    var requestFileSystem = function (type, size, successCallback, errorCallback) {
+        argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+        var fail = function (code) {
+            if (errorCallback) {
+                errorCallback(new FileError(code));
+            }
+        };
+
+        if (type < 0) {
+            fail(FileError.SYNTAX_ERR);
+        } else {
+            // if successful, return a FileSystem object
+            var success = function (file_system) {
+                if (file_system) {
+                    if (successCallback) {
+                        fileSystems.getFs(file_system.name, function (fs) {
+                            // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                            if (!fs) {
+                                fs = new FileSystem(file_system.name, file_system.root);
+                            }
+                            successCallback(fs);
+                        });
+                    }
+                } else {
+                    // no FileSystem object returned
+                    fail(FileError.NOT_FOUND_ERR);
+                }
+            };
+            exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+        }
+    };
+
+    module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/android/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..73715bc
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Look up file system Entry referred to by local URI.
+     * @param {DOMString} uri  URI referring to a local file or directory
+     * @param successCallback  invoked with Entry object corresponding to URI
+     * @param errorCallback    invoked if error occurs retrieving file system entry
+     */
+    module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+        argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+        // error callback
+        var fail = function (error) {
+            if (errorCallback) {
+                errorCallback(new FileError(error));
+            }
+        };
+        // sanity check for 'not:valid:filename' or '/not:valid:filename'
+        // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+        if (!uri || uri.split(':').length > 2) {
+            setTimeout(function () {
+                fail(FileError.ENCODING_ERR);
+            }, 0);
+            return;
+        }
+        // if successful, return either a file or directory entry
+        var success = function (entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+                    fileSystems.getFs(fsName, function (fs) {
+                        // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                        if (!fs) {
+                            fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+                        }
+                        var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+                        successCallback(result);
+                    });
+                }
+            } else {
+                // no Entry object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+        exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+    };
+
+    module.exports.resolveLocalFileSystemURI = function () {
+        console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+        module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+    };
+})();
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/android/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..3982139
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
+/*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "authenticate",
+    [params]
+  );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "isAvailable",
+    [{}]
+  );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/android/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..a3021c2
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,118 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // special patch to correctly work on Ripple emulator (CB-9760)
+    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+        module.exports = window.open.bind(window); // fallback to default window.open behaviour
+        return;
+    }
+
+    var exec = require('cordova/exec');
+    var channel = require('cordova/channel');
+    var modulemapper = require('cordova/modulemapper');
+    var urlutil = require('cordova/urlutil');
+
+    function InAppBrowser () {
+        this.channels = {
+            'loadstart': channel.create('loadstart'),
+            'loadstop': channel.create('loadstop'),
+            'loaderror': channel.create('loaderror'),
+            'exit': channel.create('exit'),
+            'customscheme': channel.create('customscheme')
+        };
+    }
+
+    InAppBrowser.prototype = {
+        _eventHandler: function (event) {
+            if (event && (event.type in this.channels)) {
+                this.channels[event.type].fire(event);
+            }
+        },
+        close: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'close', []);
+        },
+        show: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'show', []);
+        },
+        hide: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'hide', []);
+        },
+        addEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].subscribe(f);
+            }
+        },
+        removeEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].unsubscribe(f);
+            }
+        },
+
+        executeScript: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('executeScript requires exactly one of code or file to be specified');
+            }
+        },
+
+        insertCSS: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('insertCSS requires exactly one of code or file to be specified');
+            }
+        }
+    };
+
+    module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+        // Don't catch calls that write to existing frames (e.g. named iframes).
+        if (window.frames && window.frames[strWindowName]) {
+            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+            return origOpenFunc.apply(window, arguments);
+        }
+
+        strUrl = urlutil.makeAbsolute(strUrl);
+        var iab = new InAppBrowser();
+
+        callbacks = callbacks || {};
+        for (var callbackName in callbacks) {
+            iab.addEventListener(callbackName, callbacks[callbackName]);
+        }
+
+        var cb = function (eventname) {
+            iab._eventHandler(eventname);
+        };
+
+        strWindowFeatures = strWindowFeatures || '';
+
+        exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+        return iab;
+    };
+})();
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/android/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..2469e9e
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,344 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) {
+// This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+  switch (string) {
+    case '1':
+      return true;
+    case '0':
+      return false;
+    default:
+    throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+  }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+  return {
+    authorized: stringToBool(statusDictionary.authorized),
+    denied: stringToBool(statusDictionary.denied),
+    restricted: stringToBool(statusDictionary.restricted),
+    prepared: stringToBool(statusDictionary.prepared),
+    scanning: stringToBool(statusDictionary.scanning),
+    previewing: stringToBool(statusDictionary.previewing),
+    showing: stringToBool(statusDictionary.showing),
+    lightEnabled: stringToBool(statusDictionary.lightEnabled),
+    canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+    canEnableLight: stringToBool(statusDictionary.canEnableLight),
+    canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+    currentCamera: parseInt(statusDictionary.currentCamera)
+  };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+  var body = document.body;
+  if (body.style) {
+    body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+    body.style.backgroundImage = '';
+    setTimeout(function() {
+      body.style.backgroundColor = 'transparent';
+    }, 1);
+    if (body.parentNode && body.parentNode.style) {
+      body.parentNode.style.backgroundColor = 'transparent';
+      body.parentNode.style.backgroundImage = '';
+    }
+  }
+}
+
+function errorCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(error) {
+    var errorCode = parseInt(error);
+    var QRScannerError = {};
+    switch (errorCode) {
+      case 0:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner experienced an unexpected error.'
+        };
+        break;
+      case 1:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_DENIED',
+          code: 1,
+          _message: 'The user denied camera access.'
+        };
+        break;
+      case 2:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_RESTRICTED',
+          code: 2,
+          _message: 'Camera access is restricted.'
+        };
+        break;
+      case 3:
+        QRScannerError = {
+          name: 'BACK_CAMERA_UNAVAILABLE',
+          code: 3,
+          _message: 'The back camera is unavailable.'
+        };
+        break;
+      case 4:
+        QRScannerError = {
+          name: 'FRONT_CAMERA_UNAVAILABLE',
+          code: 4,
+          _message: 'The front camera is unavailable.'
+        };
+        break;
+      case 5:
+        QRScannerError = {
+          name: 'CAMERA_UNAVAILABLE',
+          code: 5,
+          _message: 'The camera is unavailable.'
+        };
+        break;
+      case 6:
+        QRScannerError = {
+          name: 'SCAN_CANCELED',
+          code: 6,
+          _message: 'Scan was canceled.'
+        };
+        break;
+      case 7:
+        QRScannerError = {
+          name: 'LIGHT_UNAVAILABLE',
+          code: 7,
+          _message: 'The device light is unavailable.'
+        };
+        break;
+      case 8:
+        // Open settings is only available on iOS 8.0+.
+        QRScannerError = {
+          name: 'OPEN_SETTINGS_UNAVAILABLE',
+          code: 8,
+          _message: 'The device is unable to open settings.'
+        };
+        break;
+      default:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner returned an invalid error code.'
+        };
+        break;
+    }
+    callback(QRScannerError);
+  };
+}
+
+function successCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    callback(null, convertStatus(statusDict));
+  };
+}
+
+function doneCallback(callback, clear) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    if (clear) {
+      clearBackground();
+    }
+    callback(convertStatus(statusDict));
+  };
+}
+
+return {
+  prepare: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+  },
+  destroy: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+  },
+  scan: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to scan method.');
+    }
+    var success = function(result) {
+      callback(null, result);
+    };
+    cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+  },
+  cancelScan: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+  },
+  show: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+  },
+  hide: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+  },
+  pausePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+  },
+  resumePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+  },
+  enableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+  },
+  disableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+  },
+  useCamera: function(index, callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+  },
+  useFrontCamera: function(callback) {
+    var frontCamera = 1;
+    if (callback) {
+      this.useCamera(frontCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+    }
+  },
+  useBackCamera: function(callback) {
+    var backCamera = 0;
+    if (callback) {
+      this.useCamera(backCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+    }
+  },
+  openSettings: function(callback) {
+    if (callback) {
+      cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+    }
+  },
+  getStatus: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to getStatus method.');
+    }
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+  }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
new file mode 100644
index 0000000..911ad50
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+*/

+

+var exec = require('cordova/exec');

+

+var splashscreen = {

+    show:function() {

+        exec(null, null, "SplashScreen", "show", []);

+    },

+    hide:function() {

+        exec(null, null, "SplashScreen", "hide", []);

+    }

+};

+

+module.exports = splashscreen;

+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/android/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..708186f
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,116 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+    "black": "#000000",
+    "darkGray": "#A9A9A9",
+    "lightGray": "#D3D3D3",
+    "white": "#FFFFFF",
+    "gray": "#808080",
+    "red": "#FF0000",
+    "green": "#00FF00",
+    "blue": "#0000FF",
+    "cyan": "#00FFFF",
+    "yellow": "#FFFF00",
+    "magenta": "#FF00FF",
+    "orange": "#FFA500",
+    "purple": "#800080",
+    "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+    isVisible: true,
+
+    overlaysWebView: function (doOverlay) {
+        exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+    },
+
+    styleDefault: function () {
+        // dark text ( to be used on a light background )
+        exec(null, null, "StatusBar", "styleDefault", []);
+    },
+
+    styleLightContent: function () {
+        // light text ( to be used on a dark background )
+        exec(null, null, "StatusBar", "styleLightContent", []);
+    },
+
+    styleBlackTranslucent: function () {
+        // #88000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+    },
+
+    styleBlackOpaque: function () {
+        // #FF000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackOpaque", []);
+    },
+
+    backgroundColorByName: function (colorname) {
+        return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+    },
+
+    backgroundColorByHexString: function (hexString) {
+        if (hexString.charAt(0) !== "#") {
+            hexString = "#" + hexString;
+        }
+
+        if (hexString.length === 4) {
+            var split = hexString.split("");
+            hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+        }
+
+        exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+    },
+
+    hide: function () {
+        exec(null, null, "StatusBar", "hide", []);
+        StatusBar.isVisible = false;
+    },
+
+    show: function () {
+        exec(null, null, "StatusBar", "show", []);
+        StatusBar.isVisible = true;
+    }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+    exec(function (res) {
+        if (typeof res == 'object') {
+            if (res.type == 'tap') {
+                cordova.fireWindowEvent('statusTap');
+            }
+        } else {
+            StatusBar.isVisible = res;
+        }
+    }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js b/platforms/android/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
new file mode 100644
index 0000000..9c935cb
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
@@ -0,0 +1,121 @@
+cordova.define("cordova-plugin-themeablebrowser.themeablebrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+function ThemeableBrowser() {
+   this.channels = {};
+}
+
+ThemeableBrowser.prototype = {
+    _eventHandler: function (event) {
+        if (event && (event.type in this.channels)) {
+            this.channels[event.type].fire(event);
+        }
+    },
+    close: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'close', []);
+        return this;
+    },
+    show: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'show', []);
+        return this;
+    },
+    reload: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'reload', []);
+        return this;
+    },
+    addEventListener: function (eventname,f) {
+        if (!(eventname in this.channels)) {
+            this.channels[eventname] = channel.create(eventname);
+        }
+        this.channels[eventname].subscribe(f);
+        return this;
+    },
+    removeEventListener: function(eventname, f) {
+        if (eventname in this.channels) {
+            this.channels[eventname].unsubscribe(f);
+        }
+        return this;
+    },
+
+    executeScript: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('executeScript requires exactly one of code or file to be specified');
+        }
+        return this;
+    },
+
+    insertCSS: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('insertCSS requires exactly one of code or file to be specified');
+        }
+        return this;
+    }
+};
+
+exports.open = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
+    // Don't catch calls that write to existing frames (e.g. named iframes).
+    if (window.frames && window.frames[strWindowName]) {
+        var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+        return origOpenFunc.apply(window, arguments);
+    }
+
+    strUrl = urlutil.makeAbsolute(strUrl);
+    var iab = new ThemeableBrowser();
+
+    callbacks = callbacks || {};
+    for (var callbackName in callbacks) {
+        iab.addEventListener(callbackName, callbacks[callbackName]);
+    }
+
+    var cb = function(eventname) {
+       iab._eventHandler(eventname);
+    };
+
+    strWindowFeatures = strWindowFeatures && JSON.stringify(strWindowFeatures);
+    // Slightly delay the actual native call to give the user a chance to
+    // register event listeners first, otherwise some warnings or errors may be missed.
+    setTimeout(function() {
+        exec(cb, cb, 'ThemeableBrowser', 'open', [strUrl, strWindowName, strWindowFeatures || '']);
+    }, 0);
+    return iab;
+};
+
+exports.EVT_ERR = 'ThemeableBrowserError';
+exports.EVT_WRN = 'ThemeableBrowserWarning';
+exports.ERR_CRITICAL = 'critical';
+exports.ERR_LOADFAIL = 'loadfail';
+exports.WRN_UNEXPECTED = 'unexpected';
+exports.WRN_UNDEFINED = 'undefined';
+});
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/android/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..38a3a85
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) {
+function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+  if (!window.plugins) {
+    window.plugins = {};
+  }
+
+  window.plugins.touchid = new TouchID();
+  return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});
diff --git a/platforms/android/project.properties b/platforms/android/project.properties
new file mode 100644
index 0000000..661238d
--- /dev/null
+++ b/platforms/android/project.properties
@@ -0,0 +1,16 @@
+# This file was originally created by the Android Tools, but is now
+# used by cordova-android to manage the state of the various third party
+# libraries used in your application
+
+# This is the Library Module that contains the Cordova Library, this is not
+# required when using an AAR
+
+# This is the application project.  This is only required for Android Studio Gradle projects
+
+# Project target.
+target=android-28
+android.library.reference.1=CordovaLib
+android.library.reference.2=app
+cordova.system.library.1=com.squareup.okhttp3:okhttp-urlconnection:3.10.0
+cordova.gradle.include.1=cordova-plugin-qrscanner/dlapp-qrscanner.gradle
+cordova.system.library.2=com.android.support:support-v4:24.1.1+
\ No newline at end of file
diff --git a/platforms/android/settings.gradle b/platforms/android/settings.gradle
new file mode 100644
index 0000000..dfb8557
--- /dev/null
+++ b/platforms/android/settings.gradle
@@ -0,0 +1,4 @@
+// GENERATED FILE - DO NOT EDIT
+include ":"
+include ":CordovaLib"
+include ":app"
diff --git a/platforms/android/wrapper.gradle b/platforms/android/wrapper.gradle
new file mode 100644
index 0000000..d7ebabd
--- /dev/null
+++ b/platforms/android/wrapper.gradle
@@ -0,0 +1 @@
+//This file is intentionally just a comment
diff --git a/platforms/browser/browser.json b/platforms/browser/browser.json
new file mode 100644
index 0000000..8ae268b
--- /dev/null
+++ b/platforms/browser/browser.json
@@ -0,0 +1,449 @@
+{
+  "prepare_queue": {
+    "installed": [],
+    "uninstalled": []
+  },
+  "config_munge": {
+    "files": {
+      "config.xml": {
+        "parents": {
+          "/*": [
+            {
+              "xml": "<feature name=\"CordovaHttpPlugin\"><param name=\"browser-package\" value=\"CordovaHttpPlugin\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"QRScanner\"><param name=\"browser-package\" value=\"QRScanner\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Camera\"><param name=\"browser-package\" value=\"Camera\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Device\"><param name=\"browser-package\" value=\"Device\" /></feature>",
+              "count": 1
+            }
+          ]
+        }
+      },
+      "*-Info.plist": {
+        "parents": {
+          "NSCameraUsageDescription": [
+            {
+              "xml": "<string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>",
+              "count": 1,
+              "mode": "merge",
+              "id": "config.xml"
+            }
+          ]
+        }
+      }
+    }
+  },
+  "installed_plugins": {
+    "cordova-plugin-add-swift-support": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-fingerprint-aio": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-touch-id": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-whitelist": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-file": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-advanced-http": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-statusbar": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-disable-ios11-statusbar": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-qrscanner": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-camera": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-inappbrowser": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-device": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-themeablebrowser": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    }
+  },
+  "dependent_plugins": {},
+  "modules": [
+    {
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "id": "cordova-plugin-touch-id.TouchID",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "id": "cordova-plugin-file.DirectoryReader",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "id": "cordova-plugin-file.Entry",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "id": "cordova-plugin-file.File",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "id": "cordova-plugin-file.FileEntry",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "id": "cordova-plugin-file.FileError",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "id": "cordova-plugin-file.FileReader",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "id": "cordova-plugin-file.FileSystem",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "id": "cordova-plugin-file.FileUploadResult",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "id": "cordova-plugin-file.FileWriter",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "id": "cordova-plugin-file.Flags",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "id": "cordova-plugin-file.Metadata",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "id": "cordova-plugin-file.ProgressEvent",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "id": "cordova-plugin-file.fileSystems",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "id": "cordova-plugin-file.requestFileSystem",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "id": "cordova-plugin-file.isChrome",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/browser/Preparing.js",
+      "id": "cordova-plugin-file.Preparing",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-file/src/browser/FileProxy.js",
+      "id": "cordova-plugin-file.browserFileProxy",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-file/www/browser/FileSystem.js",
+      "id": "cordova-plugin-file.firefoxFileSystem",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "id": "cordova-plugin-advanced-http.helpers",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "id": "cordova-plugin-advanced-http.js-util",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "id": "cordova-plugin-advanced-http.lodash",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "id": "cordova-plugin-advanced-http.messages",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "id": "cordova-plugin-advanced-http.url-util",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "id": "cordova-plugin-advanced-http.http",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js",
+      "id": "cordova-plugin-advanced-http.http-proxy",
+      "pluginId": "cordova-plugin-advanced-http",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "id": "cordova-plugin-statusbar.statusbar",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js",
+      "id": "cordova-plugin-statusbar.StatusBarProxy",
+      "pluginId": "cordova-plugin-statusbar",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js",
+      "id": "cordova-plugin-qrscanner.QRScannerProxy",
+      "pluginId": "cordova-plugin-qrscanner",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-camera/www/CameraConstants.js",
+      "id": "cordova-plugin-camera.Camera",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "Camera"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js",
+      "id": "cordova-plugin-camera.CameraPopoverOptions",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "CameraPopoverOptions"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-camera/www/Camera.js",
+      "id": "cordova-plugin-camera.camera",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "navigator.camera"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-camera/src/browser/CameraProxy.js",
+      "id": "cordova-plugin-camera.CameraProxy",
+      "pluginId": "cordova-plugin-camera",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+      "id": "cordova-plugin-inappbrowser.inappbrowser",
+      "pluginId": "cordova-plugin-inappbrowser",
+      "clobbers": [
+        "cordova.InAppBrowser.open",
+        "window.open"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js",
+      "id": "cordova-plugin-inappbrowser.InAppBrowserProxy",
+      "pluginId": "cordova-plugin-inappbrowser",
+      "runs": true
+    },
+    {
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "id": "cordova-plugin-device.device",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "file": "plugins/cordova-plugin-device/src/browser/DeviceProxy.js",
+      "id": "cordova-plugin-device.DeviceProxy",
+      "pluginId": "cordova-plugin-device",
+      "runs": true
+    }
+  ],
+  "plugin_metadata": {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  }
+}
diff --git a/platforms/browser/config.xml b/platforms/browser/config.xml
new file mode 100644
index 0000000..a7be4bc
--- /dev/null
+++ b/platforms/browser/config.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>dlapp</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <allow-intent href="http://*/*" />
+    <allow-intent href="https://*/*" />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*" />
+    <allow-intent href="geo:*" />
+    <allow-navigation href="http://*/*" />
+    <allow-navigation href="https://*/*" />
+    <allow-navigation href="data:*" />
+    <access origin="http://ip*" />
+    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+        <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+    </edit-config>
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="SplashScreenDelay" value="0" />
+    <preference name="ErrorUrl" value="error.html" />
+    <preference name="Orientation" value="portrait" />
+    <preference name="UseSwiftLanguageVersion" value="4.0" />
+    <preference name="DisallowOverscroll" value="true" />
+    <preference name="UIWebViewBounce" value="false" />
+    <preference name="BackupWebStorage" value="local" />
+</widget>
diff --git a/platforms/browser/cordova/Api.js b/platforms/browser/cordova/Api.js
new file mode 100644
index 0000000..da0ec8a
--- /dev/null
+++ b/platforms/browser/cordova/Api.js
@@ -0,0 +1,531 @@
+/**
+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.
+*/
+
+/*
+    this file is found by cordova-lib when you attempt to
+    'cordova platform add PATH' where path is this repo.
+*/
+
+var shell = require('shelljs');
+var path = require('path');
+var fs = require('fs');
+
+var cdvcmn = require('cordova-common');
+var CordovaLogger = cdvcmn.CordovaLogger;
+var ConfigParser = cdvcmn.ConfigParser;
+var ActionStack = cdvcmn.ActionStack;
+var selfEvents = cdvcmn.events;
+var xmlHelpers = cdvcmn.xmlHelpers;
+var PlatformJson = cdvcmn.PlatformJson;
+var PlatformMunger = cdvcmn.ConfigChanges.PlatformMunger;
+var PluginInfoProvider = cdvcmn.PluginInfoProvider;
+
+var BrowserParser = require('./browser_parser');
+var PLATFORM_NAME = 'browser';
+
+function setupEvents (externalEventEmitter) {
+    if (externalEventEmitter) {
+        // This will make the platform internal events visible outside
+        selfEvents.forwardEventsTo(externalEventEmitter);
+        return externalEventEmitter;
+    }
+
+    // There is no logger if external emitter is not present,
+    // so attach a console logger
+    CordovaLogger.get().subscribe(selfEvents);
+    return selfEvents;
+}
+
+function Api (platform, platformRootDir, events) {
+
+    this.platform = platform || PLATFORM_NAME;
+
+    // MyApp/platforms/browser
+    this.root = path.resolve(__dirname, '..');
+    this.events = setupEvents(events);
+    this.parser = new BrowserParser(this.root);
+    this._handler = require('./browser_handler');
+
+    this.locations = {
+        platformRootDir: platformRootDir,
+        root: this.root,
+        www: path.join(this.root, 'www'),
+        res: path.join(this.root, 'res'),
+        platformWww: path.join(this.root, 'platform_www'),
+        configXml: path.join(this.root, 'config.xml'),
+        defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),
+        build: path.join(this.root, 'build'),
+        // NOTE: Due to platformApi spec we need to return relative paths here
+        cordovaJs: 'bin/templates/project/assets/www/cordova.js',
+        cordovaJsSrc: 'cordova-js-src'
+    };
+
+    this._platformJson = PlatformJson.load(this.root, platform);
+    this._pluginInfoProvider = new PluginInfoProvider();
+    this._munger = new PlatformMunger(platform, this.root, this._platformJson, this._pluginInfoProvider);
+}
+
+Api.createPlatform = function (dest, config, options, events) {
+
+    var creator = require('../../lib/create');
+    events = setupEvents(events);
+
+    var name = 'HelloCordova';
+    var id = 'io.cordova.hellocordova';
+    if (config) {
+        name = config.name();
+        id = config.packageName();
+    }
+
+    var result;
+    try {
+        // we create the project using our scripts in this platform
+        result = creator.createProject(dest, id, name, options)
+            .then(function () {
+                // after platform is created we return Api instance based on new Api.js location
+                // Api.js has been copied to the new project
+                // This is required to correctly resolve paths in the future api calls
+                var PlatformApi = require(path.resolve(dest, 'cordova/Api'));
+                return new PlatformApi('browser', dest, events);
+            });
+    } catch (e) {
+        events.emit('error', 'createPlatform is not callable from the browser project API.');
+        throw (e);
+    }
+    return result;
+};
+
+Api.updatePlatform = function (dest, options, events) {
+    // console.log("test-platform:Api:updatePlatform");
+    // todo?: create projectInstance and fulfill promise with it.
+    return Promise.resolve();
+};
+
+Api.prototype.getPlatformInfo = function () {
+    // console.log("browser-platform:Api:getPlatformInfo");
+    // return PlatformInfo object
+    return {
+        'locations': this.locations,
+        'root': this.root,
+        'name': this.platform,
+        'version': { 'version': '1.0.0' }, // um, todo!
+        'projectConfig': this.config
+    };
+};
+
+Api.prototype.prepare = function (cordovaProject, options) {
+
+    // First cleanup current config and merge project's one into own
+    var defaultConfigPath = path.join(this.locations.platformRootDir, 'cordova',
+        'defaults.xml');
+    var ownConfigPath = this.locations.configXml;
+    var sourceCfg = cordovaProject.projectConfig;
+
+    // If defaults.xml is present, overwrite platform config.xml with it.
+    // Otherwise save whatever is there as defaults so it can be
+    // restored or copy project config into platform if none exists.
+    if (fs.existsSync(defaultConfigPath)) {
+        this.events.emit('verbose', 'Generating config.xml from defaults for platform "' + this.platform + '"');
+        shell.cp('-f', defaultConfigPath, ownConfigPath);
+    } else if (fs.existsSync(ownConfigPath)) {
+        this.events.emit('verbose', 'Generating defaults.xml from own config.xml for platform "' + this.platform + '"');
+        shell.cp('-f', ownConfigPath, defaultConfigPath);
+    } else {
+        this.events.emit('verbose', 'case 3"' + this.platform + '"');
+        shell.cp('-f', sourceCfg.path, ownConfigPath);
+    }
+
+    // merge our configs
+    this.config = new ConfigParser(ownConfigPath);
+    xmlHelpers.mergeXml(cordovaProject.projectConfig.doc.getroot(),
+        this.config.doc.getroot(),
+        this.platform, true);
+    this.config.write();
+
+    // Update own www dir with project's www assets and plugins' assets and js-files
+    this.parser.update_www(cordovaProject, options);
+
+    // Copy or Create manifest.json
+    // todo: move this to a manifest helper module
+    // output path
+    var manifestPath = path.join(this.locations.www, 'manifest.json');
+    var srcManifestPath = path.join(cordovaProject.locations.www, 'manifest.json');
+    if (fs.existsSync(srcManifestPath)) {
+        // just blindly copy it to our output/www
+        // todo: validate it? ensure all properties we expect exist?
+        this.events.emit('verbose', 'copying ' + srcManifestPath + ' => ' + manifestPath);
+        shell.cp('-f', srcManifestPath, manifestPath);
+    } else {
+        var manifestJson = {
+            'background_color': '#FFF',
+            'display': 'standalone'
+        };
+        if (this.config) {
+            if (this.config.name()) {
+                manifestJson.name = this.config.name();
+            }
+            if (this.config.shortName()) {
+                manifestJson.short_name = this.config.shortName();
+            }
+            if (this.config.packageName()) {
+                manifestJson.version = this.config.packageName();
+            }
+            if (this.config.description()) {
+                manifestJson.description = this.config.description();
+            }
+            if (this.config.author()) {
+                manifestJson.author = this.config.author();
+            }
+            // icons
+            var icons = this.config.getStaticResources('browser', 'icon');
+            var manifestIcons = icons.map(function (icon) {
+                // given a tag like this :
+                // <icon src="res/ios/icon.png" width="57" height="57" density="mdpi" />
+                /* configParser returns icons that look like this :
+                {   src: 'res/ios/icon.png',
+                    target: undefined,
+                    density: 'mdpi',
+                    platform: null,
+                    width: 57,
+                    height: 57
+                } ******/
+                /* manifest expects them to be like this :
+                {   "src": "images/touch/icon-128x128.png",
+                    "type": "image/png",
+                    "sizes": "128x128"
+                } ******/
+                // ?Is it worth looking at file extentions?
+                return { 'src': icon.src,
+                    'type': 'image/png',
+                    'sizes': (icon.width + 'x' + icon.height) };
+            });
+            manifestJson.icons = manifestIcons;
+
+            // orientation
+            // <preference name="Orientation" value="landscape" />
+            var oriPref = this.config.getGlobalPreference('Orientation');
+            if (oriPref) {
+                // if it's a supported value, use it
+                if (['landscape', 'portrait'].indexOf(oriPref) > -1) {
+                    manifestJson.orientation = oriPref;
+                } else { // anything else maps to 'any'
+                    manifestJson.orientation = 'any';
+                }
+            }
+
+            // get start_url
+            var contentNode = this.config.doc.find('content') || { 'attrib': { 'src': 'index.html' } }; // sensible default
+            manifestJson.start_url = contentNode.attrib.src;
+
+            // now we get some values from start_url page ...
+            var startUrlPath = path.join(cordovaProject.locations.www, manifestJson.start_url);
+            if (fs.existsSync(startUrlPath)) {
+                var contents = fs.readFileSync(startUrlPath, 'utf-8');
+                // matches <meta name="theme-color" content="#FF0044">
+                var themeColorRegex = /<meta(?=[^>]*name="theme-color")\s[^>]*content="([^>]*)"/i;
+                var result = themeColorRegex.exec(contents);
+                var themeColor;
+                if (result && result.length >= 2) {
+                    themeColor = result[1];
+                } else { // see if there is a preference in config.xml
+                    // <preference name="StatusBarBackgroundColor" value="#000000" />
+                    themeColor = this.config.getGlobalPreference('StatusBarBackgroundColor');
+                }
+                if (themeColor) {
+                    manifestJson.theme_color = themeColor;
+                }
+            }
+        }
+        fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 2), 'utf8');
+    }
+
+    // update project according to config.xml changes.
+    return this.parser.update_project(this.config, options);
+};
+
+Api.prototype.addPlugin = function (pluginInfo, installOptions) {
+
+    // console.log(new Error().stack);
+    if (!pluginInfo) {
+        return Promise.reject(new Error('The parameter is incorrect. The first parameter ' +
+            'should be valid PluginInfo instance'));
+    }
+
+    installOptions = installOptions || {};
+    installOptions.variables = installOptions.variables || {};
+    // CB-10108 platformVersion option is required for proper plugin installation
+    installOptions.platformVersion = installOptions.platformVersion ||
+        this.getPlatformInfo().version;
+
+    var self = this;
+    var actions = new ActionStack();
+    var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+    // gather all files needs to be handled during install
+    pluginInfo.getFilesAndFrameworks(this.platform)
+        .concat(pluginInfo.getAssets(this.platform))
+        .concat(pluginInfo.getJsModules(this.platform))
+        .forEach(function (item) {
+            actions.push(actions.createAction(
+                self._getInstaller(item.itemType),
+                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile],
+                self._getUninstaller(item.itemType),
+                [item, pluginInfo.dir, pluginInfo.id, installOptions, projectFile]));
+        });
+
+    // run through the action stack
+    return actions.process(this.platform, this.root)
+        .then(function () {
+            if (projectFile) {
+                projectFile.write();
+            }
+
+            // Add PACKAGE_NAME variable into vars
+            if (!installOptions.variables.PACKAGE_NAME) {
+                installOptions.variables.PACKAGE_NAME = self._handler.package_name(self.root);
+            }
+
+            self._munger
+                // Ignore passed `is_top_level` option since platform itself doesn't know
+                // anything about managing dependencies - it's responsibility of caller.
+                .add_plugin_changes(pluginInfo, installOptions.variables, /* is_top_level= */true, /* should_increment= */true)
+                .save_all();
+
+            var targetDir = installOptions.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.getPlatformInfo().locations.www;
+
+            self._addModulesInfo(pluginInfo, targetDir);
+        });
+};
+
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+    // console.log("NotImplemented :: browser-platform:Api:removePlugin ",plugin, uninstallOptions);
+
+    uninstallOptions = uninstallOptions || {};
+    // CB-10108 platformVersion option is required for proper plugin installation
+    uninstallOptions.platformVersion = uninstallOptions.platformVersion ||
+        this.getPlatformInfo().version;
+
+    var self = this;
+    var actions = new ActionStack();
+    var projectFile = this._handler.parseProjectFile && this._handler.parseProjectFile(this.root);
+
+    // queue up plugin files
+    plugin.getFilesAndFrameworks(this.platform)
+        .concat(plugin.getAssets(this.platform))
+        .concat(plugin.getJsModules(this.platform))
+        .forEach(function (item) {
+            actions.push(actions.createAction(
+                self._getUninstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile],
+                self._getInstaller(item.itemType), [item, plugin.dir, plugin.id, uninstallOptions, projectFile]));
+        });
+
+    // run through the action stack
+    return actions.process(this.platform, this.root)
+        .then(function () {
+            if (projectFile) {
+                projectFile.write();
+            }
+
+            self._munger
+                // Ignore passed `is_top_level` option since platform itself doesn't know
+                // anything about managing dependencies - it's responsibility of caller.
+                .remove_plugin_changes(plugin, /* is_top_level= */true)
+                .save_all();
+
+            var targetDir = uninstallOptions.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self.getPlatformInfo().locations.www;
+
+            self._removeModulesInfo(plugin, targetDir);
+            // Remove stale plugin directory
+            // TODO: this should be done by plugin files uninstaller
+            shell.rm('-rf', path.resolve(self.root, 'Plugins', plugin.id));
+        });
+};
+
+Api.prototype._getInstaller = function (type) {
+    var self = this;
+    return function (item, plugin_dir, plugin_id, options, project) {
+        var installer = self._handler[type];
+
+        if (!installer) {
+            console.log('unrecognized type ' + type);
+
+        } else {
+            var wwwDest = options.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self._handler.www_dir(self.root);
+
+            if (type === 'asset') {
+                installer.install(item, plugin_dir, wwwDest);
+            } else if (type === 'js-module') {
+                installer.install(item, plugin_dir, plugin_id, wwwDest);
+            } else {
+                installer.install(item, plugin_dir, self.root, plugin_id, options, project);
+            }
+        }
+    };
+};
+
+Api.prototype._getUninstaller = function (type) {
+    var self = this;
+    return function (item, plugin_dir, plugin_id, options, project) {
+        var installer = self._handler[type];
+
+        if (!installer) {
+            console.log('browser plugin uninstall: unrecognized type, skipping : ' + type);
+
+        } else {
+            var wwwDest = options.usePlatformWww ?
+                self.getPlatformInfo().locations.platformWww :
+                self._handler.www_dir(self.root);
+
+            if (['asset', 'js-module'].indexOf(type) > -1) {
+                return installer.uninstall(item, wwwDest, plugin_id);
+            } else {
+                return installer.uninstall(item, self.root, plugin_id, options, project);
+            }
+
+        }
+    };
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ *   platform_json and cordova_plugins.js on disk.
+ *
+ * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules
+ *   needs to be added.
+ * @param   {String}  targetDir  The directory, where updated cordova_plugins.js
+ *   should be written to.
+ */
+Api.prototype._addModulesInfo = function (plugin, targetDir) {
+    var installedModules = this._platformJson.root.modules || [];
+
+    var installedPaths = installedModules.map(function (installedModule) {
+        return installedModule.file;
+    });
+
+    var modulesToInstall = plugin.getJsModules(this.platform)
+        .filter(function (moduleToInstall) {
+            return installedPaths.indexOf(moduleToInstall.file) === -1;
+        }).map(function (moduleToInstall) {
+            var moduleName = plugin.id + '.' + (moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1]);
+            var obj = {
+                file: ['plugins', plugin.id, moduleToInstall.src].join('/'), /* eslint no-useless-escape : 0 */
+                id: moduleName,
+                pluginId: plugin.id
+            };
+            if (moduleToInstall.clobbers.length > 0) {
+                obj.clobbers = moduleToInstall.clobbers.map(function (o) { return o.target; });
+            }
+            if (moduleToInstall.merges.length > 0) {
+                obj.merges = moduleToInstall.merges.map(function (o) { return o.target; });
+            }
+            if (moduleToInstall.runs) {
+                obj.runs = true;
+            }
+
+            return obj;
+        });
+
+    this._platformJson.root.modules = installedModules.concat(modulesToInstall);
+    if (!this._platformJson.root.plugin_metadata) {
+        this._platformJson.root.plugin_metadata = {};
+    }
+    this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;
+
+    this._writePluginModules(targetDir);
+    this._platformJson.save();
+};
+/**
+ * Fetches all installed modules, generates cordova_plugins contents and writes
+ *   it to file.
+ *
+ * @param   {String}  targetDir  Directory, where write cordova_plugins.js to.
+ *   Ususally it is either <platform>/www or <platform>/platform_www
+ *   directories.
+ */
+Api.prototype._writePluginModules = function (targetDir) {
+    // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
+    var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
+    final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, '    ') + ';\n';
+    final_contents += 'module.exports.metadata = \n';
+    final_contents += '// TOP OF METADATA\n';
+    final_contents += JSON.stringify(this._platformJson.root.plugin_metadata || {}, null, '    ') + '\n';
+    final_contents += '// BOTTOM OF METADATA\n';
+    final_contents += '});'; // Close cordova.define.
+
+    shell.mkdir('-p', targetDir);
+    fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ *   platform_json and cordova_plugins.js on disk.
+ *
+ * @param   {PluginInfo}  plugin  PluginInfo instance for plugin, which modules
+ *   needs to be removed.
+ * @param   {String}  targetDir  The directory, where updated cordova_plugins.js
+ *   should be written to.
+ */
+Api.prototype._removeModulesInfo = function (plugin, targetDir) {
+    var installedModules = this._platformJson.root.modules || [];
+    var modulesToRemove = plugin.getJsModules(this.platform)
+        .map(function (jsModule) {
+            return ['plugins', plugin.id, jsModule.src].join('/');
+        });
+
+    var updatedModules = installedModules
+        .filter(function (installedModule) {
+            return (modulesToRemove.indexOf(installedModule.file) === -1);
+        });
+
+    this._platformJson.root.modules = updatedModules;
+    if (this._platformJson.root.plugin_metadata) {
+        delete this._platformJson.root.plugin_metadata[plugin.id];
+    }
+
+    this._writePluginModules(targetDir);
+    this._platformJson.save();
+};
+
+Api.prototype.build = function (buildOptions) {
+    var self = this;
+    return require('./lib/check_reqs').run()
+        .then(function () {
+            return require('./lib/build').run.call(self, buildOptions);
+        });
+};
+
+Api.prototype.run = function (runOptions) {
+    return require('./lib/run').run(runOptions);
+};
+
+Api.prototype.clean = function (cleanOptions) {
+    return require('./lib/clean').run(cleanOptions);
+};
+
+Api.prototype.requirements = function () {
+    return require('./lib/check_reqs').run();
+};
+
+module.exports = Api;
diff --git a/platforms/browser/cordova/browser_handler.js b/platforms/browser/cordova/browser_handler.js
new file mode 100644
index 0000000..bccddb4
--- /dev/null
+++ b/platforms/browser/cordova/browser_handler.js
@@ -0,0 +1,135 @@
+/**
+    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.
+*/
+
+var path = require('path');
+var fs = require('fs');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+
+module.exports = {
+    www_dir: function (project_dir) {
+        return path.join(project_dir, 'www');
+    },
+    package_name: function (project_dir) {
+        // this method should the id from root config.xml => <widget id=xxx
+        // return common.package_name(project_dir, this.www_dir(project_dir));
+        // console.log('package_name called with ' + project_dir);
+        var pkgName = 'io.cordova.hellocordova';
+        var widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
+
+        var configPath = path.join(project_dir, 'config.xml');
+        if (fs.existsSync(configPath)) {
+            var configStr = fs.readFileSync(configPath, 'utf8');
+            var res = configStr.match(widget_id_regex);
+            if (res && res.length > 1) {
+                pkgName = res[1];
+            }
+        }
+        return pkgName;
+    },
+    'js-module': {
+        install: function (jsModule, plugin_dir, plugin_id, www_dir) {
+            // Copy the plugin's files into the www directory.
+            var moduleSource = path.resolve(plugin_dir, jsModule.src);
+            // Get module name based on existing 'name' attribute or filename
+            // Must use path.extname/path.basename instead of path.parse due to CB-9981
+            var moduleName = plugin_id + '.' + (jsModule.name || path.basename(jsModule.src, path.extname(jsModule.src)));
+
+            // Read in the file, prepend the cordova.define, and write it back out.
+            var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+            if (moduleSource.match(/.*\.json$/)) {
+                scriptContent = 'module.exports = ' + scriptContent;
+            }
+            scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) { ' + scriptContent + '\n});\n';
+
+            var moduleDestination = path.resolve(www_dir, 'plugins', plugin_id, jsModule.src);
+            shell.mkdir('-p', path.dirname(moduleDestination));
+            fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+        },
+        uninstall: function (jsModule, www_dir, plugin_id) {
+            var pluginRelativePath = path.join('plugins', plugin_id, jsModule.src);
+            // common.removeFileAndParents(www_dir, pluginRelativePath);
+            console.log('js-module uninstall called : ' + pluginRelativePath);
+        }
+    },
+    'source-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            // var dest = path.join(obj.targetDir, path.basename(obj.src));
+            // common.copyFile(plugin_dir, obj.src, project_dir, dest);
+            console.log('install called');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            // var dest = path.join(obj.targetDir, path.basename(obj.src));
+            // common.removeFile(project_dir, dest);
+            console.log('uninstall called');
+        }
+    },
+    'header-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'header-fileinstall is not supported for browser');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'header-file.uninstall is not supported for browser');
+        }
+    },
+    'resource-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'resource-file.install is not supported for browser');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'resource-file.uninstall is not supported for browser');
+        }
+    },
+    'framework': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'framework.install is not supported for browser');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'framework.uninstall is not supported for browser');
+        }
+    },
+    'lib-file': {
+        install: function (obj, plugin_dir, project_dir, plugin_id, options) {
+            events.emit('verbose', 'lib-file.install is not supported for browser');
+        },
+        uninstall: function (obj, project_dir, plugin_id, options) {
+            events.emit('verbose', 'lib-file.uninstall is not supported for browser');
+        }
+    },
+    asset: {
+        install: function (asset, plugin_dir, wwwDest) {
+            var src = path.join(plugin_dir, asset.src);
+            var dest = path.join(wwwDest, asset.target);
+            var destDir = path.parse(dest).dir;
+            if (destDir !== '' && !fs.existsSync(destDir)) {
+                shell.mkdir('-p', destDir);
+            }
+
+            if (fs.statSync(src).isDirectory()) {
+                shell.cp('-Rf', src + '/*', dest);
+            } else {
+                shell.cp('-f', src, dest);
+            }
+        },
+        uninstall: function (asset, wwwDest, plugin_id) {
+            shell.rm('-rf', path.join(wwwDest, asset.target));
+            shell.rm('-rf', path.join(wwwDest, 'plugins', plugin_id));
+        }
+    }
+};
diff --git a/platforms/browser/cordova/browser_parser.js b/platforms/browser/cordova/browser_parser.js
new file mode 100644
index 0000000..99397c3
--- /dev/null
+++ b/platforms/browser/cordova/browser_parser.js
@@ -0,0 +1,120 @@
+/**
+    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.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var CordovaError = require('cordova-common').CordovaError;
+var events = require('cordova-common').events;
+var FileUpdater = require('cordova-common').FileUpdater;
+
+function dirExists (dir) {
+    return fs.existsSync(dir) && fs.statSync(dir).isDirectory();
+}
+
+function browser_parser (project) {
+    if (!dirExists(project) || !dirExists(path.join(project, 'cordova'))) {
+        throw new CordovaError('The provided path "' + project + '" is not a valid browser project.');
+    }
+    this.path = project;
+}
+
+module.exports = browser_parser;
+
+// Returns a promise.
+browser_parser.prototype.update_from_config = function () {
+    return Promise.resolve();
+};
+
+browser_parser.prototype.www_dir = function () {
+    return path.join(this.path, 'www');
+};
+
+// Used for creating platform_www in projects created by older versions.
+browser_parser.prototype.cordovajs_path = function (libDir) {
+    var jsPath = path.join(libDir, 'cordova-lib', 'cordova.js');
+    return path.resolve(jsPath);
+};
+
+browser_parser.prototype.cordovajs_src_path = function (libDir) {
+    // console.log("cordovajs_src_path");
+    var jsPath = path.join(libDir, 'cordova-js-src');
+    return path.resolve(jsPath);
+};
+
+/**
+ * Logs all file operations via the verbose event stream, indented.
+ */
+function logFileOp (message) {
+    events.emit('verbose', '  ' + message);
+}
+
+// Replace the www dir with contents of platform_www and app www.
+browser_parser.prototype.update_www = function (cordovaProject, opts) {
+    var platform_www = path.join(this.path, 'platform_www');
+    var my_www = this.www_dir();
+    // add cordova www and platform_www to sourceDirs
+    var sourceDirs = [
+        path.relative(cordovaProject.root, cordovaProject.locations.www),
+        path.relative(cordovaProject.root, platform_www)
+    ];
+
+    // If project contains 'merges' for our platform, use them as another overrides
+    var merges_path = path.join(cordovaProject.root, 'merges', 'browser');
+    if (fs.existsSync(merges_path)) {
+        events.emit('verbose', 'Found "merges/browser" folder. Copying its contents into the browser project.');
+        // add merges/browser to sourceDirs
+        sourceDirs.push(path.join('merges', 'browser'));
+    }
+
+    // targetDir points to browser/www
+    var targetDir = path.relative(cordovaProject.root, my_www);
+    events.emit('verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+    FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+};
+
+browser_parser.prototype.update_overrides = function () {
+    // console.log("update_overrides");
+
+    // TODO: ?
+    // var projectRoot = util.isCordova(this.path);
+    // var mergesPath = path.join(util.appDir(projectRoot), 'merges', 'browser');
+    // if(fs.existsSync(mergesPath)) {
+    //     var overrides = path.join(mergesPath, '*');
+    //     shell.cp('-rf', overrides, this.www_dir());
+    // }
+};
+
+browser_parser.prototype.config_xml = function () {
+    return path.join(this.path, 'config.xml');
+};
+
+// Returns a promise.
+browser_parser.prototype.update_project = function (cfg) {
+    // console.log("update_project ",cfg);
+    var defer = this.update_from_config();
+    var self = this;
+    var www_dir = self.www_dir();
+    defer.then(function () {
+        self.update_overrides();
+        // Copy munged config.xml to platform www dir
+        shell.cp('-rf', path.join(www_dir, '..', 'config.xml'), www_dir);
+    });
+    return defer;
+};
diff --git a/platforms/browser/cordova/build b/platforms/browser/cordova/build
new file mode 100755
index 0000000..e867ab1
--- /dev/null
+++ b/platforms/browser/cordova/build
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var build = require('./lib/build'),
+    args  = process.argv;
+
+// provide help
+if ( args[2] == '--help' || args[2] == '/?' || args[2] == '-h' || args[2] == '/h' ||
+                    args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
+    build.help();
+    process.exit(0);
+} else {
+
+    build.run();
+}
diff --git a/platforms/browser/cordova/build.bat b/platforms/browser/cordova/build.bat
new file mode 100644
index 0000000..02641bc
--- /dev/null
+++ b/platforms/browser/cordova/build.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0build"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/browser/cordova/clean b/platforms/browser/cordova/clean
new file mode 100644
index 0000000..1852d66
--- /dev/null
+++ b/platforms/browser/cordova/clean
@@ -0,0 +1,36 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var path = require('path'),
+    clean = require('./lib/clean'),
+    args  = process.argv;
+
+// Support basic help commands
+if ( args.length > 2
+   || args[2] == '--help' || args[2] == '/?' || args[2] == '-h' ||
+                    args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
+    console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'clean')) );
+    process.exit(0);
+} else {
+    clean.run();
+}
+
diff --git a/platforms/browser/cordova/clean.bat b/platforms/browser/cordova/clean.bat
new file mode 100644
index 0000000..5c572aa
--- /dev/null
+++ b/platforms/browser/cordova/clean.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0clean"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/browser/cordova/defaults.xml b/platforms/browser/cordova/defaults.xml
new file mode 100644
index 0000000..a7b31c0
--- /dev/null
+++ b/platforms/browser/cordova/defaults.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+
+</widget>
diff --git a/platforms/browser/cordova/lib/build.js b/platforms/browser/cordova/lib/build.js
new file mode 100644
index 0000000..01f3fb1
--- /dev/null
+++ b/platforms/browser/cordova/lib/build.js
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+
+/*
+ * 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.
+ */
+
+var path = require('path');
+var check_reqs = require('./check_reqs');
+
+/**
+ * run
+ *   Creates a zip file int platform/build folder
+ */
+module.exports.run = function () {
+    return check_reqs.run();
+};
+
+module.exports.help = function () {
+    console.log('Usage: cordova build browser');
+    var wwwPath = path.resolve(path.join(__dirname, '../../www'));
+    console.log("Build will create the packaged app in '" + wwwPath + "'.");
+};
diff --git a/platforms/browser/cordova/lib/check_reqs.js b/platforms/browser/cordova/lib/check_reqs.js
new file mode 100644
index 0000000..c615e14
--- /dev/null
+++ b/platforms/browser/cordova/lib/check_reqs.js
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+/*
+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.
+*/
+
+// add methods as we determine what are the requirements
+
+module.exports.run = function () {
+    // caller expects a promise resolved with an array of conditions
+    return Promise.resolve([]);
+};
diff --git a/platforms/browser/cordova/lib/clean.js b/platforms/browser/cordova/lib/clean.js
new file mode 100644
index 0000000..6ee7675
--- /dev/null
+++ b/platforms/browser/cordova/lib/clean.js
@@ -0,0 +1,51 @@
+#!/usr/bin/env node
+
+/*
+ * 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.
+ */
+
+var fs = require('fs');
+var shell = require('shelljs');
+var path = require('path');
+var check_reqs = require('./check_reqs');
+var platformBuildDir = path.join('platforms', 'browser', 'www');
+
+var run = function () {
+
+    // TODO: everything calls check_reqs ... why?
+    // Check that requirements are (still) met
+    if (!check_reqs.run()) {
+        console.error('Please make sure you meet the software requirements in order to clean an browser cordova project');
+        process.exit(2);
+    }
+
+    try {
+        if (fs.existsSync(platformBuildDir)) {
+            shell.rm('-r', platformBuildDir);
+        }
+    } catch (err) {
+        console.log('could not remove ' + platformBuildDir + ' : ' + err.message);
+    }
+};
+
+module.exports.run = run;
+// just on the off chance something is still calling cleanProject, we will leave this here for a while
+module.exports.cleanProject = function () {
+    console.log('lib/clean will soon only export a `run` command, please update to not call `cleanProject`.');
+    return run();
+};
diff --git a/platforms/browser/cordova/lib/run.js b/platforms/browser/cordova/lib/run.js
new file mode 100644
index 0000000..0846231
--- /dev/null
+++ b/platforms/browser/cordova/lib/run.js
@@ -0,0 +1,68 @@
+#!/usr/bin/env node
+
+/*
+ * 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.
+ */
+
+var fs = require('fs');
+var path = require('path');
+var url = require('url');
+var cordovaServe = require('cordova-serve');
+
+module.exports.run = function (args) {
+    // defaults
+    args.port = args.port || 8000;
+    args.target = args.target || 'default'; // make default the system browser
+    args.noLogOutput = args.silent || false;
+
+    var wwwPath = path.join(__dirname, '../../www');
+    var manifestFilePath = path.resolve(path.join(wwwPath, 'manifest.json'));
+
+    var startPage;
+
+    // get start page from manifest
+    if (fs.existsSync(manifestFilePath)) {
+        try {
+            var manifest = require(manifestFilePath);
+            startPage = manifest.start_url;
+        } catch (err) {
+            console.log('failed to require manifest ... ' + err);
+        }
+    }
+
+    var server = cordovaServe();
+    server.servePlatform('browser', { port: args.port, noServerInfo: true, noLogOutput: args.noLogOutput })
+        .then(function () {
+            if (!startPage) {
+                // failing all else, set the default
+                startPage = 'index.html';
+            }
+
+            var projectUrl = (new url.URL(`http://localhost:${server.port}/${startPage}`)).href;
+
+            console.log('startPage = ' + startPage);
+            console.log('Static file server running @ ' + projectUrl + '\nCTRL + C to shut down');
+            return server.launchBrowser({ 'target': args.target, 'url': projectUrl });
+        })
+        .catch(function (error) {
+            console.log(error.message || error.toString());
+            if (server.server) {
+                server.server.close();
+            }
+        });
+};
diff --git a/platforms/browser/cordova/log b/platforms/browser/cordova/log
new file mode 100755
index 0000000..bb6fb8c
--- /dev/null
+++ b/platforms/browser/cordova/log
@@ -0,0 +1,20 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+console.log("cordova/log");
\ No newline at end of file
diff --git a/platforms/browser/cordova/run b/platforms/browser/cordova/run
new file mode 100755
index 0000000..b41e299
--- /dev/null
+++ b/platforms/browser/cordova/run
@@ -0,0 +1,53 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var fs = require('fs'),
+    path = require('path'),
+    nopt  = require('nopt'),
+    url = require('url'),
+    runForrest = require('./lib/run'),
+    cordovaServe = require('cordova-serve');
+
+var args = process.argv;
+
+start(args);
+
+function start(argv) {
+    var args  = nopt({'help': Boolean, 'target': String, 'port': Number}, {'help': ['/?', '-h', 'help', '-help', '/help']}, argv);
+    if(args.help) {
+        help();
+    }
+    else {
+        return runForrest.run(args);
+    }
+}
+
+function help() {
+    console.log("\nUsage: run [ --target=<browser> ] [ --port=<number> ]");
+    console.log("    --target=<browser> : Launches the specified browser. Chrome is default.");
+    console.log("    --port=<number>    : Http server uses specified port number.");
+    console.log("Examples:");
+    console.log("    run");
+    console.log("    run -- --target=ie");
+    console.log("    run -- --target=chrome --port=8000");
+    console.log("");
+    process.exit(0);
+}
diff --git a/platforms/browser/cordova/run.bat b/platforms/browser/cordova/run.bat
new file mode 100644
index 0000000..b9c4402
--- /dev/null
+++ b/platforms/browser/cordova/run.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0run"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'run' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/browser/cordova/version b/platforms/browser/cordova/version
new file mode 100755
index 0000000..814b805
--- /dev/null
+++ b/platforms/browser/cordova/version
@@ -0,0 +1,25 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+// Coho updates this line:
+var VERSION = "6.0.0";
+
+console.log(VERSION);
diff --git a/platforms/browser/cordova/version.bat b/platforms/browser/cordova/version.bat
new file mode 100644
index 0000000..3610c17
--- /dev/null
+++ b/platforms/browser/cordova/version.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0version"
+IF EXIST %script_path% (
+        node %script_path% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/browser/platform_www/cordova-js-src/confighelper.js b/platforms/browser/platform_www/cordova-js-src/confighelper.js
new file mode 100644
index 0000000..34d8b19
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/confighelper.js
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+var config;
+
+function Config(xhr) {
+    function loadPreferences(xhr) {
+       var parser = new DOMParser();
+       var doc = parser.parseFromString(xhr.responseText, "application/xml");
+
+       var preferences = doc.getElementsByTagName("preference");
+       return Array.prototype.slice.call(preferences);
+    }
+
+    this.xhr = xhr;
+    this.preferences = loadPreferences(this.xhr);
+}
+
+function readConfig(success, error) {
+    var xhr;
+
+    if(typeof config != 'undefined') {
+        success(config);
+    }
+
+    function fail(msg) {
+        console.error(msg);
+
+        if(error) {
+            error(msg);
+        }
+    }
+
+    var xhrStatusChangeHandler = function() {
+        if (xhr.readyState == 4) {
+            if (xhr.status == 200 || xhr.status == 304 || xhr.status === 0 /* file:// */) {
+                config = new Config(xhr);
+                success(config);
+            }
+            else {
+                fail('[Browser][cordova.js][xhrStatusChangeHandler] Could not XHR config.xml: ' + xhr.statusText);
+            }
+        }
+    };
+
+    xhr = new XMLHttpRequest();
+    xhr.addEventListener("load", xhrStatusChangeHandler);
+
+
+    try {
+        xhr.open("get", "config.xml", true);
+        xhr.send();
+    } catch(e) {
+        fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
+    }
+}
+
+/**
+ * Reads a preference value from config.xml.
+ * Returns preference value or undefined if it does not exist.
+ * @param {String} preferenceName Preference name to read */
+Config.prototype.getPreferenceValue = function getPreferenceValue(preferenceName) {
+    var preferenceItem = this.preferences && this.preferences.filter(function(item) {
+        return item.attributes.name && item.attributes.name.value === preferenceName;
+    });
+
+    if(preferenceItem && preferenceItem[0] && preferenceItem[0].attributes && preferenceItem[0].attributes.value) {
+        return preferenceItem[0].attributes.value.value;
+    }
+};
+
+exports.readConfig = readConfig;
diff --git a/platforms/browser/platform_www/cordova-js-src/exec.js b/platforms/browser/platform_www/cordova-js-src/exec.js
new file mode 100644
index 0000000..97f736a
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/exec.js
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
+var cordova = require('cordova');
+var execProxy = require('cordova/exec/proxy');
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
+
+    var proxy = execProxy.get(service, action);
+
+    args = args || [];
+
+    if (proxy) {
+        
+        var callbackId = service + cordova.callbackId++;
+        
+        if (typeof success === "function" || typeof fail === "function") {
+            cordova.callbacks[callbackId] = {success: success, fail: fail};
+        }
+        try {
+
+            
+
+            // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+            // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+            var onSuccess = function (result, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // see CB-8996 Mobilespec app hang on windows
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+                    {
+                        status: callbackStatus,
+                        message: result,
+                        keepCallback: callbackOptions.keepCallback || false
+                    });
+            };
+            var onError = function (err, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // note: status can be 0
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackError(callbackOptions.callbackId || callbackId,
+                {
+                    status: callbackStatus,
+                    message: err,
+                    keepCallback: callbackOptions.keepCallback || false
+                });
+            };
+            proxy(onSuccess, onError, args);
+
+        } catch (e) {
+            console.log("Exception calling native with command :: " + service + " :: " + action  + " ::exception=" + e);
+        }
+    } else {
+
+        console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+        
+        if(typeof fail === "function" ) {
+            fail("Missing Command Error");
+        }
+    }
+};
diff --git a/platforms/browser/platform_www/cordova-js-src/platform.js b/platforms/browser/platform_www/cordova-js-src/platform.js
new file mode 100644
index 0000000..96eb943
--- /dev/null
+++ b/platforms/browser/platform_www/cordova-js-src/platform.js
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+module.exports = {
+    id: 'browser',
+    cordovaVersion: '4.2.0', // cordova-js
+
+    bootstrap: function() {
+
+        var modulemapper = require('cordova/modulemapper');
+        var channel = require('cordova/channel');
+
+        modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy');
+
+        channel.onNativeReady.fire();
+
+        document.addEventListener("visibilitychange", function(){
+            if(document.hidden) {
+                channel.onPause.fire();
+            }
+            else {
+                channel.onResume.fire();
+            }
+        });
+
+    // End of bootstrap
+    }
+};
diff --git a/platforms/browser/platform_www/cordova.js b/platforms/browser/platform_www/cordova.js
new file mode 100644
index 0000000..02de9c7
--- /dev/null
+++ b/platforms/browser/platform_www/cordova.js
@@ -0,0 +1,1594 @@
+// Platform: browser
+// d07d9d0989196f1b90fe962ca68f5ceb355c69ec
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '6.0.0';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
+            'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/confighelper.js
+define("cordova/confighelper", function(require, exports, module) {
+
+var config;
+
+function Config(xhr) {
+    function loadPreferences(xhr) {
+       var parser = new DOMParser();
+       var doc = parser.parseFromString(xhr.responseText, "application/xml");
+
+       var preferences = doc.getElementsByTagName("preference");
+       return Array.prototype.slice.call(preferences);
+    }
+
+    this.xhr = xhr;
+    this.preferences = loadPreferences(this.xhr);
+}
+
+function readConfig(success, error) {
+    var xhr;
+
+    if(typeof config != 'undefined') {
+        success(config);
+    }
+
+    function fail(msg) {
+        console.error(msg);
+
+        if(error) {
+            error(msg);
+        }
+    }
+
+    var xhrStatusChangeHandler = function() {
+        if (xhr.readyState == 4) {
+            if (xhr.status == 200 || xhr.status == 304 || xhr.status === 0 /* file:// */) {
+                config = new Config(xhr);
+                success(config);
+            }
+            else {
+                fail('[Browser][cordova.js][xhrStatusChangeHandler] Could not XHR config.xml: ' + xhr.statusText);
+            }
+        }
+    };
+
+    xhr = new XMLHttpRequest();
+    xhr.addEventListener("load", xhrStatusChangeHandler);
+
+
+    try {
+        xhr.open("get", "config.xml", true);
+        xhr.send();
+    } catch(e) {
+        fail('[Browser][cordova.js][readConfig] Could not XHR config.xml: ' + JSON.stringify(e));
+    }
+}
+
+/**
+ * Reads a preference value from config.xml.
+ * Returns preference value or undefined if it does not exist.
+ * @param {String} preferenceName Preference name to read */
+Config.prototype.getPreferenceValue = function getPreferenceValue(preferenceName) {
+    var preferenceItem = this.preferences && this.preferences.filter(function(item) {
+        return item.attributes.name && item.attributes.name.value === preferenceName;
+    });
+
+    if(preferenceItem && preferenceItem[0] && preferenceItem[0].attributes && preferenceItem[0].attributes.value) {
+        return preferenceItem[0].attributes.value.value;
+    }
+};
+
+exports.readConfig = readConfig;
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/*jslint sloppy:true, plusplus:true*/
+/*global require, module, console */
+
+var cordova = require('cordova');
+var execProxy = require('cordova/exec/proxy');
+
+/**
+ * Execute a cordova command.  It is up to the native side whether this action
+ * is synchronous or asynchronous.  The native side can return:
+ *      Synchronous: PluginResult object as a JSON string
+ *      Asynchronous: Empty string ""
+ * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
+ * depending upon the result of the action.
+ *
+ * @param {Function} success    The success callback
+ * @param {Function} fail       The fail callback
+ * @param {String} service      The name of the service to use
+ * @param {String} action       Action to be run in cordova
+ * @param {String[]} [args]     Zero or more arguments to pass to the method
+ */
+module.exports = function (success, fail, service, action, args) {
+
+    var proxy = execProxy.get(service, action);
+
+    args = args || [];
+
+    if (proxy) {
+        
+        var callbackId = service + cordova.callbackId++;
+        
+        if (typeof success === "function" || typeof fail === "function") {
+            cordova.callbacks[callbackId] = {success: success, fail: fail};
+        }
+        try {
+
+            
+
+            // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+            // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+            var onSuccess = function (result, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // see CB-8996 Mobilespec app hang on windows
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+                    {
+                        status: callbackStatus,
+                        message: result,
+                        keepCallback: callbackOptions.keepCallback || false
+                    });
+            };
+            var onError = function (err, callbackOptions) {
+                callbackOptions = callbackOptions || {};
+                var callbackStatus;
+                // covering both undefined and null.
+                // strict null comparison was causing callbackStatus to be undefined
+                // and then no callback was called because of the check in cordova.callbackFromNative
+                // note: status can be 0
+                if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+                    callbackStatus = callbackOptions.status;
+                }
+                else {
+                    callbackStatus = cordova.callbackStatus.OK;
+                }
+                cordova.callbackError(callbackOptions.callbackId || callbackId,
+                {
+                    status: callbackStatus,
+                    message: err,
+                    keepCallback: callbackOptions.keepCallback || false
+                });
+            };
+            proxy(onSuccess, onError, args);
+
+        } catch (e) {
+            console.log("Exception calling native with command :: " + service + " :: " + action  + " ::exception=" + e);
+        }
+    } else {
+
+        console.log("Error: exec proxy not found for :: " + service + " :: " + action);
+        
+        if(typeof fail === "function" ) {
+            fail("Missing Command Error");
+        }
+    }
+};
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/erisu/git/apache/cordova/cordova-browser/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+    id: 'browser',
+    cordovaVersion: '4.2.0', // cordova-js
+
+    bootstrap: function() {
+
+        var modulemapper = require('cordova/modulemapper');
+        var channel = require('cordova/channel');
+
+        modulemapper.clobbers('cordova/exec/proxy', 'cordova.commandProxy');
+
+        channel.onNativeReady.fire();
+
+        document.addEventListener("visibilitychange", function(){
+            if(document.hidden) {
+                channel.onPause.fire();
+            }
+            else {
+                channel.onResume.fire();
+            }
+        });
+
+    // End of bootstrap
+    }
+};
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/browser/platform_www/cordova_plugins.js b/platforms/browser/platform_www/cordova_plugins.js
new file mode 100644
index 0000000..2b5f2ff
--- /dev/null
+++ b/platforms/browser/platform_www/cordova_plugins.js
@@ -0,0 +1,368 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+module.exports = [
+    {
+        "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+        "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+        "pluginId": "cordova-plugin-fingerprint-aio",
+        "clobbers": [
+            "Fingerprint"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+        "id": "cordova-plugin-touch-id.TouchID",
+        "pluginId": "cordova-plugin-touch-id",
+        "clobbers": [
+            "window.plugins.touchid"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+        "id": "cordova-plugin-file.DirectoryEntry",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.DirectoryEntry"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+        "id": "cordova-plugin-file.DirectoryReader",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.DirectoryReader"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/Entry.js",
+        "id": "cordova-plugin-file.Entry",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.Entry"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/File.js",
+        "id": "cordova-plugin-file.File",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.File"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+        "id": "cordova-plugin-file.FileEntry",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileEntry"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileError.js",
+        "id": "cordova-plugin-file.FileError",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileError"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileReader.js",
+        "id": "cordova-plugin-file.FileReader",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileReader"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+        "id": "cordova-plugin-file.FileSystem",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileSystem"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+        "id": "cordova-plugin-file.FileUploadOptions",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileUploadOptions"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+        "id": "cordova-plugin-file.FileUploadResult",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileUploadResult"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+        "id": "cordova-plugin-file.FileWriter",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.FileWriter"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/Flags.js",
+        "id": "cordova-plugin-file.Flags",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.Flags"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+        "id": "cordova-plugin-file.LocalFileSystem",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.LocalFileSystem"
+        ],
+        "merges": [
+            "window"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/Metadata.js",
+        "id": "cordova-plugin-file.Metadata",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.Metadata"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+        "id": "cordova-plugin-file.ProgressEvent",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.ProgressEvent"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+        "id": "cordova-plugin-file.fileSystems",
+        "pluginId": "cordova-plugin-file"
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+        "id": "cordova-plugin-file.requestFileSystem",
+        "pluginId": "cordova-plugin-file",
+        "clobbers": [
+            "window.requestFileSystem"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+        "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+        "pluginId": "cordova-plugin-file",
+        "merges": [
+            "window"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+        "id": "cordova-plugin-file.isChrome",
+        "pluginId": "cordova-plugin-file",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/browser/Preparing.js",
+        "id": "cordova-plugin-file.Preparing",
+        "pluginId": "cordova-plugin-file",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-file/src/browser/FileProxy.js",
+        "id": "cordova-plugin-file.browserFileProxy",
+        "pluginId": "cordova-plugin-file",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+        "id": "cordova-plugin-file.fileSystemPaths",
+        "pluginId": "cordova-plugin-file",
+        "merges": [
+            "cordova"
+        ],
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-file/www/browser/FileSystem.js",
+        "id": "cordova-plugin-file.firefoxFileSystem",
+        "pluginId": "cordova-plugin-file",
+        "merges": [
+            "window.FileSystem"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+        "id": "cordova-plugin-advanced-http.cookie-handler",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+        "id": "cordova-plugin-advanced-http.global-configs",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+        "id": "cordova-plugin-advanced-http.helpers",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+        "id": "cordova-plugin-advanced-http.js-util",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+        "id": "cordova-plugin-advanced-http.local-storage-store",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+        "id": "cordova-plugin-advanced-http.lodash",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+        "id": "cordova-plugin-advanced-http.messages",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+        "id": "cordova-plugin-advanced-http.public-interface",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+        "id": "cordova-plugin-advanced-http.tough-cookie",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+        "id": "cordova-plugin-advanced-http.url-util",
+        "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+        "id": "cordova-plugin-advanced-http.http",
+        "pluginId": "cordova-plugin-advanced-http",
+        "clobbers": [
+            "cordova.plugin.http"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js",
+        "id": "cordova-plugin-advanced-http.http-proxy",
+        "pluginId": "cordova-plugin-advanced-http",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+        "id": "cordova-plugin-statusbar.statusbar",
+        "pluginId": "cordova-plugin-statusbar",
+        "clobbers": [
+            "window.StatusBar"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js",
+        "id": "cordova-plugin-statusbar.StatusBarProxy",
+        "pluginId": "cordova-plugin-statusbar",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+        "id": "cordova-plugin-qrscanner.QRScanner",
+        "pluginId": "cordova-plugin-qrscanner",
+        "clobbers": [
+            "QRScanner"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js",
+        "id": "cordova-plugin-qrscanner.QRScannerProxy",
+        "pluginId": "cordova-plugin-qrscanner",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-camera/www/CameraConstants.js",
+        "id": "cordova-plugin-camera.Camera",
+        "pluginId": "cordova-plugin-camera",
+        "clobbers": [
+            "Camera"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js",
+        "id": "cordova-plugin-camera.CameraPopoverOptions",
+        "pluginId": "cordova-plugin-camera",
+        "clobbers": [
+            "CameraPopoverOptions"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-camera/www/Camera.js",
+        "id": "cordova-plugin-camera.camera",
+        "pluginId": "cordova-plugin-camera",
+        "clobbers": [
+            "navigator.camera"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-camera/src/browser/CameraProxy.js",
+        "id": "cordova-plugin-camera.CameraProxy",
+        "pluginId": "cordova-plugin-camera",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
+        "id": "cordova-plugin-inappbrowser.inappbrowser",
+        "pluginId": "cordova-plugin-inappbrowser",
+        "clobbers": [
+            "cordova.InAppBrowser.open",
+            "window.open"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js",
+        "id": "cordova-plugin-inappbrowser.InAppBrowserProxy",
+        "pluginId": "cordova-plugin-inappbrowser",
+        "runs": true
+    },
+    {
+        "file": "plugins/cordova-plugin-device/www/device.js",
+        "id": "cordova-plugin-device.device",
+        "pluginId": "cordova-plugin-device",
+        "clobbers": [
+            "device"
+        ]
+    },
+    {
+        "file": "plugins/cordova-plugin-device/src/browser/DeviceProxy.js",
+        "id": "cordova-plugin-device.DeviceProxy",
+        "pluginId": "cordova-plugin-device",
+        "runs": true
+    }
+];
+module.exports.metadata = 
+// TOP OF METADATA
+{
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+}
+// BOTTOM OF METADATA
+});
\ No newline at end of file
diff --git a/platforms/browser/platform_www/favicon.ico b/platforms/browser/platform_www/favicon.ico
new file mode 100644
index 0000000..fa7a758
--- /dev/null
+++ b/platforms/browser/platform_www/favicon.ico
Binary files differ
diff --git a/platforms/browser/platform_www/manifest.json b/platforms/browser/platform_www/manifest.json
new file mode 100644
index 0000000..5ad3f7b
--- /dev/null
+++ b/platforms/browser/platform_www/manifest.json
@@ -0,0 +1,24 @@
+{
+  "name": "大理市民卡",
+  "short_name": "大理市民卡",
+  "description": "Description of your app from template",
+  "start_url": "index.html",
+  "scope": "index.html",
+  "icons": [
+    {
+      "src": "img/logo.png",
+      "sizes": "192x192",
+      "type": "image/png"
+    },
+    {
+      "src": "img/splash.png",
+      "sizes": "512x512",
+      "type": "image/png"
+    }
+  ],
+  "default_locale": "en",
+  "display": "standalone",
+  "background_color": "#FFF",
+  "theme_color": "#000",
+  "orientation": "landscape"
+}
\ No newline at end of file
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js
new file mode 100644
index 0000000..953386f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/src/browser/cordova-http-plugin.js
@@ -0,0 +1,222 @@
+cordova.define("cordova-plugin-advanced-http.http-proxy", function(require, exports, module) { var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var cordovaProxy = require('cordova/exec/proxy');
+var jsUtil = require(pluginId + '.js-util');
+
+function serializeJsonData(data) {
+  try {
+    return JSON.stringify(data);
+  } catch (err) {
+    return null;
+  }
+}
+
+function serializePrimitive(key, value) {
+  if (value === null || value === undefined) {
+    return encodeURIComponent(key) + '=';
+  }
+
+  return encodeURIComponent(key) + '=' + encodeURIComponent(value);
+}
+
+function serializeArray(key, values) {
+  return values.map(function(value) {
+    return encodeURIComponent(key) + '[]=' + encodeURIComponent(value);
+  }).join('&');
+}
+
+function serializeParams(params) {
+  if (params === null) return '';
+
+  return Object.keys(params).map(function(key) {
+    if (jsUtil.getTypeOf(params[key]) === 'Array') {
+      return serializeArray(key, params[key]);
+    }
+
+    return serializePrimitive(key, params[key]);
+  }).join('&');
+}
+
+function deserializeResponseHeaders(headers) {
+  var headerMap = {};
+  var arr = headers.trim().split(/[\r\n]+/);
+
+  arr.forEach(function (line) {
+    var parts = line.split(': ');
+    var header = parts.shift().toLowerCase();
+    var value = parts.join(': ');
+
+    headerMap[header] = value;
+  });
+
+  return headerMap;
+}
+
+function getResponseData(xhr) {
+  if (xhr.responseType !== 'text' || jsUtil.getTypeOf(xhr.responseText) !== 'String') {
+    return xhr.response;
+  }
+
+  return xhr.responseText;
+}
+
+function createXhrSuccessObject(xhr) {
+  return {
+    url: xhr.responseURL,
+    status: xhr.status,
+    data: getResponseData(xhr),
+    headers: deserializeResponseHeaders(xhr.getAllResponseHeaders())
+  };
+}
+
+function createXhrFailureObject(xhr) {
+  var obj = {};
+
+  obj.headers = xhr.getAllResponseHeaders();
+  obj.error = getResponseData(xhr);
+  obj.error = obj.error || 'advanced-http: please check browser console for error messages';
+
+  if (xhr.responseURL) obj.url = xhr.responseURL;
+  if (xhr.status) obj.status = xhr.status;
+
+  return obj;
+}
+
+function getHeaderValue(headers, headerName) {
+  let result = null;
+
+  Object.keys(headers).forEach(function(key) {
+    if (key.toLowerCase() === headerName.toLowerCase()) {
+      result = headers[key];
+    }
+  });
+
+  return result;
+}
+
+function setDefaultContentType(headers, contentType) {
+  if (getHeaderValue(headers, 'Content-Type') === null) {
+    headers['Content-Type'] = contentType;
+  }
+}
+
+function setHeaders(xhr, headers) {
+  Object.keys(headers).forEach(function(key) {
+    if (key.toLowerCase() === 'cookie') return;
+
+    xhr.setRequestHeader(key, headers[key]);
+  });
+}
+
+function sendRequest(method, withData, opts, success, failure) {
+  var data, serializer, headers, timeout, followRedirect, responseType;
+  var url = opts[0];
+
+  if (withData) {
+    data = opts[1];
+    serializer = opts[2];
+    headers = opts[3];
+    timeout = opts[4];
+    followRedirect = opts[5];
+    responseType = opts[6];
+  } else {
+    headers = opts[1];
+    timeout = opts[2];
+    followRedirect = opts[3];
+    responseType = opts[4];
+
+  }
+
+  var processedData = null;
+  var xhr = new XMLHttpRequest();
+
+  xhr.open(method, url);
+
+  if (headers.Cookie && headers.Cookie.length > 0) {
+    return failure('advanced-http: custom cookies not supported on browser platform');
+  }
+
+  if (!followRedirect) {
+    return failure('advanced-http: disabling follow redirect not supported on browser platform');
+  }
+
+  switch (serializer) {
+    case 'json':
+      setDefaultContentType(headers, 'application/json; charset=utf8');
+      processedData = serializeJsonData(data);
+
+      if (processedData === null) {
+        return failure('advanced-http: failed serializing data');
+      }
+
+      break;
+
+    case 'utf8':
+      setDefaultContentType(headers, 'text/plain; charset=utf8');
+      processedData = data.text;
+      break;
+
+    case 'urlencoded':
+      setDefaultContentType(headers, 'application/x-www-form-urlencoded');
+      processedData = serializeParams(data);
+      break;
+  }
+
+  xhr.timeout = timeout * 1000;
+  xhr.responseType = responseType;
+  setHeaders(xhr, headers);
+
+  xhr.onerror = xhr.ontimeout = function () {
+    return failure(createXhrFailureObject(xhr));
+  };
+
+  xhr.onload = function () {
+    if (xhr.readyState !== xhr.DONE) return;
+
+    if (xhr.status < 200 || xhr.status > 299) {
+      return failure(createXhrFailureObject(xhr));
+    }
+
+    return success(createXhrSuccessObject(xhr));
+  };
+
+  xhr.send(processedData);
+}
+
+var browserInterface = {
+  get: function (success, failure, opts) {
+    return sendRequest('get', false, opts, success, failure);
+  },
+  head: function (success, failure, opts) {
+    return sendRequest('head', false, opts, success, failure);
+  },
+  delete: function (success, failure, opts) {
+    return sendRequest('delete', false, opts, success, failure);
+  },
+  post: function (success, failure, opts) {
+    return sendRequest('post', true, opts, success, failure);
+  },
+  put: function (success, failure, opts) {
+    return sendRequest('put', true, opts, success, failure);
+  },
+  patch: function (success, failure, opts) {
+    return sendRequest('patch', true, opts, success, failure);
+  },
+  uploadFile: function (success, failure, opts) {
+    return failure('advanced-http: function "uploadFile" not supported on browser platform');
+  },
+  downloadFile: function (success, failure, opts) {
+    return failure('advanced-http: function "downloadFile" not supported on browser platform');
+  },
+  setServerTrustMode: function (success, failure, opts) {
+    return failure('advanced-http: function "setServerTrustMode" not supported on browser platform');
+  },
+  setClientAuthMode: function (success, failure, opts) {
+    return failure('advanced-http: function "setClientAuthMode" not supported on browser platform');
+  }
+};
+
+module.exports = browserInterface;
+cordovaProxy.add('CordovaHttpPlugin', browserInterface);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..e41e8af
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) { /*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..61d60b8
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,72 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) { module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+  var storeKey = '__advancedHttpCookieStore__';
+
+  var store = new WebStorageCookieStore(storage, storeKey);
+  var cookieJar = new ToughCookie.CookieJar(store);
+
+  return {
+    setCookieFromString: setCookieFromString,
+    setCookie: setCookie,
+    getCookieString: getCookieString,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies
+  };
+
+  function splitCookieString(cookieStr) {
+    var cookieParts = cookieStr.split(',');
+    var splitCookies = [];
+    var processedCookie = null;
+
+    for (var i = 0; i < cookieParts.length; ++i) {
+      if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+        processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+        i++;
+      } else {
+        processedCookie = cookieParts[i];
+      }
+
+      processedCookie = processedCookie.trim();
+      splitCookies.push(processedCookie);
+    }
+
+    return splitCookies;
+  }
+
+  function setCookieFromString(url, cookieStr) {
+    if (!cookieStr) return;
+
+    var cookies = splitCookieString(cookieStr);
+
+    for (var i = 0; i < cookies.length; ++i) {
+      cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+    }
+  }
+
+  function setCookie(url, cookie, options) {
+    options = options || {};
+    options.ignoreError = false;
+    cookieJar.setCookieSync(cookie, url, options);
+  }
+
+  function getCookieString(url) {
+    return cookieJar.getCookieStringSync(url);
+  }
+
+  function clearCookies() {
+    window.localStorage.removeItem(storeKey);
+  }
+
+  function removeCookies(url, cb) {
+    cookieJar.getCookies(url, function (error, cookies) {
+      if (!cookies || cookies.length === 0) {
+        return cb(null, []);
+      }
+
+      var domain = cookies[0].domain;
+
+      cookieJar.store.removeCookies(domain, null, cb);
+    });
+  }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..b9ff2ec
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,10 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) { var globalConfigs = {
+  headers: {},
+  serializer: 'urlencoded',
+  followRedirect: true,
+  timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..e1cb118
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,352 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) { module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+  var validSerializers = ['urlencoded', 'json', 'utf8'];
+  var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+  var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+  var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+  var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+  var interface = {
+    b64EncodeUnicode: b64EncodeUnicode,
+    checkSerializer: checkSerializer,
+    checkSSLCertMode: checkSSLCertMode,
+    checkClientAuthMode: checkClientAuthMode,
+    checkClientAuthOptions: checkClientAuthOptions,
+    checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+    checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+    checkTimeoutValue: checkTimeoutValue,
+    checkFollowRedirectValue: checkFollowRedirectValue,
+    injectCookieHandler: injectCookieHandler,
+    injectRawResponseHandler: injectRawResponseHandler,
+    injectFileEntryHandler: injectFileEntryHandler,
+    getMergedHeaders: getMergedHeaders,
+    getProcessedData: getProcessedData,
+    handleMissingCallbacks: handleMissingCallbacks,
+    handleMissingOptions: handleMissingOptions
+  };
+
+  // expose all functions for testing purposes
+  if (init.debug) {
+    interface.mergeHeaders = mergeHeaders;
+    interface.checkForValidStringValue = checkForValidStringValue;
+    interface.checkKeyValuePairObject = checkKeyValuePairObject;
+    interface.checkHttpMethod = checkHttpMethod;
+    interface.checkResponseType = checkResponseType;
+    interface.checkHeadersObject = checkHeadersObject;
+    interface.checkParamsObject = checkParamsObject;
+    interface.resolveCookieString = resolveCookieString;
+    interface.createFileEntry = createFileEntry;
+    interface.getCookieHeader = getCookieHeader;
+    interface.getMatchingHostHeaders = getMatchingHostHeaders;
+    interface.getAllowedDataTypes = getAllowedDataTypes;
+  }
+
+  return interface;
+
+  // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+  function b64EncodeUnicode(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode('0x' + p1);
+    }));
+  }
+
+  function mergeHeaders(globalHeaders, localHeaders) {
+    var globalKeys = Object.keys(globalHeaders);
+    var key;
+
+    for (var i = 0; i < globalKeys.length; i++) {
+      key = globalKeys[i];
+
+      if (!localHeaders.hasOwnProperty(key)) {
+        localHeaders[key] = globalHeaders[key];
+      }
+    }
+
+    return localHeaders;
+  }
+
+  function checkForValidStringValue(list, value, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    value = value.trim().toLowerCase();
+
+    if (list.indexOf(value) === -1) {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    return value;
+  }
+
+  function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(obj) !== 'Object') {
+      throw new Error(onInvalidValueMessage);
+    }
+
+    var keys = Object.keys(obj);
+
+    for (var i = 0; i < keys.length; i++) {
+      if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+        throw new Error(onInvalidValueMessage);
+      }
+    }
+
+    return obj;
+  }
+
+  function checkHttpMethod(method) {
+    return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+  }
+
+  function checkResponseType(type) {
+    return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+  }
+
+  function checkSerializer(serializer) {
+    return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+  }
+
+  function checkSSLCertMode(mode) {
+    return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+  }
+
+  function checkClientAuthMode(mode) {
+    return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+  }
+
+  function checkClientAuthOptions(mode, options) {
+    options = options || {};
+
+    // none
+    if (mode === validClientAuthModes[0]) {
+      return {
+        alias: null,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    if (jsUtil.getTypeOf(options) !== 'Object') {
+      throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+    }
+
+    // systemstore
+    if (mode === validClientAuthModes[1]) {
+      if (jsUtil.getTypeOf(options.alias) !== 'String'
+        && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+      }
+
+      return {
+        alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    // buffer
+    if (mode === validClientAuthModes[2]) {
+      if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+      }
+
+      if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+      }
+
+      return {
+        alias: null,
+        rawPkcs: options.rawPkcs,
+        pkcsPassword: options.pkcsPassword
+      }
+    }
+  }
+
+  function checkForBlacklistedHeaderKey(key) {
+    if (key.toLowerCase() === 'cookie') {
+      throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+    }
+
+    return key;
+  }
+
+  function checkForInvalidHeaderValue(value) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(messages.INVALID_HEADERS_VALUE);
+    }
+
+    return value;
+  }
+
+  function checkTimeoutValue(timeout) {
+    if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+      throw new Error(messages.INVALID_TIMEOUT_VALUE);
+    }
+
+    return timeout;
+  }
+
+  function checkFollowRedirectValue(follow) {
+    if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+      throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+    }
+
+    return follow;
+  }
+
+  function checkHeadersObject(headers) {
+    return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+  }
+
+  function checkParamsObject(params) {
+    return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+  }
+
+  function resolveCookieString(headers) {
+    var keys = Object.keys(headers || {});
+
+    for (var i = 0; i < keys.length; ++i) {
+      if (keys[i].match(/^set-cookie$/i)) {
+        return headers[keys[i]];
+      }
+    }
+
+    return null;
+  }
+
+  function createFileEntry(rawEntry) {
+    var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+    entry.isDirectory = rawEntry.isDirectory;
+    entry.isFile = rawEntry.isFile;
+    entry.name = rawEntry.name;
+    entry.fullPath = rawEntry.fullPath;
+    entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+    entry.nativeURL = rawEntry.nativeURL;
+
+    return entry;
+  }
+
+  function injectCookieHandler(url, cb) {
+    return function (response) {
+      cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+      cb(response);
+    }
+  }
+
+  function injectRawResponseHandler(responseType, cb) {
+    return function (response) {
+      var dataType = jsUtil.getTypeOf(response.data);
+
+      // don't need post-processing if it's already binary type (on browser platform)
+      if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+        return cb(response);
+      }
+
+      // arraybuffer
+      if (responseType === validResponseTypes[1]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        response.data = buffer;
+      }
+
+      // blob
+      if (responseType === validResponseTypes[2]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        var type = response.headers['content-type'] || '';
+        var blob = new Blob([ buffer ], { type: type });
+        response.data = blob;
+      }
+
+      cb(response);
+    }
+  }
+
+  function injectFileEntryHandler(cb) {
+    return function (response) {
+      cb(createFileEntry(response.file));
+    }
+  }
+
+  function getCookieHeader(url) {
+    var cookieString = cookieHandler.getCookieString(url);
+
+    if (cookieString.length) {
+      return { Cookie: cookieHandler.getCookieString(url) };
+    }
+
+    return {};
+  }
+
+  function getMatchingHostHeaders(url, headersList) {
+    var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+    var domain = matches && matches[1];
+
+    return headersList[domain] || null;
+  }
+
+  function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+    var globalHeaders = predefinedHeaders['*'] || {};
+    var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+    var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+    mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+    mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+    return mergedHeaders;
+  }
+
+  function getAllowedDataTypes(dataSerializer) {
+    switch (dataSerializer) {
+      case 'utf8':
+        return ['String'];
+      case 'urlencoded':
+        return ['Object'];
+      default:
+        return ['Array', 'Object'];
+    }
+  }
+
+  function getProcessedData(data, dataSerializer) {
+    var currentDataType = jsUtil.getTypeOf(data);
+    var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+    if (allowedDataTypes.indexOf(currentDataType) === -1) {
+      throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+    }
+
+    if (dataSerializer === 'utf8') {
+      data = { text: data };
+    }
+
+    return data;
+  }
+
+  function handleMissingCallbacks(successFn, failFn) {
+    if (jsUtil.getTypeOf(successFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_SUCCESS);
+    }
+
+    if (jsUtil.getTypeOf(failFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_FAIL);
+    }
+  }
+
+  function handleMissingOptions(options, globals) {
+    options = options || {};
+
+    return {
+      method: checkHttpMethod(options.method || validHttpMethods[0]),
+      responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+      serializer: checkSerializer(options.serializer || globals.serializer),
+      timeout: checkTimeoutValue(options.timeout || globals.timeout),
+      followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+      headers: checkHeadersObject(options.headers || {}),
+      params: checkParamsObject(options.params || {}),
+      data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+      filePath: options.filePath || '',
+      name: options.name || ''
+    };
+  }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..ff0db76
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) { module.exports = {
+  // typeof is not working reliably in JS
+  getTypeOf: function (object) {
+    switch (Object.prototype.toString.call(object)) {
+      case '[object Array]':
+        return 'Array';
+      case '[object Blob]':
+        return 'Blob';
+      case '[object ArrayBuffer]':
+        return 'ArrayBuffer';
+      case '[object Boolean]':
+        return 'Boolean';
+      case '[object Function]':
+        return 'Function';
+      case '[object Null]':
+        return 'Null';
+      case '[object Number]':
+        return 'Number';
+      case '[object Object]':
+        return 'Object';
+      case '[object String]':
+        return 'String';
+      case '[object Undefined]':
+        return 'Undefined';
+      default:
+        return 'Unknown';
+    }
+  }
+}
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..05cd38a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,183 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) { /*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+  function WebStorageCookieStore(storage, storeKey) {
+    ToughCookie.Store.call(this);
+    this._storage = storage;
+    this._storeKey = storeKey || '__cookieStore__';
+    this.synchronous = true;
+  }
+
+  WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+  WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+    var cookie = _.get(store, [domain, path, key], null);
+
+    callback(null, ToughCookie.Cookie.fromJSON(cookie));
+  };
+
+  WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+    if (!domain) {
+      callback(null, []);
+      return;
+    }
+
+    var that = this;
+    var cookies = [];
+    var store = this._readStore();
+    var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+    domains.forEach(function (domain) {
+      if (!store[domain]) {
+        return;
+      }
+
+      var matchingPaths = Object.keys(store[domain]);
+
+      if (path != null) {
+        matchingPaths = matchingPaths.filter(function (cookiePath) {
+          return that._isOnPath(cookiePath, path);
+        });
+      }
+
+      matchingPaths.forEach(function (path) {
+        Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    callback(null, cookies);
+  };
+
+  /**
+   * Returns whether `cookiePath` is on the given `urlPath`
+   */
+  WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+    if (!cookiePath) {
+      return false;
+    }
+
+    if (cookiePath === urlPath) {
+      return true;
+    }
+
+    if (urlPath.indexOf(cookiePath) !== 0) {
+      return false;
+    }
+
+    if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+      return false;
+    }
+
+    return true;
+  };
+
+  WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+    var store = this._readStore();
+
+    _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+    this.putCookie(newCookie, callback);
+  };
+
+
+  WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+
+    _.unset(store, [domain, path, key]);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+    var store = this._readStore();
+
+    if (path == null) {
+      _.unset(store, [domain]);
+    } else {
+      _.unset(store, [domain, path]);
+    }
+
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+    var cookies = [];
+    var store = this._readStore();
+
+    Object.keys(store).forEach(function (domain) {
+      Object.keys(store[domain]).forEach(function (path) {
+        Array.protype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    cookies.sort(function (c1, c2) {
+      return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+    });
+
+    callback(null, cookies);
+  };
+
+  WebStorageCookieStore.prototype._readStore = function () {
+    var json = this._storage.getItem(this._storeKey);
+
+    if (json !== null) {
+      try {
+        return JSON.parse(json);
+      } catch (e) { }
+    }
+
+    return {};
+  };
+
+  WebStorageCookieStore.prototype._writeStore = function (store) {
+    this._storage.setItem(this._storeKey, JSON.stringify(store));
+  };
+
+  return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..956c885
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,21 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) { /**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..0feefaf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,21 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) { module.exports = {
+  ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+  DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+  INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+  INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+  INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+  INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+  INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+  INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+  INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+  INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+  INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+  INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+  INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+  INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+  INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+  MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+  MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a7dea53
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,201 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) { module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+  const publicInterface = {
+    getBasicAuthHeader: getBasicAuthHeader,
+    useBasicAuth: useBasicAuth,
+    getHeaders: getHeaders,
+    setHeader: setHeader,
+    getDataSerializer: getDataSerializer,
+    setDataSerializer: setDataSerializer,
+    setCookie: setCookie,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies,
+    getCookieString: getCookieString,
+    getRequestTimeout: getRequestTimeout,
+    setRequestTimeout: setRequestTimeout,
+    getFollowRedirect: getFollowRedirect,
+    setFollowRedirect: setFollowRedirect,
+    // @DEPRECATED
+    disableRedirect: disableRedirect,
+    // @DEPRECATED
+    setSSLCertMode: setServerTrustMode,
+    setServerTrustMode: setServerTrustMode,
+    setClientAuthMode: setClientAuthMode,
+    sendRequest: sendRequest,
+    post: post,
+    get: get,
+    put: put,
+    patch: patch,
+    delete: del,
+    head: head,
+    uploadFile: uploadFile,
+    downloadFile: downloadFile
+  };
+
+  function getBasicAuthHeader(username, password) {
+    return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+  }
+
+  function useBasicAuth(username, password) {
+    this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+  }
+
+  function getHeaders(host) {
+    return globalConfigs.headers[host || '*'] || null;
+  }
+
+  function setHeader() {
+    // this one is for being backward compatible
+    var host = '*';
+    var header = arguments[0];
+    var value = arguments[1];
+
+    if (arguments.length === 3) {
+      host = arguments[0];
+      header = arguments[1];
+      value = arguments[2];
+    }
+
+    helpers.checkForBlacklistedHeaderKey(header);
+    helpers.checkForInvalidHeaderValue(value);
+
+    globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+    globalConfigs.headers[host][header] = value;
+  }
+
+  function getDataSerializer() {
+    return globalConfigs.serializer;
+  }
+
+  function setDataSerializer(serializer) {
+    globalConfigs.serializer = helpers.checkSerializer(serializer);
+  }
+
+  function setCookie(url, cookie, options) {
+    cookieHandler.setCookie(url, cookie, options);
+  }
+
+  function clearCookies() {
+    cookieHandler.clearCookies();
+  }
+
+  function removeCookies(url, callback) {
+    cookieHandler.removeCookies(url, callback);
+  }
+
+  function getCookieString(url) {
+    return cookieHandler.getCookieString(url);
+  }
+
+  function getRequestTimeout() {
+    return globalConfigs.timeout;
+  }
+
+  function setRequestTimeout(timeout) {
+    globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+  }
+
+  function getFollowRedirect() {
+    return globalConfigs.followRedirect;
+  }
+
+  function setFollowRedirect(follow) {
+    globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+  }
+
+  // @DEPRECATED
+  function disableRedirect(disable, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    setFollowRedirect(!disable);
+    success();
+  }
+
+  function setServerTrustMode(mode, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+  }
+
+  function setClientAuthMode() {
+    var mode = arguments[0];
+    var options = null;
+    var success = arguments[1];
+    var failure = arguments[2];
+
+    if (arguments.length === 4) {
+      options = arguments[1];
+      success = arguments[2];
+      failure = arguments[3];
+    }
+
+    mode = helpers.checkClientAuthMode(mode);
+    options = helpers.checkClientAuthOptions(mode, options);
+
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+  }
+
+  function sendRequest(url, options, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    options = helpers.handleMissingOptions(options, globalConfigs);
+    url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+    var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+    var onFail = helpers.injectCookieHandler(url, failure);
+    var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+    switch (options.method) {
+      case 'post':
+      case 'put':
+      case 'patch':
+        var data = helpers.getProcessedData(options.data, options.serializer);
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+      case 'upload':
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+      case 'download':
+        var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+        return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+      default:
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+    }
+  }
+
+  function post(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+  };
+
+  function get(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+  };
+
+  function put(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+  }
+
+  function patch(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+  }
+
+  function del(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+  }
+
+  function head(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+  }
+
+  function uploadFile(url, params, headers, filePath, name, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+  }
+
+  function downloadFile(url, params, headers, filePath, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+  }
+
+  return publicInterface;
+}
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..47c162e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5090 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) { (function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["ToughCookie"] = factory();
+	else
+		root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var net = __webpack_require__(1);
+	var urlParse = __webpack_require__(2).parse;
+	var util = __webpack_require__(9);
+	var pubsuffix = __webpack_require__(13);
+	var Store = __webpack_require__(17).Store;
+	var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var VERSION = __webpack_require__(21).version;
+
+	var punycode;
+	try {
+	  punycode = __webpack_require__(15);
+	} catch(e) {
+	  console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+	}
+
+	// From RFC6265 S4.1.1
+	// note that it excludes \x3B ";"
+	var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+	var CONTROL_CHARS = /[\x00-\x1F]/;
+
+	// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+	// the "relaxed" mode, see:
+	// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+	var TERMINATORS = ['\n', '\r', '\0'];
+
+	// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+	// Note ';' is \x3B
+	var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+	// date-time parsing constants (RFC6265 S5.1.1)
+
+	var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+	var MONTH_TO_NUM = {
+	  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+	  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+	};
+	var NUM_TO_MONTH = [
+	  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+	];
+	var NUM_TO_DAY = [
+	  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+	];
+
+	var MAX_TIME = 2147483647000; // 31-bit max
+	var MIN_TIME = 0; // 31-bit min
+
+	/*
+	 * Parses a Natural number (i.e., non-negative integer) with either the
+	 *    <min>*<max>DIGIT ( non-digit *OCTET )
+	 * or
+	 *    <min>*<max>DIGIT
+	 * grammar (RFC6265 S5.1.1).
+	 *
+	 * The "trailingOK" boolean controls if the grammar accepts a
+	 * "( non-digit *OCTET )" trailer.
+	 */
+	function parseDigits(token, minDigits, maxDigits, trailingOK) {
+	  var count = 0;
+	  while (count < token.length) {
+	    var c = token.charCodeAt(count);
+	    // "non-digit = %x00-2F / %x3A-FF"
+	    if (c <= 0x2F || c >= 0x3A) {
+	      break;
+	    }
+	    count++;
+	  }
+
+	  // constrain to a minimum and maximum number of digits.
+	  if (count < minDigits || count > maxDigits) {
+	    return null;
+	  }
+
+	  if (!trailingOK && count != token.length) {
+	    return null;
+	  }
+
+	  return parseInt(token.substr(0,count), 10);
+	}
+
+	function parseTime(token) {
+	  var parts = token.split(':');
+	  var result = [0,0,0];
+
+	  /* RF6256 S5.1.1:
+	   *      time            = hms-time ( non-digit *OCTET )
+	   *      hms-time        = time-field ":" time-field ":" time-field
+	   *      time-field      = 1*2DIGIT
+	   */
+
+	  if (parts.length !== 3) {
+	    return null;
+	  }
+
+	  for (var i = 0; i < 3; i++) {
+	    // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+	    // followed by "( non-digit *OCTET )" so therefore the last time-field can
+	    // have a trailer
+	    var trailingOK = (i == 2);
+	    var num = parseDigits(parts[i], 1, 2, trailingOK);
+	    if (num === null) {
+	      return null;
+	    }
+	    result[i] = num;
+	  }
+
+	  return result;
+	}
+
+	function parseMonth(token) {
+	  token = String(token).substr(0,3).toLowerCase();
+	  var num = MONTH_TO_NUM[token];
+	  return num >= 0 ? num : null;
+	}
+
+	/*
+	 * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+	 */
+	function parseDate(str) {
+	  if (!str) {
+	    return;
+	  }
+
+	  /* RFC6265 S5.1.1:
+	   * 2. Process each date-token sequentially in the order the date-tokens
+	   * appear in the cookie-date
+	   */
+	  var tokens = str.split(DATE_DELIM);
+	  if (!tokens) {
+	    return;
+	  }
+
+	  var hour = null;
+	  var minute = null;
+	  var second = null;
+	  var dayOfMonth = null;
+	  var month = null;
+	  var year = null;
+
+	  for (var i=0; i<tokens.length; i++) {
+	    var token = tokens[i].trim();
+	    if (!token.length) {
+	      continue;
+	    }
+
+	    var result;
+
+	    /* 2.1. If the found-time flag is not set and the token matches the time
+	     * production, set the found-time flag and set the hour- value,
+	     * minute-value, and second-value to the numbers denoted by the digits in
+	     * the date-token, respectively.  Skip the remaining sub-steps and continue
+	     * to the next date-token.
+	     */
+	    if (second === null) {
+	      result = parseTime(token);
+	      if (result) {
+	        hour = result[0];
+	        minute = result[1];
+	        second = result[2];
+	        continue;
+	      }
+	    }
+
+	    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+	     * the day-of-month production, set the found-day-of- month flag and set
+	     * the day-of-month-value to the number denoted by the date-token.  Skip
+	     * the remaining sub-steps and continue to the next date-token.
+	     */
+	    if (dayOfMonth === null) {
+	      // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 1, 2, true);
+	      if (result !== null) {
+	        dayOfMonth = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.3. If the found-month flag is not set and the date-token matches the
+	     * month production, set the found-month flag and set the month-value to
+	     * the month denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (month === null) {
+	      result = parseMonth(token);
+	      if (result !== null) {
+	        month = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.4. If the found-year flag is not set and the date-token matches the
+	     * year production, set the found-year flag and set the year-value to the
+	     * number denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (year === null) {
+	      // "year = 2*4DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 2, 4, true);
+	      if (result !== null) {
+	        year = result;
+	        /* From S5.1.1:
+	         * 3.  If the year-value is greater than or equal to 70 and less
+	         * than or equal to 99, increment the year-value by 1900.
+	         * 4.  If the year-value is greater than or equal to 0 and less
+	         * than or equal to 69, increment the year-value by 2000.
+	         */
+	        if (year >= 70 && year <= 99) {
+	          year += 1900;
+	        } else if (year >= 0 && year <= 69) {
+	          year += 2000;
+	        }
+	      }
+	    }
+	  }
+
+	  /* RFC 6265 S5.1.1
+	   * "5. Abort these steps and fail to parse the cookie-date if:
+	   *     *  at least one of the found-day-of-month, found-month, found-
+	   *        year, or found-time flags is not set,
+	   *     *  the day-of-month-value is less than 1 or greater than 31,
+	   *     *  the year-value is less than 1601,
+	   *     *  the hour-value is greater than 23,
+	   *     *  the minute-value is greater than 59, or
+	   *     *  the second-value is greater than 59.
+	   *     (Note that leap seconds cannot be represented in this syntax.)"
+	   *
+	   * So, in order as above:
+	   */
+	  if (
+	    dayOfMonth === null || month === null || year === null || second === null ||
+	    dayOfMonth < 1 || dayOfMonth > 31 ||
+	    year < 1601 ||
+	    hour > 23 ||
+	    minute > 59 ||
+	    second > 59
+	  ) {
+	    return;
+	  }
+
+	  return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+	}
+
+	function formatDate(date) {
+	  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+	  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+	  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+	  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+	  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+	    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+	    h+':'+m+':'+s+' GMT';
+	}
+
+	// S5.1.2 Canonicalized Host Names
+	function canonicalDomain(str) {
+	  if (str == null) {
+	    return null;
+	  }
+	  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+	  // convert to IDN if any non-ASCII characters
+	  if (punycode && /[^\u0001-\u007f]/.test(str)) {
+	    str = punycode.toASCII(str);
+	  }
+
+	  return str.toLowerCase();
+	}
+
+	// S5.1.3 Domain Matching
+	function domainMatch(str, domStr, canonicalize) {
+	  if (str == null || domStr == null) {
+	    return null;
+	  }
+	  if (canonicalize !== false) {
+	    str = canonicalDomain(str);
+	    domStr = canonicalDomain(domStr);
+	  }
+
+	  /*
+	   * "The domain string and the string are identical. (Note that both the
+	   * domain string and the string will have been canonicalized to lower case at
+	   * this point)"
+	   */
+	  if (str == domStr) {
+	    return true;
+	  }
+
+	  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+	  /* "* The string is a host name (i.e., not an IP address)." */
+	  if (net.isIP(str)) {
+	    return false;
+	  }
+
+	  /* "* The domain string is a suffix of the string" */
+	  var idx = str.indexOf(domStr);
+	  if (idx <= 0) {
+	    return false; // it's a non-match (-1) or prefix (0)
+	  }
+
+	  // e.g "a.b.c".indexOf("b.c") === 2
+	  // 5 === 3+2
+	  if (str.length !== domStr.length + idx) { // it's not a suffix
+	    return false;
+	  }
+
+	  /* "* The last character of the string that is not included in the domain
+	  * string is a %x2E (".") character." */
+	  if (str.substr(idx-1,1) !== '.') {
+	    return false;
+	  }
+
+	  return true;
+	}
+
+
+	// RFC6265 S5.1.4 Paths and Path-Match
+
+	/*
+	 * "The user agent MUST use an algorithm equivalent to the following algorithm
+	 * to compute the default-path of a cookie:"
+	 *
+	 * Assumption: the path (and not query part or absolute uri) is passed in.
+	 */
+	function defaultPath(path) {
+	  // "2. If the uri-path is empty or if the first character of the uri-path is not
+	  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+	  if (!path || path.substr(0,1) !== "/") {
+	    return "/";
+	  }
+
+	  // "3. If the uri-path contains no more than one %x2F ("/") character, output
+	  // %x2F ("/") and skip the remaining step."
+	  if (path === "/") {
+	    return path;
+	  }
+
+	  var rightSlash = path.lastIndexOf("/");
+	  if (rightSlash === 0) {
+	    return "/";
+	  }
+
+	  // "4. Output the characters of the uri-path from the first character up to,
+	  // but not including, the right-most %x2F ("/")."
+	  return path.slice(0, rightSlash);
+	}
+
+	function trimTerminator(str) {
+	  for (var t = 0; t < TERMINATORS.length; t++) {
+	    var terminatorIdx = str.indexOf(TERMINATORS[t]);
+	    if (terminatorIdx !== -1) {
+	      str = str.substr(0,terminatorIdx);
+	    }
+	  }
+
+	  return str;
+	}
+
+	function parseCookiePair(cookiePair, looseMode) {
+	  cookiePair = trimTerminator(cookiePair);
+
+	  var firstEq = cookiePair.indexOf('=');
+	  if (looseMode) {
+	    if (firstEq === 0) { // '=' is immediately at start
+	      cookiePair = cookiePair.substr(1);
+	      firstEq = cookiePair.indexOf('='); // might still need to split on '='
+	    }
+	  } else { // non-loose mode
+	    if (firstEq <= 0) { // no '=' or is at start
+	      return; // needs to have non-empty "cookie-name"
+	    }
+	  }
+
+	  var cookieName, cookieValue;
+	  if (firstEq <= 0) {
+	    cookieName = "";
+	    cookieValue = cookiePair.trim();
+	  } else {
+	    cookieName = cookiePair.substr(0, firstEq).trim();
+	    cookieValue = cookiePair.substr(firstEq+1).trim();
+	  }
+
+	  if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+	    return;
+	  }
+
+	  var c = new Cookie();
+	  c.key = cookieName;
+	  c.value = cookieValue;
+	  return c;
+	}
+
+	function parse(str, options) {
+	  if (!options || typeof options !== 'object') {
+	    options = {};
+	  }
+	  str = str.trim();
+
+	  // We use a regex to parse the "name-value-pair" part of S5.2
+	  var firstSemi = str.indexOf(';'); // S5.2 step 1
+	  var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+	  var c = parseCookiePair(cookiePair, !!options.loose);
+	  if (!c) {
+	    return;
+	  }
+
+	  if (firstSemi === -1) {
+	    return c;
+	  }
+
+	  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+	  // (including the %x3B (";") in question)." plus later on in the same section
+	  // "discard the first ";" and trim".
+	  var unparsed = str.slice(firstSemi + 1).trim();
+
+	  // "If the unparsed-attributes string is empty, skip the rest of these
+	  // steps."
+	  if (unparsed.length === 0) {
+	    return c;
+	  }
+
+	  /*
+	   * S5.2 says that when looping over the items "[p]rocess the attribute-name
+	   * and attribute-value according to the requirements in the following
+	   * subsections" for every item.  Plus, for many of the individual attributes
+	   * in S5.3 it says to use the "attribute-value of the last attribute in the
+	   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
+	   * the previous value.
+	   */
+	  var cookie_avs = unparsed.split(';');
+	  while (cookie_avs.length) {
+	    var av = cookie_avs.shift().trim();
+	    if (av.length === 0) { // happens if ";;" appears
+	      continue;
+	    }
+	    var av_sep = av.indexOf('=');
+	    var av_key, av_value;
+
+	    if (av_sep === -1) {
+	      av_key = av;
+	      av_value = null;
+	    } else {
+	      av_key = av.substr(0,av_sep);
+	      av_value = av.substr(av_sep+1);
+	    }
+
+	    av_key = av_key.trim().toLowerCase();
+
+	    if (av_value) {
+	      av_value = av_value.trim();
+	    }
+
+	    switch(av_key) {
+	    case 'expires': // S5.2.1
+	      if (av_value) {
+	        var exp = parseDate(av_value);
+	        // "If the attribute-value failed to parse as a cookie date, ignore the
+	        // cookie-av."
+	        if (exp) {
+	          // over and underflow not realistically a concern: V8's getTime() seems to
+	          // store something larger than a 32-bit time_t (even with 32-bit node)
+	          c.expires = exp;
+	        }
+	      }
+	      break;
+
+	    case 'max-age': // S5.2.2
+	      if (av_value) {
+	        // "If the first character of the attribute-value is not a DIGIT or a "-"
+	        // character ...[or]... If the remainder of attribute-value contains a
+	        // non-DIGIT character, ignore the cookie-av."
+	        if (/^-?[0-9]+$/.test(av_value)) {
+	          var delta = parseInt(av_value, 10);
+	          // "If delta-seconds is less than or equal to zero (0), let expiry-time
+	          // be the earliest representable date and time."
+	          c.setMaxAge(delta);
+	        }
+	      }
+	      break;
+
+	    case 'domain': // S5.2.3
+	      // "If the attribute-value is empty, the behavior is undefined.  However,
+	      // the user agent SHOULD ignore the cookie-av entirely."
+	      if (av_value) {
+	        // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+	        // (".") character."
+	        var domain = av_value.trim().replace(/^\./, '');
+	        if (domain) {
+	          // "Convert the cookie-domain to lower case."
+	          c.domain = domain.toLowerCase();
+	        }
+	      }
+	      break;
+
+	    case 'path': // S5.2.4
+	      /*
+	       * "If the attribute-value is empty or if the first character of the
+	       * attribute-value is not %x2F ("/"):
+	       *   Let cookie-path be the default-path.
+	       * Otherwise:
+	       *   Let cookie-path be the attribute-value."
+	       *
+	       * We'll represent the default-path as null since it depends on the
+	       * context of the parsing.
+	       */
+	      c.path = av_value && av_value[0] === "/" ? av_value : null;
+	      break;
+
+	    case 'secure': // S5.2.5
+	      /*
+	       * "If the attribute-name case-insensitively matches the string "Secure",
+	       * the user agent MUST append an attribute to the cookie-attribute-list
+	       * with an attribute-name of Secure and an empty attribute-value."
+	       */
+	      c.secure = true;
+	      break;
+
+	    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+	      c.httpOnly = true;
+	      break;
+
+	    default:
+	      c.extensions = c.extensions || [];
+	      c.extensions.push(av);
+	      break;
+	    }
+	  }
+
+	  return c;
+	}
+
+	// avoid the V8 deoptimization monster!
+	function jsonParse(str) {
+	  var obj;
+	  try {
+	    obj = JSON.parse(str);
+	  } catch (e) {
+	    return e;
+	  }
+	  return obj;
+	}
+
+	function fromJSON(str) {
+	  if (!str) {
+	    return null;
+	  }
+
+	  var obj;
+	  if (typeof str === 'string') {
+	    obj = jsonParse(str);
+	    if (obj instanceof Error) {
+	      return null;
+	    }
+	  } else {
+	    // assume it's an Object
+	    obj = str;
+	  }
+
+	  var c = new Cookie();
+	  for (var i=0; i<Cookie.serializableProperties.length; i++) {
+	    var prop = Cookie.serializableProperties[i];
+	    if (obj[prop] === undefined ||
+	        obj[prop] === Cookie.prototype[prop])
+	    {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (obj[prop] === null) {
+	        c[prop] = null;
+	      } else {
+	        c[prop] = obj[prop] == "Infinity" ?
+	          "Infinity" : new Date(obj[prop]);
+	      }
+	    } else {
+	      c[prop] = obj[prop];
+	    }
+	  }
+
+	  return c;
+	}
+
+	/* Section 5.4 part 2:
+	 * "*  Cookies with longer paths are listed before cookies with
+	 *     shorter paths.
+	 *
+	 *  *  Among cookies that have equal-length path fields, cookies with
+	 *     earlier creation-times are listed before cookies with later
+	 *     creation-times."
+	 */
+
+	function cookieCompare(a,b) {
+	  var cmp = 0;
+
+	  // descending for length: b CMP a
+	  var aPathLen = a.path ? a.path.length : 0;
+	  var bPathLen = b.path ? b.path.length : 0;
+	  cmp = bPathLen - aPathLen;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // ascending for time: a CMP b
+	  var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+	  var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+	  cmp = aTime - bTime;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // break ties for the same millisecond (precision of JavaScript's clock)
+	  cmp = a.creationIndex - b.creationIndex;
+
+	  return cmp;
+	}
+
+	// Gives the permutation of all possible pathMatch()es of a given path. The
+	// array is in longest-to-shortest order.  Handy for indexing.
+	function permutePath(path) {
+	  if (path === '/') {
+	    return ['/'];
+	  }
+	  if (path.lastIndexOf('/') === path.length-1) {
+	    path = path.substr(0,path.length-1);
+	  }
+	  var permutations = [path];
+	  while (path.length > 1) {
+	    var lindex = path.lastIndexOf('/');
+	    if (lindex === 0) {
+	      break;
+	    }
+	    path = path.substr(0,lindex);
+	    permutations.push(path);
+	  }
+	  permutations.push('/');
+	  return permutations;
+	}
+
+	function getCookieContext(url) {
+	  if (url instanceof Object) {
+	    return url;
+	  }
+	  // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+	  // Therefore, we will just skip decoding for such URIs.
+	  try {
+	    url = decodeURI(url);
+	  }
+	  catch(err) {
+	    // Silently swallow error
+	  }
+
+	  return urlParse(url);
+	}
+
+	function Cookie(options) {
+	  options = options || {};
+
+	  Object.keys(options).forEach(function(prop) {
+	    if (Cookie.prototype.hasOwnProperty(prop) &&
+	        Cookie.prototype[prop] !== options[prop] &&
+	        prop.substr(0,1) !== '_')
+	    {
+	      this[prop] = options[prop];
+	    }
+	  }, this);
+
+	  this.creation = this.creation || new Date();
+
+	  // used to break creation ties in cookieCompare():
+	  Object.defineProperty(this, 'creationIndex', {
+	    configurable: false,
+	    enumerable: false, // important for assert.deepEqual checks
+	    writable: true,
+	    value: ++Cookie.cookiesCreated
+	  });
+	}
+
+	Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+	Cookie.parse = parse;
+	Cookie.fromJSON = fromJSON;
+
+	Cookie.prototype.key = "";
+	Cookie.prototype.value = "";
+
+	// the order in which the RFC has them:
+	Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+	Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+	Cookie.prototype.domain = null;
+	Cookie.prototype.path = null;
+	Cookie.prototype.secure = false;
+	Cookie.prototype.httpOnly = false;
+	Cookie.prototype.extensions = null;
+
+	// set by the CookieJar:
+	Cookie.prototype.hostOnly = null; // boolean when set
+	Cookie.prototype.pathIsDefault = null; // boolean when set
+	Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+	Cookie.prototype.lastAccessed = null; // Date when set
+	Object.defineProperty(Cookie.prototype, 'creationIndex', {
+	  configurable: true,
+	  enumerable: false,
+	  writable: true,
+	  value: 0
+	});
+
+	Cookie.serializableProperties = Object.keys(Cookie.prototype)
+	  .filter(function(prop) {
+	    return !(
+	      Cookie.prototype[prop] instanceof Function ||
+	      prop === 'creationIndex' ||
+	      prop.substr(0,1) === '_'
+	    );
+	  });
+
+	Cookie.prototype.inspect = function inspect() {
+	  var now = Date.now();
+	  return 'Cookie="'+this.toString() +
+	    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+	    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+	    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+	    '"';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+	}
+
+	Cookie.prototype.toJSON = function() {
+	  var obj = {};
+
+	  var props = Cookie.serializableProperties;
+	  for (var i=0; i<props.length; i++) {
+	    var prop = props[i];
+	    if (this[prop] === Cookie.prototype[prop]) {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (this[prop] === null) {
+	        obj[prop] = null;
+	      } else {
+	        obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+	          "Infinity" : this[prop].toISOString();
+	      }
+	    } else if (prop === 'maxAge') {
+	      if (this[prop] !== null) {
+	        // again, intentionally not ===
+	        obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+	          this[prop].toString() : this[prop];
+	      }
+	    } else {
+	      if (this[prop] !== Cookie.prototype[prop]) {
+	        obj[prop] = this[prop];
+	      }
+	    }
+	  }
+
+	  return obj;
+	};
+
+	Cookie.prototype.clone = function() {
+	  return fromJSON(this.toJSON());
+	};
+
+	Cookie.prototype.validate = function validate() {
+	  if (!COOKIE_OCTETS.test(this.value)) {
+	    return false;
+	  }
+	  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+	    return false;
+	  }
+	  if (this.maxAge != null && this.maxAge <= 0) {
+	    return false; // "Max-Age=" non-zero-digit *DIGIT
+	  }
+	  if (this.path != null && !PATH_VALUE.test(this.path)) {
+	    return false;
+	  }
+
+	  var cdomain = this.cdomain();
+	  if (cdomain) {
+	    if (cdomain.match(/\.$/)) {
+	      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+	    }
+	    var suffix = pubsuffix.getPublicSuffix(cdomain);
+	    if (suffix == null) { // it's a public suffix
+	      return false;
+	    }
+	  }
+	  return true;
+	};
+
+	Cookie.prototype.setExpires = function setExpires(exp) {
+	  if (exp instanceof Date) {
+	    this.expires = exp;
+	  } else {
+	    this.expires = parseDate(exp) || "Infinity";
+	  }
+	};
+
+	Cookie.prototype.setMaxAge = function setMaxAge(age) {
+	  if (age === Infinity || age === -Infinity) {
+	    this.maxAge = age.toString(); // so JSON.stringify() works
+	  } else {
+	    this.maxAge = age;
+	  }
+	};
+
+	// gives Cookie header format
+	Cookie.prototype.cookieString = function cookieString() {
+	  var val = this.value;
+	  if (val == null) {
+	    val = '';
+	  }
+	  if (this.key === '') {
+	    return val;
+	  }
+	  return this.key+'='+val;
+	};
+
+	// gives Set-Cookie header format
+	Cookie.prototype.toString = function toString() {
+	  var str = this.cookieString();
+
+	  if (this.expires != Infinity) {
+	    if (this.expires instanceof Date) {
+	      str += '; Expires='+formatDate(this.expires);
+	    } else {
+	      str += '; Expires='+this.expires;
+	    }
+	  }
+
+	  if (this.maxAge != null && this.maxAge != Infinity) {
+	    str += '; Max-Age='+this.maxAge;
+	  }
+
+	  if (this.domain && !this.hostOnly) {
+	    str += '; Domain='+this.domain;
+	  }
+	  if (this.path) {
+	    str += '; Path='+this.path;
+	  }
+
+	  if (this.secure) {
+	    str += '; Secure';
+	  }
+	  if (this.httpOnly) {
+	    str += '; HttpOnly';
+	  }
+	  if (this.extensions) {
+	    this.extensions.forEach(function(ext) {
+	      str += '; '+ext;
+	    });
+	  }
+
+	  return str;
+	};
+
+	// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	// S5.3 says to give the "latest representable date" for which we use Infinity
+	// For "expired" we use 0
+	Cookie.prototype.TTL = function TTL(now) {
+	  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+	   * attribute, the Max-Age attribute has precedence and controls the
+	   * expiration date of the cookie.
+	   * (Concurs with S5.3 step 3)
+	   */
+	  if (this.maxAge != null) {
+	    return this.maxAge<=0 ? 0 : this.maxAge*1000;
+	  }
+
+	  var expires = this.expires;
+	  if (expires != Infinity) {
+	    if (!(expires instanceof Date)) {
+	      expires = parseDate(expires) || Infinity;
+	    }
+
+	    if (expires == Infinity) {
+	      return Infinity;
+	    }
+
+	    return expires.getTime() - (now || Date.now());
+	  }
+
+	  return Infinity;
+	};
+
+	// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	Cookie.prototype.expiryTime = function expiryTime(now) {
+	  if (this.maxAge != null) {
+	    var relativeTo = now || this.creation || new Date();
+	    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+	    return relativeTo.getTime() + age;
+	  }
+
+	  if (this.expires == Infinity) {
+	    return Infinity;
+	  }
+	  return this.expires.getTime();
+	};
+
+	// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere), except it returns a Date
+	Cookie.prototype.expiryDate = function expiryDate(now) {
+	  var millisec = this.expiryTime(now);
+	  if (millisec == Infinity) {
+	    return new Date(MAX_TIME);
+	  } else if (millisec == -Infinity) {
+	    return new Date(MIN_TIME);
+	  } else {
+	    return new Date(millisec);
+	  }
+	};
+
+	// This replaces the "persistent-flag" parts of S5.3 step 3
+	Cookie.prototype.isPersistent = function isPersistent() {
+	  return (this.maxAge != null || this.expires != Infinity);
+	};
+
+	// Mostly S5.1.2 and S5.2.3:
+	Cookie.prototype.cdomain =
+	Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+	  if (this.domain == null) {
+	    return null;
+	  }
+	  return canonicalDomain(this.domain);
+	};
+
+	function CookieJar(store, options) {
+	  if (typeof options === "boolean") {
+	    options = {rejectPublicSuffixes: options};
+	  } else if (options == null) {
+	    options = {};
+	  }
+	  if (options.rejectPublicSuffixes != null) {
+	    this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+	  }
+	  if (options.looseMode != null) {
+	    this.enableLooseMode = options.looseMode;
+	  }
+
+	  if (!store) {
+	    store = new MemoryCookieStore();
+	  }
+	  this.store = store;
+	}
+	CookieJar.prototype.store = null;
+	CookieJar.prototype.rejectPublicSuffixes = true;
+	CookieJar.prototype.enableLooseMode = false;
+	var CAN_BE_SYNC = [];
+
+	CAN_BE_SYNC.push('setCookie');
+	CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+	  var err;
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var loose = this.enableLooseMode;
+	  if (options.loose != null) {
+	    loose = options.loose;
+	  }
+
+	  // S5.3 step 1
+	  if (!(cookie instanceof Cookie)) {
+	    cookie = Cookie.parse(cookie, { loose: loose });
+	  }
+	  if (!cookie) {
+	    err = new Error("Cookie failed to parse");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  // S5.3 step 2
+	  var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+	  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+	  // S5.3 step 4: NOOP; domain is null by default
+
+	  // S5.3 step 5: public suffixes
+	  if (this.rejectPublicSuffixes && cookie.domain) {
+	    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+	    if (suffix == null) { // e.g. "com"
+	      err = new Error("Cookie has domain set to a public suffix");
+	      return cb(options.ignoreError ? null : err);
+	    }
+	  }
+
+	  // S5.3 step 6:
+	  if (cookie.domain) {
+	    if (!domainMatch(host, cookie.cdomain(), false)) {
+	      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+	      return cb(options.ignoreError ? null : err);
+	    }
+
+	    if (cookie.hostOnly == null) { // don't reset if already set
+	      cookie.hostOnly = false;
+	    }
+
+	  } else {
+	    cookie.hostOnly = true;
+	    cookie.domain = host;
+	  }
+
+	  //S5.2.4 If the attribute-value is empty or if the first character of the
+	  //attribute-value is not %x2F ("/"):
+	  //Let cookie-path be the default-path.
+	  if (!cookie.path || cookie.path[0] !== '/') {
+	    cookie.path = defaultPath(context.pathname);
+	    cookie.pathIsDefault = true;
+	  }
+
+	  // S5.3 step 8: NOOP; secure attribute
+	  // S5.3 step 9: NOOP; httpOnly attribute
+
+	  // S5.3 step 10
+	  if (options.http === false && cookie.httpOnly) {
+	    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  var store = this.store;
+
+	  if (!store.updateCookie) {
+	    store.updateCookie = function(oldCookie, newCookie, cb) {
+	      this.putCookie(newCookie, cb);
+	    };
+	  }
+
+	  function withCookie(err, oldCookie) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    var next = function(err) {
+	      if (err) {
+	        return cb(err);
+	      } else {
+	        cb(null, cookie);
+	      }
+	    };
+
+	    if (oldCookie) {
+	      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+	      // domain, and path as the newly created cookie:"
+	      if (options.http === false && oldCookie.httpOnly) { // step 11.2
+	        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+	        return cb(options.ignoreError ? null : err);
+	      }
+	      cookie.creation = oldCookie.creation; // step 11.3
+	      cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+	      cookie.lastAccessed = now;
+	      // Step 11.4 (delete cookie) is implied by just setting the new one:
+	      store.updateCookie(oldCookie, cookie, next); // step 12
+
+	    } else {
+	      cookie.creation = cookie.lastAccessed = now;
+	      store.putCookie(cookie, next); // step 12
+	    }
+	  }
+
+	  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+	};
+
+	// RFC6365 S5.4
+	CAN_BE_SYNC.push('getCookies');
+	CookieJar.prototype.getCookies = function(url, options, cb) {
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var path = context.pathname || '/';
+
+	  var secure = options.secure;
+	  if (secure == null && context.protocol &&
+	      (context.protocol == 'https:' || context.protocol == 'wss:'))
+	  {
+	    secure = true;
+	  }
+
+	  var http = options.http;
+	  if (http == null) {
+	    http = true;
+	  }
+
+	  var now = options.now || Date.now();
+	  var expireCheck = options.expire !== false;
+	  var allPaths = !!options.allPaths;
+	  var store = this.store;
+
+	  function matchingCookie(c) {
+	    // "Either:
+	    //   The cookie's host-only-flag is true and the canonicalized
+	    //   request-host is identical to the cookie's domain.
+	    // Or:
+	    //   The cookie's host-only-flag is false and the canonicalized
+	    //   request-host domain-matches the cookie's domain."
+	    if (c.hostOnly) {
+	      if (c.domain != host) {
+	        return false;
+	      }
+	    } else {
+	      if (!domainMatch(host, c.domain, false)) {
+	        return false;
+	      }
+	    }
+
+	    // "The request-uri's path path-matches the cookie's path."
+	    if (!allPaths && !pathMatch(path, c.path)) {
+	      return false;
+	    }
+
+	    // "If the cookie's secure-only-flag is true, then the request-uri's
+	    // scheme must denote a "secure" protocol"
+	    if (c.secure && !secure) {
+	      return false;
+	    }
+
+	    // "If the cookie's http-only-flag is true, then exclude the cookie if the
+	    // cookie-string is being generated for a "non-HTTP" API"
+	    if (c.httpOnly && !http) {
+	      return false;
+	    }
+
+	    // deferred from S5.3
+	    // non-RFC: allow retention of expired cookies by choice
+	    if (expireCheck && c.expiryTime() <= now) {
+	      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+	      return false;
+	    }
+
+	    return true;
+	  }
+
+	  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    cookies = cookies.filter(matchingCookie);
+
+	    // sorting of S5.4 part 2
+	    if (options.sort !== false) {
+	      cookies = cookies.sort(cookieCompare);
+	    }
+
+	    // S5.4 part 3
+	    var now = new Date();
+	    cookies.forEach(function(c) {
+	      c.lastAccessed = now;
+	    });
+	    // TODO persist lastAccessed
+
+	    cb(null,cookies);
+	  });
+	};
+
+	CAN_BE_SYNC.push('getCookieString');
+	CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies
+	        .sort(cookieCompare)
+	        .map(function(c){
+	          return c.cookieString();
+	        })
+	        .join('; '));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('getSetCookieStrings');
+	CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies.map(function(c){
+	        return c.toString();
+	      }));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('serialize');
+	CookieJar.prototype.serialize = function(cb) {
+	  var type = this.store.constructor.name;
+	  if (type === 'Object') {
+	    type = null;
+	  }
+
+	  // update README.md "Serialization Format" if you change this, please!
+	  var serialized = {
+	    // The version of tough-cookie that serialized this jar. Generally a good
+	    // practice since future versions can make data import decisions based on
+	    // known past behavior. When/if this matters, use `semver`.
+	    version: 'tough-cookie@'+VERSION,
+
+	    // add the store type, to make humans happy:
+	    storeType: type,
+
+	    // CookieJar configuration:
+	    rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+	    // this gets filled from getAllCookies:
+	    cookies: []
+	  };
+
+	  if (!(this.store.getAllCookies &&
+	        typeof this.store.getAllCookies === 'function'))
+	  {
+	    return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+	  }
+
+	  this.store.getAllCookies(function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    serialized.cookies = cookies.map(function(cookie) {
+	      // convert to serialized 'raw' cookies
+	      cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+	      // Remove the index so new ones get assigned during deserialization
+	      delete cookie.creationIndex;
+
+	      return cookie;
+	    });
+
+	    return cb(null, serialized);
+	  });
+	};
+
+	// well-known name that JSON.stringify calls
+	CookieJar.prototype.toJSON = function() {
+	  return this.serializeSync();
+	};
+
+	// use the class method CookieJar.deserialize instead of calling this directly
+	CAN_BE_SYNC.push('_importCookies');
+	CookieJar.prototype._importCookies = function(serialized, cb) {
+	  var jar = this;
+	  var cookies = serialized.cookies;
+	  if (!cookies || !Array.isArray(cookies)) {
+	    return cb(new Error('serialized jar has no cookies array'));
+	  }
+	  cookies = cookies.slice(); // do not modify the original
+
+	  function putNext(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    if (!cookies.length) {
+	      return cb(err, jar);
+	    }
+
+	    var cookie;
+	    try {
+	      cookie = fromJSON(cookies.shift());
+	    } catch (e) {
+	      return cb(e);
+	    }
+
+	    if (cookie === null) {
+	      return putNext(null); // skip this cookie
+	    }
+
+	    jar.store.putCookie(cookie, putNext);
+	  }
+
+	  putNext();
+	};
+
+	CookieJar.deserialize = function(strOrObj, store, cb) {
+	  if (arguments.length !== 3) {
+	    // store is optional
+	    cb = store;
+	    store = null;
+	  }
+
+	  var serialized;
+	  if (typeof strOrObj === 'string') {
+	    serialized = jsonParse(strOrObj);
+	    if (serialized instanceof Error) {
+	      return cb(serialized);
+	    }
+	  } else {
+	    serialized = strOrObj;
+	  }
+
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+	  jar._importCookies(serialized, function(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    cb(null, jar);
+	  });
+	};
+
+	CookieJar.deserializeSync = function(strOrObj, store) {
+	  var serialized = typeof strOrObj === 'string' ?
+	    JSON.parse(strOrObj) : strOrObj;
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+	  // catch this mistake early:
+	  if (!jar.store.synchronous) {
+	    throw new Error('CookieJar store is not synchronous; use async API instead.');
+	  }
+
+	  jar._importCookiesSync(serialized);
+	  return jar;
+	};
+	CookieJar.fromJSON = CookieJar.deserializeSync;
+
+	CAN_BE_SYNC.push('clone');
+	CookieJar.prototype.clone = function(newStore, cb) {
+	  if (arguments.length === 1) {
+	    cb = newStore;
+	    newStore = null;
+	  }
+
+	  this.serialize(function(err,serialized) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    CookieJar.deserialize(newStore, serialized, cb);
+	  });
+	};
+
+	// Use a closure to provide a true imperative API for synchronous stores.
+	function syncWrap(method) {
+	  return function() {
+	    if (!this.store.synchronous) {
+	      throw new Error('CookieJar store is not synchronous; use async API instead.');
+	    }
+
+	    var args = Array.prototype.slice.call(arguments);
+	    var syncErr, syncResult;
+	    args.push(function syncCb(err, result) {
+	      syncErr = err;
+	      syncResult = result;
+	    });
+	    this[method].apply(this, args);
+
+	    if (syncErr) {
+	      throw syncErr;
+	    }
+	    return syncResult;
+	  };
+	}
+
+	// wrap all declared CAN_BE_SYNC methods in the sync wrapper
+	CAN_BE_SYNC.forEach(function(method) {
+	  CookieJar.prototype[method+'Sync'] = syncWrap(method);
+	});
+
+	exports.CookieJar = CookieJar;
+	exports.Cookie = Cookie;
+	exports.Store = Store;
+	exports.MemoryCookieStore = MemoryCookieStore;
+	exports.parseDate = parseDate;
+	exports.formatDate = formatDate;
+	exports.parse = parse;
+	exports.fromJSON = fromJSON;
+	exports.domainMatch = domainMatch;
+	exports.defaultPath = defaultPath;
+	exports.pathMatch = pathMatch;
+	exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+	exports.cookieCompare = cookieCompare;
+	exports.permuteDomain = __webpack_require__(19).permuteDomain;
+	exports.permutePath = permutePath;
+	exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+	/*
+	* Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+	* Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+	*/
+
+	var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+	var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+	function isIPv4(hostOrIp) {
+	  return hostOrIp.match(patternIPv4) ? true : false;
+	}
+
+	function isIPv6(hostOrIp) {
+	  return hostOrIp.match(patternIPv6) ? true : false;
+	}
+
+	function isIP(hostOrIp) {
+	  if (isIPv4(hostOrIp)) {
+	    return 4;
+	  }
+
+	  if (isIPv6(hostOrIp)) {
+	    return 6;
+	  }
+
+	  return 0;
+	}
+
+	module.exports = {
+	  isIPv4: isIPv4,
+	  isIPv6: isIPv6,
+	  isIP: isIP
+	};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var punycode = __webpack_require__(3);
+	var util = __webpack_require__(5);
+
+	exports.parse = urlParse;
+	exports.resolve = urlResolve;
+	exports.resolveObject = urlResolveObject;
+	exports.format = urlFormat;
+
+	exports.Url = Url;
+
+	function Url() {
+	  this.protocol = null;
+	  this.slashes = null;
+	  this.auth = null;
+	  this.host = null;
+	  this.port = null;
+	  this.hostname = null;
+	  this.hash = null;
+	  this.search = null;
+	  this.query = null;
+	  this.pathname = null;
+	  this.path = null;
+	  this.href = null;
+	}
+
+	// Reference: RFC 3986, RFC 1808, RFC 2396
+
+	// define these here so at least they only have to be
+	// compiled once on the first module load.
+	var protocolPattern = /^([a-z0-9.+-]+:)/i,
+	    portPattern = /:[0-9]*$/,
+
+	    // Special case for a simple path URL
+	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+	    // RFC 2396: characters reserved for delimiting URLs.
+	    // We actually just auto-escape these.
+	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+	    // RFC 2396: characters not allowed for various reasons.
+	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
+	    autoEscape = ['\''].concat(unwise),
+	    // Characters that are never ever allowed in a hostname.
+	    // Note that any invalid chars are also handled, but these
+	    // are the ones that are *expected* to be seen, so we fast-path
+	    // them.
+	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+	    hostEndingChars = ['/', '?', '#'],
+	    hostnameMaxLen = 255,
+	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+	    // protocols that can allow "unsafe" and "unwise" chars.
+	    unsafeProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that never have a hostname.
+	    hostlessProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that always contain a // bit.
+	    slashedProtocol = {
+	      'http': true,
+	      'https': true,
+	      'ftp': true,
+	      'gopher': true,
+	      'file': true,
+	      'http:': true,
+	      'https:': true,
+	      'ftp:': true,
+	      'gopher:': true,
+	      'file:': true
+	    },
+	    querystring = __webpack_require__(6);
+
+	function urlParse(url, parseQueryString, slashesDenoteHost) {
+	  if (url && util.isObject(url) && url instanceof Url) return url;
+
+	  var u = new Url;
+	  u.parse(url, parseQueryString, slashesDenoteHost);
+	  return u;
+	}
+
+	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+	  if (!util.isString(url)) {
+	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+	  }
+
+	  // Copy chrome, IE, opera backslash-handling behavior.
+	  // Back slashes before the query string get converted to forward slashes
+	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
+	  var queryIndex = url.indexOf('?'),
+	      splitter =
+	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+	      uSplit = url.split(splitter),
+	      slashRegex = /\\/g;
+	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
+	  url = uSplit.join(splitter);
+
+	  var rest = url;
+
+	  // trim before proceeding.
+	  // This is to support parse stuff like "  http://foo.com  \n"
+	  rest = rest.trim();
+
+	  if (!slashesDenoteHost && url.split('#').length === 1) {
+	    // Try fast path regexp
+	    var simplePath = simplePathPattern.exec(rest);
+	    if (simplePath) {
+	      this.path = rest;
+	      this.href = rest;
+	      this.pathname = simplePath[1];
+	      if (simplePath[2]) {
+	        this.search = simplePath[2];
+	        if (parseQueryString) {
+	          this.query = querystring.parse(this.search.substr(1));
+	        } else {
+	          this.query = this.search.substr(1);
+	        }
+	      } else if (parseQueryString) {
+	        this.search = '';
+	        this.query = {};
+	      }
+	      return this;
+	    }
+	  }
+
+	  var proto = protocolPattern.exec(rest);
+	  if (proto) {
+	    proto = proto[0];
+	    var lowerProto = proto.toLowerCase();
+	    this.protocol = lowerProto;
+	    rest = rest.substr(proto.length);
+	  }
+
+	  // figure out if it's got a host
+	  // user@server is *always* interpreted as a hostname, and url
+	  // resolution will treat //foo/bar as host=foo,path=bar because that's
+	  // how the browser resolves relative URLs.
+	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+	    var slashes = rest.substr(0, 2) === '//';
+	    if (slashes && !(proto && hostlessProtocol[proto])) {
+	      rest = rest.substr(2);
+	      this.slashes = true;
+	    }
+	  }
+
+	  if (!hostlessProtocol[proto] &&
+	      (slashes || (proto && !slashedProtocol[proto]))) {
+
+	    // there's a hostname.
+	    // the first instance of /, ?, ;, or # ends the host.
+	    //
+	    // If there is an @ in the hostname, then non-host chars *are* allowed
+	    // to the left of the last @ sign, unless some host-ending character
+	    // comes *before* the @-sign.
+	    // URLs are obnoxious.
+	    //
+	    // ex:
+	    // http://a@b@c/ => user:a@b host:c
+	    // http://a@b?@c => user:a host:c path:/?@c
+
+	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+	    // Review our test case against browsers more comprehensively.
+
+	    // find the first instance of any hostEndingChars
+	    var hostEnd = -1;
+	    for (var i = 0; i < hostEndingChars.length; i++) {
+	      var hec = rest.indexOf(hostEndingChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+
+	    // at this point, either we have an explicit point where the
+	    // auth portion cannot go past, or the last @ char is the decider.
+	    var auth, atSign;
+	    if (hostEnd === -1) {
+	      // atSign can be anywhere.
+	      atSign = rest.lastIndexOf('@');
+	    } else {
+	      // atSign must be in auth portion.
+	      // http://a@b/c@d => host:b auth:a path:/c@d
+	      atSign = rest.lastIndexOf('@', hostEnd);
+	    }
+
+	    // Now we have a portion which is definitely the auth.
+	    // Pull that off.
+	    if (atSign !== -1) {
+	      auth = rest.slice(0, atSign);
+	      rest = rest.slice(atSign + 1);
+	      this.auth = decodeURIComponent(auth);
+	    }
+
+	    // the host is the remaining to the left of the first non-host char
+	    hostEnd = -1;
+	    for (var i = 0; i < nonHostChars.length; i++) {
+	      var hec = rest.indexOf(nonHostChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+	    // if we still have not hit it, then the entire thing is a host.
+	    if (hostEnd === -1)
+	      hostEnd = rest.length;
+
+	    this.host = rest.slice(0, hostEnd);
+	    rest = rest.slice(hostEnd);
+
+	    // pull out port.
+	    this.parseHost();
+
+	    // we've indicated that there is a hostname,
+	    // so even if it's empty, it has to be present.
+	    this.hostname = this.hostname || '';
+
+	    // if hostname begins with [ and ends with ]
+	    // assume that it's an IPv6 address.
+	    var ipv6Hostname = this.hostname[0] === '[' &&
+	        this.hostname[this.hostname.length - 1] === ']';
+
+	    // validate a little.
+	    if (!ipv6Hostname) {
+	      var hostparts = this.hostname.split(/\./);
+	      for (var i = 0, l = hostparts.length; i < l; i++) {
+	        var part = hostparts[i];
+	        if (!part) continue;
+	        if (!part.match(hostnamePartPattern)) {
+	          var newpart = '';
+	          for (var j = 0, k = part.length; j < k; j++) {
+	            if (part.charCodeAt(j) > 127) {
+	              // we replace non-ASCII char with a temporary placeholder
+	              // we need this to make sure size of hostname is not
+	              // broken by replacing non-ASCII by nothing
+	              newpart += 'x';
+	            } else {
+	              newpart += part[j];
+	            }
+	          }
+	          // we test again with ASCII char only
+	          if (!newpart.match(hostnamePartPattern)) {
+	            var validParts = hostparts.slice(0, i);
+	            var notHost = hostparts.slice(i + 1);
+	            var bit = part.match(hostnamePartStart);
+	            if (bit) {
+	              validParts.push(bit[1]);
+	              notHost.unshift(bit[2]);
+	            }
+	            if (notHost.length) {
+	              rest = '/' + notHost.join('.') + rest;
+	            }
+	            this.hostname = validParts.join('.');
+	            break;
+	          }
+	        }
+	      }
+	    }
+
+	    if (this.hostname.length > hostnameMaxLen) {
+	      this.hostname = '';
+	    } else {
+	      // hostnames are always lower case.
+	      this.hostname = this.hostname.toLowerCase();
+	    }
+
+	    if (!ipv6Hostname) {
+	      // IDNA Support: Returns a punycoded representation of "domain".
+	      // It only converts parts of the domain name that
+	      // have non-ASCII characters, i.e. it doesn't matter if
+	      // you call it with a domain that already is ASCII-only.
+	      this.hostname = punycode.toASCII(this.hostname);
+	    }
+
+	    var p = this.port ? ':' + this.port : '';
+	    var h = this.hostname || '';
+	    this.host = h + p;
+	    this.href += this.host;
+
+	    // strip [ and ] from the hostname
+	    // the host field still retains them, though
+	    if (ipv6Hostname) {
+	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+	      if (rest[0] !== '/') {
+	        rest = '/' + rest;
+	      }
+	    }
+	  }
+
+	  // now rest is set to the post-host stuff.
+	  // chop off any delim chars.
+	  if (!unsafeProtocol[lowerProto]) {
+
+	    // First, make 100% sure that any "autoEscape" chars get
+	    // escaped, even if encodeURIComponent doesn't think they
+	    // need to be.
+	    for (var i = 0, l = autoEscape.length; i < l; i++) {
+	      var ae = autoEscape[i];
+	      if (rest.indexOf(ae) === -1)
+	        continue;
+	      var esc = encodeURIComponent(ae);
+	      if (esc === ae) {
+	        esc = escape(ae);
+	      }
+	      rest = rest.split(ae).join(esc);
+	    }
+	  }
+
+
+	  // chop off from the tail first.
+	  var hash = rest.indexOf('#');
+	  if (hash !== -1) {
+	    // got a fragment string.
+	    this.hash = rest.substr(hash);
+	    rest = rest.slice(0, hash);
+	  }
+	  var qm = rest.indexOf('?');
+	  if (qm !== -1) {
+	    this.search = rest.substr(qm);
+	    this.query = rest.substr(qm + 1);
+	    if (parseQueryString) {
+	      this.query = querystring.parse(this.query);
+	    }
+	    rest = rest.slice(0, qm);
+	  } else if (parseQueryString) {
+	    // no query string, but parseQueryString still requested
+	    this.search = '';
+	    this.query = {};
+	  }
+	  if (rest) this.pathname = rest;
+	  if (slashedProtocol[lowerProto] &&
+	      this.hostname && !this.pathname) {
+	    this.pathname = '/';
+	  }
+
+	  //to support http.request
+	  if (this.pathname || this.search) {
+	    var p = this.pathname || '';
+	    var s = this.search || '';
+	    this.path = p + s;
+	  }
+
+	  // finally, reconstruct the href based on what has been validated.
+	  this.href = this.format();
+	  return this;
+	};
+
+	// format a parsed object into a url string
+	function urlFormat(obj) {
+	  // ensure it's an object, and not a string url.
+	  // If it's an obj, this is a no-op.
+	  // this way, you can call url_format() on strings
+	  // to clean up potentially wonky urls.
+	  if (util.isString(obj)) obj = urlParse(obj);
+	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+	  return obj.format();
+	}
+
+	Url.prototype.format = function() {
+	  var auth = this.auth || '';
+	  if (auth) {
+	    auth = encodeURIComponent(auth);
+	    auth = auth.replace(/%3A/i, ':');
+	    auth += '@';
+	  }
+
+	  var protocol = this.protocol || '',
+	      pathname = this.pathname || '',
+	      hash = this.hash || '',
+	      host = false,
+	      query = '';
+
+	  if (this.host) {
+	    host = auth + this.host;
+	  } else if (this.hostname) {
+	    host = auth + (this.hostname.indexOf(':') === -1 ?
+	        this.hostname :
+	        '[' + this.hostname + ']');
+	    if (this.port) {
+	      host += ':' + this.port;
+	    }
+	  }
+
+	  if (this.query &&
+	      util.isObject(this.query) &&
+	      Object.keys(this.query).length) {
+	    query = querystring.stringify(this.query);
+	  }
+
+	  var search = this.search || (query && ('?' + query)) || '';
+
+	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
+	  // unless they had them to begin with.
+	  if (this.slashes ||
+	      (!protocol || slashedProtocol[protocol]) && host !== false) {
+	    host = '//' + (host || '');
+	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+	  } else if (!host) {
+	    host = '';
+	  }
+
+	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+	  if (search && search.charAt(0) !== '?') search = '?' + search;
+
+	  pathname = pathname.replace(/[?#]/g, function(match) {
+	    return encodeURIComponent(match);
+	  });
+	  search = search.replace('#', '%23');
+
+	  return protocol + host + pathname + search + hash;
+	};
+
+	function urlResolve(source, relative) {
+	  return urlParse(source, false, true).resolve(relative);
+	}
+
+	Url.prototype.resolve = function(relative) {
+	  return this.resolveObject(urlParse(relative, false, true)).format();
+	};
+
+	function urlResolveObject(source, relative) {
+	  if (!source) return relative;
+	  return urlParse(source, false, true).resolveObject(relative);
+	}
+
+	Url.prototype.resolveObject = function(relative) {
+	  if (util.isString(relative)) {
+	    var rel = new Url();
+	    rel.parse(relative, false, true);
+	    relative = rel;
+	  }
+
+	  var result = new Url();
+	  var tkeys = Object.keys(this);
+	  for (var tk = 0; tk < tkeys.length; tk++) {
+	    var tkey = tkeys[tk];
+	    result[tkey] = this[tkey];
+	  }
+
+	  // hash is always overridden, no matter what.
+	  // even href="" will remove it.
+	  result.hash = relative.hash;
+
+	  // if the relative url is empty, then there's nothing left to do here.
+	  if (relative.href === '') {
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // hrefs like //foo/bar always cut to the protocol.
+	  if (relative.slashes && !relative.protocol) {
+	    // take everything except the protocol from relative
+	    var rkeys = Object.keys(relative);
+	    for (var rk = 0; rk < rkeys.length; rk++) {
+	      var rkey = rkeys[rk];
+	      if (rkey !== 'protocol')
+	        result[rkey] = relative[rkey];
+	    }
+
+	    //urlParse appends trailing / to urls like http://www.example.com
+	    if (slashedProtocol[result.protocol] &&
+	        result.hostname && !result.pathname) {
+	      result.path = result.pathname = '/';
+	    }
+
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (relative.protocol && relative.protocol !== result.protocol) {
+	    // if it's a known url protocol, then changing
+	    // the protocol does weird things
+	    // first, if it's not file:, then we MUST have a host,
+	    // and if there was a path
+	    // to begin with, then we MUST have a path.
+	    // if it is file:, then the host is dropped,
+	    // because that's known to be hostless.
+	    // anything else is assumed to be absolute.
+	    if (!slashedProtocol[relative.protocol]) {
+	      var keys = Object.keys(relative);
+	      for (var v = 0; v < keys.length; v++) {
+	        var k = keys[v];
+	        result[k] = relative[k];
+	      }
+	      result.href = result.format();
+	      return result;
+	    }
+
+	    result.protocol = relative.protocol;
+	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
+	      var relPath = (relative.pathname || '').split('/');
+	      while (relPath.length && !(relative.host = relPath.shift()));
+	      if (!relative.host) relative.host = '';
+	      if (!relative.hostname) relative.hostname = '';
+	      if (relPath[0] !== '') relPath.unshift('');
+	      if (relPath.length < 2) relPath.unshift('');
+	      result.pathname = relPath.join('/');
+	    } else {
+	      result.pathname = relative.pathname;
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    result.host = relative.host || '';
+	    result.auth = relative.auth;
+	    result.hostname = relative.hostname || relative.host;
+	    result.port = relative.port;
+	    // to support http.request
+	    if (result.pathname || result.search) {
+	      var p = result.pathname || '';
+	      var s = result.search || '';
+	      result.path = p + s;
+	    }
+	    result.slashes = result.slashes || relative.slashes;
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+	      isRelAbs = (
+	          relative.host ||
+	          relative.pathname && relative.pathname.charAt(0) === '/'
+	      ),
+	      mustEndAbs = (isRelAbs || isSourceAbs ||
+	                    (result.host && relative.pathname)),
+	      removeAllDots = mustEndAbs,
+	      srcPath = result.pathname && result.pathname.split('/') || [],
+	      relPath = relative.pathname && relative.pathname.split('/') || [],
+	      psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+	  // if the url is a non-slashed url, then relative
+	  // links like ../.. should be able
+	  // to crawl up to the hostname, as well.  This is strange.
+	  // result.protocol has already been set by now.
+	  // Later on, put the first path part into the host field.
+	  if (psychotic) {
+	    result.hostname = '';
+	    result.port = null;
+	    if (result.host) {
+	      if (srcPath[0] === '') srcPath[0] = result.host;
+	      else srcPath.unshift(result.host);
+	    }
+	    result.host = '';
+	    if (relative.protocol) {
+	      relative.hostname = null;
+	      relative.port = null;
+	      if (relative.host) {
+	        if (relPath[0] === '') relPath[0] = relative.host;
+	        else relPath.unshift(relative.host);
+	      }
+	      relative.host = null;
+	    }
+	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+	  }
+
+	  if (isRelAbs) {
+	    // it's absolute.
+	    result.host = (relative.host || relative.host === '') ?
+	                  relative.host : result.host;
+	    result.hostname = (relative.hostname || relative.hostname === '') ?
+	                      relative.hostname : result.hostname;
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    srcPath = relPath;
+	    // fall through to the dot-handling below.
+	  } else if (relPath.length) {
+	    // it's relative
+	    // throw away the existing file, and take the new path instead.
+	    if (!srcPath) srcPath = [];
+	    srcPath.pop();
+	    srcPath = srcPath.concat(relPath);
+	    result.search = relative.search;
+	    result.query = relative.query;
+	  } else if (!util.isNullOrUndefined(relative.search)) {
+	    // just pull out the search.
+	    // like href='?foo'.
+	    // Put this after the other two cases because it simplifies the booleans
+	    if (psychotic) {
+	      result.hostname = result.host = srcPath.shift();
+	      //occationaly the auth can get stuck only in host
+	      //this especially happens in cases like
+	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                       result.host.split('@') : false;
+	      if (authInHost) {
+	        result.auth = authInHost.shift();
+	        result.host = result.hostname = authInHost.shift();
+	      }
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    //to support http.request
+	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	      result.path = (result.pathname ? result.pathname : '') +
+	                    (result.search ? result.search : '');
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (!srcPath.length) {
+	    // no path at all.  easy.
+	    // we've already handled the other stuff above.
+	    result.pathname = null;
+	    //to support http.request
+	    if (result.search) {
+	      result.path = '/' + result.search;
+	    } else {
+	      result.path = null;
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // if a url ENDs in . or .., then it must get a trailing slash.
+	  // however, if it ends in anything else non-slashy,
+	  // then it must NOT get a trailing slash.
+	  var last = srcPath.slice(-1)[0];
+	  var hasTrailingSlash = (
+	      (result.host || relative.host || srcPath.length > 1) &&
+	      (last === '.' || last === '..') || last === '');
+
+	  // strip single dots, resolve double dots to parent dir
+	  // if the path tries to go above the root, `up` ends up > 0
+	  var up = 0;
+	  for (var i = srcPath.length; i >= 0; i--) {
+	    last = srcPath[i];
+	    if (last === '.') {
+	      srcPath.splice(i, 1);
+	    } else if (last === '..') {
+	      srcPath.splice(i, 1);
+	      up++;
+	    } else if (up) {
+	      srcPath.splice(i, 1);
+	      up--;
+	    }
+	  }
+
+	  // if the path is allowed to go above the root, restore leading ..s
+	  if (!mustEndAbs && !removeAllDots) {
+	    for (; up--; up) {
+	      srcPath.unshift('..');
+	    }
+	  }
+
+	  if (mustEndAbs && srcPath[0] !== '' &&
+	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+	    srcPath.unshift('');
+	  }
+
+	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+	    srcPath.push('');
+	  }
+
+	  var isAbsolute = srcPath[0] === '' ||
+	      (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+	  // put the host back
+	  if (psychotic) {
+	    result.hostname = result.host = isAbsolute ? '' :
+	                                    srcPath.length ? srcPath.shift() : '';
+	    //occationaly the auth can get stuck only in host
+	    //this especially happens in cases like
+	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                     result.host.split('@') : false;
+	    if (authInHost) {
+	      result.auth = authInHost.shift();
+	      result.host = result.hostname = authInHost.shift();
+	    }
+	  }
+
+	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+	  if (mustEndAbs && !isAbsolute) {
+	    srcPath.unshift('');
+	  }
+
+	  if (!srcPath.length) {
+	    result.pathname = null;
+	    result.path = null;
+	  } else {
+	    result.pathname = srcPath.join('/');
+	  }
+
+	  //to support request.http
+	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	    result.path = (result.pathname ? result.pathname : '') +
+	                  (result.search ? result.search : '');
+	  }
+	  result.auth = relative.auth || result.auth;
+	  result.slashes = result.slashes || relative.slashes;
+	  result.href = result.format();
+	  return result;
+	};
+
+	Url.prototype.parseHost = function() {
+	  var host = this.host;
+	  var port = portPattern.exec(host);
+	  if (port) {
+	    port = port[0];
+	    if (port !== ':') {
+	      this.port = port.substr(1);
+	    }
+	    host = host.substr(0, host.length - port.length);
+	  }
+	  if (host) this.hostname = host;
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * http://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.3.2',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else { // in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else { // in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	module.exports = function(module) {

+		if(!module.webpackPolyfill) {

+			module.deprecate = function() {};

+			module.paths = [];

+			// module.parent = undefined by default

+			module.children = [];

+			module.webpackPolyfill = 1;

+		}

+		return module;

+	}

+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+	'use strict';
+
+	module.exports = {
+	  isString: function(arg) {
+	    return typeof(arg) === 'string';
+	  },
+	  isObject: function(arg) {
+	    return typeof(arg) === 'object' && arg !== null;
+	  },
+	  isNull: function(arg) {
+	    return arg === null;
+	  },
+	  isNullOrUndefined: function(arg) {
+	    return arg == null;
+	  }
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	exports.decode = exports.parse = __webpack_require__(7);
+	exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	// If obj.hasOwnProperty has been overridden, then calling
+	// obj.hasOwnProperty(prop) will break.
+	// See: https://github.com/joyent/node/issues/1707
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	module.exports = function(qs, sep, eq, options) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  var obj = {};
+
+	  if (typeof qs !== 'string' || qs.length === 0) {
+	    return obj;
+	  }
+
+	  var regexp = /\+/g;
+	  qs = qs.split(sep);
+
+	  var maxKeys = 1000;
+	  if (options && typeof options.maxKeys === 'number') {
+	    maxKeys = options.maxKeys;
+	  }
+
+	  var len = qs.length;
+	  // maxKeys <= 0 means that we should not limit keys count
+	  if (maxKeys > 0 && len > maxKeys) {
+	    len = maxKeys;
+	  }
+
+	  for (var i = 0; i < len; ++i) {
+	    var x = qs[i].replace(regexp, '%20'),
+	        idx = x.indexOf(eq),
+	        kstr, vstr, k, v;
+
+	    if (idx >= 0) {
+	      kstr = x.substr(0, idx);
+	      vstr = x.substr(idx + 1);
+	    } else {
+	      kstr = x;
+	      vstr = '';
+	    }
+
+	    k = decodeURIComponent(kstr);
+	    v = decodeURIComponent(vstr);
+
+	    if (!hasOwnProperty(obj, k)) {
+	      obj[k] = v;
+	    } else if (Array.isArray(obj[k])) {
+	      obj[k].push(v);
+	    } else {
+	      obj[k] = [obj[k], v];
+	    }
+	  }
+
+	  return obj;
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var stringifyPrimitive = function(v) {
+	  switch (typeof v) {
+	    case 'string':
+	      return v;
+
+	    case 'boolean':
+	      return v ? 'true' : 'false';
+
+	    case 'number':
+	      return isFinite(v) ? v : '';
+
+	    default:
+	      return '';
+	  }
+	};
+
+	module.exports = function(obj, sep, eq, name) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  if (obj === null) {
+	    obj = undefined;
+	  }
+
+	  if (typeof obj === 'object') {
+	    return Object.keys(obj).map(function(k) {
+	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+	      if (Array.isArray(obj[k])) {
+	        return obj[k].map(function(v) {
+	          return ks + encodeURIComponent(stringifyPrimitive(v));
+	        }).join(sep);
+	      } else {
+	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+	      }
+	    }).join(sep);
+
+	  }
+
+	  if (!name) return '';
+	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
+	         encodeURIComponent(stringifyPrimitive(obj));
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	var formatRegExp = /%[sdj%]/g;
+	exports.format = function(f) {
+	  if (!isString(f)) {
+	    var objects = [];
+	    for (var i = 0; i < arguments.length; i++) {
+	      objects.push(inspect(arguments[i]));
+	    }
+	    return objects.join(' ');
+	  }
+
+	  var i = 1;
+	  var args = arguments;
+	  var len = args.length;
+	  var str = String(f).replace(formatRegExp, function(x) {
+	    if (x === '%%') return '%';
+	    if (i >= len) return x;
+	    switch (x) {
+	      case '%s': return String(args[i++]);
+	      case '%d': return Number(args[i++]);
+	      case '%j':
+	        try {
+	          return JSON.stringify(args[i++]);
+	        } catch (_) {
+	          return '[Circular]';
+	        }
+	      default:
+	        return x;
+	    }
+	  });
+	  for (var x = args[i]; i < len; x = args[++i]) {
+	    if (isNull(x) || !isObject(x)) {
+	      str += ' ' + x;
+	    } else {
+	      str += ' ' + inspect(x);
+	    }
+	  }
+	  return str;
+	};
+
+
+	// Mark that a method should not be used.
+	// Returns a modified function which warns once by default.
+	// If --no-deprecation is set, then it is a no-op.
+	exports.deprecate = function(fn, msg) {
+	  // Allow for deprecating things in the process of starting up.
+	  if (isUndefined(global.process)) {
+	    return function() {
+	      return exports.deprecate(fn, msg).apply(this, arguments);
+	    };
+	  }
+
+	  if (process.noDeprecation === true) {
+	    return fn;
+	  }
+
+	  var warned = false;
+	  function deprecated() {
+	    if (!warned) {
+	      if (process.throwDeprecation) {
+	        throw new Error(msg);
+	      } else if (process.traceDeprecation) {
+	        console.trace(msg);
+	      } else {
+	        console.error(msg);
+	      }
+	      warned = true;
+	    }
+	    return fn.apply(this, arguments);
+	  }
+
+	  return deprecated;
+	};
+
+
+	var debugs = {};
+	var debugEnviron;
+	exports.debuglog = function(set) {
+	  if (isUndefined(debugEnviron))
+	    debugEnviron = process.env.NODE_DEBUG || '';
+	  set = set.toUpperCase();
+	  if (!debugs[set]) {
+	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+	      var pid = process.pid;
+	      debugs[set] = function() {
+	        var msg = exports.format.apply(exports, arguments);
+	        console.error('%s %d: %s', set, pid, msg);
+	      };
+	    } else {
+	      debugs[set] = function() {};
+	    }
+	  }
+	  return debugs[set];
+	};
+
+
+	/**
+	 * Echos the value of a value. Trys to print the value out
+	 * in the best way possible given the different types.
+	 *
+	 * @param {Object} obj The object to print out.
+	 * @param {Object} opts Optional options object that alters the output.
+	 */
+	/* legacy: obj, showHidden, depth, colors*/
+	function inspect(obj, opts) {
+	  // default options
+	  var ctx = {
+	    seen: [],
+	    stylize: stylizeNoColor
+	  };
+	  // legacy...
+	  if (arguments.length >= 3) ctx.depth = arguments[2];
+	  if (arguments.length >= 4) ctx.colors = arguments[3];
+	  if (isBoolean(opts)) {
+	    // legacy...
+	    ctx.showHidden = opts;
+	  } else if (opts) {
+	    // got an "options" object
+	    exports._extend(ctx, opts);
+	  }
+	  // set default options
+	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+	  if (isUndefined(ctx.depth)) ctx.depth = 2;
+	  if (isUndefined(ctx.colors)) ctx.colors = false;
+	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+	  if (ctx.colors) ctx.stylize = stylizeWithColor;
+	  return formatValue(ctx, obj, ctx.depth);
+	}
+	exports.inspect = inspect;
+
+
+	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+	inspect.colors = {
+	  'bold' : [1, 22],
+	  'italic' : [3, 23],
+	  'underline' : [4, 24],
+	  'inverse' : [7, 27],
+	  'white' : [37, 39],
+	  'grey' : [90, 39],
+	  'black' : [30, 39],
+	  'blue' : [34, 39],
+	  'cyan' : [36, 39],
+	  'green' : [32, 39],
+	  'magenta' : [35, 39],
+	  'red' : [31, 39],
+	  'yellow' : [33, 39]
+	};
+
+	// Don't use 'blue' not visible on cmd.exe
+	inspect.styles = {
+	  'special': 'cyan',
+	  'number': 'yellow',
+	  'boolean': 'yellow',
+	  'undefined': 'grey',
+	  'null': 'bold',
+	  'string': 'green',
+	  'date': 'magenta',
+	  // "name": intentionally not styling
+	  'regexp': 'red'
+	};
+
+
+	function stylizeWithColor(str, styleType) {
+	  var style = inspect.styles[styleType];
+
+	  if (style) {
+	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+	           '\u001b[' + inspect.colors[style][1] + 'm';
+	  } else {
+	    return str;
+	  }
+	}
+
+
+	function stylizeNoColor(str, styleType) {
+	  return str;
+	}
+
+
+	function arrayToHash(array) {
+	  var hash = {};
+
+	  array.forEach(function(val, idx) {
+	    hash[val] = true;
+	  });
+
+	  return hash;
+	}
+
+
+	function formatValue(ctx, value, recurseTimes) {
+	  // Provide a hook for user-specified inspect functions.
+	  // Check that value is an object with an inspect function on it
+	  if (ctx.customInspect &&
+	      value &&
+	      isFunction(value.inspect) &&
+	      // Filter out the util module, it's inspect function is special
+	      value.inspect !== exports.inspect &&
+	      // Also filter out any prototype objects using the circular check.
+	      !(value.constructor && value.constructor.prototype === value)) {
+	    var ret = value.inspect(recurseTimes, ctx);
+	    if (!isString(ret)) {
+	      ret = formatValue(ctx, ret, recurseTimes);
+	    }
+	    return ret;
+	  }
+
+	  // Primitive types cannot have properties
+	  var primitive = formatPrimitive(ctx, value);
+	  if (primitive) {
+	    return primitive;
+	  }
+
+	  // Look up the keys of the object.
+	  var keys = Object.keys(value);
+	  var visibleKeys = arrayToHash(keys);
+
+	  if (ctx.showHidden) {
+	    keys = Object.getOwnPropertyNames(value);
+	  }
+
+	  // IE doesn't make error fields non-enumerable
+	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+	  if (isError(value)
+	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+	    return formatError(value);
+	  }
+
+	  // Some type of object without properties can be shortcutted.
+	  if (keys.length === 0) {
+	    if (isFunction(value)) {
+	      var name = value.name ? ': ' + value.name : '';
+	      return ctx.stylize('[Function' + name + ']', 'special');
+	    }
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    }
+	    if (isDate(value)) {
+	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
+	    }
+	    if (isError(value)) {
+	      return formatError(value);
+	    }
+	  }
+
+	  var base = '', array = false, braces = ['{', '}'];
+
+	  // Make Array say that they are Array
+	  if (isArray(value)) {
+	    array = true;
+	    braces = ['[', ']'];
+	  }
+
+	  // Make functions say that they are functions
+	  if (isFunction(value)) {
+	    var n = value.name ? ': ' + value.name : '';
+	    base = ' [Function' + n + ']';
+	  }
+
+	  // Make RegExps say that they are RegExps
+	  if (isRegExp(value)) {
+	    base = ' ' + RegExp.prototype.toString.call(value);
+	  }
+
+	  // Make dates with properties first say the date
+	  if (isDate(value)) {
+	    base = ' ' + Date.prototype.toUTCString.call(value);
+	  }
+
+	  // Make error with message first say the error
+	  if (isError(value)) {
+	    base = ' ' + formatError(value);
+	  }
+
+	  if (keys.length === 0 && (!array || value.length == 0)) {
+	    return braces[0] + base + braces[1];
+	  }
+
+	  if (recurseTimes < 0) {
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    } else {
+	      return ctx.stylize('[Object]', 'special');
+	    }
+	  }
+
+	  ctx.seen.push(value);
+
+	  var output;
+	  if (array) {
+	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+	  } else {
+	    output = keys.map(function(key) {
+	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+	    });
+	  }
+
+	  ctx.seen.pop();
+
+	  return reduceToSingleString(output, base, braces);
+	}
+
+
+	function formatPrimitive(ctx, value) {
+	  if (isUndefined(value))
+	    return ctx.stylize('undefined', 'undefined');
+	  if (isString(value)) {
+	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+	                                             .replace(/'/g, "\\'")
+	                                             .replace(/\\"/g, '"') + '\'';
+	    return ctx.stylize(simple, 'string');
+	  }
+	  if (isNumber(value))
+	    return ctx.stylize('' + value, 'number');
+	  if (isBoolean(value))
+	    return ctx.stylize('' + value, 'boolean');
+	  // For some reason typeof null is "object", so special case here.
+	  if (isNull(value))
+	    return ctx.stylize('null', 'null');
+	}
+
+
+	function formatError(value) {
+	  return '[' + Error.prototype.toString.call(value) + ']';
+	}
+
+
+	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+	  var output = [];
+	  for (var i = 0, l = value.length; i < l; ++i) {
+	    if (hasOwnProperty(value, String(i))) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          String(i), true));
+	    } else {
+	      output.push('');
+	    }
+	  }
+	  keys.forEach(function(key) {
+	    if (!key.match(/^\d+$/)) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          key, true));
+	    }
+	  });
+	  return output;
+	}
+
+
+	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+	  var name, str, desc;
+	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+	  if (desc.get) {
+	    if (desc.set) {
+	      str = ctx.stylize('[Getter/Setter]', 'special');
+	    } else {
+	      str = ctx.stylize('[Getter]', 'special');
+	    }
+	  } else {
+	    if (desc.set) {
+	      str = ctx.stylize('[Setter]', 'special');
+	    }
+	  }
+	  if (!hasOwnProperty(visibleKeys, key)) {
+	    name = '[' + key + ']';
+	  }
+	  if (!str) {
+	    if (ctx.seen.indexOf(desc.value) < 0) {
+	      if (isNull(recurseTimes)) {
+	        str = formatValue(ctx, desc.value, null);
+	      } else {
+	        str = formatValue(ctx, desc.value, recurseTimes - 1);
+	      }
+	      if (str.indexOf('\n') > -1) {
+	        if (array) {
+	          str = str.split('\n').map(function(line) {
+	            return '  ' + line;
+	          }).join('\n').substr(2);
+	        } else {
+	          str = '\n' + str.split('\n').map(function(line) {
+	            return '   ' + line;
+	          }).join('\n');
+	        }
+	      }
+	    } else {
+	      str = ctx.stylize('[Circular]', 'special');
+	    }
+	  }
+	  if (isUndefined(name)) {
+	    if (array && key.match(/^\d+$/)) {
+	      return str;
+	    }
+	    name = JSON.stringify('' + key);
+	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+	      name = name.substr(1, name.length - 2);
+	      name = ctx.stylize(name, 'name');
+	    } else {
+	      name = name.replace(/'/g, "\\'")
+	                 .replace(/\\"/g, '"')
+	                 .replace(/(^"|"$)/g, "'");
+	      name = ctx.stylize(name, 'string');
+	    }
+	  }
+
+	  return name + ': ' + str;
+	}
+
+
+	function reduceToSingleString(output, base, braces) {
+	  var numLinesEst = 0;
+	  var length = output.reduce(function(prev, cur) {
+	    numLinesEst++;
+	    if (cur.indexOf('\n') >= 0) numLinesEst++;
+	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+	  }, 0);
+
+	  if (length > 60) {
+	    return braces[0] +
+	           (base === '' ? '' : base + '\n ') +
+	           ' ' +
+	           output.join(',\n  ') +
+	           ' ' +
+	           braces[1];
+	  }
+
+	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+	}
+
+
+	// NOTE: These type checking functions intentionally don't use `instanceof`
+	// because it is fragile and can be easily faked with `Object.create()`.
+	function isArray(ar) {
+	  return Array.isArray(ar);
+	}
+	exports.isArray = isArray;
+
+	function isBoolean(arg) {
+	  return typeof arg === 'boolean';
+	}
+	exports.isBoolean = isBoolean;
+
+	function isNull(arg) {
+	  return arg === null;
+	}
+	exports.isNull = isNull;
+
+	function isNullOrUndefined(arg) {
+	  return arg == null;
+	}
+	exports.isNullOrUndefined = isNullOrUndefined;
+
+	function isNumber(arg) {
+	  return typeof arg === 'number';
+	}
+	exports.isNumber = isNumber;
+
+	function isString(arg) {
+	  return typeof arg === 'string';
+	}
+	exports.isString = isString;
+
+	function isSymbol(arg) {
+	  return typeof arg === 'symbol';
+	}
+	exports.isSymbol = isSymbol;
+
+	function isUndefined(arg) {
+	  return arg === void 0;
+	}
+	exports.isUndefined = isUndefined;
+
+	function isRegExp(re) {
+	  return isObject(re) && objectToString(re) === '[object RegExp]';
+	}
+	exports.isRegExp = isRegExp;
+
+	function isObject(arg) {
+	  return typeof arg === 'object' && arg !== null;
+	}
+	exports.isObject = isObject;
+
+	function isDate(d) {
+	  return isObject(d) && objectToString(d) === '[object Date]';
+	}
+	exports.isDate = isDate;
+
+	function isError(e) {
+	  return isObject(e) &&
+	      (objectToString(e) === '[object Error]' || e instanceof Error);
+	}
+	exports.isError = isError;
+
+	function isFunction(arg) {
+	  return typeof arg === 'function';
+	}
+	exports.isFunction = isFunction;
+
+	function isPrimitive(arg) {
+	  return arg === null ||
+	         typeof arg === 'boolean' ||
+	         typeof arg === 'number' ||
+	         typeof arg === 'string' ||
+	         typeof arg === 'symbol' ||  // ES6 symbol
+	         typeof arg === 'undefined';
+	}
+	exports.isPrimitive = isPrimitive;
+
+	exports.isBuffer = __webpack_require__(11);
+
+	function objectToString(o) {
+	  return Object.prototype.toString.call(o);
+	}
+
+
+	function pad(n) {
+	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+	}
+
+
+	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+	              'Oct', 'Nov', 'Dec'];
+
+	// 26 Feb 16:19:34
+	function timestamp() {
+	  var d = new Date();
+	  var time = [pad(d.getHours()),
+	              pad(d.getMinutes()),
+	              pad(d.getSeconds())].join(':');
+	  return [d.getDate(), months[d.getMonth()], time].join(' ');
+	}
+
+
+	// log is just a thin wrapper to console.log that prepends a timestamp
+	exports.log = function() {
+	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+	};
+
+
+	/**
+	 * Inherit the prototype methods from one constructor into another.
+	 *
+	 * The Function.prototype.inherits from lang.js rewritten as a standalone
+	 * function (not on Function.prototype). NOTE: If this file is to be loaded
+	 * during bootstrapping this function needs to be rewritten using some native
+	 * functions as prototype setup using normal JavaScript does not work as
+	 * expected during bootstrapping (see mirror.js in r114903).
+	 *
+	 * @param {function} ctor Constructor function which needs to inherit the
+	 *     prototype.
+	 * @param {function} superCtor Constructor function to inherit prototype from.
+	 */
+	exports.inherits = __webpack_require__(12);
+
+	exports._extend = function(origin, add) {
+	  // Don't do anything if add isn't an object
+	  if (!add || !isObject(add)) return origin;
+
+	  var keys = Object.keys(add);
+	  var i = keys.length;
+	  while (i--) {
+	    origin[keys[i]] = add[keys[i]];
+	  }
+	  return origin;
+	};
+
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	// shim for using process in browser
+	var process = module.exports = {};
+
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+
+
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+
+
+
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+
+	    var len = queue.length;
+	    while(len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+
+	function noop() {}
+
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+
+	process.listeners = function (name) { return [] }
+
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+
+	process.cwd = function () { return '/' };
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	module.exports = function isBuffer(arg) {
+	  return arg && typeof arg === 'object'
+	    && typeof arg.copy === 'function'
+	    && typeof arg.fill === 'function'
+	    && typeof arg.readUInt8 === 'function';
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	if (typeof Object.create === 'function') {
+	  // implementation from standard node.js 'util' module
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    ctor.prototype = Object.create(superCtor.prototype, {
+	      constructor: {
+	        value: ctor,
+	        enumerable: false,
+	        writable: true,
+	        configurable: true
+	      }
+	    });
+	  };
+	} else {
+	  // old school shim for old browsers
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    var TempCtor = function () {}
+	    TempCtor.prototype = superCtor.prototype
+	    ctor.prototype = new TempCtor()
+	    ctor.prototype.constructor = ctor
+	  }
+	}
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2018, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var psl = __webpack_require__(14);
+
+	function getPublicSuffix(domain) {
+	  return psl.get(domain);
+	}
+
+	exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+	'use strict';
+
+
+	var Punycode = __webpack_require__(15);
+
+
+	var internals = {};
+
+
+	//
+	// Read rules from file.
+	//
+	internals.rules = __webpack_require__(16).map(function (rule) {
+
+	  return {
+	    rule: rule,
+	    suffix: rule.replace(/^(\*\.|\!)/, ''),
+	    punySuffix: -1,
+	    wildcard: rule.charAt(0) === '*',
+	    exception: rule.charAt(0) === '!'
+	  };
+	});
+
+
+	//
+	// Check is given string ends with `suffix`.
+	//
+	internals.endsWith = function (str, suffix) {
+
+	  return str.indexOf(suffix, str.length - suffix.length) !== -1;
+	};
+
+
+	//
+	// Find rule for a given domain.
+	//
+	internals.findRule = function (domain) {
+
+	  var punyDomain = Punycode.toASCII(domain);
+	  return internals.rules.reduce(function (memo, rule) {
+
+	    if (rule.punySuffix === -1){
+	      rule.punySuffix = Punycode.toASCII(rule.suffix);
+	    }
+	    if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+	      return memo;
+	    }
+	    // This has been commented out as it never seems to run. This is because
+	    // sub tlds always appear after their parents and we never find a shorter
+	    // match.
+	    //if (memo) {
+	    //  var memoSuffix = Punycode.toASCII(memo.suffix);
+	    //  if (memoSuffix.length >= punySuffix.length) {
+	    //    return memo;
+	    //  }
+	    //}
+	    return rule;
+	  }, null);
+	};
+
+
+	//
+	// Error codes and messages.
+	//
+	exports.errorCodes = {
+	  DOMAIN_TOO_SHORT: 'Domain name too short.',
+	  DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+	  LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+	  LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+	  LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+	  LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+	  LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+	};
+
+
+	//
+	// Validate domain name and throw if not valid.
+	//
+	// From wikipedia:
+	//
+	// Hostnames are composed of series of labels concatenated with dots, as are all
+	// domain names. Each label must be between 1 and 63 characters long, and the
+	// entire hostname (including the delimiting dots) has a maximum of 255 chars.
+	//
+	// Allowed chars:
+	//
+	// * `a-z`
+	// * `0-9`
+	// * `-` but not as a starting or ending character
+	// * `.` as a separator for the textual portions of a domain name
+	//
+	// * http://en.wikipedia.org/wiki/Domain_name
+	// * http://en.wikipedia.org/wiki/Hostname
+	//
+	internals.validate = function (input) {
+
+	  // Before we can validate we need to take care of IDNs with unicode chars.
+	  var ascii = Punycode.toASCII(input);
+
+	  if (ascii.length < 1) {
+	    return 'DOMAIN_TOO_SHORT';
+	  }
+	  if (ascii.length > 255) {
+	    return 'DOMAIN_TOO_LONG';
+	  }
+
+	  // Check each part's length and allowed chars.
+	  var labels = ascii.split('.');
+	  var label;
+
+	  for (var i = 0; i < labels.length; ++i) {
+	    label = labels[i];
+	    if (!label.length) {
+	      return 'LABEL_TOO_SHORT';
+	    }
+	    if (label.length > 63) {
+	      return 'LABEL_TOO_LONG';
+	    }
+	    if (label.charAt(0) === '-') {
+	      return 'LABEL_STARTS_WITH_DASH';
+	    }
+	    if (label.charAt(label.length - 1) === '-') {
+	      return 'LABEL_ENDS_WITH_DASH';
+	    }
+	    if (!/^[a-z0-9\-]+$/.test(label)) {
+	      return 'LABEL_INVALID_CHARS';
+	    }
+	  }
+	};
+
+
+	//
+	// Public API
+	//
+
+
+	//
+	// Parse domain.
+	//
+	exports.parse = function (input) {
+
+	  if (typeof input !== 'string') {
+	    throw new TypeError('Domain name must be a string.');
+	  }
+
+	  // Force domain to lowercase.
+	  var domain = input.slice(0).toLowerCase();
+
+	  // Handle FQDN.
+	  // TODO: Simply remove trailing dot?
+	  if (domain.charAt(domain.length - 1) === '.') {
+	    domain = domain.slice(0, domain.length - 1);
+	  }
+
+	  // Validate and sanitise input.
+	  var error = internals.validate(domain);
+	  if (error) {
+	    return {
+	      input: input,
+	      error: {
+	        message: exports.errorCodes[error],
+	        code: error
+	      }
+	    };
+	  }
+
+	  var parsed = {
+	    input: input,
+	    tld: null,
+	    sld: null,
+	    domain: null,
+	    subdomain: null,
+	    listed: false
+	  };
+
+	  var domainParts = domain.split('.');
+
+	  // Non-Internet TLD
+	  if (domainParts[domainParts.length - 1] === 'local') {
+	    return parsed;
+	  }
+
+	  var handlePunycode = function () {
+
+	    if (!/xn--/.test(domain)) {
+	      return parsed;
+	    }
+	    if (parsed.domain) {
+	      parsed.domain = Punycode.toASCII(parsed.domain);
+	    }
+	    if (parsed.subdomain) {
+	      parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+	    }
+	    return parsed;
+	  };
+
+	  var rule = internals.findRule(domain);
+
+	  // Unlisted tld.
+	  if (!rule) {
+	    if (domainParts.length < 2) {
+	      return parsed;
+	    }
+	    parsed.tld = domainParts.pop();
+	    parsed.sld = domainParts.pop();
+	    parsed.domain = [parsed.sld, parsed.tld].join('.');
+	    if (domainParts.length) {
+	      parsed.subdomain = domainParts.pop();
+	    }
+	    return handlePunycode();
+	  }
+
+	  // At this point we know the public suffix is listed.
+	  parsed.listed = true;
+
+	  var tldParts = rule.suffix.split('.');
+	  var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+	  if (rule.exception) {
+	    privateParts.push(tldParts.shift());
+	  }
+
+	  parsed.tld = tldParts.join('.');
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  if (rule.wildcard) {
+	    tldParts.unshift(privateParts.pop());
+	    parsed.tld = tldParts.join('.');
+	  }
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  parsed.sld = privateParts.pop();
+	  parsed.domain = [parsed.sld,  parsed.tld].join('.');
+
+	  if (privateParts.length) {
+	    parsed.subdomain = privateParts.join('.');
+	  }
+
+	  return handlePunycode();
+	};
+
+
+	//
+	// Get domain.
+	//
+	exports.get = function (domain) {
+
+	  if (!domain) {
+	    return null;
+	  }
+	  return exports.parse(domain).domain || null;
+	};
+
+
+	//
+	// Check whether domain belongs to a known public suffix.
+	//
+	exports.isValid = function (domain) {
+
+	  var parsed = exports.parse(domain);
+	  return Boolean(parsed.domain && parsed.listed);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw new RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * https://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.4.1',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) {
+				// in Node.js, io.js, or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else {
+				// in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else {
+			// in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	/*jshint unused:false */
+
+	function Store() {
+	}
+	exports.Store = Store;
+
+	// Stores may be synchronous, but are still required to use a
+	// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
+	// API that converts from synchronous-callbacks to imperative style.
+	Store.prototype.synchronous = false;
+
+	Store.prototype.findCookie = function(domain, path, key, cb) {
+	  throw new Error('findCookie is not implemented');
+	};
+
+	Store.prototype.findCookies = function(domain, path, cb) {
+	  throw new Error('findCookies is not implemented');
+	};
+
+	Store.prototype.putCookie = function(cookie, cb) {
+	  throw new Error('putCookie is not implemented');
+	};
+
+	Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // recommended default implementation:
+	  // return this.putCookie(newCookie, cb);
+	  throw new Error('updateCookie is not implemented');
+	};
+
+	Store.prototype.removeCookie = function(domain, path, key, cb) {
+	  throw new Error('removeCookie is not implemented');
+	};
+
+	Store.prototype.removeCookies = function(domain, path, cb) {
+	  throw new Error('removeCookies is not implemented');
+	};
+
+	Store.prototype.getAllCookies = function(cb) {
+	  throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var Store = __webpack_require__(17).Store;
+	var permuteDomain = __webpack_require__(19).permuteDomain;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var util = __webpack_require__(9);
+
+	function MemoryCookieStore() {
+	  Store.call(this);
+	  this.idx = {};
+	}
+	util.inherits(MemoryCookieStore, Store);
+	exports.MemoryCookieStore = MemoryCookieStore;
+	MemoryCookieStore.prototype.idx = null;
+
+	// Since it's just a struct in RAM, this Store is synchronous
+	MemoryCookieStore.prototype.synchronous = true;
+
+	// force a default depth:
+	MemoryCookieStore.prototype.inspect = function() {
+	  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+	}
+
+	MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+	  if (!this.idx[domain]) {
+	    return cb(null,undefined);
+	  }
+	  if (!this.idx[domain][path]) {
+	    return cb(null,undefined);
+	  }
+	  return cb(null,this.idx[domain][path][key]||null);
+	};
+
+	MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+	  var results = [];
+	  if (!domain) {
+	    return cb(null,[]);
+	  }
+
+	  var pathMatcher;
+	  if (!path) {
+	    // null means "all paths"
+	    pathMatcher = function matchAll(domainIndex) {
+	      for (var curPath in domainIndex) {
+	        var pathIndex = domainIndex[curPath];
+	        for (var key in pathIndex) {
+	          results.push(pathIndex[key]);
+	        }
+	      }
+	    };
+
+	  } else {
+	    pathMatcher = function matchRFC(domainIndex) {
+	       //NOTE: we should use path-match algorithm from S5.1.4 here
+	       //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+	       Object.keys(domainIndex).forEach(function (cookiePath) {
+	         if (pathMatch(path, cookiePath)) {
+	           var pathIndex = domainIndex[cookiePath];
+
+	           for (var key in pathIndex) {
+	             results.push(pathIndex[key]);
+	           }
+	         }
+	       });
+	     };
+	  }
+
+	  var domains = permuteDomain(domain) || [domain];
+	  var idx = this.idx;
+	  domains.forEach(function(curDomain) {
+	    var domainIndex = idx[curDomain];
+	    if (!domainIndex) {
+	      return;
+	    }
+	    pathMatcher(domainIndex);
+	  });
+
+	  cb(null,results);
+	};
+
+	MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+	  if (!this.idx[cookie.domain]) {
+	    this.idx[cookie.domain] = {};
+	  }
+	  if (!this.idx[cookie.domain][cookie.path]) {
+	    this.idx[cookie.domain][cookie.path] = {};
+	  }
+	  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // updateCookie() may avoid updating cookies that are identical.  For example,
+	  // lastAccessed may not be important to some stores and an equality
+	  // comparison could exclude that field.
+	  this.putCookie(newCookie,cb);
+	};
+
+	MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+	  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+	    delete this.idx[domain][path][key];
+	  }
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+	  if (this.idx[domain]) {
+	    if (path) {
+	      delete this.idx[domain][path];
+	    } else {
+	      delete this.idx[domain];
+	    }
+	  }
+	  return cb(null);
+	};
+
+	MemoryCookieStore.prototype.getAllCookies = function(cb) {
+	  var cookies = [];
+	  var idx = this.idx;
+
+	  var domains = Object.keys(idx);
+	  domains.forEach(function(domain) {
+	    var paths = Object.keys(idx[domain]);
+	    paths.forEach(function(path) {
+	      var keys = Object.keys(idx[domain][path]);
+	      keys.forEach(function(key) {
+	        if (key !== null) {
+	          cookies.push(idx[domain][path][key]);
+	        }
+	      });
+	    });
+	  });
+
+	  // Sort by creationIndex so deserializing retains the creation order.
+	  // When implementing your own store, this SHOULD retain the order too
+	  cookies.sort(function(a,b) {
+	    return (a.creationIndex||0) - (b.creationIndex||0);
+	  });
+
+	  cb(null, cookies);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	var pubsuffix = __webpack_require__(13);
+
+	// Gives the permutation of all possible domainMatch()es of a given domain. The
+	// array is in shortest-to-longest order.  Handy for indexing.
+	function permuteDomain (domain) {
+	  var pubSuf = pubsuffix.getPublicSuffix(domain);
+	  if (!pubSuf) {
+	    return null;
+	  }
+	  if (pubSuf == domain) {
+	    return [domain];
+	  }
+
+	  var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+	  var parts = prefix.split('.').reverse();
+	  var cur = pubSuf;
+	  var permutations = [cur];
+	  while (parts.length) {
+	    cur = parts.shift() + '.' + cur;
+	    permutations.push(cur);
+	  }
+	  return permutations;
+	}
+
+	exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	/*
+	 * "A request-path path-matches a given cookie-path if at least one of the
+	 * following conditions holds:"
+	 */
+	function pathMatch (reqPath, cookiePath) {
+	  // "o  The cookie-path and the request-path are identical."
+	  if (cookiePath === reqPath) {
+	    return true;
+	  }
+
+	  var idx = reqPath.indexOf(cookiePath);
+	  if (idx === 0) {
+	    // "o  The cookie-path is a prefix of the request-path, and the last
+	    // character of the cookie-path is %x2F ("/")."
+	    if (cookiePath.substr(-1) === "/") {
+	      return true;
+	    }
+
+	    // " o  The cookie-path is a prefix of the request-path, and the first
+	    // character of the request-path that is not included in the cookie- path
+	    // is a %x2F ("/") character."
+	    if (reqPath.substr(cookiePath.length, 1) === "/") {
+	      return true;
+	    }
+	  }
+
+	  return false;
+	}
+
+	exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..2e92be6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,105 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) { module.exports = function init(jsUtil) {
+  return {
+    parseUrl: parseUrl,
+    appendQueryParamsString: appendQueryParamsString,
+    serializeQueryParams: serializeQueryParams
+  }
+
+  function parseUrl(url) {
+    var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+    return match && {
+        protocol: match[1],
+        host: match[2],
+        hostname: match[3],
+        port: match[4] || '',
+        pathname: match[5],
+        search: match[6],
+        hash: match[7]
+    }
+  }
+
+  function appendQueryParamsString(url, params) {
+    if (!url.length || !params.length) {
+      return url;
+    }
+
+    var parsed = parseUrl(url);
+
+    return parsed.protocol
+      + '//'
+      + parsed.host
+      + parsed.pathname
+      + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+      + parsed.hash;
+  }
+
+  function serializeQueryParams(params, encode) {
+    return serializeObject('', params, encode);
+  }
+
+  function serializeObject(parentKey, object, encode) {
+    var parts = [];
+
+    for (var key in object) {
+      if (!object.hasOwnProperty(key)) {
+        continue;
+      }
+
+      var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+      if (jsUtil.getTypeOf(object[key]) === 'Array') {
+        parts.push(serializeArray(identifier, object[key], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+        parts.push(serializeObject(identifier, object[key], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeArray(parentKey, array, encode) {
+    var parts = [];
+
+    for (var i = 0; i < array.length; ++i) {
+      if (jsUtil.getTypeOf(array[i]) === 'Array') {
+        parts.push(serializeArray(parentKey + '[]', array[i], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+        parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeIdentifier(parentKey, key, encode) {
+    if (!parentKey.length) {
+      return encode ? encodeURIComponent(key) : key;
+    }
+
+    if (encode) {
+      return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+    } else {
+      return parentKey + '[' + key + ']';
+    }
+  }
+
+  function serializeValue(value, encode) {
+    if (encode) {
+      return encodeURIComponent(value);
+    } else {
+      return value;
+    }
+  }
+};
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js
new file mode 100644
index 0000000..50d8bff
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/src/browser/CameraProxy.js
@@ -0,0 +1,125 @@
+cordova.define("cordova-plugin-camera.CameraProxy", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+ */
+
+var HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
+
+function takePicture (success, error, opts) {
+    if (opts && opts[2] === 1) {
+        capture(success, error, opts);
+    } else {
+        var input = document.createElement('input');
+        input.style.position = 'relative';
+        input.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+        input.className = 'cordova-camera-select';
+        input.type = 'file';
+        input.name = 'files[]';
+
+        input.onchange = function (inputEvent) {
+            var reader = new FileReader(); /* eslint no-undef : 0 */
+            reader.onload = function (readerEvent) {
+                input.parentNode.removeChild(input);
+
+                var imageData = readerEvent.target.result;
+
+                return success(imageData.substr(imageData.indexOf(',') + 1));
+            };
+
+            reader.readAsDataURL(inputEvent.target.files[0]);
+        };
+
+        document.body.appendChild(input);
+    }
+}
+
+function capture (success, errorCallback, opts) {
+    var localMediaStream;
+    var targetWidth = opts[3];
+    var targetHeight = opts[4];
+
+    targetWidth = targetWidth === -1 ? 320 : targetWidth;
+    targetHeight = targetHeight === -1 ? 240 : targetHeight;
+
+    var video = document.createElement('video');
+    var button = document.createElement('button');
+    var parent = document.createElement('div');
+    parent.style.position = 'relative';
+    parent.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+    parent.className = 'cordova-camera-capture';
+    parent.appendChild(video);
+    parent.appendChild(button);
+
+    video.width = targetWidth;
+    video.height = targetHeight;
+    button.innerHTML = 'Capture!';
+
+    button.onclick = function () {
+        // create a canvas and capture a frame from video stream
+        var canvas = document.createElement('canvas');
+        canvas.width = targetWidth;
+        canvas.height = targetHeight;
+        canvas.getContext('2d').drawImage(video, 0, 0, targetWidth, targetHeight);
+
+        // convert image stored in canvas to base64 encoded image
+        var imageData = canvas.toDataURL('image/png');
+        imageData = imageData.replace('data:image/png;base64,', '');
+
+        // stop video stream, remove video and button.
+        // Note that MediaStream.stop() is deprecated as of Chrome 47.
+        if (localMediaStream.stop) {
+            localMediaStream.stop();
+        } else {
+            localMediaStream.getTracks().forEach(function (track) {
+                track.stop();
+            });
+        }
+        parent.parentNode.removeChild(parent);
+
+        return success(imageData);
+    };
+
+    navigator.getUserMedia = navigator.getUserMedia ||
+                             navigator.webkitGetUserMedia ||
+                             navigator.mozGetUserMedia ||
+                             navigator.msGetUserMedia;
+
+    var successCallback = function (stream) {
+        localMediaStream = stream;
+        video.src = window.URL.createObjectURL(localMediaStream);
+        video.play();
+
+        document.body.appendChild(parent);
+    };
+
+    if (navigator.getUserMedia) {
+        navigator.getUserMedia({video: true, audio: true}, successCallback, errorCallback);
+    } else {
+        alert('Browser does not support camera :(');
+    }
+}
+
+module.exports = {
+    takePicture: takePicture,
+    cleanup: function () {}
+};
+
+require('cordova/exec/proxy').add('Camera', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3959553
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,187 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ *    var image = document.getElementById('myImage');
+ *    image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the  returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery.  The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified.  To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+        mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+    // XXX: commented out
+    // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ *     console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ *     alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+    exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..c271df6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,103 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+     * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+     * disable any image modifications (resize, quality change, cropping, etc.) due
+     * to implementation specific.
+     *
+     * @enum {number}
+     */
+    DestinationType: {
+        /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+        DATA_URL: 0,
+        /** Return file uri (content://media/external/images/media/2 for Android) */
+        FILE_URI: 1,
+        /** Return native uri (eg. asset-library://... for iOS) */
+        NATIVE_URI: 2
+    },
+    /**
+     * @enum {number}
+     */
+    EncodingType: {
+        /** Return JPEG encoded image */
+        JPEG: 0,
+        /** Return PNG encoded image */
+        PNG: 1
+    },
+    /**
+     * @enum {number}
+     */
+    MediaType: {
+        /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+        PICTURE: 0,
+        /** Allow selection of video only, ONLY RETURNS URL */
+        VIDEO: 1,
+        /** Allow selection from all media types */
+        ALLMEDIA: 2
+    },
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+     * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+     * change, cropping, etc.) due to implementation specific.
+     *
+     * @enum {number}
+     */
+    PictureSourceType: {
+        /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+        PHOTOLIBRARY: 0,
+        /** Take picture from camera */
+        CAMERA: 1,
+        /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+        SAVEDPHOTOALBUM: 2
+    },
+    /**
+     * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+     * @enum {number}
+     */
+    PopoverArrowDirection: {
+        ARROW_UP: 1,
+        ARROW_DOWN: 2,
+        ARROW_LEFT: 4,
+        ARROW_RIGHT: 8,
+        ARROW_ANY: 15
+    },
+    /**
+     * @enum {number}
+     */
+    Direction: {
+        /** Use the back-facing camera */
+        BACK: 0,
+        /** Use the front-facing camera */
+        FRONT: 1
+    }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..9b42e8b
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,54 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen.  Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js
new file mode 100644
index 0000000..a4998fe
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-device/src/browser/DeviceProxy.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.DeviceProxy", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+ */
+var browser = require('cordova/platform');
+
+function getPlatform () {
+    return 'browser';
+}
+
+function getModel () {
+    return getBrowserInfo(true);
+}
+
+function getVersion () {
+    return getBrowserInfo(false);
+}
+
+function getBrowserInfo (getModel) {
+    var userAgent = navigator.userAgent;
+    var returnVal = '';
+    var offset;
+
+    if ((offset = userAgent.indexOf('Edge')) !== -1) {
+        returnVal = (getModel) ? 'Edge' : userAgent.substring(offset + 5);
+    } else if ((offset = userAgent.indexOf('Chrome')) !== -1) {
+        returnVal = (getModel) ? 'Chrome' : userAgent.substring(offset + 7);
+    } else if ((offset = userAgent.indexOf('Safari')) !== -1) {
+        if (getModel) {
+            returnVal = 'Safari';
+        } else {
+            returnVal = userAgent.substring(offset + 7);
+
+            if ((offset = userAgent.indexOf('Version')) !== -1) {
+                returnVal = userAgent.substring(offset + 8);
+            }
+        }
+    } else if ((offset = userAgent.indexOf('Firefox')) !== -1) {
+        returnVal = (getModel) ? 'Firefox' : userAgent.substring(offset + 8);
+    } else if ((offset = userAgent.indexOf('MSIE')) !== -1) {
+        returnVal = (getModel) ? 'MSIE' : userAgent.substring(offset + 5);
+    } else if ((offset = userAgent.indexOf('Trident')) !== -1) {
+        returnVal = (getModel) ? 'MSIE' : '11';
+    }
+
+    if ((offset = returnVal.indexOf(';')) !== -1 || (offset = returnVal.indexOf(' ')) !== -1) {
+        returnVal = returnVal.substring(0, offset);
+    }
+
+    return returnVal;
+}
+
+module.exports = {
+    getDeviceInfo: function (success, error) {
+        setTimeout(function () {
+            success({
+                cordova: browser.cordovaVersion,
+                platform: getPlatform(),
+                model: getModel(),
+                version: getVersion(),
+                uuid: null,
+                isVirtual: false
+            });
+        }, 0);
+    }
+};
+
+require('cordova/exec/proxy').add('Device', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js b/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..059351d
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,85 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+    this.available = false;
+    this.platform = null;
+    this.version = null;
+    this.uuid = null;
+    this.cordova = null;
+    this.model = null;
+    this.manufacturer = null;
+    this.isVirtual = null;
+    this.serial = null;
+
+    var me = this;
+
+    channel.onCordovaReady.subscribe(function () {
+        me.getInfo(function (info) {
+            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+            // TODO: CB-5105 native implementations should not return info.cordova
+            var buildLabel = cordova.version;
+            me.available = true;
+            me.platform = info.platform;
+            me.version = info.version;
+            me.uuid = info.uuid;
+            me.cordova = buildLabel;
+            me.model = info.model;
+            me.isVirtual = info.isVirtual;
+            me.manufacturer = info.manufacturer || 'unknown';
+            me.serial = info.serial || 'unknown';
+            channel.onCordovaInfoReady.fire();
+        }, function (e) {
+            me.available = false;
+            utils.alert('[ERROR] Error initializing Cordova: ' + e);
+        });
+    });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+    exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js
new file mode 100644
index 0000000..d7b0541
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/src/browser/FileProxy.js
@@ -0,0 +1,986 @@
+cordova.define("cordova-plugin-file.browserFileProxy", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+ */
+(function () {
+    /* global require, exports, module */
+    /* global FILESYSTEM_PREFIX */
+    /* global IDBKeyRange */
+
+    /* Heavily based on https://github.com/ebidel/idb.filesystem.js */
+
+    // For chrome we don't need to implement proxy methods
+    // All functionality can be accessed natively.
+    if (require('./isChrome')()) {
+        var pathsPrefix = {
+            // Read-only directory where the application is installed.
+            applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
+            // Where to put app-specific data files.
+            dataDirectory: 'filesystem:file:///persistent/',
+            // Cached files that should survive app restarts.
+            // Apps should not rely on the OS to delete files in here.
+            cacheDirectory: 'filesystem:file:///temporary/'
+        };
+
+        exports.requestAllPaths = function (successCallback) {
+            successCallback(pathsPrefix);
+        };
+
+        require('cordova/exec/proxy').add('File', module.exports);
+        return;
+    }
+
+    var LocalFileSystem = require('./LocalFileSystem');
+    var FileSystem = require('./FileSystem');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var File = require('./File');
+
+    (function (exports, global) {
+        var indexedDB = global.indexedDB || global.mozIndexedDB;
+        if (!indexedDB) {
+            throw 'Firefox OS File plugin: indexedDB not supported';
+        }
+
+        var fs_ = null;
+
+        var idb_ = {};
+        idb_.db = null;
+        var FILE_STORE_ = 'entries';
+
+        var DIR_SEPARATOR = '/';
+
+        var pathsPrefix = {
+            // Read-only directory where the application is installed.
+            applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
+            // Where to put app-specific data files.
+            dataDirectory: 'file:///persistent/',
+            // Cached files that should survive app restarts.
+            // Apps should not rely on the OS to delete files in here.
+            cacheDirectory: 'file:///temporary/'
+        };
+
+        var unicodeLastChar = 65535;
+
+    /** * Exported functionality ***/
+
+        exports.requestFileSystem = function (successCallback, errorCallback, args) {
+            var type = args[0];
+            // Size is ignored since IDB filesystem size depends
+            // on browser implementation and can't be set up by user
+            var size = args[1]; // eslint-disable-line no-unused-vars
+
+            if (type !== LocalFileSystem.TEMPORARY && type !== LocalFileSystem.PERSISTENT) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            var name = type === LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent';
+            var storageName = (location.protocol + location.host).replace(/:/g, '_'); // eslint-disable-line no-undef
+
+            var root = new DirectoryEntry('', DIR_SEPARATOR);
+            fs_ = new FileSystem(name, root);
+
+            idb_.open(storageName, function () {
+                successCallback(fs_);
+            }, errorCallback);
+        };
+
+        // Overridden by Android, BlackBerry 10 and iOS to populate fsMap
+        require('./fileSystems').getFs = function (name, callback) {
+            callback(new FileSystem(name, fs_.root));
+        };
+
+        // list a directory's contents (files and folders).
+        exports.readEntries = function (successCallback, errorCallback, args) {
+            var fullPath = args[0];
+
+            if (typeof successCallback !== 'function') {
+                throw Error('Expected successCallback argument.');
+            }
+
+            var path = resolveToFullPath_(fullPath);
+
+            exports.getDirectory(function () {
+                idb_.getAllEntries(path.fullPath + DIR_SEPARATOR, path.storagePath, function (entries) {
+                    successCallback(entries);
+                }, errorCallback);
+            }, function () {
+                if (errorCallback) {
+                    errorCallback(FileError.NOT_FOUND_ERR);
+                }
+            }, [path.storagePath, path.fullPath, {create: false}]);
+        };
+
+        exports.getFile = function (successCallback, errorCallback, args) {
+            var fullPath = args[0];
+            var path = args[1];
+            var options = args[2] || {};
+
+            // Create an absolute path if we were handed a relative one.
+            path = resolveToFullPath_(fullPath, path);
+
+            idb_.get(path.storagePath, function (fileEntry) {
+                if (options.create === true && options.exclusive === true && fileEntry) {
+                    // If create and exclusive are both true, and the path already exists,
+                    // getFile must fail.
+
+                    if (errorCallback) {
+                        errorCallback(FileError.PATH_EXISTS_ERR);
+                    }
+                } else if (options.create === true && !fileEntry) {
+                    // If create is true, the path doesn't exist, and no other error occurs,
+                    // getFile must create it as a zero-length file and return a corresponding
+                    // FileEntry.
+                    var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+                    newFileEntry.file_ = new MyFile({
+                        size: 0,
+                        name: newFileEntry.name,
+                        lastModifiedDate: new Date(),
+                        storagePath: path.storagePath
+                    });
+
+                    idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
+                } else if (options.create === true && fileEntry) {
+                    if (fileEntry.isFile) {
+                        // Overwrite file, delete then create new.
+                        idb_['delete'](path.storagePath, function () {
+                            var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+                            newFileEntry.file_ = new MyFile({
+                                size: 0,
+                                name: newFileEntry.name,
+                                lastModifiedDate: new Date(),
+                                storagePath: path.storagePath
+                            });
+
+                            idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
+                        }, errorCallback);
+                    } else {
+                        if (errorCallback) {
+                            errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                        }
+                    }
+                } else if ((!options.create || options.create === false) && !fileEntry) {
+                    // If create is not true and the path doesn't exist, getFile must fail.
+                    if (errorCallback) {
+                        errorCallback(FileError.NOT_FOUND_ERR);
+                    }
+                } else if ((!options.create || options.create === false) && fileEntry &&
+                    fileEntry.isDirectory) {
+                    // If create is not true and the path exists, but is a directory, getFile
+                    // must fail.
+                    if (errorCallback) {
+                        errorCallback(FileError.TYPE_MISMATCH_ERR);
+                    }
+                } else {
+                    // Otherwise, if no other error occurs, getFile must return a FileEntry
+                    // corresponding to path.
+
+                    successCallback(fileEntryFromIdbEntry(fileEntry));
+                }
+            }, errorCallback);
+        };
+
+        exports.getFileMetadata = function (successCallback, errorCallback, args) {
+            var fullPath = args[0];
+
+            exports.getFile(function (fileEntry) {
+                successCallback(new File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate,
+                    fileEntry.file_.size));
+            }, errorCallback, [fullPath, null]);
+        };
+
+        exports.getMetadata = function (successCallback, errorCallback, args) {
+            exports.getFile(function (fileEntry) {
+                successCallback(
+                    {
+                        modificationTime: fileEntry.file_.lastModifiedDate,
+                        size: fileEntry.file_.lastModifiedDate
+                    });
+            }, errorCallback, args);
+        };
+
+        exports.setMetadata = function (successCallback, errorCallback, args) {
+            var fullPath = args[0];
+            var metadataObject = args[1];
+
+            exports.getFile(function (fileEntry) {
+                fileEntry.file_.lastModifiedDate = metadataObject.modificationTime;
+                idb_.put(fileEntry, fileEntry.file_.storagePath, successCallback, errorCallback);
+            }, errorCallback, [fullPath, null]);
+        };
+
+        exports.write = function (successCallback, errorCallback, args) {
+            var fileName = args[0];
+            var data = args[1];
+            var position = args[2];
+            var isBinary = args[3]; // eslint-disable-line no-unused-vars
+
+            if (!data) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            if (typeof data === 'string' || data instanceof String) {
+                data = new Blob([data]); // eslint-disable-line no-undef
+            }
+
+            exports.getFile(function (fileEntry) {
+                var blob_ = fileEntry.file_.blob_;
+
+                if (!blob_) {
+                    blob_ = new Blob([data], {type: data.type}); // eslint-disable-line no-undef
+                } else {
+                    // Calc the head and tail fragments
+                    var head = blob_.slice(0, position);
+                    var tail = blob_.slice(position + (data.size || data.byteLength));
+
+                    // Calc the padding
+                    var padding = position - head.size;
+                    if (padding < 0) {
+                        padding = 0;
+                    }
+
+                    // Do the "write". In fact, a full overwrite of the Blob.
+                    blob_ = new Blob([head, new Uint8Array(padding), data, tail], // eslint-disable-line no-undef
+                        {type: data.type});
+                }
+
+                // Set the blob we're writing on this file entry so we can recall it later.
+                fileEntry.file_.blob_ = blob_;
+                fileEntry.file_.lastModifiedDate = new Date() || null;
+                fileEntry.file_.size = blob_.size;
+                fileEntry.file_.name = blob_.name;
+                fileEntry.file_.type = blob_.type;
+
+                idb_.put(fileEntry, fileEntry.file_.storagePath, function () {
+                    successCallback(data.size || data.byteLength);
+                }, errorCallback);
+            }, errorCallback, [fileName, null]);
+        };
+
+        exports.readAsText = function (successCallback, errorCallback, args) {
+            var fileName = args[0];
+            var enc = args[1];
+            var startPos = args[2];
+            var endPos = args[3];
+
+            readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback);
+        };
+
+        exports.readAsDataURL = function (successCallback, errorCallback, args) {
+            var fileName = args[0];
+            var startPos = args[1];
+            var endPos = args[2];
+
+            readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback);
+        };
+
+        exports.readAsBinaryString = function (successCallback, errorCallback, args) {
+            var fileName = args[0];
+            var startPos = args[1];
+            var endPos = args[2];
+
+            readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback);
+        };
+
+        exports.readAsArrayBuffer = function (successCallback, errorCallback, args) {
+            var fileName = args[0];
+            var startPos = args[1];
+            var endPos = args[2];
+
+            readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback);
+        };
+
+        exports.removeRecursively = exports.remove = function (successCallback, errorCallback, args) {
+            if (typeof successCallback !== 'function') {
+                throw Error('Expected successCallback argument.');
+            }
+
+            var fullPath = resolveToFullPath_(args[0]).storagePath;
+            if (fullPath === pathsPrefix.cacheDirectory || fullPath === pathsPrefix.dataDirectory) {
+                errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR);
+                return;
+            }
+
+            function deleteEntry (isDirectory) {
+                // TODO: This doesn't protect against directories that have content in it.
+                // Should throw an error instead if the dirEntry is not empty.
+                idb_['delete'](fullPath, function () {
+                    successCallback();
+                }, function () {
+                    if (errorCallback) { errorCallback(); }
+                }, isDirectory);
+            }
+
+            // We need to to understand what we are deleting:
+            exports.getDirectory(function (entry) {
+                deleteEntry(entry.isDirectory);
+            }, function () {
+                // DirectoryEntry was already deleted or entry is FileEntry
+                deleteEntry(false);
+            }, [fullPath, null, {create: false}]);
+        };
+
+        exports.getDirectory = function (successCallback, errorCallback, args) {
+            var fullPath = args[0];
+            var path = args[1];
+            var options = args[2];
+
+            // Create an absolute path if we were handed a relative one.
+            path = resolveToFullPath_(fullPath, path);
+
+            idb_.get(path.storagePath, function (folderEntry) {
+                if (!options) {
+                    options = {};
+                }
+
+                if (options.create === true && options.exclusive === true && folderEntry) {
+                    // If create and exclusive are both true, and the path already exists,
+                    // getDirectory must fail.
+                    if (errorCallback) {
+                        errorCallback(FileError.PATH_EXISTS_ERR);
+                    }
+                    // There is a strange bug in mobilespec + FF, which results in coming to multiple else-if's
+                    // so we are shielding from it with returns.
+                    return;
+                }
+
+                if (options.create === true && !folderEntry) {
+                    // If create is true, the path doesn't exist, and no other error occurs,
+                    // getDirectory must create it as a zero-length file and return a corresponding
+                    // MyDirectoryEntry.
+                    var dirEntry = new DirectoryEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
+
+                    idb_.put(dirEntry, path.storagePath, successCallback, errorCallback);
+                    return;
+                }
+
+                if (options.create === true && folderEntry) {
+
+                    if (folderEntry.isDirectory) {
+                        // IDB won't save methods, so we need re-create the MyDirectoryEntry.
+                        successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
+                    } else {
+                        if (errorCallback) {
+                            errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                        }
+                    }
+                    return;
+                }
+
+                if ((!options.create || options.create === false) && !folderEntry) {
+                    // Handle root special. It should always exist.
+                    if (path.fullPath === DIR_SEPARATOR) {
+                        successCallback(fs_.root);
+                        return;
+                    }
+
+                    // If create is not true and the path doesn't exist, getDirectory must fail.
+                    if (errorCallback) {
+                        errorCallback(FileError.NOT_FOUND_ERR);
+                    }
+
+                    return;
+                }
+                if ((!options.create || options.create === false) && folderEntry && folderEntry.isFile) {
+                    // If create is not true and the path exists, but is a file, getDirectory
+                    // must fail.
+                    if (errorCallback) {
+                        errorCallback(FileError.TYPE_MISMATCH_ERR);
+                    }
+                    return;
+                }
+
+                // Otherwise, if no other error occurs, getDirectory must return a
+                // MyDirectoryEntry corresponding to path.
+
+                // IDB won't' save methods, so we need re-create MyDirectoryEntry.
+                successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
+            }, errorCallback);
+        };
+
+        exports.getParent = function (successCallback, errorCallback, args) {
+            if (typeof successCallback !== 'function') {
+                throw Error('Expected successCallback argument.');
+            }
+
+            var fullPath = args[0];
+            // fullPath is like this:
+            // file:///persistent/path/to/file or
+            // file:///persistent/path/to/directory/
+
+            if (fullPath === DIR_SEPARATOR || fullPath === pathsPrefix.cacheDirectory ||
+                fullPath === pathsPrefix.dataDirectory) {
+                successCallback(fs_.root);
+                return;
+            }
+
+            // To delete all slashes at the end
+            while (fullPath[fullPath.length - 1] === '/') {
+                fullPath = fullPath.substr(0, fullPath.length - 1);
+            }
+
+            var pathArr = fullPath.split(DIR_SEPARATOR);
+            pathArr.pop();
+            var parentName = pathArr.pop();
+            var path = pathArr.join(DIR_SEPARATOR) + DIR_SEPARATOR;
+
+            // To get parent of root files
+            var joined = path + parentName + DIR_SEPARATOR;// is like this: file:///persistent/
+            if (joined === pathsPrefix.cacheDirectory || joined === pathsPrefix.dataDirectory) {
+                exports.getDirectory(successCallback, errorCallback, [joined, DIR_SEPARATOR, {create: false}]);
+                return;
+            }
+
+            exports.getDirectory(successCallback, errorCallback, [path, parentName, {create: false}]);
+        };
+
+        exports.copyTo = function (successCallback, errorCallback, args) {
+            var srcPath = args[0];
+            var parentFullPath = args[1];
+            var name = args[2];
+
+            if (name.indexOf('/') !== -1 || srcPath === parentFullPath + name) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+
+                return;
+            }
+
+            // Read src file
+            exports.getFile(function (srcFileEntry) {
+
+                var path = resolveToFullPath_(parentFullPath);
+                // Check directory
+                exports.getDirectory(function () {
+
+                    // Create dest file
+                    exports.getFile(function (dstFileEntry) {
+
+                        exports.write(function () {
+                            successCallback(dstFileEntry);
+                        }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]);
+
+                    }, errorCallback, [parentFullPath, name, {create: true}]);
+
+                }, function () { if (errorCallback) { errorCallback(FileError.NOT_FOUND_ERR); } },
+                [path.storagePath, null, {create: false}]);
+
+            }, errorCallback, [srcPath, null]);
+        };
+
+        exports.moveTo = function (successCallback, errorCallback, args) {
+            var srcPath = args[0];
+            // parentFullPath and name parameters is ignored because
+            // args is being passed downstream to exports.copyTo method
+            var parentFullPath = args[1]; // eslint-disable-line
+            var name = args[2]; // eslint-disable-line
+
+            exports.copyTo(function (fileEntry) {
+
+                exports.remove(function () {
+                    successCallback(fileEntry);
+                }, errorCallback, [srcPath]);
+
+            }, errorCallback, args);
+        };
+
+        exports.resolveLocalFileSystemURI = function (successCallback, errorCallback, args) {
+            var path = args[0];
+
+            // Ignore parameters
+            if (path.indexOf('?') !== -1) {
+                path = String(path).split('?')[0];
+            }
+
+            // support for encodeURI
+            if (/\%5/g.test(path) || /\%20/g.test(path)) {  // eslint-disable-line no-useless-escape
+                path = decodeURI(path);
+            }
+
+            if (path.trim()[0] === '/') {
+                if (errorCallback) {
+                    errorCallback(FileError.ENCODING_ERR);
+                }
+                return;
+            }
+
+            // support for cdvfile
+            if (path.trim().substr(0, 7) === 'cdvfile') {
+                if (path.indexOf('cdvfile://localhost') === -1) {
+                    if (errorCallback) {
+                        errorCallback(FileError.ENCODING_ERR);
+                    }
+                    return;
+                }
+
+                var indexPersistent = path.indexOf('persistent');
+                var indexTemporary = path.indexOf('temporary');
+
+                // cdvfile://localhost/persistent/path/to/file
+                if (indexPersistent !== -1) {
+                    path = 'file:///persistent' + path.substr(indexPersistent + 10);
+                } else if (indexTemporary !== -1) {
+                    path = 'file:///temporary' + path.substr(indexTemporary + 9);
+                } else {
+                    if (errorCallback) {
+                        errorCallback(FileError.ENCODING_ERR);
+                    }
+                    return;
+                }
+            }
+
+            // to avoid path form of '///path/to/file'
+            function handlePathSlashes (path) {
+                var cutIndex = 0;
+                for (var i = 0; i < path.length - 1; i++) {
+                    if (path[i] === DIR_SEPARATOR && path[i + 1] === DIR_SEPARATOR) {
+                        cutIndex = i + 1;
+                    } else break;
+                }
+
+                return path.substr(cutIndex);
+            }
+
+            // Handle localhost containing paths (see specs )
+            if (path.indexOf('file://localhost/') === 0) {
+                path = path.replace('file://localhost/', 'file:///');
+            }
+
+            if (path.indexOf(pathsPrefix.dataDirectory) === 0) {
+                path = path.substring(pathsPrefix.dataDirectory.length - 1);
+                path = handlePathSlashes(path);
+
+                exports.requestFileSystem(function () {
+                    exports.getFile(successCallback, function () {
+                        exports.getDirectory(successCallback, errorCallback, [pathsPrefix.dataDirectory, path,
+                        {create: false}]);
+                    }, [pathsPrefix.dataDirectory, path, {create: false}]);
+                }, errorCallback, [LocalFileSystem.PERSISTENT]);
+            } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) {
+                path = path.substring(pathsPrefix.cacheDirectory.length - 1);
+                path = handlePathSlashes(path);
+
+                exports.requestFileSystem(function () {
+                    exports.getFile(successCallback, function () {
+                        exports.getDirectory(successCallback, errorCallback, [pathsPrefix.cacheDirectory, path,
+                        {create: false}]);
+                    }, [pathsPrefix.cacheDirectory, path, {create: false}]);
+                }, errorCallback, [LocalFileSystem.TEMPORARY]);
+            } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) {
+                path = path.substring(pathsPrefix.applicationDirectory.length);
+                // TODO: need to cut out redundant slashes?
+
+                var xhr = new XMLHttpRequest(); // eslint-disable-line no-undef
+                xhr.open('GET', path, true);
+                xhr.onreadystatechange = function () {
+                    if (xhr.status === 200 && xhr.readyState === 4) {
+                        exports.requestFileSystem(function (fs) {
+                            fs.name = location.hostname; // eslint-disable-line no-undef
+
+                            // TODO: need to call exports.getFile(...) to handle errors correct
+                            fs.root.getFile(path, {create: true}, writeFile, errorCallback);
+                        }, errorCallback, [LocalFileSystem.PERSISTENT]);
+                    }
+                };
+
+                xhr.onerror = function () {
+                    if (errorCallback) {
+                        errorCallback(FileError.NOT_READABLE_ERR);
+                    }
+                };
+
+                xhr.send();
+            } else {
+                if (errorCallback) {
+                    errorCallback(FileError.NOT_FOUND_ERR);
+                }
+            }
+
+            function writeFile (entry) {
+                entry.createWriter(function (fileWriter) {
+                    fileWriter.onwriteend = function (evt) {
+                        if (!evt.target.error) {
+                            entry.filesystemName = location.hostname; // eslint-disable-line no-undef
+                            successCallback(entry);
+                        }
+                    };
+                    fileWriter.onerror = function () {
+                        if (errorCallback) {
+                            errorCallback(FileError.NOT_READABLE_ERR);
+                        }
+                    };
+                    fileWriter.write(new Blob([xhr.response])); // eslint-disable-line no-undef
+                }, errorCallback); // eslint-disable-line no-undef
+            }
+        };
+
+        exports.requestAllPaths = function (successCallback) {
+            successCallback(pathsPrefix);
+        };
+
+    /** * Helpers ***/
+
+        /**
+         * Interface to wrap the native File interface.
+         *
+         * This interface is necessary for creating zero-length (empty) files,
+         * something the Filesystem API allows you to do. Unfortunately, File's
+         * constructor cannot be called directly, making it impossible to instantiate
+         * an empty File in JS.
+         *
+         * @param {Object} opts Initial values.
+         * @constructor
+         */
+        function MyFile (opts) {
+            var blob_ = new Blob(); // eslint-disable-line no-undef
+
+            this.size = opts.size || 0;
+            this.name = opts.name || '';
+            this.type = opts.type || '';
+            this.lastModifiedDate = opts.lastModifiedDate || null;
+            this.storagePath = opts.storagePath || '';
+
+            // Need some black magic to correct the object's size/name/type based on the
+            // blob that is saved.
+            Object.defineProperty(this, 'blob_', {
+                enumerable: true,
+                get: function () {
+                    return blob_;
+                },
+                set: function (val) {
+                    blob_ = val;
+                    this.size = blob_.size;
+                    this.name = blob_.name;
+                    this.type = blob_.type;
+                    this.lastModifiedDate = blob_.lastModifiedDate;
+                }.bind(this)
+            });
+        }
+
+        MyFile.prototype.constructor = MyFile;
+
+        // When saving an entry, the fullPath should always lead with a slash and never
+        // end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute
+        // one. This method ensures path is legit!
+        function resolveToFullPath_ (cwdFullPath, path) {
+            path = path || '';
+            var fullPath = path;
+            var prefix = '';
+
+            cwdFullPath = cwdFullPath || DIR_SEPARATOR;
+            if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) {
+                prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
+                cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
+            }
+
+            var relativePath = path[0] !== DIR_SEPARATOR;
+            if (relativePath) {
+                fullPath = cwdFullPath;
+                if (cwdFullPath !== DIR_SEPARATOR) {
+                    fullPath += DIR_SEPARATOR + path;
+                } else {
+                    fullPath += path;
+                }
+            }
+
+            // Remove doubled separator substrings
+            var re = new RegExp(DIR_SEPARATOR + DIR_SEPARATOR, 'g');
+            fullPath = fullPath.replace(re, DIR_SEPARATOR);
+
+            // Adjust '..'s by removing parent directories when '..' flows in path.
+            var parts = fullPath.split(DIR_SEPARATOR);
+            for (var i = 0; i < parts.length; ++i) {
+                var part = parts[i];
+                if (part === '..') {
+                    parts[i - 1] = '';
+                    parts[i] = '';
+                }
+            }
+            fullPath = parts.filter(function (el) {
+                return el;
+            }).join(DIR_SEPARATOR);
+
+            // Add back in leading slash.
+            if (fullPath[0] !== DIR_SEPARATOR) {
+                fullPath = DIR_SEPARATOR + fullPath;
+            }
+
+            // Replace './' by current dir. ('./one/./two' -> one/two)
+            fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR);
+
+            // Replace '//' with '/'.
+            fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR);
+
+            // Replace '/.' with '/'.
+            fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR);
+
+            // Remove '/' if it appears on the end.
+            if (fullPath[fullPath.length - 1] === DIR_SEPARATOR &&
+                fullPath !== DIR_SEPARATOR) {
+                fullPath = fullPath.substring(0, fullPath.length - 1);
+            }
+
+            var storagePath = prefix + fullPath;
+            storagePath = decodeURI(storagePath);
+            fullPath = decodeURI(fullPath);
+
+            return {
+                storagePath: storagePath,
+                fullPath: fullPath,
+                fileName: fullPath.split(DIR_SEPARATOR).pop(),
+                fsName: prefix.split(DIR_SEPARATOR).pop()
+            };
+        }
+
+        function fileEntryFromIdbEntry (fileEntry) {
+            // IDB won't save methods, so we need re-create the FileEntry.
+            var clonedFileEntry = new FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.filesystem);
+            clonedFileEntry.file_ = fileEntry.file_;
+
+            return clonedFileEntry;
+        }
+
+        function readAs (what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) {
+            exports.getFile(function (fileEntry) {
+                var fileReader = new FileReader(); // eslint-disable-line no-undef
+                var blob = fileEntry.file_.blob_.slice(startPos, endPos);
+
+                fileReader.onload = function (e) {
+                    successCallback(e.target.result);
+                };
+
+                fileReader.onerror = errorCallback;
+
+                switch (what) {
+                case 'text':
+                    fileReader.readAsText(blob, encoding);
+                    break;
+                case 'dataURL':
+                    fileReader.readAsDataURL(blob);
+                    break;
+                case 'arrayBuffer':
+                    fileReader.readAsArrayBuffer(blob);
+                    break;
+                case 'binaryString':
+                    fileReader.readAsBinaryString(blob);
+                    break;
+                }
+
+            }, errorCallback, [fullPath, null]);
+        }
+
+    /** * Core logic to handle IDB operations ***/
+
+        idb_.open = function (dbName, successCallback, errorCallback) {
+            var self = this;
+
+            // TODO: FF 12.0a1 isn't liking a db name with : in it.
+            var request = indexedDB.open(dbName.replace(':', '_')/*, 1 /*version */);
+
+            request.onerror = errorCallback || onError;
+
+            request.onupgradeneeded = function (e) {
+                // First open was called or higher db version was used.
+
+                // console.log('onupgradeneeded: oldVersion:' + e.oldVersion,
+                //           'newVersion:' + e.newVersion);
+
+                self.db = e.target.result;
+                self.db.onerror = onError;
+
+                if (!self.db.objectStoreNames.contains(FILE_STORE_)) {
+                    self.db.createObjectStore(FILE_STORE_/*, {keyPath: 'id', autoIncrement: true} */);
+                }
+            };
+
+            request.onsuccess = function (e) {
+                self.db = e.target.result;
+                self.db.onerror = onError;
+                successCallback(e);
+            };
+
+            request.onblocked = errorCallback || onError;
+        };
+
+        idb_.close = function () {
+            this.db.close();
+            this.db = null;
+        };
+
+        idb_.get = function (fullPath, successCallback, errorCallback) {
+            if (!this.db) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            var tx = this.db.transaction([FILE_STORE_], 'readonly');
+
+            var request = tx.objectStore(FILE_STORE_).get(fullPath);
+
+            tx.onabort = errorCallback || onError;
+            tx.oncomplete = function () {
+                successCallback(request.result);
+            };
+        };
+
+        idb_.getAllEntries = function (fullPath, storagePath, successCallback, errorCallback) {
+            if (!this.db) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            var results = [];
+
+            if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) {
+                storagePath = storagePath.substring(0, storagePath.length - 1);
+            }
+
+            var range = IDBKeyRange.bound(storagePath + DIR_SEPARATOR + ' ',
+                storagePath + DIR_SEPARATOR + String.fromCharCode(unicodeLastChar));
+
+            var tx = this.db.transaction([FILE_STORE_], 'readonly');
+            tx.onabort = errorCallback || onError;
+            tx.oncomplete = function () {
+                results = results.filter(function (val) {
+                    var pathWithoutSlash = val.fullPath;
+
+                    if (val.fullPath[val.fullPath.length - 1] === DIR_SEPARATOR) {
+                        pathWithoutSlash = pathWithoutSlash.substr(0, pathWithoutSlash.length - 1);
+                    }
+
+                    var valPartsLen = pathWithoutSlash.split(DIR_SEPARATOR).length;
+                    var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
+
+                    /* Input fullPath parameter  equals '//' for root folder */
+                    /* Entries in root folder has valPartsLen equals 2 (see below) */
+                    if (fullPath[fullPath.length - 1] === DIR_SEPARATOR && fullPath.trim().length === 2) {
+                        fullPathPartsLen = 1;
+                    } else if (fullPath[fullPath.length - 1] === DIR_SEPARATOR) {
+                        fullPathPartsLen = fullPath.substr(0, fullPath.length - 1).split(DIR_SEPARATOR).length;
+                    } else {
+                        fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
+                    }
+
+                    if (valPartsLen === fullPathPartsLen + 1) {
+                        // If this a subfolder and entry is a direct child, include it in
+                        // the results. Otherwise, it's not an entry of this folder.
+                        return val;
+                    } else return false;
+                });
+
+                successCallback(results);
+            };
+
+            var request = tx.objectStore(FILE_STORE_).openCursor(range);
+
+            request.onsuccess = function (e) {
+                var cursor = e.target.result;
+                if (cursor) {
+                    var val = cursor.value;
+
+                    results.push(val.isFile ? fileEntryFromIdbEntry(val) : new DirectoryEntry(val.name, val.fullPath, val.filesystem));
+                    cursor['continue']();
+                }
+            };
+        };
+
+        idb_['delete'] = function (fullPath, successCallback, errorCallback, isDirectory) {
+            if (!idb_.db) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            var tx = this.db.transaction([FILE_STORE_], 'readwrite');
+            tx.oncomplete = successCallback;
+            tx.onabort = errorCallback || onError;
+            tx.oncomplete = function () {
+                if (isDirectory) {
+                    // We delete nested files and folders after deleting parent folder
+                    // We use ranges: https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange
+                    fullPath = fullPath + DIR_SEPARATOR;
+
+                    // Range contains all entries in the form fullPath<symbol> where
+                    // symbol in the range from ' ' to symbol which has code `unicodeLastChar`
+                    var range = IDBKeyRange.bound(fullPath + ' ', fullPath + String.fromCharCode(unicodeLastChar));
+
+                    var newTx = this.db.transaction([FILE_STORE_], 'readwrite');
+                    newTx.oncomplete = successCallback;
+                    newTx.onabort = errorCallback || onError;
+                    newTx.objectStore(FILE_STORE_)['delete'](range);
+                } else {
+                    successCallback();
+                }
+            };
+            tx.objectStore(FILE_STORE_)['delete'](fullPath);
+        };
+
+        idb_.put = function (entry, storagePath, successCallback, errorCallback) {
+            if (!this.db) {
+                if (errorCallback) {
+                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
+                }
+                return;
+            }
+
+            var tx = this.db.transaction([FILE_STORE_], 'readwrite');
+            tx.onabort = errorCallback || onError;
+            tx.oncomplete = function () {
+                // TODO: Error is thrown if we pass the request event back instead.
+                successCallback(entry);
+            };
+
+            tx.objectStore(FILE_STORE_).put(entry, storagePath);
+        };
+
+        // Global error handler. Errors bubble from request, to transaction, to db.
+        function onError (e) {
+            switch (e.target.errorCode) {
+            case 12:
+                console.log('Error - Attempt to open db with a lower version than the ' +
+                        'current one.');
+                break;
+            default:
+                console.log('errorCode: ' + e.target.errorCode);
+            }
+
+            console.log(e, e.code, e.message);
+        }
+
+    })(module.exports, window);
+
+    require('cordova/exec/proxy').add('File', module.exports);
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..7e1d3f7
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,119 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+    // add trailing slash if it is missing
+    if ((fullPath) && !/\/$/.test(fullPath)) {
+        fullPath += '/';
+    }
+    // add trailing slash if it is missing
+    if (nativeURL && !/\/$/.test(nativeURL)) {
+        nativeURL += '/';
+    }
+    DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+    return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var FileEntry = require('./FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..ce74ade
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,74 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+    this.localURL = localURL || null;
+    this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+    // If we've already read and passed on this directory's entries, return an empty list.
+    if (this.hasReadEntries) {
+        successCallback([]);
+        return;
+    }
+    var reader = this;
+    var win = typeof successCallback !== 'function' ? null : function (result) {
+        var retVal = [];
+        for (var i = 0; i < result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('./DirectoryEntry'))();
+            } else if (result[i].isFile) {
+                entry = new (require('./FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+            entry.nativeURL = result[i].nativeURL;
+            retVal.push(entry);
+        }
+        reader.hasReadEntries = true;
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..973cf14
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,262 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ * @param fileSystem
+ *            {FileSystem} the filesystem on which this entry resides
+ *            (readonly)
+ * @param nativeURL
+ *            {DOMString} an alternate URL which can be used by native
+ *            webview controls, for example media players.
+ *            (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+    this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function (entryMetadata) {
+        var metadata = new Metadata({
+            size: entryMetadata.size,
+            modificationTime: entryMetadata.lastModifiedDate
+        });
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+    // entry name
+    var name = newName || this.name;
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+        // entry name
+    var name = newName || this.name;
+    // success callback
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+    if (this.filesystem && this.filesystem.__format__) {
+        return this.filesystem.__format__(this.fullPath, this.nativeURL);
+    }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+    if (this.nativeURL) {
+        return this.nativeURL;
+    }
+    // fullPath attribute may contain the full URL in the case that
+    // toInternalURL fails.
+    return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var DirectoryEntry = require('./DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..974b09f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,80 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+    this.name = name || '';
+    this.localURL = localURL || null;
+    this.type = type || null;
+    this.lastModified = lastModifiedDate || null;
+    // For backwards compatibility, store the timestamp in lastModifiedDate as well
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..b16c851
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+    // remove trailing slash if it is present
+    if (fullPath && /\/$/.test(fullPath)) {
+        fullPath = fullPath.substring(0, fullPath.length - 1);
+    }
+    if (nativeURL && /\/$/.test(nativeURL)) {
+        nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+    }
+
+    FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+    this.file(function (filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.localURL === null || writer.localURL === '') {
+            if (errorCallback) {
+                errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+            }
+        } else {
+            if (successCallback) {
+                successCallback(writer);
+            }
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+    var localURL = this.toInternalURL();
+    var win = successCallback && function (f) {
+        var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..7a0a66e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,48 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+    this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..1227dd8
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,300 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._progress = null;
+    this._localURL = '';
+    this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+    return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+    return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+    return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+        return this._realReader[eventName] || null;
+    }, function (value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+    // Already loading something
+    if (reader.readyState === FileReader.LOADING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._progress = 0;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file.localURL === 'string') {
+        reader._localURL = file.localURL;
+    } else {
+        reader._localURL = '';
+        return true;
+    }
+
+    if (reader.onloadstart) {
+        reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+    if (readType === 'readAsDataURL') {
+        // Windows proxy does not support reading file slices as Data URLs
+        // so read the whole file at once.
+        CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+            // Calculate new chunk size for data URLs to be multiply of 3
+            // Otherwise concatenated base64 chunks won't be valid base64 data
+            FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+    }
+
+    if (typeof r !== 'undefined') {
+        accumulate(r);
+        this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+        if (typeof this.onprogress === 'function') {
+            this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+        }
+    }
+
+    if (typeof r === 'undefined' || this._progress < totalSize) {
+        var execArgs = [
+            this._localURL,
+            offset + this._progress,
+            offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+        if (encoding) {
+            execArgs.splice(1, 0, encoding);
+        }
+        exec(
+            readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+            readFailureCallback.bind(this),
+            'File', readType, execArgs);
+    } else {
+        this._readyState = FileReader.DONE;
+
+        if (typeof this.onload === 'function') {
+            this.onload(new ProgressEvent('load', {target: this}));
+        }
+
+        if (typeof this.onloadend === 'function') {
+            this.onloadend(new ProgressEvent('loadend', {target: this}));
+        }
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+    this._result = null;
+    this._error = new FileError(e);
+
+    if (typeof this.onerror === 'function') {
+        this.onerror(new ProgressEvent('error', {target: this}));
+    }
+
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+    if (origFileReader && !this._localURL) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target: this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding || 'UTF-8';
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+        var commaIndex = r.indexOf(',');
+        if (this._progress === 0) {
+            this._result = r;
+        } else {
+            this._result += r.substring(commaIndex + 1);
+        }
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+        var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+        resultArray.set(new Uint8Array(r), this._progress);
+        this._result = resultArray.buffer;
+    }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..f7e751e
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,57 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+    this.name = name;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+    } else {
+        this.root = new DirectoryEntry(this.name, '/', this);
+    }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+    return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+    return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+    // Because # is a valid filename character, it must be encoded to prevent part of the
+    // path from being parsed as a URI fragment.
+    return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..908091b
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String}   Name of file request parameter.
+ * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object}    Object with key: value params to send to the server.
+ * @param headers {Object}   Keys are header names, values are header values. Multiple
+ *                           headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+    this.fileKey = fileKey || null;
+    this.fileName = fileName || null;
+    this.mimeType = mimeType || null;
+    this.params = params || null;
+    this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..a94cb9a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+    this.bytesSent = size;
+    this.responseCode = code;
+    this.response = content;
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..1f978bb
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,326 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+    this.fileName = '';
+    this.length = 0;
+    if (file) {
+        this.localURL = file.localURL || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {'target': this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === 'function') {
+        this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+    var that = this;
+    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+    /* eslint-disable no-undef */
+    var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+    var isBinary;
+
+    // Check to see if the incoming data is a blob
+    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+        var fileReader = new FileReader();
+        /* eslint-enable no-undef */
+        fileReader.onload = function () {
+            // Call this method again, with the arraybuffer as argument
+            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+        };
+        fileReader.onerror = function () {
+            // DONE state
+            that.readyState = FileWriter.DONE;
+
+            // Save error
+            that.error = this.error;
+
+            // If onerror callback
+            if (typeof that.onerror === 'function') {
+                that.onerror(new ProgressEvent('error', {'target': that}));
+            }
+
+            // If onwriteend callback
+            if (typeof that.onwriteend === 'function') {
+                that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+            }
+        };
+
+        // WRITING state
+        this.readyState = FileWriter.WRITING;
+
+        if (supportsBinary) {
+            fileReader.readAsArrayBuffer(data);
+        } else {
+            fileReader.readAsText(data);
+        }
+        return;
+    }
+
+    // Mark data type for safer transport over the binary bridge
+    isBinary = supportsBinary && (data instanceof ArrayBuffer);
+    if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+        data = Array.apply(null, new Uint8Array(data));
+    }
+
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset && offset !== 0) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    // Offset is bigger than file size so set position
+    // to the end of the file.
+    } else if (offset > this.length) {
+        this.position = this.length;
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    } else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..f51db30
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,38 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags (create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..e424c10
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,25 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..5550f8a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,42 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+    if (typeof metadata === 'object') {
+        this.modificationTime = new Date(metadata.modificationTime);
+        this.size = metadata.size || 0;
+    } else if (typeof metadata === 'undefined') {
+        this.modificationTime = null;
+        this.size = 0;
+    } else {
+        /* Backwards compatiblity with platforms that only return a timestamp */
+        this.modificationTime = new Date(metadata);
+    }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..0315adf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,69 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+    return function ProgressEvent (type, dict) {
+        this.type = type;
+        this.bubbles = false;
+        this.cancelBubble = false;
+        this.cancelable = false;
+        this.lengthComputable = false;
+        this.loaded = dict && dict.loaded ? dict.loaded : 0;
+        this.total = dict && dict.total ? dict.total : 0;
+        this.target = dict && dict.target ? dict.target : null;
+    };
+    // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js
new file mode 100644
index 0000000..0f49c2c
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/FileSystem.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.firefoxFileSystem", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/* global FILESYSTEM_PREFIX: true, module */
+
+FILESYSTEM_PREFIX = 'file:///';
+
+module.exports = {
+    __format__: function (fullPath) {
+        return (FILESYSTEM_PREFIX + this.name + (fullPath[0] === '/' ? '' : '/') + FileSystem.encodeURIPath(fullPath)); // eslint-disable-line no-undef
+    }
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js
new file mode 100644
index 0000000..24ea404
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/Preparing.js
@@ -0,0 +1,194 @@
+cordova.define("cordova-plugin-file.Preparing", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    /* global require */
+
+    // Only Chrome uses this file.
+    if (!require('./isChrome')()) {
+        return;
+    }
+
+    var channel = require('cordova/channel');
+    var FileError = require('./FileError');
+    var PERSISTENT_FS_QUOTA = 5 * 1024 * 1024;
+    var filePluginIsReadyEvent = new Event('filePluginIsReady'); // eslint-disable-line no-undef
+
+    var entryFunctionsCreated = false;
+    var quotaWasRequested = false;
+    var eventWasThrown = false;
+
+    if (!window.requestFileSystem) {
+        window.requestFileSystem = function (type, size, win, fail) {
+            if (fail) {
+                fail('Not supported');
+            }
+        };
+    } else {
+        window.requestFileSystem(window.TEMPORARY, 1, createFileEntryFunctions, function () {});
+    }
+
+    if (!window.resolveLocalFileSystemURL) {
+        window.resolveLocalFileSystemURL = function (url, win, fail) {
+            if (fail) {
+                fail('Not supported');
+            }
+        };
+    }
+
+    // Resolves a filesystem entry by its path - which is passed either in standard (filesystem:file://) or
+    // Cordova-specific (cdvfile://) universal way.
+    // Aligns with specification: http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-LocalFileSystem-resolveLocalFileSystemURL
+    var nativeResolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+    window.resolveLocalFileSystemURL = function (url, win, fail) {
+        /* If url starts with `cdvfile` then we need convert it to Chrome real url first:
+          cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file */
+        if (url.trim().substr(0, 7) === 'cdvfile') {
+            /* Quirk:
+            Plugin supports cdvfile://localhost (local resources) only.
+            I.e. external resources are not supported via cdvfile. */
+            if (url.indexOf('cdvfile://localhost') !== -1) {
+                // Browser supports temporary and persistent only
+                var indexPersistent = url.indexOf('persistent');
+                var indexTemporary = url.indexOf('temporary');
+
+                /* Chrome urls start with 'filesystem:' prefix. See quirk:
+                   toURL function in Chrome returns filesystem:-prefixed path depending on application host.
+                   For example, filesystem:file:///persistent/somefile.txt,
+                   filesystem:http://localhost:8080/persistent/somefile.txt. */
+                var prefix = 'filesystem:file:///';
+                if (location.protocol !== 'file:') { // eslint-disable-line no-undef
+                    prefix = 'filesystem:' + location.origin + '/'; // eslint-disable-line no-undef
+                }
+
+                var result;
+                if (indexPersistent !== -1) {
+                    // cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file
+                    // or filesystem:http://localhost:8080/persistent/path/to/file
+                    result = prefix + 'persistent' + url.substr(indexPersistent + 10);
+                    nativeResolveLocalFileSystemURL(result, win, fail);
+                    return;
+                }
+
+                if (indexTemporary !== -1) {
+                    // cdvfile://localhost/temporary/path/to/file -> filesystem:file://temporary/path/to/file
+                    // or filesystem:http://localhost:8080/temporary/path/to/file
+                    result = prefix + 'temporary' + url.substr(indexTemporary + 9);
+                    nativeResolveLocalFileSystemURL(result, win, fail);
+                    return;
+                }
+            }
+
+            // cdvfile other than local file resource is not supported
+            if (fail) {
+                fail(new FileError(FileError.ENCODING_ERR));
+            }
+        } else {
+            nativeResolveLocalFileSystemURL(url, win, fail);
+        }
+    };
+
+    function createFileEntryFunctions (fs) {
+        fs.root.getFile('todelete_658674_833_4_cdv', {create: true}, function (fileEntry) {
+            var fileEntryType = Object.getPrototypeOf(fileEntry);
+            var entryType = Object.getPrototypeOf(fileEntryType);
+
+            // Save the original method
+            var origToURL = entryType.toURL;
+            entryType.toURL = function () {
+                var origURL = origToURL.call(this);
+                if (this.isDirectory && origURL.substr(-1) !== '/') {
+                    return origURL + '/';
+                }
+                return origURL;
+            };
+
+            entryType.toNativeURL = function () {
+                console.warn("DEPRECATED: Update your code to use 'toURL'");
+                return this.toURL();
+            };
+
+            entryType.toInternalURL = function () {
+                if (this.toURL().indexOf('persistent') > -1) {
+                    return 'cdvfile://localhost/persistent' + this.fullPath;
+                }
+
+                if (this.toURL().indexOf('temporary') > -1) {
+                    return 'cdvfile://localhost/temporary' + this.fullPath;
+                }
+            };
+
+            entryType.setMetadata = function (win, fail /*, metadata */) {
+                if (fail) {
+                    fail('Not supported');
+                }
+            };
+
+            fileEntry.createWriter(function (writer) {
+                var originalWrite = writer.write;
+                var writerProto = Object.getPrototypeOf(writer);
+                writerProto.write = function (blob) {
+                    if (blob instanceof Blob) { // eslint-disable-line no-undef
+                        originalWrite.apply(this, [blob]);
+                    } else {
+                        var realBlob = new Blob([blob]); // eslint-disable-line no-undef
+                        originalWrite.apply(this, [realBlob]);
+                    }
+                };
+
+                fileEntry.remove(function () { entryFunctionsCreated = true; }, function () { /* empty callback */ });
+            });
+        });
+    }
+
+    window.initPersistentFileSystem = function (size, win, fail) {
+        if (navigator.webkitPersistentStorage) {
+            navigator.webkitPersistentStorage.requestQuota(size, win, fail);
+            return;
+        }
+
+        fail('This browser does not support this function');
+    };
+
+    window.isFilePluginReadyRaised = function () { return eventWasThrown; };
+
+    window.initPersistentFileSystem(PERSISTENT_FS_QUOTA, function () {
+        console.log('Persistent fs quota granted');
+        quotaWasRequested = true;
+    }, function (e) {
+        console.log('Error occured while trying to request Persistent fs quota: ' + JSON.stringify(e));
+    });
+
+    channel.onCordovaReady.subscribe(function () {
+        function dispatchEventIfReady () {
+            if (entryFunctionsCreated && quotaWasRequested) {
+                window.dispatchEvent(filePluginIsReadyEvent);
+                eventWasThrown = true;
+            } else {
+                setTimeout(dispatchEventIfReady, 100);
+            }
+        }
+
+        dispatchEventIfReady();
+    }, false);
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..1421b21
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) { /*

+ *

+ * 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.

+ *

+ */

+

+module.exports = function () {

+    // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and

+    // possibly a good flag to indicate that we're running in Chrome

+    return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;

+};

+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..be7278f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,64 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+    documentsDirectory: null,
+    // BlackBerry10: Files globally available to all apps
+    sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+    function after (paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..99b38f6
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,27 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+    callback(null);
+};
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..e182354
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,83 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // For browser platform: not all browsers use this file.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var FileError = require('./FileError');
+    var FileSystem = require('./FileSystem');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Request a file system in which to store application data.
+     * @param type  local file system type
+     * @param size  indicates how much storage space, in bytes, the application expects to need
+     * @param successCallback  invoked with a FileSystem object
+     * @param errorCallback  invoked if error occurs retrieving file system
+     */
+    var requestFileSystem = function (type, size, successCallback, errorCallback) {
+        argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+        var fail = function (code) {
+            if (errorCallback) {
+                errorCallback(new FileError(code));
+            }
+        };
+
+        if (type < 0) {
+            fail(FileError.SYNTAX_ERR);
+        } else {
+            // if successful, return a FileSystem object
+            var success = function (file_system) {
+                if (file_system) {
+                    if (successCallback) {
+                        fileSystems.getFs(file_system.name, function (fs) {
+                            // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                            if (!fs) {
+                                fs = new FileSystem(file_system.name, file_system.root);
+                            }
+                            successCallback(fs);
+                        });
+                    }
+                } else {
+                    // no FileSystem object returned
+                    fail(FileError.NOT_FOUND_ERR);
+                }
+            };
+            exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+        }
+    };
+
+    module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..659d417
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,93 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+(function () {
+    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Look up file system Entry referred to by local URI.
+     * @param {DOMString} uri  URI referring to a local file or directory
+     * @param successCallback  invoked with Entry object corresponding to URI
+     * @param errorCallback    invoked if error occurs retrieving file system entry
+     */
+    module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+        argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+        // error callback
+        var fail = function (error) {
+            if (errorCallback) {
+                errorCallback(new FileError(error));
+            }
+        };
+        // sanity check for 'not:valid:filename' or '/not:valid:filename'
+        // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+        if (!uri || uri.split(':').length > 2) {
+            setTimeout(function () {
+                fail(FileError.ENCODING_ERR);
+            }, 0);
+            return;
+        }
+        // if successful, return either a file or directory entry
+        var success = function (entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+                    fileSystems.getFs(fsName, function (fs) {
+                        // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                        if (!fs) {
+                            fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+                        }
+                        var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+                        successCallback(result);
+                    });
+                }
+            } else {
+                // no Entry object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+        exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+    };
+
+    module.exports.resolveLocalFileSystemURI = function () {
+        console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+        module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+    };
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..6c8203d
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) { /*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "authenticate",
+    [params]
+  );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "isAvailable",
+    [{}]
+  );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js
new file mode 100644
index 0000000..86e120f
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/src/browser/InAppBrowserProxy.js
@@ -0,0 +1,249 @@
+cordova.define("cordova-plugin-inappbrowser.InAppBrowserProxy", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+var modulemapper = require('cordova/modulemapper');
+
+var browserWrap,
+    popup,
+    navigationButtonsDiv,
+    navigationButtonsDivInner,
+    backButton,
+    forwardButton,
+    closeButton;
+
+function attachNavigationEvents (element, callback) {
+    var onError = function () {
+        try {
+            callback({ type: 'loaderror', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        } catch (err) {
+            // blocked by CORS :\
+            callback({ type: 'loaderror', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        }
+    };
+
+    element.addEventListener('pageshow', function () {
+        try {
+            callback({ type: 'loadstart', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        } catch (err) {
+            // blocked by CORS :\
+            callback({ type: 'loadstart', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        }
+    });
+
+    element.addEventListener('load', function () {
+        try {
+            callback({ type: 'loadstop', url: this.contentWindow.location.href }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        } catch (err) {
+            // blocked by CORS :\
+            callback({ type: 'loadstop', url: null }, {keepCallback: true}); // eslint-disable-line standard/no-callback-literal
+        }
+    });
+
+    element.addEventListener('error', onError);
+    element.addEventListener('abort', onError);
+}
+
+var IAB = {
+    close: function (win, lose) {
+        if (browserWrap) {
+            // use the "open" function callback so that the exit event is fired properly
+            if (IAB._win) IAB._win({ type: 'exit' });
+
+            browserWrap.parentNode.removeChild(browserWrap);
+            browserWrap = null;
+            popup = null;
+        }
+    },
+
+    show: function (win, lose) {
+        if (browserWrap) {
+            browserWrap.style.display = 'block';
+        }
+    },
+
+    open: function (win, lose, args) {
+        var strUrl = args[0];
+        var target = args[1];
+        var features = args[2];
+
+        IAB._win = win;
+
+        if (target === '_self' || !target) {
+            window.location = strUrl;
+        } else if (target === '_system') {
+            modulemapper.getOriginalSymbol(window, 'window.open').call(window, strUrl, '_blank');
+        } else {
+            // "_blank" or anything else
+            if (!browserWrap) {
+                browserWrap = document.createElement('div');
+                browserWrap.style.position = 'absolute';
+                browserWrap.style.top = '0';
+                browserWrap.style.left = '0';
+                browserWrap.style.boxSizing = 'border-box';
+                browserWrap.style.borderWidth = '40px';
+                browserWrap.style.width = '100vw';
+                browserWrap.style.height = '100vh';
+                browserWrap.style.borderStyle = 'solid';
+                browserWrap.style.borderColor = 'rgba(0,0,0,0.25)';
+
+                browserWrap.onclick = function () {
+                    setTimeout(function () {
+                        IAB.close();
+                    }, 0);
+                };
+
+                document.body.appendChild(browserWrap);
+            }
+
+            if (features.indexOf('hidden=yes') !== -1) {
+                browserWrap.style.display = 'none';
+            }
+
+            popup = document.createElement('iframe');
+            popup.style.borderWidth = '0px';
+            popup.style.width = '100%';
+
+            browserWrap.appendChild(popup);
+
+            if (features.indexOf('location=yes') !== -1 || features.indexOf('location') === -1) {
+                popup.style.height = 'calc(100% - 60px)';
+                popup.style.marginBottom = '-4px';
+
+                navigationButtonsDiv = document.createElement('div');
+                navigationButtonsDiv.style.height = '60px';
+                navigationButtonsDiv.style.backgroundColor = '#404040';
+                navigationButtonsDiv.style.zIndex = '999';
+                navigationButtonsDiv.onclick = function (e) {
+                    e.cancelBubble = true;
+                };
+
+                navigationButtonsDivInner = document.createElement('div');
+                navigationButtonsDivInner.style.paddingTop = '10px';
+                navigationButtonsDivInner.style.height = '50px';
+                navigationButtonsDivInner.style.width = '160px';
+                navigationButtonsDivInner.style.margin = '0 auto';
+                navigationButtonsDivInner.style.backgroundColor = '#404040';
+                navigationButtonsDivInner.style.zIndex = '999';
+                navigationButtonsDivInner.onclick = function (e) {
+                    e.cancelBubble = true;
+                };
+
+                backButton = document.createElement('button');
+                backButton.style.width = '40px';
+                backButton.style.height = '40px';
+                backButton.style.borderRadius = '40px';
+
+                backButton.innerHTML = '←';
+                backButton.addEventListener('click', function (e) {
+                    if (popup.canGoBack) { popup.goBack(); }
+                });
+
+                forwardButton = document.createElement('button');
+                forwardButton.style.marginLeft = '20px';
+                forwardButton.style.width = '40px';
+                forwardButton.style.height = '40px';
+                forwardButton.style.borderRadius = '40px';
+
+                forwardButton.innerHTML = '→';
+                forwardButton.addEventListener('click', function (e) {
+                    if (popup.canGoForward) { popup.goForward(); }
+                });
+
+                closeButton = document.createElement('button');
+                closeButton.style.marginLeft = '20px';
+                closeButton.style.width = '40px';
+                closeButton.style.height = '40px';
+                closeButton.style.borderRadius = '40px';
+
+                closeButton.innerHTML = '✖';
+                closeButton.addEventListener('click', function (e) {
+                    setTimeout(function () {
+                        IAB.close();
+                    }, 0);
+                });
+
+                // iframe navigation is not yet supported
+                backButton.disabled = true;
+                forwardButton.disabled = true;
+
+                navigationButtonsDivInner.appendChild(backButton);
+                navigationButtonsDivInner.appendChild(forwardButton);
+                navigationButtonsDivInner.appendChild(closeButton);
+                navigationButtonsDiv.appendChild(navigationButtonsDivInner);
+
+                browserWrap.appendChild(navigationButtonsDiv);
+            } else {
+                popup.style.height = '100%';
+            }
+
+            // start listening for navigation events
+            attachNavigationEvents(popup, win);
+
+            popup.src = strUrl;
+        }
+    },
+
+    injectScriptCode: function (win, fail, args) {
+        var code = args[0];
+        var hasCallback = args[1];
+
+        if (browserWrap && popup) {
+            try {
+                popup.contentWindow.eval(code);
+                if (hasCallback) {
+                    win([]);
+                }
+            } catch (e) {
+                console.error('Error occured while trying to injectScriptCode: ' + JSON.stringify(e));
+            }
+        }
+    },
+
+    injectScriptFile: function (win, fail, args) {
+        var msg = 'Browser cordova-plugin-inappbrowser injectScriptFile is not yet implemented';
+        console.warn(msg);
+        if (fail) {
+            fail(msg);
+        }
+    },
+
+    injectStyleCode: function (win, fail, args) {
+        var msg = 'Browser cordova-plugin-inappbrowser injectStyleCode is not yet implemented';
+        console.warn(msg);
+        if (fail) {
+            fail(msg);
+        }
+    },
+
+    injectStyleFile: function (win, fail, args) {
+        var msg = 'Browser cordova-plugin-inappbrowser injectStyleFile is not yet implemented';
+        console.warn(msg);
+        if (fail) {
+            fail(msg);
+        }
+    }
+};
+
+module.exports = IAB;
+
+require('cordova/exec/proxy').add('InAppBrowser', module.exports);
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..759dacf
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,117 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // special patch to correctly work on Ripple emulator (CB-9760)
+    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+        module.exports = window.open.bind(window); // fallback to default window.open behaviour
+        return;
+    }
+
+    var exec = require('cordova/exec');
+    var channel = require('cordova/channel');
+    var modulemapper = require('cordova/modulemapper');
+    var urlutil = require('cordova/urlutil');
+
+    function InAppBrowser () {
+        this.channels = {
+            'loadstart': channel.create('loadstart'),
+            'loadstop': channel.create('loadstop'),
+            'loaderror': channel.create('loaderror'),
+            'exit': channel.create('exit'),
+            'customscheme': channel.create('customscheme')
+        };
+    }
+
+    InAppBrowser.prototype = {
+        _eventHandler: function (event) {
+            if (event && (event.type in this.channels)) {
+                this.channels[event.type].fire(event);
+            }
+        },
+        close: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'close', []);
+        },
+        show: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'show', []);
+        },
+        hide: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'hide', []);
+        },
+        addEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].subscribe(f);
+            }
+        },
+        removeEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].unsubscribe(f);
+            }
+        },
+
+        executeScript: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('executeScript requires exactly one of code or file to be specified');
+            }
+        },
+
+        insertCSS: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('insertCSS requires exactly one of code or file to be specified');
+            }
+        }
+    };
+
+    module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+        // Don't catch calls that write to existing frames (e.g. named iframes).
+        if (window.frames && window.frames[strWindowName]) {
+            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+            return origOpenFunc.apply(window, arguments);
+        }
+
+        strUrl = urlutil.makeAbsolute(strUrl);
+        var iab = new InAppBrowser();
+
+        callbacks = callbacks || {};
+        for (var callbackName in callbacks) {
+            iab.addEventListener(callbackName, callbacks[callbackName]);
+        }
+
+        var cb = function (eventname) {
+            iab._eventHandler(eventname);
+        };
+
+        strWindowFeatures = strWindowFeatures || '';
+
+        exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+        return iab;
+    };
+})();
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js
new file mode 100644
index 0000000..44888a7
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/src/browser/plugin.min.js
@@ -0,0 +1,4243 @@
+cordova.define("cordova-plugin-qrscanner.QRScannerProxy", function(require, exports, module) { // This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 17);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+var logDisabled_ = true;
+
+// Utility methods.
+var utils = {
+  disableLog: function(bool) {
+    if (typeof bool !== 'boolean') {
+      return new Error('Argument type: ' + typeof bool +
+          '. Please use a boolean.');
+    }
+    logDisabled_ = bool;
+    return (bool) ? 'adapter.js logging disabled' :
+        'adapter.js logging enabled';
+  },
+
+  log: function() {
+    if (typeof window === 'object') {
+      if (logDisabled_) {
+        return;
+      }
+      if (typeof console !== 'undefined' && typeof console.log === 'function') {
+        console.log.apply(console, arguments);
+      }
+    }
+  },
+
+  /**
+   * Extract browser version out of the provided user agent string.
+   *
+   * @param {!string} uastring userAgent string.
+   * @param {!string} expr Regular expression used as match criteria.
+   * @param {!number} pos position in the version string to be returned.
+   * @return {!number} browser version.
+   */
+  extractVersion: function(uastring, expr, pos) {
+    var match = uastring.match(expr);
+    return match && match.length >= pos && parseInt(match[pos], 10);
+  },
+
+  /**
+   * Browser detector.
+   *
+   * @return {object} result containing browser and version
+   *     properties.
+   */
+  detectBrowser: function() {
+    // Returned result object.
+    var result = {};
+    result.browser = null;
+    result.version = null;
+
+    // Fail early if it's not a browser
+    if (typeof window === 'undefined' || !window.navigator) {
+      result.browser = 'Not a browser.';
+      return result;
+    }
+
+    // Firefox.
+    if (navigator.mozGetUserMedia) {
+      result.browser = 'firefox';
+      result.version = this.extractVersion(navigator.userAgent,
+          /Firefox\/(\d+)\./, 1);
+    } else if (navigator.webkitGetUserMedia) {
+      // Chrome, Chromium, Webview, Opera, all use the chrome shim for now
+      if (window.webkitRTCPeerConnection) {
+        result.browser = 'chrome';
+        result.version = this.extractVersion(navigator.userAgent,
+          /Chrom(e|ium)\/(\d+)\./, 2);
+      } else { // Safari (in an unpublished version) or unknown webkit-based.
+        if (navigator.userAgent.match(/Version\/(\d+).(\d+)/)) {
+          result.browser = 'safari';
+          result.version = this.extractVersion(navigator.userAgent,
+            /AppleWebKit\/(\d+)\./, 1);
+        } else { // unknown webkit-based browser.
+          result.browser = 'Unsupported webkit-based browser ' +
+              'with GUM support but no WebRTC support.';
+          return result;
+        }
+      }
+    } else if (navigator.mediaDevices &&
+        navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
+      result.browser = 'edge';
+      result.version = this.extractVersion(navigator.userAgent,
+          /Edge\/(\d+).(\d+)$/, 2);
+    } else if (navigator.mediaDevices &&
+        navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
+        // Safari, with webkitGetUserMedia removed.
+      result.browser = 'safari';
+      result.version = this.extractVersion(navigator.userAgent,
+          /AppleWebKit\/(\d+)\./, 1);
+    } else { // Default fallthrough: not supported.
+      result.browser = 'Not a supported browser.';
+      return result;
+    }
+
+    return result;
+  },
+
+  // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
+
+  shimCreateObjectURL: function() {
+    if (!(typeof window === 'object' && window.HTMLMediaElement &&
+          'srcObject' in window.HTMLMediaElement.prototype)) {
+      // Only shim CreateObjectURL using srcObject if srcObject exists.
+      return undefined;
+    }
+
+    var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
+    var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
+    var streams = new Map(), newId = 0;
+
+    URL.createObjectURL = function(stream) {
+      if ('getTracks' in stream) {
+        var url = 'polyblob:' + (++newId);
+        streams.set(url, stream);
+        console.log('URL.createObjectURL(stream) is deprecated! ' +
+                    'Use elem.srcObject = stream instead!');
+        return url;
+      }
+      return nativeCreateObjectURL(stream);
+    };
+    URL.revokeObjectURL = function(url) {
+      nativeRevokeObjectURL(url);
+      streams.delete(url);
+    };
+
+    var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
+                                              'src');
+    Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
+      get: function() {
+        return dsc.get.apply(this);
+      },
+      set: function(url) {
+        this.srcObject = streams.get(url) || null;
+        return dsc.set.apply(this, [url]);
+      }
+    });
+
+    var nativeSetAttribute = HTMLMediaElement.prototype.setAttribute;
+    HTMLMediaElement.prototype.setAttribute = function() {
+      if (arguments.length === 2 &&
+          ('' + arguments[0]).toLowerCase() === 'src') {
+        this.srcObject = streams.get(arguments[1]) || null;
+      }
+      return nativeSetAttribute.apply(this, arguments);
+    };
+  }
+};
+
+// Export.
+module.exports = {
+  log: utils.log,
+  disableLog: utils.disableLog,
+  browserDetails: utils.detectBrowser(),
+  extractVersion: utils.extractVersion,
+  shimCreateObjectURL: utils.shimCreateObjectURL,
+  detectBrowser: utils.detectBrowser.bind(utils)
+};
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+__webpack_require__(8);
+var workerScript = __webpack_require__(6);
+
+module.exports = function(){
+
+  var ELEMENTS = {
+    preview: 'cordova-plugin-qrscanner-video-preview',
+    still: 'cordova-plugin-qrscanner-still'
+  };
+  var ZINDEXES = {
+    preview: -100,
+    still: -99
+  };
+  var backCamera = null;
+  var frontCamera = null;
+  var currentCamera = 0;
+  var activeMediaStream = null;
+  var scanning = false;
+  var previewing = false;
+  var scanWorker = null;
+  var thisScanCycle = null;
+  var nextScan = null;
+  var cancelNextScan = null;
+
+  // standard screen widths/heights, from 4k down to 320x240
+  // widths and heights are each tested separately to account for screen rotation
+  var standardWidthsAndHeights = [
+    5120, 4096, 3840, 3440, 3200, 3072, 3000, 2880, 2800, 2736, 2732, 2560,
+    2538, 2400, 2304, 2160, 2100, 2048, 2000, 1920, 1856, 1824, 1800, 1792,
+    1776, 1728, 1700, 1680, 1600, 1536, 1440, 1400, 1392, 1366, 1344, 1334,
+    1280, 1200, 1152, 1136, 1120, 1080, 1050, 1024, 1000, 960, 900, 854, 848,
+    832, 800, 768, 750, 720, 640, 624, 600, 576, 544, 540, 512, 480, 320, 240
+  ];
+
+  var facingModes = [
+    'environment',
+    'user'
+  ];
+
+  //utils
+  function killStream(mediaStream){
+    mediaStream.getTracks().forEach(function(track){
+      track.stop();
+    });
+  }
+
+  // For performance, we test best-to-worst constraints. Once we find a match,
+  // we move to the next test. Since `ConstraintNotSatisfiedError`s are thrown
+  // much faster than streams can be started and stopped, the scan is much
+  // faster, even though it may iterate through more constraint objects.
+  function getCameraSpecsById(deviceId){
+
+    // return a getUserMedia Constraints
+    function getConstraintObj(deviceId, facingMode, width, height){
+      var obj = { audio: false, video: {} };
+      obj.video.deviceId = {exact: deviceId};
+      if(facingMode) {
+        obj.video.facingMode = {exact: facingMode};
+      }
+      if(width) {
+        obj.video.width = {exact: width};
+      }
+      if(height) {
+        obj.video.height = {exact: height};
+      }
+      return obj;
+    }
+
+    var facingModeConstraints = facingModes.map(function(mode){
+    	return getConstraintObj(deviceId, mode);
+    });
+    var widthConstraints = standardWidthsAndHeights.map(function(width){
+    	return getConstraintObj(deviceId, null, width);
+    });
+    var heightConstraints = standardWidthsAndHeights.map(function(height){
+    	return getConstraintObj(deviceId, null, null, height);
+    });
+
+    // create a promise which tries to resolve the best constraints for this deviceId
+    // rather than reject, failures return a value of `null`
+    function getFirstResolvingConstraint(constraintsBestToWorst){
+      return new Promise(function(resolveBestConstraints){
+        // build a chain of promises which either resolves or continues searching
+        return constraintsBestToWorst.reduce(function(chain, next){
+          return chain.then(function(searchState){
+            if(searchState.found){
+              // The best working constraint was found. Skip further tests.
+              return searchState;
+            } else {
+              searchState.nextConstraint = next;
+              return window.navigator.mediaDevices.getUserMedia(searchState.nextConstraint).then(function(mediaStream){
+                // We found the first working constraint object, now we can stop
+                // the stream and short-circuit the search.
+                killStream(mediaStream);
+                searchState.found = true;
+                return searchState;
+              }, function(){
+                // didn't get a media stream. The search continues:
+                return searchState;
+              });
+            }
+          });
+        }, Promise.resolve({
+          // kick off the search:
+          found: false,
+          nextConstraint: {}
+        })).then(function(searchState){
+          if(searchState.found){
+            resolveBestConstraints(searchState.nextConstraint);
+          } else {
+            resolveBestConstraints(null);
+          }
+        });
+      });
+    }
+
+    return getFirstResolvingConstraint(facingModeConstraints).then(function(facingModeSpecs){
+      return getFirstResolvingConstraint(widthConstraints).then(function(widthSpecs){
+        return getFirstResolvingConstraint(heightConstraints).then(function(heightSpecs){
+          return {
+            deviceId: deviceId,
+            facingMode: facingModeSpecs === null ? null : facingModeSpecs.video.facingMode.exact,
+            width: widthSpecs === null ? null : widthSpecs.video.width.exact,
+            height: heightSpecs === null ? null : heightSpecs.video.height.exact
+          };
+        });
+      });
+    });
+  }
+
+  function chooseCameras(){
+    var devices = window.navigator.mediaDevices.enumerateDevices();
+    return devices.then(function(mediaDeviceInfoList){
+      var videoDeviceIds = mediaDeviceInfoList.filter(function(elem){
+        return elem.kind === 'videoinput';
+      }).map(function(elem){
+        return elem.deviceId;
+      });
+      return videoDeviceIds;
+    }).then(function(videoDeviceIds){
+      // there is no standardized way for us to get the specs of each camera
+      // (due to concerns over user fingerprinting), so we're forced to
+      // iteratively test each camera for it's capabilities
+      var searches = [];
+      videoDeviceIds.forEach(function(id){
+        searches.push(getCameraSpecsById(id));
+      });
+      return Promise.all(searches);
+    }).then(function(cameraSpecsArray){
+      return cameraSpecsArray.filter(function(camera){
+        // filter out any cameras where width and height could not be captured
+        if(camera !== null && camera.width !== null && camera.height !== null){
+          return true;
+        }
+      }).sort(function(a, b){
+        // sort cameras from highest resolution (by width) to lowest
+        return b.width - a.width;
+      });
+    }).then(function(bestToWorstCameras){
+      var backCamera = null,
+          frontCamera = null;
+      // choose backCamera
+      for(var i = 0; i < bestToWorstCameras.length; i++){
+        if (bestToWorstCameras[i].facingMode === 'environment'){
+          backCamera = bestToWorstCameras[i];
+          // (shouldn't be used for frontCamera)
+          bestToWorstCameras.splice(i, 1);
+          break;
+        }
+      }
+      // if no back-facing cameras were found, choose the highest resolution
+      if(backCamera === null){
+        if(bestToWorstCameras.length > 0){
+          backCamera = bestToWorstCameras[0];
+          // (shouldn't be used for frontCamera)
+          bestToWorstCameras.splice(0, 1);
+        } else {
+          // user doesn't have any available cameras
+          backCamera = false;
+        }
+      }
+      if(bestToWorstCameras.length > 0){
+        // frontCamera should simply be the next-best resolution camera
+        frontCamera = bestToWorstCameras[0];
+      } else {
+        // user doesn't have any more cameras
+        frontCamera = false;
+      }
+      return {
+        backCamera: backCamera,
+        frontCamera: frontCamera
+      };
+    });
+  }
+
+  function mediaStreamIsActive(){
+    return activeMediaStream !== null;
+  }
+
+  function killActiveMediaStream(){
+    killStream(activeMediaStream);
+    activeMediaStream = null;
+  }
+
+  function getVideoPreview(){
+    return document.getElementById(ELEMENTS.preview);
+  }
+
+  function getImg(){
+    return document.getElementById(ELEMENTS.still);
+  }
+
+  function getCurrentCameraIndex(){
+    return currentCamera;
+  }
+
+  function getCurrentCamera(){
+    return currentCamera === 1 ? frontCamera : backCamera;
+  }
+
+  function bringStillToFront(){
+    var img = getImg();
+    if(img){
+      img.style.visibility = 'visible';
+      previewing = false;
+    }
+  }
+
+  function bringPreviewToFront(){
+    var img = getImg();
+    if(img){
+      img.style.visibility = 'hidden';
+      previewing = true;
+    }
+  }
+
+  function isInitialized(){
+    return backCamera !== null;
+  }
+
+  function canChangeCamera(){
+    return !!backCamera && !!frontCamera;
+  }
+
+  function calcStatus(){
+    return {
+      // !authorized means the user either has no camera or has denied access.
+      // This would leave a value of `null` before prepare(), and `false` after.
+      authorized: (backCamera !== null && backCamera !== false)? '1': '0',
+      // No applicable API
+      denied: '0',
+      // No applicable API
+      restricted: '0',
+      prepared: isInitialized() ? '1' : '0',
+      scanning: scanning? '1' : '0',
+      previewing: previewing? '1' : '0',
+      // We leave this true after prepare() to match the mobile experience as
+      // closely as possible. (Without additional covering, the preview will
+      // always be visible to the user).
+      showing: getVideoPreview()? '1' : '0',
+      // No applicable API
+      lightEnabled: '0',
+      // No applicable API
+      canOpenSettings: '0',
+      // No applicable API
+      canEnableLight: '0',
+      canChangeCamera: canChangeCamera() ? '1' : '0',
+      currentCamera: currentCamera.toString()
+    };
+  }
+
+  function startCamera(success, error){
+      var currentCameraIndex = getCurrentCameraIndex();
+      var currentCamera = getCurrentCamera();
+      window.navigator.mediaDevices.getUserMedia({
+        audio: false,
+        video: {
+          deviceId: {exact: currentCamera.deviceId},
+          width: {ideal: currentCamera.width},
+          height: {ideal: currentCamera.height}
+        }
+      }).then(function(mediaStream){
+        activeMediaStream = mediaStream;
+        var video = getVideoPreview();
+        video.src = URL.createObjectURL(mediaStream);
+        success(calcStatus());
+      }, function(err){
+        // something bad happened
+        err = null;
+        var code = currentCameraIndex? 4 : 3;
+        error(code); // FRONT_CAMERA_UNAVAILABLE : BACK_CAMERA_UNAVAILABLE
+      });
+  }
+
+  function getTempCanvasAndContext(videoElement){
+    var tempCanvas = document.createElement('canvas');
+    var camera = getCurrentCamera();
+    tempCanvas.height = camera.height;
+    tempCanvas.width = camera.width;
+    var tempCanvasContext = tempCanvas.getContext('2d');
+    tempCanvasContext.drawImage(videoElement, 0, 0, camera.width, camera.height);
+    return {
+      canvas: tempCanvas,
+      context: tempCanvasContext
+    };
+  }
+
+  function getCurrentImageData(videoElement){
+    var snapshot = getTempCanvasAndContext(videoElement);
+    return snapshot.context.getImageData(0, 0, snapshot.canvas.width, snapshot.canvas.height);
+  }
+
+  // take a screenshot of the video preview with a temp canvas
+  function captureCurrentFrame(videoElement){
+    return getTempCanvasAndContext(videoElement).canvas.toDataURL('image/png');
+  }
+
+  function initialize(success, error){
+    if(scanWorker === null){
+      var workerBlob = new Blob([workerScript],{type: "text/javascript"});
+      scanWorker = new Worker(URL.createObjectURL(workerBlob));
+    }
+    if(!getVideoPreview()){
+      // prepare DOM (sync)
+      var videoPreview = document.createElement('video');
+      videoPreview.setAttribute('autoplay', 'autoplay');
+      videoPreview.setAttribute('id', ELEMENTS.preview);
+      videoPreview.setAttribute('style', 'display:block;position:fixed;top:50%;left:50%;' +
+      'width:auto;height:auto;min-width:100%;min-height:100%;z-index:' + ZINDEXES.preview +
+      ';-moz-transform: translateX(-50%) translateY(-50%);-webkit-transform: ' +
+      'translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);' +
+      'background-size:cover;background-position:50% 50%;background-color:#FFF;');
+      videoPreview.addEventListener('loadeddata', function(){
+        bringPreviewToFront();
+      });
+
+      var stillImg = document.createElement('div');
+      stillImg.setAttribute('id', ELEMENTS.still);
+      stillImg.setAttribute('style', 'display:block;position:fixed;top:50%;left:50%;visibility: hidden;' +
+      'width:auto;height:auto;min-width:100%;min-height:100%;z-index:' + ZINDEXES.still +
+      ';-moz-transform: translateX(-50%) translateY(-50%);-webkit-transform: ' +
+      'translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);' +
+      'background-size:cover;background-position:50% 50%;background-color:#FFF;');
+
+      document.body.appendChild(videoPreview);
+      document.body.appendChild(stillImg);
+    }
+    if(backCamera === null){
+      // set instance cameras
+      chooseCameras().then(function(cameras){
+        backCamera = cameras.backCamera;
+        frontCamera = cameras.frontCamera;
+        if(backCamera !== false){
+          success();
+        } else {
+          error(5); // CAMERA_UNAVAILABLE
+        }
+      }, function(err){
+        // something bad happened
+        err = null;
+        error(0); // UNEXPECTED_ERROR
+      });
+    } else if (backCamera === false){
+      error(5); // CAMERA_UNAVAILABLE
+    } else {
+      success();
+    }
+  }
+
+  /*
+   *  --- Begin Public API ---
+   */
+
+  function prepare(success, error){
+    initialize(function(){
+      // return status on success
+      success(calcStatus());
+    },
+    // pass errors through
+    error);
+  }
+
+  function show(success, error){
+    function showCamera(){
+      if(!mediaStreamIsActive()){
+        startCamera(success, error);
+      } else {
+        success(calcStatus());
+      }
+    }
+    if(!isInitialized()){
+      initialize(function(){
+        // on successful initialization, attempt to showCamera
+        showCamera();
+      },
+      // pass errors through
+      error);
+    } else {
+      showCamera();
+    }
+  }
+
+  function hide(success, error){
+    error = null; // should never error
+    if(mediaStreamIsActive()){
+      killActiveMediaStream();
+    }
+    var video = getVideoPreview();
+    if(video){
+      video.src = '';
+    }
+    success(calcStatus());
+  }
+
+  function scan(success, error) {
+    // initialize and start video preview if not already active
+    show(function(ignore){
+      // ignore success output – `scan` method callback should be passed the decoded data
+      ignore = null;
+      var video = getVideoPreview();
+      var returned = false;
+      scanning = true;
+      scanWorker.onmessage = function(event){
+        var obj = event.data;
+        if(obj.result && !returned){
+          returned = true;
+          thisScanCycle = null;
+          success(obj.result);
+        }
+      };
+      thisScanCycle = function(){
+        scanWorker.postMessage(getCurrentImageData(video));
+        if(cancelNextScan !== null){
+          // avoid race conditions, always clear before starting a cycle
+          cancelNextScan();
+        }
+        // interval in milliseconds at which to try decoding the QR code
+        var SCAN_INTERVAL = window.QRScanner_SCAN_INTERVAL || 130;
+        // this value can be adjusted on-the-fly (while a scan is active) to
+        // balance scan speed vs. CPU/power usage
+        nextScan = window.setTimeout(thisScanCycle, SCAN_INTERVAL);
+        cancelNextScan = function(sendError){
+          window.clearTimeout(nextScan);
+          nextScan = null;
+          cancelNextScan = null;
+          if(sendError){
+            error(6); // SCAN_CANCELED
+          }
+        };
+      };
+      thisScanCycle();
+    }, error);
+  }
+
+  function cancelScan(success, error){
+    error = null; // should never error
+    if(cancelNextScan !== null){
+      cancelNextScan(true);
+    }
+    scanning = false;
+    if(typeof success === "function"){
+      success(calcStatus());
+    }
+  }
+
+  function pausePreview(success, error){
+    error = null; // should never error
+    if(mediaStreamIsActive()){
+      // pause scanning too
+      if(cancelNextScan !== null){
+        cancelNextScan();
+      }
+      var video = getVideoPreview();
+      video.pause();
+      var img = new Image();
+      img.src = captureCurrentFrame(video);
+      getImg().style.backgroundImage = 'url(' + img.src + ')';
+      bringStillToFront();
+      // kill the active stream to turn off the privacy light (the screenshot
+      // in the stillImg will remain visible)
+      killActiveMediaStream();
+      success(calcStatus());
+    } else {
+      success(calcStatus());
+    }
+  }
+
+  function resumePreview(success, error){
+    // if a scan was happening, resume it
+    if(thisScanCycle !== null){
+      thisScanCycle();
+    }
+    show(success, error);
+  }
+
+  function enableLight(success, error){
+    error(7); //LIGHT_UNAVAILABLE
+  }
+
+  function disableLight(success, error){
+    error(7); //LIGHT_UNAVAILABLE
+  }
+
+  function useCamera(success, error, array){
+    var requestedCamera = array[0];
+    var initialized = isInitialized();
+    if(requestedCamera !== currentCamera){
+      if(initialized && requestedCamera === 1 && !canChangeCamera()){
+          error(4); //FRONT_CAMERA_UNAVAILABLE
+      } else {
+        currentCamera = requestedCamera;
+        if(initialized){
+          hide(function(status){
+            // Don't need this one
+            status = null;
+          });
+          show(success, error);
+        } else {
+          success(calcStatus());
+        }
+      }
+    } else {
+      success(calcStatus());
+    }
+  }
+
+  function openSettings(success, error){
+    error(8); //OPEN_SETTINGS_UNAVAILABLE
+  }
+
+  function getStatus(success, error){
+    error = null; // should never error
+    success(calcStatus());
+  }
+
+  // Reset all instance variables to their original state.
+  // This method might be useful in cases where a new camera is available, and
+  // the application needs to force the plugin to chooseCameras() again.
+  function destroy(success, error){
+    error = null; // should never error
+    cancelScan();
+    if(mediaStreamIsActive()){
+      killActiveMediaStream();
+    }
+    backCamera = null;
+    frontCamera = null;
+    var preview = getVideoPreview();
+    var still = getImg();
+    if(preview){
+      preview.remove();
+    }
+    if(still){
+      still.remove();
+    }
+    success(calcStatus());
+  }
+
+  return {
+      prepare: prepare,
+      show: show,
+      hide: hide,
+      scan: scan,
+      cancelScan: cancelScan,
+      pausePreview: pausePreview,
+      resumePreview: resumePreview,
+      enableLight: enableLight,
+      disableLight: disableLight,
+      useCamera: useCamera,
+      openSettings: openSettings,
+      getStatus: getStatus,
+      destroy: destroy
+  };
+};
+
+
+/***/ }),
+/* 3 */,
+/* 4 */,
+/* 5 */
+/***/ (function(module, exports) {
+
+module.exports = cordovaRequire;
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports) {
+
+module.exports = "!function(t){function e(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,\"a\",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p=\"\",e(e.s=19)}([function(t,e,n){\"use strict\";function i(){this.imagedata=null,this.width=0,this.height=0,this.qrCodeSymbol=null,this.debug=!1,this.callback=null}function r(t,e){return t>=0?t>>e:(t>>e)+(2<<~e)}n.d(e,\"b\",function(){return s}),e.a=i,e.c=r;var o=n(14),a=n(13),s={};s.sizeOfDataLengthInfo=[[10,9,8,8],[12,11,16,10],[14,13,16,12]],i.prototype.decode=function(t,e){var n=function(){try{this.error=void 0,this.result=this.process(this.imagedata)}catch(t){this.error=t,this.result=void 0}return null!=this.callback&&this.callback(this.error,this.result),this.result}.bind(this);if(void 0!=t&&void 0!=t.width)this.width=t.width,this.height=t.height,this.imagedata={data:e||t.data},this.imagedata.width=t.width,this.imagedata.height=t.height,n();else{if(\"undefined\"==typeof Image)throw new Error(\"This source format is not supported in your environment, you need to pass an image buffer with width and height (see https://github.com/edi9999/jsqrcode/blob/master/test/qrcode.js)\");var i=new Image;i.crossOrigin=\"Anonymous\",i.onload=function(){var t=document.createElement(\"canvas\"),e=t.getContext(\"2d\"),r=document.getElementById(\"out-canvas\");if(null!=r){var o=r.getContext(\"2d\");o.clearRect(0,0,320,240),o.drawImage(i,0,0,320,240)}t.width=i.width,t.height=i.height,e.drawImage(i,0,0),this.width=i.width,this.height=i.height;try{this.imagedata=e.getImageData(0,0,i.width,i.height)}catch(t){if(this.result=\"Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!\",null!=this.callback)return this.callback(null,this.result)}n()}.bind(this),i.src=t}},i.prototype.decode_utf8=function(t){return decodeURIComponent(escape(t))},i.prototype.process=function(t){for(var e=(new Date).getTime(),n=this.grayScaleToBitmap(this.grayscale(t)),i=new o.a(n),r=i.detect(),s=a.a.decode(r.bits),h=s.DataByte,f=\"\",w=0;w<h.length;w++)for(var u=0;u<h[w].length;u++)f+=String.fromCharCode(h[w][u]);var l=(new Date).getTime(),c=l-e;return this.debug&&console.log(\"QR Code processing time (ms): \"+c),{result:this.decode_utf8(f),points:r.points}},i.prototype.getPixel=function(t,e,n){if(t.width<e)throw\"point error\";if(t.height<n)throw\"point error\";var i=4*e+n*t.width*4;return(33*t.data[i]+34*t.data[i+1]+33*t.data[i+2])/100},i.prototype.binarize=function(t){for(var e=new Array(this.width*this.height),n=0;n<this.height;n++)for(var i=0;i<this.width;i++){var r=this.getPixel(i,n);e[i+n*this.width]=r<=t}return e},i.prototype.getMiddleBrightnessPerArea=function(t){for(var e=Math.floor(t.width/4),n=Math.floor(t.height/4),i=new Array(4),r=0;r<4;r++){i[r]=new Array(4);for(var o=0;o<4;o++)i[r][o]=[0,0]}for(var a=0;a<4;a++)for(var s=0;s<4;s++){i[s][a][0]=255;for(var h=0;h<n;h++)for(var f=0;f<e;f++){var w=t.data[e*s+f+(n*a+h)*t.width];w<i[s][a][0]&&(i[s][a][0]=w),w>i[s][a][1]&&(i[s][a][1]=w)}}for(var u=new Array(4),l=0;l<4;l++)u[l]=new Array(4);for(var a=0;a<4;a++)for(var s=0;s<4;s++)u[s][a]=Math.floor((i[s][a][0]+i[s][a][1])/2);return u},i.prototype.grayScaleToBitmap=function(t){for(var e=this.getMiddleBrightnessPerArea(t),n=e.length,i=Math.floor(t.width/n),r=Math.floor(t.height/n),o=0;o<n;o++)for(var a=0;a<n;a++)for(var s=0;s<r;s++)for(var h=0;h<i;h++)t.data[i*a+h+(r*o+s)*t.width]=t.data[i*a+h+(r*o+s)*t.width]<e[a][o];return t},i.prototype.grayscale=function(t){for(var e=new Array(t.width*t.height),n=0;n<t.height;n++)for(var i=0;i<t.width;i++){var r=this.getPixel(t,i,n);e[i+n*t.width]=r}return{height:t.height,width:t.width,data:e}}},function(t,e,n){\"use strict\";function i(t,e){if(e||(e=t),t<1||e<1)throw\"Both dimensions must be greater than 0\";this.width=t,this.height=e;var n=t>>5;0!=(31&t)&&n++,this.rowSize=n,this.bits=new Array(n*e);for(var i=0;i<this.bits.length;i++)this.bits[i]=0}e.a=i;var r=n(0);Object.defineProperty(i.prototype,\"Dimension\",{get:function(){if(this.width!=this.height)throw\"Can't call getDimension() on a non-square matrix\";return this.width}}),i.prototype.get_Renamed=function(t,e){var i=e*this.rowSize+(t>>5);return 0!=(1&n.i(r.c)(this.bits[i],31&t))},i.prototype.set_Renamed=function(t,e){var n=e*this.rowSize+(t>>5);this.bits[n]|=1<<(31&t)},i.prototype.flip=function(t,e){var n=e*this.rowSize+(t>>5);this.bits[n]^=1<<(31&t)},i.prototype.clear=function(){for(var t=this.bits.length,e=0;e<t;e++)this.bits[e]=0},i.prototype.setRegion=function(t,e,n,i){if(e<0||t<0)throw\"Left and top must be nonnegative\";if(i<1||n<1)throw\"Height and width must be at least 1\";var r=t+n,o=e+i;if(o>this.height||r>this.width)throw\"The region must fit inside the matrix\";for(var a=e;a<o;a++)for(var s=a*this.rowSize,h=t;h<r;h++)this.bits[s+(h>>5)]|=1<<(31&h)}},function(t,e,n){\"use strict\";function i(t){this.errorCorrectionLevel=o.a.forBits(t>>3&3),this.dataMask=7&t}e.a=i;var r=n(0),o=n(15),a=[[21522,0],[20773,1],[24188,2],[23371,3],[17913,4],[16590,5],[20375,6],[19104,7],[30660,8],[29427,9],[32170,10],[30877,11],[26159,12],[25368,13],[27713,14],[26998,15],[5769,16],[5054,17],[7399,18],[6608,19],[1890,20],[597,21],[3340,22],[2107,23],[13663,24],[12392,25],[16177,26],[14854,27],[9396,28],[8579,29],[11994,30],[11245,31]],s=[0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4];i.prototype.GetHashCode=function(){return this.errorCorrectionLevel.ordinal()<<3|this.dataMask},i.prototype.Equals=function(t){var e=t;return this.errorCorrectionLevel==e.errorCorrectionLevel&&this.dataMask==e.dataMask},i.numBitsDiffering=function(t,e){return t^=e,s[15&t]+s[15&n.i(r.c)(t,4)]+s[15&n.i(r.c)(t,8)]+s[15&n.i(r.c)(t,12)]+s[15&n.i(r.c)(t,16)]+s[15&n.i(r.c)(t,20)]+s[15&n.i(r.c)(t,24)]+s[15&n.i(r.c)(t,28)]},i.decodeFormatInformation=function(t){var e=i.doDecodeFormatInformation(t);return null!=e?e:i.doDecodeFormatInformation(21522^t)},i.doDecodeFormatInformation=function(t){for(var e=4294967295,n=0,r=0;r<a.length;r++){var o=a[r],s=o[0];if(s==t)return new i(o[1]);var h=this.numBitsDiffering(t,s);h<e&&(n=o[1],e=h)}return e<=3?new i(n):null}},function(t,e,n){\"use strict\";function i(t){this.expTable=new Array(256),this.logTable=new Array(256);for(var e=1,n=0;n<256;n++)this.expTable[n]=e,(e<<=1)>=256&&(e^=t);for(var n=0;n<255;n++)this.logTable[this.expTable[n]]=n;var i=new Array(1);i[0]=0,this.zero=new r.a(this,new Array(i));var o=new Array(1);o[0]=1,this.one=new r.a(this,new Array(o))}e.a=i;var r=n(4);Object.defineProperty(i.prototype,\"Zero\",{get:function(){return this.zero}}),Object.defineProperty(i.prototype,\"One\",{get:function(){return this.one}}),i.prototype.buildMonomial=function(t,e){if(t<0)throw\"System.ArgumentException\";if(0==e)return this.zero;for(var n=new Array(t+1),i=0;i<n.length;i++)n[i]=0;return n[0]=e,new r.a(this,n)},i.prototype.exp=function(t){return this.expTable[t]},i.prototype.log=function(t){if(0==t)throw\"System.ArgumentException\";return this.logTable[t]},i.prototype.inverse=function(t){if(0==t)throw\"System.ArithmeticException\";return this.expTable[255-this.logTable[t]]},i.prototype.addOrSubtract=function(t,e){return t^e},i.prototype.multiply=function(t,e){return 0==t||0==e?0:1==t?e:1==e?t:this.expTable[(this.logTable[t]+this.logTable[e])%255]},i.QR_CODE_FIELD=new i(285),i.DATA_MATRIX_FIELD=new i(301)},function(t,e,n){\"use strict\";function i(t,e){if(null==e||0==e.length)throw\"System.ArgumentException\";this.field=t;var n=e.length;if(n>1&&0==e[0]){for(var i=1;i<n&&0==e[i];)i++;if(i==n)this.coefficients=t.Zero.coefficients;else{this.coefficients=new Array(n-i);for(var r=0;r<this.coefficients.length;r++)this.coefficients[r]=0;for(var o=0;o<this.coefficients.length;o++)this.coefficients[o]=e[i+o]}}else this.coefficients=e}e.a=i,Object.defineProperty(i.prototype,\"Zero\",{get:function(){return 0==this.coefficients[0]}}),Object.defineProperty(i.prototype,\"Degree\",{get:function(){return this.coefficients.length-1}}),i.prototype.getCoefficient=function(t){return this.coefficients[this.coefficients.length-1-t]},i.prototype.evaluateAt=function(t){if(0==t)return this.getCoefficient(0);var e=this.coefficients.length;if(1==t){for(var n=0,i=0;i<e;i++)n=this.field.addOrSubtract(n,this.coefficients[i]);return n}for(var r=this.coefficients[0],i=1;i<e;i++)r=this.field.addOrSubtract(this.field.multiply(t,r),this.coefficients[i]);return r},i.prototype.addOrSubtract=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(this.Zero)return t;if(t.Zero)return this;var e=this.coefficients,n=t.coefficients;if(e.length>n.length){var r=e;e=n,n=r}for(var o=new Array(n.length),a=n.length-e.length,s=0;s<a;s++)o[s]=n[s];for(var h=a;h<n.length;h++)o[h]=this.field.addOrSubtract(e[h-a],n[h]);return new i(this.field,o)},i.prototype.multiply1=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(this.Zero||t.Zero)return this.field.Zero;for(var e=this.coefficients,n=e.length,r=t.coefficients,o=r.length,a=new Array(n+o-1),s=0;s<n;s++)for(var h=e[s],f=0;f<o;f++)a[s+f]=this.field.addOrSubtract(a[s+f],this.field.multiply(h,r[f]));return new i(this.field,a)},i.prototype.multiply2=function(t){if(0==t)return this.field.Zero;if(1==t)return this;for(var e=this.coefficients.length,n=new Array(e),r=0;r<e;r++)n[r]=this.field.multiply(this.coefficients[r],t);return new i(this.field,n)},i.prototype.multiplyByMonomial=function(t,e){if(t<0)throw\"System.ArgumentException\";if(0==e)return this.field.Zero;for(var n=this.coefficients.length,r=new Array(n+t),o=0;o<r.length;o++)r[o]=0;for(var o=0;o<n;o++)r[o]=this.field.multiply(this.coefficients[o],e);return new i(this.field,r)},i.prototype.divide=function(t){if(this.field!=t.field)throw\"GF256Polys do not have same GF256 field\";if(t.Zero)throw\"Divide by 0\";for(var e=this.field.Zero,n=this,i=t.getCoefficient(t.Degree),r=this.field.inverse(i);n.Degree>=t.Degree&&!n.Zero;){var o=n.Degree-t.Degree,a=this.field.multiply(n.getCoefficient(n.Degree),r),s=t.multiplyByMonomial(o,a),h=this.field.buildMonomial(o,a);e=e.addOrSubtract(h),n=n.addOrSubtract(s)}return[e,n]}},function(t,e,n){\"use strict\";function i(t,e){this.count=t,this.dataCodewords=e}function r(t,e,n){this.ecCodewordsPerBlock=t,this.ecBlocks=n?[e,n]:[e]}function o(t,e,n,i,r,o){this.versionNumber=t,this.alignmentPatternCenters=e,this.ecBlocks=[n,i,r,o];for(var a=0,s=n.ecCodewordsPerBlock,h=n.getECBlocks(),f=0;f<h.length;f++){var w=h[f];a+=w.count*(w.dataCodewords+s)}this.totalCodewords=a}e.a=o;var a=n(2),s=n(1);Object.defineProperty(r.prototype,\"TotalECCodewords\",{get:function(){return this.ecCodewordsPerBlock*this.NumBlocks}}),Object.defineProperty(r.prototype,\"NumBlocks\",{get:function(){for(var t=0,e=0;e<this.ecBlocks.length;e++)t+=this.ecBlocks[e].length;return t}}),r.prototype.getECBlocks=function(){return this.ecBlocks},Object.defineProperty(o.prototype,\"DimensionForVersion\",{get:function(){return 17+4*this.versionNumber}}),o.prototype.buildFunctionPattern=function(){var t=this.DimensionForVersion,e=new s.a(t);e.setRegion(0,0,9,9),e.setRegion(t-8,0,8,9),e.setRegion(0,t-8,9,8);for(var n=this.alignmentPatternCenters.length,i=0;i<n;i++)for(var r=this.alignmentPatternCenters[i]-2,o=0;o<n;o++)0==i&&(0==o||o==n-1)||i==n-1&&0==o||e.setRegion(this.alignmentPatternCenters[o]-2,r,5,5);return e.setRegion(6,9,1,t-17),e.setRegion(9,6,t-17,1),this.versionNumber>6&&(e.setRegion(t-11,0,3,6),e.setRegion(0,t-11,6,3)),e},o.prototype.getECBlocksForLevel=function(t){return this.ecBlocks[t.ordinal()]},o.VERSION_DECODE_INFO=[31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017],o.VERSIONS=function(){return[new o(1,[],new r(7,new i(1,19)),new r(10,new i(1,16)),new r(13,new i(1,13)),new r(17,new i(1,9))),new o(2,[6,18],new r(10,new i(1,34)),new r(16,new i(1,28)),new r(22,new i(1,22)),new r(28,new i(1,16))),new o(3,[6,22],new r(15,new i(1,55)),new r(26,new i(1,44)),new r(18,new i(2,17)),new r(22,new i(2,13))),new o(4,[6,26],new r(20,new i(1,80)),new r(18,new i(2,32)),new r(26,new i(2,24)),new r(16,new i(4,9))),new o(5,[6,30],new r(26,new i(1,108)),new r(24,new i(2,43)),new r(18,new i(2,15),new i(2,16)),new r(22,new i(2,11),new i(2,12))),new o(6,[6,34],new r(18,new i(2,68)),new r(16,new i(4,27)),new r(24,new i(4,19)),new r(28,new i(4,15))),new o(7,[6,22,38],new r(20,new i(2,78)),new r(18,new i(4,31)),new r(18,new i(2,14),new i(4,15)),new r(26,new i(4,13),new i(1,14))),new o(8,[6,24,42],new r(24,new i(2,97)),new r(22,new i(2,38),new i(2,39)),new r(22,new i(4,18),new i(2,19)),new r(26,new i(4,14),new i(2,15))),new o(9,[6,26,46],new r(30,new i(2,116)),new r(22,new i(3,36),new i(2,37)),new r(20,new i(4,16),new i(4,17)),new r(24,new i(4,12),new i(4,13))),new o(10,[6,28,50],new r(18,new i(2,68),new i(2,69)),new r(26,new i(4,43),new i(1,44)),new r(24,new i(6,19),new i(2,20)),new r(28,new i(6,15),new i(2,16))),new o(11,[6,30,54],new r(20,new i(4,81)),new r(30,new i(1,50),new i(4,51)),new r(28,new i(4,22),new i(4,23)),new r(24,new i(3,12),new i(8,13))),new o(12,[6,32,58],new r(24,new i(2,92),new i(2,93)),new r(22,new i(6,36),new i(2,37)),new r(26,new i(4,20),new i(6,21)),new r(28,new i(7,14),new i(4,15))),new o(13,[6,34,62],new r(26,new i(4,107)),new r(22,new i(8,37),new i(1,38)),new r(24,new i(8,20),new i(4,21)),new r(22,new i(12,11),new i(4,12))),new o(14,[6,26,46,66],new r(30,new i(3,115),new i(1,116)),new r(24,new i(4,40),new i(5,41)),new r(20,new i(11,16),new i(5,17)),new r(24,new i(11,12),new i(5,13))),new o(15,[6,26,48,70],new r(22,new i(5,87),new i(1,88)),new r(24,new i(5,41),new i(5,42)),new r(30,new i(5,24),new i(7,25)),new r(24,new i(11,12),new i(7,13))),new o(16,[6,26,50,74],new r(24,new i(5,98),new i(1,99)),new r(28,new i(7,45),new i(3,46)),new r(24,new i(15,19),new i(2,20)),new r(30,new i(3,15),new i(13,16))),new o(17,[6,30,54,78],new r(28,new i(1,107),new i(5,108)),new r(28,new i(10,46),new i(1,47)),new r(28,new i(1,22),new i(15,23)),new r(28,new i(2,14),new i(17,15))),new o(18,[6,30,56,82],new r(30,new i(5,120),new i(1,121)),new r(26,new i(9,43),new i(4,44)),new r(28,new i(17,22),new i(1,23)),new r(28,new i(2,14),new i(19,15))),new o(19,[6,30,58,86],new r(28,new i(3,113),new i(4,114)),new r(26,new i(3,44),new i(11,45)),new r(26,new i(17,21),new i(4,22)),new r(26,new i(9,13),new i(16,14))),new o(20,[6,34,62,90],new r(28,new i(3,107),new i(5,108)),new r(26,new i(3,41),new i(13,42)),new r(30,new i(15,24),new i(5,25)),new r(28,new i(15,15),new i(10,16))),new o(21,[6,28,50,72,94],new r(28,new i(4,116),new i(4,117)),new r(26,new i(17,42)),new r(28,new i(17,22),new i(6,23)),new r(30,new i(19,16),new i(6,17))),new o(22,[6,26,50,74,98],new r(28,new i(2,111),new i(7,112)),new r(28,new i(17,46)),new r(30,new i(7,24),new i(16,25)),new r(24,new i(34,13))),new o(23,[6,30,54,74,102],new r(30,new i(4,121),new i(5,122)),new r(28,new i(4,47),new i(14,48)),new r(30,new i(11,24),new i(14,25)),new r(30,new i(16,15),new i(14,16))),new o(24,[6,28,54,80,106],new r(30,new i(6,117),new i(4,118)),new r(28,new i(6,45),new i(14,46)),new r(30,new i(11,24),new i(16,25)),new r(30,new i(30,16),new i(2,17))),new o(25,[6,32,58,84,110],new r(26,new i(8,106),new i(4,107)),new r(28,new i(8,47),new i(13,48)),new r(30,new i(7,24),new i(22,25)),new r(30,new i(22,15),new i(13,16))),new o(26,[6,30,58,86,114],new r(28,new i(10,114),new i(2,115)),new r(28,new i(19,46),new i(4,47)),new r(28,new i(28,22),new i(6,23)),new r(30,new i(33,16),new i(4,17))),new o(27,[6,34,62,90,118],new r(30,new i(8,122),new i(4,123)),new r(28,new i(22,45),new i(3,46)),new r(30,new i(8,23),new i(26,24)),new r(30,new i(12,15),new i(28,16))),new o(28,[6,26,50,74,98,122],new r(30,new i(3,117),new i(10,118)),new r(28,new i(3,45),new i(23,46)),new r(30,new i(4,24),new i(31,25)),new r(30,new i(11,15),new i(31,16))),new o(29,[6,30,54,78,102,126],new r(30,new i(7,116),new i(7,117)),new r(28,new i(21,45),new i(7,46)),new r(30,new i(1,23),new i(37,24)),new r(30,new i(19,15),new i(26,16))),new o(30,[6,26,52,78,104,130],new r(30,new i(5,115),new i(10,116)),new r(28,new i(19,47),new i(10,48)),new r(30,new i(15,24),new i(25,25)),new r(30,new i(23,15),new i(25,16))),new o(31,[6,30,56,82,108,134],new r(30,new i(13,115),new i(3,116)),new r(28,new i(2,46),new i(29,47)),new r(30,new i(42,24),new i(1,25)),new r(30,new i(23,15),new i(28,16))),new o(32,[6,34,60,86,112,138],new r(30,new i(17,115)),new r(28,new i(10,46),new i(23,47)),new r(30,new i(10,24),new i(35,25)),new r(30,new i(19,15),new i(35,16))),new o(33,[6,30,58,86,114,142],new r(30,new i(17,115),new i(1,116)),new r(28,new i(14,46),new i(21,47)),new r(30,new i(29,24),new i(19,25)),new r(30,new i(11,15),new i(46,16))),new o(34,[6,34,62,90,118,146],new r(30,new i(13,115),new i(6,116)),new r(28,new i(14,46),new i(23,47)),new r(30,new i(44,24),new i(7,25)),new r(30,new i(59,16),new i(1,17))),new o(35,[6,30,54,78,102,126,150],new r(30,new i(12,121),new i(7,122)),new r(28,new i(12,47),new i(26,48)),new r(30,new i(39,24),new i(14,25)),new r(30,new i(22,15),new i(41,16))),new o(36,[6,24,50,76,102,128,154],new r(30,new i(6,121),new i(14,122)),new r(28,new i(6,47),new i(34,48)),new r(30,new i(46,24),new i(10,25)),new r(30,new i(2,15),new i(64,16))),new o(37,[6,28,54,80,106,132,158],new r(30,new i(17,122),new i(4,123)),new r(28,new i(29,46),new i(14,47)),new r(30,new i(49,24),new i(10,25)),new r(30,new i(24,15),new i(46,16))),new o(38,[6,32,58,84,110,136,162],new r(30,new i(4,122),new i(18,123)),new r(28,new i(13,46),new i(32,47)),new r(30,new i(48,24),new i(14,25)),new r(30,new i(42,15),new i(32,16))),new o(39,[6,26,54,82,110,138,166],new r(30,new i(20,117),new i(4,118)),new r(28,new i(40,47),new i(7,48)),new r(30,new i(43,24),new i(22,25)),new r(30,new i(10,15),new i(67,16))),new o(40,[6,30,58,86,114,142,170],new r(30,new i(19,118),new i(6,119)),new r(28,new i(18,47),new i(31,48)),new r(30,new i(34,24),new i(34,25)),new r(30,new i(20,15),new i(61,16)))]}(),o.getVersionForNumber=function(t){if(t<1||t>40)throw\"ArgumentException\";return o.VERSIONS[t-1]},o.getProvisionalVersionForDimension=function(t){if(t%4!=1)throw\"Error getProvisionalVersionForDimension\";try{return o.getVersionForNumber(t-17>>2)}catch(t){throw\"Error getVersionForNumber\"}},o.decodeVersionInformation=function(t){for(var e=4294967295,n=0,i=0;i<o.VERSION_DECODE_INFO.length;i++){var r=o.VERSION_DECODE_INFO[i];if(r==t)return this.getVersionForNumber(i+7);var s=a.a.numBitsDiffering(t,r);s<e&&(n=i+7,e=s)}return e<=3?this.getVersionForNumber(n):null}},function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0});var i=n(0);e.default=i.a},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,\"loaded\",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,\"id\",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){\"use strict\";function i(t,e,n){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=n}function r(t,e,n,i,r,o,a){this.image=t,this.possibleCenters=[],this.startX=e,this.startY=n,this.width=i,this.height=r,this.moduleSize=o,this.crossCheckStateCount=[0,0,0],this.resultPointCallback=a}e.a=r,Object.defineProperty(i.prototype,\"X\",{get:function(){return Math.floor(this.x)}}),Object.defineProperty(i.prototype,\"Y\",{get:function(){return Math.floor(this.y)}}),i.prototype.incrementCount=function(){this.count++},i.prototype.aboutEquals=function(t,e,n){if(Math.abs(e-this.y)<=t&&Math.abs(n-this.x)<=t){var i=Math.abs(t-this.estimatedModuleSize);return i<=1||i/this.estimatedModuleSize<=1}return!1},r.prototype.centerFromEnd=function(t,e){return e-t[2]-t[1]/2},r.prototype.foundPatternCross=function(t){for(var e=this.moduleSize,n=e/2,i=0;i<3;i++)if(Math.abs(e-t[i])>=n)return!1;return!0},r.prototype.crossCheckVertical=function(t,e,n,i){var r=this.image,o=r.height,a=this.crossCheckStateCount;a[0]=0,a[1]=0,a[2]=0;for(var s=t;s>=0&&r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&!r.data[e+s*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s++;if(s==o||a[1]>n)return NaN;for(;s<o&&!r.data[e+s*r.width]&&a[2]<=n;)a[2]++,s++;if(a[2]>n)return NaN;var h=a[0]+a[1]+a[2];return 5*Math.abs(h-i)>=2*i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},r.prototype.handlePossibleCenter=function(t,e,n){var r=t[0]+t[1]+t[2],o=this.centerFromEnd(t,n),a=this.crossCheckVertical(e,Math.floor(o),2*t[1],r);if(!isNaN(a)){for(var s=(t[0]+t[1]+t[2])/3,h=this.possibleCenters.length,f=0;f<h;f++){if(this.possibleCenters[f].aboutEquals(s,a,o))return new i(o,a,s)}var w=new i(o,a,s);this.possibleCenters.push(w),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(w)}return null},r.prototype.find=function(){for(var t=this.image,e=this.startX,n=this.height,i=e+this.width,r=this.startY+(n>>1),o=[0,0,0],a=0;a<n;a++){var s=r+(0==(1&a)?a+1>>1:-(a+1>>1));o[0]=0,o[1]=0,o[2]=0;for(var h=e;h<i&&!t.data[h+t.width*s];)h++;for(var f=0;h<i;){if(t.data[h+s*t.width])if(1==f)o[f]++;else if(2==f){if(this.foundPatternCross(o)){var w=this.handlePossibleCenter(o,s,h);if(null!=w)return w}o[0]=o[2],o[1]=1,o[2]=0,f=1}else o[++f]++;else 1==f&&f++,o[f]++;h++}if(this.foundPatternCross(o)){var w=this.handlePossibleCenter(o,s,i);if(null!=w)return w}}if(0!=this.possibleCenters.length)return this.possibleCenters[0];throw\"Couldn't find enough alignment patterns\"}},function(t,e,n){\"use strict\";function i(t){var e=t.Dimension;if(e<21||1!=(3&e))throw\"Error BitMatrixParser\";this.bitMatrix=t,this.parsedVersion=null,this.parsedFormatInfo=null}e.a=i;var r=n(2),o=n(5),a=n(12);i.prototype.copyBit=function(t,e,n){return this.bitMatrix.get_Renamed(t,e)?n<<1|1:n<<1},i.prototype.readFormatInformation=function(){if(null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var t=0,e=0;e<6;e++)t=this.copyBit(e,8,t);t=this.copyBit(7,8,t),t=this.copyBit(8,8,t),t=this.copyBit(8,7,t);for(var n=5;n>=0;n--)t=this.copyBit(8,n,t);if(this.parsedFormatInfo=r.a.decodeFormatInformation(t),null!=this.parsedFormatInfo)return this.parsedFormatInfo;var i=this.bitMatrix.Dimension;t=0;for(var o=i-8,e=i-1;e>=o;e--)t=this.copyBit(e,8,t);for(var n=i-7;n<i;n++)t=this.copyBit(8,n,t);if(this.parsedFormatInfo=r.a.decodeFormatInformation(t),null!=this.parsedFormatInfo)return this.parsedFormatInfo;throw\"Error readFormatInformation\"},i.prototype.readVersion=function(){if(null!=this.parsedVersion)return this.parsedVersion;var t=this.bitMatrix.Dimension,e=t-17>>2;if(e<=6)return o.a.getVersionForNumber(e);for(var n=0,i=t-11,r=5;r>=0;r--)for(var a=t-9;a>=i;a--)n=this.copyBit(a,r,n);if(this.parsedVersion=o.a.decodeVersionInformation(n),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==t)return this.parsedVersion;n=0;for(var a=5;a>=0;a--)for(var r=t-9;r>=i;r--)n=this.copyBit(a,r,n);if(this.parsedVersion=o.a.decodeVersionInformation(n),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==t)return this.parsedVersion;throw\"Error readVersion\"},i.prototype.readCodewords=function(){var t=this.readFormatInformation(),e=this.readVersion(),n=a.a.forReference(t.dataMask),i=this.bitMatrix.Dimension;n.unmaskBitMatrix(this.bitMatrix,i);for(var r=e.buildFunctionPattern(),o=!0,s=new Array(e.totalCodewords),h=0,f=0,w=0,u=i-1;u>0;u-=2){6==u&&u--;for(var l=0;l<i;l++)for(var c=o?i-1-l:l,d=0;d<2;d++)r.get_Renamed(u-d,c)||(w++,f<<=1,this.bitMatrix.get_Renamed(u-d,c)&&(f|=1),8==w&&(s[h++]=f,w=0,f=0));o^=!0}if(h!=e.totalCodewords)throw\"Error readCodewords\";return s}},function(t,e,n){\"use strict\";function i(t,e){this.numDataCodewords=t,this.codewords=e}e.a=i,i.getDataBlocks=function(t,e,n){if(t.length!=e.totalCodewords)throw\"ArgumentException\";for(var r=e.getECBlocksForLevel(n),o=0,a=r.getECBlocks(),s=0;s<a.length;s++)o+=a[s].count;for(var h=new Array(o),f=0,w=0;w<a.length;w++)for(var u=a[w],s=0;s<u.count;s++){var l=u.dataCodewords,c=r.ecCodewordsPerBlock+l;h[f++]=new i(l,new Array(c))}for(var d=h[0].codewords.length,p=h.length-1;p>=0;){if(h[p].codewords.length==d)break;p--}p++;for(var g=d-r.ecCodewordsPerBlock,v=0,s=0;s<g;s++)for(var w=0;w<f;w++)h[w].codewords[s]=t[v++];for(var w=p;w<f;w++)h[w].codewords[g]=t[v++];for(var m=h[0].codewords.length,s=g;s<m;s++)for(var w=0;w<f;w++){var b=w<p?s:s+1;h[w].codewords[b]=t[v++]}return h}},function(t,e,n){\"use strict\";function i(t,e,n){this.blockPointer=0,this.bitPointer=7,this.dataLength=0,this.blocks=t,this.numErrorCorrectionCode=n,e<=9?this.dataLengthMode=0:e>=10&&e<=26?this.dataLengthMode=1:e>=27&&e<=40&&(this.dataLengthMode=2)}e.a=i;var r=n(0);i.prototype.getNextBits=function(t){var e=0;if(t<this.bitPointer+1){for(var n=0,i=0;i<t;i++)n+=1<<i;return n<<=this.bitPointer-t+1,e=(this.blocks[this.blockPointer]&n)>>this.bitPointer-t+1,this.bitPointer-=t,e}if(t<this.bitPointer+1+8){for(var r=0,i=0;i<this.bitPointer+1;i++)r+=1<<i;return e=(this.blocks[this.blockPointer]&r)<<t-(this.bitPointer+1),this.blockPointer++,e+=this.blocks[this.blockPointer]>>8-(t-(this.bitPointer+1)),this.bitPointer=this.bitPointer-t%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),e}if(t<this.bitPointer+1+16){for(var r=0,o=0,i=0;i<this.bitPointer+1;i++)r+=1<<i;var a=(this.blocks[this.blockPointer]&r)<<t-(this.bitPointer+1);this.blockPointer++;var s=this.blocks[this.blockPointer]<<t-(this.bitPointer+1+8);this.blockPointer++;for(var i=0;i<t-(this.bitPointer+1+8);i++)o+=1<<i;o<<=8-(t-(this.bitPointer+1+8));return e=a+s+((this.blocks[this.blockPointer]&o)>>8-(t-(this.bitPointer+1+8))),this.bitPointer=this.bitPointer-(t-8)%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),e}return 0},i.prototype.NextMode=function(){return this.blockPointer>this.blocks.length-this.numErrorCorrectionCode-2?0:this.getNextBits(4)},i.prototype.getDataLength=function(t){for(var e=0;;){if(t>>e==1)break;e++}return this.getNextBits(r.b.sizeOfDataLengthInfo[this.dataLengthMode][e])},i.prototype.getRomanAndFigureString=function(t){var e=t,n=0,i=\"\",r=[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"A\",\"B\",\"C\",\"D\",\"E\",\"F\",\"G\",\"H\",\"I\",\"J\",\"K\",\"L\",\"M\",\"N\",\"O\",\"P\",\"Q\",\"R\",\"S\",\"T\",\"U\",\"V\",\"W\",\"X\",\"Y\",\"Z\",\" \",\"$\",\"%\",\"*\",\"+\",\"-\",\".\",\"/\",\":\"];do{if(e>1){n=this.getNextBits(11);var o=Math.floor(n/45),a=n%45;i+=r[o],i+=r[a],e-=2}else 1==e&&(n=this.getNextBits(6),i+=r[n],e-=1)}while(e>0);return i},i.prototype.getFigureString=function(t){var e=t,n=0,i=\"\";do{e>=3?(n=this.getNextBits(10),n<100&&(i+=\"0\"),n<10&&(i+=\"0\"),e-=3):2==e?(n=this.getNextBits(7),n<10&&(i+=\"0\"),e-=2):1==e&&(n=this.getNextBits(4),e-=1),i+=n}while(e>0);return i},i.prototype.get8bitByteArray=function(t){var e=t,n=0,i=[];do{n=this.getNextBits(8),i.push(n),e--}while(e>0);return i},i.prototype.getKanjiString=function(t){var e=t,n=0,i=\"\";do{n=this.getNextBits(13);var r=n%192,o=n/192,a=(o<<8)+r,s=0;s=a+33088<=40956?a+33088:a+49472,i+=String.fromCharCode(s),e--}while(e>0);return i},Object.defineProperty(i.prototype,\"DataByte\",{get:function(){for(var t=[];;){var e=this.NextMode();if(0==e){if(t.length>0)break;throw\"Empty data block\"}if(1!=e&&2!=e&&4!=e&&8!=e&&7!=e)throw\"Invalid mode: \"+e+\" in (block:\"+this.blockPointer+\" bit:\"+this.bitPointer+\")\";var n=this.getDataLength(e);if(n<1)throw\"Invalid data length: \"+n;switch(e){case 1:for(var i=this.getFigureString(n),r=new Array(i.length),o=0;o<i.length;o++)r[o]=i.charCodeAt(o);t.push(r);break;case 2:for(var i=this.getRomanAndFigureString(n),r=new Array(i.length),o=0;o<i.length;o++)r[o]=i.charCodeAt(o);t.push(r);break;case 4:var a=this.get8bitByteArray(n);t.push(a);break;case 8:var i=this.getKanjiString(n);t.push(i)}}return t}})},function(t,e,n){\"use strict\";function i(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(t+e&1)}}function r(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(1&t)}}function o(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return e%3==0}}function a(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return(t+e)%3==0}}function s(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==(n.i(u.c)(t,1)+e/3&1)}}function h(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){var n=t*e;return(1&n)+n%3==0}}function f(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){var n=t*e;return 0==((1&n)+n%3&1)}}function w(){this.unmaskBitMatrix=function(t,e){for(var n=0;n<e;n++)for(var i=0;i<e;i++)this.isMasked(n,i)&&t.flip(i,n)},this.isMasked=function(t,e){return 0==((t+e&1)+t*e%3&1)}}var u=n(0),l={};l.forReference=function(t){if(t<0||t>7)throw\"System.ArgumentException\";return l.DATA_MASKS[t]},l.DATA_MASKS=[new i,new r,new o,new a,new s,new h,new f,new w],e.a=l},function(t,e,n){\"use strict\";var i=n(18),r=n(3),o=n(9),a=n(10),s=n(11),h={};h.rsDecoder=new i.a(r.a.QR_CODE_FIELD),h.correctErrors=function(t,e){for(var n=t.length,i=new Array(n),r=0;r<n;r++)i[r]=255&t[r];var o=t.length-e;try{h.rsDecoder.decode(i,o)}catch(t){throw t}for(var r=0;r<e;r++)t[r]=i[r]},h.decode=function(t){for(var e=new o.a(t),n=e.readVersion(),i=e.readFormatInformation().errorCorrectionLevel,r=e.readCodewords(),f=a.a.getDataBlocks(r,n,i),w=0,u=0;u<f.length;u++)w+=f[u].numDataCodewords;for(var l=new Array(w),c=0,d=0;d<f.length;d++){var p=f[d],g=p.codewords,v=p.numDataCodewords;h.correctErrors(g,v);for(var u=0;u<v;u++)l[c++]=g[u]}return new s.a(l,n.versionNumber,i.bits)},e.a=h},function(t,e,n){\"use strict\";function i(t,e,n,i,r,o,a,s,h){this.a11=t,this.a12=i,this.a13=a,this.a21=e,this.a22=r,this.a23=s,this.a31=n,this.a32=o,this.a33=h}function r(t,e){this.bits=t,this.points=e}function o(t){this.image=t,this.resultPointCallback=null}e.a=o;var a=n(5),s=n(8),h=n(17),f=n(16);i.prototype.transformPoints1=function(t){for(var e=t.length,n=this.a11,i=this.a12,r=this.a13,o=this.a21,a=this.a22,s=this.a23,h=this.a31,f=this.a32,w=this.a33,u=0;u<e;u+=2){var l=t[u],c=t[u+1],d=r*l+s*c+w;t[u]=(n*l+o*c+h)/d,t[u+1]=(i*l+a*c+f)/d}},i.prototype.transformPoints2=function(t,e){for(var n=t.length,i=0;i<n;i++){var r=t[i],o=e[i],a=this.a13*r+this.a23*o+this.a33;t[i]=(this.a11*r+this.a21*o+this.a31)/a,e[i]=(this.a12*r+this.a22*o+this.a32)/a}},i.prototype.buildAdjoint=function(){return new i(this.a22*this.a33-this.a23*this.a32,this.a23*this.a31-this.a21*this.a33,this.a21*this.a32-this.a22*this.a31,this.a13*this.a32-this.a12*this.a33,this.a11*this.a33-this.a13*this.a31,this.a12*this.a31-this.a11*this.a32,this.a12*this.a23-this.a13*this.a22,this.a13*this.a21-this.a11*this.a23,this.a11*this.a22-this.a12*this.a21)},i.prototype.times=function(t){return new i(this.a11*t.a11+this.a21*t.a12+this.a31*t.a13,this.a11*t.a21+this.a21*t.a22+this.a31*t.a23,this.a11*t.a31+this.a21*t.a32+this.a31*t.a33,this.a12*t.a11+this.a22*t.a12+this.a32*t.a13,this.a12*t.a21+this.a22*t.a22+this.a32*t.a23,this.a12*t.a31+this.a22*t.a32+this.a32*t.a33,this.a13*t.a11+this.a23*t.a12+this.a33*t.a13,this.a13*t.a21+this.a23*t.a22+this.a33*t.a23,this.a13*t.a31+this.a23*t.a32+this.a33*t.a33)},i.quadrilateralToQuadrilateral=function(t,e,n,i,r,o,a,s,h,f,w,u,l,c,d,p){var g=this.quadrilateralToSquare(t,e,n,i,r,o,a,s);return this.squareToQuadrilateral(h,f,w,u,l,c,d,p).times(g)},i.squareToQuadrilateral=function(t,e,n,r,o,a,s,h){var f=h-a,w=e-r+a-h;if(0==f&&0==w)return new i(n-t,o-n,t,r-e,a-r,e,0,0,1);var u=n-o,l=s-o,c=t-n+o-s,d=r-a,p=u*f-l*d,g=(c*f-l*w)/p,v=(u*w-c*d)/p;return new i(n-t+g*n,s-t+v*s,t,r-e+g*r,h-e+v*h,e,g,v,1)},i.quadrilateralToSquare=function(t,e,n,i,r,o,a,s){return this.squareToQuadrilateral(t,e,n,i,r,o,a,s).buildAdjoint()},o.prototype.sizeOfBlackWhiteBlackRun=function(t,e,n,i){var r=Math.abs(i-e)>Math.abs(n-t);if(r){var o=t;t=e,e=o,o=n,n=i,i=o}for(var a=Math.abs(n-t),s=Math.abs(i-e),h=-a>>1,f=e<i?1:-1,w=t<n?1:-1,u=0,l=t,c=e;l!=n;l+=w){var d=r?c:l,p=r?l:c;if(1==u?this.image.data[d+p*this.image.width]&&u++:this.image.data[d+p*this.image.width]||u++,3==u){var g=l-t,v=c-e;return Math.sqrt(g*g+v*v)}if((h+=s)>0){if(c==i)break;c+=f,h-=a}}var m=n-t,b=i-e;return Math.sqrt(m*m+b*b)},o.prototype.sizeOfBlackWhiteBlackRunBothWays=function(t,e,n,i){var r=this.sizeOfBlackWhiteBlackRun(t,e,n,i),o=1,a=t-(n-t);a<0?(o=t/(t-a),a=0):a>=this.image.width&&(o=(this.image.width-1-t)/(a-t),a=this.image.width-1);var s=Math.floor(e-(i-e)*o);return o=1,s<0?(o=e/(e-s),s=0):s>=this.image.height&&(o=(this.image.height-1-e)/(s-e),s=this.image.height-1),a=Math.floor(t+(a-t)*o),(r+=this.sizeOfBlackWhiteBlackRun(t,e,a,s))-1},o.prototype.calculateModuleSizeOneWay=function(t,e){var n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.X),Math.floor(t.Y),Math.floor(e.X),Math.floor(e.Y)),i=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.X),Math.floor(e.Y),Math.floor(t.X),Math.floor(t.Y));return isNaN(n)?i/7:isNaN(i)?n/7:(n+i)/14},o.prototype.calculateModuleSize=function(t,e,n){return(this.calculateModuleSizeOneWay(t,e)+this.calculateModuleSizeOneWay(t,n))/2},o.prototype.distance=function(t,e){var n=t.X-e.X,i=t.Y-e.Y;return Math.sqrt(n*n+i*i)},o.prototype.computeDimension=function(t,e,n,i){var r=Math.round(this.distance(t,e)/i),o=Math.round(this.distance(t,n)/i),a=7+(r+o>>1);switch(3&a){case 0:a++;break;case 2:a--;break;case 3:throw\"Error\"}return a},o.prototype.findAlignmentInRegion=function(t,e,n,i){var r=Math.floor(i*t),o=Math.max(0,e-r),a=Math.min(this.image.width-1,e+r);if(a-o<3*t)throw\"Error\";var h=Math.max(0,n-r),f=Math.min(this.image.height-1,n+r);return new s.a(this.image,o,h,a-o,f-h,t,this.resultPointCallback).find()},o.prototype.createTransform=function(t,e,n,r,o){var a,s,h,f,w=o-3.5;return null!=r?(a=r.X,s=r.Y,h=f=w-3):(a=e.X-t.X+n.X,s=e.Y-t.Y+n.Y,h=f=w),i.quadrilateralToQuadrilateral(3.5,3.5,w,3.5,h,f,3.5,w,t.X,t.Y,e.X,e.Y,a,s,n.X,n.Y)},o.prototype.sampleGrid=function(t,e,n){return h.a.sampleGrid3(t,n,e)},o.prototype.processFinderPatternInfo=function(t){var e=t.topLeft,n=t.topRight,i=t.bottomLeft,o=this.calculateModuleSize(e,n,i);if(o<1)throw\"Error\";var s=this.computeDimension(e,n,i,o),h=a.a.getProvisionalVersionForDimension(s),f=h.DimensionForVersion-7,w=null;if(h.alignmentPatternCenters.length>0)for(var u=n.X-e.X+i.X,l=n.Y-e.Y+i.Y,c=1-3/f,d=Math.floor(e.X+c*(u-e.X)),p=Math.floor(e.Y+c*(l-e.Y)),g=4;g<=16;g<<=1){w=this.findAlignmentInRegion(o,d,p,g);break}var v,m=this.createTransform(e,n,i,w,s),b=this.sampleGrid(this.image,m,s);return v=null==w?[i,e,n]:[i,e,n,w],new r(b,v)},o.prototype.detect=function(){var t=(new f.a).findFinderPattern(this.image);return this.processFinderPatternInfo(t)}},function(t,e,n){\"use strict\";function i(t,e,n){this.ordinal_Renamed_Field=t,this.bits=e,this.name=n}e.a=i,i.prototype.ordinal=function(){return this.ordinal_Renamed_Field},i.forBits=function(t){if(t<0||t>=r.length)throw\"ArgumentException\";return r[t]};var r=[new i(1,0,\"M\"),new i(0,1,\"L\"),new i(3,2,\"H\"),new i(2,3,\"Q\")]},function(t,e,n){\"use strict\";function i(t){function e(t,e){var n=t.X-e.X,i=t.Y-e.Y;return Math.sqrt(n*n+i*i)}var n,i,r,o=e(t[0],t[1]),a=e(t[1],t[2]),s=e(t[0],t[2]);if(a>=o&&a>=s?(i=t[0],n=t[1],r=t[2]):s>=a&&s>=o?(i=t[1],n=t[0],r=t[2]):(i=t[2],n=t[0],r=t[1]),function(t,e,n){var i=e.x,r=e.y;return(n.x-i)*(t.y-r)-(n.y-r)*(t.x-i)}(n,i,r)<0){var h=n;n=r,r=h}t[0]=n,t[1]=i,t[2]=r}function r(t,e,n){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=n}function o(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2]}function a(){this.image=null,this.possibleCenters=[],this.hasSkipped=!1,this.crossCheckStateCount=[0,0,0,0,0],this.resultPointCallback=null}e.a=a;Object.defineProperty(r.prototype,\"X\",{get:function(){return this.x}}),Object.defineProperty(r.prototype,\"Y\",{get:function(){return this.y}}),r.prototype.incrementCount=function(){this.count++},r.prototype.aboutEquals=function(t,e,n){if(Math.abs(e-this.y)<=t&&Math.abs(n-this.x)<=t){var i=Math.abs(t-this.estimatedModuleSize);return i<=1||i/this.estimatedModuleSize<=1}return!1},Object.defineProperty(a.prototype,\"CrossCheckStateCount\",{get:function(){return this.crossCheckStateCount[0]=0,this.crossCheckStateCount[1]=0,this.crossCheckStateCount[2]=0,this.crossCheckStateCount[3]=0,this.crossCheckStateCount[4]=0,this.crossCheckStateCount}}),a.prototype.foundPatternCross=function(t){for(var e=0,n=0;n<5;n++){var i=t[n];if(0==i)return!1;e+=i}if(e<7)return!1;var r=Math.floor((e<<8)/7),o=Math.floor(r/2);return Math.abs(r-(t[0]<<8))<o&&Math.abs(r-(t[1]<<8))<o&&Math.abs(3*r-(t[2]<<8))<3*o&&Math.abs(r-(t[3]<<8))<o&&Math.abs(r-(t[4]<<8))<o},a.prototype.centerFromEnd=function(t,e){return e-t[4]-t[3]-t[2]/2},a.prototype.crossCheckVertical=function(t,e,n,i){for(var r=this.image,o=r.height,a=this.CrossCheckStateCount,s=t;s>=0&&r.data[e+s*r.width];)a[2]++,s--;if(s<0)return NaN;for(;s>=0&&!r.data[e+s*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&r.data[e+s*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[e+s*r.width];)a[2]++,s++;if(s==o)return NaN;for(;s<o&&!r.data[e+s*r.width]&&a[3]<n;)a[3]++,s++;if(s==o||a[3]>=n)return NaN;for(;s<o&&r.data[e+s*r.width]&&a[4]<n;)a[4]++,s++;if(a[4]>=n)return NaN;var h=a[0]+a[1]+a[2]+a[3]+a[4];return 5*Math.abs(h-i)>=2*i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},a.prototype.crossCheckHorizontal=function(t,e,n,i){for(var r=this.image,o=r.width,a=this.CrossCheckStateCount,s=t;s>=0&&r.data[s+e*r.width];)a[2]++,s--;if(s<0)return NaN;for(;s>=0&&!r.data[s+e*r.width]&&a[1]<=n;)a[1]++,s--;if(s<0||a[1]>n)return NaN;for(;s>=0&&r.data[s+e*r.width]&&a[0]<=n;)a[0]++,s--;if(a[0]>n)return NaN;for(s=t+1;s<o&&r.data[s+e*r.width];)a[2]++,s++;if(s==o)return NaN;for(;s<o&&!r.data[s+e*r.width]&&a[3]<n;)a[3]++,s++;if(s==o||a[3]>=n)return NaN;for(;s<o&&r.data[s+e*r.width]&&a[4]<n;)a[4]++,s++;if(a[4]>=n)return NaN;var h=a[0]+a[1]+a[2]+a[3]+a[4];return 5*Math.abs(h-i)>=i?NaN:this.foundPatternCross(a)?this.centerFromEnd(a,s):NaN},a.prototype.handlePossibleCenter=function(t,e,n){var i=t[0]+t[1]+t[2]+t[3]+t[4],o=this.centerFromEnd(t,n),a=this.crossCheckVertical(e,Math.floor(o),t[2],i);if(!isNaN(a)&&(o=this.crossCheckHorizontal(Math.floor(o),Math.floor(a),t[2],i),!isNaN(o))){for(var s=i/7,h=!1,f=this.possibleCenters.length,w=0;w<f;w++){var u=this.possibleCenters[w];if(u.aboutEquals(s,a,o)){u.incrementCount(),h=!0;break}}if(!h){var l=new r(o,a,s);this.possibleCenters.push(l),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(l)}return!0}return!1},a.prototype.selectBestPatterns=function(){var t=this.possibleCenters.length;if(t<3)throw\"Couldn't find enough finder patterns:\"+t+\" patterns found\";if(t>3){for(var e=0,n=0,i=0;i<t;i++){var r=this.possibleCenters[i].estimatedModuleSize;e+=r,n+=r*r}var o=e/t;this.possibleCenters.sort(function(t,e){var n=Math.abs(e.estimatedModuleSize-o),i=Math.abs(t.estimatedModuleSize-o);return n<i?-1:n==i?0:1});for(var a=Math.sqrt(n/t-o*o),s=Math.max(.2*o,a),i=this.possibleCenters-1;i>=0;i--){var h=this.possibleCenters[i];Math.abs(h.estimatedModuleSize-o)>s&&this.possibleCenters.splice(i,1)}}return this.possibleCenters.length>3&&this.possibleCenters.sort(function(t,e){return t.count>e.count?-1:t.count<e.count?1:0}),[this.possibleCenters[0],this.possibleCenters[1],this.possibleCenters[2]]},a.prototype.findRowSkip=function(){var t=this.possibleCenters.length;if(t<=1)return 0;for(var e=null,n=0;n<t;n++){var i=this.possibleCenters[n];if(i.count>=2){if(null!=e)return this.hasSkipped=!0,Math.floor((Math.abs(e.X-i.X)-Math.abs(e.Y-i.Y))/2);e=i}}return 0},a.prototype.haveMultiplyConfirmedCenters=function(){for(var t=0,e=0,n=this.possibleCenters.length,i=0;i<n;i++){var r=this.possibleCenters[i];r.count>=2&&(t++,e+=r.estimatedModuleSize)}if(t<3)return!1;for(var o=e/n,a=0,i=0;i<n;i++)r=this.possibleCenters[i],a+=Math.abs(r.estimatedModuleSize-o);return a<=.05*e},a.prototype.findFinderPattern=function(t){this.image=t;var e=t.height,n=t.width,r=Math.floor(3*e/228);r<3&&(r=3);for(var a=!1,s=new Array(5),h=r-1;h<e&&!a;h+=r){s[0]=0,s[1]=0,s[2]=0,s[3]=0,s[4]=0;for(var f=0,w=0;w<n;w++)if(t.data[w+h*t.width])1==(1&f)&&f++,s[f]++;else if(0==(1&f))if(4==f)if(this.foundPatternCross(s)){var u=this.handlePossibleCenter(s,h,w);if(u)if(r=2,this.hasSkipped)a=this.haveMultiplyConfirmedCenters();else{var l=this.findRowSkip();l>s[2]&&(h+=l-s[2]-r,w=n-1)}else{do{w++}while(w<n&&!t.data[w+h*t.width]);w--}f=0,s[0]=0,s[1]=0,s[2]=0,s[3]=0,s[4]=0}else s[0]=s[2],s[1]=s[3],s[2]=s[4],s[3]=1,s[4]=0,f=3;else s[++f]++;else s[f]++;if(this.foundPatternCross(s)){var u=this.handlePossibleCenter(s,h,n);u&&(r=s[0],this.hasSkipped&&(a=this.haveMultiplyConfirmedCenters()))}}var c=this.selectBestPatterns();return i(c),new o(c)}},function(t,e,n){\"use strict\";var i=n(1),r={};r.checkAndNudgePoints=function(t,e){for(var n=t.width,i=t.height,r=!0,o=0;o<e.length&&r;o+=2){var a=Math.floor(e[o]),s=Math.floor(e[o+1]);if(a<-1||a>n||s<-1||s>i)throw\"Error.checkAndNudgePoints \";r=!1,-1==a?(e[o]=0,r=!0):a==n&&(e[o]=n-1,r=!0),-1==s?(e[o+1]=0,r=!0):s==i&&(e[o+1]=i-1,r=!0)}r=!0;for(var o=e.length-2;o>=0&&r;o-=2){var a=Math.floor(e[o]),s=Math.floor(e[o+1]);if(a<-1||a>n||s<-1||s>i)throw\"Error.checkAndNudgePoints \";r=!1,-1==a?(e[o]=0,r=!0):a==n&&(e[o]=n-1,r=!0),-1==s?(e[o+1]=0,r=!0):s==i&&(e[o+1]=i-1,r=!0)}},r.sampleGrid3=function(t,e,n){for(var o=new i.a(e),a=new Array(e<<1),s=0;s<e;s++){for(var h=a.length,f=s+.5,w=0;w<h;w+=2)a[w]=.5+(w>>1),a[w+1]=f;n.transformPoints1(a),r.checkAndNudgePoints(t,a);try{for(var w=0;w<h;w+=2){t.data[Math.floor(a[w])+t.width*Math.floor(a[w+1])]&&o.set_Renamed(w>>1,s)}}catch(t){throw\"Error.checkAndNudgePoints\"}}return o},e.a=r},function(t,e,n){\"use strict\";function i(t){this.field=t}e.a=i;var r=n(3),o=n(4);i.prototype.decode=function(t,e){for(var n=new o.a(this.field,t),i=new Array(e),a=0;a<i.length;a++)i[a]=0;for(var s=!0,a=0;a<e;a++){var h=n.evaluateAt(this.field.exp(a));i[i.length-1-a]=h,0!=h&&(s=!1)}if(!s)for(var f=new o.a(this.field,i),w=this.runEuclideanAlgorithm(this.field.buildMonomial(e,1),f,e),u=w[0],l=w[1],c=this.findErrorLocations(u),d=this.findErrorMagnitudes(l,c,!1),a=0;a<c.length;a++){var p=t.length-1-this.field.log(c[a]);if(p<0)throw\"ReedSolomonException Bad error location\";t[p]=r.a.prototype.addOrSubtract(t[p],d[a])}},i.prototype.runEuclideanAlgorithm=function(t,e,n){if(t.Degree<e.Degree){var i=t;t=e,e=i}for(var r=t,o=e,a=this.field.One,s=this.field.Zero,h=this.field.Zero,f=this.field.One;o.Degree>=Math.floor(n/2);){var w=r,u=a,l=h;if(r=o,a=s,h=f,r.Zero)throw\"r_{i-1} was zero\";o=w;for(var c=this.field.Zero,d=r.getCoefficient(r.Degree),p=this.field.inverse(d);o.Degree>=r.Degree&&!o.Zero;){var g=o.Degree-r.Degree,v=this.field.multiply(o.getCoefficient(o.Degree),p);c=c.addOrSubtract(this.field.buildMonomial(g,v)),o=o.addOrSubtract(r.multiplyByMonomial(g,v))}s=c.multiply1(a).addOrSubtract(u),f=c.multiply1(h).addOrSubtract(l)}var m=f.getCoefficient(0);if(0==m)throw\"ReedSolomonException sigmaTilde(0) was zero\";var b=this.field.inverse(m);return[f.multiply2(b),o.multiply2(b)]},i.prototype.findErrorLocations=function(t){var e=t.Degree;if(1==e)return new Array(t.getCoefficient(1));for(var n=new Array(e),i=0,r=1;r<256&&i<e;r++)0==t.evaluateAt(r)&&(n[i]=this.field.inverse(r),i++);if(i!=e)throw\"Error locator degree does not match number of roots\";return n},i.prototype.findErrorMagnitudes=function(t,e,n){for(var i=e.length,o=new Array(i),a=0;a<i;a++){for(var s=this.field.inverse(e[a]),h=1,f=0;f<i;f++)a!=f&&(h=this.field.multiply(h,r.a.prototype.addOrSubtract(1,this.field.multiply(e[f],s))));o[a]=this.field.multiply(t.evaluateAt(s),this.field.inverse(h)),n&&(o[a]=this.field.multiply(o[a],s))}return o}},function(t,e,n){(function(t){var e=n(6).default,i=new e;i.callback=function(t,e){postMessage({result:e,err:t})},onmessage=function(t){var e=t.data;i.decode(e)}}).call(e,n(7)(t))}]);"
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+ /* eslint-env node */
+
+
+// SDP helpers.
+var SDPUtils = {};
+
+// Generate an alphanumeric identifier for cname or mids.
+// TODO: use UUIDs instead? https://gist.github.com/jed/982883
+SDPUtils.generateIdentifier = function() {
+  return Math.random().toString(36).substr(2, 10);
+};
+
+// The RTCP CNAME used by all peerconnections from the same JS.
+SDPUtils.localCName = SDPUtils.generateIdentifier();
+
+// Splits SDP into lines, dealing with both CRLF and LF.
+SDPUtils.splitLines = function(blob) {
+  return blob.trim().split('\n').map(function(line) {
+    return line.trim();
+  });
+};
+// Splits SDP into sessionpart and mediasections. Ensures CRLF.
+SDPUtils.splitSections = function(blob) {
+  var parts = blob.split('\nm=');
+  return parts.map(function(part, index) {
+    return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
+  });
+};
+
+// Returns lines that start with a certain prefix.
+SDPUtils.matchPrefix = function(blob, prefix) {
+  return SDPUtils.splitLines(blob).filter(function(line) {
+    return line.indexOf(prefix) === 0;
+  });
+};
+
+// Parses an ICE candidate line. Sample input:
+// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
+// rport 55996"
+SDPUtils.parseCandidate = function(line) {
+  var parts;
+  // Parse both variants.
+  if (line.indexOf('a=candidate:') === 0) {
+    parts = line.substring(12).split(' ');
+  } else {
+    parts = line.substring(10).split(' ');
+  }
+
+  var candidate = {
+    foundation: parts[0],
+    component: parts[1],
+    protocol: parts[2].toLowerCase(),
+    priority: parseInt(parts[3], 10),
+    ip: parts[4],
+    port: parseInt(parts[5], 10),
+    // skip parts[6] == 'typ'
+    type: parts[7]
+  };
+
+  for (var i = 8; i < parts.length; i += 2) {
+    switch (parts[i]) {
+      case 'raddr':
+        candidate.relatedAddress = parts[i + 1];
+        break;
+      case 'rport':
+        candidate.relatedPort = parseInt(parts[i + 1], 10);
+        break;
+      case 'tcptype':
+        candidate.tcpType = parts[i + 1];
+        break;
+      default: // extension handling, in particular ufrag
+        candidate[parts[i]] = parts[i + 1];
+        break;
+    }
+  }
+  return candidate;
+};
+
+// Translates a candidate object into SDP candidate attribute.
+SDPUtils.writeCandidate = function(candidate) {
+  var sdp = [];
+  sdp.push(candidate.foundation);
+  sdp.push(candidate.component);
+  sdp.push(candidate.protocol.toUpperCase());
+  sdp.push(candidate.priority);
+  sdp.push(candidate.ip);
+  sdp.push(candidate.port);
+
+  var type = candidate.type;
+  sdp.push('typ');
+  sdp.push(type);
+  if (type !== 'host' && candidate.relatedAddress &&
+      candidate.relatedPort) {
+    sdp.push('raddr');
+    sdp.push(candidate.relatedAddress); // was: relAddr
+    sdp.push('rport');
+    sdp.push(candidate.relatedPort); // was: relPort
+  }
+  if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
+    sdp.push('tcptype');
+    sdp.push(candidate.tcpType);
+  }
+  return 'candidate:' + sdp.join(' ');
+};
+
+// Parses an ice-options line, returns an array of option tags.
+// a=ice-options:foo bar
+SDPUtils.parseIceOptions = function(line) {
+  return line.substr(14).split(' ');
+}
+
+// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
+// a=rtpmap:111 opus/48000/2
+SDPUtils.parseRtpMap = function(line) {
+  var parts = line.substr(9).split(' ');
+  var parsed = {
+    payloadType: parseInt(parts.shift(), 10) // was: id
+  };
+
+  parts = parts[0].split('/');
+
+  parsed.name = parts[0];
+  parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
+  // was: channels
+  parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
+  return parsed;
+};
+
+// Generate an a=rtpmap line from RTCRtpCodecCapability or
+// RTCRtpCodecParameters.
+SDPUtils.writeRtpMap = function(codec) {
+  var pt = codec.payloadType;
+  if (codec.preferredPayloadType !== undefined) {
+    pt = codec.preferredPayloadType;
+  }
+  return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
+      (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
+};
+
+// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
+// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
+// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
+SDPUtils.parseExtmap = function(line) {
+  var parts = line.substr(9).split(' ');
+  return {
+    id: parseInt(parts[0], 10),
+    direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
+    uri: parts[1]
+  };
+};
+
+// Generates a=extmap line from RTCRtpHeaderExtensionParameters or
+// RTCRtpHeaderExtension.
+SDPUtils.writeExtmap = function(headerExtension) {
+  return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
+      (headerExtension.direction && headerExtension.direction !== 'sendrecv'
+          ? '/' + headerExtension.direction
+          : '') +
+      ' ' + headerExtension.uri + '\r\n';
+};
+
+// Parses an ftmp line, returns dictionary. Sample input:
+// a=fmtp:96 vbr=on;cng=on
+// Also deals with vbr=on; cng=on
+SDPUtils.parseFmtp = function(line) {
+  var parsed = {};
+  var kv;
+  var parts = line.substr(line.indexOf(' ') + 1).split(';');
+  for (var j = 0; j < parts.length; j++) {
+    kv = parts[j].trim().split('=');
+    parsed[kv[0].trim()] = kv[1];
+  }
+  return parsed;
+};
+
+// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
+SDPUtils.writeFmtp = function(codec) {
+  var line = '';
+  var pt = codec.payloadType;
+  if (codec.preferredPayloadType !== undefined) {
+    pt = codec.preferredPayloadType;
+  }
+  if (codec.parameters && Object.keys(codec.parameters).length) {
+    var params = [];
+    Object.keys(codec.parameters).forEach(function(param) {
+      params.push(param + '=' + codec.parameters[param]);
+    });
+    line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
+  }
+  return line;
+};
+
+// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
+// a=rtcp-fb:98 nack rpsi
+SDPUtils.parseRtcpFb = function(line) {
+  var parts = line.substr(line.indexOf(' ') + 1).split(' ');
+  return {
+    type: parts.shift(),
+    parameter: parts.join(' ')
+  };
+};
+// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
+SDPUtils.writeRtcpFb = function(codec) {
+  var lines = '';
+  var pt = codec.payloadType;
+  if (codec.preferredPayloadType !== undefined) {
+    pt = codec.preferredPayloadType;
+  }
+  if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
+    // FIXME: special handling for trr-int?
+    codec.rtcpFeedback.forEach(function(fb) {
+      lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
+      (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
+          '\r\n';
+    });
+  }
+  return lines;
+};
+
+// Parses an RFC 5576 ssrc media attribute. Sample input:
+// a=ssrc:3735928559 cname:something
+SDPUtils.parseSsrcMedia = function(line) {
+  var sp = line.indexOf(' ');
+  var parts = {
+    ssrc: parseInt(line.substr(7, sp - 7), 10)
+  };
+  var colon = line.indexOf(':', sp);
+  if (colon > -1) {
+    parts.attribute = line.substr(sp + 1, colon - sp - 1);
+    parts.value = line.substr(colon + 1);
+  } else {
+    parts.attribute = line.substr(sp + 1);
+  }
+  return parts;
+};
+
+// Extracts the MID (RFC 5888) from a media section.
+// returns the MID or undefined if no mid line was found.
+SDPUtils.getMid = function(mediaSection) {
+  var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
+  if (mid) {
+    return mid.substr(6);
+  }
+}
+
+SDPUtils.parseFingerprint = function(line) {
+  var parts = line.substr(14).split(' ');
+  return {
+    algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
+    value: parts[1]
+  };
+};
+
+// Extracts DTLS parameters from SDP media section or sessionpart.
+// FIXME: for consistency with other functions this should only
+//   get the fingerprint line as input. See also getIceParameters.
+SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
+  var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
+      'a=fingerprint:');
+  // Note: a=setup line is ignored since we use the 'auto' role.
+  // Note2: 'algorithm' is not case sensitive except in Edge.
+  return {
+    role: 'auto',
+    fingerprints: lines.map(SDPUtils.parseFingerprint)
+  };
+};
+
+// Serializes DTLS parameters to SDP.
+SDPUtils.writeDtlsParameters = function(params, setupType) {
+  var sdp = 'a=setup:' + setupType + '\r\n';
+  params.fingerprints.forEach(function(fp) {
+    sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
+  });
+  return sdp;
+};
+// Parses ICE information from SDP media section or sessionpart.
+// FIXME: for consistency with other functions this should only
+//   get the ice-ufrag and ice-pwd lines as input.
+SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
+  var lines = SDPUtils.splitLines(mediaSection);
+  // Search in session part, too.
+  lines = lines.concat(SDPUtils.splitLines(sessionpart));
+  var iceParameters = {
+    usernameFragment: lines.filter(function(line) {
+      return line.indexOf('a=ice-ufrag:') === 0;
+    })[0].substr(12),
+    password: lines.filter(function(line) {
+      return line.indexOf('a=ice-pwd:') === 0;
+    })[0].substr(10)
+  };
+  return iceParameters;
+};
+
+// Serializes ICE parameters to SDP.
+SDPUtils.writeIceParameters = function(params) {
+  return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
+      'a=ice-pwd:' + params.password + '\r\n';
+};
+
+// Parses the SDP media section and returns RTCRtpParameters.
+SDPUtils.parseRtpParameters = function(mediaSection) {
+  var description = {
+    codecs: [],
+    headerExtensions: [],
+    fecMechanisms: [],
+    rtcp: []
+  };
+  var lines = SDPUtils.splitLines(mediaSection);
+  var mline = lines[0].split(' ');
+  for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
+    var pt = mline[i];
+    var rtpmapline = SDPUtils.matchPrefix(
+        mediaSection, 'a=rtpmap:' + pt + ' ')[0];
+    if (rtpmapline) {
+      var codec = SDPUtils.parseRtpMap(rtpmapline);
+      var fmtps = SDPUtils.matchPrefix(
+          mediaSection, 'a=fmtp:' + pt + ' ');
+      // Only the first a=fmtp:<pt> is considered.
+      codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
+      codec.rtcpFeedback = SDPUtils.matchPrefix(
+          mediaSection, 'a=rtcp-fb:' + pt + ' ')
+        .map(SDPUtils.parseRtcpFb);
+      description.codecs.push(codec);
+      // parse FEC mechanisms from rtpmap lines.
+      switch (codec.name.toUpperCase()) {
+        case 'RED':
+        case 'ULPFEC':
+          description.fecMechanisms.push(codec.name.toUpperCase());
+          break;
+        default: // only RED and ULPFEC are recognized as FEC mechanisms.
+          break;
+      }
+    }
+  }
+  SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
+    description.headerExtensions.push(SDPUtils.parseExtmap(line));
+  });
+  // FIXME: parse rtcp.
+  return description;
+};
+
+// Generates parts of the SDP media section describing the capabilities /
+// parameters.
+SDPUtils.writeRtpDescription = function(kind, caps) {
+  var sdp = '';
+
+  // Build the mline.
+  sdp += 'm=' + kind + ' ';
+  sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
+  sdp += ' UDP/TLS/RTP/SAVPF ';
+  sdp += caps.codecs.map(function(codec) {
+    if (codec.preferredPayloadType !== undefined) {
+      return codec.preferredPayloadType;
+    }
+    return codec.payloadType;
+  }).join(' ') + '\r\n';
+
+  sdp += 'c=IN IP4 0.0.0.0\r\n';
+  sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
+
+  // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
+  caps.codecs.forEach(function(codec) {
+    sdp += SDPUtils.writeRtpMap(codec);
+    sdp += SDPUtils.writeFmtp(codec);
+    sdp += SDPUtils.writeRtcpFb(codec);
+  });
+  var maxptime = 0;
+  caps.codecs.forEach(function(codec) {
+    if (codec.maxptime > maxptime) {
+      maxptime = codec.maxptime;
+    }
+  });
+  if (maxptime > 0) {
+    sdp += 'a=maxptime:' + maxptime + '\r\n';
+  }
+  sdp += 'a=rtcp-mux\r\n';
+
+  caps.headerExtensions.forEach(function(extension) {
+    sdp += SDPUtils.writeExtmap(extension);
+  });
+  // FIXME: write fecMechanisms.
+  return sdp;
+};
+
+// Parses the SDP media section and returns an array of
+// RTCRtpEncodingParameters.
+SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
+  var encodingParameters = [];
+  var description = SDPUtils.parseRtpParameters(mediaSection);
+  var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
+  var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
+
+  // filter a=ssrc:... cname:, ignore PlanB-msid
+  var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+  .map(function(line) {
+    return SDPUtils.parseSsrcMedia(line);
+  })
+  .filter(function(parts) {
+    return parts.attribute === 'cname';
+  });
+  var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
+  var secondarySsrc;
+
+  var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
+  .map(function(line) {
+    var parts = line.split(' ');
+    parts.shift();
+    return parts.map(function(part) {
+      return parseInt(part, 10);
+    });
+  });
+  if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
+    secondarySsrc = flows[0][1];
+  }
+
+  description.codecs.forEach(function(codec) {
+    if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
+      var encParam = {
+        ssrc: primarySsrc,
+        codecPayloadType: parseInt(codec.parameters.apt, 10),
+        rtx: {
+          ssrc: secondarySsrc
+        }
+      };
+      encodingParameters.push(encParam);
+      if (hasRed) {
+        encParam = JSON.parse(JSON.stringify(encParam));
+        encParam.fec = {
+          ssrc: secondarySsrc,
+          mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
+        };
+        encodingParameters.push(encParam);
+      }
+    }
+  });
+  if (encodingParameters.length === 0 && primarySsrc) {
+    encodingParameters.push({
+      ssrc: primarySsrc
+    });
+  }
+
+  // we support both b=AS and b=TIAS but interpret AS as TIAS.
+  var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
+  if (bandwidth.length) {
+    if (bandwidth[0].indexOf('b=TIAS:') === 0) {
+      bandwidth = parseInt(bandwidth[0].substr(7), 10);
+    } else if (bandwidth[0].indexOf('b=AS:') === 0) {
+      bandwidth = parseInt(bandwidth[0].substr(5), 10);
+    }
+    encodingParameters.forEach(function(params) {
+      params.maxBitrate = bandwidth;
+    });
+  }
+  return encodingParameters;
+};
+
+// parses http://draft.ortc.org/#rtcrtcpparameters*
+SDPUtils.parseRtcpParameters = function(mediaSection) {
+  var rtcpParameters = {};
+
+  var cname;
+  // Gets the first SSRC. Note that with RTX there might be multiple
+  // SSRCs.
+  var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+      .map(function(line) {
+        return SDPUtils.parseSsrcMedia(line);
+      })
+      .filter(function(obj) {
+        return obj.attribute === 'cname';
+      })[0];
+  if (remoteSsrc) {
+    rtcpParameters.cname = remoteSsrc.value;
+    rtcpParameters.ssrc = remoteSsrc.ssrc;
+  }
+
+  // Edge uses the compound attribute instead of reducedSize
+  // compound is !reducedSize
+  var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
+  rtcpParameters.reducedSize = rsize.length > 0;
+  rtcpParameters.compound = rsize.length === 0;
+
+  // parses the rtcp-mux attrіbute.
+  // Note that Edge does not support unmuxed RTCP.
+  var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
+  rtcpParameters.mux = mux.length > 0;
+
+  return rtcpParameters;
+};
+
+// parses either a=msid: or a=ssrc:... msid lines and returns
+// the id of the MediaStream and MediaStreamTrack.
+SDPUtils.parseMsid = function(mediaSection) {
+  var parts;
+  var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
+  if (spec.length === 1) {
+    parts = spec[0].substr(7).split(' ');
+    return {stream: parts[0], track: parts[1]};
+  }
+  var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
+  .map(function(line) {
+    return SDPUtils.parseSsrcMedia(line);
+  })
+  .filter(function(parts) {
+    return parts.attribute === 'msid';
+  });
+  if (planB.length > 0) {
+    parts = planB[0].value.split(' ');
+    return {stream: parts[0], track: parts[1]};
+  }
+};
+
+SDPUtils.writeSessionBoilerplate = function() {
+  // FIXME: sess-id should be an NTP timestamp.
+  return 'v=0\r\n' +
+      'o=thisisadapterortc 8169639915646943137 2 IN IP4 127.0.0.1\r\n' +
+      's=-\r\n' +
+      't=0 0\r\n';
+};
+
+SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
+  var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
+
+  // Map ICE parameters (ufrag, pwd) to SDP.
+  sdp += SDPUtils.writeIceParameters(
+      transceiver.iceGatherer.getLocalParameters());
+
+  // Map DTLS parameters to SDP.
+  sdp += SDPUtils.writeDtlsParameters(
+      transceiver.dtlsTransport.getLocalParameters(),
+      type === 'offer' ? 'actpass' : 'active');
+
+  sdp += 'a=mid:' + transceiver.mid + '\r\n';
+
+  if (transceiver.direction) {
+    sdp += 'a=' + transceiver.direction + '\r\n';
+  } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
+    sdp += 'a=sendrecv\r\n';
+  } else if (transceiver.rtpSender) {
+    sdp += 'a=sendonly\r\n';
+  } else if (transceiver.rtpReceiver) {
+    sdp += 'a=recvonly\r\n';
+  } else {
+    sdp += 'a=inactive\r\n';
+  }
+
+  if (transceiver.rtpSender) {
+    // spec.
+    var msid = 'msid:' + stream.id + ' ' +
+        transceiver.rtpSender.track.id + '\r\n';
+    sdp += 'a=' + msid;
+
+    // for Chrome.
+    sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
+        ' ' + msid;
+    if (transceiver.sendEncodingParameters[0].rtx) {
+      sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
+          ' ' + msid;
+      sdp += 'a=ssrc-group:FID ' +
+          transceiver.sendEncodingParameters[0].ssrc + ' ' +
+          transceiver.sendEncodingParameters[0].rtx.ssrc +
+          '\r\n';
+    }
+  }
+  // FIXME: this should be written by writeRtpDescription.
+  sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
+      ' cname:' + SDPUtils.localCName + '\r\n';
+  if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
+    sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
+        ' cname:' + SDPUtils.localCName + '\r\n';
+  }
+  return sdp;
+};
+
+// Gets the direction from the mediaSection or the sessionpart.
+SDPUtils.getDirection = function(mediaSection, sessionpart) {
+  // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
+  var lines = SDPUtils.splitLines(mediaSection);
+  for (var i = 0; i < lines.length; i++) {
+    switch (lines[i]) {
+      case 'a=sendrecv':
+      case 'a=sendonly':
+      case 'a=recvonly':
+      case 'a=inactive':
+        return lines[i].substr(2);
+      default:
+        // FIXME: What should happen here?
+    }
+  }
+  if (sessionpart) {
+    return SDPUtils.getDirection(sessionpart);
+  }
+  return 'sendrecv';
+};
+
+SDPUtils.getKind = function(mediaSection) {
+  var lines = SDPUtils.splitLines(mediaSection);
+  var mline = lines[0].split(' ');
+  return mline[0].substr(2);
+};
+
+SDPUtils.isRejected = function(mediaSection) {
+  return mediaSection.split(' ', 2)[1] === '0';
+};
+
+// Expose public methods.
+module.exports = SDPUtils;
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+
+// Shimming starts here.
+(function() {
+  // Utils.
+  var utils = __webpack_require__(0);
+  var logging = utils.log;
+  var browserDetails = utils.browserDetails;
+  // Export to the adapter global object visible in the browser.
+  module.exports.browserDetails = browserDetails;
+  module.exports.extractVersion = utils.extractVersion;
+  module.exports.disableLog = utils.disableLog;
+
+  // Uncomment the line below if you want logging to occur, including logging
+  // for the switch statement below. Can also be turned on in the browser via
+  // adapter.disableLog(false), but then logging from the switch statement below
+  // will not appear.
+  // require('./utils').disableLog(false);
+
+  // Browser shims.
+  var chromeShim = __webpack_require__(9) || null;
+  var edgeShim = __webpack_require__(11) || null;
+  var firefoxShim = __webpack_require__(14) || null;
+  var safariShim = __webpack_require__(16) || null;
+
+  // Shim browser if found.
+  switch (browserDetails.browser) {
+    case 'chrome':
+      if (!chromeShim || !chromeShim.shimPeerConnection) {
+        logging('Chrome shim is not included in this adapter release.');
+        return;
+      }
+      logging('adapter.js shimming chrome.');
+      // Export to the adapter global object visible in the browser.
+      module.exports.browserShim = chromeShim;
+
+      chromeShim.shimGetUserMedia();
+      chromeShim.shimMediaStream();
+      utils.shimCreateObjectURL();
+      chromeShim.shimSourceObject();
+      chromeShim.shimPeerConnection();
+      chromeShim.shimOnTrack();
+      chromeShim.shimGetSendersWithDtmf();
+      break;
+    case 'firefox':
+      if (!firefoxShim || !firefoxShim.shimPeerConnection) {
+        logging('Firefox shim is not included in this adapter release.');
+        return;
+      }
+      logging('adapter.js shimming firefox.');
+      // Export to the adapter global object visible in the browser.
+      module.exports.browserShim = firefoxShim;
+
+      firefoxShim.shimGetUserMedia();
+      utils.shimCreateObjectURL();
+      firefoxShim.shimSourceObject();
+      firefoxShim.shimPeerConnection();
+      firefoxShim.shimOnTrack();
+      break;
+    case 'edge':
+      if (!edgeShim || !edgeShim.shimPeerConnection) {
+        logging('MS edge shim is not included in this adapter release.');
+        return;
+      }
+      logging('adapter.js shimming edge.');
+      // Export to the adapter global object visible in the browser.
+      module.exports.browserShim = edgeShim;
+
+      edgeShim.shimGetUserMedia();
+      utils.shimCreateObjectURL();
+      edgeShim.shimPeerConnection();
+      edgeShim.shimReplaceTrack();
+      break;
+    case 'safari':
+      if (!safariShim) {
+        logging('Safari shim is not included in this adapter release.');
+        return;
+      }
+      logging('adapter.js shimming safari.');
+      // Export to the adapter global object visible in the browser.
+      module.exports.browserShim = safariShim;
+
+      safariShim.shimCallbacksAPI();
+      safariShim.shimAddStream();
+      safariShim.shimOnAddStream();
+      safariShim.shimGetUserMedia();
+      break;
+    default:
+      logging('Unsupported browser!');
+  }
+})();
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+var chromeShim = {
+  shimMediaStream: function() {
+    window.MediaStream = window.MediaStream || window.webkitMediaStream;
+  },
+
+  shimOnTrack: function() {
+    if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
+        window.RTCPeerConnection.prototype)) {
+      Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
+        get: function() {
+          return this._ontrack;
+        },
+        set: function(f) {
+          var self = this;
+          if (this._ontrack) {
+            this.removeEventListener('track', this._ontrack);
+            this.removeEventListener('addstream', this._ontrackpoly);
+          }
+          this.addEventListener('track', this._ontrack = f);
+          this.addEventListener('addstream', this._ontrackpoly = function(e) {
+            // onaddstream does not fire when a track is added to an existing
+            // stream. But stream.onaddtrack is implemented so we use that.
+            e.stream.addEventListener('addtrack', function(te) {
+              var receiver;
+              if (RTCPeerConnection.prototype.getReceivers) {
+                receiver = self.getReceivers().find(function(r) {
+                  return r.track.id === te.track.id;
+                });
+              } else {
+                receiver = {track: te.track};
+              }
+
+              var event = new Event('track');
+              event.track = te.track;
+              event.receiver = receiver;
+              event.streams = [e.stream];
+              self.dispatchEvent(event);
+            });
+            e.stream.getTracks().forEach(function(track) {
+              var receiver;
+              if (RTCPeerConnection.prototype.getReceivers) {
+                receiver = self.getReceivers().find(function(r) {
+                  return r.track.id === track.id;
+                });
+              } else {
+                receiver = {track: track};
+              }
+              var event = new Event('track');
+              event.track = track;
+              event.receiver = receiver;
+              event.streams = [e.stream];
+              this.dispatchEvent(event);
+            }.bind(this));
+          }.bind(this));
+        }
+      });
+    }
+  },
+
+  shimGetSendersWithDtmf: function() {
+    if (typeof window === 'object' && window.RTCPeerConnection &&
+        !('getSenders' in RTCPeerConnection.prototype) &&
+        'createDTMFSender' in RTCPeerConnection.prototype) {
+      RTCPeerConnection.prototype.getSenders = function() {
+        return this._senders || [];
+      };
+      var origAddStream = RTCPeerConnection.prototype.addStream;
+      var origRemoveStream = RTCPeerConnection.prototype.removeStream;
+
+      if (!RTCPeerConnection.prototype.addTrack) {
+        RTCPeerConnection.prototype.addTrack = function(track, stream) {
+          var pc = this;
+          if (pc.signalingState === 'closed') {
+            throw new DOMException(
+              'The RTCPeerConnection\'s signalingState is \'closed\'.',
+              'InvalidStateError');
+          }
+          var streams = [].slice.call(arguments, 1);
+          if (streams.length !== 1 ||
+              !streams[0].getTracks().find(function(t) {
+                return t === track;
+              })) {
+            // this is not fully correct but all we can manage without
+            // [[associated MediaStreams]] internal slot.
+            throw new DOMException(
+              'The adapter.js addTrack polyfill only supports a single ' +
+              ' stream which is associated with the specified track.',
+              'NotSupportedError');
+          }
+
+          pc._senders = pc._senders || [];
+          var alreadyExists = pc._senders.find(function(t) {
+            return t.track === track;
+          });
+          if (alreadyExists) {
+            throw new DOMException('Track already exists.',
+                'InvalidAccessError');
+          }
+
+          pc._streams = pc._streams || {};
+          var oldStream = pc._streams[stream.id];
+          if (oldStream) {
+            oldStream.addTrack(track);
+            pc.removeStream(oldStream);
+            pc.addStream(oldStream);
+          } else {
+            var newStream = new MediaStream([track]);
+            pc._streams[stream.id] = newStream;
+            pc.addStream(newStream);
+          }
+
+          var sender = {
+            track: track,
+            get dtmf() {
+              if (this._dtmf === undefined) {
+                if (track.kind === 'audio') {
+                  this._dtmf = pc.createDTMFSender(track);
+                } else {
+                  this._dtmf = null;
+                }
+              }
+              return this._dtmf;
+            }
+          };
+          pc._senders.push(sender);
+          return sender;
+        };
+      }
+      RTCPeerConnection.prototype.addStream = function(stream) {
+        var pc = this;
+        pc._senders = pc._senders || [];
+        origAddStream.apply(pc, [stream]);
+        stream.getTracks().forEach(function(track) {
+          pc._senders.push({
+            track: track,
+            get dtmf() {
+              if (this._dtmf === undefined) {
+                if (track.kind === 'audio') {
+                  this._dtmf = pc.createDTMFSender(track);
+                } else {
+                  this._dtmf = null;
+                }
+              }
+              return this._dtmf;
+            }
+          });
+        });
+      };
+
+      RTCPeerConnection.prototype.removeStream = function(stream) {
+        var pc = this;
+        pc._senders = pc._senders || [];
+        origRemoveStream.apply(pc, [stream]);
+        stream.getTracks().forEach(function(track) {
+          var sender = pc._senders.find(function(s) {
+            return s.track === track;
+          });
+          if (sender) {
+            pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
+          }
+        });
+      };
+    }
+  },
+
+  shimSourceObject: function() {
+    if (typeof window === 'object') {
+      if (window.HTMLMediaElement &&
+        !('srcObject' in window.HTMLMediaElement.prototype)) {
+        // Shim the srcObject property, once, when HTMLMediaElement is found.
+        Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+          get: function() {
+            return this._srcObject;
+          },
+          set: function(stream) {
+            var self = this;
+            // Use _srcObject as a private property for this shim
+            this._srcObject = stream;
+            if (this.src) {
+              URL.revokeObjectURL(this.src);
+            }
+
+            if (!stream) {
+              this.src = '';
+              return undefined;
+            }
+            this.src = URL.createObjectURL(stream);
+            // We need to recreate the blob url when a track is added or
+            // removed. Doing it manually since we want to avoid a recursion.
+            stream.addEventListener('addtrack', function() {
+              if (self.src) {
+                URL.revokeObjectURL(self.src);
+              }
+              self.src = URL.createObjectURL(stream);
+            });
+            stream.addEventListener('removetrack', function() {
+              if (self.src) {
+                URL.revokeObjectURL(self.src);
+              }
+              self.src = URL.createObjectURL(stream);
+            });
+          }
+        });
+      }
+    }
+  },
+
+  shimPeerConnection: function() {
+    // The RTCPeerConnection object.
+    if (!window.RTCPeerConnection) {
+      window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+        // Translate iceTransportPolicy to iceTransports,
+        // see https://code.google.com/p/webrtc/issues/detail?id=4869
+        // this was fixed in M56 along with unprefixing RTCPeerConnection.
+        logging('PeerConnection');
+        if (pcConfig && pcConfig.iceTransportPolicy) {
+          pcConfig.iceTransports = pcConfig.iceTransportPolicy;
+        }
+
+        return new webkitRTCPeerConnection(pcConfig, pcConstraints);
+      };
+      window.RTCPeerConnection.prototype = webkitRTCPeerConnection.prototype;
+      // wrap static methods. Currently just generateCertificate.
+      if (webkitRTCPeerConnection.generateCertificate) {
+        Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+          get: function() {
+            return webkitRTCPeerConnection.generateCertificate;
+          }
+        });
+      }
+    } else {
+      // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
+      var OrigPeerConnection = RTCPeerConnection;
+      window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+        if (pcConfig && pcConfig.iceServers) {
+          var newIceServers = [];
+          for (var i = 0; i < pcConfig.iceServers.length; i++) {
+            var server = pcConfig.iceServers[i];
+            if (!server.hasOwnProperty('urls') &&
+                server.hasOwnProperty('url')) {
+              console.warn('RTCIceServer.url is deprecated! Use urls instead.');
+              server = JSON.parse(JSON.stringify(server));
+              server.urls = server.url;
+              newIceServers.push(server);
+            } else {
+              newIceServers.push(pcConfig.iceServers[i]);
+            }
+          }
+          pcConfig.iceServers = newIceServers;
+        }
+        return new OrigPeerConnection(pcConfig, pcConstraints);
+      };
+      window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
+      // wrap static methods. Currently just generateCertificate.
+      Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+        get: function() {
+          return OrigPeerConnection.generateCertificate;
+        }
+      });
+    }
+
+    var origGetStats = RTCPeerConnection.prototype.getStats;
+    RTCPeerConnection.prototype.getStats = function(selector,
+        successCallback, errorCallback) {
+      var self = this;
+      var args = arguments;
+
+      // If selector is a function then we are in the old style stats so just
+      // pass back the original getStats format to avoid breaking old users.
+      if (arguments.length > 0 && typeof selector === 'function') {
+        return origGetStats.apply(this, arguments);
+      }
+
+      // When spec-style getStats is supported, return those when called with
+      // either no arguments or the selector argument is null.
+      if (origGetStats.length === 0 && (arguments.length === 0 ||
+          typeof arguments[0] !== 'function')) {
+        return origGetStats.apply(this, []);
+      }
+
+      var fixChromeStats_ = function(response) {
+        var standardReport = {};
+        var reports = response.result();
+        reports.forEach(function(report) {
+          var standardStats = {
+            id: report.id,
+            timestamp: report.timestamp,
+            type: {
+              localcandidate: 'local-candidate',
+              remotecandidate: 'remote-candidate'
+            }[report.type] || report.type
+          };
+          report.names().forEach(function(name) {
+            standardStats[name] = report.stat(name);
+          });
+          standardReport[standardStats.id] = standardStats;
+        });
+
+        return standardReport;
+      };
+
+      // shim getStats with maplike support
+      var makeMapStats = function(stats) {
+        return new Map(Object.keys(stats).map(function(key) {
+          return [key, stats[key]];
+        }));
+      };
+
+      if (arguments.length >= 2) {
+        var successCallbackWrapper_ = function(response) {
+          args[1](makeMapStats(fixChromeStats_(response)));
+        };
+
+        return origGetStats.apply(this, [successCallbackWrapper_,
+          arguments[0]]);
+      }
+
+      // promise-support
+      return new Promise(function(resolve, reject) {
+        origGetStats.apply(self, [
+          function(response) {
+            resolve(makeMapStats(fixChromeStats_(response)));
+          }, reject]);
+      }).then(successCallback, errorCallback);
+    };
+
+    // add promise support -- natively available in Chrome 51
+    if (browserDetails.version < 51) {
+      ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+          .forEach(function(method) {
+            var nativeMethod = RTCPeerConnection.prototype[method];
+            RTCPeerConnection.prototype[method] = function() {
+              var args = arguments;
+              var self = this;
+              var promise = new Promise(function(resolve, reject) {
+                nativeMethod.apply(self, [args[0], resolve, reject]);
+              });
+              if (args.length < 2) {
+                return promise;
+              }
+              return promise.then(function() {
+                args[1].apply(null, []);
+              },
+              function(err) {
+                if (args.length >= 3) {
+                  args[2].apply(null, [err]);
+                }
+              });
+            };
+          });
+    }
+
+    // promise support for createOffer and createAnswer. Available (without
+    // bugs) since M52: crbug/619289
+    if (browserDetails.version < 52) {
+      ['createOffer', 'createAnswer'].forEach(function(method) {
+        var nativeMethod = RTCPeerConnection.prototype[method];
+        RTCPeerConnection.prototype[method] = function() {
+          var self = this;
+          if (arguments.length < 1 || (arguments.length === 1 &&
+              typeof arguments[0] === 'object')) {
+            var opts = arguments.length === 1 ? arguments[0] : undefined;
+            return new Promise(function(resolve, reject) {
+              nativeMethod.apply(self, [resolve, reject, opts]);
+            });
+          }
+          return nativeMethod.apply(this, arguments);
+        };
+      });
+    }
+
+    // shim implicit creation of RTCSessionDescription/RTCIceCandidate
+    ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+        .forEach(function(method) {
+          var nativeMethod = RTCPeerConnection.prototype[method];
+          RTCPeerConnection.prototype[method] = function() {
+            arguments[0] = new ((method === 'addIceCandidate') ?
+                RTCIceCandidate : RTCSessionDescription)(arguments[0]);
+            return nativeMethod.apply(this, arguments);
+          };
+        });
+
+    // support for addIceCandidate(null or undefined)
+    var nativeAddIceCandidate =
+        RTCPeerConnection.prototype.addIceCandidate;
+    RTCPeerConnection.prototype.addIceCandidate = function() {
+      if (!arguments[0]) {
+        if (arguments[1]) {
+          arguments[1].apply(null);
+        }
+        return Promise.resolve();
+      }
+      return nativeAddIceCandidate.apply(this, arguments);
+    };
+  }
+};
+
+
+// Expose public methods.
+module.exports = {
+  shimMediaStream: chromeShim.shimMediaStream,
+  shimOnTrack: chromeShim.shimOnTrack,
+  shimGetSendersWithDtmf: chromeShim.shimGetSendersWithDtmf,
+  shimSourceObject: chromeShim.shimSourceObject,
+  shimPeerConnection: chromeShim.shimPeerConnection,
+  shimGetUserMedia: __webpack_require__(10)
+};
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+// Expose public methods.
+module.exports = function() {
+  var constraintsToChrome_ = function(c) {
+    if (typeof c !== 'object' || c.mandatory || c.optional) {
+      return c;
+    }
+    var cc = {};
+    Object.keys(c).forEach(function(key) {
+      if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+        return;
+      }
+      var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
+      if (r.exact !== undefined && typeof r.exact === 'number') {
+        r.min = r.max = r.exact;
+      }
+      var oldname_ = function(prefix, name) {
+        if (prefix) {
+          return prefix + name.charAt(0).toUpperCase() + name.slice(1);
+        }
+        return (name === 'deviceId') ? 'sourceId' : name;
+      };
+      if (r.ideal !== undefined) {
+        cc.optional = cc.optional || [];
+        var oc = {};
+        if (typeof r.ideal === 'number') {
+          oc[oldname_('min', key)] = r.ideal;
+          cc.optional.push(oc);
+          oc = {};
+          oc[oldname_('max', key)] = r.ideal;
+          cc.optional.push(oc);
+        } else {
+          oc[oldname_('', key)] = r.ideal;
+          cc.optional.push(oc);
+        }
+      }
+      if (r.exact !== undefined && typeof r.exact !== 'number') {
+        cc.mandatory = cc.mandatory || {};
+        cc.mandatory[oldname_('', key)] = r.exact;
+      } else {
+        ['min', 'max'].forEach(function(mix) {
+          if (r[mix] !== undefined) {
+            cc.mandatory = cc.mandatory || {};
+            cc.mandatory[oldname_(mix, key)] = r[mix];
+          }
+        });
+      }
+    });
+    if (c.advanced) {
+      cc.optional = (cc.optional || []).concat(c.advanced);
+    }
+    return cc;
+  };
+
+  var shimConstraints_ = function(constraints, func) {
+    constraints = JSON.parse(JSON.stringify(constraints));
+    if (constraints && constraints.audio) {
+      constraints.audio = constraintsToChrome_(constraints.audio);
+    }
+    if (constraints && typeof constraints.video === 'object') {
+      // Shim facingMode for mobile & surface pro.
+      var face = constraints.video.facingMode;
+      face = face && ((typeof face === 'object') ? face : {ideal: face});
+      var getSupportedFacingModeLies = browserDetails.version < 61;
+
+      if ((face && (face.exact === 'user' || face.exact === 'environment' ||
+                    face.ideal === 'user' || face.ideal === 'environment')) &&
+          !(navigator.mediaDevices.getSupportedConstraints &&
+            navigator.mediaDevices.getSupportedConstraints().facingMode &&
+            !getSupportedFacingModeLies)) {
+        delete constraints.video.facingMode;
+        var matches;
+        if (face.exact === 'environment' || face.ideal === 'environment') {
+          matches = ['back', 'rear'];
+        } else if (face.exact === 'user' || face.ideal === 'user') {
+          matches = ['front'];
+        }
+        if (matches) {
+          // Look for matches in label, or use last cam for back (typical).
+          return navigator.mediaDevices.enumerateDevices()
+          .then(function(devices) {
+            devices = devices.filter(function(d) {
+              return d.kind === 'videoinput';
+            });
+            var dev = devices.find(function(d) {
+              return matches.some(function(match) {
+                return d.label.toLowerCase().indexOf(match) !== -1;
+              });
+            });
+            if (!dev && devices.length && matches.indexOf('back') !== -1) {
+              dev = devices[devices.length - 1]; // more likely the back cam
+            }
+            if (dev) {
+              constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
+                                                        {ideal: dev.deviceId};
+            }
+            constraints.video = constraintsToChrome_(constraints.video);
+            logging('chrome: ' + JSON.stringify(constraints));
+            return func(constraints);
+          });
+        }
+      }
+      constraints.video = constraintsToChrome_(constraints.video);
+    }
+    logging('chrome: ' + JSON.stringify(constraints));
+    return func(constraints);
+  };
+
+  var shimError_ = function(e) {
+    return {
+      name: {
+        ConstraintNotSatisfiedError: 'OverconstrainedError',
+        PermissionDeniedError: 'NotAllowedError',
+        TrackStartError: 'NotReadableError'
+      }[e.name] || e.name,
+      message: e.message,
+      constraint: e.constraintName,
+      toString: function() {
+        return this.name + (this.message && ': ') + this.message;
+      }
+    };
+  };
+
+  var getUserMedia_ = function(constraints, onSuccess, onError) {
+    shimConstraints_(constraints, function(c) {
+      navigator.webkitGetUserMedia(c, onSuccess, function(e) {
+        onError(shimError_(e));
+      });
+    });
+  };
+
+  navigator.getUserMedia = getUserMedia_;
+
+  // Returns the result of getUserMedia as a Promise.
+  var getUserMediaPromise_ = function(constraints) {
+    return new Promise(function(resolve, reject) {
+      navigator.getUserMedia(constraints, resolve, reject);
+    });
+  };
+
+  if (!navigator.mediaDevices) {
+    navigator.mediaDevices = {
+      getUserMedia: getUserMediaPromise_,
+      enumerateDevices: function() {
+        return new Promise(function(resolve) {
+          var kinds = {audio: 'audioinput', video: 'videoinput'};
+          return MediaStreamTrack.getSources(function(devices) {
+            resolve(devices.map(function(device) {
+              return {label: device.label,
+                kind: kinds[device.kind],
+                deviceId: device.id,
+                groupId: ''};
+            }));
+          });
+        });
+      },
+      getSupportedConstraints: function() {
+        return {
+          deviceId: true, echoCancellation: true, facingMode: true,
+          frameRate: true, height: true, width: true
+        };
+      }
+    };
+  }
+
+  // A shim for getUserMedia method on the mediaDevices object.
+  // TODO(KaptenJansson) remove once implemented in Chrome stable.
+  if (!navigator.mediaDevices.getUserMedia) {
+    navigator.mediaDevices.getUserMedia = function(constraints) {
+      return getUserMediaPromise_(constraints);
+    };
+  } else {
+    // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
+    // function which returns a Promise, it does not accept spec-style
+    // constraints.
+    var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+        bind(navigator.mediaDevices);
+    navigator.mediaDevices.getUserMedia = function(cs) {
+      return shimConstraints_(cs, function(c) {
+        return origGetUserMedia(c).then(function(stream) {
+          if (c.audio && !stream.getAudioTracks().length ||
+              c.video && !stream.getVideoTracks().length) {
+            stream.getTracks().forEach(function(track) {
+              track.stop();
+            });
+            throw new DOMException('', 'NotFoundError');
+          }
+          return stream;
+        }, function(e) {
+          return Promise.reject(shimError_(e));
+        });
+      });
+    };
+  }
+
+  // Dummy devicechange event methods.
+  // TODO(KaptenJansson) remove once implemented in Chrome stable.
+  if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
+    navigator.mediaDevices.addEventListener = function() {
+      logging('Dummy mediaDevices.addEventListener called.');
+    };
+  }
+  if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
+    navigator.mediaDevices.removeEventListener = function() {
+      logging('Dummy mediaDevices.removeEventListener called.');
+    };
+  }
+};
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+var browserDetails = __webpack_require__(0).browserDetails;
+var shimRTCPeerConnection = __webpack_require__(13);
+
+module.exports = {
+  shimGetUserMedia: __webpack_require__(12),
+  shimPeerConnection: function() {
+    if (window.RTCIceGatherer) {
+      // ORTC defines an RTCIceCandidate object but no constructor.
+      // Not implemented in Edge.
+      if (!window.RTCIceCandidate) {
+        window.RTCIceCandidate = function(args) {
+          return args;
+        };
+      }
+      // ORTC does not have a session description object but
+      // other browsers (i.e. Chrome) that will support both PC and ORTC
+      // in the future might have this defined already.
+      if (!window.RTCSessionDescription) {
+        window.RTCSessionDescription = function(args) {
+          return args;
+        };
+      }
+      // this adds an additional event listener to MediaStrackTrack that signals
+      // when a tracks enabled property was changed. Workaround for a bug in
+      // addStream, see below. No longer required in 15025+
+      if (browserDetails.version < 15025) {
+        var origMSTEnabled = Object.getOwnPropertyDescriptor(
+            MediaStreamTrack.prototype, 'enabled');
+        Object.defineProperty(MediaStreamTrack.prototype, 'enabled', {
+          set: function(value) {
+            origMSTEnabled.set.call(this, value);
+            var ev = new Event('enabled');
+            ev.enabled = value;
+            this.dispatchEvent(ev);
+          }
+        });
+      }
+    }
+    window.RTCPeerConnection = shimRTCPeerConnection(browserDetails.version);
+  },
+  shimReplaceTrack: function() {
+    // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
+    if (window.RTCRtpSender && !('replaceTrack' in RTCRtpSender.prototype)) {
+      RTCRtpSender.prototype.replaceTrack = RTCRtpSender.prototype.setTrack;
+    }
+  }
+};
+
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+// Expose public methods.
+module.exports = function() {
+  var shimError_ = function(e) {
+    return {
+      name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
+      message: e.message,
+      constraint: e.constraint,
+      toString: function() {
+        return this.name;
+      }
+    };
+  };
+
+  // getUserMedia error shim.
+  var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+      bind(navigator.mediaDevices);
+  navigator.mediaDevices.getUserMedia = function(c) {
+    return origGetUserMedia(c).catch(function(e) {
+      return Promise.reject(shimError_(e));
+    });
+  };
+};
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+var SDPUtils = __webpack_require__(7);
+
+// sort tracks such that they follow an a-v-a-v...
+// pattern.
+function sortTracks(tracks) {
+  var audioTracks = tracks.filter(function(track) {
+    return track.kind === 'audio';
+  });
+  var videoTracks = tracks.filter(function(track) {
+    return track.kind === 'video';
+  });
+  tracks = [];
+  while (audioTracks.length || videoTracks.length) {
+    if (audioTracks.length) {
+      tracks.push(audioTracks.shift());
+    }
+    if (videoTracks.length) {
+      tracks.push(videoTracks.shift());
+    }
+  }
+  return tracks;
+}
+
+// Edge does not like
+// 1) stun:
+// 2) turn: that does not have all of turn:host:port?transport=udp
+// 3) turn: with ipv6 addresses
+// 4) turn: occurring muliple times
+function filterIceServers(iceServers, edgeVersion) {
+  var hasTurn = false;
+  iceServers = JSON.parse(JSON.stringify(iceServers));
+  return iceServers.filter(function(server) {
+    if (server && (server.urls || server.url)) {
+      var urls = server.urls || server.url;
+      if (server.url && !server.urls) {
+        console.warn('RTCIceServer.url is deprecated! Use urls instead.');
+      }
+      var isString = typeof urls === 'string';
+      if (isString) {
+        urls = [urls];
+      }
+      urls = urls.filter(function(url) {
+        var validTurn = url.indexOf('turn:') === 0 &&
+            url.indexOf('transport=udp') !== -1 &&
+            url.indexOf('turn:[') === -1 &&
+            !hasTurn;
+
+        if (validTurn) {
+          hasTurn = true;
+          return true;
+        }
+        return url.indexOf('stun:') === 0 && edgeVersion >= 14393;
+      });
+
+      delete server.url;
+      server.urls = isString ? urls[0] : urls;
+      return !!urls.length;
+    }
+    return false;
+  });
+}
+
+// Determines the intersection of local and remote capabilities.
+function getCommonCapabilities(localCapabilities, remoteCapabilities) {
+  var commonCapabilities = {
+    codecs: [],
+    headerExtensions: [],
+    fecMechanisms: []
+  };
+
+  var findCodecByPayloadType = function(pt, codecs) {
+    pt = parseInt(pt, 10);
+    for (var i = 0; i < codecs.length; i++) {
+      if (codecs[i].payloadType === pt ||
+          codecs[i].preferredPayloadType === pt) {
+        return codecs[i];
+      }
+    }
+  };
+
+  var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
+    var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
+    var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
+    return lCodec && rCodec &&
+        lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
+  };
+
+  localCapabilities.codecs.forEach(function(lCodec) {
+    for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
+      var rCodec = remoteCapabilities.codecs[i];
+      if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
+          lCodec.clockRate === rCodec.clockRate) {
+        if (lCodec.name.toLowerCase() === 'rtx' &&
+            lCodec.parameters && rCodec.parameters.apt) {
+          // for RTX we need to find the local rtx that has a apt
+          // which points to the same local codec as the remote one.
+          if (!rtxCapabilityMatches(lCodec, rCodec,
+              localCapabilities.codecs, remoteCapabilities.codecs)) {
+            continue;
+          }
+        }
+        rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
+        // number of channels is the highest common number of channels
+        rCodec.numChannels = Math.min(lCodec.numChannels,
+            rCodec.numChannels);
+        // push rCodec so we reply with offerer payload type
+        commonCapabilities.codecs.push(rCodec);
+
+        // determine common feedback mechanisms
+        rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
+          for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
+            if (lCodec.rtcpFeedback[j].type === fb.type &&
+                lCodec.rtcpFeedback[j].parameter === fb.parameter) {
+              return true;
+            }
+          }
+          return false;
+        });
+        // FIXME: also need to determine .parameters
+        //  see https://github.com/openpeer/ortc/issues/569
+        break;
+      }
+    }
+  });
+
+  localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
+    for (var i = 0; i < remoteCapabilities.headerExtensions.length;
+         i++) {
+      var rHeaderExtension = remoteCapabilities.headerExtensions[i];
+      if (lHeaderExtension.uri === rHeaderExtension.uri) {
+        commonCapabilities.headerExtensions.push(rHeaderExtension);
+        break;
+      }
+    }
+  });
+
+  // FIXME: fecMechanisms
+  return commonCapabilities;
+}
+
+// is action=setLocalDescription with type allowed in signalingState
+function isActionAllowedInSignalingState(action, type, signalingState) {
+  return {
+    offer: {
+      setLocalDescription: ['stable', 'have-local-offer'],
+      setRemoteDescription: ['stable', 'have-remote-offer']
+    },
+    answer: {
+      setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
+      setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
+    }
+  }[type][action].indexOf(signalingState) !== -1;
+}
+
+module.exports = function(edgeVersion) {
+  var RTCPeerConnection = function(config) {
+    var self = this;
+
+    var _eventTarget = document.createDocumentFragment();
+    ['addEventListener', 'removeEventListener', 'dispatchEvent']
+        .forEach(function(method) {
+          self[method] = _eventTarget[method].bind(_eventTarget);
+        });
+
+    this.needNegotiation = false;
+
+    this.onicecandidate = null;
+    this.onaddstream = null;
+    this.ontrack = null;
+    this.onremovestream = null;
+    this.onsignalingstatechange = null;
+    this.oniceconnectionstatechange = null;
+    this.onicegatheringstatechange = null;
+    this.onnegotiationneeded = null;
+    this.ondatachannel = null;
+    this.canTrickleIceCandidates = null;
+
+    this.localStreams = [];
+    this.remoteStreams = [];
+    this.getLocalStreams = function() {
+      return self.localStreams;
+    };
+    this.getRemoteStreams = function() {
+      return self.remoteStreams;
+    };
+
+    this.localDescription = new RTCSessionDescription({
+      type: '',
+      sdp: ''
+    });
+    this.remoteDescription = new RTCSessionDescription({
+      type: '',
+      sdp: ''
+    });
+    this.signalingState = 'stable';
+    this.iceConnectionState = 'new';
+    this.iceGatheringState = 'new';
+
+    this.iceOptions = {
+      gatherPolicy: 'all',
+      iceServers: []
+    };
+    if (config && config.iceTransportPolicy) {
+      switch (config.iceTransportPolicy) {
+        case 'all':
+        case 'relay':
+          this.iceOptions.gatherPolicy = config.iceTransportPolicy;
+          break;
+        default:
+          // don't set iceTransportPolicy.
+          break;
+      }
+    }
+    this.usingBundle = config && config.bundlePolicy === 'max-bundle';
+
+    if (config && config.iceServers) {
+      this.iceOptions.iceServers = filterIceServers(config.iceServers,
+          edgeVersion);
+    }
+    this._config = config || {};
+
+    // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
+    // everything that is needed to describe a SDP m-line.
+    this.transceivers = [];
+
+    // since the iceGatherer is currently created in createOffer but we
+    // must not emit candidates until after setLocalDescription we buffer
+    // them in this array.
+    this._localIceCandidatesBuffer = [];
+  };
+
+  RTCPeerConnection.prototype._emitGatheringStateChange = function() {
+    var event = new Event('icegatheringstatechange');
+    this.dispatchEvent(event);
+    if (this.onicegatheringstatechange !== null) {
+      this.onicegatheringstatechange(event);
+    }
+  };
+
+  RTCPeerConnection.prototype._emitBufferedCandidates = function() {
+    var self = this;
+    var sections = SDPUtils.splitSections(self.localDescription.sdp);
+    // FIXME: need to apply ice candidates in a way which is async but
+    // in-order
+    this._localIceCandidatesBuffer.forEach(function(event) {
+      var end = !event.candidate || Object.keys(event.candidate).length === 0;
+      if (end) {
+        for (var j = 1; j < sections.length; j++) {
+          if (sections[j].indexOf('\r\na=end-of-candidates\r\n') === -1) {
+            sections[j] += 'a=end-of-candidates\r\n';
+          }
+        }
+      } else {
+        sections[event.candidate.sdpMLineIndex + 1] +=
+            'a=' + event.candidate.candidate + '\r\n';
+      }
+      self.localDescription.sdp = sections.join('');
+      self.dispatchEvent(event);
+      if (self.onicecandidate !== null) {
+        self.onicecandidate(event);
+      }
+      if (!event.candidate && self.iceGatheringState !== 'complete') {
+        var complete = self.transceivers.every(function(transceiver) {
+          return transceiver.iceGatherer &&
+              transceiver.iceGatherer.state === 'completed';
+        });
+        if (complete && self.iceGatheringStateChange !== 'complete') {
+          self.iceGatheringState = 'complete';
+          self._emitGatheringStateChange();
+        }
+      }
+    });
+    this._localIceCandidatesBuffer = [];
+  };
+
+  RTCPeerConnection.prototype.getConfiguration = function() {
+    return this._config;
+  };
+
+  // internal helper to create a transceiver object.
+  // (whih is not yet the same as the WebRTC 1.0 transceiver)
+  RTCPeerConnection.prototype._createTransceiver = function(kind) {
+    var hasBundleTransport = this.transceivers.length > 0;
+    var transceiver = {
+      track: null,
+      iceGatherer: null,
+      iceTransport: null,
+      dtlsTransport: null,
+      localCapabilities: null,
+      remoteCapabilities: null,
+      rtpSender: null,
+      rtpReceiver: null,
+      kind: kind,
+      mid: null,
+      sendEncodingParameters: null,
+      recvEncodingParameters: null,
+      stream: null,
+      wantReceive: true
+    };
+    if (this.usingBundle && hasBundleTransport) {
+      transceiver.iceTransport = this.transceivers[0].iceTransport;
+      transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
+    } else {
+      var transports = this._createIceAndDtlsTransports();
+      transceiver.iceTransport = transports.iceTransport;
+      transceiver.dtlsTransport = transports.dtlsTransport;
+    }
+    this.transceivers.push(transceiver);
+    return transceiver;
+  };
+
+  RTCPeerConnection.prototype.addTrack = function(track, stream) {
+    var transceiver;
+    for (var i = 0; i < this.transceivers.length; i++) {
+      if (!this.transceivers[i].track &&
+          this.transceivers[i].kind === track.kind) {
+        transceiver = this.transceivers[i];
+      }
+    }
+    if (!transceiver) {
+      transceiver = this._createTransceiver(track.kind);
+    }
+
+    transceiver.track = track;
+    transceiver.stream = stream;
+    transceiver.rtpSender = new RTCRtpSender(track,
+        transceiver.dtlsTransport);
+
+    this._maybeFireNegotiationNeeded();
+    return transceiver.rtpSender;
+  };
+
+  RTCPeerConnection.prototype.addStream = function(stream) {
+    var self = this;
+    if (edgeVersion >= 15025) {
+      this.localStreams.push(stream);
+      stream.getTracks().forEach(function(track) {
+        self.addTrack(track, stream);
+      });
+    } else {
+      // Clone is necessary for local demos mostly, attaching directly
+      // to two different senders does not work (build 10547).
+      // Fixed in 15025 (or earlier)
+      var clonedStream = stream.clone();
+      stream.getTracks().forEach(function(track, idx) {
+        var clonedTrack = clonedStream.getTracks()[idx];
+        track.addEventListener('enabled', function(event) {
+          clonedTrack.enabled = event.enabled;
+        });
+      });
+      clonedStream.getTracks().forEach(function(track) {
+        self.addTrack(track, clonedStream);
+      });
+      this.localStreams.push(clonedStream);
+    }
+    this._maybeFireNegotiationNeeded();
+  };
+
+  RTCPeerConnection.prototype.removeStream = function(stream) {
+    var idx = this.localStreams.indexOf(stream);
+    if (idx > -1) {
+      this.localStreams.splice(idx, 1);
+      this._maybeFireNegotiationNeeded();
+    }
+  };
+
+  RTCPeerConnection.prototype.getSenders = function() {
+    return this.transceivers.filter(function(transceiver) {
+      return !!transceiver.rtpSender;
+    })
+    .map(function(transceiver) {
+      return transceiver.rtpSender;
+    });
+  };
+
+  RTCPeerConnection.prototype.getReceivers = function() {
+    return this.transceivers.filter(function(transceiver) {
+      return !!transceiver.rtpReceiver;
+    })
+    .map(function(transceiver) {
+      return transceiver.rtpReceiver;
+    });
+  };
+
+  // Create ICE gatherer and hook it up.
+  RTCPeerConnection.prototype._createIceGatherer = function(mid,
+      sdpMLineIndex) {
+    var self = this;
+    var iceGatherer = new RTCIceGatherer(self.iceOptions);
+    iceGatherer.onlocalcandidate = function(evt) {
+      var event = new Event('icecandidate');
+      event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
+
+      var cand = evt.candidate;
+      var end = !cand || Object.keys(cand).length === 0;
+      // Edge emits an empty object for RTCIceCandidateComplete‥
+      if (end) {
+        // polyfill since RTCIceGatherer.state is not implemented in
+        // Edge 10547 yet.
+        if (iceGatherer.state === undefined) {
+          iceGatherer.state = 'completed';
+        }
+      } else {
+        // RTCIceCandidate doesn't have a component, needs to be added
+        cand.component = 1;
+        event.candidate.candidate = SDPUtils.writeCandidate(cand);
+      }
+
+      // update local description.
+      var sections = SDPUtils.splitSections(self.localDescription.sdp);
+      if (!end) {
+        sections[event.candidate.sdpMLineIndex + 1] +=
+            'a=' + event.candidate.candidate + '\r\n';
+      } else {
+        sections[event.candidate.sdpMLineIndex + 1] +=
+            'a=end-of-candidates\r\n';
+      }
+      self.localDescription.sdp = sections.join('');
+      var transceivers = self._pendingOffer ? self._pendingOffer :
+          self.transceivers;
+      var complete = transceivers.every(function(transceiver) {
+        return transceiver.iceGatherer &&
+            transceiver.iceGatherer.state === 'completed';
+      });
+
+      // Emit candidate if localDescription is set.
+      // Also emits null candidate when all gatherers are complete.
+      switch (self.iceGatheringState) {
+        case 'new':
+          if (!end) {
+            self._localIceCandidatesBuffer.push(event);
+          }
+          if (end && complete) {
+            self._localIceCandidatesBuffer.push(
+                new Event('icecandidate'));
+          }
+          break;
+        case 'gathering':
+          self._emitBufferedCandidates();
+          if (!end) {
+            self.dispatchEvent(event);
+            if (self.onicecandidate !== null) {
+              self.onicecandidate(event);
+            }
+          }
+          if (complete) {
+            self.dispatchEvent(new Event('icecandidate'));
+            if (self.onicecandidate !== null) {
+              self.onicecandidate(new Event('icecandidate'));
+            }
+            self.iceGatheringState = 'complete';
+            self._emitGatheringStateChange();
+          }
+          break;
+        case 'complete':
+          // should not happen... currently!
+          break;
+        default: // no-op.
+          break;
+      }
+    };
+    return iceGatherer;
+  };
+
+  // Create ICE transport and DTLS transport.
+  RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
+    var self = this;
+    var iceTransport = new RTCIceTransport(null);
+    iceTransport.onicestatechange = function() {
+      self._updateConnectionState();
+    };
+
+    var dtlsTransport = new RTCDtlsTransport(iceTransport);
+    dtlsTransport.ondtlsstatechange = function() {
+      self._updateConnectionState();
+    };
+    dtlsTransport.onerror = function() {
+      // onerror does not set state to failed by itself.
+      Object.defineProperty(dtlsTransport, 'state',
+          {value: 'failed', writable: true});
+      self._updateConnectionState();
+    };
+
+    return {
+      iceTransport: iceTransport,
+      dtlsTransport: dtlsTransport
+    };
+  };
+
+  // Destroy ICE gatherer, ICE transport and DTLS transport.
+  // Without triggering the callbacks.
+  RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
+      sdpMLineIndex) {
+    var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
+    if (iceGatherer) {
+      delete iceGatherer.onlocalcandidate;
+      delete this.transceivers[sdpMLineIndex].iceGatherer;
+    }
+    var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
+    if (iceTransport) {
+      delete iceTransport.onicestatechange;
+      delete this.transceivers[sdpMLineIndex].iceTransport;
+    }
+    var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
+    if (dtlsTransport) {
+      delete dtlsTransport.ondtlssttatechange;
+      delete dtlsTransport.onerror;
+      delete this.transceivers[sdpMLineIndex].dtlsTransport;
+    }
+  };
+
+  // Start the RTP Sender and Receiver for a transceiver.
+  RTCPeerConnection.prototype._transceive = function(transceiver,
+      send, recv) {
+    var params = getCommonCapabilities(transceiver.localCapabilities,
+        transceiver.remoteCapabilities);
+    if (send && transceiver.rtpSender) {
+      params.encodings = transceiver.sendEncodingParameters;
+      params.rtcp = {
+        cname: SDPUtils.localCName,
+        compound: transceiver.rtcpParameters.compound
+      };
+      if (transceiver.recvEncodingParameters.length) {
+        params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
+      }
+      transceiver.rtpSender.send(params);
+    }
+    if (recv && transceiver.rtpReceiver) {
+      // remove RTX field in Edge 14942
+      if (transceiver.kind === 'video'
+          && transceiver.recvEncodingParameters
+          && edgeVersion < 15019) {
+        transceiver.recvEncodingParameters.forEach(function(p) {
+          delete p.rtx;
+        });
+      }
+      params.encodings = transceiver.recvEncodingParameters;
+      params.rtcp = {
+        cname: transceiver.rtcpParameters.cname,
+        compound: transceiver.rtcpParameters.compound
+      };
+      if (transceiver.sendEncodingParameters.length) {
+        params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
+      }
+      transceiver.rtpReceiver.receive(params);
+    }
+  };
+
+  RTCPeerConnection.prototype.setLocalDescription = function(description) {
+    var self = this;
+
+    if (!isActionAllowedInSignalingState('setLocalDescription',
+        description.type, this.signalingState)) {
+      var e = new Error('Can not set local ' + description.type +
+          ' in state ' + this.signalingState);
+      e.name = 'InvalidStateError';
+      if (arguments.length > 2 && typeof arguments[2] === 'function') {
+        window.setTimeout(arguments[2], 0, e);
+      }
+      return Promise.reject(e);
+    }
+
+    var sections;
+    var sessionpart;
+    if (description.type === 'offer') {
+      // FIXME: What was the purpose of this empty if statement?
+      // if (!this._pendingOffer) {
+      // } else {
+      if (this._pendingOffer) {
+        // VERY limited support for SDP munging. Limited to:
+        // * changing the order of codecs
+        sections = SDPUtils.splitSections(description.sdp);
+        sessionpart = sections.shift();
+        sections.forEach(function(mediaSection, sdpMLineIndex) {
+          var caps = SDPUtils.parseRtpParameters(mediaSection);
+          self._pendingOffer[sdpMLineIndex].localCapabilities = caps;
+        });
+        this.transceivers = this._pendingOffer;
+        delete this._pendingOffer;
+      }
+    } else if (description.type === 'answer') {
+      sections = SDPUtils.splitSections(self.remoteDescription.sdp);
+      sessionpart = sections.shift();
+      var isIceLite = SDPUtils.matchPrefix(sessionpart,
+          'a=ice-lite').length > 0;
+      sections.forEach(function(mediaSection, sdpMLineIndex) {
+        var transceiver = self.transceivers[sdpMLineIndex];
+        var iceGatherer = transceiver.iceGatherer;
+        var iceTransport = transceiver.iceTransport;
+        var dtlsTransport = transceiver.dtlsTransport;
+        var localCapabilities = transceiver.localCapabilities;
+        var remoteCapabilities = transceiver.remoteCapabilities;
+
+        var rejected = SDPUtils.isRejected(mediaSection);
+
+        if (!rejected && !transceiver.isDatachannel) {
+          var remoteIceParameters = SDPUtils.getIceParameters(
+              mediaSection, sessionpart);
+          var remoteDtlsParameters = SDPUtils.getDtlsParameters(
+              mediaSection, sessionpart);
+          if (isIceLite) {
+            remoteDtlsParameters.role = 'server';
+          }
+
+          if (!self.usingBundle || sdpMLineIndex === 0) {
+            iceTransport.start(iceGatherer, remoteIceParameters,
+                isIceLite ? 'controlling' : 'controlled');
+            dtlsTransport.start(remoteDtlsParameters);
+          }
+
+          // Calculate intersection of capabilities.
+          var params = getCommonCapabilities(localCapabilities,
+              remoteCapabilities);
+
+          // Start the RTCRtpSender. The RTCRtpReceiver for this
+          // transceiver has already been started in setRemoteDescription.
+          self._transceive(transceiver,
+              params.codecs.length > 0,
+              false);
+        }
+      });
+    }
+
+    this.localDescription = {
+      type: description.type,
+      sdp: description.sdp
+    };
+    switch (description.type) {
+      case 'offer':
+        this._updateSignalingState('have-local-offer');
+        break;
+      case 'answer':
+        this._updateSignalingState('stable');
+        break;
+      default:
+        throw new TypeError('unsupported type "' + description.type +
+            '"');
+    }
+
+    // If a success callback was provided, emit ICE candidates after it
+    // has been executed. Otherwise, emit callback after the Promise is
+    // resolved.
+    var hasCallback = arguments.length > 1 &&
+      typeof arguments[1] === 'function';
+    if (hasCallback) {
+      var cb = arguments[1];
+      window.setTimeout(function() {
+        cb();
+        if (self.iceGatheringState === 'new') {
+          self.iceGatheringState = 'gathering';
+          self._emitGatheringStateChange();
+        }
+        self._emitBufferedCandidates();
+      }, 0);
+    }
+    var p = Promise.resolve();
+    p.then(function() {
+      if (!hasCallback) {
+        if (self.iceGatheringState === 'new') {
+          self.iceGatheringState = 'gathering';
+          self._emitGatheringStateChange();
+        }
+        // Usually candidates will be emitted earlier.
+        window.setTimeout(self._emitBufferedCandidates.bind(self), 500);
+      }
+    });
+    return p;
+  };
+
+  RTCPeerConnection.prototype.setRemoteDescription = function(description) {
+    var self = this;
+
+    if (!isActionAllowedInSignalingState('setRemoteDescription',
+        description.type, this.signalingState)) {
+      var e = new Error('Can not set remote ' + description.type +
+          ' in state ' + this.signalingState);
+      e.name = 'InvalidStateError';
+      if (arguments.length > 2 && typeof arguments[2] === 'function') {
+        window.setTimeout(arguments[2], 0, e);
+      }
+      return Promise.reject(e);
+    }
+
+    var streams = {};
+    var receiverList = [];
+    var sections = SDPUtils.splitSections(description.sdp);
+    var sessionpart = sections.shift();
+    var isIceLite = SDPUtils.matchPrefix(sessionpart,
+        'a=ice-lite').length > 0;
+    var usingBundle = SDPUtils.matchPrefix(sessionpart,
+        'a=group:BUNDLE ').length > 0;
+    this.usingBundle = usingBundle;
+    var iceOptions = SDPUtils.matchPrefix(sessionpart,
+        'a=ice-options:')[0];
+    if (iceOptions) {
+      this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
+          .indexOf('trickle') >= 0;
+    } else {
+      this.canTrickleIceCandidates = false;
+    }
+
+    sections.forEach(function(mediaSection, sdpMLineIndex) {
+      var lines = SDPUtils.splitLines(mediaSection);
+      var kind = SDPUtils.getKind(mediaSection);
+      var rejected = SDPUtils.isRejected(mediaSection);
+      var protocol = lines[0].substr(2).split(' ')[2];
+
+      var direction = SDPUtils.getDirection(mediaSection, sessionpart);
+      var remoteMsid = SDPUtils.parseMsid(mediaSection);
+
+      var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
+
+      // Reject datachannels which are not implemented yet.
+      if (kind === 'application' && protocol === 'DTLS/SCTP') {
+        self.transceivers[sdpMLineIndex] = {
+          mid: mid,
+          isDatachannel: true
+        };
+        return;
+      }
+
+      var transceiver;
+      var iceGatherer;
+      var iceTransport;
+      var dtlsTransport;
+      var rtpReceiver;
+      var sendEncodingParameters;
+      var recvEncodingParameters;
+      var localCapabilities;
+
+      var track;
+      // FIXME: ensure the mediaSection has rtcp-mux set.
+      var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
+      var remoteIceParameters;
+      var remoteDtlsParameters;
+      if (!rejected) {
+        remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
+            sessionpart);
+        remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
+            sessionpart);
+        remoteDtlsParameters.role = 'client';
+      }
+      recvEncodingParameters =
+          SDPUtils.parseRtpEncodingParameters(mediaSection);
+
+      var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);
+
+      var isComplete = SDPUtils.matchPrefix(mediaSection,
+          'a=end-of-candidates', sessionpart).length > 0;
+      var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
+          .map(function(cand) {
+            return SDPUtils.parseCandidate(cand);
+          })
+          .filter(function(cand) {
+            return cand.component === '1' || cand.component === 1;
+          });
+      if (description.type === 'offer' && !rejected) {
+        transceiver = self.transceivers[sdpMLineIndex] ||
+            self._createTransceiver(kind);
+        transceiver.mid = mid;
+
+        if (!transceiver.iceGatherer) {
+          transceiver.iceGatherer = usingBundle && sdpMLineIndex > 0 ?
+              self.transceivers[0].iceGatherer :
+              self._createIceGatherer(mid, sdpMLineIndex);
+        }
+
+        if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
+          transceiver.iceTransport.setRemoteCandidates(cands);
+        }
+
+        localCapabilities = RTCRtpReceiver.getCapabilities(kind);
+
+        // filter RTX until additional stuff needed for RTX is implemented
+        // in adapter.js
+        if (edgeVersion < 15019) {
+          localCapabilities.codecs = localCapabilities.codecs.filter(
+              function(codec) {
+                return codec.name !== 'rtx';
+              });
+        }
+
+        sendEncodingParameters = [{
+          ssrc: (2 * sdpMLineIndex + 2) * 1001
+        }];
+
+        if (direction === 'sendrecv' || direction === 'sendonly') {
+          rtpReceiver = new RTCRtpReceiver(transceiver.dtlsTransport,
+              kind);
+
+          track = rtpReceiver.track;
+          // FIXME: does not work with Plan B.
+          if (remoteMsid) {
+            if (!streams[remoteMsid.stream]) {
+              streams[remoteMsid.stream] = new MediaStream();
+              Object.defineProperty(streams[remoteMsid.stream], 'id', {
+                get: function() {
+                  return remoteMsid.stream;
+                }
+              });
+            }
+            Object.defineProperty(track, 'id', {
+              get: function() {
+                return remoteMsid.track;
+              }
+            });
+            streams[remoteMsid.stream].addTrack(track);
+            receiverList.push([track, rtpReceiver,
+              streams[remoteMsid.stream]]);
+          } else {
+            if (!streams.default) {
+              streams.default = new MediaStream();
+            }
+            streams.default.addTrack(track);
+            receiverList.push([track, rtpReceiver, streams.default]);
+          }
+        }
+
+        transceiver.localCapabilities = localCapabilities;
+        transceiver.remoteCapabilities = remoteCapabilities;
+        transceiver.rtpReceiver = rtpReceiver;
+        transceiver.rtcpParameters = rtcpParameters;
+        transceiver.sendEncodingParameters = sendEncodingParameters;
+        transceiver.recvEncodingParameters = recvEncodingParameters;
+
+        // Start the RTCRtpReceiver now. The RTPSender is started in
+        // setLocalDescription.
+        self._transceive(self.transceivers[sdpMLineIndex],
+            false,
+            direction === 'sendrecv' || direction === 'sendonly');
+      } else if (description.type === 'answer' && !rejected) {
+        if (usingBundle && sdpMLineIndex > 0) {
+          self._disposeIceAndDtlsTransports(sdpMLineIndex);
+          self.transceivers[sdpMLineIndex].iceGatherer =
+              self.transceivers[0].iceGatherer;
+          self.transceivers[sdpMLineIndex].iceTransport =
+              self.transceivers[0].iceTransport;
+          self.transceivers[sdpMLineIndex].dtlsTransport =
+              self.transceivers[0].dtlsTransport;
+          if (self.transceivers[sdpMLineIndex].rtpSender) {
+            self.transceivers[sdpMLineIndex].rtpSender.setTransport(
+                self.transceivers[0].dtlsTransport);
+          }
+          if (self.transceivers[sdpMLineIndex].rtpReceiver) {
+            self.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
+                self.transceivers[0].dtlsTransport);
+          }
+        }
+        transceiver = self.transceivers[sdpMLineIndex];
+        iceGatherer = transceiver.iceGatherer;
+        iceTransport = transceiver.iceTransport;
+        dtlsTransport = transceiver.dtlsTransport;
+        rtpReceiver = transceiver.rtpReceiver;
+        sendEncodingParameters = transceiver.sendEncodingParameters;
+        localCapabilities = transceiver.localCapabilities;
+
+        self.transceivers[sdpMLineIndex].recvEncodingParameters =
+            recvEncodingParameters;
+        self.transceivers[sdpMLineIndex].remoteCapabilities =
+            remoteCapabilities;
+        self.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
+
+        if ((isIceLite || isComplete) && cands.length) {
+          iceTransport.setRemoteCandidates(cands);
+        }
+        if (!usingBundle || sdpMLineIndex === 0) {
+          iceTransport.start(iceGatherer, remoteIceParameters,
+              'controlling');
+          dtlsTransport.start(remoteDtlsParameters);
+        }
+
+        self._transceive(transceiver,
+            direction === 'sendrecv' || direction === 'recvonly',
+            direction === 'sendrecv' || direction === 'sendonly');
+
+        if (rtpReceiver &&
+            (direction === 'sendrecv' || direction === 'sendonly')) {
+          track = rtpReceiver.track;
+          if (remoteMsid) {
+            if (!streams[remoteMsid.stream]) {
+              streams[remoteMsid.stream] = new MediaStream();
+            }
+            streams[remoteMsid.stream].addTrack(track);
+            receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
+          } else {
+            if (!streams.default) {
+              streams.default = new MediaStream();
+            }
+            streams.default.addTrack(track);
+            receiverList.push([track, rtpReceiver, streams.default]);
+          }
+        } else {
+          // FIXME: actually the receiver should be created later.
+          delete transceiver.rtpReceiver;
+        }
+      }
+    });
+
+    this.remoteDescription = {
+      type: description.type,
+      sdp: description.sdp
+    };
+    switch (description.type) {
+      case 'offer':
+        this._updateSignalingState('have-remote-offer');
+        break;
+      case 'answer':
+        this._updateSignalingState('stable');
+        break;
+      default:
+        throw new TypeError('unsupported type "' + description.type +
+            '"');
+    }
+    Object.keys(streams).forEach(function(sid) {
+      var stream = streams[sid];
+      if (stream.getTracks().length) {
+        self.remoteStreams.push(stream);
+        var event = new Event('addstream');
+        event.stream = stream;
+        self.dispatchEvent(event);
+        if (self.onaddstream !== null) {
+          window.setTimeout(function() {
+            self.onaddstream(event);
+          }, 0);
+        }
+
+        receiverList.forEach(function(item) {
+          var track = item[0];
+          var receiver = item[1];
+          if (stream.id !== item[2].id) {
+            return;
+          }
+          var trackEvent = new Event('track');
+          trackEvent.track = track;
+          trackEvent.receiver = receiver;
+          trackEvent.streams = [stream];
+          self.dispatchEvent(trackEvent);
+          if (self.ontrack !== null) {
+            window.setTimeout(function() {
+              self.ontrack(trackEvent);
+            }, 0);
+          }
+        });
+      }
+    });
+
+    // check whether addIceCandidate({}) was called within four seconds after
+    // setRemoteDescription.
+    window.setTimeout(function() {
+      if (!(self && self.transceivers)) {
+        return;
+      }
+      self.transceivers.forEach(function(transceiver) {
+        if (transceiver.iceTransport &&
+            transceiver.iceTransport.state === 'new' &&
+            transceiver.iceTransport.getRemoteCandidates().length > 0) {
+          console.warn('Timeout for addRemoteCandidate. Consider sending ' +
+              'an end-of-candidates notification');
+          transceiver.iceTransport.addRemoteCandidate({});
+        }
+      });
+    }, 4000);
+
+    if (arguments.length > 1 && typeof arguments[1] === 'function') {
+      window.setTimeout(arguments[1], 0);
+    }
+    return Promise.resolve();
+  };
+
+  RTCPeerConnection.prototype.close = function() {
+    this.transceivers.forEach(function(transceiver) {
+      /* not yet
+      if (transceiver.iceGatherer) {
+        transceiver.iceGatherer.close();
+      }
+      */
+      if (transceiver.iceTransport) {
+        transceiver.iceTransport.stop();
+      }
+      if (transceiver.dtlsTransport) {
+        transceiver.dtlsTransport.stop();
+      }
+      if (transceiver.rtpSender) {
+        transceiver.rtpSender.stop();
+      }
+      if (transceiver.rtpReceiver) {
+        transceiver.rtpReceiver.stop();
+      }
+    });
+    // FIXME: clean up tracks, local streams, remote streams, etc
+    this._updateSignalingState('closed');
+  };
+
+  // Update the signaling state.
+  RTCPeerConnection.prototype._updateSignalingState = function(newState) {
+    this.signalingState = newState;
+    var event = new Event('signalingstatechange');
+    this.dispatchEvent(event);
+    if (this.onsignalingstatechange !== null) {
+      this.onsignalingstatechange(event);
+    }
+  };
+
+  // Determine whether to fire the negotiationneeded event.
+  RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
+    var self = this;
+    if (this.signalingState !== 'stable' || this.needNegotiation === true) {
+      return;
+    }
+    this.needNegotiation = true;
+    window.setTimeout(function() {
+      if (self.needNegotiation === false) {
+        return;
+      }
+      self.needNegotiation = false;
+      var event = new Event('negotiationneeded');
+      self.dispatchEvent(event);
+      if (self.onnegotiationneeded !== null) {
+        self.onnegotiationneeded(event);
+      }
+    }, 0);
+  };
+
+  // Update the connection state.
+  RTCPeerConnection.prototype._updateConnectionState = function() {
+    var self = this;
+    var newState;
+    var states = {
+      'new': 0,
+      closed: 0,
+      connecting: 0,
+      checking: 0,
+      connected: 0,
+      completed: 0,
+      failed: 0
+    };
+    this.transceivers.forEach(function(transceiver) {
+      states[transceiver.iceTransport.state]++;
+      states[transceiver.dtlsTransport.state]++;
+    });
+    // ICETransport.completed and connected are the same for this purpose.
+    states.connected += states.completed;
+
+    newState = 'new';
+    if (states.failed > 0) {
+      newState = 'failed';
+    } else if (states.connecting > 0 || states.checking > 0) {
+      newState = 'connecting';
+    } else if (states.disconnected > 0) {
+      newState = 'disconnected';
+    } else if (states.new > 0) {
+      newState = 'new';
+    } else if (states.connected > 0 || states.completed > 0) {
+      newState = 'connected';
+    }
+
+    if (newState !== self.iceConnectionState) {
+      self.iceConnectionState = newState;
+      var event = new Event('iceconnectionstatechange');
+      this.dispatchEvent(event);
+      if (this.oniceconnectionstatechange !== null) {
+        this.oniceconnectionstatechange(event);
+      }
+    }
+  };
+
+  RTCPeerConnection.prototype.createOffer = function() {
+    var self = this;
+    if (this._pendingOffer) {
+      throw new Error('createOffer called while there is a pending offer.');
+    }
+    var offerOptions;
+    if (arguments.length === 1 && typeof arguments[0] !== 'function') {
+      offerOptions = arguments[0];
+    } else if (arguments.length === 3) {
+      offerOptions = arguments[2];
+    }
+
+    var numAudioTracks = this.transceivers.filter(function(t) {
+      return t.kind === 'audio';
+    }).length;
+    var numVideoTracks = this.transceivers.filter(function(t) {
+      return t.kind === 'video';
+    }).length;
+
+    // Determine number of audio and video tracks we need to send/recv.
+    if (offerOptions) {
+      // Reject Chrome legacy constraints.
+      if (offerOptions.mandatory || offerOptions.optional) {
+        throw new TypeError(
+            'Legacy mandatory/optional constraints not supported.');
+      }
+      if (offerOptions.offerToReceiveAudio !== undefined) {
+        if (offerOptions.offerToReceiveAudio === true) {
+          numAudioTracks = 1;
+        } else if (offerOptions.offerToReceiveAudio === false) {
+          numAudioTracks = 0;
+        } else {
+          numAudioTracks = offerOptions.offerToReceiveAudio;
+        }
+      }
+      if (offerOptions.offerToReceiveVideo !== undefined) {
+        if (offerOptions.offerToReceiveVideo === true) {
+          numVideoTracks = 1;
+        } else if (offerOptions.offerToReceiveVideo === false) {
+          numVideoTracks = 0;
+        } else {
+          numVideoTracks = offerOptions.offerToReceiveVideo;
+        }
+      }
+    }
+
+    this.transceivers.forEach(function(transceiver) {
+      if (transceiver.kind === 'audio') {
+        numAudioTracks--;
+        if (numAudioTracks < 0) {
+          transceiver.wantReceive = false;
+        }
+      } else if (transceiver.kind === 'video') {
+        numVideoTracks--;
+        if (numVideoTracks < 0) {
+          transceiver.wantReceive = false;
+        }
+      }
+    });
+
+    // Create M-lines for recvonly streams.
+    while (numAudioTracks > 0 || numVideoTracks > 0) {
+      if (numAudioTracks > 0) {
+        this._createTransceiver('audio');
+        numAudioTracks--;
+      }
+      if (numVideoTracks > 0) {
+        this._createTransceiver('video');
+        numVideoTracks--;
+      }
+    }
+    // reorder tracks
+    var transceivers = sortTracks(this.transceivers);
+
+    var sdp = SDPUtils.writeSessionBoilerplate();
+    transceivers.forEach(function(transceiver, sdpMLineIndex) {
+      // For each track, create an ice gatherer, ice transport,
+      // dtls transport, potentially rtpsender and rtpreceiver.
+      var track = transceiver.track;
+      var kind = transceiver.kind;
+      var mid = SDPUtils.generateIdentifier();
+      transceiver.mid = mid;
+
+      if (!transceiver.iceGatherer) {
+        transceiver.iceGatherer = self.usingBundle && sdpMLineIndex > 0 ?
+            transceivers[0].iceGatherer :
+            self._createIceGatherer(mid, sdpMLineIndex);
+      }
+
+      var localCapabilities = RTCRtpSender.getCapabilities(kind);
+      // filter RTX until additional stuff needed for RTX is implemented
+      // in adapter.js
+      if (edgeVersion < 15019) {
+        localCapabilities.codecs = localCapabilities.codecs.filter(
+            function(codec) {
+              return codec.name !== 'rtx';
+            });
+      }
+      localCapabilities.codecs.forEach(function(codec) {
+        // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
+        // by adding level-asymmetry-allowed=1
+        if (codec.name === 'H264' &&
+            codec.parameters['level-asymmetry-allowed'] === undefined) {
+          codec.parameters['level-asymmetry-allowed'] = '1';
+        }
+      });
+
+      // generate an ssrc now, to be used later in rtpSender.send
+      var sendEncodingParameters = [{
+        ssrc: (2 * sdpMLineIndex + 1) * 1001
+      }];
+      if (track) {
+        // add RTX
+        if (edgeVersion >= 15019 && kind === 'video') {
+          sendEncodingParameters[0].rtx = {
+            ssrc: (2 * sdpMLineIndex + 1) * 1001 + 1
+          };
+        }
+      }
+
+      if (transceiver.wantReceive) {
+        transceiver.rtpReceiver = new RTCRtpReceiver(transceiver.dtlsTransport,
+            kind);
+      }
+
+      transceiver.localCapabilities = localCapabilities;
+      transceiver.sendEncodingParameters = sendEncodingParameters;
+    });
+
+    // always offer BUNDLE and dispose on return if not supported.
+    if (this._config.bundlePolicy !== 'max-compat') {
+      sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) {
+        return t.mid;
+      }).join(' ') + '\r\n';
+    }
+    sdp += 'a=ice-options:trickle\r\n';
+
+    transceivers.forEach(function(transceiver, sdpMLineIndex) {
+      sdp += SDPUtils.writeMediaSection(transceiver,
+          transceiver.localCapabilities, 'offer', transceiver.stream);
+      sdp += 'a=rtcp-rsize\r\n';
+    });
+
+    this._pendingOffer = transceivers;
+    var desc = new RTCSessionDescription({
+      type: 'offer',
+      sdp: sdp
+    });
+    if (arguments.length && typeof arguments[0] === 'function') {
+      window.setTimeout(arguments[0], 0, desc);
+    }
+    return Promise.resolve(desc);
+  };
+
+  RTCPeerConnection.prototype.createAnswer = function() {
+    var sdp = SDPUtils.writeSessionBoilerplate();
+    if (this.usingBundle) {
+      sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
+        return t.mid;
+      }).join(' ') + '\r\n';
+    }
+    this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+      if (transceiver.isDatachannel) {
+        sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
+            'c=IN IP4 0.0.0.0\r\n' +
+            'a=mid:' + transceiver.mid + '\r\n';
+        return;
+      }
+
+      // FIXME: look at direction.
+      if (transceiver.stream) {
+        var localTrack;
+        if (transceiver.kind === 'audio') {
+          localTrack = transceiver.stream.getAudioTracks()[0];
+        } else if (transceiver.kind === 'video') {
+          localTrack = transceiver.stream.getVideoTracks()[0];
+        }
+        if (localTrack) {
+          // add RTX
+          if (edgeVersion >= 15019 && transceiver.kind === 'video') {
+            transceiver.sendEncodingParameters[0].rtx = {
+              ssrc: (2 * sdpMLineIndex + 2) * 1001 + 1
+            };
+          }
+        }
+      }
+
+      // Calculate intersection of capabilities.
+      var commonCapabilities = getCommonCapabilities(
+          transceiver.localCapabilities,
+          transceiver.remoteCapabilities);
+
+      var hasRtx = commonCapabilities.codecs.filter(function(c) {
+        return c.name.toLowerCase() === 'rtx';
+      }).length;
+      if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
+        delete transceiver.sendEncodingParameters[0].rtx;
+      }
+
+      sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities,
+          'answer', transceiver.stream);
+      if (transceiver.rtcpParameters &&
+          transceiver.rtcpParameters.reducedSize) {
+        sdp += 'a=rtcp-rsize\r\n';
+      }
+    });
+
+    var desc = new RTCSessionDescription({
+      type: 'answer',
+      sdp: sdp
+    });
+    if (arguments.length && typeof arguments[0] === 'function') {
+      window.setTimeout(arguments[0], 0, desc);
+    }
+    return Promise.resolve(desc);
+  };
+
+  RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
+    if (!candidate) {
+      for (var j = 0; j < this.transceivers.length; j++) {
+        this.transceivers[j].iceTransport.addRemoteCandidate({});
+        if (this.usingBundle) {
+          return Promise.resolve();
+        }
+      }
+    } else {
+      var mLineIndex = candidate.sdpMLineIndex;
+      if (candidate.sdpMid) {
+        for (var i = 0; i < this.transceivers.length; i++) {
+          if (this.transceivers[i].mid === candidate.sdpMid) {
+            mLineIndex = i;
+            break;
+          }
+        }
+      }
+      var transceiver = this.transceivers[mLineIndex];
+      if (transceiver) {
+        var cand = Object.keys(candidate.candidate).length > 0 ?
+            SDPUtils.parseCandidate(candidate.candidate) : {};
+        // Ignore Chrome's invalid candidates since Edge does not like them.
+        if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
+          return Promise.resolve();
+        }
+        // Ignore RTCP candidates, we assume RTCP-MUX.
+        if (cand.component &&
+            !(cand.component === '1' || cand.component === 1)) {
+          return Promise.resolve();
+        }
+        transceiver.iceTransport.addRemoteCandidate(cand);
+
+        // update the remoteDescription.
+        var sections = SDPUtils.splitSections(this.remoteDescription.sdp);
+        sections[mLineIndex + 1] += (cand.type ? candidate.candidate.trim()
+            : 'a=end-of-candidates') + '\r\n';
+        this.remoteDescription.sdp = sections.join('');
+      }
+    }
+    if (arguments.length > 1 && typeof arguments[1] === 'function') {
+      window.setTimeout(arguments[1], 0);
+    }
+    return Promise.resolve();
+  };
+
+  RTCPeerConnection.prototype.getStats = function() {
+    var promises = [];
+    this.transceivers.forEach(function(transceiver) {
+      ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
+        'dtlsTransport'].forEach(function(method) {
+          if (transceiver[method]) {
+            promises.push(transceiver[method].getStats());
+          }
+        });
+    });
+    var cb = arguments.length > 1 && typeof arguments[1] === 'function' &&
+        arguments[1];
+    var fixStatsType = function(stat) {
+      return {
+        inboundrtp: 'inbound-rtp',
+        outboundrtp: 'outbound-rtp',
+        candidatepair: 'candidate-pair',
+        localcandidate: 'local-candidate',
+        remotecandidate: 'remote-candidate'
+      }[stat.type] || stat.type;
+    };
+    return new Promise(function(resolve) {
+      // shim getStats with maplike support
+      var results = new Map();
+      Promise.all(promises).then(function(res) {
+        res.forEach(function(result) {
+          Object.keys(result).forEach(function(id) {
+            result[id].type = fixStatsType(result[id]);
+            results.set(id, result[id]);
+          });
+        });
+        if (cb) {
+          window.setTimeout(cb, 0, results);
+        }
+        resolve(results);
+      });
+    });
+  };
+  return RTCPeerConnection;
+};
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+var browserDetails = __webpack_require__(0).browserDetails;
+
+var firefoxShim = {
+  shimOnTrack: function() {
+    if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
+        window.RTCPeerConnection.prototype)) {
+      Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
+        get: function() {
+          return this._ontrack;
+        },
+        set: function(f) {
+          if (this._ontrack) {
+            this.removeEventListener('track', this._ontrack);
+            this.removeEventListener('addstream', this._ontrackpoly);
+          }
+          this.addEventListener('track', this._ontrack = f);
+          this.addEventListener('addstream', this._ontrackpoly = function(e) {
+            e.stream.getTracks().forEach(function(track) {
+              var event = new Event('track');
+              event.track = track;
+              event.receiver = {track: track};
+              event.streams = [e.stream];
+              this.dispatchEvent(event);
+            }.bind(this));
+          }.bind(this));
+        }
+      });
+    }
+  },
+
+  shimSourceObject: function() {
+    // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
+    if (typeof window === 'object') {
+      if (window.HTMLMediaElement &&
+        !('srcObject' in window.HTMLMediaElement.prototype)) {
+        // Shim the srcObject property, once, when HTMLMediaElement is found.
+        Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+          get: function() {
+            return this.mozSrcObject;
+          },
+          set: function(stream) {
+            this.mozSrcObject = stream;
+          }
+        });
+      }
+    }
+  },
+
+  shimPeerConnection: function() {
+    if (typeof window !== 'object' || !(window.RTCPeerConnection ||
+        window.mozRTCPeerConnection)) {
+      return; // probably media.peerconnection.enabled=false in about:config
+    }
+    // The RTCPeerConnection object.
+    if (!window.RTCPeerConnection) {
+      window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+        if (browserDetails.version < 38) {
+          // .urls is not supported in FF < 38.
+          // create RTCIceServers with a single url.
+          if (pcConfig && pcConfig.iceServers) {
+            var newIceServers = [];
+            for (var i = 0; i < pcConfig.iceServers.length; i++) {
+              var server = pcConfig.iceServers[i];
+              if (server.hasOwnProperty('urls')) {
+                for (var j = 0; j < server.urls.length; j++) {
+                  var newServer = {
+                    url: server.urls[j]
+                  };
+                  if (server.urls[j].indexOf('turn') === 0) {
+                    newServer.username = server.username;
+                    newServer.credential = server.credential;
+                  }
+                  newIceServers.push(newServer);
+                }
+              } else {
+                newIceServers.push(pcConfig.iceServers[i]);
+              }
+            }
+            pcConfig.iceServers = newIceServers;
+          }
+        }
+        return new mozRTCPeerConnection(pcConfig, pcConstraints);
+      };
+      window.RTCPeerConnection.prototype = mozRTCPeerConnection.prototype;
+
+      // wrap static methods. Currently just generateCertificate.
+      if (mozRTCPeerConnection.generateCertificate) {
+        Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+          get: function() {
+            return mozRTCPeerConnection.generateCertificate;
+          }
+        });
+      }
+
+      window.RTCSessionDescription = mozRTCSessionDescription;
+      window.RTCIceCandidate = mozRTCIceCandidate;
+    }
+
+    // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
+    ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
+        .forEach(function(method) {
+          var nativeMethod = RTCPeerConnection.prototype[method];
+          RTCPeerConnection.prototype[method] = function() {
+            arguments[0] = new ((method === 'addIceCandidate') ?
+                RTCIceCandidate : RTCSessionDescription)(arguments[0]);
+            return nativeMethod.apply(this, arguments);
+          };
+        });
+
+    // support for addIceCandidate(null or undefined)
+    var nativeAddIceCandidate =
+        RTCPeerConnection.prototype.addIceCandidate;
+    RTCPeerConnection.prototype.addIceCandidate = function() {
+      if (!arguments[0]) {
+        if (arguments[1]) {
+          arguments[1].apply(null);
+        }
+        return Promise.resolve();
+      }
+      return nativeAddIceCandidate.apply(this, arguments);
+    };
+
+    // shim getStats with maplike support
+    var makeMapStats = function(stats) {
+      var map = new Map();
+      Object.keys(stats).forEach(function(key) {
+        map.set(key, stats[key]);
+        map[key] = stats[key];
+      });
+      return map;
+    };
+
+    var modernStatsTypes = {
+      inboundrtp: 'inbound-rtp',
+      outboundrtp: 'outbound-rtp',
+      candidatepair: 'candidate-pair',
+      localcandidate: 'local-candidate',
+      remotecandidate: 'remote-candidate'
+    };
+
+    var nativeGetStats = RTCPeerConnection.prototype.getStats;
+    RTCPeerConnection.prototype.getStats = function(selector, onSucc, onErr) {
+      return nativeGetStats.apply(this, [selector || null])
+        .then(function(stats) {
+          if (browserDetails.version < 48) {
+            stats = makeMapStats(stats);
+          }
+          if (browserDetails.version < 53 && !onSucc) {
+            // Shim only promise getStats with spec-hyphens in type names
+            // Leave callback version alone; misc old uses of forEach before Map
+            try {
+              stats.forEach(function(stat) {
+                stat.type = modernStatsTypes[stat.type] || stat.type;
+              });
+            } catch (e) {
+              if (e.name !== 'TypeError') {
+                throw e;
+              }
+              // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
+              stats.forEach(function(stat, i) {
+                stats.set(i, Object.assign({}, stat, {
+                  type: modernStatsTypes[stat.type] || stat.type
+                }));
+              });
+            }
+          }
+          return stats;
+        })
+        .then(onSucc, onErr);
+    };
+  }
+};
+
+// Expose public methods.
+module.exports = {
+  shimOnTrack: firefoxShim.shimOnTrack,
+  shimSourceObject: firefoxShim.shimSourceObject,
+  shimPeerConnection: firefoxShim.shimPeerConnection,
+  shimGetUserMedia: __webpack_require__(15)
+};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+ /* eslint-env node */
+
+
+var logging = __webpack_require__(0).log;
+var browserDetails = __webpack_require__(0).browserDetails;
+
+// Expose public methods.
+module.exports = function() {
+  var shimError_ = function(e) {
+    return {
+      name: {
+        InternalError: 'NotReadableError',
+        NotSupportedError: 'TypeError',
+        PermissionDeniedError: 'NotAllowedError',
+        SecurityError: 'NotAllowedError'
+      }[e.name] || e.name,
+      message: {
+        'The operation is insecure.': 'The request is not allowed by the ' +
+        'user agent or the platform in the current context.'
+      }[e.message] || e.message,
+      constraint: e.constraint,
+      toString: function() {
+        return this.name + (this.message && ': ') + this.message;
+      }
+    };
+  };
+
+  // getUserMedia constraints shim.
+  var getUserMedia_ = function(constraints, onSuccess, onError) {
+    var constraintsToFF37_ = function(c) {
+      if (typeof c !== 'object' || c.require) {
+        return c;
+      }
+      var require = [];
+      Object.keys(c).forEach(function(key) {
+        if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+          return;
+        }
+        var r = c[key] = (typeof c[key] === 'object') ?
+            c[key] : {ideal: c[key]};
+        if (r.min !== undefined ||
+            r.max !== undefined || r.exact !== undefined) {
+          require.push(key);
+        }
+        if (r.exact !== undefined) {
+          if (typeof r.exact === 'number') {
+            r. min = r.max = r.exact;
+          } else {
+            c[key] = r.exact;
+          }
+          delete r.exact;
+        }
+        if (r.ideal !== undefined) {
+          c.advanced = c.advanced || [];
+          var oc = {};
+          if (typeof r.ideal === 'number') {
+            oc[key] = {min: r.ideal, max: r.ideal};
+          } else {
+            oc[key] = r.ideal;
+          }
+          c.advanced.push(oc);
+          delete r.ideal;
+          if (!Object.keys(r).length) {
+            delete c[key];
+          }
+        }
+      });
+      if (require.length) {
+        c.require = require;
+      }
+      return c;
+    };
+    constraints = JSON.parse(JSON.stringify(constraints));
+    if (browserDetails.version < 38) {
+      logging('spec: ' + JSON.stringify(constraints));
+      if (constraints.audio) {
+        constraints.audio = constraintsToFF37_(constraints.audio);
+      }
+      if (constraints.video) {
+        constraints.video = constraintsToFF37_(constraints.video);
+      }
+      logging('ff37: ' + JSON.stringify(constraints));
+    }
+    return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
+      onError(shimError_(e));
+    });
+  };
+
+  // Returns the result of getUserMedia as a Promise.
+  var getUserMediaPromise_ = function(constraints) {
+    return new Promise(function(resolve, reject) {
+      getUserMedia_(constraints, resolve, reject);
+    });
+  };
+
+  // Shim for mediaDevices on older versions.
+  if (!navigator.mediaDevices) {
+    navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
+      addEventListener: function() { },
+      removeEventListener: function() { }
+    };
+  }
+  navigator.mediaDevices.enumerateDevices =
+      navigator.mediaDevices.enumerateDevices || function() {
+        return new Promise(function(resolve) {
+          var infos = [
+            {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
+            {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
+          ];
+          resolve(infos);
+        });
+      };
+
+  if (browserDetails.version < 41) {
+    // Work around http://bugzil.la/1169665
+    var orgEnumerateDevices =
+        navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
+    navigator.mediaDevices.enumerateDevices = function() {
+      return orgEnumerateDevices().then(undefined, function(e) {
+        if (e.name === 'NotFoundError') {
+          return [];
+        }
+        throw e;
+      });
+    };
+  }
+  if (browserDetails.version < 49) {
+    var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+        bind(navigator.mediaDevices);
+    navigator.mediaDevices.getUserMedia = function(c) {
+      return origGetUserMedia(c).then(function(stream) {
+        // Work around https://bugzil.la/802326
+        if (c.audio && !stream.getAudioTracks().length ||
+            c.video && !stream.getVideoTracks().length) {
+          stream.getTracks().forEach(function(track) {
+            track.stop();
+          });
+          throw new DOMException('The object can not be found here.',
+                                 'NotFoundError');
+        }
+        return stream;
+      }, function(e) {
+        return Promise.reject(shimError_(e));
+      });
+    };
+  }
+  navigator.getUserMedia = function(constraints, onSuccess, onError) {
+    if (browserDetails.version < 44) {
+      return getUserMedia_(constraints, onSuccess, onError);
+    }
+    // Replace Firefox 44+'s deprecation warning with unprefixed version.
+    console.warn('navigator.getUserMedia has been replaced by ' +
+                 'navigator.mediaDevices.getUserMedia');
+    navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
+  };
+};
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree.
+ */
+
+var safariShim = {
+  // TODO: DrAlex, should be here, double check against LayoutTests
+
+  // TODO: once the back-end for the mac port is done, add.
+  // TODO: check for webkitGTK+
+  // shimPeerConnection: function() { },
+
+  shimAddStream: function() {
+    if (typeof window === 'object' && window.RTCPeerConnection &&
+        !('addStream' in window.RTCPeerConnection.prototype)) {
+      RTCPeerConnection.prototype.addStream = function(stream) {
+        var self = this;
+        stream.getTracks().forEach(function(track) {
+          self.addTrack(track, stream);
+        });
+      };
+    }
+  },
+  shimOnAddStream: function() {
+    if (typeof window === 'object' && window.RTCPeerConnection &&
+        !('onaddstream' in window.RTCPeerConnection.prototype)) {
+      Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
+        get: function() {
+          return this._onaddstream;
+        },
+        set: function(f) {
+          if (this._onaddstream) {
+            this.removeEventListener('addstream', this._onaddstream);
+            this.removeEventListener('track', this._onaddstreampoly);
+          }
+          this.addEventListener('addstream', this._onaddstream = f);
+          this.addEventListener('track', this._onaddstreampoly = function(e) {
+            var stream = e.streams[0];
+            if (!this._streams) {
+              this._streams = [];
+            }
+            if (this._streams.indexOf(stream) >= 0) {
+              return;
+            }
+            this._streams.push(stream);
+            var event = new Event('addstream');
+            event.stream = e.streams[0];
+            this.dispatchEvent(event);
+          }.bind(this));
+        }
+      });
+    }
+  },
+  shimCallbacksAPI: function() {
+    if (typeof window !== 'object' || !window.RTCPeerConnection) {
+      return;
+    }
+    var prototype = RTCPeerConnection.prototype;
+    var createOffer = prototype.createOffer;
+    var createAnswer = prototype.createAnswer;
+    var setLocalDescription = prototype.setLocalDescription;
+    var setRemoteDescription = prototype.setRemoteDescription;
+    var addIceCandidate = prototype.addIceCandidate;
+
+    prototype.createOffer = function(successCallback, failureCallback) {
+      var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
+      var promise = createOffer.apply(this, [options]);
+      if (!failureCallback) {
+        return promise;
+      }
+      promise.then(successCallback, failureCallback);
+      return Promise.resolve();
+    };
+
+    prototype.createAnswer = function(successCallback, failureCallback) {
+      var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
+      var promise = createAnswer.apply(this, [options]);
+      if (!failureCallback) {
+        return promise;
+      }
+      promise.then(successCallback, failureCallback);
+      return Promise.resolve();
+    };
+
+    var withCallback = function(description, successCallback, failureCallback) {
+      var promise = setLocalDescription.apply(this, [description]);
+      if (!failureCallback) {
+        return promise;
+      }
+      promise.then(successCallback, failureCallback);
+      return Promise.resolve();
+    };
+    prototype.setLocalDescription = withCallback;
+
+    withCallback = function(description, successCallback, failureCallback) {
+      var promise = setRemoteDescription.apply(this, [description]);
+      if (!failureCallback) {
+        return promise;
+      }
+      promise.then(successCallback, failureCallback);
+      return Promise.resolve();
+    };
+    prototype.setRemoteDescription = withCallback;
+
+    withCallback = function(candidate, successCallback, failureCallback) {
+      var promise = addIceCandidate.apply(this, [candidate]);
+      if (!failureCallback) {
+        return promise;
+      }
+      promise.then(successCallback, failureCallback);
+      return Promise.resolve();
+    };
+    prototype.addIceCandidate = withCallback;
+  },
+  shimGetUserMedia: function() {
+    if (!navigator.getUserMedia) {
+      if (navigator.webkitGetUserMedia) {
+        navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
+      } else if (navigator.mediaDevices &&
+          navigator.mediaDevices.getUserMedia) {
+        navigator.getUserMedia = function(constraints, cb, errcb) {
+          navigator.mediaDevices.getUserMedia(constraints)
+          .then(cb, errcb);
+        }.bind(navigator);
+      }
+    }
+  }
+};
+
+// Expose public methods.
+module.exports = {
+  shimCallbacksAPI: safariShim.shimCallbacksAPI,
+  shimAddStream: safariShim.shimAddStream,
+  shimOnAddStream: safariShim.shimOnAddStream,
+  shimGetUserMedia: safariShim.shimGetUserMedia
+  // TODO
+  // shimPeerConnection: safariShim.shimPeerConnection
+};
+
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var cordovaRequire = __webpack_require__(5);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerInternal = __webpack_require__(2);
+
+cordovaModule.exports = createQRScannerInternal();
+cordovaRequire('cordova/exec/proxy').add('QRScanner', cordovaModule.exports);
+
+
+/***/ })
+/******/ ]);
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..5d95c0a
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,343 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) { // This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+  switch (string) {
+    case '1':
+      return true;
+    case '0':
+      return false;
+    default:
+    throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+  }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+  return {
+    authorized: stringToBool(statusDictionary.authorized),
+    denied: stringToBool(statusDictionary.denied),
+    restricted: stringToBool(statusDictionary.restricted),
+    prepared: stringToBool(statusDictionary.prepared),
+    scanning: stringToBool(statusDictionary.scanning),
+    previewing: stringToBool(statusDictionary.previewing),
+    showing: stringToBool(statusDictionary.showing),
+    lightEnabled: stringToBool(statusDictionary.lightEnabled),
+    canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+    canEnableLight: stringToBool(statusDictionary.canEnableLight),
+    canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+    currentCamera: parseInt(statusDictionary.currentCamera)
+  };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+  var body = document.body;
+  if (body.style) {
+    body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+    body.style.backgroundImage = '';
+    setTimeout(function() {
+      body.style.backgroundColor = 'transparent';
+    }, 1);
+    if (body.parentNode && body.parentNode.style) {
+      body.parentNode.style.backgroundColor = 'transparent';
+      body.parentNode.style.backgroundImage = '';
+    }
+  }
+}
+
+function errorCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(error) {
+    var errorCode = parseInt(error);
+    var QRScannerError = {};
+    switch (errorCode) {
+      case 0:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner experienced an unexpected error.'
+        };
+        break;
+      case 1:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_DENIED',
+          code: 1,
+          _message: 'The user denied camera access.'
+        };
+        break;
+      case 2:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_RESTRICTED',
+          code: 2,
+          _message: 'Camera access is restricted.'
+        };
+        break;
+      case 3:
+        QRScannerError = {
+          name: 'BACK_CAMERA_UNAVAILABLE',
+          code: 3,
+          _message: 'The back camera is unavailable.'
+        };
+        break;
+      case 4:
+        QRScannerError = {
+          name: 'FRONT_CAMERA_UNAVAILABLE',
+          code: 4,
+          _message: 'The front camera is unavailable.'
+        };
+        break;
+      case 5:
+        QRScannerError = {
+          name: 'CAMERA_UNAVAILABLE',
+          code: 5,
+          _message: 'The camera is unavailable.'
+        };
+        break;
+      case 6:
+        QRScannerError = {
+          name: 'SCAN_CANCELED',
+          code: 6,
+          _message: 'Scan was canceled.'
+        };
+        break;
+      case 7:
+        QRScannerError = {
+          name: 'LIGHT_UNAVAILABLE',
+          code: 7,
+          _message: 'The device light is unavailable.'
+        };
+        break;
+      case 8:
+        // Open settings is only available on iOS 8.0+.
+        QRScannerError = {
+          name: 'OPEN_SETTINGS_UNAVAILABLE',
+          code: 8,
+          _message: 'The device is unable to open settings.'
+        };
+        break;
+      default:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner returned an invalid error code.'
+        };
+        break;
+    }
+    callback(QRScannerError);
+  };
+}
+
+function successCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    callback(null, convertStatus(statusDict));
+  };
+}
+
+function doneCallback(callback, clear) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    if (clear) {
+      clearBackground();
+    }
+    callback(convertStatus(statusDict));
+  };
+}
+
+return {
+  prepare: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+  },
+  destroy: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+  },
+  scan: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to scan method.');
+    }
+    var success = function(result) {
+      callback(null, result);
+    };
+    cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+  },
+  cancelScan: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+  },
+  show: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+  },
+  hide: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+  },
+  pausePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+  },
+  resumePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+  },
+  enableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+  },
+  disableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+  },
+  useCamera: function(index, callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+  },
+  useFrontCamera: function(callback) {
+    var frontCamera = 1;
+    if (callback) {
+      this.useCamera(frontCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+    }
+  },
+  useBackCamera: function(callback) {
+    var backCamera = 0;
+    if (callback) {
+      this.useCamera(backCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+    }
+  },
+  openSettings: function(callback) {
+    if (callback) {
+      cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+    }
+  },
+  getStatus: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to getStatus method.');
+    }
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+  }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js
new file mode 100644
index 0000000..6f04cf5
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/src/browser/SplashScreenProxy.js
@@ -0,0 +1,172 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreenProxy", function(require, exports, module) { /*

+ *

+ * 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.

+ *

+*/

+

+// Default parameter values including image size can be changed in `config.xml`

+var splashImageWidth = 170;

+var splashImageHeight = 200;

+var position = { x: 0, y: 0, width: splashImageWidth, height: splashImageHeight }; 

+var localSplash; // the image to display

+var localSplashImage;

+var bgColor = "#464646";

+var imageSrc = '/img/logo.png';

+var splashScreenDelay = 3000; // in milliseconds

+var showSplashScreen = true; // show splashcreen by default

+var cordova = require('cordova');

+var configHelper = cordova.require('cordova/confighelper');

+var autoHideSplashScreen = true;

+

+function updateImageLocation() {

+    position.width = Math.min(splashImageWidth, window.innerWidth);

+    position.height = position.width * (splashImageHeight / splashImageWidth);

+

+    localSplash.style.width = window.innerWidth + "px";

+    localSplash.style.height = window.innerHeight + "px";

+    localSplash.style.top = "0px";

+    localSplash.style.left = "0px";

+

+    localSplashImage.style.top = "50%";

+    localSplashImage.style.left = "50%";

+    localSplashImage.style.height = position.height + "px";

+    localSplashImage.style.width = position.width + "px";

+    localSplashImage.style.marginTop = (-position.height / 2) + "px";

+    localSplashImage.style.marginLeft = (-position.width / 2) + "px";

+}

+

+function onResize() {

+    updateImageLocation();

+}

+

+var SplashScreen = {

+    setBGColor: function (cssBGColor) {

+        bgColor = cssBGColor;

+        if (localSplash) {

+            localSplash.style.backgroundColor = bgColor;

+        }

+    },

+    show: function () {

+        if(!localSplash) {

+            window.addEventListener("resize", onResize, false);

+            localSplash = document.createElement("div");

+            localSplash.style.backgroundColor = bgColor;

+            localSplash.style.position = "absolute";

+            localSplash.style["z-index"] = "99999";

+

+            localSplashImage = document.createElement("img");

+            localSplashImage.src = imageSrc;

+            localSplashImage.style.position = "absolute";

+

+            updateImageLocation();

+

+            localSplash.appendChild(localSplashImage);

+            document.body.appendChild(localSplash);

+

+            // deviceready fires earlier than the plugin init on cold-start

+            if (SplashScreen.shouldHideImmediately) {

+                SplashScreen.shouldHideImmediately = false;

+                window.setTimeout(function () {

+                    SplashScreen.hide();

+                }, 1000);

+            }

+        }

+    },

+    hide: function () {

+        if(localSplash) {

+            var innerLocalSplash = localSplash;

+            localSplash = null;

+            window.removeEventListener("resize", onResize, false);

+

+            innerLocalSplash.style.opacity = '0';

+            innerLocalSplash.style["-webkit-transition"] = "opacity 1s ease-in-out";

+            innerLocalSplash.style["-moz-transition"] = "opacity 1s ease-in-out";

+            innerLocalSplash.style["-ms-transition"] = "opacity 1s ease-in-out";

+            innerLocalSplash.style["-o-transition"] = "opacity 1s ease-in-out";

+

+            window.setTimeout(function () {

+                document.body.removeChild(innerLocalSplash);

+                innerLocalSplash = null;

+            }, 1000);

+        } else {

+            SplashScreen.shouldHideImmediately = true;

+        }

+    }

+};

+

+/**

+ * Reads preferences via ConfigHelper and substitutes default parameters.

+ */

+function readPreferencesFromCfg(cfg) {

+    try {

+        var value = cfg.getPreferenceValue('ShowSplashScreen');

+        if(typeof value != 'undefined') {

+            showSplashScreen = value === 'true';

+        }

+

+        splashScreenDelay = cfg.getPreferenceValue('SplashScreenDelay') || splashScreenDelay;

+        splashScreenDelay = parseInt(splashScreenDelay, 10);

+

+        imageSrc = cfg.getPreferenceValue('SplashScreen') || imageSrc;

+        bgColor = cfg.getPreferenceValue('SplashScreenBackgroundColor') || bgColor;

+        splashImageWidth = cfg.getPreferenceValue('SplashScreenWidth') || splashImageWidth;

+        splashImageHeight = cfg.getPreferenceValue('SplashScreenHeight') || splashImageHeight;

+        autoHideSplashScreen = cfg.getPreferenceValue('AutoHideSplashScreen') || autoHideSplashScreen;

+        autoHideSplashScreen = (autoHideSplashScreen === true || autoHideSplashScreen.toLowerCase() === 'true');

+    } catch(e) {

+        var msg = '[Browser][SplashScreen] Error occurred on loading preferences from config.xml: ' + JSON.stringify(e);

+        console.error(msg);

+    }

+}

+

+/**

+ * Shows and hides splashscreen if it is enabled, with a delay according the current preferences.

+ */

+function showAndHide() {

+    if(showSplashScreen) {

+        SplashScreen.show();

+

+        window.setTimeout(function() {

+            SplashScreen.hide();

+        }, splashScreenDelay);

+    }

+}

+

+/**

+ * Tries to read config.xml and override default properties and then shows and hides splashscreen if it is enabled.

+ */

+(function initAndShow() {

+    configHelper.readConfig(function(config) {

+        readPreferencesFromCfg(config);

+        if (autoHideSplashScreen) {

+            showAndHide();

+        } else {

+            SplashScreen.show();

+        }

+

+    }, function(err) {

+        console.error(err);

+    });

+})();

+

+module.exports = SplashScreen;

+

+require("cordova/exec/proxy").add("SplashScreen", SplashScreen);

+

+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
new file mode 100644
index 0000000..5b42e17
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-splashscreen/www/splashscreen.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-splashscreen.SplashScreen", function(require, exports, module) { /*

+ *

+ * 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.

+ *

+*/

+

+var exec = require('cordova/exec');

+

+var splashscreen = {

+    show:function() {

+        exec(null, null, "SplashScreen", "show", []);

+    },

+    hide:function() {

+        exec(null, null, "SplashScreen", "hide", []);

+    }

+};

+

+module.exports = splashscreen;

+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js
new file mode 100644
index 0000000..e6e41ec
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/src/browser/StatusBarProxy.js
@@ -0,0 +1,52 @@
+cordova.define("cordova-plugin-statusbar.StatusBarProxy", function(require, exports, module) { /*
+ * 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.
+ *
+ */
+
+function notSupported(win,fail) {
+    //
+    console.log('StatusBar is not supported');
+    setTimeout(function(){
+        if (win) {
+            win();
+        }
+        // note that while it is not explicitly supported, it does not fail
+        // this is really just here to allow developers to test their code in the browser
+        // and if we fail, then their app might as well. -jm
+    },0);
+}
+
+module.exports = {
+    isVisible: false,
+    styleBlackTranslucent:notSupported,
+    styleDefault:notSupported,
+    styleLightContent:notSupported,
+    styleBlackOpaque:notSupported,
+    overlaysWebView:notSupported,
+    styleLightContect: notSupported,
+    backgroundColorByName: notSupported,
+    backgroundColorByHexString: notSupported,
+    hide: notSupported,
+    show: notSupported,
+    _ready:notSupported
+};
+
+require("cordova/exec/proxy").add("StatusBar", module.exports);
+
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..9684d23
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,115 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) { /*
+ *
+ * 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.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+    "black": "#000000",
+    "darkGray": "#A9A9A9",
+    "lightGray": "#D3D3D3",
+    "white": "#FFFFFF",
+    "gray": "#808080",
+    "red": "#FF0000",
+    "green": "#00FF00",
+    "blue": "#0000FF",
+    "cyan": "#00FFFF",
+    "yellow": "#FFFF00",
+    "magenta": "#FF00FF",
+    "orange": "#FFA500",
+    "purple": "#800080",
+    "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+    isVisible: true,
+
+    overlaysWebView: function (doOverlay) {
+        exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+    },
+
+    styleDefault: function () {
+        // dark text ( to be used on a light background )
+        exec(null, null, "StatusBar", "styleDefault", []);
+    },
+
+    styleLightContent: function () {
+        // light text ( to be used on a dark background )
+        exec(null, null, "StatusBar", "styleLightContent", []);
+    },
+
+    styleBlackTranslucent: function () {
+        // #88000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+    },
+
+    styleBlackOpaque: function () {
+        // #FF000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackOpaque", []);
+    },
+
+    backgroundColorByName: function (colorname) {
+        return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+    },
+
+    backgroundColorByHexString: function (hexString) {
+        if (hexString.charAt(0) !== "#") {
+            hexString = "#" + hexString;
+        }
+
+        if (hexString.length === 4) {
+            var split = hexString.split("");
+            hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+        }
+
+        exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+    },
+
+    hide: function () {
+        exec(null, null, "StatusBar", "hide", []);
+        StatusBar.isVisible = false;
+    },
+
+    show: function () {
+        exec(null, null, "StatusBar", "show", []);
+        StatusBar.isVisible = true;
+    }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+    exec(function (res) {
+        if (typeof res == 'object') {
+            if (res.type == 'tap') {
+                cordova.fireWindowEvent('statusTap');
+            }
+        } else {
+            StatusBar.isVisible = res;
+        }
+    }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..6e4b765
--- /dev/null
+++ b/platforms/browser/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,35 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) { function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+  if (!window.plugins) {
+    window.plugins = {};
+  }
+
+  window.plugins.touchid = new TouchID();
+  return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});
diff --git a/platforms/ios/.gitignore b/platforms/ios/.gitignore
new file mode 100644
index 0000000..cc76483
--- /dev/null
+++ b/platforms/ios/.gitignore
@@ -0,0 +1,5 @@
+*.mode1v3
+*.perspectivev3
+*.pbxuser
+.DS_Store
+build/
diff --git a/platforms/ios/CordovaLib/Classes/Private/CDVDebug.h b/platforms/ios/CordovaLib/Classes/Private/CDVDebug.h
new file mode 100644
index 0000000..4a0d9f9
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/CDVDebug.h
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+#ifdef DEBUG
+    #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+    #define DLog(...)
+#endif
+#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
diff --git a/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.h b/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.h
new file mode 100644
index 0000000..afb5cc6
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.h
@@ -0,0 +1,31 @@
+/*
+ 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.
+ */
+
+@interface NSArray (CDVJSONSerializingPrivate)
+- (NSString*)cdv_JSONString;
+@end
+
+@interface NSDictionary (CDVJSONSerializingPrivate)
+- (NSString*)cdv_JSONString;
+@end
+
+@interface NSString (CDVJSONSerializingPrivate)
+- (id)cdv_JSONObject;
+- (id)cdv_JSONFragment;
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.m b/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.m
new file mode 100644
index 0000000..175ed39
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.m
@@ -0,0 +1,99 @@
+/*
+ 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.
+ */
+
+#import "CDVJSON_private.h"
+#import <Foundation/NSJSONSerialization.h>
+
+@implementation NSArray (CDVJSONSerializingPrivate)
+
+- (NSString*)cdv_JSONString
+{
+    @autoreleasepool {
+        NSError* error = nil;
+        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
+                                                           options:0
+                                                             error:&error];
+
+        if (error != nil) {
+            NSLog(@"NSArray JSONString error: %@", [error localizedDescription]);
+            return nil;
+        } else {
+            return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+        }
+    }
+}
+
+@end
+
+@implementation NSDictionary (CDVJSONSerializingPrivate)
+
+- (NSString*)cdv_JSONString
+{
+    @autoreleasepool {
+        NSError* error = nil;
+        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:self
+                                                           options:NSJSONWritingPrettyPrinted
+                                                             error:&error];
+
+        if (error != nil) {
+            NSLog(@"NSDictionary JSONString error: %@", [error localizedDescription]);
+            return nil;
+        } else {
+            return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+        }
+    }
+}
+
+@end
+
+@implementation NSString (CDVJSONSerializingPrivate)
+
+- (id)cdv_JSONObject
+{
+    @autoreleasepool {   
+        NSError* error = nil;
+        id object = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
+                                                    options:NSJSONReadingMutableContainers
+                                                      error:&error];
+
+        if (error != nil) {
+            NSLog(@"NSString JSONObject error: %@, Malformed Data: %@", [error localizedDescription], self);
+        }
+
+        return object;
+    }
+}
+
+- (id)cdv_JSONFragment
+{
+    @autoreleasepool {
+        NSError* error = nil;
+        id object = [NSJSONSerialization JSONObjectWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
+                                                    options:NSJSONReadingAllowFragments
+                                                      error:&error];
+
+        if (error != nil) {
+            NSLog(@"NSString JSONObject error: %@", [error localizedDescription]);
+        }
+
+        return object;
+    }
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/CDVPlugin+Private.h b/platforms/ios/CordovaLib/Classes/Private/CDVPlugin+Private.h
new file mode 100644
index 0000000..f88638c
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/CDVPlugin+Private.h
@@ -0,0 +1,24 @@
+/*
+ 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.
+ */
+
+@interface CDVPlugin (Private)
+
+- (instancetype)initWithWebViewEngine:(id <CDVWebViewEngineProtocol>)theWebViewEngine;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h
new file mode 100644
index 0000000..f39e066
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h
@@ -0,0 +1,26 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+
+@interface CDVGestureHandler : CDVPlugin
+
+@property (nonatomic, strong) UILongPressGestureRecognizer* lpgr;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m
new file mode 100644
index 0000000..34ed463
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m
@@ -0,0 +1,70 @@
+/*
+ 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.
+ */
+
+#import "CDVGestureHandler.h"
+
+@implementation CDVGestureHandler
+
+- (void)pluginInitialize
+{
+    [self applyLongPressFix];
+}
+
+- (void)applyLongPressFix
+{
+    // You can't suppress 3D Touch and still have regular longpress,
+    // so if this is false, let's not consider the 3D Touch setting at all.
+    if (![self.commandDelegate.settings objectForKey:@"suppresseslongpressgesture"] ||
+        ![[self.commandDelegate.settings objectForKey:@"suppresseslongpressgesture"] boolValue]) {
+        return;
+    }
+
+    self.lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGestures:)];
+    self.lpgr.minimumPressDuration = 0.45f;
+    self.lpgr.allowableMovement = 200.0f;
+
+    // 0.45 is ok for 'regular longpress', 0.05-0.08 is required for '3D Touch longpress',
+    // but since this will also kill onclick handlers (not ontouchend) it's optional.
+    if ([self.commandDelegate.settings objectForKey:@"suppresses3dtouchgesture"] &&
+        [[self.commandDelegate.settings objectForKey:@"suppresses3dtouchgesture"] boolValue]) {
+        self.lpgr.minimumPressDuration = 0.15f;
+    }
+
+    NSArray *views = self.webView.subviews;
+    if (views.count == 0) {
+        NSLog(@"No webview subviews found, not applying the longpress fix.");
+        return;
+    }
+    for (int i=0; i<views.count; i++) {
+        UIView *webViewScrollView = views[i];
+        if ([webViewScrollView isKindOfClass:[UIScrollView class]]) {
+            NSArray *webViewScrollViewSubViews = webViewScrollView.subviews;
+            UIView *browser = webViewScrollViewSubViews[0];
+            [browser addGestureRecognizer:self.lpgr];
+            break;
+        }
+    }
+}
+
+- (void)handleLongPressGestures:(UILongPressGestureRecognizer*)sender
+{
+    
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.h
new file mode 100644
index 0000000..37dab40
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.h
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+
+@interface CDVHandleOpenURL : CDVPlugin
+
+@property (nonatomic, strong) NSURL* url;
+@property (nonatomic, assign) BOOL pageLoaded;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.m
new file mode 100644
index 0000000..400cb9d
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.m
@@ -0,0 +1,86 @@
+/*
+ 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.
+ */
+
+#import "CDVHandleOpenURL.h"
+#import <Cordova/CDV.h>
+
+@implementation CDVHandleOpenURL
+
+- (void)pluginInitialize
+{
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationLaunchedWithUrl:) name:CDVPluginHandleOpenURLNotification object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationPageDidLoad:) name:CDVPageDidLoadNotification object:nil];
+}
+
+- (void)applicationLaunchedWithUrl:(NSNotification*)notification
+{
+    NSURL* url = [notification object];
+
+    self.url = url;
+
+    // warm-start handler
+    if (self.pageLoaded) {
+        [self processOpenUrl:self.url pageLoaded:YES];
+        self.url = nil;
+    }
+}
+
+- (void)applicationPageDidLoad:(NSNotification*)notification
+{
+    // cold-start handler
+
+    self.pageLoaded = YES;
+
+    if (self.url) {
+        [self processOpenUrl:self.url pageLoaded:YES];
+        self.url = nil;
+    }
+}
+
+- (void)processOpenUrl:(NSURL*)url pageLoaded:(BOOL)pageLoaded
+{
+    __weak __typeof(self) weakSelf = self;
+
+    dispatch_block_t handleOpenUrl = ^(void) {
+        // calls into javascript global function 'handleOpenURL'
+        NSString* jsString = [NSString stringWithFormat:@"document.addEventListener('deviceready',function(){if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}});", url.absoluteString];
+
+        [weakSelf.webViewEngine evaluateJavaScript:jsString completionHandler:nil];
+    };
+
+    if (!pageLoaded) {
+        NSString* jsString = @"document.readystate";
+        [self.webViewEngine evaluateJavaScript:jsString
+                             completionHandler:^(id object, NSError* error) {
+            if ((error == nil) && [object isKindOfClass:[NSString class]]) {
+                NSString* readyState = (NSString*)object;
+                BOOL ready = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+                if (ready) {
+                    handleOpenUrl();
+                } else {
+                    self.url = url;
+                }
+            }
+        }];
+    } else {
+        handleOpenUrl();
+    }
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h
new file mode 100644
index 0000000..94c10de
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h
@@ -0,0 +1,34 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+#import <Cordova/CDVWhitelist.h>
+
+typedef NS_ENUM(NSInteger, CDVIntentAndNavigationFilterValue) {
+    CDVIntentAndNavigationFilterValueIntentAllowed,
+    CDVIntentAndNavigationFilterValueNavigationAllowed,
+    CDVIntentAndNavigationFilterValueNoneAllowed
+};
+
+@interface CDVIntentAndNavigationFilter : CDVPlugin <NSXMLParserDelegate>
+
++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist;
++ (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType filterValue:(CDVIntentAndNavigationFilterValue)filterValue;
++ (BOOL)shouldOpenURLRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m
new file mode 100644
index 0000000..ccfe77e
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m
@@ -0,0 +1,142 @@
+/*
+ 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.
+ */
+
+#import "CDVIntentAndNavigationFilter.h"
+#import <Cordova/CDV.h>
+
+@interface CDVIntentAndNavigationFilter ()
+
+@property (nonatomic, readwrite) NSMutableArray* allowIntents;
+@property (nonatomic, readwrite) NSMutableArray* allowNavigations;
+@property (nonatomic, readwrite) CDVWhitelist* allowIntentsWhitelist;
+@property (nonatomic, readwrite) CDVWhitelist* allowNavigationsWhitelist;
+
+@end
+
+@implementation CDVIntentAndNavigationFilter
+
+#pragma mark NSXMLParserDelegate
+
+- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName attributes:(NSDictionary*)attributeDict
+{
+    if ([elementName isEqualToString:@"allow-navigation"]) {
+        [self.allowNavigations addObject:attributeDict[@"href"]];
+    }
+    if ([elementName isEqualToString:@"allow-intent"]) {
+        [self.allowIntents addObject:attributeDict[@"href"]];
+    }
+}
+
+- (void)parserDidStartDocument:(NSXMLParser*)parser
+{
+    // file: url <allow-navigations> are added by default
+    self.allowNavigations = [[NSMutableArray alloc] initWithArray:@[ @"file://" ]];
+    // no intents are added by default
+    self.allowIntents = [[NSMutableArray alloc] init];
+}
+
+- (void)parserDidEndDocument:(NSXMLParser*)parser
+{
+    self.allowIntentsWhitelist = [[CDVWhitelist alloc] initWithArray:self.allowIntents];
+    self.allowNavigationsWhitelist = [[CDVWhitelist alloc] initWithArray:self.allowNavigations];
+}
+
+- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
+{
+    NSAssert(NO, @"config.xml parse error line %ld col %ld", (long)[parser lineNumber], (long)[parser columnNumber]);
+}
+
+#pragma mark CDVPlugin
+
+- (void)pluginInitialize
+{
+    if ([self.viewController isKindOfClass:[CDVViewController class]]) {
+        [(CDVViewController*)self.viewController parseSettingsWithParser:self];
+    }
+}
+
++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist
+{
+    // a URL can only allow-intent OR allow-navigation, if both are specified,
+    // only allow-navigation is allowed
+    
+    BOOL allowNavigationsPass = [navigationsWhitelist URLIsAllowed:url logFailure:NO];
+    BOOL allowIntentPass = [intentsWhitelist URLIsAllowed:url logFailure:NO];
+    
+    if (allowNavigationsPass && allowIntentPass) {
+        return CDVIntentAndNavigationFilterValueNavigationAllowed;
+    } else if (allowNavigationsPass) {
+        return CDVIntentAndNavigationFilterValueNavigationAllowed;
+    } else if (allowIntentPass) {
+        return CDVIntentAndNavigationFilterValueIntentAllowed;
+    }
+    
+    return CDVIntentAndNavigationFilterValueNoneAllowed;
+}
+
+- (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url
+{
+    return [[self class] filterUrl:url intentsWhitelist:self.allowIntentsWhitelist navigationsWhitelist:self.allowNavigationsWhitelist];
+}
+
++ (BOOL)shouldOpenURLRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    return (UIWebViewNavigationTypeLinkClicked == navigationType ||
+        (UIWebViewNavigationTypeOther == navigationType &&
+         [[request.mainDocumentURL absoluteString] isEqualToString:[request.URL absoluteString]]
+         )
+        );
+}
+
++ (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType filterValue:(CDVIntentAndNavigationFilterValue)filterValue
+{
+    NSString* allowIntents_whitelistRejectionFormatString = @"ERROR External navigation rejected - <allow-intent> not set for url='%@'";
+    NSString* allowNavigations_whitelistRejectionFormatString = @"ERROR Internal navigation rejected - <allow-navigation> not set for url='%@'";
+    
+    NSURL* url = [request URL];
+    
+    switch (filterValue) {
+        case CDVIntentAndNavigationFilterValueNavigationAllowed:
+            return YES;
+        case CDVIntentAndNavigationFilterValueIntentAllowed:
+            // only allow-intent if it's a UIWebViewNavigationTypeLinkClicked (anchor tag) OR
+            // it's a UIWebViewNavigationTypeOther, and it's an internal link
+            if ([[self class] shouldOpenURLRequest:request navigationType:navigationType]){
+                [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
+            }
+            
+            // consume the request (i.e. no error) if it wasn't handled above
+            return NO;
+        case CDVIntentAndNavigationFilterValueNoneAllowed:
+            // allow-navigation attempt failed for sure
+            NSLog(@"%@", [NSString stringWithFormat:allowNavigations_whitelistRejectionFormatString, [url absoluteString]]);
+            // anchor tag link means it was an allow-intent attempt that failed as well
+            if (UIWebViewNavigationTypeLinkClicked == navigationType) {
+                NSLog(@"%@", [NSString stringWithFormat:allowIntents_whitelistRejectionFormatString, [url absoluteString]]);
+            }
+            return NO;
+    }
+}
+
+- (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    return [[self class] shouldOverrideLoadWithRequest:request navigationType:navigationType filterValue:[self filterUrl:request.URL]];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.h
new file mode 100644
index 0000000..e93675e
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.h
@@ -0,0 +1,50 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+
+#define kCDVLocalStorageErrorDomain @"kCDVLocalStorageErrorDomain"
+#define kCDVLocalStorageFileOperationError 1
+
+@interface CDVLocalStorage : CDVPlugin
+
+@property (nonatomic, readonly, strong) NSMutableArray* backupInfo;
+
+- (BOOL)shouldBackup;
+- (BOOL)shouldRestore;
+- (void)backup:(CDVInvokedUrlCommand*)command;
+- (void)restore:(CDVInvokedUrlCommand*)command;
+
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType;
+// Visible for testing.
++ (BOOL)__verifyAndFixDatabaseLocationsWithAppPlistDict:(NSMutableDictionary*)appPlistDict
+                                             bundlePath:(NSString*)bundlePath
+                                            fileManager:(NSFileManager*)fileManager;
+@end
+
+@interface CDVBackupInfo : NSObject
+
+@property (nonatomic, copy) NSString* original;
+@property (nonatomic, copy) NSString* backup;
+@property (nonatomic, copy) NSString* label;
+
+- (BOOL)shouldBackup;
+- (BOOL)shouldRestore;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.m
new file mode 100644
index 0000000..21b5cd9
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.m
@@ -0,0 +1,487 @@
+/*
+ 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.
+ */
+
+#import "CDVLocalStorage.h"
+#import <Cordova/CDV.h>
+
+@interface CDVLocalStorage ()
+
+@property (nonatomic, readwrite, strong) NSMutableArray* backupInfo;  // array of CDVBackupInfo objects
+@property (nonatomic, readwrite, weak) id <UIWebViewDelegate> webviewDelegate;
+
+@end
+
+@implementation CDVLocalStorage
+
+@synthesize backupInfo, webviewDelegate;
+
+- (void)pluginInitialize
+{
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResignActive)
+                                                 name:UIApplicationWillResignActiveNotification object:nil];
+    BOOL cloudBackup = [@"cloud" isEqualToString : self.commandDelegate.settings[[@"BackupWebStorage" lowercaseString]]];
+
+    self.backupInfo = [[self class] createBackupInfoWithCloudBackup:cloudBackup];
+}
+
+#pragma mark -
+#pragma mark Plugin interface methods
+
++ (NSMutableArray*)createBackupInfoWithTargetDir:(NSString*)targetDir backupDir:(NSString*)backupDir targetDirNests:(BOOL)targetDirNests backupDirNests:(BOOL)backupDirNests rename:(BOOL)rename
+{
+    /*
+     This "helper" does so much work and has so many options it would probably be clearer to refactor the whole thing.
+     Basically, there are three database locations:
+
+     1. "Normal" dir -- LIB/<nested dires WebKit/LocalStorage etc>/<normal filenames>
+     2. "Caches" dir -- LIB/Caches/<normal filenames>
+     3. "Backup" dir -- DOC/Backups/<renamed filenames>
+
+     And between these three, there are various migration paths, most of which only consider 2 of the 3, which is why this helper is based on 2 locations and has a notion of "direction".
+     */
+    NSMutableArray* backupInfo = [NSMutableArray arrayWithCapacity:3];
+
+    NSString* original;
+    NSString* backup;
+    CDVBackupInfo* backupItem;
+
+    // ////////// LOCALSTORAGE
+
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/file__0.localstorage":@"file__0.localstorage"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+    backup = [backup stringByAppendingPathComponent:(rename ? @"localstorage.appdata.db" : @"file__0.localstorage")];
+
+    backupItem = [[CDVBackupInfo alloc] init];
+    backupItem.backup = backup;
+    backupItem.original = original;
+    backupItem.label = @"localStorage database";
+
+    [backupInfo addObject:backupItem];
+
+    // ////////// WEBSQL MAIN DB
+
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/Databases.db":@"Databases.db"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+    backup = [backup stringByAppendingPathComponent:(rename ? @"websqlmain.appdata.db" : @"Databases.db")];
+
+    backupItem = [[CDVBackupInfo alloc] init];
+    backupItem.backup = backup;
+    backupItem.original = original;
+    backupItem.label = @"websql main database";
+
+    [backupInfo addObject:backupItem];
+
+    // ////////// WEBSQL DATABASES
+
+    original = [targetDir stringByAppendingPathComponent:targetDirNests ? @"WebKit/LocalStorage/file__0":@"file__0"];
+    backup = [backupDir stringByAppendingPathComponent:(backupDirNests ? @"WebKit/LocalStorage" : @"")];
+    backup = [backup stringByAppendingPathComponent:(rename ? @"websqldbs.appdata.db" : @"file__0")];
+
+    backupItem = [[CDVBackupInfo alloc] init];
+    backupItem.backup = backup;
+    backupItem.original = original;
+    backupItem.label = @"websql databases";
+
+    [backupInfo addObject:backupItem];
+
+    return backupInfo;
+}
+
++ (NSMutableArray*)createBackupInfoWithCloudBackup:(BOOL)cloudBackup
+{
+    // create backup info from backup folder to caches folder
+    NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+    NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+    NSString* cacheFolder = [appLibraryFolder stringByAppendingPathComponent:@"Caches"];
+    NSString* backupsFolder = [appDocumentsFolder stringByAppendingPathComponent:@"Backups"];
+
+    // create the backups folder, if needed
+    [[NSFileManager defaultManager] createDirectoryAtPath:backupsFolder withIntermediateDirectories:YES attributes:nil error:nil];
+
+    [self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:backupsFolder] skip:!cloudBackup];
+
+    return [self createBackupInfoWithTargetDir:cacheFolder backupDir:backupsFolder targetDirNests:NO backupDirNests:NO rename:YES];
+}
+
++ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL*)URL skip:(BOOL)skip
+{
+    NSError* error = nil;
+    BOOL success = [URL setResourceValue:[NSNumber numberWithBool:skip] forKey:NSURLIsExcludedFromBackupKey error:&error];
+
+    if (!success) {
+        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
+    }
+    return success;
+}
+
++ (BOOL)copyFrom:(NSString*)src to:(NSString*)dest error:(NSError* __autoreleasing*)error
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+
+    if (![fileManager fileExistsAtPath:src]) {
+        NSString* errorString = [NSString stringWithFormat:@"%@ file does not exist.", src];
+        if (error != NULL) {
+            (*error) = [NSError errorWithDomain:kCDVLocalStorageErrorDomain
+                                           code:kCDVLocalStorageFileOperationError
+                                       userInfo:[NSDictionary dictionaryWithObject:errorString
+                                                                            forKey:NSLocalizedDescriptionKey]];
+        }
+        return NO;
+    }
+
+    // generate unique filepath in temp directory
+    CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
+    CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
+    NSString* tempBackup = [[NSTemporaryDirectory() stringByAppendingPathComponent:(__bridge NSString*)uuidString] stringByAppendingPathExtension:@"bak"];
+    CFRelease(uuidString);
+    CFRelease(uuidRef);
+
+    BOOL destExists = [fileManager fileExistsAtPath:dest];
+
+    // backup the dest
+    if (destExists && ![fileManager copyItemAtPath:dest toPath:tempBackup error:error]) {
+        return NO;
+    }
+
+    // remove the dest
+    if (destExists && ![fileManager removeItemAtPath:dest error:error]) {
+        return NO;
+    }
+
+    // create path to dest
+    if (!destExists && ![fileManager createDirectoryAtPath:[dest stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:error]) {
+        return NO;
+    }
+
+    // copy src to dest
+    if ([fileManager copyItemAtPath:src toPath:dest error:error]) {
+        // success - cleanup - delete the backup to the dest
+        if ([fileManager fileExistsAtPath:tempBackup]) {
+            [fileManager removeItemAtPath:tempBackup error:error];
+        }
+        return YES;
+    } else {
+        // failure - we restore the temp backup file to dest
+        [fileManager copyItemAtPath:tempBackup toPath:dest error:error];
+        // cleanup - delete the backup to the dest
+        if ([fileManager fileExistsAtPath:tempBackup]) {
+            [fileManager removeItemAtPath:tempBackup error:error];
+        }
+        return NO;
+    }
+}
+
+- (BOOL)shouldBackup
+{
+    for (CDVBackupInfo* info in self.backupInfo) {
+        if ([info shouldBackup]) {
+            return YES;
+        }
+    }
+
+    return NO;
+}
+
+- (BOOL)shouldRestore
+{
+    for (CDVBackupInfo* info in self.backupInfo) {
+        if ([info shouldRestore]) {
+            return YES;
+        }
+    }
+
+    return NO;
+}
+
+/* copy from webkitDbLocation to persistentDbLocation */
+- (void)backup:(CDVInvokedUrlCommand*)command
+{
+    NSString* callbackId = command.callbackId;
+
+    NSError* __autoreleasing error = nil;
+    CDVPluginResult* result = nil;
+    NSString* message = nil;
+
+    for (CDVBackupInfo* info in self.backupInfo) {
+        if ([info shouldBackup]) {
+            [[self class] copyFrom:info.original to:info.backup error:&error];
+
+            if (callbackId) {
+                if (error == nil) {
+                    message = [NSString stringWithFormat:@"Backed up: %@", info.label];
+                    NSLog(@"%@", message);
+
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+                    [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+                } else {
+                    message = [NSString stringWithFormat:@"Error in CDVLocalStorage (%@) backup: %@", info.label, [error localizedDescription]];
+                    NSLog(@"%@", message);
+
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+                    [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+                }
+            }
+        }
+    }
+}
+
+/* copy from persistentDbLocation to webkitDbLocation */
+- (void)restore:(CDVInvokedUrlCommand*)command
+{
+    NSError* __autoreleasing error = nil;
+    CDVPluginResult* result = nil;
+    NSString* message = nil;
+
+    for (CDVBackupInfo* info in self.backupInfo) {
+        if ([info shouldRestore]) {
+            [[self class] copyFrom:info.backup to:info.original error:&error];
+
+            if (error == nil) {
+                message = [NSString stringWithFormat:@"Restored: %@", info.label];
+                NSLog(@"%@", message);
+
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message];
+                [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            } else {
+                message = [NSString stringWithFormat:@"Error in CDVLocalStorage (%@) restore: %@", info.label, [error localizedDescription]];
+                NSLog(@"%@", message);
+
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message];
+                [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            }
+        }
+    }
+}
+
++ (void)__fixupDatabaseLocationsWithBackupType:(NSString*)backupType
+{
+    [self __verifyAndFixDatabaseLocations];
+    [self __restoreLegacyDatabaseLocationsWithBackupType:backupType];
+}
+
++ (void)__verifyAndFixDatabaseLocations
+{
+    NSBundle* mainBundle = [NSBundle mainBundle];
+    NSString* bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent];
+    NSString* bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@"CFBundleIdentifier"];
+    NSString* appPlistPath = [bundlePath stringByAppendingPathComponent:[NSString stringWithFormat:@"Library/Preferences/%@.plist", bundleIdentifier]];
+
+    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath];
+    BOOL modified = [[self class] __verifyAndFixDatabaseLocationsWithAppPlistDict:appPlistDict
+                                                                       bundlePath:bundlePath
+                                                                      fileManager:[NSFileManager defaultManager]];
+
+    if (modified) {
+        BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES];
+        [[NSUserDefaults standardUserDefaults] synchronize];
+        NSLog(@"Fix applied for database locations?: %@", ok ? @"YES" : @"NO");
+    }
+}
+
++ (BOOL)__verifyAndFixDatabaseLocationsWithAppPlistDict:(NSMutableDictionary*)appPlistDict
+                                             bundlePath:(NSString*)bundlePath
+                                            fileManager:(NSFileManager*)fileManager
+{
+    NSString* libraryCaches = @"Library/Caches";
+    NSString* libraryWebKit = @"Library/WebKit";
+
+    NSArray* keysToCheck = [NSArray arrayWithObjects:
+        @"WebKitLocalStorageDatabasePathPreferenceKey",
+        @"WebDatabaseDirectory",
+        nil];
+
+    BOOL dirty = NO;
+
+    for (NSString* key in keysToCheck) {
+        NSString* value = [appPlistDict objectForKey:key];
+        // verify key exists, and path is in app bundle, if not - fix
+        if ((value != nil) && ![value hasPrefix:bundlePath]) {
+            // the pathSuffix to use may be wrong - OTA upgrades from < 5.1 to 5.1 do keep the old path Library/WebKit,
+            // while Xcode synced ones do change the storage location to Library/Caches
+            NSString* newBundlePath = [bundlePath stringByAppendingPathComponent:libraryCaches];
+            if (![fileManager fileExistsAtPath:newBundlePath]) {
+                newBundlePath = [bundlePath stringByAppendingPathComponent:libraryWebKit];
+            }
+            [appPlistDict setValue:newBundlePath forKey:key];
+            dirty = YES;
+        }
+    }
+
+    return dirty;
+}
+
++ (void)__restoreLegacyDatabaseLocationsWithBackupType:(NSString*)backupType
+{
+    // on iOS 6, if you toggle between cloud/local backup, you must move database locations.  Default upgrade from iOS5.1 to iOS6 is like a toggle from local to cloud.
+    NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+    NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+
+    NSMutableArray* backupInfo = [NSMutableArray arrayWithCapacity:0];
+
+    if ([backupType isEqualToString:@"cloud"]) {
+#ifdef DEBUG
+            NSLog(@"\n\nStarted backup to iCloud! Please be careful."
+                "\nYour application might be rejected by Apple if you store too much data."
+                "\nFor more information please read \"iOS Data Storage Guidelines\" at:"
+                "\nhttps://developer.apple.com/icloud/documentation/data-storage/"
+                "\nTo disable web storage backup to iCloud, set the BackupWebStorage preference to \"local\" in the Cordova config.xml file\n\n");
+#endif
+        // We would like to restore old backups/caches databases to the new destination (nested in lib folder)
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder backupDir:[appDocumentsFolder stringByAppendingPathComponent:@"Backups"] targetDirNests:YES backupDirNests:NO rename:YES]];
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:appLibraryFolder backupDir:[appLibraryFolder stringByAppendingPathComponent:@"Caches"] targetDirNests:YES backupDirNests:NO rename:NO]];
+    } else {
+        // For ios6 local backups we also want to restore from Backups dir -- but we don't need to do that here, since the plugin will do that itself.
+        [backupInfo addObjectsFromArray:[self createBackupInfoWithTargetDir:[appLibraryFolder stringByAppendingPathComponent:@"Caches"] backupDir:appLibraryFolder targetDirNests:NO backupDirNests:YES rename:NO]];
+    }
+
+    NSFileManager* manager = [NSFileManager defaultManager];
+
+    for (CDVBackupInfo* info in backupInfo) {
+        if ([manager fileExistsAtPath:info.backup]) {
+            if ([info shouldRestore]) {
+                NSLog(@"Restoring old webstorage backup. From: '%@' To: '%@'.", info.backup, info.original);
+                [self copyFrom:info.backup to:info.original error:nil];
+            }
+            NSLog(@"Removing old webstorage backup: '%@'.", info.backup);
+            [manager removeItemAtPath:info.backup error:nil];
+        }
+    }
+
+    [[NSUserDefaults standardUserDefaults] setBool:[backupType isEqualToString:@"cloud"] forKey:@"WebKitStoreWebDataForBackup"];
+}
+
+#pragma mark -
+#pragma mark Notification handlers
+
+- (void)onResignActive
+{
+    UIDevice* device = [UIDevice currentDevice];
+    NSNumber* exitsOnSuspend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationExitsOnSuspend"];
+
+    BOOL isMultitaskingSupported = [device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported];
+
+    if (exitsOnSuspend == nil) { // if it's missing, it should be NO (i.e. multi-tasking on by default)
+        exitsOnSuspend = [NSNumber numberWithBool:NO];
+    }
+
+    if (exitsOnSuspend) {
+        [self backup:nil];
+    } else if (isMultitaskingSupported) {
+        __block UIBackgroundTaskIdentifier backgroundTaskID = UIBackgroundTaskInvalid;
+
+        backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
+                [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
+                backgroundTaskID = UIBackgroundTaskInvalid;
+                NSLog(@"Background task to backup WebSQL/LocalStorage expired.");
+            }];
+        CDVLocalStorage __weak* weakSelf = self;
+        [self.commandDelegate runInBackground:^{
+            [weakSelf backup:nil];
+
+            [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
+            backgroundTaskID = UIBackgroundTaskInvalid;
+        }];
+    }
+}
+
+- (void)onAppTerminate
+{
+    [self onResignActive];
+}
+
+- (void)onReset
+{
+    [self restore:nil];
+}
+
+@end
+
+#pragma mark -
+#pragma mark CDVBackupInfo implementation
+
+@implementation CDVBackupInfo
+
+@synthesize original, backup, label;
+
+- (BOOL)file:(NSString*)aPath isNewerThanFile:(NSString*)bPath
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+    NSError* __autoreleasing error = nil;
+
+    NSDictionary* aPathAttribs = [fileManager attributesOfItemAtPath:aPath error:&error];
+    NSDictionary* bPathAttribs = [fileManager attributesOfItemAtPath:bPath error:&error];
+
+    NSDate* aPathModDate = [aPathAttribs objectForKey:NSFileModificationDate];
+    NSDate* bPathModDate = [bPathAttribs objectForKey:NSFileModificationDate];
+
+    if ((nil == aPathModDate) && (nil == bPathModDate)) {
+        return NO;
+    }
+
+    return [aPathModDate compare:bPathModDate] == NSOrderedDescending || bPathModDate == nil;
+}
+
+- (BOOL)item:(NSString*)aPath isNewerThanItem:(NSString*)bPath
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+
+    BOOL aPathIsDir = NO, bPathIsDir = NO;
+    BOOL aPathExists = [fileManager fileExistsAtPath:aPath isDirectory:&aPathIsDir];
+
+    [fileManager fileExistsAtPath:bPath isDirectory:&bPathIsDir];
+
+    if (!aPathExists) {
+        return NO;
+    }
+
+    if (!(aPathIsDir && bPathIsDir)) { // just a file
+        return [self file:aPath isNewerThanFile:bPath];
+    }
+
+    // essentially we want rsync here, but have to settle for our poor man's implementation
+    // we get the files in aPath, and see if it is newer than the file in bPath
+    // (it is newer if it doesn't exist in bPath) if we encounter the FIRST file that is newer,
+    // we return YES
+    NSDirectoryEnumerator* directoryEnumerator = [fileManager enumeratorAtPath:aPath];
+    NSString* path;
+
+    while ((path = [directoryEnumerator nextObject])) {
+        NSString* aPathFile = [aPath stringByAppendingPathComponent:path];
+        NSString* bPathFile = [bPath stringByAppendingPathComponent:path];
+
+        BOOL isNewer = [self file:aPathFile isNewerThanFile:bPathFile];
+        if (isNewer) {
+            return YES;
+        }
+    }
+
+    return NO;
+}
+
+- (BOOL)shouldBackup
+{
+    return [self item:self.original isNewerThanItem:self.backup];
+}
+
+- (BOOL)shouldRestore
+{
+    return [self item:self.backup isNewerThanItem:self.original];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.h
new file mode 100644
index 0000000..7cfb306
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.h
@@ -0,0 +1,26 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+
+@interface CDVLogger : CDVPlugin
+
+- (void)logLevel:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.m
new file mode 100644
index 0000000..810caa5
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLogger/CDVLogger.m
@@ -0,0 +1,37 @@
+/*
+ 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.
+ */
+
+#import "CDVLogger.h"
+
+@implementation CDVLogger
+
+/* log a message */
+- (void)logLevel:(CDVInvokedUrlCommand*)command
+{
+    id level = [command argumentAtIndex:0];
+    id message = [command argumentAtIndex:1];
+
+    if ([level isEqualToString:@"LOG"]) {
+        NSLog(@"%@", message);
+    } else {
+        NSLog(@"%@: %@", level, message);
+    }
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.h
new file mode 100644
index 0000000..7db8a4e
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.h
@@ -0,0 +1,41 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import <Cordova/CDVAvailability.h>
+
+/**
+ * Distinguishes top-level navigations from sub-frame navigations.
+ * shouldStartLoadWithRequest is called for every request, but didStartLoad
+ * and didFinishLoad is called only for top-level navigations.
+ * Relevant bug: CB-2389
+ */
+@interface CDVUIWebViewDelegate : NSObject <UIWebViewDelegate>{
+    __weak NSObject <UIWebViewDelegate>* _delegate;
+    NSInteger _loadCount;
+    NSInteger _state;
+    NSInteger _curLoadToken;
+    NSInteger _loadStartPollCount;
+}
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m
new file mode 100644
index 0000000..93fbb67
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m
@@ -0,0 +1,404 @@
+/*
+ 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.
+ */
+
+//
+// Testing shows:
+//
+// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
+// When loading a page with a redirect:
+// 1. shouldStartLoading (requestURL is target page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is redirect target)
+// 4. didFinishLoad (request.URL is redirect target)
+//
+// Note the lack of a second didStartLoading **
+//
+// When loading a page with iframes:
+// 1. shouldStartLoading (requestURL is main page)
+// 2. didStartLoading
+// 3. shouldStartLoading (requestURL is one of the iframes)
+// 4. didStartLoading
+// 5. didFinishLoad
+// 6. didFinishLoad
+//
+// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
+//
+// Loading a page by calling window.history.go(-1):
+// 1. didStartLoading
+// 2. didFinishLoad
+//
+// Note the lack of a shouldStartLoading call **
+// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
+//
+// Loading a page by calling location.reload()
+// 1. shouldStartLoading
+// 2. didStartLoading
+// 3. didFinishLoad
+//
+// Loading a page with an iframe that fails to load:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 4. didStart
+// 5. didFailWithError
+// 6. didFinish
+//
+// Loading a page with an iframe that fails to load due to an invalid URL:
+// 1. shouldStart (main page)
+// 2. didStart
+// 3. shouldStart (iframe)
+// 5. didFailWithError
+// 6. didFinish
+//
+// This case breaks our logic since there is a missing didStart. To prevent this,
+// we check URLs in shouldStart and return NO if they are invalid.
+//
+// Loading a page with an invalid URL
+// 1. shouldStart (main page)
+// 2. didFailWithError
+//
+// TODO: Record order when page is re-navigated before the first navigation finishes.
+//
+
+#import "CDVUIWebViewDelegate.h"
+
+// #define VerboseLog NSLog
+#define VerboseLog(...) do { \
+} while (0)
+
+typedef enum {
+    STATE_IDLE = 0,
+    STATE_WAITING_FOR_LOAD_START = 1,
+    STATE_WAITING_FOR_LOAD_FINISH = 2,
+    STATE_IOS5_POLLING_FOR_LOAD_START = 3,
+    STATE_IOS5_POLLING_FOR_LOAD_FINISH = 4,
+    STATE_CANCELLED = 5
+} State;
+
+static NSString *stripFragment(NSString* url)
+{
+    NSRange r = [url rangeOfString:@"#"];
+
+    if (r.location == NSNotFound) {
+        return url;
+    }
+    return [url substringToIndex:r.location];
+}
+
+@implementation CDVUIWebViewDelegate
+
+- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
+{
+    self = [super init];
+    if (self != nil) {
+        _delegate = delegate;
+        _loadCount = -1;
+        _state = STATE_IDLE;
+    }
+    return self;
+}
+
+- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
+{
+    if (originalRequest.URL && newRequest.URL) {
+        NSString* originalRequestUrl = [originalRequest.URL absoluteString];
+        NSString* newRequestUrl = [newRequest.URL absoluteString];
+
+        NSString* baseOriginalRequestUrl = stripFragment(originalRequestUrl);
+        NSString* baseNewRequestUrl = stripFragment(newRequestUrl);
+        return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl];
+    }
+
+    return NO;
+}
+
+- (BOOL)isPageLoaded:(UIWebView*)webView
+{
+    NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
+
+    return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
+}
+
+- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
+{
+    NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
+
+    return [[NSString stringWithFormat:@"%ld", (long)_curLoadToken] isEqualToString:loadToken];
+}
+
+- (void)setLoadToken:(UIWebView*)webView
+{
+    _curLoadToken += 1;
+    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%ld", (long)_curLoadToken]];
+}
+
+- (NSString*)evalForCurrentURL:(UIWebView*)webView
+{
+    return [webView stringByEvaluatingJavaScriptFromString:@"location.href"];
+}
+
+- (void)pollForPageLoadStart:(UIWebView*)webView
+{
+    if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
+        return;
+    }
+    if (![self isJsLoadTokenSet:webView]) {
+        VerboseLog(@"Polled for page load start. result = YES!");
+        _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
+        [self setLoadToken:webView];
+        if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+            [_delegate webViewDidStartLoad:webView];
+        }
+        [self pollForPageLoadFinish:webView];
+    } else {
+        VerboseLog(@"Polled for page load start. result = NO");
+        // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
+        ++_loadStartPollCount;
+        if (_loadStartPollCount < (1000 * .05)) {
+            [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
+        }
+    }
+}
+
+- (void)pollForPageLoadFinish:(UIWebView*)webView
+{
+    if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
+        return;
+    }
+    if ([self isPageLoaded:webView]) {
+        VerboseLog(@"Polled for page load finish. result = YES!");
+        _state = STATE_IDLE;
+        if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+            [_delegate webViewDidFinishLoad:webView];
+        }
+    } else {
+        VerboseLog(@"Polled for page load finish. result = NO");
+        [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
+    }
+}
+
+- (BOOL)shouldLoadRequest:(NSURLRequest*)request
+{
+    NSString* scheme = [[request URL] scheme];
+    NSArray* allowedSchemes = [NSArray arrayWithObjects:@"mailto",@"tel",@"blob",@"sms",@"data", nil];
+    if([allowedSchemes containsObject:scheme]) {
+        return YES;
+    }
+    else {
+        return [NSURLConnection canHandleRequest:request];
+    }
+}
+
+- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    BOOL shouldLoad = YES;
+
+    if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
+        shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
+    }
+
+    VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
+
+    if (shouldLoad) {
+        // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
+        // mainDocumentURL != URL even though it's a top-level navigation.
+        BOOL isDevToolsRefresh = (request == webView.request);
+        BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
+        if (isTopLevelNavigation) {
+            // Ignore hash changes that don't navigate to a different page.
+            // webView.request does actually update when history.replaceState() gets called.
+            if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
+                NSString* prevURL = [self evalForCurrentURL:webView];
+                if ([prevURL isEqualToString:[request.URL absoluteString]]) {
+                    VerboseLog(@"Page reload detected.");
+                } else {
+                    VerboseLog(@"Detected hash change shouldLoad");
+                    return shouldLoad;
+                }
+            }
+
+            switch (_state) {
+                case STATE_WAITING_FOR_LOAD_FINISH:
+                    // Redirect case.
+                    // We expect loadCount == 1.
+                    if (_loadCount != 1) {
+                        NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
+                    }
+                    break;
+
+                case STATE_IDLE:
+                case STATE_IOS5_POLLING_FOR_LOAD_START:
+                case STATE_CANCELLED:
+                    // Page navigation start.
+                    _loadCount = 0;
+                    _state = STATE_WAITING_FOR_LOAD_START;
+                    break;
+
+                default:
+                    {
+                        NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
+                        NSLog(@"%@", description);
+                        _loadCount = 0;
+                        _state = STATE_WAITING_FOR_LOAD_START;
+                                
+                        NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
+                        NSError* error = [[NSError alloc] initWithDomain:@"CDVUIWebViewDelegate" code:1 userInfo:errorDictionary];
+                        [self webView:webView didFailLoadWithError:error];
+                    }
+            }
+        } else {
+            // Deny invalid URLs so that we don't get the case where we go straight from
+            // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
+            shouldLoad = shouldLoad && [self shouldLoadRequest:request];
+        }
+        VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
+    }
+    return shouldLoad;
+}
+
+- (void)webViewDidStartLoad:(UIWebView*)webView
+{
+    VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+    switch (_state) {
+        case STATE_IDLE:
+            break;
+
+        case STATE_CANCELLED:
+            fireCallback = YES;
+            _state = STATE_WAITING_FOR_LOAD_FINISH;
+            _loadCount += 1;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            if (_loadCount != 0) {
+                NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%ld", (long)_loadCount);
+            }
+            fireCallback = YES;
+            _state = STATE_WAITING_FOR_LOAD_FINISH;
+            _loadCount = 1;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            _loadCount += 1;
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+
+        default:
+            NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%ld loadCount=%ld", (long)_state, (long)_loadCount);
+    }
+    VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
+        [_delegate webViewDidStartLoad:webView];
+    }
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)webView
+{
+    VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+    switch (_state) {
+        case STATE_IDLE:
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            // fix call loadRequest multiple times just callback webViewDidFinishLoad once time in iOS 12
+            if (@available(iOS 12.0, *)) {
+                fireCallback = YES;
+            } else {
+                if (_loadCount == 1) {
+                    fireCallback = YES;
+                    _state = STATE_IDLE;
+                }
+            }
+            _loadCount -= 1;
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+    }
+    VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
+        [_delegate webViewDidFinishLoad:webView];
+    }
+}
+
+- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
+{
+    VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
+    BOOL fireCallback = NO;
+
+    switch (_state) {
+        case STATE_IDLE:
+            break;
+
+        case STATE_WAITING_FOR_LOAD_START:
+            if ([error code] == NSURLErrorCancelled) {
+                _state = STATE_CANCELLED;
+            } else {
+                _state = STATE_IDLE;
+            }
+            fireCallback = YES;
+            break;
+
+        case STATE_WAITING_FOR_LOAD_FINISH:
+            if ([error code] != NSURLErrorCancelled) {
+                if (_loadCount == 1) {
+                    _state = STATE_IDLE;
+                    fireCallback = YES;
+                }
+                _loadCount = -1;
+            } else {
+                fireCallback = YES;
+                _state = STATE_CANCELLED;
+                _loadCount -= 1;
+            }
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_START:
+            [self pollForPageLoadStart:webView];
+            break;
+
+        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
+            [self pollForPageLoadFinish:webView];
+            break;
+    }
+    VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
+    if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
+        [_delegate webView:webView didFailLoadWithError:error];
+    }
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h
new file mode 100644
index 0000000..f407009
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+#import <Cordova/CDVWebViewEngineProtocol.h>
+
+@interface CDVUIWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol>
+
+@property (nonatomic, strong, readonly) id <UIWebViewDelegate> uiWebViewDelegate;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m
new file mode 100644
index 0000000..bbd343c
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m
@@ -0,0 +1,202 @@
+/*
+ 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.
+ */
+
+#import "CDVUIWebViewEngine.h"
+#import "CDVUIWebViewDelegate.h"
+#import "CDVUIWebViewNavigationDelegate.h"
+#import "NSDictionary+CordovaPreferences.h"
+
+#import <objc/message.h>
+
+@interface CDVUIWebViewEngine ()
+
+@property (nonatomic, strong, readwrite) UIView* engineWebView;
+@property (nonatomic, strong, readwrite) id <UIWebViewDelegate> uiWebViewDelegate;
+@property (nonatomic, strong, readwrite) CDVUIWebViewNavigationDelegate* navWebViewDelegate;
+
+@end
+
+@implementation CDVUIWebViewEngine
+
+@synthesize engineWebView = _engineWebView;
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super init];
+    if (self) {
+        self.engineWebView = [[UIWebView alloc] initWithFrame:frame];
+        NSLog(@"Using UIWebView");
+    }
+
+    return self;
+}
+
+- (void)pluginInitialize
+{
+    // viewController would be available now. we attempt to set all possible delegates to it, by default
+
+    UIWebView* uiWebView = (UIWebView*)_engineWebView;
+
+    if ([self.viewController conformsToProtocol:@protocol(UIWebViewDelegate)]) {
+        self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:(id <UIWebViewDelegate>)self.viewController];
+        uiWebView.delegate = self.uiWebViewDelegate;
+    } else {
+        self.navWebViewDelegate = [[CDVUIWebViewNavigationDelegate alloc] initWithEnginePlugin:self];
+        self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:self.navWebViewDelegate];
+        uiWebView.delegate = self.uiWebViewDelegate;
+    }
+
+    [self updateSettings:self.commandDelegate.settings];
+}
+
+- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler
+{
+    NSString* ret = [(UIWebView*)_engineWebView stringByEvaluatingJavaScriptFromString:javaScriptString];
+
+    if (completionHandler) {
+        completionHandler(ret, nil);
+    }
+}
+
+- (id)loadRequest:(NSURLRequest*)request
+{
+    [(UIWebView*)_engineWebView loadRequest:request];
+    return nil;
+}
+
+- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL
+{
+    [(UIWebView*)_engineWebView loadHTMLString:string baseURL:baseURL];
+    return nil;
+}
+
+- (NSURL*)URL
+{
+    return [[(UIWebView*)_engineWebView request] URL];
+}
+
+- (BOOL) canLoadRequest:(NSURLRequest*)request
+{
+    return (request != nil);
+}
+
+- (void)updateSettings:(NSDictionary*)settings
+{
+    UIWebView* uiWebView = (UIWebView*)_engineWebView;
+
+    uiWebView.scalesPageToFit = [settings cordovaBoolSettingForKey:@"EnableViewportScale" defaultValue:NO];
+    uiWebView.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO];
+    uiWebView.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES];
+    uiWebView.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES];
+    uiWebView.keyboardDisplayRequiresUserAction = [settings cordovaBoolSettingForKey:@"KeyboardDisplayRequiresUserAction" defaultValue:YES];
+    uiWebView.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO];
+    uiWebView.gapBetweenPages = [settings cordovaFloatSettingForKey:@"GapBetweenPages" defaultValue:0.0];
+    uiWebView.pageLength = [settings cordovaFloatSettingForKey:@"PageLength" defaultValue:0.0];
+
+    id prefObj = nil;
+
+    // By default, DisallowOverscroll is false (thus bounce is allowed)
+    BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);
+
+    // prevent webView from bouncing
+    if (!bounceAllowed) {
+        if ([uiWebView respondsToSelector:@selector(scrollView)]) {
+            ((UIScrollView*)[uiWebView scrollView]).bounces = NO;
+        } else {
+            for (id subview in self.webView.subviews) {
+                if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+                    ((UIScrollView*)subview).bounces = NO;
+                }
+            }
+        }
+    }
+
+    NSString* decelerationSetting = [settings cordovaSettingForKey:@"UIWebViewDecelerationSpeed"];
+    if (![@"fast" isEqualToString:decelerationSetting]) {
+        [uiWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
+    }
+
+    NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage
+    prefObj = [settings cordovaSettingForKey:@"PaginationBreakingMode"];
+    if (prefObj != nil) {
+        NSArray* validValues = @[@"page", @"column"];
+        NSString* prefValue = [validValues objectAtIndex:0];
+
+        if ([prefObj isKindOfClass:[NSString class]]) {
+            prefValue = prefObj;
+        }
+
+        paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]];
+        if (paginationBreakingMode == NSNotFound) {
+            paginationBreakingMode = 0;
+        }
+    }
+    uiWebView.paginationBreakingMode = paginationBreakingMode;
+
+    NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated
+    prefObj = [settings cordovaSettingForKey:@"PaginationMode"];
+    if (prefObj != nil) {
+        NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"];
+        NSString* prefValue = [validValues objectAtIndex:0];
+
+        if ([prefObj isKindOfClass:[NSString class]]) {
+            prefValue = prefObj;
+        }
+
+        paginationMode = [validValues indexOfObject:[prefValue lowercaseString]];
+        if (paginationMode == NSNotFound) {
+            paginationMode = 0;
+        }
+    }
+    uiWebView.paginationMode = paginationMode;
+}
+
+- (void)updateWithInfo:(NSDictionary*)info
+{
+    UIWebView* uiWebView = (UIWebView*)_engineWebView;
+
+    id <UIWebViewDelegate> uiWebViewDelegate = [info objectForKey:kCDVWebViewEngineUIWebViewDelegate];
+    NSDictionary* settings = [info objectForKey:kCDVWebViewEngineWebViewPreferences];
+
+    if (uiWebViewDelegate &&
+        [uiWebViewDelegate conformsToProtocol:@protocol(UIWebViewDelegate)]) {
+        self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:(id <UIWebViewDelegate>)uiWebViewDelegate];
+        uiWebView.delegate = self.uiWebViewDelegate;
+    }
+
+    if (settings && [settings isKindOfClass:[NSDictionary class]]) {
+        [self updateSettings:settings];
+    }
+}
+
+// This forwards the methods that are in the header that are not implemented here.
+// Both WKWebView and UIWebView implement the below:
+//     loadHTMLString:baseURL:
+//     loadRequest:
+- (id)forwardingTargetForSelector:(SEL)aSelector
+{
+    return _engineWebView;
+}
+
+- (UIView*)webView
+{
+    return self.engineWebView;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.h b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.h
new file mode 100644
index 0000000..9138deb
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.h
@@ -0,0 +1,29 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVUIWebViewEngine.h"
+
+@interface CDVUIWebViewNavigationDelegate : NSObject <UIWebViewDelegate>
+
+@property (nonatomic, weak) CDVPlugin* enginePlugin;
+
+- (instancetype)initWithEnginePlugin:(CDVPlugin*)enginePlugin;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m
new file mode 100644
index 0000000..bc56fdd
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m
@@ -0,0 +1,153 @@
+/*
+ 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.
+ */
+
+#import "CDVUIWebViewNavigationDelegate.h"
+#import <Cordova/CDVViewController.h>
+#import <Cordova/CDVCommandDelegateImpl.h>
+#import <Cordova/CDVUserAgentUtil.h>
+#import <objc/message.h>
+
+@implementation CDVUIWebViewNavigationDelegate
+
+- (instancetype)initWithEnginePlugin:(CDVPlugin*)theEnginePlugin
+{
+    self = [super init];
+    if (self) {
+        self.enginePlugin = theEnginePlugin;
+    }
+
+    return self;
+}
+
+/**
+ When web application loads Add stuff to the DOM, mainly the user-defined settings from the Settings.plist file, and
+ the device's data such as device ID, platform version, etc.
+ */
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+    NSLog(@"Resetting plugins due to page load.");
+    CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController;
+
+    [vc.commandQueue resetRequestId];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.enginePlugin.webView]];
+}
+
+/**
+ Called when the webview finishes loading.  This stops the activity view.
+ */
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    NSLog(@"Finished load of: %@", theWebView.request.URL);
+    CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController;
+
+    // It's safe to release the lock even if this is just a sub-frame that's finished loading.
+    [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
+
+    /*
+     * Hide the Top Activity THROBBER in the Battery Bar
+     */
+    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
+
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:self.enginePlugin.webView]];
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController;
+
+    [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
+
+    NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]];
+    NSLog(@"%@", message);
+
+    NSURL* errorUrl = vc.errorURL;
+    if (errorUrl) {
+        errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]] relativeToURL:errorUrl];
+        NSLog(@"%@", [errorUrl absoluteString]);
+        if(error.code != NSURLErrorCancelled) {
+            [theWebView loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+        }
+    }
+}
+
+- (BOOL)defaultResourcePolicyForURL:(NSURL*)url
+{
+    /*
+     * If a URL is being loaded that's a file url, just load it internally
+     */
+    if ([url isFileURL]) {
+        return YES;
+    }
+    
+    return NO;
+}
+
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    NSURL* url = [request URL];
+    CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController;
+
+    /*
+     * Execute any commands queued with cordova.exec() on the JS side.
+     * The part of the URL after gap:// is irrelevant.
+     */
+    if ([[url scheme] isEqualToString:@"gap"]) {
+        [vc.commandQueue fetchCommandsFromJs];
+        // The delegate is called asynchronously in this case, so we don't have to use
+        // flushCommandQueueWithDelayedJs (setTimeout(0)) as we do with hash changes.
+        [vc.commandQueue executePending];
+        return NO;
+    }
+
+    /*
+     * Give plugins the chance to handle the url
+     */
+    BOOL anyPluginsResponded = NO;
+    BOOL shouldAllowRequest = NO;
+    
+    for (NSString* pluginName in vc.pluginObjects) {
+        CDVPlugin* plugin = [vc.pluginObjects objectForKey:pluginName];
+        SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:");
+        if ([plugin respondsToSelector:selector]) {
+            anyPluginsResponded = YES;
+            shouldAllowRequest = (((BOOL (*)(id, SEL, id, int))objc_msgSend)(plugin, selector, request, navigationType));
+            if (!shouldAllowRequest) {
+                break;
+            }
+        }
+    }
+    
+    if (anyPluginsResponded) {
+        return shouldAllowRequest;
+    }
+
+    /*
+     * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview.
+     */
+    BOOL shouldAllowNavigation = [self defaultResourcePolicyForURL:url];
+    if (shouldAllowNavigation) {
+        return YES;
+    } else {
+        [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+    }
+    
+    return NO;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDV.h b/platforms/ios/CordovaLib/Classes/Public/CDV.h
new file mode 100644
index 0000000..96d6efc
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDV.h
@@ -0,0 +1,32 @@
+/*
+ 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.
+ */
+
+#import "CDVAvailability.h"
+#import "CDVAvailabilityDeprecated.h"
+#import "CDVAppDelegate.h"
+#import "CDVPlugin.h"
+#import "CDVPluginResult.h"
+#import "CDVViewController.h"
+#import "CDVCommandDelegate.h"
+#import "CDVURLProtocol.h"
+#import "CDVInvokedUrlCommand.h"
+#import "CDVWhitelist.h"
+#import "CDVScreenOrientationDelegate.h"
+#import "CDVTimer.h"
+#import "CDVUserAgentUtil.h"
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.h b/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.h
new file mode 100644
index 0000000..de5b518
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.h
@@ -0,0 +1,28 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVViewController.h"
+
+@interface CDVAppDelegate : NSObject <UIApplicationDelegate>{}
+
+@property (nonatomic, strong) IBOutlet UIWindow* window;
+@property (nonatomic, strong) IBOutlet CDVViewController* viewController;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m b/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m
new file mode 100644
index 0000000..6a339f4
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m
@@ -0,0 +1,118 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVAppDelegate.h"
+
+@implementation CDVAppDelegate
+
+@synthesize window, viewController;
+
+- (id)init
+{
+    /** If you need to do any extra app-specific initialization, you can do it here
+     *  -jm
+     **/
+    NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+
+    [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
+
+    int cacheSizeMemory = 8 * 1024 * 1024; // 8MB
+    int cacheSizeDisk = 32 * 1024 * 1024; // 32MB
+    NSURLCache* sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
+    [NSURLCache setSharedURLCache:sharedCache];
+
+    self = [super init];
+    return self;
+}
+
+#pragma mark UIApplicationDelegate implementation
+
+/**
+ * This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
+ */
+- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
+{
+    CGRect screenBounds = [[UIScreen mainScreen] bounds];
+
+    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
+    self.window.autoresizesSubviews = YES;
+
+    // only set if not already set in subclass
+    if (self.viewController == nil) {
+        self.viewController = [[CDVViewController alloc] init];
+    }
+
+    // Set your app's start page by setting the <content src='foo.html' /> tag in config.xml.
+    // If necessary, uncomment the line below to override it.
+    // self.viewController.startPage = @"index.html";
+
+    // NOTE: To customize the view's frame size (which defaults to full screen), override
+    // [self.viewController viewWillAppear:] in your view controller.
+
+    self.window.rootViewController = self.viewController;
+    [self.window makeKeyAndVisible];
+
+    return YES;
+}
+
+// this happens while we are running ( in the background, or from within our own app )
+// only valid if 40x-Info.plist specifies a protocol to handle
+- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
+{
+    if (!url) {
+        return NO;
+    }
+
+    NSMutableDictionary * openURLData = [[NSMutableDictionary alloc] init];
+
+    [openURLData setValue:url forKey:@"url"];
+
+    if (options[UIApplicationOpenURLOptionsSourceApplicationKey]) {
+        [openURLData setValue:options[UIApplicationOpenURLOptionsSourceApplicationKey] forKey:@"sourceApplication"];
+    }
+
+    if (options[UIApplicationOpenURLOptionsAnnotationKey]) {
+        [openURLData setValue:options[UIApplicationOpenURLOptionsAnnotationKey] forKey:@"annotation"];
+    }
+
+    // all plugins will get the notification, and their handlers will be called
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification object:openURLData]];
+
+    return YES;
+}
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000  
+- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
+#else //CB-12098.  Defaults to UIInterfaceOrientationMask for iOS 9+
+- (UIInterfaceOrientationMask)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
+#endif
+{
+    // iPhone doesn't support upside down by default, while the iPad does.  Override to allow all orientations always, and let the root view controller decide what's allowed (the supported orientations mask gets intersected).
+    NSUInteger supportedInterfaceOrientations = (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationPortraitUpsideDown);
+
+    return supportedInterfaceOrientations;
+}
+
+- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
+{
+    [[NSURLCache sharedURLCache] removeAllCachedResponses];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVAvailability.h b/platforms/ios/CordovaLib/Classes/Public/CDVAvailability.h
new file mode 100644
index 0000000..63341cf
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVAvailability.h
@@ -0,0 +1,113 @@
+/*
+ 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.
+ */
+
+#import "CDVAvailabilityDeprecated.h"
+
+#define __CORDOVA_IOS__
+
+#define __CORDOVA_0_9_6 906
+#define __CORDOVA_1_0_0 10000
+#define __CORDOVA_1_1_0 10100
+#define __CORDOVA_1_2_0 10200
+#define __CORDOVA_1_3_0 10300
+#define __CORDOVA_1_4_0 10400
+#define __CORDOVA_1_4_1 10401
+#define __CORDOVA_1_5_0 10500
+#define __CORDOVA_1_6_0 10600
+#define __CORDOVA_1_6_1 10601
+#define __CORDOVA_1_7_0 10700
+#define __CORDOVA_1_8_0 10800
+#define __CORDOVA_1_8_1 10801
+#define __CORDOVA_1_9_0 10900
+#define __CORDOVA_2_0_0 20000
+#define __CORDOVA_2_1_0 20100
+#define __CORDOVA_2_2_0 20200
+#define __CORDOVA_2_3_0 20300
+#define __CORDOVA_2_4_0 20400
+#define __CORDOVA_2_5_0 20500
+#define __CORDOVA_2_6_0 20600
+#define __CORDOVA_2_7_0 20700
+#define __CORDOVA_2_8_0 20800
+#define __CORDOVA_2_9_0 20900
+#define __CORDOVA_3_0_0 30000
+#define __CORDOVA_3_1_0 30100
+#define __CORDOVA_3_2_0 30200
+#define __CORDOVA_3_3_0 30300
+#define __CORDOVA_3_4_0 30400
+#define __CORDOVA_3_4_1 30401
+#define __CORDOVA_3_5_0 30500
+#define __CORDOVA_3_6_0 30600
+#define __CORDOVA_3_7_0 30700
+#define __CORDOVA_3_8_0 30800
+#define __CORDOVA_3_9_0 30900
+#define __CORDOVA_3_9_1 30901
+#define __CORDOVA_3_9_2 30902
+#define __CORDOVA_4_0_0 40000
+#define __CORDOVA_4_0_1 40001
+#define __CORDOVA_4_1_0 40100
+#define __CORDOVA_4_1_1 40101
+#define __CORDOVA_4_2_0 40200
+#define __CORDOVA_4_2_1 40201
+#define __CORDOVA_4_3_0 40300
+#define __CORDOVA_4_3_1 40301
+#define __CORDOVA_4_4_0 40400
+#define __CORDOVA_4_5_0 40500
+#define __CORDOVA_4_5_1 40501
+#define __CORDOVA_4_5_2 40502
+#define __CORDOVA_4_5_4 40504
+#define __CORDOVA_5_0_0 50000
+#define __CORDOVA_5_0_1 50001
+/* coho:next-version,insert-before */
+#define __CORDOVA_NA 99999      /* not available */
+
+/*
+ #if CORDOVA_VERSION_MIN_REQUIRED >= __CORDOVA_4_0_0
+    // do something when its at least 4.0.0
+ #else
+    // do something else (non 4.0.0)
+ #endif
+ */
+#ifndef CORDOVA_VERSION_MIN_REQUIRED
+    /* coho:next-version-min-required,replace-after */
+    #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_5_0_1
+#endif
+
+/*
+ Returns YES if it is at least version specified as NSString(X)
+ Usage:
+     if (IsAtLeastiOSVersion(@"5.1")) {
+         // do something for iOS 5.1 or greater
+     }
+ */
+#define IsAtLeastiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch] != NSOrderedAscending)
+
+/* Return the string version of the decimal version */
+#define CDV_VERSION [NSString stringWithFormat:@"%d.%d.%d", \
+    (CORDOVA_VERSION_MIN_REQUIRED / 10000),                 \
+    (CORDOVA_VERSION_MIN_REQUIRED % 10000) / 100,           \
+    (CORDOVA_VERSION_MIN_REQUIRED % 10000) % 100]
+
+// Enable this to log all exec() calls.
+#define CDV_ENABLE_EXEC_LOGGING 0
+#if CDV_ENABLE_EXEC_LOGGING
+    #define CDV_EXEC_LOG NSLog
+#else
+    #define CDV_EXEC_LOG(...) do { \
+} while (NO)
+#endif
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h b/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h
new file mode 100644
index 0000000..abf7a16
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h
@@ -0,0 +1,26 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+
+#ifdef __clang__
+    #define CDV_DEPRECATED(version, msg) __attribute__((deprecated("Deprecated in Cordova " #version ". " msg)))
+#else
+    #define CDV_DEPRECATED(version, msg) __attribute__((deprecated()))
+#endif
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegate.h b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegate.h
new file mode 100644
index 0000000..efc9ad3
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegate.h
@@ -0,0 +1,51 @@
+/*
+ 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.
+ */
+
+#import "CDVAvailability.h"
+#import "CDVInvokedUrlCommand.h"
+
+@class CDVPlugin;
+@class CDVPluginResult;
+@class CDVWhitelist;
+
+typedef NSURL* (^ UrlTransformerBlock)(NSURL*);
+
+@protocol CDVCommandDelegate <NSObject>
+
+@property (nonatomic, readonly) NSDictionary* settings;
+@property (nonatomic, copy) UrlTransformerBlock urlTransformer;
+
+- (NSString*)pathForResource:(NSString*)resourcepath;
+- (id)getCommandInstance:(NSString*)pluginName;
+
+// Sends a plugin result to the JS. This is thread-safe.
+- (void)sendPluginResult:(CDVPluginResult*)result callbackId:(NSString*)callbackId;
+// Evaluates the given JS. This is thread-safe.
+- (void)evalJs:(NSString*)js;
+// Can be used to evaluate JS right away instead of scheduling it on the run-loop.
+// This is required for dispatch resign and pause events, but should not be used
+// without reason. Without the run-loop delay, alerts used in JS callbacks may result
+// in dead-lock. This method must be called from the UI thread.
+- (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop;
+// Runs the given block on a background thread using a shared thread-pool.
+- (void)runInBackground:(void (^)(void))block;
+// Returns the User-Agent of the associated UIWebView.
+- (NSString*)userAgent;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.h b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.h
new file mode 100644
index 0000000..0531134
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.h
@@ -0,0 +1,36 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVCommandDelegate.h"
+
+@class CDVViewController;
+@class CDVCommandQueue;
+
+@interface CDVCommandDelegateImpl : NSObject <CDVCommandDelegate>{
+    @private
+    __weak CDVViewController* _viewController;
+    NSRegularExpression* _callbackIdPattern;
+    @protected
+    __weak CDVCommandQueue* _commandQueue;
+    BOOL _delayResponses;
+}
+- (id)initWithViewController:(CDVViewController*)viewController;
+- (void)flushCommandQueueWithDelayedJs;
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.m b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.m
new file mode 100644
index 0000000..effca6f
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.m
@@ -0,0 +1,186 @@
+/*
+ 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.
+ */
+
+#import "CDVCommandDelegateImpl.h"
+#import "CDVJSON_private.h"
+#import "CDVCommandQueue.h"
+#import "CDVPluginResult.h"
+#import "CDVViewController.h"
+
+@implementation CDVCommandDelegateImpl
+
+@synthesize urlTransformer;
+
+- (id)initWithViewController:(CDVViewController*)viewController
+{
+    self = [super init];
+    if (self != nil) {
+        _viewController = viewController;
+        _commandQueue = _viewController.commandQueue;
+
+        NSError* err = nil;
+        _callbackIdPattern = [NSRegularExpression regularExpressionWithPattern:@"[^A-Za-z0-9._-]" options:0 error:&err];
+        if (err != nil) {
+            // Couldn't initialize Regex
+            NSLog(@"Error: Couldn't initialize regex");
+            _callbackIdPattern = nil;
+        }
+    }
+    return self;
+}
+
+- (NSString*)pathForResource:(NSString*)resourcepath
+{
+    NSBundle* mainBundle = [NSBundle mainBundle];
+    NSMutableArray* directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]];
+    NSString* filename = [directoryParts lastObject];
+
+    [directoryParts removeLastObject];
+
+    NSString* directoryPartsJoined = [directoryParts componentsJoinedByString:@"/"];
+    NSString* directoryStr = _viewController.wwwFolderName;
+
+    if ([directoryPartsJoined length] > 0) {
+        directoryStr = [NSString stringWithFormat:@"%@/%@", _viewController.wwwFolderName, [directoryParts componentsJoinedByString:@"/"]];
+    }
+
+    return [mainBundle pathForResource:filename ofType:@"" inDirectory:directoryStr];
+}
+
+- (void)flushCommandQueueWithDelayedJs
+{
+    _delayResponses = YES;
+    [_commandQueue executePending];
+    _delayResponses = NO;
+}
+
+- (void)evalJsHelper2:(NSString*)js
+{
+    CDV_EXEC_LOG(@"Exec: evalling: %@", [js substringToIndex:MIN([js length], 160)]);
+    [_viewController.webViewEngine evaluateJavaScript:js completionHandler:^(id obj, NSError* error) {
+        // TODO: obj can be something other than string
+        if ([obj isKindOfClass:[NSString class]]) {
+            NSString* commandsJSON = (NSString*)obj;
+            if ([commandsJSON length] > 0) {
+                CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining.");
+            }
+
+            [self->_commandQueue enqueueCommandBatch:commandsJSON];
+            [self->_commandQueue executePending];
+        }
+    }];
+}
+
+- (void)evalJsHelper:(NSString*)js
+{
+    // Cycle the run-loop before executing the JS.
+    // For _delayResponses -
+    //    This ensures that we don't eval JS during the middle of an existing JS
+    //    function (possible since UIWebViewDelegate callbacks can be synchronous).
+    // For !isMainThread -
+    //    It's a hard error to eval on the non-UI thread.
+    // For !_commandQueue.currentlyExecuting -
+    //     This works around a bug where sometimes alerts() within callbacks can cause
+    //     dead-lock.
+    //     If the commandQueue is currently executing, then we know that it is safe to
+    //     execute the callback immediately.
+    // Using    (dispatch_get_main_queue()) does *not* fix deadlocks for some reason,
+    // but performSelectorOnMainThread: does.
+    if (_delayResponses || ![NSThread isMainThread] || !_commandQueue.currentlyExecuting) {
+        [self performSelectorOnMainThread:@selector(evalJsHelper2:) withObject:js waitUntilDone:NO];
+    } else {
+        [self evalJsHelper2:js];
+    }
+}
+
+- (BOOL)isValidCallbackId:(NSString*)callbackId
+{
+    if ((callbackId == nil) || (_callbackIdPattern == nil)) {
+        return NO;
+    }
+
+    // Disallow if too long or if any invalid characters were found.
+    if (([callbackId length] > 100) || [_callbackIdPattern firstMatchInString:callbackId options:0 range:NSMakeRange(0, [callbackId length])]) {
+        return NO;
+    }
+    return YES;
+}
+
+- (void)sendPluginResult:(CDVPluginResult*)result callbackId:(NSString*)callbackId
+{
+    CDV_EXEC_LOG(@"Exec(%@): Sending result. Status=%@", callbackId, result.status);
+    // This occurs when there is are no win/fail callbacks for the call.
+    if ([@"INVALID" isEqualToString:callbackId]) {
+        return;
+    }
+    // This occurs when the callback id is malformed.
+    if (![self isValidCallbackId:callbackId]) {
+        NSLog(@"Invalid callback id received by sendPluginResult");
+        return;
+    }
+    int status = [result.status intValue];
+    BOOL keepCallback = [result.keepCallback boolValue];
+    NSString* argumentsAsJSON = [result argumentsAsJSON];
+    BOOL debug = NO;
+    
+#ifdef DEBUG
+    debug = YES;
+#endif
+
+    NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d, %d)", callbackId, status, argumentsAsJSON, keepCallback, debug];
+
+    [self evalJsHelper:js];
+}
+
+- (void)evalJs:(NSString*)js
+{
+    [self evalJs:js scheduledOnRunLoop:YES];
+}
+
+- (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop
+{
+    js = [NSString stringWithFormat:@"try{cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})}catch(e){console.log('exception nativeEvalAndFetch : '+e);};", js];
+    if (scheduledOnRunLoop) {
+        [self evalJsHelper:js];
+    } else {
+        [self evalJsHelper2:js];
+    }
+}
+
+- (id)getCommandInstance:(NSString*)pluginName
+{
+    return [_viewController getCommandInstance:pluginName];
+}
+
+- (void)runInBackground:(void (^)(void))block
+{
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
+}
+
+- (NSString*)userAgent
+{
+    return [_viewController userAgent];
+}
+
+- (NSDictionary*)settings
+{
+    return _viewController.settings;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.h b/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.h
new file mode 100644
index 0000000..cb7bd6e
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.h
@@ -0,0 +1,39 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class CDVInvokedUrlCommand;
+@class CDVViewController;
+
+@interface CDVCommandQueue : NSObject
+
+@property (nonatomic, readonly) BOOL currentlyExecuting;
+
+- (id)initWithViewController:(CDVViewController*)viewController;
+- (void)dispose;
+
+- (void)resetRequestId;
+- (void)enqueueCommandBatch:(NSString*)batchJSON;
+
+- (void)fetchCommandsFromJs;
+- (void)executePending;
+- (BOOL)execute:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.m b/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.m
new file mode 100644
index 0000000..b78ed83
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.m
@@ -0,0 +1,194 @@
+/*
+ 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.
+ */
+
+#include <objc/message.h>
+#import "CDVCommandQueue.h"
+#import "CDVViewController.h"
+#import "CDVCommandDelegateImpl.h"
+#import "CDVJSON_private.h"
+#import "CDVDebug.h"
+
+// Parse JS on the main thread if it's shorter than this.
+static const NSInteger JSON_SIZE_FOR_MAIN_THREAD = 4 * 1024; // Chosen arbitrarily.
+// Execute multiple commands in one go until this many seconds have passed.
+static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame.
+
+@interface CDVCommandQueue () {
+    NSInteger _lastCommandQueueFlushRequestId;
+    __weak CDVViewController* _viewController;
+    NSMutableArray* _queue;
+    NSTimeInterval _startExecutionTime;
+}
+@end
+
+@implementation CDVCommandQueue
+
+- (BOOL)currentlyExecuting
+{
+    return _startExecutionTime > 0;
+}
+
+- (id)initWithViewController:(CDVViewController*)viewController
+{
+    self = [super init];
+    if (self != nil) {
+        _viewController = viewController;
+        _queue = [[NSMutableArray alloc] init];
+    }
+    return self;
+}
+
+- (void)dispose
+{
+    // TODO(agrieve): Make this a zeroing weak ref once we drop support for 4.3.
+    _viewController = nil;
+}
+
+- (void)resetRequestId
+{
+    _lastCommandQueueFlushRequestId = 0;
+}
+
+- (void)enqueueCommandBatch:(NSString*)batchJSON
+{
+    if ([batchJSON length] > 0) {
+        NSMutableArray* commandBatchHolder = [[NSMutableArray alloc] init];
+        [_queue addObject:commandBatchHolder];
+        if ([batchJSON length] < JSON_SIZE_FOR_MAIN_THREAD) {
+            [commandBatchHolder addObject:[batchJSON cdv_JSONObject]];
+        } else {
+            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() {
+                NSMutableArray* result = [batchJSON cdv_JSONObject];
+                @synchronized(commandBatchHolder) {
+                    [commandBatchHolder addObject:result];
+                }
+                [self performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO];
+            });
+        }
+    }
+}
+
+- (void)fetchCommandsFromJs
+{
+    __weak CDVCommandQueue* weakSelf = self;
+    NSString* js = @"cordova.require('cordova/exec').nativeFetchMessages()";
+
+    [_viewController.webViewEngine evaluateJavaScript:js
+                                    completionHandler:^(id obj, NSError* error) {
+        if ((error == nil) && [obj isKindOfClass:[NSString class]]) {
+            NSString* queuedCommandsJSON = (NSString*)obj;
+            CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0);
+            [weakSelf enqueueCommandBatch:queuedCommandsJSON];
+            // this has to be called here now, because fetchCommandsFromJs is now async (previously: synchronous)
+            [self executePending];
+        }
+    }];
+}
+
+- (void)executePending
+{
+    // Make us re-entrant-safe.
+    if (_startExecutionTime > 0) {
+        return;
+    }
+    @try {
+        _startExecutionTime = [NSDate timeIntervalSinceReferenceDate];
+
+        while ([_queue count] > 0) {
+            NSMutableArray* commandBatchHolder = _queue[0];
+            NSMutableArray* commandBatch = nil;
+            @synchronized(commandBatchHolder) {
+                // If the next-up command is still being decoded, wait for it.
+                if ([commandBatchHolder count] == 0) {
+                    break;
+                }
+                commandBatch = commandBatchHolder[0];
+            }
+
+            while ([commandBatch count] > 0) {
+                @autoreleasepool {
+                    // Execute the commands one-at-a-time.
+                    NSArray* jsonEntry = [commandBatch cdv_dequeue];
+                    if ([commandBatch count] == 0) {
+                        [_queue removeObjectAtIndex:0];
+                    }
+                    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry];
+                    CDV_EXEC_LOG(@"Exec(%@): Calling %@.%@", command.callbackId, command.className, command.methodName);
+
+                    if (![self execute:command]) {
+#ifdef DEBUG
+                            NSString* commandJson = [jsonEntry cdv_JSONString];
+                            static NSUInteger maxLogLength = 1024;
+                            NSString* commandString = ([commandJson length] > maxLogLength) ?
+                                [NSString stringWithFormat : @"%@[...]", [commandJson substringToIndex:maxLogLength]] :
+                                commandJson;
+
+                            DLog(@"FAILED pluginJSON = %@", commandString);
+#endif
+                    }
+                }
+
+                // Yield if we're taking too long.
+                if (([_queue count] > 0) && ([NSDate timeIntervalSinceReferenceDate] - _startExecutionTime > MAX_EXECUTION_TIME)) {
+                    [self performSelector:@selector(executePending) withObject:nil afterDelay:0];
+                    return;
+                }
+            }
+        }
+    } @finally
+    {
+        _startExecutionTime = 0;
+    }
+}
+
+- (BOOL)execute:(CDVInvokedUrlCommand*)command
+{
+    if ((command.className == nil) || (command.methodName == nil)) {
+        NSLog(@"ERROR: Classname and/or methodName not found for command.");
+        return NO;
+    }
+
+    // Fetch an instance of this class
+    CDVPlugin* obj = [_viewController.commandDelegate getCommandInstance:command.className];
+
+    if (!([obj isKindOfClass:[CDVPlugin class]])) {
+        NSLog(@"ERROR: Plugin '%@' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.", command.className);
+        return NO;
+    }
+    BOOL retVal = YES;
+    double started = [[NSDate date] timeIntervalSince1970] * 1000.0;
+    // Find the proper selector to call.
+    NSString* methodName = [NSString stringWithFormat:@"%@:", command.methodName];
+    SEL normalSelector = NSSelectorFromString(methodName);
+    if ([obj respondsToSelector:normalSelector]) {
+        // [obj performSelector:normalSelector withObject:command];
+        ((void (*)(id, SEL, id))objc_msgSend)(obj, normalSelector, command);
+    } else {
+        // There's no method to call, so throw an error.
+        NSLog(@"ERROR: Method '%@' not defined in Plugin '%@'", methodName, command.className);
+        retVal = NO;
+    }
+    double elapsed = [[NSDate date] timeIntervalSince1970] * 1000.0 - started;
+    if (elapsed > 10) {
+        NSLog(@"THREAD WARNING: ['%@'] took '%f' ms. Plugin should use a background thread.", command.className, elapsed);
+    }
+    return retVal;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.h b/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.h
new file mode 100644
index 0000000..bae3d0f
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.h
@@ -0,0 +1,30 @@
+/*
+ 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.
+ */
+
+@interface CDVConfigParser : NSObject <NSXMLParserDelegate>
+{
+    NSString* featureName;
+}
+
+@property (nonatomic, readonly, strong) NSMutableDictionary* pluginsDict;
+@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
+@property (nonatomic, readonly, strong) NSMutableArray* startupPluginNames;
+@property (nonatomic, readonly, strong) NSString* startPage;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.m b/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.m
new file mode 100644
index 0000000..ab32b4a
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.m
@@ -0,0 +1,81 @@
+/*
+ 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.
+ */
+
+#import "CDVConfigParser.h"
+
+@interface CDVConfigParser ()
+
+@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginsDict;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
+@property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames;
+@property (nonatomic, readwrite, strong) NSString* startPage;
+
+@end
+
+@implementation CDVConfigParser
+
+@synthesize pluginsDict, settings, startPage, startupPluginNames;
+
+- (id)init
+{
+    self = [super init];
+    if (self != nil) {
+        self.pluginsDict = [[NSMutableDictionary alloc] initWithCapacity:30];
+        self.settings = [[NSMutableDictionary alloc] initWithCapacity:30];
+        self.startupPluginNames = [[NSMutableArray alloc] initWithCapacity:8];
+        featureName = nil;
+    }
+    return self;
+}
+
+- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName attributes:(NSDictionary*)attributeDict
+{
+    if ([elementName isEqualToString:@"preference"]) {
+        settings[[attributeDict[@"name"] lowercaseString]] = attributeDict[@"value"];
+    } else if ([elementName isEqualToString:@"feature"]) { // store feature name to use with correct parameter set
+        featureName = [attributeDict[@"name"] lowercaseString];
+    } else if ((featureName != nil) && [elementName isEqualToString:@"param"]) {
+        NSString* paramName = [attributeDict[@"name"] lowercaseString];
+        id value = attributeDict[@"value"];
+        if ([paramName isEqualToString:@"ios-package"]) {
+            pluginsDict[featureName] = value;
+        }
+        BOOL paramIsOnload = ([paramName isEqualToString:@"onload"] && [@"true" isEqualToString : value]);
+        BOOL attribIsOnload = [@"true" isEqualToString :[attributeDict[@"onload"] lowercaseString]];
+        if (paramIsOnload || attribIsOnload) {
+            [self.startupPluginNames addObject:featureName];
+        }
+    } else if ([elementName isEqualToString:@"content"]) {
+        self.startPage = attributeDict[@"src"];
+    }
+}
+
+- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName
+{
+    if ([elementName isEqualToString:@"feature"]) { // no longer handling a feature so release
+        featureName = nil;
+    }
+}
+
+- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
+{
+    NSAssert(NO, @"config.xml parse error line %ld col %ld", (long)[parser lineNumber], (long)[parser columnNumber]);
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h b/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h
new file mode 100644
index 0000000..993e0a2
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h
@@ -0,0 +1,52 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVInvokedUrlCommand : NSObject {
+    NSString* _callbackId;
+    NSString* _className;
+    NSString* _methodName;
+    NSArray* _arguments;
+}
+
+@property (nonatomic, readonly) NSArray* arguments;
+@property (nonatomic, readonly) NSString* callbackId;
+@property (nonatomic, readonly) NSString* className;
+@property (nonatomic, readonly) NSString* methodName;
+
++ (CDVInvokedUrlCommand*)commandFromJson:(NSArray*)jsonEntry;
+
+- (id)initWithArguments:(NSArray*)arguments
+             callbackId:(NSString*)callbackId
+              className:(NSString*)className
+             methodName:(NSString*)methodName;
+
+- (id)initFromJson:(NSArray*)jsonEntry;
+
+// Returns the argument at the given index.
+// If index >= the number of arguments, returns nil.
+// If the argument at the given index is NSNull, returns nil.
+- (id)argumentAtIndex:(NSUInteger)index;
+// Same as above, but returns defaultValue instead of nil.
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue;
+// Same as above, but returns defaultValue instead of nil, and if the argument is not of the expected class, returns defaultValue
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue andClass:(Class)aClass;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.m b/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.m
new file mode 100644
index 0000000..5b4281d
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.m
@@ -0,0 +1,116 @@
+/*
+ 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.
+ */
+
+#import "CDVInvokedUrlCommand.h"
+#import "CDVJSON_private.h"
+
+@implementation CDVInvokedUrlCommand
+
+@synthesize arguments = _arguments;
+@synthesize callbackId = _callbackId;
+@synthesize className = _className;
+@synthesize methodName = _methodName;
+
++ (CDVInvokedUrlCommand*)commandFromJson:(NSArray*)jsonEntry
+{
+    return [[CDVInvokedUrlCommand alloc] initFromJson:jsonEntry];
+}
+
+- (id)initFromJson:(NSArray*)jsonEntry
+{
+    id tmp = [jsonEntry objectAtIndex:0];
+    NSString* callbackId = tmp == [NSNull null] ? nil : tmp;
+    NSString* className = [jsonEntry objectAtIndex:1];
+    NSString* methodName = [jsonEntry objectAtIndex:2];
+    NSMutableArray* arguments = [jsonEntry objectAtIndex:3];
+
+    return [self initWithArguments:arguments
+                        callbackId:callbackId
+                         className:className
+                        methodName:methodName];
+}
+
+- (id)initWithArguments:(NSArray*)arguments
+             callbackId:(NSString*)callbackId
+              className:(NSString*)className
+             methodName:(NSString*)methodName
+{
+    self = [super init];
+    if (self != nil) {
+        _arguments = arguments;
+        _callbackId = callbackId;
+        _className = className;
+        _methodName = methodName;
+    }
+    [self massageArguments];
+    return self;
+}
+
+- (void)massageArguments
+{
+    NSMutableArray* newArgs = nil;
+
+    for (NSUInteger i = 0, count = [_arguments count]; i < count; ++i) {
+        id arg = [_arguments objectAtIndex:i];
+        if (![arg isKindOfClass:[NSDictionary class]]) {
+            continue;
+        }
+        NSDictionary* dict = arg;
+        NSString* type = [dict objectForKey:@"CDVType"];
+        if (!type || ![type isEqualToString:@"ArrayBuffer"]) {
+            continue;
+        }
+        NSString* data = [dict objectForKey:@"data"];
+        if (!data) {
+            continue;
+        }
+        if (newArgs == nil) {
+            newArgs = [NSMutableArray arrayWithArray:_arguments];
+            _arguments = newArgs;
+        }
+        [newArgs replaceObjectAtIndex:i withObject:[[NSData alloc] initWithBase64EncodedString:data options:0]];
+    }
+}
+
+- (id)argumentAtIndex:(NSUInteger)index
+{
+    return [self argumentAtIndex:index withDefault:nil];
+}
+
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue
+{
+    return [self argumentAtIndex:index withDefault:defaultValue andClass:nil];
+}
+
+- (id)argumentAtIndex:(NSUInteger)index withDefault:(id)defaultValue andClass:(Class)aClass
+{
+    if (index >= [_arguments count]) {
+        return defaultValue;
+    }
+    id ret = [_arguments objectAtIndex:index];
+    if (ret == [NSNull null]) {
+        ret = defaultValue;
+    }
+    if ((aClass != nil) && ![ret isKindOfClass:aClass]) {
+        ret = defaultValue;
+    }
+    return ret;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.h b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.h
new file mode 100644
index 0000000..cc43b16
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.h
@@ -0,0 +1,39 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVPlugin.h"
+
+@interface CDVPlugin (CDVPluginResources)
+
+/*
+ This will return the localized string for a key in a .bundle that is named the same as your class
+ For example, if your plugin class was called Foo, and you have a Spanish localized strings file, it will
+ try to load the desired key from Foo.bundle/es.lproj/Localizable.strings
+ */
+- (NSString*)pluginLocalizedString:(NSString*)key;
+
+/*
+ This will return the image for a name in a .bundle that is named the same as your class
+ For example, if your plugin class was called Foo, and you have an image called "bar",
+ it will try to load the image from Foo.bundle/bar.png (and appropriately named retina versions)
+ */
+- (UIImage*)pluginImageResource:(NSString*)name;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.m b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.m
new file mode 100644
index 0000000..5690738
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.m
@@ -0,0 +1,38 @@
+/*
+ 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.
+ */
+
+#import "CDVPlugin+Resources.h"
+
+@implementation CDVPlugin (CDVPluginResources)
+
+- (NSString*)pluginLocalizedString:(NSString*)key
+{
+    NSBundle* bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:NSStringFromClass([self class]) ofType:@"bundle"]];
+
+    return [bundle localizedStringForKey:(key) value:nil table:nil];
+}
+
+- (UIImage*)pluginImageResource:(NSString*)name
+{
+    NSString* resourceIdentifier = [NSString stringWithFormat:@"%@.bundle/%@", NSStringFromClass([self class]), name];
+
+    return [UIImage imageNamed:resourceIdentifier];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.h b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.h
new file mode 100644
index 0000000..0bdbbab
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.h
@@ -0,0 +1,74 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "CDVPluginResult.h"
+#import "NSMutableArray+QueueAdditions.h"
+#import "CDVCommandDelegate.h"
+#import "CDVWebViewEngineProtocol.h"
+
+@interface UIView (org_apache_cordova_UIView_Extension)
+
+@property (nonatomic, weak) UIScrollView* scrollView;
+
+@end
+
+extern NSString* const CDVPageDidLoadNotification;
+extern NSString* const CDVPluginHandleOpenURLNotification;
+extern NSString* const CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification;
+extern NSString* const CDVPluginResetNotification;
+extern NSString* const CDVViewWillAppearNotification;
+extern NSString* const CDVViewDidAppearNotification;
+extern NSString* const CDVViewWillDisappearNotification;
+extern NSString* const CDVViewDidDisappearNotification;
+extern NSString* const CDVViewWillLayoutSubviewsNotification;
+extern NSString* const CDVViewDidLayoutSubviewsNotification;
+extern NSString* const CDVViewWillTransitionToSizeNotification;
+
+@interface CDVPlugin : NSObject {}
+
+@property (nonatomic, readonly, weak) UIView* webView;
+@property (nonatomic, readonly, weak) id <CDVWebViewEngineProtocol> webViewEngine;
+
+@property (nonatomic, weak) UIViewController* viewController;
+@property (nonatomic, weak) id <CDVCommandDelegate> commandDelegate;
+
+@property (readonly, assign) BOOL hasPendingOperation;
+
+- (void)pluginInitialize;
+
+- (void)handleOpenURL:(NSNotification*)notification;
+- (void)handleOpenURLWithApplicationSourceAndAnnotation:(NSNotification*)notification;
+- (void)onAppTerminate;
+- (void)onMemoryWarning;
+- (void)onReset;
+- (void)dispose;
+
+/*
+ // see initWithWebView implementation
+ - (void) onPause {}
+ - (void) onResume {}
+ - (void) onOrientationWillChange {}
+ - (void) onOrientationDidChange {}
+ */
+
+- (id)appDelegate;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.m b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.m
new file mode 100644
index 0000000..6af03e9
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.m
@@ -0,0 +1,199 @@
+/*
+ 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.
+ */
+
+#import "CDVPlugin.h"
+#import "CDVPlugin+Private.h"
+#import "CDVPlugin+Resources.h"
+#import "CDVViewController.h"
+#include <objc/message.h>
+
+@implementation UIView (org_apache_cordova_UIView_Extension)
+
+@dynamic scrollView;
+
+- (UIScrollView*)scrollView
+{
+    SEL scrollViewSelector = NSSelectorFromString(@"scrollView");
+
+    if ([self respondsToSelector:scrollViewSelector]) {
+        return ((id (*)(id, SEL))objc_msgSend)(self, scrollViewSelector);
+    }
+
+    return nil;
+}
+
+@end
+
+NSString* const CDVPageDidLoadNotification = @"CDVPageDidLoadNotification";
+NSString* const CDVPluginHandleOpenURLNotification = @"CDVPluginHandleOpenURLNotification";
+NSString* const CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification = @"CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification";
+NSString* const CDVPluginResetNotification = @"CDVPluginResetNotification";
+NSString* const CDVViewWillAppearNotification = @"CDVViewWillAppearNotification";
+NSString* const CDVViewDidAppearNotification = @"CDVViewDidAppearNotification";
+NSString* const CDVViewWillDisappearNotification = @"CDVViewWillDisappearNotification";
+NSString* const CDVViewDidDisappearNotification = @"CDVViewDidDisappearNotification";
+NSString* const CDVViewWillLayoutSubviewsNotification = @"CDVViewWillLayoutSubviewsNotification";
+NSString* const CDVViewDidLayoutSubviewsNotification = @"CDVViewDidLayoutSubviewsNotification";
+NSString* const CDVViewWillTransitionToSizeNotification = @"CDVViewWillTransitionToSizeNotification";
+
+@interface CDVPlugin ()
+
+@property (readwrite, assign) BOOL hasPendingOperation;
+@property (nonatomic, readwrite, weak) id <CDVWebViewEngineProtocol> webViewEngine;
+
+@end
+
+@implementation CDVPlugin
+@synthesize webViewEngine, viewController, commandDelegate, hasPendingOperation;
+@dynamic webView;
+
+// Do not override these methods. Use pluginInitialize instead.
+- (instancetype)initWithWebViewEngine:(id <CDVWebViewEngineProtocol>)theWebViewEngine
+{
+    self = [super init];
+    if (self) {
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:CDVPluginHandleOpenURLNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURLWithApplicationSourceAndAnnotation:) name:CDVPluginHandleOpenURLWithAppSourceAndAnnotationNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReset) name:CDVPluginResetNotification object:theWebViewEngine.engineWebView];
+
+        self.webViewEngine = theWebViewEngine;
+    }
+    return self;
+}
+
+- (void)pluginInitialize
+{
+    // You can listen to more app notifications, see:
+    // http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplication_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006728-CH3-DontLinkElementID_4
+
+    // NOTE: if you want to use these, make sure you uncomment the corresponding notification handler
+
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPause) name:UIApplicationDidEnterBackgroundNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume) name:UIApplicationWillEnterForegroundNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationWillChange) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+
+    // Added in 2.5.0
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad:) name:CDVPageDidLoadNotification object:self.webView];
+    //Added in 4.3.0
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillAppear:) name:CDVViewWillAppearNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidAppear:) name:CDVViewDidAppearNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillDisappear:) name:CDVViewWillDisappearNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidDisappear:) name:CDVViewDidDisappearNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillLayoutSubviews:) name:CDVViewWillLayoutSubviewsNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidLayoutSubviews:) name:CDVViewDidLayoutSubviewsNotification object:nil];
+    // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillTransitionToSize:) name:CDVViewWillTransitionToSizeNotification object:nil];
+}
+
+- (void)dispose
+{
+    viewController = nil;
+    commandDelegate = nil;
+}
+
+- (UIView*)webView
+{
+    if (self.webViewEngine != nil) {
+        return self.webViewEngine.engineWebView;
+    }
+
+    return nil;
+}
+
+/*
+// NOTE: for onPause and onResume, calls into JavaScript must not call or trigger any blocking UI, like alerts
+- (void) onPause {}
+- (void) onResume {}
+- (void) onOrientationWillChange {}
+- (void) onOrientationDidChange {}
+*/
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void)handleOpenURL:(NSNotification*)notification
+{
+    // override to handle urls sent to your app
+    // register your url schemes in your App-Info.plist
+
+    NSURL* url = [notification object];
+
+    if ([url isKindOfClass:[NSURL class]]) {
+        /* Do your thing! */
+    }
+}
+
+/*
+    NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts
+ */
+- (void)handleOpenURLWithApplicationSourceAndAnnotation: (NSNotification*)notification
+{
+    
+    // override to handle urls sent to your app
+    // register your url schemes in your App-Info.plist
+    
+    // The notification object is an NSDictionary which contains
+    // - url which is a type of NSURL
+    // - sourceApplication which is a type of NSString and represents the package
+    // id of the app that calls our app
+    // - annotation which a type of Property list which can be several different types
+    // please see https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/PropertyList.html
+    
+    NSDictionary*  notificationData = [notification object];
+    
+    if ([notificationData isKindOfClass: NSDictionary.class]){
+        
+        NSURL* url = notificationData[@"url"];
+        NSString* sourceApplication = notificationData[@"sourceApplication"];
+        id annotation = notificationData[@"annotation"];
+        
+        if ([url isKindOfClass:NSURL.class] && [sourceApplication isKindOfClass:NSString.class] && annotation) {
+            /* Do your thing! */
+        }
+    }
+}
+
+
+/* NOTE: calls into JavaScript must not call or trigger any blocking UI, like alerts */
+- (void)onAppTerminate
+{
+    // override this if you need to do any cleanup on app exit
+}
+
+- (void)onMemoryWarning
+{
+    // override to remove caches, etc
+}
+
+- (void)onReset
+{
+    // Override to cancel any long-running requests when the WebView navigates or refreshes.
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];   // this will remove all notifications unless added using addObserverForName:object:queue:usingBlock:
+}
+
+- (id)appDelegate
+{
+    return [[UIApplication sharedApplication] delegate];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.h b/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.h
new file mode 100644
index 0000000..2f62d77
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.h
@@ -0,0 +1,83 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailability.h"
+
+typedef NS_ENUM(NSUInteger, CDVCommandStatus) {
+    CDVCommandStatus_NO_RESULT NS_SWIFT_NAME(noResult) = 0,
+    CDVCommandStatus_OK NS_SWIFT_NAME(ok),
+    CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION NS_SWIFT_NAME(classNotFoundException),
+    CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION NS_SWIFT_NAME(illegalAccessException),
+    CDVCommandStatus_INSTANTIATION_EXCEPTION NS_SWIFT_NAME(instantiationException),
+    CDVCommandStatus_MALFORMED_URL_EXCEPTION NS_SWIFT_NAME(malformedUrlException),
+    CDVCommandStatus_IO_EXCEPTION NS_SWIFT_NAME(ioException),
+    CDVCommandStatus_INVALID_ACTION NS_SWIFT_NAME(invalidAction),
+    CDVCommandStatus_JSON_EXCEPTION NS_SWIFT_NAME(jsonException),
+    CDVCommandStatus_ERROR NS_SWIFT_NAME(error)
+};
+
+// This exists to preserve compatibility with early Swift plugins, who are
+// using CDVCommandStatus as ObjC-style constants rather than as Swift enum
+// values.
+// This declares extern'ed constants (implemented in CDVPluginResult.m)
+#define SWIFT_ENUM_COMPAT_HACK(enumVal) extern const CDVCommandStatus SWIFT_##enumVal NS_SWIFT_NAME(enumVal)
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_NO_RESULT);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_OK);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INSTANTIATION_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_MALFORMED_URL_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_IO_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INVALID_ACTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_JSON_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ERROR);
+#undef SWIFT_ENUM_COMPAT_HACK
+
+@interface CDVPluginResult : NSObject {}
+
+@property (nonatomic, strong, readonly) NSNumber* status;
+@property (nonatomic, strong, readonly) id message;
+@property (nonatomic, strong)           NSNumber* keepCallback;
+// This property can be used to scope the lifetime of another object. For example,
+// Use it to store the associated NSData when `message` is created using initWithBytesNoCopy.
+@property (nonatomic, strong) id associatedObject;
+
+- (CDVPluginResult*)init;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsString:(NSString*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArray:(NSArray*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsInt:(int)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSInteger:(NSInteger)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSUInteger:(NSUInteger)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsBool:(BOOL)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArrayBuffer:(NSData*)theMessage;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsMultipart:(NSArray*)theMessages;
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageToErrorObject:(int)errorCode;
+
++ (void)setVerbose:(BOOL)verbose;
++ (BOOL)isVerbose;
+
+- (void)setKeepCallbackAsBool:(BOOL)bKeepCallback;
+
+- (NSString*)argumentsAsJSON;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.m b/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.m
new file mode 100644
index 0000000..2f6f3a6
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.m
@@ -0,0 +1,203 @@
+/*
+ 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.
+ */
+
+#import "CDVPluginResult.h"
+#import "CDVJSON_private.h"
+#import "CDVDebug.h"
+
+// This exists to preserve compatibility with early Swift plugins, who are
+// using CDVCommandStatus as ObjC-style constants rather than as Swift enum
+// values.
+// These constants alias the enum values back to their previous names.
+#define SWIFT_ENUM_COMPAT_HACK(enumVal) const CDVCommandStatus SWIFT_##enumVal NS_SWIFT_NAME(enumVal) = enumVal
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_NO_RESULT);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_OK);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_CLASS_NOT_FOUND_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ILLEGAL_ACCESS_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INSTANTIATION_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_MALFORMED_URL_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_IO_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_INVALID_ACTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_JSON_EXCEPTION);
+SWIFT_ENUM_COMPAT_HACK(CDVCommandStatus_ERROR);
+#undef SWIFT_ENUM_COMPAT_HACK
+
+@interface CDVPluginResult ()
+
+- (CDVPluginResult*)initWithStatus:(CDVCommandStatus)statusOrdinal message:(id)theMessage;
+
+@end
+
+@implementation CDVPluginResult
+@synthesize status, message, keepCallback, associatedObject;
+
+static NSArray* org_apache_cordova_CommandStatusMsgs;
+
+id messageFromArrayBuffer(NSData* data)
+{
+    return @{
+               @"CDVType" : @"ArrayBuffer",
+               @"data" :[data base64EncodedStringWithOptions:0]
+    };
+}
+
+id massageMessage(id message)
+{
+    if ([message isKindOfClass:[NSData class]]) {
+        return messageFromArrayBuffer(message);
+    }
+    return message;
+}
+
+id messageFromMultipart(NSArray* theMessages)
+{
+    NSMutableArray* messages = [NSMutableArray arrayWithArray:theMessages];
+
+    for (NSUInteger i = 0; i < messages.count; ++i) {
+        [messages replaceObjectAtIndex:i withObject:massageMessage([messages objectAtIndex:i])];
+    }
+
+    return @{
+               @"CDVType" : @"MultiPart",
+               @"messages" : messages
+    };
+}
+
++ (void)initialize
+{
+    org_apache_cordova_CommandStatusMsgs = [[NSArray alloc] initWithObjects:@"No result",
+        @"OK",
+        @"Class not found",
+        @"Illegal access",
+        @"Instantiation error",
+        @"Malformed url",
+        @"IO error",
+        @"Invalid action",
+        @"JSON error",
+        @"Error",
+        nil];
+}
+
+- (CDVPluginResult*)init
+{
+    return [self initWithStatus:CDVCommandStatus_NO_RESULT message:nil];
+}
+
+- (CDVPluginResult*)initWithStatus:(CDVCommandStatus)statusOrdinal message:(id)theMessage
+{
+    self = [super init];
+    if (self) {
+        status = [NSNumber numberWithInt:statusOrdinal];
+        message = theMessage;
+        keepCallback = [NSNumber numberWithBool:NO];
+    }
+    return self;
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:nil];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsString:(NSString*)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArray:(NSArray*)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsInt:(int)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithInt:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSInteger:(NSInteger)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithInteger:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSUInteger:(NSUInteger)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithUnsignedInteger:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithDouble:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsBool:(BOOL)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithBool:theMessage]];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:theMessage];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArrayBuffer:(NSData*)theMessage
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:messageFromArrayBuffer(theMessage)];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsMultipart:(NSArray*)theMessages
+{
+    return [[self alloc] initWithStatus:statusOrdinal message:messageFromMultipart(theMessages)];
+}
+
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageToErrorObject:(int)errorCode
+{
+    NSDictionary* errDict = @{@"code" :[NSNumber numberWithInt:errorCode]};
+
+    return [[self alloc] initWithStatus:statusOrdinal message:errDict];
+}
+
+- (void)setKeepCallbackAsBool:(BOOL)bKeepCallback
+{
+    [self setKeepCallback:[NSNumber numberWithBool:bKeepCallback]];
+}
+
+- (NSString*)argumentsAsJSON
+{
+    id arguments = (self.message == nil ? [NSNull null] : self.message);
+    NSArray* argumentsWrappedInArray = [NSArray arrayWithObject:arguments];
+
+    NSString* argumentsJSON = [argumentsWrappedInArray cdv_JSONString];
+
+    argumentsJSON = [argumentsJSON substringWithRange:NSMakeRange(1, [argumentsJSON length] - 2)];
+
+    return argumentsJSON;
+}
+
+static BOOL gIsVerbose = NO;
++ (void)setVerbose:(BOOL)verbose
+{
+    gIsVerbose = verbose;
+}
+
++ (BOOL)isVerbose
+{
+    return gIsVerbose;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVScreenOrientationDelegate.h b/platforms/ios/CordovaLib/Classes/Public/CDVScreenOrientationDelegate.h
new file mode 100644
index 0000000..519dd49
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVScreenOrientationDelegate.h
@@ -0,0 +1,33 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol CDVScreenOrientationDelegate <NSObject>
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000  
+- (NSUInteger)supportedInterfaceOrientations;  
+#else  
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations;
+#endif
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
+- (BOOL)shouldAutorotate;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVTimer.h b/platforms/ios/CordovaLib/Classes/Public/CDVTimer.h
new file mode 100644
index 0000000..6d31593
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVTimer.h
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVTimer : NSObject
+
++ (void)start:(NSString*)name;
++ (void)stop:(NSString*)name;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVTimer.m b/platforms/ios/CordovaLib/Classes/Public/CDVTimer.m
new file mode 100644
index 0000000..784e94d
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVTimer.m
@@ -0,0 +1,123 @@
+/*
+ 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.
+ */
+
+#import "CDVTimer.h"
+
+#pragma mark CDVTimerItem
+
+@interface CDVTimerItem : NSObject
+
+@property (nonatomic, strong) NSString* name;
+@property (nonatomic, strong) NSDate* started;
+@property (nonatomic, strong) NSDate* ended;
+
+- (void)log;
+
+@end
+
+@implementation CDVTimerItem
+
+- (void)log
+{
+    NSLog(@"[CDVTimer][%@] %fms", self.name, [self.ended timeIntervalSinceDate:self.started] * 1000.0);
+}
+
+@end
+
+#pragma mark CDVTimer
+
+@interface CDVTimer ()
+
+@property (nonatomic, strong) NSMutableDictionary* items;
+
+@end
+
+@implementation CDVTimer
+
+#pragma mark object methods
+
+- (id)init
+{
+    if (self = [super init]) {
+        self.items = [NSMutableDictionary dictionaryWithCapacity:6];
+    }
+
+    return self;
+}
+
+- (void)add:(NSString*)name
+{
+    if ([self.items objectForKey:[name lowercaseString]] == nil) {
+        CDVTimerItem* item = [CDVTimerItem new];
+        item.name = name;
+        item.started = [NSDate new];
+        [self.items setObject:item forKey:[name lowercaseString]];
+    } else {
+        NSLog(@"Timer called '%@' already exists.", name);
+    }
+}
+
+- (void)remove:(NSString*)name
+{
+    CDVTimerItem* item = [self.items objectForKey:[name lowercaseString]];
+
+    if (item != nil) {
+        item.ended = [NSDate new];
+        [item log];
+        [self.items removeObjectForKey:[name lowercaseString]];
+    } else {
+        NSLog(@"Timer called '%@' does not exist.", name);
+    }
+}
+
+- (void)removeAll
+{
+    [self.items removeAllObjects];
+}
+
+#pragma mark class methods
+
++ (void)start:(NSString*)name
+{
+    [[CDVTimer sharedInstance] add:name];
+}
+
++ (void)stop:(NSString*)name
+{
+    [[CDVTimer sharedInstance] remove:name];
+}
+
++ (void)clearAll
+{
+    [[CDVTimer sharedInstance] removeAll];
+}
+
++ (CDVTimer*)sharedInstance
+{
+    static dispatch_once_t pred = 0;
+    __strong static CDVTimer* _sharedObject = nil;
+
+    dispatch_once(&pred, ^{
+            _sharedObject = [[self alloc] init];
+        });
+
+    return _sharedObject;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.h b/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.h
new file mode 100644
index 0000000..0561e04
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.h
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import "CDVAvailability.h"
+
+@class CDVViewController;
+
+@interface CDVURLProtocol : NSURLProtocol {}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m b/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m
new file mode 100644
index 0000000..7b2c5ce
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m
@@ -0,0 +1,113 @@
+/*
+ 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.
+ */
+
+#import <AssetsLibrary/ALAsset.h>
+#import <AssetsLibrary/ALAssetRepresentation.h>
+#import <AssetsLibrary/ALAssetsLibrary.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+#import "CDVURLProtocol.h"
+#import "CDVCommandQueue.h"
+#import "CDVViewController.h"
+
+// Contains a set of NSNumbers of addresses of controllers. It doesn't store
+// the actual pointer to avoid retaining.
+static NSMutableSet* gRegisteredControllers = nil;
+
+NSString* const kCDVAssetsLibraryPrefixes = @"assets-library://";
+
+@implementation CDVURLProtocol
+
+
++ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest
+{
+    NSURL* theUrl = [theRequest URL];
+
+    if ([[theUrl absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) {
+        return YES;
+    }
+
+    return NO;
+}
+
++ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
+{
+    // NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd));
+    return request;
+}
+
+- (void)startLoading
+{
+    // NSLog(@"%@ received %@ - start", self, NSStringFromSelector(_cmd));
+    NSURL* url = [[self request] URL];
+
+    if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) {
+        ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
+            if (asset) {
+                // We have the asset!  Get the data and send it along.
+                ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+                NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
+                Byte* buffer = (Byte*)malloc((unsigned long)[assetRepresentation size]);
+                NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil];
+                NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+                [self sendResponseWithResponseCode:200 data:data mimeType:MIMEType];
+            } else {
+                // Retrieving the asset failed for some reason.  Send an error.
+                [self sendResponseWithResponseCode:404 data:nil mimeType:nil];
+            }
+        };
+        ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
+            // Retrieving the asset failed for some reason.  Send an error.
+            [self sendResponseWithResponseCode:401 data:nil mimeType:nil];
+        };
+
+        ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+        [assetsLibrary assetForURL:url resultBlock:resultBlock failureBlock:failureBlock];
+        return;
+    }
+
+    NSString* body = [NSString stringWithFormat:@"Access not allowed to URL: %@", url];
+    [self sendResponseWithResponseCode:401 data:[body dataUsingEncoding:NSASCIIStringEncoding] mimeType:nil];
+}
+
+- (void)stopLoading
+{
+    // do any cleanup here
+}
+
++ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
+{
+    return NO;
+}
+
+- (void)sendResponseWithResponseCode:(NSInteger)statusCode data:(NSData*)data mimeType:(NSString*)mimeType
+{
+    if (mimeType == nil) {
+        mimeType = @"text/plain";
+    }
+
+    NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : mimeType}];
+
+    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+    if (data != nil) {
+        [[self client] URLProtocol:self didLoadData:data];
+    }
+    [[self client] URLProtocolDidFinishLoading:self];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.h b/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.h
new file mode 100644
index 0000000..4de382f
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.h
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVUserAgentUtil : NSObject
++ (NSString*)originalUserAgent;
++ (void)acquireLock:(void (^)(NSInteger lockToken))block;
++ (void)releaseLock:(NSInteger*)lockToken;
++ (void)setUserAgent:(NSString*)value lockToken:(NSInteger)lockToken;
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.m b/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.m
new file mode 100644
index 0000000..6eb5912
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.m
@@ -0,0 +1,124 @@
+/*
+ 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.
+ */
+
+#import "CDVUserAgentUtil.h"
+
+#import <UIKit/UIKit.h>
+
+// #define VerboseLog NSLog
+#define VerboseLog(...) do {} while (0)
+
+static NSString* const kCdvUserAgentKey = @"Cordova-User-Agent";
+static NSString* const kCdvUserAgentVersionKey = @"Cordova-User-Agent-Version";
+
+static NSString* gOriginalUserAgent = nil;
+static NSInteger gNextLockToken = 0;
+static NSInteger gCurrentLockToken = 0;
+static NSMutableArray* gPendingSetUserAgentBlocks = nil;
+
+@implementation CDVUserAgentUtil
+
++ (NSString*)originalUserAgent
+{
+    if (gOriginalUserAgent == nil) {
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppLocaleDidChange:)
+                                                     name:NSCurrentLocaleDidChangeNotification object:nil];
+
+        NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+        NSString* systemVersion = [[UIDevice currentDevice] systemVersion];
+        NSString* localeStr = [[NSLocale currentLocale] localeIdentifier];
+        // Record the model since simulator can change it without re-install (CB-5420).
+        NSString* model = [UIDevice currentDevice].model;
+        // Record the version of the app so that we can bust the cache when it changes (CB-10078)
+        NSString* appVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
+        NSString* systemAndLocale = [NSString stringWithFormat:@"%@ %@ %@ %@", appVersion, model, systemVersion, localeStr];
+
+        NSString* cordovaUserAgentVersion = [userDefaults stringForKey:kCdvUserAgentVersionKey];
+        gOriginalUserAgent = [userDefaults stringForKey:kCdvUserAgentKey];
+        BOOL cachedValueIsOld = ![systemAndLocale isEqualToString:cordovaUserAgentVersion];
+
+        if ((gOriginalUserAgent == nil) || cachedValueIsOld) {
+            UIWebView* sampleWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
+            gOriginalUserAgent = [sampleWebView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
+
+            [userDefaults setObject:gOriginalUserAgent forKey:kCdvUserAgentKey];
+            [userDefaults setObject:systemAndLocale forKey:kCdvUserAgentVersionKey];
+
+            [userDefaults synchronize];
+        }
+    }
+    return gOriginalUserAgent;
+}
+
++ (void)onAppLocaleDidChange:(NSNotification*)notification
+{
+    // TODO: We should figure out how to update the user-agent of existing UIWebViews when this happens.
+    // Maybe use the PDF bug (noted in setUserAgent:).
+    gOriginalUserAgent = nil;
+}
+
++ (void)acquireLock:(void (^)(NSInteger lockToken))block
+{
+    if (gCurrentLockToken == 0) {
+        gCurrentLockToken = ++gNextLockToken;
+        VerboseLog(@"Gave lock %d", gCurrentLockToken);
+        block(gCurrentLockToken);
+    } else {
+        if (gPendingSetUserAgentBlocks == nil) {
+            gPendingSetUserAgentBlocks = [[NSMutableArray alloc] initWithCapacity:4];
+        }
+        VerboseLog(@"Waiting for lock");
+        [gPendingSetUserAgentBlocks addObject:block];
+    }
+}
+
++ (void)releaseLock:(NSInteger*)lockToken
+{
+    if (lockToken == nil || *lockToken == 0) {
+        return;
+    }
+    NSAssert(gCurrentLockToken == *lockToken, @"Got token %ld, expected %ld", (long)*lockToken, (long)gCurrentLockToken);
+
+    VerboseLog(@"Released lock %d", *lockToken);
+    if ([gPendingSetUserAgentBlocks count] > 0) {
+        void (^block)(NSInteger lockToken) = [gPendingSetUserAgentBlocks objectAtIndex:0];
+        [gPendingSetUserAgentBlocks removeObjectAtIndex:0];
+        gCurrentLockToken = ++gNextLockToken;
+        NSLog(@"Gave lock %ld", (long)gCurrentLockToken);
+        block(gCurrentLockToken);
+    } else {
+        gCurrentLockToken = 0;
+    }
+    *lockToken = 0;
+}
+
++ (void)setUserAgent:(NSString*)value lockToken:(NSInteger)lockToken
+{
+    NSAssert(gCurrentLockToken == lockToken, @"Got token %ld, expected %ld", (long)lockToken, (long)gCurrentLockToken);
+    VerboseLog(@"User-Agent set to: %@", value);
+
+    // Setting the UserAgent must occur before a UIWebView is instantiated.
+    // It is read per instantiation, so it does not affect previously created views.
+    // Except! When a PDF is loaded, all currently active UIWebViews reload their
+    // User-Agent from the NSUserDefaults some time after the DidFinishLoad of the PDF bah!
+    NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:value, @"UserAgent", nil];
+    [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVViewController.h b/platforms/ios/CordovaLib/Classes/Public/CDVViewController.h
new file mode 100644
index 0000000..605dbbb
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVViewController.h
@@ -0,0 +1,92 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import <Foundation/NSJSONSerialization.h>
+#import "CDVAvailability.h"
+#import "CDVInvokedUrlCommand.h"
+#import "CDVCommandDelegate.h"
+#import "CDVCommandQueue.h"
+#import "CDVScreenOrientationDelegate.h"
+#import "CDVPlugin.h"
+#import "CDVWebViewEngineProtocol.h"
+
+@interface CDVViewController : UIViewController <CDVScreenOrientationDelegate>{
+    @protected
+    id <CDVWebViewEngineProtocol> _webViewEngine;
+    @protected
+    id <CDVCommandDelegate> _commandDelegate;
+    @protected
+    CDVCommandQueue* _commandQueue;
+    NSString* _userAgent;
+}
+
+@property (nonatomic, readonly, weak) IBOutlet UIView* webView;
+
+@property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readonly, strong) NSDictionary* pluginsMap;
+@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
+@property (nonatomic, readonly, strong) NSXMLParser* configParser;
+
+@property (nonatomic, readwrite, copy) NSString* configFile;
+@property (nonatomic, readwrite, copy) NSString* wwwFolderName;
+@property (nonatomic, readwrite, copy) NSString* startPage;
+@property (nonatomic, readonly, strong) CDVCommandQueue* commandQueue;
+@property (nonatomic, readonly, strong) id <CDVWebViewEngineProtocol> webViewEngine;
+@property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate;
+
+/**
+ The complete user agent that Cordova will use when sending web requests.
+ */
+@property (nonatomic, readonly) NSString* userAgent;
+
+/**
+ The base user agent data that Cordova will use to build its user agent.  If this
+ property isn't set, Cordova will use the standard web view user agent as its
+ base.
+ */
+@property (nonatomic, readwrite, copy) NSString* baseUserAgent;
+
+/**
+	Takes/Gives an array of UIInterfaceOrientation (int) objects
+	ex. UIInterfaceOrientationPortrait
+*/
+@property (nonatomic, readwrite, strong) NSArray* supportedOrientations;
+
+/**
+ The address of the lock token used for controlling access to setting the user-agent
+ */
+@property (nonatomic, readonly) NSInteger* userAgentLockToken;
+
+- (UIView*)newCordovaViewWithFrame:(CGRect)bounds;
+
+- (NSString*)appURLScheme;
+- (NSURL*)errorURL;
+
+- (UIColor*)colorFromColorString:(NSString*)colorString;
+- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations;
+- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation;
+
+- (id)getCommandInstance:(NSString*)pluginName;
+- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className;
+- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName;
+
+- (void)parseSettingsWithParser:(NSObject <NSXMLParserDelegate>*)delegate;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m b/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m
new file mode 100644
index 0000000..616d9ff
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m
@@ -0,0 +1,811 @@
+/*
+ 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.
+ */
+
+#import <objc/message.h>
+#import "CDV.h"
+#import "CDVPlugin+Private.h"
+#import "CDVUIWebViewDelegate.h"
+#import "CDVConfigParser.h"
+#import "CDVUserAgentUtil.h"
+#import <AVFoundation/AVFoundation.h>
+#import "NSDictionary+CordovaPreferences.h"
+#import "CDVLocalStorage.h"
+#import "CDVCommandDelegateImpl.h"
+#import <Foundation/NSCharacterSet.h>
+
+@interface CDVViewController () {
+    NSInteger _userAgentLockToken;
+}
+
+@property (nonatomic, readwrite, strong) NSXMLParser* configParser;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
+@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginObjects;
+@property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames;
+@property (nonatomic, readwrite, strong) NSDictionary* pluginsMap;
+@property (nonatomic, readwrite, strong) id <CDVWebViewEngineProtocol> webViewEngine;
+
+@property (readwrite, assign) BOOL initialized;
+
+@property (atomic, strong) NSURL* openURL;
+
+@end
+
+@implementation CDVViewController
+
+@synthesize supportedOrientations;
+@synthesize pluginObjects, pluginsMap, startupPluginNames;
+@synthesize configParser, settings;
+@synthesize wwwFolderName, startPage, initialized, openURL, baseUserAgent;
+@synthesize commandDelegate = _commandDelegate;
+@synthesize commandQueue = _commandQueue;
+@synthesize webViewEngine = _webViewEngine;
+@dynamic webView;
+
+- (void)__init
+{
+    if ((self != nil) && !self.initialized) {
+        _commandQueue = [[CDVCommandQueue alloc] initWithViewController:self];
+        _commandDelegate = [[CDVCommandDelegateImpl alloc] initWithViewController:self];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillTerminate:)
+                                                     name:UIApplicationWillTerminateNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:)
+                                                     name:UIApplicationWillResignActiveNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:)
+                                                     name:UIApplicationDidBecomeActiveNotification object:nil];
+
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillEnterForeground:)
+                                                     name:UIApplicationWillEnterForegroundNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground:)
+                                                     name:UIApplicationDidEnterBackgroundNotification object:nil];
+
+        // read from UISupportedInterfaceOrientations (or UISupportedInterfaceOrientations~iPad, if its iPad) from -Info.plist
+        self.supportedOrientations = [self parseInterfaceOrientations:
+            [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]];
+
+        [self printVersion];
+        [self printMultitaskingInfo];
+        [self printPlatformVersionWarning];
+        self.initialized = YES;
+    }
+}
+
+- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    [self __init];
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+    [self __init];
+    return self;
+}
+
+- (id)init
+{
+    self = [super init];
+    [self __init];
+    return self;
+}
+
+- (void)printVersion
+{
+    NSLog(@"Apache Cordova native platform version %@ is starting.", CDV_VERSION);
+}
+
+- (void)printPlatformVersionWarning
+{
+    if (!IsAtLeastiOSVersion(@"8.0")) {
+        NSLog(@"CRITICAL: For Cordova 4.0.0 and above, you will need to upgrade to at least iOS 8.0 or greater. Your current version of iOS is %@.",
+            [[UIDevice currentDevice] systemVersion]
+            );
+    }
+}
+
+- (void)printMultitaskingInfo
+{
+    UIDevice* device = [UIDevice currentDevice];
+    BOOL backgroundSupported = NO;
+
+    if ([device respondsToSelector:@selector(isMultitaskingSupported)]) {
+        backgroundSupported = device.multitaskingSupported;
+    }
+
+    NSNumber* exitsOnSuspend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationExitsOnSuspend"];
+    if (exitsOnSuspend == nil) { // if it's missing, it should be NO (i.e. multi-tasking on by default)
+        exitsOnSuspend = [NSNumber numberWithBool:NO];
+    }
+
+    NSLog(@"Multi-tasking -> Device: %@, App: %@", (backgroundSupported ? @"YES" : @"NO"), (![exitsOnSuspend intValue]) ? @"YES" : @"NO");
+}
+
+-(NSString*)configFilePath{
+    NSString* path = self.configFile ?: @"config.xml";
+
+    // if path is relative, resolve it against the main bundle
+    if(![path isAbsolutePath]){
+        NSString* absolutePath = [[NSBundle mainBundle] pathForResource:path ofType:nil];
+        if(!absolutePath){
+            NSAssert(NO, @"ERROR: %@ not found in the main bundle!", path);
+        }
+        path = absolutePath;
+    }
+
+    // Assert file exists
+    if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
+        NSAssert(NO, @"ERROR: %@ does not exist. Please run cordova-ios/bin/cordova_plist_to_config_xml path/to/project.", path);
+        return nil;
+    }
+
+    return path;
+}
+
+- (void)parseSettingsWithParser:(NSObject <NSXMLParserDelegate>*)delegate
+{
+    // read from config.xml in the app bundle
+    NSString* path = [self configFilePath];
+
+    NSURL* url = [NSURL fileURLWithPath:path];
+
+    self.configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
+    if (self.configParser == nil) {
+        NSLog(@"Failed to initialize XML parser.");
+        return;
+    }
+    [self.configParser setDelegate:((id < NSXMLParserDelegate >)delegate)];
+    [self.configParser parse];
+}
+
+- (void)loadSettings
+{
+    CDVConfigParser* delegate = [[CDVConfigParser alloc] init];
+
+    [self parseSettingsWithParser:delegate];
+
+    // Get the plugin dictionary, whitelist and settings from the delegate.
+    self.pluginsMap = delegate.pluginsDict;
+    self.startupPluginNames = delegate.startupPluginNames;
+    self.settings = delegate.settings;
+
+    // And the start folder/page.
+    if(self.wwwFolderName == nil){
+        self.wwwFolderName = @"www";
+    }
+    if(delegate.startPage && self.startPage == nil){
+        self.startPage = delegate.startPage;
+    }
+    if (self.startPage == nil) {
+        self.startPage = @"index.html";
+    }
+
+    // Initialize the plugin objects dict.
+    self.pluginObjects = [[NSMutableDictionary alloc] initWithCapacity:20];
+}
+
+- (NSURL*)appUrl
+{
+    NSURL* appURL = nil;
+
+    if ([self.startPage rangeOfString:@"://"].location != NSNotFound) {
+        appURL = [NSURL URLWithString:self.startPage];
+    } else if ([self.wwwFolderName rangeOfString:@"://"].location != NSNotFound) {
+        appURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", self.wwwFolderName, self.startPage]];
+    } else if([self.wwwFolderName rangeOfString:@".bundle"].location != NSNotFound){
+        // www folder is actually a bundle
+        NSBundle* bundle = [NSBundle bundleWithPath:self.wwwFolderName];
+        appURL = [bundle URLForResource:self.startPage withExtension:nil];
+    } else if([self.wwwFolderName rangeOfString:@".framework"].location != NSNotFound){
+        // www folder is actually a framework
+        NSBundle* bundle = [NSBundle bundleWithPath:self.wwwFolderName];
+        appURL = [bundle URLForResource:self.startPage withExtension:nil];
+    } else {
+        // CB-3005 strip parameters from start page to check if page exists in resources
+        NSURL* startURL = [NSURL URLWithString:self.startPage];
+        NSString* startFilePath = [self.commandDelegate pathForResource:[startURL path]];
+
+        if (startFilePath == nil) {
+            appURL = nil;
+        } else {
+            appURL = [NSURL fileURLWithPath:startFilePath];
+            // CB-3005 Add on the query params or fragment.
+            NSString* startPageNoParentDirs = self.startPage;
+            NSRange r = [startPageNoParentDirs rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"?#"] options:0];
+            if (r.location != NSNotFound) {
+                NSString* queryAndOrFragment = [self.startPage substringFromIndex:r.location];
+                appURL = [NSURL URLWithString:queryAndOrFragment relativeToURL:appURL];
+            }
+        }
+    }
+
+    return appURL;
+}
+
+- (NSURL*)errorURL
+{
+    NSURL* errorUrl = nil;
+
+    id setting = [self.settings cordovaSettingForKey:@"ErrorUrl"];
+
+    if (setting) {
+        NSString* errorUrlString = (NSString*)setting;
+        if ([errorUrlString rangeOfString:@"://"].location != NSNotFound) {
+            errorUrl = [NSURL URLWithString:errorUrlString];
+        } else {
+            NSURL* url = [NSURL URLWithString:(NSString*)setting];
+            NSString* errorFilePath = [self.commandDelegate pathForResource:[url path]];
+            if (errorFilePath) {
+                errorUrl = [NSURL fileURLWithPath:errorFilePath];
+            }
+        }
+    }
+
+    return errorUrl;
+}
+
+- (UIView*)webView
+{
+    if (self.webViewEngine != nil) {
+        return self.webViewEngine.engineWebView;
+    }
+
+    return nil;
+}
+
+// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+
+    // Load settings
+    [self loadSettings];
+
+    NSString* backupWebStorageType = @"cloud"; // default value
+
+    id backupWebStorage = [self.settings cordovaSettingForKey:@"BackupWebStorage"];
+    if ([backupWebStorage isKindOfClass:[NSString class]]) {
+        backupWebStorageType = backupWebStorage;
+    }
+    [self.settings setCordovaSetting:backupWebStorageType forKey:@"BackupWebStorage"];
+
+    [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType];
+
+    // // Instantiate the WebView ///////////////
+
+    if (!self.webView) {
+        [self createGapView];
+    }
+
+    // /////////////////
+
+    /*
+     * Fire up CDVLocalStorage to work-around WebKit storage limitations: on all iOS 5.1+ versions for local-only backups, but only needed on iOS 5.1 for cloud backup.
+        With minimum iOS 7/8 supported, only first clause applies.
+     */
+    if ([backupWebStorageType isEqualToString:@"local"]) {
+        NSString* localStorageFeatureName = @"localstorage";
+        if ([self.pluginsMap objectForKey:localStorageFeatureName]) { // plugin specified in config
+            [self.startupPluginNames addObject:localStorageFeatureName];
+        }
+    }
+
+    if ([self.startupPluginNames count] > 0) {
+        [CDVTimer start:@"TotalPluginStartup"];
+
+        for (NSString* pluginName in self.startupPluginNames) {
+            [CDVTimer start:pluginName];
+            [self getCommandInstance:pluginName];
+            [CDVTimer stop:pluginName];
+        }
+
+        [CDVTimer stop:@"TotalPluginStartup"];
+    }
+
+    // /////////////////
+    NSURL* appURL = [self appUrl];
+    __weak __typeof__(self) weakSelf = self;
+
+    [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
+        // Fix the memory leak caused by the strong reference.
+        [weakSelf setLockToken:lockToken];
+        if (appURL) {
+            NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
+            [self.webViewEngine loadRequest:appReq];
+        } else {
+            NSString* loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", self.wwwFolderName, self.startPage];
+            NSLog(@"%@", loadErr);
+
+            NSURL* errorUrl = [self errorURL];
+            if (errorUrl) {
+                errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [loadErr stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]] relativeToURL:errorUrl];
+                NSLog(@"%@", [errorUrl absoluteString]);
+                [self.webViewEngine loadRequest:[NSURLRequest requestWithURL:errorUrl]];
+            } else {
+                NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr];
+                [self.webViewEngine loadHTMLString:html baseURL:nil];
+            }
+        }
+    }];
+    
+    // /////////////////
+    
+    NSString* bgColorString = [self.settings cordovaSettingForKey:@"BackgroundColor"];
+    UIColor* bgColor = [self colorFromColorString:bgColorString];
+    [self.webView setBackgroundColor:bgColor];
+}
+
+- (void)setLockToken:(NSInteger)lockToken
+{
+	_userAgentLockToken = lockToken;
+	[CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken];
+}
+
+-(void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillAppearNotification object:nil]];
+}
+
+-(void)viewDidAppear:(BOOL)animated
+{
+    [super viewDidAppear:animated];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidAppearNotification object:nil]];
+}
+
+-(void)viewWillDisappear:(BOOL)animated
+{
+    [super viewWillDisappear:animated];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillDisappearNotification object:nil]];
+}
+
+-(void)viewDidDisappear:(BOOL)animated
+{
+    [super viewDidDisappear:animated];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidDisappearNotification object:nil]];
+}
+
+-(void)viewWillLayoutSubviews
+{
+    [super viewWillLayoutSubviews];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillLayoutSubviewsNotification object:nil]];
+}
+
+-(void)viewDidLayoutSubviews
+{
+    [super viewDidLayoutSubviews];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidLayoutSubviewsNotification object:nil]];
+}
+
+-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
+{
+    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillTransitionToSizeNotification object:[NSValue valueWithCGSize:size]]];
+}
+
+- (UIColor*)colorFromColorString:(NSString*)colorString
+{
+    // No value, nothing to do
+    if (!colorString) {
+        return nil;
+    }
+    
+    // Validate format
+    NSError* error = NULL;
+    NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"^(#[0-9A-F]{3}|(0x|#)([0-9A-F]{2})?[0-9A-F]{6})$" options:NSRegularExpressionCaseInsensitive error:&error];
+    NSUInteger countMatches = [regex numberOfMatchesInString:colorString options:0 range:NSMakeRange(0, [colorString length])];
+    
+    if (!countMatches) {
+        return nil;
+    }
+    
+    // #FAB to #FFAABB
+    if ([colorString hasPrefix:@"#"] && [colorString length] == 4) {
+        NSString* r = [colorString substringWithRange:NSMakeRange(1, 1)];
+        NSString* g = [colorString substringWithRange:NSMakeRange(2, 1)];
+        NSString* b = [colorString substringWithRange:NSMakeRange(3, 1)];
+        colorString = [NSString stringWithFormat:@"#%@%@%@%@%@%@", r, r, g, g, b, b];
+    }
+    
+    // #RRGGBB to 0xRRGGBB
+    colorString = [colorString stringByReplacingOccurrencesOfString:@"#" withString:@"0x"];
+    
+    // 0xRRGGBB to 0xAARRGGBB
+    if ([colorString hasPrefix:@"0x"] && [colorString length] == 8) {
+        colorString = [@"0xFF" stringByAppendingString:[colorString substringFromIndex:2]];
+    }
+    
+    // 0xAARRGGBB to int
+    unsigned colorValue = 0;
+    NSScanner *scanner = [NSScanner scannerWithString:colorString];
+    if (![scanner scanHexInt:&colorValue]) {
+        return nil;
+    }
+    
+    // int to UIColor
+    return [UIColor colorWithRed:((float)((colorValue & 0x00FF0000) >> 16))/255.0
+                           green:((float)((colorValue & 0x0000FF00) >>  8))/255.0
+                            blue:((float)((colorValue & 0x000000FF) >>  0))/255.0
+                           alpha:((float)((colorValue & 0xFF000000) >> 24))/255.0];
+}
+
+- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations
+{
+    NSMutableArray* result = [[NSMutableArray alloc] init];
+
+    if (orientations != nil) {
+        NSEnumerator* enumerator = [orientations objectEnumerator];
+        NSString* orientationString;
+
+        while (orientationString = [enumerator nextObject]) {
+            if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) {
+                [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) {
+                [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]];
+            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) {
+                [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]];
+            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) {
+                [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]];
+            }
+        }
+    }
+
+    // default
+    if ([result count] == 0) {
+        [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]];
+    }
+
+    return result;
+}
+
+- (BOOL)shouldAutorotate
+{
+    return YES;
+}
+
+// CB-12098
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000  
+- (NSUInteger)supportedInterfaceOrientations  
+#else  
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations
+#endif
+{
+    NSUInteger ret = 0;
+
+    if ([self supportsOrientation:UIInterfaceOrientationPortrait]) {
+        ret = ret | (1 << UIInterfaceOrientationPortrait);
+    }
+    if ([self supportsOrientation:UIInterfaceOrientationPortraitUpsideDown]) {
+        ret = ret | (1 << UIInterfaceOrientationPortraitUpsideDown);
+    }
+    if ([self supportsOrientation:UIInterfaceOrientationLandscapeRight]) {
+        ret = ret | (1 << UIInterfaceOrientationLandscapeRight);
+    }
+    if ([self supportsOrientation:UIInterfaceOrientationLandscapeLeft]) {
+        ret = ret | (1 << UIInterfaceOrientationLandscapeLeft);
+    }
+
+    return ret;
+}
+
+- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation
+{
+    return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]];
+}
+
+- (UIView*)newCordovaViewWithFrame:(CGRect)bounds
+{
+    NSString* defaultWebViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaDefaultWebViewEngine"];
+    NSString* webViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaWebViewEngine"];
+
+    if (!defaultWebViewEngineClass) {
+        defaultWebViewEngineClass = @"CDVUIWebViewEngine";
+    }
+    if (!webViewEngineClass) {
+        webViewEngineClass = defaultWebViewEngineClass;
+    }
+
+    // Find webViewEngine
+    if (NSClassFromString(webViewEngineClass)) {
+        self.webViewEngine = [[NSClassFromString(webViewEngineClass) alloc] initWithFrame:bounds];
+        // if a webView engine returns nil (not supported by the current iOS version) or doesn't conform to the protocol, or can't load the request, we use UIWebView
+        if (!self.webViewEngine || ![self.webViewEngine conformsToProtocol:@protocol(CDVWebViewEngineProtocol)] || ![self.webViewEngine canLoadRequest:[NSURLRequest requestWithURL:self.appUrl]]) {
+            self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds];
+        }
+    } else {
+        self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds];
+    }
+
+    if ([self.webViewEngine isKindOfClass:[CDVPlugin class]]) {
+        [self registerPlugin:(CDVPlugin*)self.webViewEngine withClassName:webViewEngineClass];
+    }
+
+    return self.webViewEngine.engineWebView;
+}
+
+- (NSString*)userAgent
+{
+    if (_userAgent != nil) {
+        return _userAgent;
+    }
+
+    NSString* localBaseUserAgent;
+    if (self.baseUserAgent != nil) {
+        localBaseUserAgent = self.baseUserAgent;
+    } else if ([self.settings cordovaSettingForKey:@"OverrideUserAgent"] != nil) {
+        localBaseUserAgent = [self.settings cordovaSettingForKey:@"OverrideUserAgent"];
+    } else {
+        localBaseUserAgent = [CDVUserAgentUtil originalUserAgent];
+    }
+    NSString* appendUserAgent = [self.settings cordovaSettingForKey:@"AppendUserAgent"];
+    if (appendUserAgent) {
+        _userAgent = [NSString stringWithFormat:@"%@ %@", localBaseUserAgent, appendUserAgent];
+    } else {
+        // Use our address as a unique number to append to the User-Agent.
+        _userAgent = localBaseUserAgent;
+    }
+    return _userAgent;
+}
+
+- (void)createGapView
+{
+    CGRect webViewBounds = self.view.bounds;
+
+    webViewBounds.origin = self.view.bounds.origin;
+
+    UIView* view = [self newCordovaViewWithFrame:webViewBounds];
+
+    view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+    [self.view addSubview:view];
+    [self.view sendSubviewToBack:view];
+}
+
+- (void)didReceiveMemoryWarning
+{
+    // iterate through all the plugin objects, and call hasPendingOperation
+    // if at least one has a pending operation, we don't call [super didReceiveMemoryWarning]
+
+    NSEnumerator* enumerator = [self.pluginObjects objectEnumerator];
+    CDVPlugin* plugin;
+
+    BOOL doPurge = YES;
+
+    while ((plugin = [enumerator nextObject])) {
+        if (plugin.hasPendingOperation) {
+            NSLog(@"Plugin '%@' has a pending operation, memory purge is delayed for didReceiveMemoryWarning.", NSStringFromClass([plugin class]));
+            doPurge = NO;
+        }
+    }
+
+    if (doPurge) {
+        // Releases the view if it doesn't have a superview.
+        [super didReceiveMemoryWarning];
+    }
+
+    // Release any cached data, images, etc. that aren't in use.
+}
+
+#pragma mark CordovaCommands
+
+- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className
+{
+    if ([plugin respondsToSelector:@selector(setViewController:)]) {
+        [plugin setViewController:self];
+    }
+
+    if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) {
+        [plugin setCommandDelegate:_commandDelegate];
+    }
+
+    [self.pluginObjects setObject:plugin forKey:className];
+    [plugin pluginInitialize];
+}
+
+- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName
+{
+    if ([plugin respondsToSelector:@selector(setViewController:)]) {
+        [plugin setViewController:self];
+    }
+
+    if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) {
+        [plugin setCommandDelegate:_commandDelegate];
+    }
+
+    NSString* className = NSStringFromClass([plugin class]);
+    [self.pluginObjects setObject:plugin forKey:className];
+    [self.pluginsMap setValue:className forKey:[pluginName lowercaseString]];
+    [plugin pluginInitialize];
+}
+
+/**
+ Returns an instance of a CordovaCommand object, based on its name.  If one exists already, it is returned.
+ */
+- (id)getCommandInstance:(NSString*)pluginName
+{
+    // first, we try to find the pluginName in the pluginsMap
+    // (acts as a whitelist as well) if it does not exist, we return nil
+    // NOTE: plugin names are matched as lowercase to avoid problems - however, a
+    // possible issue is there can be duplicates possible if you had:
+    // "org.apache.cordova.Foo" and "org.apache.cordova.foo" - only the lower-cased entry will match
+    NSString* className = [self.pluginsMap objectForKey:[pluginName lowercaseString]];
+
+    if (className == nil) {
+        return nil;
+    }
+
+    id obj = [self.pluginObjects objectForKey:className];
+    if (!obj) {
+        obj = [[NSClassFromString(className)alloc] initWithWebViewEngine:_webViewEngine];
+        if (!obj) {
+            NSString* fullClassName = [NSString stringWithFormat:@"%@.%@",
+                                       NSBundle.mainBundle.infoDictionary[@"CFBundleExecutable"],
+                                       className];
+            obj = [[NSClassFromString(fullClassName)alloc] initWithWebViewEngine:_webViewEngine];
+        }
+
+        if (obj != nil) {
+            [self registerPlugin:obj withClassName:className];
+        } else {
+            NSLog(@"CDVPlugin class %@ (pluginName: %@) does not exist.", className, pluginName);
+        }
+    }
+    return obj;
+}
+
+#pragma mark -
+
+- (NSString*)appURLScheme
+{
+    NSString* URLScheme = nil;
+
+    NSArray* URLTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"];
+
+    if (URLTypes != nil) {
+        NSDictionary* dict = [URLTypes objectAtIndex:0];
+        if (dict != nil) {
+            NSArray* URLSchemes = [dict objectForKey:@"CFBundleURLSchemes"];
+            if (URLSchemes != nil) {
+                URLScheme = [URLSchemes objectAtIndex:0];
+            }
+        }
+    }
+
+    return URLScheme;
+}
+
+#pragma mark -
+#pragma mark UIApplicationDelegate impl
+
+/*
+ This method lets your application know that it is about to be terminated and purged from memory entirely
+ */
+- (void)onAppWillTerminate:(NSNotification*)notification
+{
+    // empty the tmp directory
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    NSError* __autoreleasing err = nil;
+
+    // clear contents of NSTemporaryDirectory
+    NSString* tempDirectoryPath = NSTemporaryDirectory();
+    NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath];
+    NSString* fileName = nil;
+    BOOL result;
+
+    while ((fileName = [directoryEnumerator nextObject])) {
+        NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName];
+        result = [fileMgr removeItemAtPath:filePath error:&err];
+        if (!result && err) {
+            NSLog(@"Failed to delete: %@ (error: %@)", filePath, err);
+        }
+    }
+}
+
+- (bool)isUrlEmpty:(NSURL *)url
+{
+    if (!url || (url == (id) [NSNull null])) {
+        return true;
+    }
+    NSString *urlAsString = [url absoluteString];
+    return (urlAsString == (id) [NSNull null] || [urlAsString length]==0 || [urlAsString isEqualToString:@"about:blank"]);
+}
+
+- (bool)checkAndReinitViewUrl
+{
+    NSURL* appURL = [self appUrl];
+    if ([self isUrlEmpty: [self.webViewEngine URL]] && ![self isUrlEmpty: appURL]) {
+        NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
+        [self.webViewEngine loadRequest:appReq];
+        return true;
+    }
+    return false;
+}
+
+/*
+ This method is called to let your application know that it is about to move from the active to inactive state.
+ You should use this method to pause ongoing tasks, disable timer, ...
+ */
+- (void)onAppWillResignActive:(NSNotification*)notification
+{
+    [self checkAndReinitViewUrl];
+    // NSLog(@"%@",@"applicationWillResignActive");
+    [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resign');" scheduledOnRunLoop:NO];
+}
+
+/*
+ In iOS 4.0 and later, this method is called as part of the transition from the background to the inactive state.
+ You can use this method to undo many of the changes you made to your application upon entering the background.
+ invariably followed by applicationDidBecomeActive
+ */
+- (void)onAppWillEnterForeground:(NSNotification*)notification
+{
+    [self checkAndReinitViewUrl];
+    // NSLog(@"%@",@"applicationWillEnterForeground");
+    [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resume');"];
+    
+    if (!IsAtLeastiOSVersion(@"11.0")) {
+        /** Clipboard fix **/
+        UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
+        NSString* string = pasteboard.string;
+        if (string) {
+            [pasteboard setValue:string forPasteboardType:@"public.text"];
+        }
+    }
+}
+
+// This method is called to let your application know that it moved from the inactive to active state.
+- (void)onAppDidBecomeActive:(NSNotification*)notification
+{
+    [self checkAndReinitViewUrl];
+    // NSLog(@"%@",@"applicationDidBecomeActive");
+    [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('active');"];
+}
+
+/*
+ In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method
+ when the user quits an application that supports background execution.
+ */
+- (void)onAppDidEnterBackground:(NSNotification*)notification
+{
+    [self checkAndReinitViewUrl];
+    // NSLog(@"%@",@"applicationDidEnterBackground");
+    [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('pause', null, true);" scheduledOnRunLoop:NO];
+}
+
+// ///////////////////////
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+    [_commandQueue dispose];
+    [[self.pluginObjects allValues] makeObjectsPerformSelector:@selector(dispose)];
+
+    [self.webViewEngine loadHTMLString:@"about:blank" baseURL:nil];
+    [self.pluginObjects removeAllObjects];
+    [self.webView removeFromSuperview];
+    self.webViewEngine = nil;
+}
+
+- (NSInteger*)userAgentLockToken
+{
+    return &_userAgentLockToken;
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h b/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h
new file mode 100644
index 0000000..34d07f3
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h
@@ -0,0 +1,42 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+
+#define kCDVWebViewEngineScriptMessageHandlers @"kCDVWebViewEngineScriptMessageHandlers"
+#define kCDVWebViewEngineUIWebViewDelegate @"kCDVWebViewEngineUIWebViewDelegate"
+#define kCDVWebViewEngineWKNavigationDelegate @"kCDVWebViewEngineWKNavigationDelegate"
+#define kCDVWebViewEngineWKUIDelegate @"kCDVWebViewEngineWKUIDelegate"
+#define kCDVWebViewEngineWebViewPreferences @"kCDVWebViewEngineWebViewPreferences"
+
+@protocol CDVWebViewEngineProtocol <NSObject>
+
+@property (nonatomic, strong, readonly) UIView* engineWebView;
+
+- (id)loadRequest:(NSURLRequest*)request;
+- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL;
+- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler;
+
+- (NSURL*)URL;
+- (BOOL)canLoadRequest:(NSURLRequest*)request;
+
+- (instancetype)initWithFrame:(CGRect)frame;
+- (void)updateWithInfo:(NSDictionary*)info;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.h b/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.h
new file mode 100644
index 0000000..9165097
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.h
@@ -0,0 +1,34 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+extern NSString* const kCDVDefaultWhitelistRejectionString;
+
+@interface CDVWhitelist : NSObject
+
+@property (nonatomic, copy) NSString* whitelistRejectionFormatString;
+
+- (id)initWithArray:(NSArray*)array;
+- (BOOL)schemeIsAllowed:(NSString*)scheme;
+- (BOOL)URLIsAllowed:(NSURL*)url;
+- (BOOL)URLIsAllowed:(NSURL*)url logFailure:(BOOL)logFailure;
+- (NSString*)errorStringForURL:(NSURL*)url;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.m b/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.m
new file mode 100644
index 0000000..758f4d1
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.m
@@ -0,0 +1,285 @@
+/*
+ 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.
+ */
+
+#import "CDVWhitelist.h"
+
+NSString* const kCDVDefaultWhitelistRejectionString = @"ERROR whitelist rejection: url='%@'";
+NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
+
+@interface CDVWhitelistPattern : NSObject {
+    @private
+    NSRegularExpression* _scheme;
+    NSRegularExpression* _host;
+    NSNumber* _port;
+    NSRegularExpression* _path;
+}
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards;
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path;
+- (bool)matches:(NSURL*)url;
+
+@end
+
+@implementation CDVWhitelistPattern
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards
+{
+    NSString* regex = [NSRegularExpression escapedPatternForString:pattern];
+
+    if (allowWildcards) {
+        regex = [regex stringByReplacingOccurrencesOfString:@"\\*" withString:@".*"];
+
+        /* [NSURL path] has the peculiarity that a trailing slash at the end of a path
+         * will be omitted. This regex tweak compensates for that.
+         */
+        if ([regex hasSuffix:@"\\/.*"]) {
+            regex = [NSString stringWithFormat:@"%@(\\/.*)?", [regex substringToIndex:([regex length] - 4)]];
+        }
+    }
+    return [NSString stringWithFormat:@"%@$", regex];
+}
+
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path
+{
+    self = [super init];  // Potentially change "self"
+    if (self) {
+        if ((scheme == nil) || [scheme isEqualToString:@"*"]) {
+            _scheme = nil;
+        } else {
+            _scheme = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:scheme allowWildcards:NO] options:NSRegularExpressionCaseInsensitive error:nil];
+        }
+        if ([host isEqualToString:@"*"] || host == nil) {
+            _host = nil;
+        } else if ([host hasPrefix:@"*."]) {
+            _host = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"([a-z0-9.-]*\\.)?%@", [CDVWhitelistPattern regexFromPattern:[host substringFromIndex:2] allowWildcards:false]] options:NSRegularExpressionCaseInsensitive error:nil];
+        } else {
+            _host = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:host allowWildcards:NO] options:NSRegularExpressionCaseInsensitive error:nil];
+        }
+        if ((port == nil) || [port isEqualToString:@"*"]) {
+            _port = nil;
+        } else {
+            _port = [[NSNumber alloc] initWithInteger:[port integerValue]];
+        }
+        if ((path == nil) || [path isEqualToString:@"/*"]) {
+            _path = nil;
+        } else {
+            _path = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:path allowWildcards:YES] options:0 error:nil];
+        }
+    }
+    return self;
+}
+
+- (bool)matches:(NSURL*)url
+{
+    return (_scheme == nil || [_scheme numberOfMatchesInString:[url scheme] options:NSMatchingAnchored range:NSMakeRange(0, [[url scheme] length])]) &&
+           (_host == nil || ([url host] != nil && [_host numberOfMatchesInString:[url host] options:NSMatchingAnchored range:NSMakeRange(0, [[url host] length])])) &&
+           (_port == nil || [[url port] isEqualToNumber:_port]) &&
+           (_path == nil || [_path numberOfMatchesInString:[url path] options:NSMatchingAnchored range:NSMakeRange(0, [[url path] length])])
+    ;
+}
+
+@end
+
+@interface CDVWhitelist ()
+
+@property (nonatomic, readwrite, strong) NSMutableArray* whitelist;
+@property (nonatomic, readwrite, strong) NSMutableSet* permittedSchemes;
+
+- (void)addWhiteListEntry:(NSString*)pattern;
+
+@end
+
+@implementation CDVWhitelist
+
+@synthesize whitelist, permittedSchemes, whitelistRejectionFormatString;
+
+- (id)initWithArray:(NSArray*)array
+{
+    self = [super init];
+    if (self) {
+        self.whitelist = [[NSMutableArray alloc] init];
+        self.permittedSchemes = [[NSMutableSet alloc] init];
+        self.whitelistRejectionFormatString = kCDVDefaultWhitelistRejectionString;
+
+        for (NSString* pattern in array) {
+            [self addWhiteListEntry:pattern];
+        }
+    }
+    return self;
+}
+
+- (BOOL)isIPv4Address:(NSString*)externalHost
+{
+    // an IPv4 address has 4 octets b.b.b.b where b is a number between 0 and 255.
+    // for our purposes, b can also be the wildcard character '*'
+
+    // we could use a regex to solve this problem but then I would have two problems
+    // anyways, this is much clearer and maintainable
+    NSArray* octets = [externalHost componentsSeparatedByString:@"."];
+    NSUInteger num_octets = [octets count];
+
+    // quick check
+    if (num_octets != 4) {
+        return NO;
+    }
+
+    // restrict number parsing to 0-255
+    NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
+    [numberFormatter setMinimum:[NSNumber numberWithUnsignedInteger:0]];
+    [numberFormatter setMaximum:[NSNumber numberWithUnsignedInteger:255]];
+
+    // iterate through each octet, and test for a number between 0-255 or if it equals '*'
+    for (NSUInteger i = 0; i < num_octets; ++i) {
+        NSString* octet = [octets objectAtIndex:i];
+
+        if ([octet isEqualToString:@"*"]) { // passes - check next octet
+            continue;
+        } else if ([numberFormatter numberFromString:octet] == nil) { // fails - not a number and not within our range, return
+            return NO;
+        }
+    }
+
+    return YES;
+}
+
+- (void)addWhiteListEntry:(NSString*)origin
+{
+    if (self.whitelist == nil) {
+        return;
+    }
+
+    if ([origin isEqualToString:@"*"]) {
+        NSLog(@"Unlimited access to network resources");
+        self.whitelist = nil;
+        self.permittedSchemes = nil;
+    } else { // specific access
+        NSRegularExpression* parts = [NSRegularExpression regularExpressionWithPattern:@"^((\\*|[A-Za-z-]+):/?/?)?(((\\*\\.)?[^*/:]+)|\\*)?(:(\\d+))?(/.*)?" options:0 error:nil];
+        NSTextCheckingResult* m = [parts firstMatchInString:origin options:NSMatchingAnchored range:NSMakeRange(0, [origin length])];
+        if (m != nil) {
+            NSRange r;
+            NSString* scheme = nil;
+            r = [m rangeAtIndex:2];
+            if (r.location != NSNotFound) {
+                scheme = [origin substringWithRange:r];
+            }
+
+            NSString* host = nil;
+            r = [m rangeAtIndex:3];
+            if (r.location != NSNotFound) {
+                host = [origin substringWithRange:r];
+            }
+
+            // Special case for two urls which are allowed to have empty hosts
+            if (([scheme isEqualToString:@"file"] || [scheme isEqualToString:@"content"]) && (host == nil)) {
+                host = @"*";
+            }
+
+            NSString* port = nil;
+            r = [m rangeAtIndex:7];
+            if (r.location != NSNotFound) {
+                port = [origin substringWithRange:r];
+            }
+
+            NSString* path = nil;
+            r = [m rangeAtIndex:8];
+            if (r.location != NSNotFound) {
+                path = [origin substringWithRange:r];
+            }
+
+            if (scheme == nil) {
+                // XXX making it stupid friendly for people who forget to include protocol/SSL
+                [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"http" host:host port:port path:path]];
+                [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"https" host:host port:port path:path]];
+            } else {
+                [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:scheme host:host port:port path:path]];
+            }
+
+            if (self.permittedSchemes != nil) {
+                if ([scheme isEqualToString:@"*"]) {
+                    self.permittedSchemes = nil;
+                } else if (scheme != nil) {
+                    [self.permittedSchemes addObject:scheme];
+                }
+            }
+        }
+    }
+}
+
+- (BOOL)schemeIsAllowed:(NSString*)scheme
+{
+    if ([scheme isEqualToString:@"http"] ||
+        [scheme isEqualToString:@"https"] ||
+        [scheme isEqualToString:@"ftp"] ||
+        [scheme isEqualToString:@"ftps"]) {
+        return YES;
+    }
+
+    return (self.permittedSchemes == nil) || [self.permittedSchemes containsObject:scheme];
+}
+
+- (BOOL)URLIsAllowed:(NSURL*)url
+{
+    return [self URLIsAllowed:url logFailure:YES];
+}
+
+- (BOOL)URLIsAllowed:(NSURL*)url logFailure:(BOOL)logFailure
+{
+    // Shortcut acceptance: Are all urls whitelisted ("*" in whitelist)?
+    if (whitelist == nil) {
+        return YES;
+    }
+
+    // Shortcut rejection: Check that the scheme is supported
+    NSString* scheme = [[url scheme] lowercaseString];
+    if (![self schemeIsAllowed:scheme]) {
+        if (logFailure) {
+            NSLog(@"%@", [self errorStringForURL:url]);
+        }
+        return NO;
+    }
+
+    // http[s] and ftp[s] should also validate against the common set in the kCDVDefaultSchemeName list
+    if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"ftp"] || [scheme isEqualToString:@"ftps"]) {
+        NSURL* newUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@%@", kCDVDefaultSchemeName, [url host], [[url path] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLPathAllowedCharacterSet]]];
+        // If it is allowed, we are done.  If not, continue to check for the actual scheme-specific list
+        if ([self URLIsAllowed:newUrl logFailure:NO]) {
+            return YES;
+        }
+    }
+
+    // Check the url against patterns in the whitelist
+    for (CDVWhitelistPattern* p in self.whitelist) {
+        if ([p matches:url]) {
+            return YES;
+        }
+    }
+
+    if (logFailure) {
+        NSLog(@"%@", [self errorStringForURL:url]);
+    }
+    // if we got here, the url host is not in the white-list, do nothing
+    return NO;
+}
+
+- (NSString*)errorStringForURL:(NSURL*)url
+{
+    return [NSString stringWithFormat:self.whitelistRejectionFormatString, [url absoluteString]];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.h b/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.h
new file mode 100644
index 0000000..9be2be2
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.h
@@ -0,0 +1,35 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface NSDictionary (CordovaPreferences)
+
+- (id)cordovaSettingForKey:(NSString*)key;
+- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue;
+- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue;
+
+@end
+
+@interface NSMutableDictionary (CordovaPreferences)
+
+- (void)setCordovaSetting:(id)value forKey:(NSString*)key;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m b/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m
new file mode 100644
index 0000000..dcac40f
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m
@@ -0,0 +1,63 @@
+/*
+ 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.
+ */
+
+#import "NSDictionary+CordovaPreferences.h"
+#import <Foundation/Foundation.h>
+
+@implementation NSDictionary (CordovaPreferences)
+
+- (id)cordovaSettingForKey:(NSString*)key
+{
+    return [self objectForKey:[key lowercaseString]];
+}
+
+- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue
+{
+    BOOL value = defaultValue;
+    id prefObj = [self cordovaSettingForKey:key];
+
+    if (prefObj != nil) {
+        value = [(NSNumber*)prefObj boolValue];
+    }
+
+    return value;
+}
+
+- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue
+{
+    CGFloat value = defaultValue;
+    id prefObj = [self cordovaSettingForKey:key];
+
+    if (prefObj != nil) {
+        value = [prefObj floatValue];
+    }
+
+    return value;
+}
+
+@end
+
+@implementation NSMutableDictionary (CordovaPreferences)
+
+- (void)setCordovaSetting:(id)value forKey:(NSString*)key
+{
+    [self setObject:value forKey:[key lowercaseString]];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.h b/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.h
new file mode 100644
index 0000000..79e6516
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.h
@@ -0,0 +1,29 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableArray (QueueAdditions)
+
+- (id)cdv_pop;
+- (id)cdv_queueHead;
+- (id)cdv_dequeue;
+- (void)cdv_enqueue:(id)obj;
+
+@end
diff --git a/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.m b/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.m
new file mode 100644
index 0000000..2b3acdc
--- /dev/null
+++ b/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.m
@@ -0,0 +1,58 @@
+/*
+ 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.
+ */
+
+#import "NSMutableArray+QueueAdditions.h"
+
+@implementation NSMutableArray (QueueAdditions)
+
+- (id)cdv_queueHead
+{
+    if ([self count] == 0) {
+        return nil;
+    }
+
+    return [self objectAtIndex:0];
+}
+
+- (__autoreleasing id)cdv_dequeue
+{
+    if ([self count] == 0) {
+        return nil;
+    }
+
+    id head = [self objectAtIndex:0];
+    if (head != nil) {
+        // [[head retain] autorelease]; ARC - the __autoreleasing on the return value should so the same thing
+        [self removeObjectAtIndex:0];
+    }
+
+    return head;
+}
+
+- (id)cdv_pop
+{
+    return [self cdv_dequeue];
+}
+
+- (void)cdv_enqueue:(id)object
+{
+    [self addObject:object];
+}
+
+@end
diff --git a/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..682c4c5
--- /dev/null
+++ b/platforms/ios/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -0,0 +1,786 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 48;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		28BFF9141F355A4E00DDF01A /* CDVLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 28BFF9121F355A4E00DDF01A /* CDVLogger.h */; };
+		28BFF9151F355A4E00DDF01A /* CDVLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BFF9131F355A4E00DDF01A /* CDVLogger.m */; };
+		30193A501AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 30193A4E1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m */; };
+		30193A511AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30193A4F1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h */; };
+		3093E2231B16D6A3003F381A /* CDVIntentAndNavigationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3093E2211B16D6A3003F381A /* CDVIntentAndNavigationFilter.h */; };
+		3093E2241B16D6A3003F381A /* CDVIntentAndNavigationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3093E2221B16D6A3003F381A /* CDVIntentAndNavigationFilter.m */; };
+		7E7F69B61ABA35D8007546F4 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CFB1AB9028C008C4574 /* CDVLocalStorage.h */; };
+		7E7F69B81ABA368F007546F4 /* CDVUIWebViewEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D001AB9028C008C4574 /* CDVUIWebViewEngine.h */; };
+		7E7F69B91ABA3692007546F4 /* CDVHandleOpenURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF81AB9028C008C4574 /* CDVHandleOpenURL.h */; };
+		7ED95D021AB9028C008C4574 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF21AB9028C008C4574 /* CDVDebug.h */; };
+		7ED95D031AB9028C008C4574 /* CDVJSON_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF31AB9028C008C4574 /* CDVJSON_private.h */; };
+		7ED95D041AB9028C008C4574 /* CDVJSON_private.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CF41AB9028C008C4574 /* CDVJSON_private.m */; };
+		7ED95D051AB9028C008C4574 /* CDVPlugin+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF51AB9028C008C4574 /* CDVPlugin+Private.h */; };
+		7ED95D071AB9028C008C4574 /* CDVHandleOpenURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CF91AB9028C008C4574 /* CDVHandleOpenURL.m */; };
+		7ED95D091AB9028C008C4574 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CFC1AB9028C008C4574 /* CDVLocalStorage.m */; };
+		7ED95D0A1AB9028C008C4574 /* CDVUIWebViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CFE1AB9028C008C4574 /* CDVUIWebViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D0B1AB9028C008C4574 /* CDVUIWebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CFF1AB9028C008C4574 /* CDVUIWebViewDelegate.m */; };
+		7ED95D0D1AB9028C008C4574 /* CDVUIWebViewEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D011AB9028C008C4574 /* CDVUIWebViewEngine.m */; };
+		7ED95D351AB9029B008C4574 /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D0F1AB9029B008C4574 /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D361AB9029B008C4574 /* CDVAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D101AB9029B008C4574 /* CDVAppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D371AB9029B008C4574 /* CDVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D111AB9029B008C4574 /* CDVAppDelegate.m */; };
+		7ED95D381AB9029B008C4574 /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D121AB9029B008C4574 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D391AB9029B008C4574 /* CDVAvailabilityDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D131AB9029B008C4574 /* CDVAvailabilityDeprecated.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D3A1AB9029B008C4574 /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D141AB9029B008C4574 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D3B1AB9029B008C4574 /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D151AB9029B008C4574 /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D3C1AB9029B008C4574 /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D161AB9029B008C4574 /* CDVCommandDelegateImpl.m */; };
+		7ED95D3D1AB9029B008C4574 /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D171AB9029B008C4574 /* CDVCommandQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D3E1AB9029B008C4574 /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D181AB9029B008C4574 /* CDVCommandQueue.m */; };
+		7ED95D3F1AB9029B008C4574 /* CDVConfigParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D191AB9029B008C4574 /* CDVConfigParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D401AB9029B008C4574 /* CDVConfigParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1A1AB9029B008C4574 /* CDVConfigParser.m */; };
+		7ED95D411AB9029B008C4574 /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1B1AB9029B008C4574 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D421AB9029B008C4574 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1C1AB9029B008C4574 /* CDVInvokedUrlCommand.m */; };
+		7ED95D431AB9029B008C4574 /* CDVPlugin+Resources.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1D1AB9029B008C4574 /* CDVPlugin+Resources.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D441AB9029B008C4574 /* CDVPlugin+Resources.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1E1AB9029B008C4574 /* CDVPlugin+Resources.m */; };
+		7ED95D451AB9029B008C4574 /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1F1AB9029B008C4574 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D461AB9029B008C4574 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D201AB9029B008C4574 /* CDVPlugin.m */; };
+		7ED95D471AB9029B008C4574 /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D211AB9029B008C4574 /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D481AB9029B008C4574 /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D221AB9029B008C4574 /* CDVPluginResult.m */; };
+		7ED95D491AB9029B008C4574 /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D231AB9029B008C4574 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D4A1AB9029B008C4574 /* CDVTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D241AB9029B008C4574 /* CDVTimer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D4B1AB9029B008C4574 /* CDVTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D251AB9029B008C4574 /* CDVTimer.m */; };
+		7ED95D4C1AB9029B008C4574 /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D261AB9029B008C4574 /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D4D1AB9029B008C4574 /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D271AB9029B008C4574 /* CDVURLProtocol.m */; };
+		7ED95D4E1AB9029B008C4574 /* CDVUserAgentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D281AB9029B008C4574 /* CDVUserAgentUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D4F1AB9029B008C4574 /* CDVUserAgentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D291AB9029B008C4574 /* CDVUserAgentUtil.m */; };
+		7ED95D501AB9029B008C4574 /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2A1AB9029B008C4574 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D511AB9029B008C4574 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D2B1AB9029B008C4574 /* CDVViewController.m */; };
+		7ED95D521AB9029B008C4574 /* CDVWebViewEngineProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2C1AB9029B008C4574 /* CDVWebViewEngineProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D531AB9029B008C4574 /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2D1AB9029B008C4574 /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D541AB9029B008C4574 /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D2E1AB9029B008C4574 /* CDVWhitelist.m */; };
+		7ED95D571AB9029B008C4574 /* NSDictionary+CordovaPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D311AB9029B008C4574 /* NSDictionary+CordovaPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D581AB9029B008C4574 /* NSDictionary+CordovaPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D321AB9029B008C4574 /* NSDictionary+CordovaPreferences.m */; };
+		7ED95D591AB9029B008C4574 /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D331AB9029B008C4574 /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7ED95D5A1AB9029B008C4574 /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D341AB9029B008C4574 /* NSMutableArray+QueueAdditions.m */; };
+		9052DE712150D040008E83D4 /* CDVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D111AB9029B008C4574 /* CDVAppDelegate.m */; };
+		9052DE722150D040008E83D4 /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D161AB9029B008C4574 /* CDVCommandDelegateImpl.m */; };
+		9052DE732150D040008E83D4 /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D181AB9029B008C4574 /* CDVCommandQueue.m */; };
+		9052DE742150D040008E83D4 /* CDVConfigParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1A1AB9029B008C4574 /* CDVConfigParser.m */; };
+		9052DE752150D040008E83D4 /* CDVInvokedUrlCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1C1AB9029B008C4574 /* CDVInvokedUrlCommand.m */; };
+		9052DE762150D040008E83D4 /* CDVPlugin+Resources.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D1E1AB9029B008C4574 /* CDVPlugin+Resources.m */; };
+		9052DE772150D040008E83D4 /* CDVPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D201AB9029B008C4574 /* CDVPlugin.m */; };
+		9052DE782150D040008E83D4 /* CDVPluginResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D221AB9029B008C4574 /* CDVPluginResult.m */; };
+		9052DE792150D040008E83D4 /* CDVTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D251AB9029B008C4574 /* CDVTimer.m */; };
+		9052DE7A2150D040008E83D4 /* CDVURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D271AB9029B008C4574 /* CDVURLProtocol.m */; };
+		9052DE7B2150D040008E83D4 /* CDVUserAgentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D291AB9029B008C4574 /* CDVUserAgentUtil.m */; };
+		9052DE7C2150D040008E83D4 /* CDVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D2B1AB9029B008C4574 /* CDVViewController.m */; };
+		9052DE7D2150D040008E83D4 /* CDVWhitelist.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D2E1AB9029B008C4574 /* CDVWhitelist.m */; };
+		9052DE7E2150D040008E83D4 /* NSDictionary+CordovaPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D321AB9029B008C4574 /* NSDictionary+CordovaPreferences.m */; };
+		9052DE7F2150D040008E83D4 /* NSMutableArray+QueueAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D341AB9029B008C4574 /* NSMutableArray+QueueAdditions.m */; };
+		9052DE802150D040008E83D4 /* CDVJSON_private.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CF41AB9028C008C4574 /* CDVJSON_private.m */; };
+		9052DE812150D040008E83D4 /* CDVLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BFF9131F355A4E00DDF01A /* CDVLogger.m */; };
+		9052DE822150D040008E83D4 /* CDVGestureHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */; };
+		9052DE832150D040008E83D4 /* CDVIntentAndNavigationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3093E2221B16D6A3003F381A /* CDVIntentAndNavigationFilter.m */; };
+		9052DE842150D040008E83D4 /* CDVHandleOpenURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CF91AB9028C008C4574 /* CDVHandleOpenURL.m */; };
+		9052DE852150D040008E83D4 /* CDVLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CFC1AB9028C008C4574 /* CDVLocalStorage.m */; };
+		9052DE862150D040008E83D4 /* CDVUIWebViewNavigationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 30193A4E1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m */; };
+		9052DE872150D040008E83D4 /* CDVUIWebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95CFF1AB9028C008C4574 /* CDVUIWebViewDelegate.m */; };
+		9052DE882150D040008E83D4 /* CDVUIWebViewEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ED95D011AB9028C008C4574 /* CDVUIWebViewEngine.m */; };
+		9052DE892150D06B008E83D4 /* CDVDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF21AB9028C008C4574 /* CDVDebug.h */; };
+		9052DE8A2150D06B008E83D4 /* CDVJSON_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF31AB9028C008C4574 /* CDVJSON_private.h */; };
+		9052DE8B2150D06B008E83D4 /* CDVPlugin+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF51AB9028C008C4574 /* CDVPlugin+Private.h */; };
+		9052DE8C2150D06B008E83D4 /* CDVLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 28BFF9121F355A4E00DDF01A /* CDVLogger.h */; };
+		9052DE8D2150D06B008E83D4 /* CDVGestureHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */; };
+		9052DE8E2150D06B008E83D4 /* CDVIntentAndNavigationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3093E2211B16D6A3003F381A /* CDVIntentAndNavigationFilter.h */; };
+		9052DE8F2150D06B008E83D4 /* CDVHandleOpenURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CF81AB9028C008C4574 /* CDVHandleOpenURL.h */; };
+		9052DE902150D06B008E83D4 /* CDVLocalStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CFB1AB9028C008C4574 /* CDVLocalStorage.h */; };
+		9052DE912150D06B008E83D4 /* CDVUIWebViewNavigationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 30193A4F1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h */; };
+		9052DE922150D06B008E83D4 /* CDVUIWebViewEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D001AB9028C008C4574 /* CDVUIWebViewEngine.h */; };
+		A3B082D41BB15CEA00D8DC35 /* CDVGestureHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */; };
+		A3B082D51BB15CEA00D8DC35 /* CDVGestureHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */; };
+		C0C01EB61E3911D50056E6CB /* Cordova.h in Headers */ = {isa = PBXBuildFile; fileRef = C0C01EB41E3911D50056E6CB /* Cordova.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EBB1E39131A0056E6CB /* CDV.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D0F1AB9029B008C4574 /* CDV.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EBC1E39131A0056E6CB /* CDVAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D101AB9029B008C4574 /* CDVAppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EBD1E39131A0056E6CB /* CDVAvailability.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D121AB9029B008C4574 /* CDVAvailability.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EBE1E39131A0056E6CB /* CDVAvailabilityDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D131AB9029B008C4574 /* CDVAvailabilityDeprecated.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EBF1E39131A0056E6CB /* CDVCommandDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D141AB9029B008C4574 /* CDVCommandDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC01E39131A0056E6CB /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D151AB9029B008C4574 /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC11E39131A0056E6CB /* CDVCommandQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D171AB9029B008C4574 /* CDVCommandQueue.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC21E39131A0056E6CB /* CDVConfigParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D191AB9029B008C4574 /* CDVConfigParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC31E39131A0056E6CB /* CDVInvokedUrlCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1B1AB9029B008C4574 /* CDVInvokedUrlCommand.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC41E39131A0056E6CB /* CDVPlugin+Resources.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1D1AB9029B008C4574 /* CDVPlugin+Resources.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC51E39131A0056E6CB /* CDVPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D1F1AB9029B008C4574 /* CDVPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC61E39131A0056E6CB /* CDVPluginResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D211AB9029B008C4574 /* CDVPluginResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC71E39131A0056E6CB /* CDVScreenOrientationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D231AB9029B008C4574 /* CDVScreenOrientationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC81E39131A0056E6CB /* CDVTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D241AB9029B008C4574 /* CDVTimer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01EC91E39131A0056E6CB /* CDVURLProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D261AB9029B008C4574 /* CDVURLProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECA1E39131A0056E6CB /* CDVUserAgentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D281AB9029B008C4574 /* CDVUserAgentUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECB1E39131A0056E6CB /* CDVViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2A1AB9029B008C4574 /* CDVViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECC1E39131A0056E6CB /* CDVWebViewEngineProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2C1AB9029B008C4574 /* CDVWebViewEngineProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECD1E39131A0056E6CB /* CDVWhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D2D1AB9029B008C4574 /* CDVWhitelist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECE1E39131A0056E6CB /* NSDictionary+CordovaPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D311AB9029B008C4574 /* NSDictionary+CordovaPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ECF1E39131A0056E6CB /* NSMutableArray+QueueAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95D331AB9029B008C4574 /* NSMutableArray+QueueAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C0C01ED01E3913610056E6CB /* CDVUIWebViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED95CFE1AB9028C008C4574 /* CDVUIWebViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		28BFF9121F355A4E00DDF01A /* CDVLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVLogger.h; sourceTree = "<group>"; };
+		28BFF9131F355A4E00DDF01A /* CDVLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVLogger.m; sourceTree = "<group>"; };
+		30193A4E1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVUIWebViewNavigationDelegate.m; sourceTree = "<group>"; };
+		30193A4F1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVUIWebViewNavigationDelegate.h; sourceTree = "<group>"; };
+		3093E2211B16D6A3003F381A /* CDVIntentAndNavigationFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVIntentAndNavigationFilter.h; sourceTree = "<group>"; };
+		3093E2221B16D6A3003F381A /* CDVIntentAndNavigationFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVIntentAndNavigationFilter.m; sourceTree = "<group>"; };
+		68A32D7114102E1C006B237C /* libCordova.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCordova.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		7ED95CF21AB9028C008C4574 /* CDVDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVDebug.h; sourceTree = "<group>"; };
+		7ED95CF31AB9028C008C4574 /* CDVJSON_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVJSON_private.h; sourceTree = "<group>"; };
+		7ED95CF41AB9028C008C4574 /* CDVJSON_private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVJSON_private.m; sourceTree = "<group>"; };
+		7ED95CF51AB9028C008C4574 /* CDVPlugin+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CDVPlugin+Private.h"; sourceTree = "<group>"; };
+		7ED95CF81AB9028C008C4574 /* CDVHandleOpenURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVHandleOpenURL.h; sourceTree = "<group>"; };
+		7ED95CF91AB9028C008C4574 /* CDVHandleOpenURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVHandleOpenURL.m; sourceTree = "<group>"; };
+		7ED95CFB1AB9028C008C4574 /* CDVLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVLocalStorage.h; sourceTree = "<group>"; };
+		7ED95CFC1AB9028C008C4574 /* CDVLocalStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVLocalStorage.m; sourceTree = "<group>"; };
+		7ED95CFE1AB9028C008C4574 /* CDVUIWebViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVUIWebViewDelegate.h; sourceTree = "<group>"; };
+		7ED95CFF1AB9028C008C4574 /* CDVUIWebViewDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVUIWebViewDelegate.m; sourceTree = "<group>"; };
+		7ED95D001AB9028C008C4574 /* CDVUIWebViewEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVUIWebViewEngine.h; sourceTree = "<group>"; };
+		7ED95D011AB9028C008C4574 /* CDVUIWebViewEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVUIWebViewEngine.m; sourceTree = "<group>"; };
+		7ED95D0F1AB9029B008C4574 /* CDV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDV.h; sourceTree = "<group>"; };
+		7ED95D101AB9029B008C4574 /* CDVAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVAppDelegate.h; sourceTree = "<group>"; };
+		7ED95D111AB9029B008C4574 /* CDVAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVAppDelegate.m; sourceTree = "<group>"; };
+		7ED95D121AB9029B008C4574 /* CDVAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVAvailability.h; sourceTree = "<group>"; };
+		7ED95D131AB9029B008C4574 /* CDVAvailabilityDeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVAvailabilityDeprecated.h; sourceTree = "<group>"; };
+		7ED95D141AB9029B008C4574 /* CDVCommandDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCommandDelegate.h; sourceTree = "<group>"; };
+		7ED95D151AB9029B008C4574 /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCommandDelegateImpl.h; sourceTree = "<group>"; };
+		7ED95D161AB9029B008C4574 /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCommandDelegateImpl.m; sourceTree = "<group>"; };
+		7ED95D171AB9029B008C4574 /* CDVCommandQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCommandQueue.h; sourceTree = "<group>"; };
+		7ED95D181AB9029B008C4574 /* CDVCommandQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCommandQueue.m; sourceTree = "<group>"; };
+		7ED95D191AB9029B008C4574 /* CDVConfigParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVConfigParser.h; sourceTree = "<group>"; };
+		7ED95D1A1AB9029B008C4574 /* CDVConfigParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVConfigParser.m; sourceTree = "<group>"; };
+		7ED95D1B1AB9029B008C4574 /* CDVInvokedUrlCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVInvokedUrlCommand.h; sourceTree = "<group>"; };
+		7ED95D1C1AB9029B008C4574 /* CDVInvokedUrlCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVInvokedUrlCommand.m; sourceTree = "<group>"; };
+		7ED95D1D1AB9029B008C4574 /* CDVPlugin+Resources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CDVPlugin+Resources.h"; sourceTree = "<group>"; };
+		7ED95D1E1AB9029B008C4574 /* CDVPlugin+Resources.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CDVPlugin+Resources.m"; sourceTree = "<group>"; };
+		7ED95D1F1AB9029B008C4574 /* CDVPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVPlugin.h; sourceTree = "<group>"; };
+		7ED95D201AB9029B008C4574 /* CDVPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVPlugin.m; sourceTree = "<group>"; };
+		7ED95D211AB9029B008C4574 /* CDVPluginResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVPluginResult.h; sourceTree = "<group>"; };
+		7ED95D221AB9029B008C4574 /* CDVPluginResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVPluginResult.m; sourceTree = "<group>"; };
+		7ED95D231AB9029B008C4574 /* CDVScreenOrientationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVScreenOrientationDelegate.h; sourceTree = "<group>"; };
+		7ED95D241AB9029B008C4574 /* CDVTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVTimer.h; sourceTree = "<group>"; };
+		7ED95D251AB9029B008C4574 /* CDVTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVTimer.m; sourceTree = "<group>"; };
+		7ED95D261AB9029B008C4574 /* CDVURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVURLProtocol.h; sourceTree = "<group>"; };
+		7ED95D271AB9029B008C4574 /* CDVURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVURLProtocol.m; sourceTree = "<group>"; };
+		7ED95D281AB9029B008C4574 /* CDVUserAgentUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVUserAgentUtil.h; sourceTree = "<group>"; };
+		7ED95D291AB9029B008C4574 /* CDVUserAgentUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVUserAgentUtil.m; sourceTree = "<group>"; };
+		7ED95D2A1AB9029B008C4574 /* CDVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVViewController.h; sourceTree = "<group>"; };
+		7ED95D2B1AB9029B008C4574 /* CDVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVViewController.m; sourceTree = "<group>"; };
+		7ED95D2C1AB9029B008C4574 /* CDVWebViewEngineProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVWebViewEngineProtocol.h; sourceTree = "<group>"; };
+		7ED95D2D1AB9029B008C4574 /* CDVWhitelist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVWhitelist.h; sourceTree = "<group>"; };
+		7ED95D2E1AB9029B008C4574 /* CDVWhitelist.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVWhitelist.m; sourceTree = "<group>"; };
+		7ED95D311AB9029B008C4574 /* NSDictionary+CordovaPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+CordovaPreferences.h"; sourceTree = "<group>"; };
+		7ED95D321AB9029B008C4574 /* NSDictionary+CordovaPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+CordovaPreferences.m"; sourceTree = "<group>"; };
+		7ED95D331AB9029B008C4574 /* NSMutableArray+QueueAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+QueueAdditions.h"; sourceTree = "<group>"; };
+		7ED95D341AB9029B008C4574 /* NSMutableArray+QueueAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+QueueAdditions.m"; sourceTree = "<group>"; };
+		A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVGestureHandler.h; sourceTree = "<group>"; };
+		A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVGestureHandler.m; sourceTree = "<group>"; };
+		AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CordovaLib_Prefix.pch; sourceTree = SOURCE_ROOT; };
+		C0C01EB21E3911D50056E6CB /* Cordova.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Cordova.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		C0C01EB41E3911D50056E6CB /* Cordova.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Cordova.h; sourceTree = "<group>"; };
+		C0C01EB51E3911D50056E6CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		C0C01EAE1E3911D50056E6CB /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D2AAC07C0554694100DB518D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DFFF38A50411DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				68A32D7114102E1C006B237C /* libCordova.a */,
+				C0C01EB21E3911D50056E6CB /* Cordova.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 = {
+			isa = PBXGroup;
+			children = (
+				7ED95D0E1AB9029B008C4574 /* Public */,
+				7ED95CF11AB9028C008C4574 /* Private */,
+				C0C01EB31E3911D50056E6CB /* Cordova */,
+				034768DFFF38A50411DB9C8B /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		28BFF9111F355A1D00DDF01A /* CDVLogger */ = {
+			isa = PBXGroup;
+			children = (
+				28BFF9121F355A4E00DDF01A /* CDVLogger.h */,
+				28BFF9131F355A4E00DDF01A /* CDVLogger.m */,
+			);
+			path = CDVLogger;
+			sourceTree = "<group>";
+		};
+		3093E2201B16D6A3003F381A /* CDVIntentAndNavigationFilter */ = {
+			isa = PBXGroup;
+			children = (
+				3093E2211B16D6A3003F381A /* CDVIntentAndNavigationFilter.h */,
+				3093E2221B16D6A3003F381A /* CDVIntentAndNavigationFilter.m */,
+			);
+			path = CDVIntentAndNavigationFilter;
+			sourceTree = "<group>";
+		};
+		7ED95CF11AB9028C008C4574 /* Private */ = {
+			isa = PBXGroup;
+			children = (
+				AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */,
+				7ED95CF21AB9028C008C4574 /* CDVDebug.h */,
+				7ED95CF31AB9028C008C4574 /* CDVJSON_private.h */,
+				7ED95CF41AB9028C008C4574 /* CDVJSON_private.m */,
+				7ED95CF51AB9028C008C4574 /* CDVPlugin+Private.h */,
+				7ED95CF61AB9028C008C4574 /* Plugins */,
+			);
+			name = Private;
+			path = Classes/Private;
+			sourceTree = "<group>";
+		};
+		7ED95CF61AB9028C008C4574 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				28BFF9111F355A1D00DDF01A /* CDVLogger */,
+				A3B082D11BB15CEA00D8DC35 /* CDVGestureHandler */,
+				3093E2201B16D6A3003F381A /* CDVIntentAndNavigationFilter */,
+				7ED95CF71AB9028C008C4574 /* CDVHandleOpenURL */,
+				7ED95CFA1AB9028C008C4574 /* CDVLocalStorage */,
+				7ED95CFD1AB9028C008C4574 /* CDVUIWebViewEngine */,
+			);
+			path = Plugins;
+			sourceTree = "<group>";
+		};
+		7ED95CF71AB9028C008C4574 /* CDVHandleOpenURL */ = {
+			isa = PBXGroup;
+			children = (
+				7ED95CF81AB9028C008C4574 /* CDVHandleOpenURL.h */,
+				7ED95CF91AB9028C008C4574 /* CDVHandleOpenURL.m */,
+			);
+			path = CDVHandleOpenURL;
+			sourceTree = "<group>";
+		};
+		7ED95CFA1AB9028C008C4574 /* CDVLocalStorage */ = {
+			isa = PBXGroup;
+			children = (
+				7ED95CFB1AB9028C008C4574 /* CDVLocalStorage.h */,
+				7ED95CFC1AB9028C008C4574 /* CDVLocalStorage.m */,
+			);
+			path = CDVLocalStorage;
+			sourceTree = "<group>";
+		};
+		7ED95CFD1AB9028C008C4574 /* CDVUIWebViewEngine */ = {
+			isa = PBXGroup;
+			children = (
+				30193A4F1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h */,
+				30193A4E1AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m */,
+				7ED95CFE1AB9028C008C4574 /* CDVUIWebViewDelegate.h */,
+				7ED95CFF1AB9028C008C4574 /* CDVUIWebViewDelegate.m */,
+				7ED95D001AB9028C008C4574 /* CDVUIWebViewEngine.h */,
+				7ED95D011AB9028C008C4574 /* CDVUIWebViewEngine.m */,
+			);
+			path = CDVUIWebViewEngine;
+			sourceTree = "<group>";
+		};
+		7ED95D0E1AB9029B008C4574 /* Public */ = {
+			isa = PBXGroup;
+			children = (
+				7ED95D0F1AB9029B008C4574 /* CDV.h */,
+				7ED95D101AB9029B008C4574 /* CDVAppDelegate.h */,
+				7ED95D111AB9029B008C4574 /* CDVAppDelegate.m */,
+				7ED95D121AB9029B008C4574 /* CDVAvailability.h */,
+				7ED95D131AB9029B008C4574 /* CDVAvailabilityDeprecated.h */,
+				7ED95D141AB9029B008C4574 /* CDVCommandDelegate.h */,
+				7ED95D151AB9029B008C4574 /* CDVCommandDelegateImpl.h */,
+				7ED95D161AB9029B008C4574 /* CDVCommandDelegateImpl.m */,
+				7ED95D171AB9029B008C4574 /* CDVCommandQueue.h */,
+				7ED95D181AB9029B008C4574 /* CDVCommandQueue.m */,
+				7ED95D191AB9029B008C4574 /* CDVConfigParser.h */,
+				7ED95D1A1AB9029B008C4574 /* CDVConfigParser.m */,
+				7ED95D1B1AB9029B008C4574 /* CDVInvokedUrlCommand.h */,
+				7ED95D1C1AB9029B008C4574 /* CDVInvokedUrlCommand.m */,
+				7ED95D1D1AB9029B008C4574 /* CDVPlugin+Resources.h */,
+				7ED95D1E1AB9029B008C4574 /* CDVPlugin+Resources.m */,
+				7ED95D1F1AB9029B008C4574 /* CDVPlugin.h */,
+				7ED95D201AB9029B008C4574 /* CDVPlugin.m */,
+				7ED95D211AB9029B008C4574 /* CDVPluginResult.h */,
+				7ED95D221AB9029B008C4574 /* CDVPluginResult.m */,
+				7ED95D231AB9029B008C4574 /* CDVScreenOrientationDelegate.h */,
+				7ED95D241AB9029B008C4574 /* CDVTimer.h */,
+				7ED95D251AB9029B008C4574 /* CDVTimer.m */,
+				7ED95D261AB9029B008C4574 /* CDVURLProtocol.h */,
+				7ED95D271AB9029B008C4574 /* CDVURLProtocol.m */,
+				7ED95D281AB9029B008C4574 /* CDVUserAgentUtil.h */,
+				7ED95D291AB9029B008C4574 /* CDVUserAgentUtil.m */,
+				7ED95D2A1AB9029B008C4574 /* CDVViewController.h */,
+				7ED95D2B1AB9029B008C4574 /* CDVViewController.m */,
+				7ED95D2C1AB9029B008C4574 /* CDVWebViewEngineProtocol.h */,
+				7ED95D2D1AB9029B008C4574 /* CDVWhitelist.h */,
+				7ED95D2E1AB9029B008C4574 /* CDVWhitelist.m */,
+				7ED95D311AB9029B008C4574 /* NSDictionary+CordovaPreferences.h */,
+				7ED95D321AB9029B008C4574 /* NSDictionary+CordovaPreferences.m */,
+				7ED95D331AB9029B008C4574 /* NSMutableArray+QueueAdditions.h */,
+				7ED95D341AB9029B008C4574 /* NSMutableArray+QueueAdditions.m */,
+			);
+			name = Public;
+			path = Classes/Public;
+			sourceTree = "<group>";
+		};
+		A3B082D11BB15CEA00D8DC35 /* CDVGestureHandler */ = {
+			isa = PBXGroup;
+			children = (
+				A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */,
+				A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */,
+			);
+			path = CDVGestureHandler;
+			sourceTree = "<group>";
+		};
+		C0C01EB31E3911D50056E6CB /* Cordova */ = {
+			isa = PBXGroup;
+			children = (
+				C0C01EB41E3911D50056E6CB /* Cordova.h */,
+				C0C01EB51E3911D50056E6CB /* Info.plist */,
+			);
+			path = Cordova;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		C0C01EAF1E3911D50056E6CB /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				C0C01EB61E3911D50056E6CB /* Cordova.h in Headers */,
+				C0C01EBB1E39131A0056E6CB /* CDV.h in Headers */,
+				C0C01EBC1E39131A0056E6CB /* CDVAppDelegate.h in Headers */,
+				C0C01EBD1E39131A0056E6CB /* CDVAvailability.h in Headers */,
+				C0C01EBE1E39131A0056E6CB /* CDVAvailabilityDeprecated.h in Headers */,
+				C0C01EBF1E39131A0056E6CB /* CDVCommandDelegate.h in Headers */,
+				C0C01EC01E39131A0056E6CB /* CDVCommandDelegateImpl.h in Headers */,
+				C0C01EC11E39131A0056E6CB /* CDVCommandQueue.h in Headers */,
+				C0C01EC21E39131A0056E6CB /* CDVConfigParser.h in Headers */,
+				C0C01EC31E39131A0056E6CB /* CDVInvokedUrlCommand.h in Headers */,
+				C0C01EC41E39131A0056E6CB /* CDVPlugin+Resources.h in Headers */,
+				C0C01EC51E39131A0056E6CB /* CDVPlugin.h in Headers */,
+				C0C01EC61E39131A0056E6CB /* CDVPluginResult.h in Headers */,
+				C0C01EC71E39131A0056E6CB /* CDVScreenOrientationDelegate.h in Headers */,
+				C0C01EC81E39131A0056E6CB /* CDVTimer.h in Headers */,
+				C0C01EC91E39131A0056E6CB /* CDVURLProtocol.h in Headers */,
+				C0C01ECA1E39131A0056E6CB /* CDVUserAgentUtil.h in Headers */,
+				C0C01ECB1E39131A0056E6CB /* CDVViewController.h in Headers */,
+				C0C01ECC1E39131A0056E6CB /* CDVWebViewEngineProtocol.h in Headers */,
+				C0C01ECD1E39131A0056E6CB /* CDVWhitelist.h in Headers */,
+				C0C01ECE1E39131A0056E6CB /* NSDictionary+CordovaPreferences.h in Headers */,
+				C0C01ECF1E39131A0056E6CB /* NSMutableArray+QueueAdditions.h in Headers */,
+				9052DE892150D06B008E83D4 /* CDVDebug.h in Headers */,
+				9052DE8A2150D06B008E83D4 /* CDVJSON_private.h in Headers */,
+				9052DE8B2150D06B008E83D4 /* CDVPlugin+Private.h in Headers */,
+				9052DE8C2150D06B008E83D4 /* CDVLogger.h in Headers */,
+				9052DE8D2150D06B008E83D4 /* CDVGestureHandler.h in Headers */,
+				9052DE8E2150D06B008E83D4 /* CDVIntentAndNavigationFilter.h in Headers */,
+				9052DE8F2150D06B008E83D4 /* CDVHandleOpenURL.h in Headers */,
+				9052DE902150D06B008E83D4 /* CDVLocalStorage.h in Headers */,
+				9052DE912150D06B008E83D4 /* CDVUIWebViewNavigationDelegate.h in Headers */,
+				C0C01ED01E3913610056E6CB /* CDVUIWebViewDelegate.h in Headers */,
+				9052DE922150D06B008E83D4 /* CDVUIWebViewEngine.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D2AAC07A0554694100DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7ED95D351AB9029B008C4574 /* CDV.h in Headers */,
+				7ED95D361AB9029B008C4574 /* CDVAppDelegate.h in Headers */,
+				7ED95D381AB9029B008C4574 /* CDVAvailability.h in Headers */,
+				7ED95D391AB9029B008C4574 /* CDVAvailabilityDeprecated.h in Headers */,
+				7ED95D3A1AB9029B008C4574 /* CDVCommandDelegate.h in Headers */,
+				7ED95D3B1AB9029B008C4574 /* CDVCommandDelegateImpl.h in Headers */,
+				7ED95D3D1AB9029B008C4574 /* CDVCommandQueue.h in Headers */,
+				7ED95D3F1AB9029B008C4574 /* CDVConfigParser.h in Headers */,
+				7ED95D411AB9029B008C4574 /* CDVInvokedUrlCommand.h in Headers */,
+				7ED95D431AB9029B008C4574 /* CDVPlugin+Resources.h in Headers */,
+				7ED95D451AB9029B008C4574 /* CDVPlugin.h in Headers */,
+				7ED95D471AB9029B008C4574 /* CDVPluginResult.h in Headers */,
+				7ED95D491AB9029B008C4574 /* CDVScreenOrientationDelegate.h in Headers */,
+				7ED95D4A1AB9029B008C4574 /* CDVTimer.h in Headers */,
+				7ED95D4C1AB9029B008C4574 /* CDVURLProtocol.h in Headers */,
+				7ED95D4E1AB9029B008C4574 /* CDVUserAgentUtil.h in Headers */,
+				7ED95D501AB9029B008C4574 /* CDVViewController.h in Headers */,
+				7ED95D521AB9029B008C4574 /* CDVWebViewEngineProtocol.h in Headers */,
+				7ED95D531AB9029B008C4574 /* CDVWhitelist.h in Headers */,
+				7ED95D571AB9029B008C4574 /* NSDictionary+CordovaPreferences.h in Headers */,
+				7ED95D591AB9029B008C4574 /* NSMutableArray+QueueAdditions.h in Headers */,
+				7ED95D021AB9028C008C4574 /* CDVDebug.h in Headers */,
+				7ED95D031AB9028C008C4574 /* CDVJSON_private.h in Headers */,
+				7ED95D051AB9028C008C4574 /* CDVPlugin+Private.h in Headers */,
+				28BFF9141F355A4E00DDF01A /* CDVLogger.h in Headers */,
+				A3B082D41BB15CEA00D8DC35 /* CDVGestureHandler.h in Headers */,
+				3093E2231B16D6A3003F381A /* CDVIntentAndNavigationFilter.h in Headers */,
+				7E7F69B91ABA3692007546F4 /* CDVHandleOpenURL.h in Headers */,
+				7E7F69B61ABA35D8007546F4 /* CDVLocalStorage.h in Headers */,
+				30193A511AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h in Headers */,
+				7ED95D0A1AB9028C008C4574 /* CDVUIWebViewDelegate.h in Headers */,
+				7E7F69B81ABA368F007546F4 /* CDVUIWebViewEngine.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		C0C01EB11E3911D50056E6CB /* Cordova */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C0C01EB91E3911D50056E6CB /* Build configuration list for PBXNativeTarget "Cordova" */;
+			buildPhases = (
+				C0C01EAD1E3911D50056E6CB /* Sources */,
+				C0C01EAE1E3911D50056E6CB /* Frameworks */,
+				C0C01EAF1E3911D50056E6CB /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = Cordova;
+			productName = Cordova;
+			productReference = C0C01EB21E3911D50056E6CB /* Cordova.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+		D2AAC07D0554694100DB518D /* CordovaLib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */;
+			buildPhases = (
+				D2AAC07A0554694100DB518D /* Headers */,
+				D2AAC07B0554694100DB518D /* Sources */,
+				D2AAC07C0554694100DB518D /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = CordovaLib;
+			productName = CordovaLib;
+			productReference = 68A32D7114102E1C006B237C /* libCordova.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1010;
+				TargetAttributes = {
+					C0C01EB11E3911D50056E6CB = {
+						CreatedOnToolsVersion = 10.1;
+						ProvisioningStyle = Automatic;
+					};
+					D2AAC07D0554694100DB518D = {
+						CreatedOnToolsVersion = 10.1;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */;
+			compatibilityVersion = "Xcode 8.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07;
+			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D2AAC07D0554694100DB518D /* CordovaLib */,
+				C0C01EB11E3911D50056E6CB /* Cordova */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		C0C01EAD1E3911D50056E6CB /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9052DE712150D040008E83D4 /* CDVAppDelegate.m in Sources */,
+				9052DE722150D040008E83D4 /* CDVCommandDelegateImpl.m in Sources */,
+				9052DE732150D040008E83D4 /* CDVCommandQueue.m in Sources */,
+				9052DE742150D040008E83D4 /* CDVConfigParser.m in Sources */,
+				9052DE752150D040008E83D4 /* CDVInvokedUrlCommand.m in Sources */,
+				9052DE762150D040008E83D4 /* CDVPlugin+Resources.m in Sources */,
+				9052DE772150D040008E83D4 /* CDVPlugin.m in Sources */,
+				9052DE782150D040008E83D4 /* CDVPluginResult.m in Sources */,
+				9052DE792150D040008E83D4 /* CDVTimer.m in Sources */,
+				9052DE7A2150D040008E83D4 /* CDVURLProtocol.m in Sources */,
+				9052DE7B2150D040008E83D4 /* CDVUserAgentUtil.m in Sources */,
+				9052DE7C2150D040008E83D4 /* CDVViewController.m in Sources */,
+				9052DE7D2150D040008E83D4 /* CDVWhitelist.m in Sources */,
+				9052DE7E2150D040008E83D4 /* NSDictionary+CordovaPreferences.m in Sources */,
+				9052DE7F2150D040008E83D4 /* NSMutableArray+QueueAdditions.m in Sources */,
+				9052DE802150D040008E83D4 /* CDVJSON_private.m in Sources */,
+				9052DE812150D040008E83D4 /* CDVLogger.m in Sources */,
+				9052DE822150D040008E83D4 /* CDVGestureHandler.m in Sources */,
+				9052DE832150D040008E83D4 /* CDVIntentAndNavigationFilter.m in Sources */,
+				9052DE842150D040008E83D4 /* CDVHandleOpenURL.m in Sources */,
+				9052DE852150D040008E83D4 /* CDVLocalStorage.m in Sources */,
+				9052DE862150D040008E83D4 /* CDVUIWebViewNavigationDelegate.m in Sources */,
+				9052DE872150D040008E83D4 /* CDVUIWebViewDelegate.m in Sources */,
+				9052DE882150D040008E83D4 /* CDVUIWebViewEngine.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D2AAC07B0554694100DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7ED95D371AB9029B008C4574 /* CDVAppDelegate.m in Sources */,
+				7ED95D3C1AB9029B008C4574 /* CDVCommandDelegateImpl.m in Sources */,
+				7ED95D3E1AB9029B008C4574 /* CDVCommandQueue.m in Sources */,
+				7ED95D401AB9029B008C4574 /* CDVConfigParser.m in Sources */,
+				7ED95D421AB9029B008C4574 /* CDVInvokedUrlCommand.m in Sources */,
+				7ED95D441AB9029B008C4574 /* CDVPlugin+Resources.m in Sources */,
+				7ED95D461AB9029B008C4574 /* CDVPlugin.m in Sources */,
+				7ED95D481AB9029B008C4574 /* CDVPluginResult.m in Sources */,
+				7ED95D4B1AB9029B008C4574 /* CDVTimer.m in Sources */,
+				7ED95D4D1AB9029B008C4574 /* CDVURLProtocol.m in Sources */,
+				7ED95D4F1AB9029B008C4574 /* CDVUserAgentUtil.m in Sources */,
+				7ED95D511AB9029B008C4574 /* CDVViewController.m in Sources */,
+				7ED95D541AB9029B008C4574 /* CDVWhitelist.m in Sources */,
+				7ED95D581AB9029B008C4574 /* NSDictionary+CordovaPreferences.m in Sources */,
+				7ED95D5A1AB9029B008C4574 /* NSMutableArray+QueueAdditions.m in Sources */,
+				7ED95D041AB9028C008C4574 /* CDVJSON_private.m in Sources */,
+				28BFF9151F355A4E00DDF01A /* CDVLogger.m in Sources */,
+				A3B082D51BB15CEA00D8DC35 /* CDVGestureHandler.m in Sources */,
+				3093E2241B16D6A3003F381A /* CDVIntentAndNavigationFilter.m in Sources */,
+				7ED95D071AB9028C008C4574 /* CDVHandleOpenURL.m in Sources */,
+				7ED95D091AB9028C008C4574 /* CDVLocalStorage.m in Sources */,
+				30193A501AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.m in Sources */,
+				7ED95D0B1AB9028C008C4574 /* CDVUIWebViewDelegate.m in Sources */,
+				7ED95D0D1AB9028C008C4574 /* CDVUIWebViewEngine.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB921F08733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		1DEB922008733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				PUBLIC_HEADERS_FOLDER_PATH = include/Cordova;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+		1DEB922308733DC00010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		1DEB922408733DC00010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = CordovaLib_Prefix.pch;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = Cordova;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		C0C01EB71E3911D50056E6CB /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEFINES_MODULE = YES;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = Cordova/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.Cordova;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+			};
+			name = Debug;
+		};
+		C0C01EB81E3911D50056E6CB /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEFINES_MODULE = YES;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = Cordova/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.Cordova;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB921E08733DC00010E9CD /* Build configuration list for PBXNativeTarget "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB921F08733DC00010E9CD /* Debug */,
+				1DEB922008733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "CordovaLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB922308733DC00010E9CD /* Debug */,
+				1DEB922408733DC00010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C0C01EB91E3911D50056E6CB /* Build configuration list for PBXNativeTarget "Cordova" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C0C01EB71E3911D50056E6CB /* Debug */,
+				C0C01EB81E3911D50056E6CB /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/platforms/ios/CordovaLib/CordovaLib_Prefix.pch b/platforms/ios/CordovaLib/CordovaLib_Prefix.pch
new file mode 100644
index 0000000..9545580
--- /dev/null
+++ b/platforms/ios/CordovaLib/CordovaLib_Prefix.pch
@@ -0,0 +1,22 @@
+/*
+ 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.
+ */
+
+#ifdef __OBJC__
+    #import <Foundation/Foundation.h>
+#endif
diff --git a/platforms/ios/CordovaLib/VERSION b/platforms/ios/CordovaLib/VERSION
new file mode 100644
index 0000000..6b244dc
--- /dev/null
+++ b/platforms/ios/CordovaLib/VERSION
@@ -0,0 +1 @@
+5.0.1
diff --git a/platforms/ios/CordovaLib/cordova.js b/platforms/ios/CordovaLib/cordova.js
new file mode 100644
index 0000000..2e2b33a
--- /dev/null
+++ b/platforms/ios/CordovaLib/cordova.js
@@ -0,0 +1,2162 @@
+// Platform: ios
+// 948e932548412305aa7f24b3a90e386aa5c3d12c
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '5.0.1';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return { 'document': { 'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener },
+            'window': { 'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener } };
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/*global require, module, atob, document */
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    execIframe,
+    commandQueue = [], // Contains pending JS->Native messages.
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
+
+function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+        return args;
+    }
+    var ret = [];
+    args.forEach(function(arg, i) {
+        if (utils.typeName(arg) == 'ArrayBuffer') {
+            ret.push({
+                'CDVType': 'ArrayBuffer',
+                'data': base64.fromArrayBuffer(arg)
+            });
+        } else {
+            ret.push(arg);
+        }
+    });
+    return ret;
+}
+
+function massageMessageNativeToJs(message) {
+    if (message.CDVType == 'ArrayBuffer') {
+        var stringToArrayBuffer = function(str) {
+            var ret = new Uint8Array(str.length);
+            for (var i = 0; i < str.length; i++) {
+                ret[i] = str.charCodeAt(i);
+            }
+            return ret.buffer;
+        };
+        var base64ToArrayBuffer = function(b64) {
+            return stringToArrayBuffer(atob(b64));
+        };
+        message = base64ToArrayBuffer(message.data);
+    }
+    return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+    var args = [];
+    if (!message || !message.hasOwnProperty('CDVType')) {
+        args.push(message);
+    } else if (message.CDVType == 'MultiPart') {
+        message.messages.forEach(function(e) {
+            args.push(massageMessageNativeToJs(e));
+        });
+    } else {
+        args.push(massageMessageNativeToJs(message));
+    }
+    return args;
+}
+
+function iOSExec() {
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== 'string') {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+            'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
+        );
+    }
+
+    // If actionArgs is not provided, default to an empty array
+    actionArgs = actionArgs || [];
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] =
+            {success:successCallback, fail:failCallback};
+    }
+
+    actionArgs = massageArgsJsToNative(actionArgs);
+
+    var command = [callbackId, service, action, actionArgs];
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    commandQueue.push(JSON.stringify(command));
+
+    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+    // then the queue will be flushed when it returns; no need for a poke.
+    // Also, if there is already a command in the queue, then we've already
+    // poked the native side, so there is no reason to do so again.
+    if (!isInContextOfEvalJs && commandQueue.length == 1) {
+        pokeNative();
+    }
+}
+
+// CB-10530
+function proxyChanged() {
+    var cexec = cordovaExec();
+       
+    return (execProxy !== cexec && // proxy objects are different
+            iOSExec !== cexec      // proxy object is not the current iOSExec
+            );
+}
+
+// CB-10106
+function handleBridgeChange() {
+    if (proxyChanged()) {
+        var commandString = commandQueue.shift();
+        while(commandString) {
+            var command = JSON.parse(commandString);
+            var callbackId = command[0];
+            var service = command[1];
+            var action = command[2];
+            var actionArgs = command[3];
+            var callbacks = cordova.callbacks[callbackId] || {};
+            
+            execProxy(callbacks.success, callbacks.fail, service, action, actionArgs);
+            
+            commandString = commandQueue.shift();
+        };
+        return true;
+    }
+    
+    return false;
+}
+
+function pokeNative() {
+    // CB-5488 - Don't attempt to create iframe before document.body is available.
+    if (!document.body) {
+        setTimeout(pokeNative);
+        return;
+    }
+    
+    // Check if they've removed it from the DOM, and put it back if so.
+    if (execIframe && execIframe.contentWindow) {
+        execIframe.contentWindow.location = 'gap://ready';
+    } else {
+        execIframe = document.createElement('iframe');
+        execIframe.style.display = 'none';
+        execIframe.src = 'gap://ready';
+        document.body.appendChild(execIframe);
+    }
+    // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+    // This makes the bridge ~ 7% slower, but works around the poke getting lost
+    // when the iframe is removed from the DOM.
+    // An onunload listener could be used in the case where the iframe has just been
+    // created, but since unload events fire only once, it doesn't work in the normal
+    // case of iframe reuse (where unload will have already fired due to the attempted
+    // navigation of the page).
+    failSafeTimerId = setTimeout(function() {
+        if (commandQueue.length) {
+            // CB-10106 - flush the queue on bridge change
+            if (!handleBridgeChange()) {
+                pokeNative();
+             }
+        }
+    }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+}
+
+iOSExec.nativeFetchMessages = function() {
+    // Stop listing for window detatch once native side confirms poke.
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
+    }
+    // Each entry in commandQueue is a JSON string already.
+    if (!commandQueue.length) {
+        return '';
+    }
+    var json = '[' + commandQueue.join(',') + ']';
+    commandQueue.length = 0;
+    return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+    return iOSExec.nativeEvalAndFetch(function() {
+        var success = status === 0 || status === 1;
+        var args = convertMessageToArgsNativeToJs(message);
+        function nc2() {
+            cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+        }
+        setTimeout(nc2, 0);
+    });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+    // This shouldn't be nested, but better to be safe.
+    isInContextOfEvalJs++;
+    try {
+        func();
+        return iOSExec.nativeFetchMessages();
+    } finally {
+        isInContextOfEvalJs--;
+    }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+    var cexec = require('cordova/exec');
+    var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+    return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+    cordovaExec().apply(null, arguments);
+};
+
+execProxy.nativeFetchMessages = function() {
+    return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+    return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+    return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+    id: 'ios',
+    bootstrap: function () {
+        // Attach the console polyfill that is iOS-only to window.console
+        // see the file under plugin/ios/console.js
+        require('cordova/modulemapper').clobbers('cordova/plugin/ios/console', 'window.console');
+
+        require('cordova/channel').onNativeReady.fire();
+    }
+};
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/console.js
+define("cordova/plugin/ios/console", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+
+var logger = require('cordova/plugin/ios/logger');
+
+//------------------------------------------------------------------------------
+// object that we're exporting
+//------------------------------------------------------------------------------
+var console = module.exports;
+
+//------------------------------------------------------------------------------
+// copy of the original console object
+//------------------------------------------------------------------------------
+var WinConsole = window.console;
+
+//------------------------------------------------------------------------------
+// whether to use the logger
+//------------------------------------------------------------------------------
+var UseLogger = false;
+
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+var Timers = {};
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+function noop() {}
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+console.useLogger = function (value) {
+    if (arguments.length) UseLogger = !!value;
+
+    if (UseLogger) {
+        if (logger.useConsole()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+    }
+
+    return UseLogger;
+};
+
+//------------------------------------------------------------------------------
+console.log = function() {
+    if (logger.useConsole()) return;
+    logger.log.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.error = function() {
+    if (logger.useConsole()) return;
+    logger.error.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.warn = function() {
+    if (logger.useConsole()) return;
+    logger.warn.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.info = function() {
+    if (logger.useConsole()) return;
+    logger.info.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.debug = function() {
+    if (logger.useConsole()) return;
+    logger.debug.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.assert = function(expression) {
+    if (expression) return;
+
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
+    console.log("ASSERT: " + message);
+};
+
+//------------------------------------------------------------------------------
+console.clear = function() {};
+
+//------------------------------------------------------------------------------
+console.dir = function(object) {
+    console.log("%o", object);
+};
+
+//------------------------------------------------------------------------------
+console.dirxml = function(node) {
+    console.log(node.innerHTML);
+};
+
+//------------------------------------------------------------------------------
+console.trace = noop;
+
+//------------------------------------------------------------------------------
+console.group = console.log;
+
+//------------------------------------------------------------------------------
+console.groupCollapsed = console.log;
+
+//------------------------------------------------------------------------------
+console.groupEnd = noop;
+
+//------------------------------------------------------------------------------
+console.time = function(name) {
+    Timers[name] = new Date().valueOf();
+};
+
+//------------------------------------------------------------------------------
+console.timeEnd = function(name) {
+    var timeStart = Timers[name];
+    if (!timeStart) {
+        console.warn("unknown timer: " + name);
+        return;
+    }
+
+    var timeElapsed = new Date().valueOf() - timeStart;
+    console.log(name + ": " + timeElapsed + "ms");
+};
+
+//------------------------------------------------------------------------------
+console.timeStamp = noop;
+
+//------------------------------------------------------------------------------
+console.profile = noop;
+
+//------------------------------------------------------------------------------
+console.profileEnd = noop;
+
+//------------------------------------------------------------------------------
+console.count = noop;
+
+//------------------------------------------------------------------------------
+console.exception = console.log;
+
+//------------------------------------------------------------------------------
+console.table = function(data, columns) {
+    console.log("%o", data);
+};
+
+//------------------------------------------------------------------------------
+// return a new function that calls both functions passed as args
+//------------------------------------------------------------------------------
+function wrappedOrigCall(orgFunc, newFunc) {
+    return function() {
+        var args = [].slice.call(arguments);
+        try { orgFunc.apply(WinConsole, args); } catch (e) {}
+        try { newFunc.apply(console,    args); } catch (e) {}
+    };
+}
+
+//------------------------------------------------------------------------------
+// For every function that exists in the original console object, that
+// also exists in the new console object, wrap the new console method
+// with one that calls both
+//------------------------------------------------------------------------------
+for (var key in console) {
+    if (typeof WinConsole[key] == "function") {
+        console[key] = wrappedOrigCall(WinConsole[key], console[key]);
+    }
+}
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/logger.js
+define("cordova/plugin/ios/logger", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports;
+
+var exec    = require('cordova/exec');
+
+var UseConsole   = false;
+var UseLogger    = true;
+var Queued       = [];
+var DeviceReady  = false;
+var CurrentLevel;
+
+var originalConsole = console;
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+];
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {};
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i];
+    LevelsMap[level] = i;
+    logger[level]    = level;
+}
+
+CurrentLevel = LevelsMap.WARN;
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  E.g., the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] === null) {
+            throw new Error("invalid logging level: " + value);
+        }
+        CurrentLevel = LevelsMap[value];
+    }
+
+    return Levels[CurrentLevel];
+};
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value;
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined");
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function");
+        }
+
+        if (typeof console.useLogger == "function") {
+            if (console.useLogger()) {
+                throw new Error("console and logger are too intertwingly");
+            }
+        }
+    }
+
+    return UseConsole;
+};
+
+/**
+ * Getter/Setter for the useLogger functionality
+ *
+ * When useLogger is true, the logger will log via the
+ * native Logger plugin.
+ */
+logger.useLogger = function (value) {
+    // Enforce boolean
+    if (arguments.length) UseLogger = !!value;
+    return UseLogger;
+};
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments); };
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments); };
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments); };
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    args = [level].concat([].slice.call(args));
+    logger.logLevel.apply(logger, args);
+}
+
+// return the correct formatString for an object
+function formatStringForMessage(message) {
+    return (typeof message === "string") ? "" : "%o"; 
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 1);
+    var fmtString = formatStringForMessage(formatArgs[0]);
+    if (fmtString.length > 0){
+        formatArgs.unshift(fmtString); // add formatString
+    }
+
+    var message    = logger.format.apply(logger.format, formatArgs);
+
+    if (LevelsMap[level] === null) {
+        throw new Error("invalid logging level: " + level);
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return;
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message]);
+        return;
+    }
+
+    // Log using the native logger if that is enabled
+    if (UseLogger) {
+        exec(null, null, "Console", "logLevel", [level, message]);
+    }
+
+    // Log using the console if that is enabled
+    if (UseConsole) {
+        // make sure console is not using logger
+        if (console.useLogger()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+
+        // log to the console
+        switch (level) {
+            case logger.LOG:   originalConsole.log(message); break;
+            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
+            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
+            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
+            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
+        }
+    }
+};
+
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return;
+
+    DeviceReady = true;
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i];
+        logger.logLevel(messageArgs[0], messageArgs[1]);
+    }
+
+    Queued = null;
+};
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false);
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/ios/Podfile b/platforms/ios/Podfile
new file mode 100644
index 0000000..de93ed4
--- /dev/null
+++ b/platforms/ios/Podfile
@@ -0,0 +1,8 @@
+# DO NOT MODIFY -- auto-generated by Apache Cordova
+
+platform :ios, '9.0'
+
+target 'dlapp' do
+	project 'dlapp.xcodeproj'
+
+end
diff --git a/platforms/ios/cordova/Api.js b/platforms/ios/cordova/Api.js
new file mode 100755
index 0000000..73c1dbc
--- /dev/null
+++ b/platforms/ios/cordova/Api.js
@@ -0,0 +1,715 @@
+/**
+    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.
+*/
+
+/* jslint node: true */
+
+var fs = require('fs');
+var path = require('path');
+var unorm = require('unorm');
+var projectFile = require('./lib/projectFile');
+var check_reqs = require('./lib/check_reqs');
+var CordovaError = require('cordova-common').CordovaError;
+var CordovaLogger = require('cordova-common').CordovaLogger;
+var events = require('cordova-common').events;
+var PluginManager = require('cordova-common').PluginManager;
+var Q = require('q');
+var util = require('util');
+var xcode = require('xcode');
+var ConfigParser = require('cordova-common').ConfigParser;
+
+function setupEvents (externalEventEmitter) {
+    if (externalEventEmitter) {
+        // This will make the platform internal events visible outside
+        events.forwardEventsTo(externalEventEmitter);
+    } else {
+        // There is no logger if external emitter is not present,
+        // so attach a console logger
+        CordovaLogger.get().subscribe(events);
+    }
+}
+
+/**
+ * Creates a new PlatformApi instance.
+ *
+ * @param  {String}  [platform] Platform name, used for backward compatibility
+ *   w/ PlatformPoly (CordovaLib).
+ * @param  {String}  [platformRootDir] Platform root location, used for backward
+ *   compatibility w/ PlatformPoly (CordovaLib).
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ *   logging purposes. If no EventEmitter provided, all events will be logged to
+ *   console
+ */
+function Api (platform, platformRootDir, events) {
+    // 'platform' property is required as per PlatformApi spec
+    this.platform = platform || 'ios';
+    this.root = platformRootDir || path.resolve(__dirname, '..');
+
+    setupEvents(events);
+
+    var xcodeProjDir;
+    var xcodeCordovaProj;
+
+    try {
+
+        var xcodeProjDir_array = fs.readdirSync(this.root).filter(function (e) { return e.match(/\.xcodeproj$/i); });
+        if (xcodeProjDir_array.length > 1) {
+            for (var x = 0; x < xcodeProjDir_array.length; x++) {
+                if (xcodeProjDir_array[x].substring(0, 2) === '._') {
+                    xcodeProjDir_array.splice(x, 1);
+                }
+            }
+        }
+        xcodeProjDir = xcodeProjDir_array[0];
+
+        if (!xcodeProjDir) {
+            throw new CordovaError('The provided path "' + this.root + '" is not a Cordova iOS project.');
+        }
+
+        var cordovaProjName = xcodeProjDir.substring(xcodeProjDir.lastIndexOf(path.sep) + 1, xcodeProjDir.indexOf('.xcodeproj'));
+        xcodeCordovaProj = path.join(this.root, cordovaProjName);
+    } catch (e) {
+        throw new CordovaError('The provided path "' + this.root + '" is not a Cordova iOS project.');
+    }
+
+    this.locations = {
+        root: this.root,
+        www: path.join(this.root, 'www'),
+        platformWww: path.join(this.root, 'platform_www'),
+        configXml: path.join(xcodeCordovaProj, 'config.xml'),
+        defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),
+        pbxproj: path.join(this.root, xcodeProjDir, 'project.pbxproj'),
+        xcodeProjDir: path.join(this.root, xcodeProjDir),
+        xcodeCordovaProj: xcodeCordovaProj
+    };
+}
+
+/**
+ * Creates platform in a specified directory.
+ *
+ * @param  {String}  destination Destination directory, where install platform to
+ * @param  {ConfigParser}  [config] ConfgiParser instance, used to retrieve
+ *   project creation options, such as package id and project name.
+ * @param  {Object}  [options]  An options object. The most common options are:
+ * @param  {String}  [options.customTemplate]  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  [options.link]  Flag that indicates that platform's
+ *   sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ *   logging purposes. If no EventEmitter provided, all events will be logged to
+ *   console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+Api.createPlatform = function (destination, config, options, events) {
+    setupEvents(events);
+
+    // CB-6992 it is necessary to normalize characters
+    // because node and shell scripts handles unicode symbols differently
+    // We need to normalize the name to NFD form since iOS uses NFD unicode form
+    var name = unorm.nfd(config.name());
+    var result;
+    try {
+        result = require('../../../lib/create')
+            .createProject(destination, config.getAttribute('ios-CFBundleIdentifier') || config.packageName(), name, options)
+            .then(function () {
+                // after platform is created we return Api instance based on new Api.js location
+                // This is required to correctly resolve paths in the future api calls
+                var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+                return new PlatformApi('ios', destination, events);
+            });
+    } catch (e) {
+        events.emit('error', 'createPlatform is not callable from the iOS project API.');
+        throw (e);
+    }
+    return result;
+};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param  {String}  destination Destination directory, where platform installed
+ * @param  {Object}  [options]  An options object. The most common options are:
+ * @param  {String}  [options.customTemplate]  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  [options.link]  Flag that indicates that platform's
+ *   sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ *   logging purposes. If no EventEmitter provided, all events will be logged to
+ *   console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+Api.updatePlatform = function (destination, options, events) {
+    setupEvents(events);
+
+    var result;
+    try {
+        result = require('../../../lib/create')
+            .updateProject(destination, options)
+            .then(function () {
+                var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+                return new PlatformApi('ios', destination, events);
+            });
+    } catch (e) {
+        events.emit('error', 'updatePlatform is not callable from the iOS project API, you will need to do this manually.');
+        throw (e);
+    }
+    return result;
+};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return  {CordovaPlatform}  A structure that contains the description of
+ *   platform's file structure and other properties of platform.
+ */
+Api.prototype.getPlatformInfo = function () {
+    var result = {};
+    result.locations = this.locations;
+    result.root = this.root;
+    result.name = this.platform;
+    result.version = require('./version');
+    result.projectConfig = new ConfigParser(this.locations.configXml);
+
+    return result;
+};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ *   configuration. This method is required for CLI workflow and will be called
+ *   each time before build, so the changes, made to app configuration and www
+ *   code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to platform
+ *   (contains project's www location and ConfigParser instance for project's
+ *   config).
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.prepare = function (cordovaProject) {
+    cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path);
+
+    return require('./lib/prepare').prepare.call(this, cordovaProject);
+};
+
+/**
+ * Installs a new plugin into platform. It doesn't resolves plugin dependencies.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  installOptions  An options object. Possible options below:
+ * @param  {Boolean}  installOptions.link: Flag that specifies that plugin
+ *   sources will be symlinked to app's directory instead of copying (if
+ *   possible).
+ * @param  {Object}  installOptions.variables  An object that represents
+ *   variables that will be used to install plugin. See more details on plugin
+ *   variables in documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.addPlugin = function (plugin, installOptions) {
+
+    var xcodeproj = projectFile.parse(this.locations);
+    var self = this;
+
+    installOptions = installOptions || {};
+    installOptions.variables = installOptions.variables || {};
+    // Add PACKAGE_NAME variable into vars
+    if (!installOptions.variables.PACKAGE_NAME) {
+        installOptions.variables.PACKAGE_NAME = xcodeproj.getPackageName();
+    }
+
+    return PluginManager.get(self.platform, self.locations, xcodeproj)
+        .addPlugin(plugin, installOptions)
+        .then(function () {
+            if (plugin != null) {
+                var headerTags = plugin.getHeaderFiles(self.platform);
+                var bridgingHeaders = headerTags.filter(function (obj) {
+                    return (obj.type === 'BridgingHeader');
+                });
+                if (bridgingHeaders.length > 0) {
+                    var project_dir = self.locations.root;
+                    var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+                    var BridgingHeader = require('./lib/BridgingHeader').BridgingHeader;
+                    var bridgingHeaderFile = new BridgingHeader(path.join(project_dir, project_name, 'Bridging-Header.h'));
+                    events.emit('verbose', 'Adding Bridging-Headers since the plugin contained <header-file> with type="BridgingHeader"');
+                    bridgingHeaders.forEach(function (obj) {
+                        var bridgingHeaderPath = path.basename(obj.src);
+                        bridgingHeaderFile.addHeader(plugin.id, bridgingHeaderPath);
+                    });
+                    bridgingHeaderFile.write();
+                }
+            }
+        })
+        .then(function () {
+            if (plugin != null) {
+                var podSpecs = plugin.getPodSpecs ? plugin.getPodSpecs(self.platform) : [];
+                var frameworkTags = plugin.getFrameworks(self.platform);
+                var frameworkPods = frameworkTags.filter(function (obj) {
+                    return (obj.type === 'podspec');
+                });
+                return self.addPodSpecs(plugin, podSpecs, frameworkPods);
+            }
+        })
+        // CB-11022 return non-falsy value to indicate
+        // that there is no need to run prepare after
+        .thenResolve(true);
+};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ *   id, caller shoud take care of managing/storing PluginInfo instances for
+ *   future uninstalls.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+    var xcodeproj = projectFile.parse(this.locations);
+    var self = this;
+
+    return PluginManager.get(self.platform, self.locations, xcodeproj)
+        .removePlugin(plugin, uninstallOptions)
+        .then(function () {
+            if (plugin != null) {
+                var headerTags = plugin.getHeaderFiles(self.platform);
+                var bridgingHeaders = headerTags.filter(function (obj) {
+                    return (obj.type === 'BridgingHeader');
+                });
+                if (bridgingHeaders.length > 0) {
+                    var project_dir = self.locations.root;
+                    var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+                    var BridgingHeader = require('./lib/BridgingHeader').BridgingHeader;
+                    var bridgingHeaderFile = new BridgingHeader(path.join(project_dir, project_name, 'Bridging-Header.h'));
+                    events.emit('verbose', 'Removing Bridging-Headers since the plugin contained <header-file> with type="BridgingHeader"');
+                    bridgingHeaders.forEach(function (obj) {
+                        var bridgingHeaderPath = path.basename(obj.src);
+                        bridgingHeaderFile.removeHeader(plugin.id, bridgingHeaderPath);
+                    });
+                    bridgingHeaderFile.write();
+                }
+            }
+        })
+        .then(function () {
+            if (plugin != null) {
+                var podSpecs = plugin.getPodSpecs ? plugin.getPodSpecs(self.platform) : [];
+                var frameworkTags = plugin.getFrameworks(self.platform);
+                var frameworkPods = frameworkTags.filter(function (obj) {
+                    return (obj.type === 'podspec');
+                });
+                return self.removePodSpecs(plugin, podSpecs, frameworkPods);
+            }
+        })
+        // CB-11022 return non-falsy value to indicate
+        // that there is no need to run prepare after
+        .thenResolve(true);
+};
+
+/**
+ * adding CocoaPods libraries
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  podSpecs: the return value of plugin.getPodSpecs(self.platform)
+ * @param  {Object}  frameworkPods: framework tags object with type === 'podspec'
+ * @return  {Promise}  Return a promise
+ */
+
+Api.prototype.addPodSpecs = function (plugin, podSpecs, frameworkPods) {
+    var self = this;
+
+    var project_dir = self.locations.root;
+    var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+    var minDeploymentTarget = self.getPlatformInfo().projectConfig.getPreference('deployment-target', 'ios');
+
+    var Podfile = require('./lib/Podfile').Podfile;
+    var PodsJson = require('./lib/PodsJson').PodsJson;
+    var podsjsonFile = new PodsJson(path.join(project_dir, PodsJson.FILENAME));
+    var podfileFile = new Podfile(path.join(project_dir, Podfile.FILENAME), project_name, minDeploymentTarget);
+
+    if (podSpecs.length) {
+        events.emit('verbose', 'Adding pods since the plugin contained <podspecs>');
+        podSpecs.forEach(function (obj) {
+            // declarations
+            Object.keys(obj.declarations).forEach(function (key) {
+                if (obj.declarations[key] === 'true') {
+                    var declaration = Podfile.proofDeclaration(key);
+                    var podJson = {
+                        declaration: declaration
+                    };
+                    var val = podsjsonFile.getDeclaration(declaration);
+                    if (val) {
+                        podsjsonFile.incrementDeclaration(declaration);
+                    } else {
+                        podJson.count = 1;
+                        podsjsonFile.setJsonDeclaration(declaration, podJson);
+                        podfileFile.addDeclaration(podJson.declaration);
+                    }
+                }
+            });
+            // sources
+            Object.keys(obj.sources).forEach(function (key) {
+                var podJson = {
+                    source: obj.sources[key].source
+                };
+                var val = podsjsonFile.getSource(key);
+                if (val) {
+                    podsjsonFile.incrementSource(key);
+                } else {
+                    podJson.count = 1;
+                    podsjsonFile.setJsonSource(key, podJson);
+                    podfileFile.addSource(podJson.source);
+                }
+            });
+            // libraries
+            Object.keys(obj.libraries).forEach(function (key) {
+                var podJson = Object.assign({}, obj.libraries[key]);
+                var val = podsjsonFile.getLibrary(key);
+                if (val) {
+                    events.emit('warn', plugin.id + ' depends on ' + podJson.name + ', which may conflict with another plugin. ' + podJson.name + '@' + val.spec + ' is already installed and was not overwritten.');
+                    podsjsonFile.incrementLibrary(key);
+                } else {
+                    podJson.count = 1;
+                    podsjsonFile.setJsonLibrary(key, podJson);
+                    podfileFile.addSpec(podJson.name, podJson);
+                }
+            });
+
+        });
+    }
+
+    if (frameworkPods.length) {
+        events.emit('warn', '"framework" tag with type "podspec" is deprecated and will be removed. Please use the "podspec" tag.');
+        events.emit('verbose', 'Adding pods since the plugin contained <framework>(s) with type="podspec"');
+        frameworkPods.forEach(function (obj) {
+            var podJson = {
+                name: obj.src,
+                type: obj.type,
+                spec: obj.spec
+            };
+
+            var val = podsjsonFile.getLibrary(podJson.name);
+            if (val) { // found
+                if (podJson.spec !== val.spec) { // exists, different spec, print warning
+                    events.emit('warn', plugin.id + ' depends on ' + podJson.name + '@' + podJson.spec + ', which conflicts with another plugin. ' + podJson.name + '@' + val.spec + ' is already installed and was not overwritten.');
+                }
+                // increment count, but don't add in Podfile because it already exists
+                podsjsonFile.incrementLibrary(podJson.name);
+            } else { // not found, write new
+                podJson.count = 1;
+                podsjsonFile.setJsonLibrary(podJson.name, podJson);
+                // add to Podfile
+                podfileFile.addSpec(podJson.name, podJson.spec);
+            }
+        });
+    }
+
+    if (podSpecs.length > 0 || frameworkPods.length > 0) {
+        // now that all the pods have been processed, write to pods.json
+        podsjsonFile.write();
+
+        // only write and pod install if the Podfile changed
+        if (podfileFile.isDirty()) {
+            podfileFile.write();
+            events.emit('verbose', 'Running `pod install` (to install plugins)');
+            projectFile.purgeProjectFileCache(self.locations.root);
+
+            return podfileFile.install(check_reqs.check_cocoapods)
+                .then(function () {
+                    return self.setSwiftVersionForCocoaPodsLibraries(podsjsonFile);
+                });
+        } else {
+            events.emit('verbose', 'Podfile unchanged, skipping `pod install`');
+        }
+    }
+    return Q.when();
+};
+
+/**
+ * removing CocoaPods libraries
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  podSpecs: the return value of plugin.getPodSpecs(self.platform)
+ * @param  {Object}  frameworkPods: framework tags object with type === 'podspec'
+ * @return  {Promise}  Return a promise
+ */
+
+Api.prototype.removePodSpecs = function (plugin, podSpecs, frameworkPods) {
+    var self = this;
+
+    var project_dir = self.locations.root;
+    var project_name = self.locations.xcodeCordovaProj.split('/').pop();
+
+    var Podfile = require('./lib/Podfile').Podfile;
+    var PodsJson = require('./lib/PodsJson').PodsJson;
+    var podsjsonFile = new PodsJson(path.join(project_dir, PodsJson.FILENAME));
+    var podfileFile = new Podfile(path.join(project_dir, Podfile.FILENAME), project_name);
+
+    if (podSpecs.length) {
+        events.emit('verbose', 'Adding pods since the plugin contained <podspecs>');
+        podSpecs.forEach(function (obj) {
+            // declarations
+            Object.keys(obj.declarations).forEach(function (key) {
+                if (obj.declarations[key] === 'true') {
+                    var declaration = Podfile.proofDeclaration(key);
+                    var podJson = {
+                        declaration: declaration
+                    };
+                    var val = podsjsonFile.getDeclaration(declaration);
+                    if (val) {
+                        podsjsonFile.decrementDeclaration(declaration);
+                    } else {
+                        var message = util.format('plugin \"%s\" declaration \"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to remove from Podfile.', plugin.id, podJson.declaration); /* eslint no-useless-escape : 0 */
+                        events.emit('verbose', message);
+                    }
+                    if (!val || val.count === 0) {
+                        podfileFile.removeDeclaration(podJson.declaration);
+                    }
+                }
+            });
+            // sources
+            Object.keys(obj.sources).forEach(function (key) {
+                var podJson = {
+                    source: obj.sources[key].source
+                };
+                var val = podsjsonFile.getSource(key);
+                if (val) {
+                    podsjsonFile.decrementSource(key);
+                } else {
+                    var message = util.format('plugin \"%s\" source \"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to remove from Podfile.', plugin.id, podJson.source); /* eslint no-useless-escape : 0 */
+                    events.emit('verbose', message);
+                }
+                if (!val || val.count === 0) {
+                    podfileFile.removeSource(podJson.source);
+                }
+            });
+            // libraries
+            Object.keys(obj.libraries).forEach(function (key) {
+                var podJson = Object.assign({}, obj.libraries[key]);
+                var val = podsjsonFile.getLibrary(key);
+                if (val) {
+                    podsjsonFile.decrementLibrary(key);
+                } else {
+                    var message = util.format('plugin \"%s\" podspec \"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to remove from Podfile.', plugin.id, podJson.name); /* eslint no-useless-escape : 0 */
+                    events.emit('verbose', message);
+                }
+                if (!val || val.count === 0) {
+                    podfileFile.removeSpec(podJson.name);
+                }
+            });
+
+        });
+    }
+
+    if (frameworkPods.length) {
+        events.emit('warn', '"framework" tag with type "podspec" is deprecated and will be removed. Please use the "podspec" tag.');
+        events.emit('verbose', 'Adding pods since the plugin contained <framework>(s) with type=\"podspec\"'); /* eslint no-useless-escape : 0 */
+        frameworkPods.forEach(function (obj) {
+            var podJson = {
+                name: obj.src,
+                type: obj.type,
+                spec: obj.spec
+            };
+
+            var val = podsjsonFile.getLibrary(podJson.name);
+            if (val) { // found, decrement count
+                podsjsonFile.decrementLibrary(podJson.name);
+            } else { // not found (perhaps a sync error)
+                var message = util.format('plugin \"%s\" podspec \"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to remove from Podfile.', plugin.id, podJson.name); /* eslint no-useless-escape : 0 */
+                events.emit('verbose', message);
+            }
+
+            // always remove from the Podfile
+            podfileFile.removeSpec(podJson.name);
+        });
+    }
+
+    if (podSpecs.length > 0 || frameworkPods.length > 0) {
+        // now that all the pods have been processed, write to pods.json
+        podsjsonFile.write();
+
+        if (podfileFile.isDirty()) {
+            podfileFile.write();
+            events.emit('verbose', 'Running `pod install` (to uninstall pods)');
+
+            return podfileFile.install(check_reqs.check_cocoapods)
+                .then(function () {
+                    return self.setSwiftVersionForCocoaPodsLibraries(podsjsonFile);
+                });
+        } else {
+            events.emit('verbose', 'Podfile unchanged, skipping `pod install`');
+        }
+    }
+    return Q.when();
+};
+
+/**
+ * set Swift Version for all CocoaPods libraries
+ *
+ * @param  {PodsJson}  podsjsonFile  A PodsJson instance that represents pods.json
+ */
+
+Api.prototype.setSwiftVersionForCocoaPodsLibraries = function (podsjsonFile) {
+    var self = this;
+    var __dirty = false;
+    return check_reqs.check_cocoapods().then(function (toolOptions) {
+        if (toolOptions.ignore) {
+            events.emit('verbose', '=== skip Swift Version Settings For Cocoapods Libraries');
+        } else {
+            var podPbxPath = path.join(self.root, 'Pods', 'Pods.xcodeproj', 'project.pbxproj');
+            var podXcodeproj = xcode.project(podPbxPath);
+            podXcodeproj.parseSync();
+            var podTargets = podXcodeproj.pbxNativeTargetSection();
+            var podConfigurationList = podXcodeproj.pbxXCConfigurationList();
+            var podConfigs = podXcodeproj.pbxXCBuildConfigurationSection();
+
+            var libraries = podsjsonFile.getLibraries();
+            Object.keys(libraries).forEach(function (key) {
+                var podJson = libraries[key];
+                var name = podJson.name;
+                var swiftVersion = podJson['swift-version'];
+                if (swiftVersion) {
+                    __dirty = true;
+                    Object.keys(podTargets).filter(function (targetKey) {
+                        return podTargets[targetKey].productName === name;
+                    }).map(function (targetKey) {
+                        return podTargets[targetKey].buildConfigurationList;
+                    }).map(function (buildConfigurationListId) {
+                        return podConfigurationList[buildConfigurationListId];
+                    }).map(function (buildConfigurationList) {
+                        return buildConfigurationList.buildConfigurations;
+                    }).reduce(function (acc, buildConfigurations) {
+                        return acc.concat(buildConfigurations);
+                    }, []).map(function (buildConfiguration) {
+                        return buildConfiguration.value;
+                    }).forEach(function (buildId) {
+                        __dirty = true;
+                        podConfigs[buildId].buildSettings['SWIFT_VERSION'] = swiftVersion;
+                    });
+                }
+            });
+            if (__dirty) {
+                fs.writeFileSync(podPbxPath, podXcodeproj.writeSync(), 'utf-8');
+            }
+        }
+    });
+};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param  {Object}  buildOptions  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+Api.prototype.build = function (buildOptions) {
+    var self = this;
+    return check_reqs.run()
+        .then(function () {
+            return require('./lib/build').run.call(self, buildOptions);
+        });
+};
+
+/**
+ * Builds an application package for current platform and runs it on
+ *   specified/default device. If no 'device'/'emulator'/'target' options are
+ *   specified, then tries to run app on default device if connected, otherwise
+ *   runs the app on emulator.
+ *
+ * @param   {Object}  runOptions  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ *   successfully, or rejected with CordovaError.
+ */
+Api.prototype.run = function (runOptions) {
+    var self = this;
+    return check_reqs.run()
+        .then(function () {
+            return require('./lib/run').run.call(self, runOptions);
+        });
+};
+
+/**
+ * Cleans out the build artifacts from platform's directory.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError.
+ */
+Api.prototype.clean = function (cleanOptions) {
+    var self = this;
+    return check_reqs.run()
+        .then(function () {
+            return require('./lib/clean').run.call(self, cleanOptions);
+        })
+        .then(function () {
+            return require('./lib/prepare').clean.call(self, cleanOptions);
+        });
+};
+
+/**
+ * Performs a requirements check for current platform. Each platform defines its
+ *   own set of requirements, which should be resolved before platform can be
+ *   built successfully.
+ *
+ * @return  {Promise<Requirement[]>}  Promise, resolved with set of Requirement
+ *   objects for current platform.
+ */
+Api.prototype.requirements = function () {
+    return check_reqs.check_all();
+};
+
+module.exports = Api;
diff --git a/platforms/ios/cordova/apple_ios_version b/platforms/ios/cordova/apple_ios_version
new file mode 100755
index 0000000..d397bb6
--- /dev/null
+++ b/platforms/ios/cordova/apple_ios_version
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_ios_version().done(null, function(err) {
+    console.log(err);
+    process.exit(2);
+});
diff --git a/platforms/ios/cordova/apple_osx_version b/platforms/ios/cordova/apple_osx_version
new file mode 100755
index 0000000..6e697ad
--- /dev/null
+++ b/platforms/ios/cordova/apple_osx_version
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_osx_version().done(null, function(err) {
+    console.log(err);
+    process.exit(2);
+});
diff --git a/platforms/ios/cordova/apple_xcode_version b/platforms/ios/cordova/apple_xcode_version
new file mode 100755
index 0000000..112eba3
--- /dev/null
+++ b/platforms/ios/cordova/apple_xcode_version
@@ -0,0 +1,29 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_xcode_version().done(function (version) {
+    console.log(version);
+}, function(err) {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/platforms/ios/cordova/build b/platforms/ios/cordova/build
new file mode 100755
index 0000000..bd5a619
--- /dev/null
+++ b/platforms/ios/cordova/build
@@ -0,0 +1,64 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var args  = process.argv;
+var Api = require('./Api');
+var nopt = require('nopt');
+var path = require('path');
+
+// Support basic help commands
+if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
+    require('./lib/build').help();
+    process.exit(0);
+}
+
+// Parse arguments
+var buildOpts = nopt({
+    'verbose' : Boolean,
+    'silent' : Boolean,
+    'archs': String,
+    'debug': Boolean,
+    'release': Boolean,
+    'device': Boolean,
+    'emulator': Boolean,
+    'codeSignIdentity': String,
+    'codeSignResourceRules': String,
+    'provisioningProfile': String,
+    'automaticProvisioning': Boolean,
+    'developmentTeam': String,
+    'packageType': String,
+    'buildConfig' : String,
+    'buildFlag' : [String, Array],
+    'noSign' : Boolean
+}, { '-r': '--release', 'd' : '--verbose' }, args);
+
+// Make buildOptions compatible with PlatformApi build method spec
+buildOpts.argv = buildOpts.argv.remain;
+
+require('./loggingHelper').adjustLoggerLevel(buildOpts);
+
+new Api().build(buildOpts).done(function() {
+        console.log('** BUILD SUCCEEDED **');
+    }, function(err) {
+        var errorMessage = (err && err.stack) ? err.stack : err;
+        console.error(errorMessage);
+        process.exit(2);
+    });
diff --git a/platforms/ios/cordova/build-debug.xcconfig b/platforms/ios/cordova/build-debug.xcconfig
new file mode 100755
index 0000000..3f4767d
--- /dev/null
+++ b/platforms/ios/cordova/build-debug.xcconfig
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+
+//
+// XCode Build settings for "Debug" Build Configuration.
+//
+
+#include "build.xcconfig"
+
+GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1
+
+#include "build-extras.xcconfig"
+
+// (CB-11792)
+// @COCOAPODS_SILENCE_WARNINGS@ //
+#include "../pods-debug.xcconfig"
diff --git a/platforms/ios/cordova/build-extras.xcconfig b/platforms/ios/cordova/build-extras.xcconfig
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/cordova/build-extras.xcconfig
diff --git a/platforms/ios/cordova/build-release.xcconfig b/platforms/ios/cordova/build-release.xcconfig
new file mode 100755
index 0000000..70b0f07
--- /dev/null
+++ b/platforms/ios/cordova/build-release.xcconfig
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+//
+// XCode Build settings for "Release" Build Configuration.
+//
+
+#include "build.xcconfig"
+
+CODE_SIGN_IDENTITY = iPhone Distribution
+CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Distribution
+
+#include "build-extras.xcconfig"
+
+// (CB-11792)
+// @COCOAPODS_SILENCE_WARNINGS@ //
+#include "../pods-release.xcconfig"
diff --git a/platforms/ios/cordova/build.bat b/platforms/ios/cordova/build.bat
new file mode 100755
index 0000000..2f97fcb
--- /dev/null
+++ b/platforms/ios/cordova/build.bat
@@ -0,0 +1,19 @@
+:: 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
+
+@ECHO OFF
+ECHO WARN: The 'build' command is not available for cordova-ios on windows machines.>&2
diff --git a/platforms/ios/cordova/build.xcconfig b/platforms/ios/cordova/build.xcconfig
new file mode 100755
index 0000000..cc78c73
--- /dev/null
+++ b/platforms/ios/cordova/build.xcconfig
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+
+//
+// XCode build settings shared by all Build Configurations.
+// Settings are overridden by configuration-level .xcconfig file (build-release/build-debug).
+//
+
+HEADER_SEARCH_PATHS = "$(TARGET_BUILD_DIR)/usr/local/lib/include" "$(OBJROOT)/UninstalledProducts/include" "$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include" "$(BUILT_PRODUCTS_DIR)"
+OTHER_LDFLAGS = -ObjC
+
+// Type of signing identity used for codesigning, resolves to first match of given type.
+// "iPhone Developer": Development builds (default, local only; iOS Development certificate) or "iPhone Distribution": Distribution builds (Adhoc/In-House/AppStore; iOS Distribution certificate)
+CODE_SIGN_IDENTITY = iPhone Developer
+CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
+
+// (CB-9721) Set ENABLE_BITCODE to NO in build.xcconfig
+ENABLE_BITCODE = NO
+
+// (CB-9719) Set CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES to YES in build.xcconfig
+CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES
+
+// (CB-10072) 
+SWIFT_OBJC_BRIDGING_HEADER = $(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h
+
+// (CB-11854)
+CODE_SIGN_ENTITLEMENTS = $(PROJECT_DIR)/$(PROJECT_NAME)/Entitlements-$(CONFIGURATION).plist
diff --git a/platforms/ios/cordova/check_reqs b/platforms/ios/cordova/check_reqs
new file mode 100755
index 0000000..d101ccd
--- /dev/null
+++ b/platforms/ios/cordova/check_reqs
@@ -0,0 +1,32 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var check_reqs = require('./lib/check_reqs');
+
+// check for help flag
+if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) > -1) {
+    console.log('Usage: check_reqs or node check_reqs');
+} else {
+  check_reqs.run().done(null, function (err) {
+      console.error('Failed to check requirements due to ' + err);
+      process.exit(2);
+  });
+}
diff --git a/platforms/ios/cordova/check_reqs.bat b/platforms/ios/cordova/check_reqs.bat
new file mode 100755
index 0000000..683914b
--- /dev/null
+++ b/platforms/ios/cordova/check_reqs.bat
@@ -0,0 +1,25 @@
+:: 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
+@ECHO OFF
+SET script_path="%~dp0check_reqs"
+IF EXIST %script_path% (
+        node "%script_path%" %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)
\ No newline at end of file
diff --git a/platforms/ios/cordova/clean b/platforms/ios/cordova/clean
new file mode 100755
index 0000000..56665c4
--- /dev/null
+++ b/platforms/ios/cordova/clean
@@ -0,0 +1,50 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+var Api = require('./Api');
+var path  = require('path');
+var nopt = require('nopt');
+
+if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
+    console.log('Cleans the project directory.');
+    process.exit(0);
+}
+
+// Do some basic argument parsing
+var opts = nopt({
+    'verbose' : Boolean,
+    'silent' : Boolean
+}, { 'd' : '--verbose' });
+
+// Make buildOptions compatible with PlatformApi clean method spec
+opts.argv = opts.argv.original;
+
+// Skip cleaning prepared files when not invoking via cordova CLI.
+opts.noPrepare = true;
+
+require('./loggingHelper').adjustLoggerLevel(opts);
+
+new Api().clean(opts).done(function() {
+    console.log('** CLEAN SUCCEEDED **');
+}, function(err) {
+    console.error(err);
+    process.exit(2);
+});
diff --git a/platforms/ios/cordova/clean.bat b/platforms/ios/cordova/clean.bat
new file mode 100755
index 0000000..5830728
--- /dev/null
+++ b/platforms/ios/cordova/clean.bat
@@ -0,0 +1,19 @@
+:: 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
+
+@ECHO OFF
+ECHO WARN: The 'clean' command is not available for cordova-ios on windows machines.>&2
diff --git a/platforms/ios/cordova/defaults.xml b/platforms/ios/cordova/defaults.xml
new file mode 100755
index 0000000..77a0a0b
--- /dev/null
+++ b/platforms/ios/cordova/defaults.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+<widget xmlns     = "http://www.w3.org/ns/widgets"
+        id        = "io.cordova.helloCordova"
+        version   = "2.0.0">
+
+    <!-- Preferences for iOS -->
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="BackupWebStorage" value="cloud" />
+    <preference name="DisallowOverscroll" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="SuppressesLongPressGesture" value="false" />
+    <preference name="Suppresses3DTouchGesture" value="false" />
+    <preference name="GapBetweenPages" value="0" />
+    <preference name="PageLength" value="0" />
+    <preference name="PaginationBreakingMode" value="page" /> <!-- page, column -->
+    <preference name="PaginationMode" value="unpaginated" /> <!-- unpaginated, leftToRight, topToBottom, bottomToTop, rightToLeft -->
+
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage"/>
+    </feature>
+    <feature name="Console">
+        <param name="ios-package" value="CDVLogger"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="HandleOpenUrl">
+        <param name="ios-package" value="CDVHandleOpenURL"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="IntentAndNavigationFilter">
+        <param name="ios-package" value="CDVIntentAndNavigationFilter"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="GestureHandler">
+        <param name="ios-package" value="CDVGestureHandler"/>
+        <param name="onload" value="true"/>
+    </feature>
+
+</widget>
diff --git a/platforms/ios/cordova/lib/BridgingHeader.js b/platforms/ios/cordova/lib/BridgingHeader.js
new file mode 100755
index 0000000..319d3fe
--- /dev/null
+++ b/platforms/ios/cordova/lib/BridgingHeader.js
@@ -0,0 +1,125 @@
+/*
+       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.
+*/
+'use strict';
+
+var fs = require('fs');
+var CordovaError = require('cordova-common').CordovaError;
+
+function BridgingHeader (bridgingHeaderPath) {
+    this.path = bridgingHeaderPath;
+    this.bridgingHeaders = null;
+    if (!fs.existsSync(this.path)) {
+        throw new CordovaError('BridgingHeader.h is not found.');
+    }
+    this.bridgingHeaders = this.__parseForBridgingHeader(fs.readFileSync(this.path, 'utf8'));
+}
+
+BridgingHeader.prototype.addHeader = function (plugin_id, header_path) {
+    this.bridgingHeaders.push({ type: 'code', code: '#import "' + header_path + '"\n' });
+};
+
+BridgingHeader.prototype.removeHeader = function (plugin_id, header_path) {
+    this.bridgingHeaders = this.bridgingHeaders.filter(function (line) {
+        if (this.found) {
+            return true;
+        }
+        if (line.type === 'code') {
+            var re = new RegExp('#import\\s+"' + preg_quote(header_path) + '"(\\s*|\\s.+)(\\n|$)');
+            if (re.test(line.code)) {
+                this.found = true;
+                return false;
+            }
+        }
+        return true;
+    }, { found: false });
+};
+
+BridgingHeader.prototype.write = function () {
+    var text = this.__stringifyForBridgingHeader(this.bridgingHeaders);
+    fs.writeFileSync(this.path, text, 'utf8');
+};
+
+BridgingHeader.prototype.__stringifyForBridgingHeader = function (bridgingHeaders) {
+    return bridgingHeaders.map(function (obj) {
+        return obj.code;
+    }).join('');
+};
+
+BridgingHeader.prototype.__parseForBridgingHeader = function (text) {
+    var i = 0;
+    var list = [];
+    var type = 'code';
+    var start = 0;
+    while (i < text.length) {
+        switch (type) {
+        case 'comment':
+            if (i + 1 < text.length && text[i] === '*' && text[i + 1] === '/') {
+                i += 2;
+                list.push({ type: type, code: text.slice(start, i) });
+                type = 'code';
+                start = i;
+            } else {
+                i += 1;
+            }
+            break;
+        case 'line-comment':
+            if (i < text.length && text[i] === '\n') {
+                i += 1;
+                list.push({ type: type, code: text.slice(start, i) });
+                type = 'code';
+                start = i;
+            } else {
+                i += 1;
+            }
+            break;
+        case 'code':
+        default:
+            if (i + 1 < text.length && text[i] === '/' && text[i + 1] === '*') { // comment
+                if (start < i) {
+                    list.push({ type: type, code: text.slice(start, i) });
+                }
+                type = 'comment';
+                start = i;
+            } else if (i + 1 < text.length && text[i] === '/' && text[i + 1] === '/') { // line comment
+                if (start < i) {
+                    list.push({ type: type, code: text.slice(start, i) });
+                }
+                type = 'line-comment';
+                start = i;
+            } else if (i < text.length && text[i] === '\n') {
+                i += 1;
+                list.push({ type: type, code: text.slice(start, i) });
+                start = i;
+            } else {
+                i += 1;
+            }
+            break;
+        }
+    }
+    if (start < i) {
+        list.push({ type: type, code: text.slice(start, i) });
+    }
+    return list;
+};
+
+function preg_quote (str, delimiter) {
+    return (str + '').replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + (delimiter || '') + '-]', 'g'), '\\$&');
+}
+
+module.exports.BridgingHeader = BridgingHeader;
diff --git a/platforms/ios/cordova/lib/Podfile.js b/platforms/ios/cordova/lib/Podfile.js
new file mode 100755
index 0000000..0a3cdcd
--- /dev/null
+++ b/platforms/ios/cordova/lib/Podfile.js
@@ -0,0 +1,427 @@
+/*
+       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.
+*/
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+var events = require('cordova-common').events;
+var Q = require('q');
+var superspawn = require('cordova-common').superspawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+Podfile.FILENAME = 'Podfile';
+Podfile.declarationRegexpMap = {
+    'use_frameworks!': 'use[-_]frameworks!?',
+    'inhibit_all_warnings!': 'inhibit[-_]all[-_]warnings!?'
+};
+
+function Podfile (podFilePath, projectName, minDeploymentTarget) {
+    this.declarationToken = '##INSERT_DECLARATION##';
+    this.sourceToken = '##INSERT_SOURCE##';
+    this.podToken = '##INSERT_POD##';
+
+    this.path = podFilePath;
+    this.projectName = projectName;
+    this.minDeploymentTarget = minDeploymentTarget || '9.0';
+    this.contents = null;
+    this.sources = null;
+    this.declarations = null;
+    this.pods = null;
+    this.__dirty = false;
+
+    // check whether it is named Podfile
+    var filename = this.path.split(path.sep).pop();
+    if (filename !== Podfile.FILENAME) {
+        throw new CordovaError(util.format('Podfile: The file at %s is not `%s`.', this.path, Podfile.FILENAME));
+    }
+
+    if (!projectName) {
+        throw new CordovaError('Podfile: The projectName was not specified in the constructor.');
+    }
+
+    if (!fs.existsSync(this.path)) {
+        events.emit('verbose', util.format('Podfile: The file at %s does not exist.', this.path));
+        events.emit('verbose', 'Creating new Podfile in platforms/ios');
+        this.clear();
+        this.write();
+    } else {
+        events.emit('verbose', 'Podfile found in platforms/ios');
+        // parse for pods
+        var fileText = fs.readFileSync(this.path, 'utf8');
+        this.declarations = this.__parseForDeclarations(fileText);
+        this.sources = this.__parseForSources(fileText);
+        this.pods = this.__parseForPods(fileText);
+    }
+}
+
+Podfile.prototype.__parseForDeclarations = function (text) {
+    // split by \n
+    var arr = text.split('\n');
+
+    // getting lines between "platform :ios, '9.0'"" and "target 'HelloCordova'" do
+    var declarationsPreRE = new RegExp('platform :ios,\\s+\'[^\']+\'');
+    var declarationsPostRE = new RegExp('target\\s+\'[^\']+\'\\s+do');
+    var declarationRE = new RegExp('^\\s*[^#]');
+
+    return arr.reduce(function (acc, line) {
+        switch (acc.state) {
+        case 0:
+            if (declarationsPreRE.exec(line)) {
+                acc.state = 1; // Start to read
+            }
+            break;
+        case 1:
+            if (declarationsPostRE.exec(line)) {
+                acc.state = 2; // Finish to read
+            } else {
+                acc.lines.push(line);
+            }
+            break;
+        case 2:
+        default:
+            // do nothing;
+        }
+        return acc;
+    }, { state: 0, lines: [] })
+        .lines
+        .filter(function (line) {
+            return declarationRE.exec(line);
+        })
+        .reduce(function (obj, line) {
+            obj[line] = line;
+            return obj;
+        }, {});
+};
+
+Podfile.prototype.__parseForSources = function (text) {
+    // split by \n
+    var arr = text.split('\n');
+
+    var sourceRE = new RegExp('source \'(.*)\'');
+    return arr.filter(function (line) {
+        var m = sourceRE.exec(line);
+
+        return (m !== null);
+    })
+        .reduce(function (obj, line) {
+            var m = sourceRE.exec(line);
+            if (m !== null) {
+                var source = m[1];
+                obj[source] = source;
+            }
+            return obj;
+        }, {});
+};
+
+Podfile.prototype.__parseForPods = function (text) {
+    // split by \n
+    var arr = text.split('\n');
+
+    // aim is to match (space insignificant around the comma, comma optional):
+    //     pod 'Foobar', '1.2'
+    //     pod 'Foobar', 'abc 123 1.2'
+    //     pod 'PonyDebugger', :configurations => ['Debug', 'Beta']
+    // var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)');
+    var podRE = new RegExp('pod \'([^\']*)\'\\s*(?:,\\s*\'([^\']*)\'\\s*)?,?\\s*(.*)');
+
+    // only grab lines that don't have the pod spec'
+    return arr.filter(function (line) {
+        var m = podRE.exec(line);
+
+        return (m !== null);
+    })
+        .reduce(function (obj, line) {
+            var m = podRE.exec(line);
+
+            if (m !== null) {
+                var podspec = {
+                    name: m[1]
+                };
+                if (m[2]) {
+                    podspec.spec = m[2];
+                }
+                if (m[3]) {
+                    podspec.options = m[3];
+                }
+                obj[m[1]] = podspec; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'}
+            }
+
+            return obj;
+        }, {});
+};
+
+Podfile.prototype.escapeSingleQuotes = function (string) {
+    return string.replace('\'', '\\\'');
+};
+
+Podfile.prototype.getTemplate = function () {
+    // Escaping possible ' in the project name
+    var projectName = this.escapeSingleQuotes(this.projectName);
+    return util.format(
+        '# DO NOT MODIFY -- auto-generated by Apache Cordova\n' +
+            '%s\n' +
+            'platform :ios, \'%s\'\n' +
+            '%s\n' +
+            'target \'%s\' do\n' +
+            '\tproject \'%s.xcodeproj\'\n' +
+            '%s\n' +
+            'end\n',
+        this.sourceToken, this.minDeploymentTarget, this.declarationToken, projectName, projectName, this.podToken);
+};
+
+Podfile.prototype.addSpec = function (name, spec) {
+    name = name || '';
+    // optional
+    spec = spec; /* eslint no-self-assign : 0 */
+
+    if (!name.length) { // blank names are not allowed
+        throw new CordovaError('Podfile addSpec: name is not specified.');
+    }
+
+    if (typeof spec === 'string') {
+        if (spec.startsWith(':')) {
+            spec = { name: name, options: spec };
+        } else {
+            spec = { name: name, spec: spec };
+        }
+    }
+
+    this.pods[name] = spec;
+    this.__dirty = true;
+
+    events.emit('verbose', util.format('Added pod line for `%s`', name));
+};
+
+Podfile.prototype.removeSpec = function (name) {
+    if (this.existsSpec(name)) {
+        delete this.pods[name];
+        this.__dirty = true;
+    }
+
+    events.emit('verbose', util.format('Removed pod line for `%s`', name));
+};
+
+Podfile.prototype.getSpec = function (name) {
+    return this.pods[name];
+};
+
+Podfile.prototype.existsSpec = function (name) {
+    return (name in this.pods);
+};
+
+Podfile.prototype.addSource = function (src) {
+    this.sources[src] = src;
+    this.__dirty = true;
+
+    events.emit('verbose', util.format('Added source line for `%s`', src));
+};
+
+Podfile.prototype.removeSource = function (src) {
+    if (this.existsSource(src)) {
+        delete this.sources[src];
+        this.__dirty = true;
+    }
+
+    events.emit('verbose', util.format('Removed source line for `%s`', src));
+};
+
+Podfile.prototype.existsSource = function (src) {
+    return (src in this.sources);
+};
+
+Podfile.prototype.addDeclaration = function (declaration) {
+    this.declarations[declaration] = declaration;
+    this.__dirty = true;
+
+    events.emit('verbose', util.format('Added declaration line for `%s`', declaration));
+};
+
+Podfile.prototype.removeDeclaration = function (declaration) {
+    if (this.existsDeclaration(declaration)) {
+        delete this.declarations[declaration];
+        this.__dirty = true;
+    }
+
+    events.emit('verbose', util.format('Removed source line for `%s`', declaration));
+};
+
+Podfile.proofDeclaration = function (declaration) {
+    var list = Object.keys(Podfile.declarationRegexpMap).filter(function (key) {
+        var regexp = new RegExp(Podfile.declarationRegexpMap[key]);
+        return regexp.test(declaration);
+    });
+    if (list.length > 0) {
+        return list[0];
+    }
+    return declaration;
+};
+
+Podfile.prototype.existsDeclaration = function (declaration) {
+    return (declaration in this.declarations);
+};
+
+Podfile.prototype.clear = function () {
+    this.sources = {};
+    this.declarations = {};
+    this.pods = {};
+    this.__dirty = true;
+};
+
+Podfile.prototype.destroy = function () {
+    fs.unlinkSync(this.path);
+    events.emit('verbose', util.format('Deleted `%s`', this.path));
+};
+
+Podfile.prototype.write = function () {
+    var text = this.getTemplate();
+    var self = this;
+
+    var podsString =
+    Object.keys(this.pods).map(function (key) {
+        var name = key;
+        var json = self.pods[key];
+
+        if (typeof json === 'string') { // compatibility for using framework tag.
+            var spec = json;
+            if (spec.length) {
+                if (spec.indexOf(':') === 0) {
+                    // don't quote it, it's a specification (starts with ':')
+                    return util.format('\tpod \'%s\', %s', name, spec);
+                } else {
+                    // quote it, it's a version
+                    return util.format('\tpod \'%s\', \'%s\'', name, spec);
+                }
+            } else {
+                return util.format('\tpod \'%s\'', name);
+            }
+        } else {
+            var list = ['\'' + name + '\''];
+            if ('spec' in json && json.spec.length) {
+                list.push('\'' + json.spec + '\'');
+            }
+
+            var options = ['tag', 'branch', 'commit', 'git', 'podspec'].filter(function (tag) {
+                return tag in json;
+            }).map(function (tag) {
+                return ':' + tag + ' => \'' + json[tag] + '\'';
+            });
+            if ('configurations' in json) {
+                options.push(':configurations => [' + json['configurations'].split(',').map(function (conf) { return '\'' + conf.trim() + '\''; }).join(',') + ']');
+            }
+            if ('options' in json) {
+                options = [json.options];
+            }
+            if (options.length > 0) {
+                list.push(options.join(', '));
+            }
+            return util.format('\tpod %s', list.join(', '));
+        }
+    }).join('\n');
+
+    var sourcesString =
+    Object.keys(this.sources).map(function (key) {
+        var source = self.sources[key];
+        return util.format('source \'%s\'', source);
+    }).join('\n');
+
+    var declarationString =
+    Object.keys(this.declarations).map(function (key) {
+        var declaration = self.declarations[key];
+        return declaration;
+    }).join('\n');
+
+    text = text.replace(this.podToken, podsString)
+        .replace(this.sourceToken, sourcesString)
+        .replace(this.declarationToken, declarationString);
+
+    fs.writeFileSync(this.path, text, 'utf8');
+    this.__dirty = false;
+
+    events.emit('verbose', 'Wrote to Podfile.');
+};
+
+Podfile.prototype.isDirty = function () {
+    return this.__dirty;
+};
+
+Podfile.prototype.before_install = function (toolOptions) {
+    toolOptions = toolOptions || {};
+
+    // Template tokens in order: project name, project name, debug | release
+    var template =
+    '// DO NOT MODIFY -- auto-generated by Apache Cordova\n' +
+    '#include "Pods/Target Support Files/Pods-%s/Pods-%s.%s.xcconfig"';
+
+    var debugContents = util.format(template, this.projectName, this.projectName, 'debug');
+    var releaseContents = util.format(template, this.projectName, this.projectName, 'release');
+
+    var debugConfigPath = path.join(this.path, '..', 'pods-debug.xcconfig');
+    var releaseConfigPath = path.join(this.path, '..', 'pods-release.xcconfig');
+
+    fs.writeFileSync(debugConfigPath, debugContents, 'utf8');
+    fs.writeFileSync(releaseConfigPath, releaseContents, 'utf8');
+
+    return Q.resolve(toolOptions);
+};
+
+Podfile.prototype.install = function (requirementsCheckerFunction) {
+    var opts = {};
+    opts.cwd = path.join(this.path, '..'); // parent path of this Podfile
+    opts.stdio = 'pipe';
+    opts.printCommand = true;
+    var first = true;
+    var self = this;
+
+    if (!requirementsCheckerFunction) {
+        requirementsCheckerFunction = Q();
+    }
+
+    return requirementsCheckerFunction()
+        .then(function (toolOptions) {
+            return self.before_install(toolOptions);
+        })
+        .then(function (toolOptions) {
+            if (toolOptions.ignore) {
+                events.emit('verbose', '==== pod install start ====\n');
+                events.emit('verbose', toolOptions.ignoreMessage);
+                return Q.resolve();
+            } else {
+                return superspawn.spawn('pod', ['install', '--verbose'], opts)
+                    .progress(function (stdio) {
+                        if (stdio.stderr) { console.error(stdio.stderr); }
+                        if (stdio.stdout) {
+                            if (first) {
+                                events.emit('verbose', '==== pod install start ====\n');
+                                first = false;
+                            }
+                            events.emit('verbose', stdio.stdout);
+                        }
+                    });
+            }
+        })
+        .then(function () { // done
+            events.emit('verbose', '==== pod install end ====\n');
+        })
+        .fail(function (error) {
+            throw error;
+        });
+};
+
+module.exports.Podfile = Podfile;
diff --git a/platforms/ios/cordova/lib/PodsJson.js b/platforms/ios/cordova/lib/PodsJson.js
new file mode 100755
index 0000000..25afbac
--- /dev/null
+++ b/platforms/ios/cordova/lib/PodsJson.js
@@ -0,0 +1,209 @@
+/*
+       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.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+var events = require('cordova-common').events;
+var CordovaError = require('cordova-common').CordovaError;
+
+PodsJson.FILENAME = 'pods.json';
+PodsJson.LIBRARY = 'libraries';
+PodsJson.SOURCE = 'sources';
+PodsJson.DECLARATION = 'declarations';
+
+function PodsJson (podsJsonPath) {
+    this.path = podsJsonPath;
+    this.contents = null;
+    this.__dirty = false;
+
+    var filename = this.path.split(path.sep).pop();
+    if (filename !== PodsJson.FILENAME) {
+        throw new CordovaError(util.format('PodsJson: The file at %s is not `%s`.', this.path, PodsJson.FILENAME));
+    }
+
+    if (!fs.existsSync(this.path)) {
+        events.emit('verbose', util.format('pods.json: The file at %s does not exist.', this.path));
+        events.emit('verbose', 'Creating new pods.json in platforms/ios');
+        this.clear();
+        this.write();
+    } else {
+        events.emit('verbose', 'pods.json found in platforms/ios');
+        // load contents
+        var contents = fs.readFileSync(this.path, 'utf8');
+        this.contents = JSON.parse(contents);
+    }
+    this.__updateFormatIfNecessary();
+}
+
+PodsJson.prototype.__isOldFormat = function () {
+    if (this.contents !== null) {
+        if (this.contents.declarations === undefined ||
+            this.contents.sources === undefined ||
+            this.contents.libraries === undefined) {
+            return true;
+        }
+    }
+    return false;
+};
+
+PodsJson.prototype.__updateFormatIfNecessary = function () {
+    if (this.__isOldFormat()) {
+        this.contents = {
+            declarations: {},
+            sources: {},
+            libraries: this.contents
+        };
+        this.__dirty = true;
+        events.emit('verbose', 'Update format of pods.json');
+    }
+};
+
+PodsJson.prototype.getLibraries = function () {
+    return this.contents[PodsJson.LIBRARY];
+};
+
+PodsJson.prototype.__get = function (kind, name) {
+    return this.contents[kind][name];
+};
+
+PodsJson.prototype.getLibrary = function (name) {
+    return this.__get(PodsJson.LIBRARY, name);
+};
+
+PodsJson.prototype.getSource = function (name) {
+    return this.__get(PodsJson.SOURCE, name);
+};
+
+PodsJson.prototype.getDeclaration = function (name) {
+    return this.__get(PodsJson.DECLARATION, name);
+};
+
+PodsJson.prototype.__remove = function (kind, name) {
+    if (this.contents[kind][name]) {
+        delete this.contents[kind][name];
+        this.__dirty = true;
+        events.emit('verbose', util.format('Remove from pods.json for `%s` - `%s`', name));
+    }
+};
+
+PodsJson.prototype.removeLibrary = function (name) {
+    this.__remove(PodsJson.LIBRARY, name);
+};
+
+PodsJson.prototype.removeSource = function (name) {
+    this.__remove(PodsJson.SOURCE, name);
+};
+
+PodsJson.prototype.removeDeclaration = function (name) {
+    this.__remove(PodsJson.DECLARATION, name);
+};
+
+PodsJson.prototype.clear = function () {
+    this.contents = {
+        declarations: {},
+        sources: {},
+        libraries: {}
+    };
+    this.__dirty = true;
+};
+
+PodsJson.prototype.destroy = function () {
+    fs.unlinkSync(this.path);
+    events.emit('verbose', util.format('Deleted `%s`', this.path));
+};
+
+PodsJson.prototype.write = function () {
+    if (this.contents) {
+        fs.writeFileSync(this.path, JSON.stringify(this.contents, null, 4));
+        this.__dirty = false;
+        events.emit('verbose', 'Wrote to pods.json.');
+    }
+};
+
+PodsJson.prototype.__increment = function (kind, name) {
+    var val = this.__get(kind, name);
+    if (val) {
+        val.count++;
+    }
+};
+
+PodsJson.prototype.incrementLibrary = function (name) {
+    this.__increment(PodsJson.LIBRARY, name);
+};
+
+PodsJson.prototype.incrementSource = function (name) {
+    this.__increment(PodsJson.SOURCE, name);
+};
+
+PodsJson.prototype.incrementDeclaration = function (name) {
+    this.__increment(PodsJson.DECLARATION, name);
+};
+
+PodsJson.prototype.__decrement = function (kind, name) {
+    var val = this.__get(kind, name);
+    if (val) {
+        val.count--;
+        if (val.count <= 0) {
+            this.__remove(kind, name);
+        }
+    }
+};
+
+PodsJson.prototype.decrementLibrary = function (name) {
+    this.__decrement(PodsJson.LIBRARY, name);
+};
+
+PodsJson.prototype.decrementSource = function (name) {
+    this.__decrement(PodsJson.SOURCE, name);
+};
+
+PodsJson.prototype.decrementDeclaration = function (name) {
+    this.__decrement(PodsJson.DECLARATION, name);
+};
+
+PodsJson.prototype.__setJson = function (kind, name, json) {
+    this.contents[kind][name] = Object.assign({}, json);
+    this.__dirty = true;
+    events.emit('verbose', util.format('Set pods.json for `%s` - `%s`', kind, name));
+};
+
+// sample json for library
+// { name: "Eureka", spec: "4.2.0", "swift-version": "4.1", count: 1 }
+PodsJson.prototype.setJsonLibrary = function (name, json) {
+    this.__setJson(PodsJson.LIBRARY, name, json);
+};
+
+// sample json for source
+// { source: "https://github.com/brightcove/BrightcoveSpecs.git", count: 1 }
+PodsJson.prototype.setJsonSource = function (name, json) {
+    this.__setJson(PodsJson.SOURCE, name, json);
+};
+
+// sample json for declaration
+// { declaration: ""}
+PodsJson.prototype.setJsonDeclaration = function (name, json) {
+    this.__setJson(PodsJson.DECLARATION, name, json);
+};
+
+PodsJson.prototype.isDirty = function () {
+    return this.__dirty;
+};
+
+module.exports.PodsJson = PodsJson;
diff --git a/platforms/ios/cordova/lib/build.js b/platforms/ios/cordova/lib/build.js
new file mode 100755
index 0000000..7a36c06
--- /dev/null
+++ b/platforms/ios/cordova/lib/build.js
@@ -0,0 +1,464 @@
+/**
+ * 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.
+ */
+
+var Q = require('q');
+var path = require('path');
+var shell = require('shelljs');
+var superspawn = require('cordova-common').superspawn;
+var fs = require('fs');
+var plist = require('plist');
+var util = require('util');
+
+var check_reqs = require('./check_reqs');
+var projectFile = require('./projectFile');
+
+var events = require('cordova-common').events;
+
+// These are regular expressions to detect if the user is changing any of the built-in xcodebuildArgs
+/* eslint-disable no-useless-escape */
+var buildFlagMatchers = {
+    'workspace': /^\-workspace\s*(.*)/,
+    'scheme': /^\-scheme\s*(.*)/,
+    'configuration': /^\-configuration\s*(.*)/,
+    'sdk': /^\-sdk\s*(.*)/,
+    'destination': /^\-destination\s*(.*)/,
+    'archivePath': /^\-archivePath\s*(.*)/,
+    'configuration_build_dir': /^(CONFIGURATION_BUILD_DIR=.*)/,
+    'shared_precomps_dir': /^(SHARED_PRECOMPS_DIR=.*)/
+};
+/* eslint-enable no-useless-escape */
+
+/**
+ * Creates a project object (see projectFile.js/parseProjectFile) from
+ * a project path and name
+ *
+ * @param {*} projectPath
+ * @param {*} projectName
+ */
+function createProjectObject (projectPath, projectName) {
+    var locations = {
+        root: projectPath,
+        pbxproj: path.join(projectPath, projectName + '.xcodeproj', 'project.pbxproj')
+    };
+
+    return projectFile.parse(locations);
+}
+
+/**
+ * Gets the resolved bundle identifier from a project.
+ * Resolves the variable set in INFO.plist, if any (simple case)
+ *
+ * @param {*} projectObject
+ */
+function getBundleIdentifier (projectObject) {
+    var packageName = projectObject.getPackageName();
+    var bundleIdentifier = packageName;
+
+    var variables = packageName.match(/\$\((\w+)\)/); // match $(VARIABLE), if any
+    if (variables && variables.length >= 2) {
+        bundleIdentifier = projectObject.xcode.getBuildProperty(variables[1]);
+    }
+
+    return bundleIdentifier;
+}
+
+/**
+ * Returns a promise that resolves to the default simulator target; the logic here
+ * matches what `cordova emulate ios` does.
+ *
+ * The return object has two properties: `name` (the Xcode destination name),
+ * `identifier` (the simctl identifier), and `simIdentifier` (essentially the cordova emulate target)
+ *
+ * @return {Promise}
+ */
+function getDefaultSimulatorTarget () {
+    return require('./list-emulator-build-targets').run()
+        .then(function (emulators) {
+            var targetEmulator;
+            if (emulators.length > 0) {
+                targetEmulator = emulators[0];
+            }
+            emulators.forEach(function (emulator) {
+                if (emulator.name.indexOf('iPhone') === 0) {
+                    targetEmulator = emulator;
+                }
+            });
+            return targetEmulator;
+        });
+}
+
+module.exports.run = function (buildOpts) {
+    var emulatorTarget = '';
+    var projectPath = path.join(__dirname, '..', '..');
+    var projectName = '';
+
+    buildOpts = buildOpts || {};
+
+    if (buildOpts.debug && buildOpts.release) {
+        return Q.reject('Cannot specify "debug" and "release" options together.');
+    }
+
+    if (buildOpts.device && buildOpts.emulator) {
+        return Q.reject('Cannot specify "device" and "emulator" options together.');
+    }
+
+    if (buildOpts.buildConfig) {
+        if (!fs.existsSync(buildOpts.buildConfig)) {
+            return Q.reject('Build config file does not exist:' + buildOpts.buildConfig);
+        }
+        events.emit('log', 'Reading build config file:', path.resolve(buildOpts.buildConfig));
+        var contents = fs.readFileSync(buildOpts.buildConfig, 'utf-8');
+        var buildConfig = JSON.parse(contents.replace(/^\ufeff/, '')); // Remove BOM
+        if (buildConfig.ios) {
+            var buildType = buildOpts.release ? 'release' : 'debug';
+            var config = buildConfig.ios[buildType];
+            if (config) {
+                ['codeSignIdentity', 'codeSignResourceRules', 'provisioningProfile', 'developmentTeam', 'packageType', 'buildFlag', 'iCloudContainerEnvironment', 'automaticProvisioning'].forEach(
+                    function (key) {
+                        buildOpts[key] = buildOpts[key] || config[key];
+                    });
+            }
+        }
+    }
+
+    return require('./list-devices').run()
+        .then(function (devices) {
+            if (devices.length > 0 && !(buildOpts.emulator)) {
+                // we also explicitly set device flag in options as we pass
+                // those parameters to other api (build as an example)
+                buildOpts.device = true;
+                return check_reqs.check_ios_deploy();
+            }
+        }).then(function () {
+            // CB-12287: Determine the device we should target when building for a simulator
+            if (!buildOpts.device) {
+                var newTarget = buildOpts.target || '';
+
+                if (newTarget) {
+                    // only grab the device name, not the runtime specifier
+                    newTarget = newTarget.split(',')[0];
+                }
+                // a target was given to us, find the matching Xcode destination name
+                var promise = require('./list-emulator-build-targets').targetForSimIdentifier(newTarget);
+                return promise.then(function (theTarget) {
+                    if (!theTarget) {
+                        return getDefaultSimulatorTarget().then(function (defaultTarget) {
+                            emulatorTarget = defaultTarget.name;
+                            events.emit('warn', `No simulator found for "${newTarget}. Falling back to the default target.`);
+                            events.emit('log', `Building for "${emulatorTarget}" Simulator (${defaultTarget.identifier}, ${defaultTarget.simIdentifier}).`);
+                            return emulatorTarget;
+                        });
+                    } else {
+                        emulatorTarget = theTarget.name;
+                        events.emit('log', `Building for "${emulatorTarget}" Simulator (${theTarget.identifier}, ${theTarget.simIdentifier}).`);
+                        return emulatorTarget;
+                    }
+                });
+            }
+        }).then(function () {
+            return check_reqs.run();
+        }).then(function () {
+            return findXCodeProjectIn(projectPath);
+        }).then(function (name) {
+            projectName = name;
+            var extraConfig = '';
+            if (buildOpts.codeSignIdentity) {
+                extraConfig += 'CODE_SIGN_IDENTITY = ' + buildOpts.codeSignIdentity + '\n';
+                extraConfig += 'CODE_SIGN_IDENTITY[sdk=iphoneos*] = ' + buildOpts.codeSignIdentity + '\n';
+            }
+            if (buildOpts.codeSignResourceRules) {
+                extraConfig += 'CODE_SIGN_RESOURCE_RULES_PATH = ' + buildOpts.codeSignResourceRules + '\n';
+            }
+            if (buildOpts.provisioningProfile) {
+                extraConfig += 'PROVISIONING_PROFILE = ' + buildOpts.provisioningProfile + '\n';
+            }
+            if (buildOpts.developmentTeam) {
+                extraConfig += 'DEVELOPMENT_TEAM = ' + buildOpts.developmentTeam + '\n';
+            }
+
+            function writeCodeSignStyle (value) {
+                var project = createProjectObject(projectPath, projectName);
+
+                events.emit('verbose', `Set CODE_SIGN_STYLE Build Property to ${value}.`);
+                project.xcode.updateBuildProperty('CODE_SIGN_STYLE', value);
+                events.emit('verbose', `Set ProvisioningStyle Target Attribute to ${value}.`);
+                project.xcode.addTargetAttribute('ProvisioningStyle', value);
+
+                project.write();
+            }
+
+            if (buildOpts.provisioningProfile) {
+                events.emit('verbose', 'ProvisioningProfile build option set, changing project settings to Manual.');
+                writeCodeSignStyle('Manual');
+            } else if (buildOpts.automaticProvisioning) {
+                events.emit('verbose', 'ProvisioningProfile build option NOT set, changing project settings to Automatic.');
+                writeCodeSignStyle('Automatic');
+            }
+
+            return Q.nfcall(fs.writeFile, path.join(__dirname, '..', 'build-extras.xcconfig'), extraConfig, 'utf-8');
+        }).then(function () {
+            var configuration = buildOpts.release ? 'Release' : 'Debug';
+
+            events.emit('log', 'Building project: ' + path.join(projectPath, projectName + '.xcworkspace'));
+            events.emit('log', '\tConfiguration: ' + configuration);
+            events.emit('log', '\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator'));
+            events.emit('log', '\tTarget: ' + emulatorTarget);
+
+            var buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator'));
+
+            // remove the build/device folder before building
+            shell.rm('-rf', buildOutputDir);
+
+            var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget, buildOpts.automaticProvisioning);
+            return superspawn.spawn('xcodebuild', xcodebuildArgs, { cwd: projectPath, printCommand: true, stdio: 'inherit' });
+
+        }).then(function () {
+            if (!buildOpts.device || buildOpts.noSign) {
+                return;
+            }
+
+            var project = createProjectObject(projectPath, projectName);
+            var bundleIdentifier = getBundleIdentifier(project);
+            var exportOptions = { 'compileBitcode': false, 'method': 'development' };
+
+            if (buildOpts.packageType) {
+                exportOptions.method = buildOpts.packageType;
+            }
+
+            if (buildOpts.iCloudContainerEnvironment) {
+                exportOptions.iCloudContainerEnvironment = buildOpts.iCloudContainerEnvironment;
+            }
+
+            if (buildOpts.developmentTeam) {
+                exportOptions.teamID = buildOpts.developmentTeam;
+            }
+
+            if (buildOpts.provisioningProfile && bundleIdentifier) {
+                exportOptions.provisioningProfiles = { [ bundleIdentifier ]: String(buildOpts.provisioningProfile) };
+                exportOptions.signingStyle = 'manual';
+            }
+
+            if (buildOpts.codeSignIdentity) {
+                exportOptions.signingCertificate = buildOpts.codeSignIdentity;
+            }
+
+            var exportOptionsPlist = plist.build(exportOptions);
+            var exportOptionsPath = path.join(projectPath, 'exportOptions.plist');
+
+            var buildOutputDir = path.join(projectPath, 'build', 'device');
+
+            function checkSystemRuby () {
+                var ruby_cmd = shell.which('ruby');
+
+                if (ruby_cmd !== '/usr/bin/ruby') {
+                    events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' +
+                  'If you use RVM, please run `rvm use system`.\n' +
+                  'If you use chruby, please run `chruby system`.');
+                }
+            }
+
+            function packageArchive () {
+                var xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath, buildOpts.automaticProvisioning);
+                return superspawn.spawn('xcodebuild', xcodearchiveArgs, { cwd: projectPath, printCommand: true, stdio: 'inherit' });
+            }
+
+            return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8')
+                .then(checkSystemRuby)
+                .then(packageArchive);
+        });
+};
+
+/**
+ * Searches for first XCode project in specified folder
+ * @param  {String} projectPath Path where to search project
+ * @return {Promise}            Promise either fulfilled with project name or rejected
+ */
+function findXCodeProjectIn (projectPath) {
+    // 'Searching for Xcode project in ' + projectPath);
+    var xcodeProjFiles = shell.ls(projectPath).filter(function (name) {
+        return path.extname(name) === '.xcodeproj';
+    });
+
+    if (xcodeProjFiles.length === 0) {
+        return Q.reject('No Xcode project found in ' + projectPath);
+    }
+    if (xcodeProjFiles.length > 1) {
+        events.emit('warn', 'Found multiple .xcodeproj directories in \n' +
+            projectPath + '\nUsing first one');
+    }
+
+    var projectName = path.basename(xcodeProjFiles[0], '.xcodeproj');
+    return Q.resolve(projectName);
+}
+
+module.exports.findXCodeProjectIn = findXCodeProjectIn;
+
+/**
+ * Returns array of arguments for xcodebuild
+ * @param  {String}  projectName    Name of xcode project
+ * @param  {String}  projectPath    Path to project file. Will be used to set CWD for xcodebuild
+ * @param  {String}  configuration  Configuration name: debug|release
+ * @param  {Boolean} isDevice       Flag that specify target for package (device/emulator)
+ * @param  {Array}   buildFlags
+ * @param  {String}  emulatorTarget Target for emulator (rather than default)
+ * @param  {Boolean} autoProvisioning   Whether to allow Xcode to automatically update provisioning
+ * @return {Array}                  Array of arguments that could be passed directly to spawn method
+ */
+function getXcodeBuildArgs (projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget, autoProvisioning) {
+    var xcodebuildArgs;
+    var options;
+    var buildActions;
+    var settings;
+    var customArgs = {};
+    customArgs.otherFlags = [];
+
+    if (buildFlags) {
+        if (typeof buildFlags === 'string' || buildFlags instanceof String) {
+            parseBuildFlag(buildFlags, customArgs);
+        } else { // buildFlags is an Array of strings
+            buildFlags.forEach(function (flag) {
+                parseBuildFlag(flag, customArgs);
+            });
+        }
+    }
+
+    if (isDevice) {
+        options = [
+            '-workspace', customArgs.workspace || projectName + '.xcworkspace',
+            '-scheme', customArgs.scheme || projectName,
+            '-configuration', customArgs.configuration || configuration,
+            '-destination', customArgs.destination || 'generic/platform=iOS',
+            '-archivePath', customArgs.archivePath || projectName + '.xcarchive'
+        ];
+        buildActions = [ 'archive' ];
+        settings = [
+            customArgs.configuration_build_dir || 'CONFIGURATION_BUILD_DIR=' + path.join(projectPath, 'build', 'device'),
+            customArgs.shared_precomps_dir || 'SHARED_PRECOMPS_DIR=' + path.join(projectPath, 'build', 'sharedpch')
+        ];
+        // Add other matched flags to otherFlags to let xcodebuild present an appropriate error.
+        // This is preferable to just ignoring the flags that the user has passed in.
+        if (customArgs.sdk) {
+            customArgs.otherFlags = customArgs.otherFlags.concat(['-sdk', customArgs.sdk]);
+        }
+
+        if (autoProvisioning) {
+            options = options.concat(['-allowProvisioningUpdates']);
+        }
+    } else { // emulator
+        options = [
+            '-workspace', customArgs.project || projectName + '.xcworkspace',
+            '-scheme', customArgs.scheme || projectName,
+            '-configuration', customArgs.configuration || configuration,
+            '-sdk', customArgs.sdk || 'iphonesimulator',
+            '-destination', customArgs.destination || 'platform=iOS Simulator,name=' + emulatorTarget
+        ];
+        buildActions = [ 'build' ];
+        settings = [
+            customArgs.configuration_build_dir || 'CONFIGURATION_BUILD_DIR=' + path.join(projectPath, 'build', 'emulator'),
+            customArgs.shared_precomps_dir || 'SHARED_PRECOMPS_DIR=' + path.join(projectPath, 'build', 'sharedpch')
+        ];
+        // Add other matched flags to otherFlags to let xcodebuild present an appropriate error.
+        // This is preferable to just ignoring the flags that the user has passed in.
+        if (customArgs.archivePath) {
+            customArgs.otherFlags = customArgs.otherFlags.concat(['-archivePath', customArgs.archivePath]);
+        }
+    }
+    xcodebuildArgs = options.concat(buildActions).concat(settings).concat(customArgs.otherFlags);
+    return xcodebuildArgs;
+}
+
+/**
+ * Returns array of arguments for xcodebuild
+ * @param  {String}  projectName        Name of xcode project
+ * @param  {String}  projectPath        Path to project file. Will be used to set CWD for xcodebuild
+ * @param  {String}  outputPath         Output directory to contain the IPA
+ * @param  {String}  exportOptionsPath  Path to the exportOptions.plist file
+ * @param  {Boolean} autoProvisioning   Whether to allow Xcode to automatically update provisioning
+ * @return {Array}                      Array of arguments that could be passed directly to spawn method
+ */
+function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOptionsPath, autoProvisioning) {
+    return [
+        '-exportArchive',
+        '-archivePath', projectName + '.xcarchive',
+        '-exportOptionsPlist', exportOptionsPath,
+        '-exportPath', outputPath
+    ].concat(autoProvisioning ? ['-allowProvisioningUpdates'] : []);
+}
+
+function parseBuildFlag (buildFlag, args) {
+    var matched;
+    for (var key in buildFlagMatchers) {
+        var found = buildFlag.match(buildFlagMatchers[key]);
+        if (found) {
+            matched = true;
+            // found[0] is the whole match, found[1] is the first match in parentheses.
+            args[key] = found[1];
+            events.emit('warn', util.format('Overriding xcodebuildArg: %s', buildFlag));
+        }
+    }
+
+    if (!matched) {
+        // If the flag starts with a '-' then it is an xcodebuild built-in option or a
+        // user-defined setting. The regex makes sure that we don't split a user-defined
+        // setting that is wrapped in quotes.
+        /* eslint-disable no-useless-escape */
+        if (buildFlag[0] === '-' && !buildFlag.match(/^.*=(\".*\")|(\'.*\')$/)) {
+            args.otherFlags = args.otherFlags.concat(buildFlag.split(' '));
+            events.emit('warn', util.format('Adding xcodebuildArg: %s', buildFlag.split(' ')));
+        } else {
+            args.otherFlags.push(buildFlag);
+            events.emit('warn', util.format('Adding xcodebuildArg: %s', buildFlag));
+        }
+    }
+}
+
+// help/usage function
+module.exports.help = function help () {
+    console.log('');
+    console.log('Usage: build [--debug | --release] [--archs=\"<list of architectures...>\"]');
+    console.log('             [--device | --simulator] [--codeSignIdentity=\"<identity>\"]');
+    console.log('             [--codeSignResourceRules=\"<resourcerules path>\"]');
+    console.log('             [--developmentTeam=\"<Team ID>\"]');
+    console.log('             [--provisioningProfile=\"<provisioning profile>\"]');
+    console.log('    --help                  : Displays this dialog.');
+    console.log('    --debug                 : Builds project in debug mode. (Default)');
+    console.log('    --release               : Builds project in release mode.');
+    console.log('    -r                      : Shortcut :: builds project in release mode.');
+    /* eslint-enable no-useless-escape */
+    // TODO: add support for building different archs
+    // console.log("    --archs   : Builds project binaries for specific chip architectures (`anycpu`, `arm`, `x86`, `x64`).");
+    console.log('    --device, --simulator');
+    console.log('                            : Specifies, what type of project to build');
+    console.log('    --codeSignIdentity      : Type of signing identity used for code signing.');
+    console.log('    --codeSignResourceRules : Path to ResourceRules.plist.');
+    console.log('    --developmentTeam       : New for Xcode 8. The development team (Team ID)');
+    console.log('                              to use for code signing.');
+    console.log('    --provisioningProfile   : UUID of the profile.');
+    console.log('    --device --noSign       : Builds project without application signing.');
+    console.log('');
+    console.log('examples:');
+    console.log('    build ');
+    console.log('    build --debug');
+    console.log('    build --release');
+    console.log('    build --codeSignIdentity="iPhone Distribution" --provisioningProfile="926c2bd6-8de9-4c2f-8407-1016d2d12954"');
+    // TODO: add support for building different archs
+    // console.log("    build --release --archs=\"armv7\"");
+    console.log('');
+    process.exit(0);
+};
diff --git a/platforms/ios/cordova/lib/check_reqs.js b/platforms/ios/cordova/lib/check_reqs.js
new file mode 100755
index 0000000..85a0c3e
--- /dev/null
+++ b/platforms/ios/cordova/lib/check_reqs.js
@@ -0,0 +1,228 @@
+/*
+       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.
+*/
+
+'use strict';
+
+const Q = require('q');
+const shell = require('shelljs');
+const util = require('util');
+const versions = require('./versions');
+
+const SUPPORTED_OS_PLATFORMS = [ 'darwin' ];
+
+const XCODEBUILD_MIN_VERSION = '9.0.0';
+const XCODEBUILD_NOT_FOUND_MESSAGE =
+    'Please install version ' + XCODEBUILD_MIN_VERSION + ' or greater from App Store';
+
+const IOS_DEPLOY_MIN_VERSION = '1.9.2';
+const IOS_DEPLOY_NOT_FOUND_MESSAGE =
+    'Please download, build and install version ' + IOS_DEPLOY_MIN_VERSION + ' or greater' +
+    ' from https://github.com/ios-control/ios-deploy into your path, or do \'npm install -g ios-deploy\'';
+
+const COCOAPODS_MIN_VERSION = '1.0.1';
+const COCOAPODS_NOT_FOUND_MESSAGE =
+    'Please install version ' + COCOAPODS_MIN_VERSION + ' or greater from https://cocoapods.org/';
+const COCOAPODS_NOT_SYNCED_MESSAGE =
+    'The CocoaPods repo has not been synced yet, this will take a long time (approximately 500MB as of Sept 2016). Please run `pod setup` first to sync the repo.';
+const COCOAPODS_SYNCED_MIN_SIZE = 475; // in megabytes
+const COCOAPODS_SYNC_ERROR_MESSAGE =
+    'The CocoaPods repo has been created, but there appears to be a sync error. The repo size should be at least ' + COCOAPODS_SYNCED_MIN_SIZE + '. Please run `pod setup --verbose` to sync the repo.';
+const COCOAPODS_REPO_NOT_FOUND_MESSAGE = 'The CocoaPods repo at ~/.cocoapods was not found.';
+
+/**
+ * Checks if xcode util is available
+ * @return {Promise} Returns a promise either resolved with xcode version or rejected
+ */
+module.exports.run = module.exports.check_xcodebuild = function () {
+    return checkTool('xcodebuild', XCODEBUILD_MIN_VERSION, XCODEBUILD_NOT_FOUND_MESSAGE);
+};
+
+/**
+ * Checks if ios-deploy util is available
+ * @return {Promise} Returns a promise either resolved with ios-deploy version or rejected
+ */
+module.exports.check_ios_deploy = function () {
+    return checkTool('ios-deploy', IOS_DEPLOY_MIN_VERSION, IOS_DEPLOY_NOT_FOUND_MESSAGE);
+};
+
+module.exports.check_os = function () {
+    // Build iOS apps available for OSX platform only, so we reject on others platforms
+    return os_platform_is_supported() ?
+        Q.resolve(process.platform) :
+        Q.reject('Cordova tooling for iOS requires Apple macOS');
+};
+
+function os_platform_is_supported () {
+    return (SUPPORTED_OS_PLATFORMS.indexOf(process.platform) !== -1);
+}
+
+function check_cocoapod_tool (toolChecker) {
+    toolChecker = toolChecker || checkTool;
+    if (os_platform_is_supported()) { // CB-12856
+        return toolChecker('pod', COCOAPODS_MIN_VERSION, COCOAPODS_NOT_FOUND_MESSAGE, 'CocoaPods');
+    } else {
+        return Q.resolve({
+            'ignore': true,
+            'ignoreMessage': `CocoaPods check and installation ignored on ${process.platform}`
+        });
+    }
+}
+
+/**
+ * Checks if cocoapods repo size is what is expected
+ * @return {Promise} Returns a promise either resolved or rejected
+ */
+module.exports.check_cocoapods_repo_size = function () {
+    return check_cocoapod_tool()
+        .then(function (toolOptions) {
+            // check size of ~/.cocoapods repo
+            let commandString = util.format('du -sh %s/.cocoapods', process.env.HOME);
+            let command = shell.exec(commandString, { silent: true });
+            // command.output is e.g "750M   path/to/.cocoapods", we just scan the number
+            let size = toolOptions.ignore ? 0 : parseFloat(command.output);
+
+            if (toolOptions.ignore || command.code === 0) { // success, parse output
+                return Q.resolve(size, toolOptions);
+            } else { // error, perhaps not found
+                return Q.reject(util.format('%s (%s)', COCOAPODS_REPO_NOT_FOUND_MESSAGE, command.output));
+            }
+        })
+        .then(function (repoSize, toolOptions) {
+            if (toolOptions.ignore || COCOAPODS_SYNCED_MIN_SIZE <= repoSize) { // success, expected size
+                return Q.resolve(toolOptions);
+            } else {
+                return Q.reject(COCOAPODS_SYNC_ERROR_MESSAGE);
+            }
+        });
+};
+
+/**
+ * Checks if cocoapods is available, and whether the repo is synced (because it takes a long time to download)
+ * @return {Promise} Returns a promise either resolved or rejected
+ */
+module.exports.check_cocoapods = function (toolChecker) {
+    return check_cocoapod_tool(toolChecker)
+        // check whether the cocoapods repo has been synced through `pod repo` command
+        // a value of '0 repos' means it hasn't been synced
+        .then(function (toolOptions) {
+            let code = shell.exec('pod repo | grep -e "^0 repos"', { silent: true }).code;
+            let repoIsSynced = (code !== 0);
+
+            if (toolOptions.ignore || repoIsSynced) {
+                // return check_cocoapods_repo_size();
+                // we could check the repo size above, but it takes too long.
+                return Q.resolve(toolOptions);
+            } else {
+                return Q.reject(COCOAPODS_NOT_SYNCED_MESSAGE);
+            }
+        });
+};
+
+/**
+ * Checks if specific tool is available.
+ * @param  {String} tool       Tool name to check. Known tools are 'xcodebuild' and 'ios-deploy'
+ * @param  {Number} minVersion Min allowed tool version.
+ * @param  {String} message    Message that will be used to reject promise.
+ * @param  {String} toolFriendlyName  Friendly name of the tool, to report to the user. Optional.
+ * @return {Promise}           Returns a promise either resolved with tool version or rejected
+ */
+function checkTool (tool, minVersion, message, toolFriendlyName) {
+    toolFriendlyName = toolFriendlyName || tool;
+
+    // Check whether tool command is available at all
+    let tool_command = shell.which(tool);
+    if (!tool_command) {
+        return Q.reject(toolFriendlyName + ' was not found. ' + (message || ''));
+    }
+
+    // check if tool version is greater than specified one
+    return versions.get_tool_version(tool).then(function (version) {
+        version = version.trim();
+        return versions.compareVersions(version, minVersion) >= 0 ?
+            Q.resolve({ 'version': version }) :
+            Q.reject('Cordova needs ' + toolFriendlyName + ' version ' + minVersion +
+              ' or greater, you have version ' + version + '. ' + (message || ''));
+    });
+}
+
+/**
+ * Object that represents one of requirements for current platform.
+ * @param {String}  id        The unique identifier for this requirements.
+ * @param {String}  name      The name of requirements. Human-readable field.
+ * @param {Boolean} isFatal   Marks the requirement as fatal. If such requirement will fail
+ *                            next requirements' checks will be skipped.
+ */
+let Requirement = function (id, name, isFatal) {
+    this.id = id;
+    this.name = name;
+    this.installed = false;
+    this.metadata = {};
+    this.isFatal = isFatal || false;
+};
+
+/**
+ * Methods that runs all checks one by one and returns a result of checks
+ * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
+ *
+ * @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
+ */
+module.exports.check_all = function () {
+
+    const requirements = [
+        new Requirement('os', 'Apple macOS', true),
+        new Requirement('xcode', 'Xcode'),
+        new Requirement('ios-deploy', 'ios-deploy'),
+        new Requirement('CocoaPods', 'CocoaPods')
+    ];
+
+    let result = [];
+    let fatalIsHit = false;
+
+    let checkFns = [
+        module.exports.check_os,
+        module.exports.check_xcodebuild,
+        module.exports.check_ios_deploy,
+        module.exports.check_cocoapods
+    ];
+
+    // Then execute requirement checks one-by-one
+    return checkFns.reduce(function (promise, checkFn, idx) {
+        return promise.then(function () {
+            // If fatal requirement is failed,
+            // we don't need to check others
+            if (fatalIsHit) return Q();
+
+            let requirement = requirements[idx];
+            return checkFn()
+                .then(function (version) {
+                    requirement.installed = true;
+                    requirement.metadata.version = version;
+                    result.push(requirement);
+                }, function (err) {
+                    if (requirement.isFatal) fatalIsHit = true;
+                    requirement.metadata.reason = err;
+                    result.push(requirement);
+                });
+        });
+    }, Q())
+        .then(function () {
+            // When chain is completed, return requirements array to upstream API
+            return result;
+        });
+};
diff --git a/platforms/ios/cordova/lib/clean.js b/platforms/ios/cordova/lib/clean.js
new file mode 100755
index 0000000..e5c24a5
--- /dev/null
+++ b/platforms/ios/cordova/lib/clean.js
@@ -0,0 +1,42 @@
+/**
+ * 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.
+ */
+
+var Q = require('q');
+var path = require('path');
+var shell = require('shelljs');
+var superspawn = require('cordova-common').superspawn;
+
+var projectPath = path.join(__dirname, '..', '..');
+
+module.exports.run = function () {
+    var projectName = shell.ls(projectPath).filter(function (name) {
+        return path.extname(name) === '.xcodeproj';
+    })[0];
+
+    if (!projectName) {
+        return Q.reject('No Xcode project found in ' + projectPath);
+    }
+
+    return superspawn.spawn('xcodebuild', ['-project', projectName, '-configuration', 'Debug', '-alltargets', 'clean'], { cwd: projectPath, printCommand: true, stdio: 'inherit' })
+        .then(function () {
+            return superspawn.spawn('xcodebuild', ['-project', projectName, '-configuration', 'Release', '-alltargets', 'clean'], { cwd: projectPath, printCommand: true, stdio: 'inherit' });
+        }).then(function () {
+            return shell.rm('-rf', path.join(projectPath, 'build'));
+        });
+};
diff --git a/platforms/ios/cordova/lib/list-devices b/platforms/ios/cordova/lib/list-devices
new file mode 100755
index 0000000..528934a
--- /dev/null
+++ b/platforms/ios/cordova/lib/list-devices
@@ -0,0 +1,67 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var Q = require('q'),
+    exec = require('child_process').exec;
+
+/**
+ * Gets list of connected iOS devices
+ * @return {Promise} Promise fulfilled with list of available iOS devices
+ */
+function listDevices() {
+    var commands = [
+        Q.nfcall(exec, "ioreg -p IOUSB -l | sed -n -e '/iPad/,/USB Serial Number/p' | grep 'Serial Number' | awk -F\\\" '{print $4 \" iPad\"}'"),
+        Q.nfcall(exec, "ioreg -p IOUSB -l | sed -n -e '/iPhone/,/USB Serial Number/p' | grep 'Serial Number' | awk -F\\\" '{print $4 \" iPhone\"}'"),
+        Q.nfcall(exec, "ioreg -p IOUSB -l | sed -n -e '/iPod/,/USB Serial Number/p' | grep 'Serial Number' | awk -F\\\" '{print $4 \" iPod\"}'"),
+    ];
+
+    // wrap al lexec calls into promises and wait until they're fullfilled
+    return Q.all(commands).then(function (results) {
+        var accumulator = [];
+        results.forEach(function (result) {
+          var devicefound;
+          // Each command promise resolves with array [stout, stderr], and we need stdout only
+          // Append stdout lines to accumulator
+          devicefound = result[0].trim().split('\n');
+          if(devicefound && devicefound.length) {
+            devicefound.forEach(function(device) {
+              if (device) {
+                accumulator.push(device);
+              }
+            });
+          }
+        });
+        return accumulator;
+    });
+}
+
+exports.run = listDevices;
+
+// Check if module is started as separate script.
+// If so, then invoke main method and print out results.
+if (!module.parent) {
+    listDevices().then(function (devices) {
+        devices.forEach(function (device) {
+            console.log(device);
+        });
+    });
+}
\ No newline at end of file
diff --git a/platforms/ios/cordova/lib/list-emulator-build-targets b/platforms/ios/cordova/lib/list-emulator-build-targets
new file mode 100755
index 0000000..8f1ffab
--- /dev/null
+++ b/platforms/ios/cordova/lib/list-emulator-build-targets
@@ -0,0 +1,109 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var Q = require('q'),
+    exec = require('child_process').exec;
+
+/**
+ * Returns a list of available simulator build targets of the form
+ * 
+ *     [
+ *         { name: <xcode-destination-name>,
+ *           identifier: <simctl-identifier>,
+ *           simIdentifier: <cordova emulate target>
+ *         }
+ *     ]
+ * 
+ */
+function listEmulatorBuildTargets () {
+    return Q.nfcall(exec, 'xcrun simctl list --json')
+    .then(function(stdio) {
+        return JSON.parse(stdio[0]);
+    })
+    .then(function(simInfo) {
+        var devices = simInfo.devices;
+        var deviceTypes = simInfo.devicetypes;
+        return deviceTypes.reduce(function (typeAcc, deviceType) {
+            if (!deviceType.name.match(/^[iPad|iPhone]/)) {
+                // ignore targets we don't support (like Apple Watch or Apple TV)
+                return typeAcc;
+            }
+            var availableDevices = Object.keys(devices).reduce(function (availAcc, deviceCategory) {
+                var availableDevicesInCategory = devices[deviceCategory];
+                availableDevicesInCategory.forEach(function (device) {
+                    if (device.name === deviceType.name || device.name === deviceType.name.replace(/\-inch/g, ' inch')) {
+                        // Check new flag isAvailable (XCode 10.1+) or legacy string availability (XCode 10 and lower)
+                        if (device.isAvailable || (device.availability && device.availability.toLowerCase().indexOf('unavailable') < 0)) {
+                            availAcc.push(device);
+                        }
+                    } 
+                });
+                return availAcc;
+            }, []);
+            // we only want device types that have at least one available device
+            // (regardless of OS); this filters things out like iPhone 4s, which
+            // is present in deviceTypes, but probably not available on the user's
+            // system.
+            if (availableDevices.length > 0) {
+                typeAcc.push(deviceType);
+            }
+            return typeAcc;
+        }, []);
+    })
+    .then(function(filteredTargets) {
+        // the simIdentifier, or cordova emulate target name, is the very last part
+        // of identifier.
+        return filteredTargets.map(function (target) {
+            var identifierPieces = target.identifier.split(".");
+            target.simIdentifier = identifierPieces[identifierPieces.length-1];
+            return target;
+        });
+    });
+}
+
+exports.run = listEmulatorBuildTargets;
+
+/**
+ * Given a simIdentifier, return the matching target.
+ * 
+ * @param {string} simIdentifier       a target, like "iPhone-SE"
+ * @return {Object}                    the matching target, or undefined if no match
+ */
+exports.targetForSimIdentifier = function(simIdentifier) {
+    return listEmulatorBuildTargets()
+    .then(function(targets) {
+        return targets.reduce(function(acc, target) {
+            if (!acc && target.simIdentifier.toLowerCase() === simIdentifier.toLowerCase()) {
+                acc = target;
+            }
+            return acc;
+        }, undefined);
+    });
+}
+
+// Check if module is started as separate script.
+// If so, then invoke main method and print out results.
+if (!module.parent) {
+    listEmulatorBuildTargets().then(function (targets) {
+        console.log(JSON.stringify(targets, null, 2));
+    });
+}
diff --git a/platforms/ios/cordova/lib/list-emulator-images b/platforms/ios/cordova/lib/list-emulator-images
new file mode 100755
index 0000000..d8be576
--- /dev/null
+++ b/platforms/ios/cordova/lib/list-emulator-images
@@ -0,0 +1,47 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var Q = require('q'),
+    iossim = require('ios-sim'),
+    exec = require('child_process').exec,
+    check_reqs = require('./check_reqs');
+
+/**
+ * Gets list of iOS devices available for simulation
+ * @return {Promise} Promise fulfilled with list of devices available for simulation
+ */
+function listEmulatorImages () {
+    return Q.resolve(iossim.getdevicetypes());
+}
+
+
+exports.run = listEmulatorImages;
+
+// Check if module is started as separate script.
+// If so, then invoke main method and print out results.
+if (!module.parent) {
+    listEmulatorImages().then(function (names) {
+        names.forEach(function (name) {
+            console.log(name);
+        });
+    });
+}
diff --git a/platforms/ios/cordova/lib/list-started-emulators b/platforms/ios/cordova/lib/list-started-emulators
new file mode 100755
index 0000000..710fa2f
--- /dev/null
+++ b/platforms/ios/cordova/lib/list-started-emulators
@@ -0,0 +1,50 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var Q = require('q'),
+    exec = require('child_process').exec;
+
+/**
+ * Gets list of running iOS simulators
+ * @return {Promise} Promise fulfilled with list of running iOS simulators
+ */
+function listStartedEmulators () {
+    // wrap exec call into promise
+    return Q.nfcall(exec, 'ps aux | grep -i "[i]OS Simulator"')
+    .then(function () {
+        return Q.nfcall(exec, 'defaults read com.apple.iphonesimulator "SimulateDevice"');
+    }).then(function (stdio) {
+        return stdio[0].trim().split('\n');
+    });
+}
+
+exports.run = listStartedEmulators;
+
+// Check if module is started as separate script.
+// If so, then invoke main method and print out results.
+if (!module.parent) {
+    listStartedEmulators().then(function (emulators) {
+        emulators.forEach(function (emulator) {
+            console.log(emulator);
+        });
+    });
+}
diff --git a/platforms/ios/cordova/lib/plugman/pluginHandlers.js b/platforms/ios/cordova/lib/plugman/pluginHandlers.js
new file mode 100755
index 0000000..bd9d853
--- /dev/null
+++ b/platforms/ios/cordova/lib/plugman/pluginHandlers.js
@@ -0,0 +1,391 @@
+/*
+       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.
+*/
+'use strict';
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var util = require('util');
+var events = require('cordova-common').events;
+var CordovaError = require('cordova-common').CordovaError;
+
+// These frameworks are required by cordova-ios by default. We should never add/remove them.
+var keep_these_frameworks = [
+    'MobileCoreServices.framework',
+    'CoreGraphics.framework',
+    'AssetsLibrary.framework'
+];
+
+var handlers = {
+    'source-file': {
+        install: function (obj, plugin, project, options) {
+            installHelper('source-file', obj, plugin.dir, project.projectDir, plugin.id, options, project);
+        },
+        uninstall: function (obj, plugin, project, options) {
+            uninstallHelper('source-file', obj, project.projectDir, plugin.id, options, project);
+        }
+    },
+    'header-file': {
+        install: function (obj, plugin, project, options) {
+            installHelper('header-file', obj, plugin.dir, project.projectDir, plugin.id, options, project);
+        },
+        uninstall: function (obj, plugin, project, options) {
+            uninstallHelper('header-file', obj, project.projectDir, plugin.id, options, project);
+        }
+    },
+    'resource-file': {
+        install: function (obj, plugin, project, options) {
+            var src = obj.src;
+            var target = obj.target;
+            var srcFile = path.resolve(plugin.dir, src);
+
+            if (!target) {
+                target = path.basename(src);
+            }
+            var destFile = path.resolve(project.resources_dir, target);
+
+            if (!fs.existsSync(srcFile)) {
+                throw new CordovaError('Cannot find resource file "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
+            }
+            if (fs.existsSync(destFile)) {
+                throw new CordovaError('File already exists at destination "' + destFile + '" for resource file specified by plugin ' + plugin.id + ' in iOS platform');
+            }
+            project.xcode.addResourceFile(path.join('Resources', target));
+            var link = !!(options && options.link);
+            copyFile(plugin.dir, src, project.projectDir, destFile, link);
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var src = obj.src;
+            var target = obj.target;
+
+            if (!target) {
+                target = path.basename(src);
+            }
+            var destFile = path.resolve(project.resources_dir, target);
+
+            project.xcode.removeResourceFile(path.join('Resources', target));
+            shell.rm('-rf', destFile);
+        }
+    },
+    'framework': { // CB-5238 custom frameworks only
+        install: function (obj, plugin, project, options) {
+            var src = obj.src;
+            var custom = !!(obj.custom); // convert to boolean (if truthy/falsy)
+            var embed = !!(obj.embed); // convert to boolean (if truthy/falsy)
+            var link = !embed; // either link or embed can be true, but not both. the other has to be false
+
+            if (!custom) {
+                var keepFrameworks = keep_these_frameworks;
+
+                if (keepFrameworks.indexOf(src) < 0) {
+                    if (obj.type === 'podspec') {
+                        // podspec handled in Api.js
+                    } else {
+                        project.frameworks[src] = project.frameworks[src] || 0;
+                        project.frameworks[src]++;
+                        let opt = { customFramework: false, embed: false, link: true, weak: obj.weak };
+                        events.emit('verbose', util.format('Adding non-custom framework to project... %s -> %s', src, JSON.stringify(opt)));
+                        project.xcode.addFramework(src, opt);
+                        events.emit('verbose', util.format('Non-custom framework added to project. %s -> %s', src, JSON.stringify(opt)));
+                    }
+                }
+                return;
+            }
+            var srcFile = path.resolve(plugin.dir, src);
+            var targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src));
+            if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find framework "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
+            if (fs.existsSync(targetDir)) throw new CordovaError('Framework "' + targetDir + '" for plugin ' + plugin.id + ' already exists in iOS platform');
+            var symlink = !!(options && options.link);
+            copyFile(plugin.dir, src, project.projectDir, targetDir, symlink); // frameworks are directories
+            // CB-10773 translate back slashes to forward on win32
+            var project_relative = fixPathSep(path.relative(project.projectDir, targetDir));
+            // CB-11233 create Embed Frameworks Build Phase if does not exist
+            var existsEmbedFrameworks = project.xcode.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Frameworks');
+            if (!existsEmbedFrameworks && embed) {
+                events.emit('verbose', '"Embed Frameworks" Build Phase (Embedded Binaries) does not exist, creating it.');
+                project.xcode.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Embed Frameworks', null, 'frameworks');
+            }
+            let opt = { customFramework: true, embed: embed, link: link, sign: true };
+            events.emit('verbose', util.format('Adding custom framework to project... %s -> %s', src, JSON.stringify(opt)));
+            project.xcode.addFramework(project_relative, opt);
+            events.emit('verbose', util.format('Custom framework added to project. %s -> %s', src, JSON.stringify(opt)));
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var src = obj.src;
+
+            if (!obj.custom) { // CB-9825 cocoapod integration for plugins
+                var keepFrameworks = keep_these_frameworks;
+                if (keepFrameworks.indexOf(src) < 0) {
+                    if (obj.type !== 'podspec') {
+                        // this should be refactored
+                        project.frameworks[src] = project.frameworks[src] || 1;
+                        project.frameworks[src]--;
+                        if (project.frameworks[src] < 1) {
+                            // Only remove non-custom framework from xcode project
+                            // if there is no references remains
+                            project.xcode.removeFramework(src);
+                            delete project.frameworks[src];
+                        }
+                    }
+                }
+                return;
+            }
+
+            var targetDir = fixPathSep(path.resolve(project.plugins_dir, plugin.id, path.basename(src)));
+            var pbxFile = project.xcode.removeFramework(targetDir, { customFramework: true });
+            if (pbxFile) {
+                project.xcode.removeFromPbxEmbedFrameworksBuildPhase(pbxFile);
+            }
+            shell.rm('-rf', targetDir);
+        }
+    },
+    'lib-file': {
+        install: function (obj, plugin, project, options) {
+            events.emit('verbose', '<lib-file> install is not supported for iOS plugins');
+        },
+        uninstall: function (obj, plugin, project, options) {
+            events.emit('verbose', '<lib-file> uninstall is not supported for iOS plugins');
+        }
+    },
+    'asset': {
+        install: function (obj, plugin, project, options) {
+            if (!obj.src) {
+                throw new CordovaError(generateAttributeError('src', 'asset', plugin.id));
+            }
+            if (!obj.target) {
+                throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
+            }
+
+            copyFile(plugin.dir, obj.src, project.www, obj.target);
+            if (options && options.usePlatformWww) copyFile(plugin.dir, obj.src, project.platformWww, obj.target);
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var target = obj.target;
+
+            if (!target) {
+                throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
+            }
+
+            removeFile(project.www, target);
+            removeFileF(path.resolve(project.www, 'plugins', plugin.id));
+            if (options && options.usePlatformWww) {
+                removeFile(project.platformWww, target);
+                removeFileF(path.resolve(project.platformWww, 'plugins', plugin.id));
+            }
+        }
+    },
+    'js-module': {
+        install: function (obj, plugin, project, options) {
+            // Copy the plugin's files into the www directory.
+            var moduleSource = path.resolve(plugin.dir, obj.src);
+            var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
+
+            // Read in the file, prepend the cordova.define, and write it back out.
+            var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+            if (moduleSource.match(/.*\.json$/)) {
+                scriptContent = 'module.exports = ' + scriptContent;
+            }
+            scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
+
+            var moduleDestination = path.resolve(project.www, 'plugins', plugin.id, obj.src);
+            shell.mkdir('-p', path.dirname(moduleDestination));
+            fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+            if (options && options.usePlatformWww) {
+                var platformWwwDestination = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
+                shell.mkdir('-p', path.dirname(platformWwwDestination));
+                fs.writeFileSync(platformWwwDestination, scriptContent, 'utf-8');
+            }
+        },
+        uninstall: function (obj, plugin, project, options) {
+            var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
+            removeFileAndParents(project.www, pluginRelativePath);
+            if (options && options.usePlatformWww) removeFileAndParents(project.platformWww, pluginRelativePath);
+        }
+    }
+};
+
+module.exports.getInstaller = function (type) {
+    if (handlers[type] && handlers[type].install) {
+        return handlers[type].install;
+    }
+
+    events.emit('warn', '<' + type + '> is not supported for iOS plugins');
+};
+
+module.exports.getUninstaller = function (type) {
+    if (handlers[type] && handlers[type].uninstall) {
+        return handlers[type].uninstall;
+    }
+
+    events.emit('warn', '<' + type + '> is not supported for iOS plugins');
+};
+
+function installHelper (type, obj, plugin_dir, project_dir, plugin_id, options, project) {
+    var srcFile = path.resolve(plugin_dir, obj.src);
+    var targetDir = path.resolve(project.plugins_dir, plugin_id, obj.targetDir || '');
+    var destFile = path.join(targetDir, path.basename(obj.src));
+
+    var project_ref;
+    var link = !!(options && options.link);
+    if (link) {
+        var trueSrc = fs.realpathSync(srcFile);
+        // Create a symlink in the expected place, so that uninstall can use it.
+        if (options && options.force) {
+            copyFile(plugin_dir, trueSrc, project_dir, destFile, link);
+        } else {
+            copyNewFile(plugin_dir, trueSrc, project_dir, destFile, link);
+        }
+        // Xcode won't save changes to a file if there is a symlink involved.
+        // Make the Xcode reference the file directly.
+        // Note: Can't use path.join() here since it collapses 'Plugins/..', and xcode
+        // library special-cases Plugins/ prefix.
+        project_ref = 'Plugins/' + fixPathSep(path.relative(fs.realpathSync(project.plugins_dir), trueSrc));
+    } else {
+        if (options && options.force) {
+            copyFile(plugin_dir, srcFile, project_dir, destFile, link);
+        } else {
+            copyNewFile(plugin_dir, srcFile, project_dir, destFile, link);
+        }
+        project_ref = 'Plugins/' + fixPathSep(path.relative(project.plugins_dir, destFile));
+    }
+
+    if (type === 'header-file') {
+        project.xcode.addHeaderFile(project_ref);
+    } else if (obj.framework) {
+        var opt = { weak: obj.weak };
+        var project_relative = path.join(path.basename(project.xcode_path), project_ref);
+        project.xcode.addFramework(project_relative, opt);
+        project.xcode.addToLibrarySearchPaths({ path: project_ref });
+    } else {
+        project.xcode.addSourceFile(project_ref, obj.compilerFlags ? { compilerFlags: obj.compilerFlags } : {});
+    }
+}
+
+function uninstallHelper (type, obj, project_dir, plugin_id, options, project) {
+    var targetDir = path.resolve(project.plugins_dir, plugin_id, obj.targetDir || '');
+    var destFile = path.join(targetDir, path.basename(obj.src));
+
+    var project_ref;
+    var link = !!(options && options.link);
+    if (link) {
+        var trueSrc = fs.readlinkSync(destFile);
+        project_ref = 'Plugins/' + fixPathSep(path.relative(fs.realpathSync(project.plugins_dir), trueSrc));
+    } else {
+        project_ref = 'Plugins/' + fixPathSep(path.relative(project.plugins_dir, destFile));
+    }
+
+    shell.rm('-rf', targetDir);
+
+    if (type === 'header-file') {
+        project.xcode.removeHeaderFile(project_ref);
+    } else if (obj.framework) {
+        var project_relative = path.join(path.basename(project.xcode_path), project_ref);
+        project.xcode.removeFramework(project_relative);
+        project.xcode.removeFromLibrarySearchPaths({ path: project_ref });
+    } else {
+        project.xcode.removeSourceFile(project_ref);
+    }
+}
+
+var pathSepFix = new RegExp(path.sep.replace(/\\/, '\\\\'), 'g');
+function fixPathSep (file) {
+    return file.replace(pathSepFix, '/');
+}
+
+function copyFile (plugin_dir, src, project_dir, dest, link) {
+    src = path.resolve(plugin_dir, src);
+    if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
+
+    // check that src path is inside plugin directory
+    var real_path = fs.realpathSync(src);
+    var real_plugin_path = fs.realpathSync(plugin_dir);
+    if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
+
+    dest = path.resolve(project_dir, dest);
+
+    // check that dest path is located in project directory
+    if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
+
+    shell.mkdir('-p', path.dirname(dest));
+
+    if (link) {
+        linkFileOrDirTree(src, dest);
+    } else if (fs.statSync(src).isDirectory()) {
+        // XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
+        shell.cp('-Rf', path.join(src, '/*'), dest);
+    } else {
+        shell.cp('-f', src, dest);
+    }
+}
+
+// Same as copy file but throws error if target exists
+function copyNewFile (plugin_dir, src, project_dir, dest, link) {
+    var target_path = path.resolve(project_dir, dest);
+    if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
+
+    copyFile(plugin_dir, src, project_dir, dest, !!link);
+}
+
+function linkFileOrDirTree (src, dest) {
+    if (fs.existsSync(dest)) {
+        shell.rm('-Rf', dest);
+    }
+
+    if (fs.statSync(src).isDirectory()) {
+        shell.mkdir('-p', dest);
+        fs.readdirSync(src).forEach(function (entry) {
+            linkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
+        });
+    } else {
+        fs.linkSync(src, dest);
+    }
+}
+
+// checks if file exists and then deletes. Error if doesn't exist
+function removeFile (project_dir, src) {
+    var file = path.resolve(project_dir, src);
+    shell.rm('-Rf', file);
+}
+
+// deletes file/directory without checking
+function removeFileF (file) {
+    shell.rm('-Rf', file);
+}
+
+function removeFileAndParents (baseDir, destFile, stopper) {
+    stopper = stopper || '.';
+    var file = path.resolve(baseDir, destFile);
+    if (!fs.existsSync(file)) return;
+
+    removeFileF(file);
+
+    // check if directory is empty
+    var curDir = path.dirname(file);
+
+    while (curDir !== path.resolve(baseDir, stopper)) {
+        if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
+            fs.rmdirSync(curDir);
+            curDir = path.resolve(curDir, '..');
+        } else {
+            // directory not empty...do nothing
+            break;
+        }
+    }
+}
+
+function generateAttributeError (attribute, element, id) {
+    return 'Required attribute "' + attribute + '" not specified in <' + element + '> element from plugin: ' + id;
+}
diff --git a/platforms/ios/cordova/lib/prepare.js b/platforms/ios/cordova/lib/prepare.js
new file mode 100755
index 0000000..a15380e
--- /dev/null
+++ b/platforms/ios/cordova/lib/prepare.js
@@ -0,0 +1,1172 @@
+/**
+    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.
+*/
+
+'use strict';
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var unorm = require('unorm');
+var plist = require('plist');
+var URL = require('url');
+var events = require('cordova-common').events;
+var xmlHelpers = require('cordova-common').xmlHelpers;
+var ConfigParser = require('cordova-common').ConfigParser;
+var CordovaError = require('cordova-common').CordovaError;
+var PlatformJson = require('cordova-common').PlatformJson;
+var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
+var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
+var FileUpdater = require('cordova-common').FileUpdater;
+var projectFile = require('./projectFile');
+
+// launch storyboard and related constants
+var LAUNCHIMAGE_BUILD_SETTING = 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME';
+var LAUNCHIMAGE_BUILD_SETTING_VALUE = 'LaunchImage';
+var UI_LAUNCH_STORYBOARD_NAME = 'UILaunchStoryboardName';
+var CDV_LAUNCH_STORYBOARD_NAME = 'CDVLaunchScreen';
+var IMAGESET_COMPACT_SIZE_CLASS = 'compact';
+var CDV_ANY_SIZE_CLASS = 'any';
+
+module.exports.prepare = function (cordovaProject, options) {
+    var self = this;
+
+    var platformJson = PlatformJson.load(this.locations.root, 'ios');
+    var munger = new PlatformMunger('ios', this.locations.root, platformJson, new PluginInfoProvider());
+
+    this._config = updateConfigFile(cordovaProject.projectConfig, munger, this.locations);
+
+    // Update own www dir with project's www assets and plugins' assets and js-files
+    return Q.when(updateWww(cordovaProject, this.locations))
+        .then(function () {
+            // update project according to config.xml changes.
+            return updateProject(self._config, self.locations);
+        })
+        .then(function () {
+            updateIcons(cordovaProject, self.locations);
+            updateSplashScreens(cordovaProject, self.locations);
+            updateLaunchStoryboardImages(cordovaProject, self.locations);
+            updateFileResources(cordovaProject, self.locations);
+        })
+        .then(function () {
+            events.emit('verbose', 'Prepared iOS project successfully');
+        });
+};
+
+module.exports.clean = function (options) {
+    // A cordovaProject isn't passed into the clean() function, because it might have
+    // been called from the platform shell script rather than the CLI. Check for the
+    // noPrepare option passed in by the non-CLI clean script. If that's present, or if
+    // there's no config.xml found at the project root, then don't clean prepared files.
+    var projectRoot = path.resolve(this.root, '../..');
+    var projectConfigFile = path.join(projectRoot, 'config.xml');
+    if ((options && options.noPrepare) || !fs.existsSync(projectConfigFile) ||
+            !fs.existsSync(this.locations.configXml)) {
+        return Q();
+    }
+
+    var projectConfig = new ConfigParser(this.locations.configXml);
+
+    var self = this;
+    return Q().then(function () {
+        cleanWww(projectRoot, self.locations);
+        cleanIcons(projectRoot, projectConfig, self.locations);
+        cleanSplashScreens(projectRoot, projectConfig, self.locations);
+        cleanLaunchStoryboardImages(projectRoot, projectConfig, self.locations);
+        cleanFileResources(projectRoot, projectConfig, self.locations);
+    });
+};
+
+/**
+ * Updates config files in project based on app's config.xml and config munge,
+ *   generated by plugins.
+ *
+ * @param   {ConfigParser}   sourceConfig  A project's configuration that will
+ *   be merged into platform's config.xml
+ * @param   {ConfigChanges}  configMunger  An initialized ConfigChanges instance
+ *   for this platform.
+ * @param   {Object}         locations     A map of locations for this platform
+ *
+ * @return  {ConfigParser}                 An instance of ConfigParser, that
+ *   represents current project's configuration. When returned, the
+ *   configuration is already dumped to appropriate config.xml file.
+ */
+function updateConfigFile (sourceConfig, configMunger, locations) {
+    events.emit('verbose', 'Generating platform-specific config.xml from defaults for iOS at ' + locations.configXml);
+
+    // First cleanup current config and merge project's one into own
+    // Overwrite platform config.xml with defaults.xml.
+    shell.cp('-f', locations.defaultConfigXml, locations.configXml);
+
+    // Then apply config changes from global munge to all config files
+    // in project (including project's config)
+    configMunger.reapply_global_munge().save_all();
+
+    events.emit('verbose', 'Merging project\'s config.xml into platform-specific iOS config.xml');
+    // Merge changes from app's config.xml into platform's one
+    var config = new ConfigParser(locations.configXml);
+    xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
+        config.doc.getroot(), 'ios', /* clobber= */true);
+
+    config.write();
+    return config;
+}
+
+/**
+ * Logs all file operations via the verbose event stream, indented.
+ */
+function logFileOp (message) {
+    events.emit('verbose', '  ' + message);
+}
+
+/**
+ * Updates platform 'www' directory by replacing it with contents of
+ *   'platform_www' and app www. Also copies project's overrides' folder into
+ *   the platform 'www' folder
+ *
+ * @param   {Object}  cordovaProject   An object which describes cordova project.
+ * @param   {boolean} destinations     An object that contains destinations
+ *   paths for www files.
+ */
+function updateWww (cordovaProject, destinations) {
+    var sourceDirs = [
+        path.relative(cordovaProject.root, cordovaProject.locations.www),
+        path.relative(cordovaProject.root, destinations.platformWww)
+    ];
+
+    // If project contains 'merges' for our platform, use them as another overrides
+    var merges_path = path.join(cordovaProject.root, 'merges', 'ios');
+    if (fs.existsSync(merges_path)) {
+        events.emit('verbose', 'Found "merges/ios" folder. Copying its contents into the iOS project.');
+        sourceDirs.push(path.join('merges', 'ios'));
+    }
+
+    var targetDir = path.relative(cordovaProject.root, destinations.www);
+    events.emit(
+        'verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
+    FileUpdater.mergeAndUpdateDir(
+        sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+/**
+ * Cleans all files from the platform 'www' directory.
+ */
+function cleanWww (projectRoot, locations) {
+    var targetDir = path.relative(projectRoot, locations.www);
+    events.emit('verbose', 'Cleaning ' + targetDir);
+
+    // No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
+    FileUpdater.mergeAndUpdateDir(
+        [], targetDir, { rootDir: projectRoot, all: true }, logFileOp);
+}
+
+/**
+ * Updates project structure and AndroidManifest according to project's configuration.
+ *
+ * @param   {ConfigParser}  platformConfig  A project's configuration that will
+ *   be used to update project
+ * @param   {Object}  locations       A map of locations for this platform (In/Out)
+ */
+function updateProject (platformConfig, locations) {
+
+    // CB-6992 it is necessary to normalize characters
+    // because node and shell scripts handles unicode symbols differently
+    // We need to normalize the name to NFD form since iOS uses NFD unicode form
+    var name = unorm.nfd(platformConfig.name());
+    var version = platformConfig.version();
+    var displayName = platformConfig.shortName && platformConfig.shortName();
+
+    var originalName = path.basename(locations.xcodeCordovaProj);
+
+    // Update package id (bundle id)
+    var plistFile = path.join(locations.xcodeCordovaProj, originalName + '-Info.plist');
+    var infoPlist = plist.parse(fs.readFileSync(plistFile, 'utf8'));
+
+    // Update version (bundle version)
+    infoPlist['CFBundleShortVersionString'] = version;
+    var CFBundleVersion = platformConfig.getAttribute('ios-CFBundleVersion') || default_CFBundleVersion(version);
+    infoPlist['CFBundleVersion'] = CFBundleVersion;
+
+    if (platformConfig.getAttribute('defaultlocale')) {
+        infoPlist['CFBundleDevelopmentRegion'] = platformConfig.getAttribute('defaultlocale');
+    }
+
+    if (displayName) {
+        infoPlist['CFBundleDisplayName'] = displayName;
+    }
+
+    // replace Info.plist ATS entries according to <access> and <allow-navigation> config.xml entries
+    var ats = writeATSEntries(platformConfig);
+    if (Object.keys(ats).length > 0) {
+        infoPlist['NSAppTransportSecurity'] = ats;
+    } else {
+        delete infoPlist['NSAppTransportSecurity'];
+    }
+
+    handleOrientationSettings(platformConfig, infoPlist);
+    updateProjectPlistForLaunchStoryboard(platformConfig, infoPlist);
+
+    /* eslint-disable no-tabs */
+    // Write out the plist file with the same formatting as Xcode does
+    var info_contents = plist.build(infoPlist, { indent: '	', offset: -1 });
+    /* eslint-enable no-tabs */
+
+    info_contents = info_contents.replace(/<string>[\s\r\n]*<\/string>/g, '<string></string>');
+    fs.writeFileSync(plistFile, info_contents, 'utf-8');
+    events.emit('verbose', 'Wrote out iOS Bundle Version "' + version + '" to ' + plistFile);
+
+    return handleBuildSettings(platformConfig, locations, infoPlist).then(function () {
+        if (name === originalName) {
+            events.emit('verbose', 'iOS Product Name has not changed (still "' + originalName + '")');
+            return Q();
+        } else { // CB-11712 <name> was changed, we don't support it'
+            var errorString =
+            'The product name change (<name> tag) in config.xml is not supported dynamically.\n' +
+            'To change your product name, you have to remove, then add your ios platform again.\n' +
+            'Make sure you save your plugins beforehand using `cordova plugin save`.\n' +
+            '\tcordova plugin save\n' +
+            '\tcordova platform rm ios\n' +
+            '\tcordova platform add ios\n'
+            ;
+
+            return Q.reject(new CordovaError(errorString));
+        }
+    });
+}
+
+function handleOrientationSettings (platformConfig, infoPlist) {
+
+    switch (getOrientationValue(platformConfig)) {
+    case 'portrait':
+        infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ];
+        infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ];
+        infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown' ];
+        break;
+    case 'landscape':
+        infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationLandscapeLeft' ];
+        infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        break;
+    case 'all':
+        infoPlist['UIInterfaceOrientation'] = [ 'UIInterfaceOrientationPortrait' ];
+        infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        break;
+    case 'default':
+        infoPlist['UISupportedInterfaceOrientations'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        infoPlist['UISupportedInterfaceOrientations~ipad'] = [ 'UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight' ];
+        delete infoPlist['UIInterfaceOrientation'];
+    }
+}
+
+function handleBuildSettings (platformConfig, locations, infoPlist) {
+    var pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName();
+    var targetDevice = parseTargetDevicePreference(platformConfig.getPreference('target-device', 'ios'));
+    var deploymentTarget = platformConfig.getPreference('deployment-target', 'ios');
+    var needUpdatedBuildSettingsForLaunchStoryboard = checkIfBuildSettingsNeedUpdatedForLaunchStoryboard(platformConfig, infoPlist);
+    var swiftVersion = platformConfig.getPreference('SwiftVersion', 'ios');
+
+    var project;
+
+    try {
+        project = projectFile.parse(locations);
+    } catch (err) {
+        return Q.reject(new CordovaError('Could not parse ' + locations.pbxproj + ': ' + err));
+    }
+
+    var origPkg = project.xcode.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER');
+
+    // no build settings provided and we don't need to update build settings for launch storyboards,
+    // then we don't need to parse and update .pbxproj file
+    if (origPkg === pkg && !targetDevice && !deploymentTarget && !needUpdatedBuildSettingsForLaunchStoryboard && !swiftVersion) {
+        return Q();
+    }
+
+    if (origPkg !== pkg) {
+        events.emit('verbose', 'Set PRODUCT_BUNDLE_IDENTIFIER to ' + pkg + '.');
+        project.xcode.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', pkg);
+    }
+
+    if (targetDevice) {
+        events.emit('verbose', 'Set TARGETED_DEVICE_FAMILY to ' + targetDevice + '.');
+        project.xcode.updateBuildProperty('TARGETED_DEVICE_FAMILY', targetDevice);
+    }
+
+    if (deploymentTarget) {
+        events.emit('verbose', 'Set IPHONEOS_DEPLOYMENT_TARGET to "' + deploymentTarget + '".');
+        project.xcode.updateBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget);
+    }
+
+    if (swiftVersion) {
+        events.emit('verbose', 'Set SwiftVersion to "' + swiftVersion + '".');
+        project.xcode.updateBuildProperty('SWIFT_VERSION', swiftVersion);
+    }
+
+    updateBuildSettingsForLaunchStoryboard(project.xcode, platformConfig, infoPlist);
+
+    project.write();
+
+    return Q();
+}
+
+function mapIconResources (icons, iconsDir) {
+    // See https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
+    // for launch images sizes reference.
+    var platformIcons = [
+        { dest: 'icon-20.png', width: 20, height: 20 },
+        { dest: 'icon-20@2x.png', width: 40, height: 40 },
+        { dest: 'icon-20@3x.png', width: 60, height: 60 },
+        { dest: 'icon-40.png', width: 40, height: 40 },
+        { dest: 'icon-40@2x.png', width: 80, height: 80 },
+        { dest: 'icon-50.png', width: 50, height: 50 },
+        { dest: 'icon-50@2x.png', width: 100, height: 100 },
+        { dest: 'icon-60@2x.png', width: 120, height: 120 },
+        { dest: 'icon-60@3x.png', width: 180, height: 180 },
+        { dest: 'icon-72.png', width: 72, height: 72 },
+        { dest: 'icon-72@2x.png', width: 144, height: 144 },
+        { dest: 'icon-76.png', width: 76, height: 76 },
+        { dest: 'icon-76@2x.png', width: 152, height: 152 },
+        { dest: 'icon-83.5@2x.png', width: 167, height: 167 },
+        { dest: 'icon-1024.png', width: 1024, height: 1024 },
+        { dest: 'icon-29.png', width: 29, height: 29 },
+        { dest: 'icon-29@2x.png', width: 58, height: 58 },
+        { dest: 'icon-29@3x.png', width: 87, height: 87 },
+        { dest: 'icon.png', width: 57, height: 57 },
+        { dest: 'icon@2x.png', width: 114, height: 114 },
+        { dest: 'icon-24@2x.png', width: 48, height: 48 },
+        { dest: 'icon-27.5@2x.png', width: 55, height: 55 },
+        { dest: 'icon-44@2x.png', width: 88, height: 88 },
+        { dest: 'icon-86@2x.png', width: 172, height: 172 },
+        { dest: 'icon-98@2x.png', width: 196, height: 196 }
+    ];
+
+    var pathMap = {};
+    platformIcons.forEach(function (item) {
+        var icon = icons.getBySize(item.width, item.height) || icons.getDefault();
+        if (icon) {
+            var target = path.join(iconsDir, item.dest);
+            pathMap[target] = icon.src;
+        }
+    });
+    return pathMap;
+}
+
+function getIconsDir (projectRoot, platformProjDir) {
+    var iconsDir;
+    var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+
+    if (xcassetsExists) {
+        iconsDir = path.join(platformProjDir, 'Images.xcassets/AppIcon.appiconset/');
+    } else {
+        iconsDir = path.join(platformProjDir, 'Resources/icons/');
+    }
+
+    return iconsDir;
+}
+
+function updateIcons (cordovaProject, locations) {
+    var icons = cordovaProject.projectConfig.getIcons('ios');
+
+    if (icons.length === 0) {
+        events.emit('verbose', 'This app does not have icons defined');
+        return;
+    }
+
+    var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+    var iconsDir = getIconsDir(cordovaProject.root, platformProjDir);
+    var resourceMap = mapIconResources(icons, iconsDir);
+    events.emit('verbose', 'Updating icons at ' + iconsDir);
+    FileUpdater.updatePaths(
+        resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+function cleanIcons (projectRoot, projectConfig, locations) {
+    var icons = projectConfig.getIcons('ios');
+    if (icons.length > 0) {
+        var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+        var iconsDir = getIconsDir(projectRoot, platformProjDir);
+        var resourceMap = mapIconResources(icons, iconsDir);
+        Object.keys(resourceMap).forEach(function (targetIconPath) {
+            resourceMap[targetIconPath] = null;
+        });
+        events.emit('verbose', 'Cleaning icons at ' + iconsDir);
+
+        // Source paths are removed from the map, so updatePaths() will delete the target files.
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+    }
+}
+
+function mapSplashScreenResources (splashScreens, splashScreensDir) {
+    var platformSplashScreens = [
+        { dest: 'Default~iphone.png', width: 320, height: 480 },
+        { dest: 'Default@2x~iphone.png', width: 640, height: 960 },
+        { dest: 'Default-Portrait~ipad.png', width: 768, height: 1024 },
+        { dest: 'Default-Portrait@2x~ipad.png', width: 1536, height: 2048 },
+        { dest: 'Default-Landscape~ipad.png', width: 1024, height: 768 },
+        { dest: 'Default-Landscape@2x~ipad.png', width: 2048, height: 1536 },
+        { dest: 'Default-568h@2x~iphone.png', width: 640, height: 1136 },
+        { dest: 'Default-667h.png', width: 750, height: 1334 },
+        { dest: 'Default-736h.png', width: 1242, height: 2208 },
+        { dest: 'Default-Landscape-736h.png', width: 2208, height: 1242 },
+        { dest: 'Default-2436h.png', width: 1125, height: 2436 },
+        { dest: 'Default-Landscape-2436h.png', width: 2436, height: 1125 }
+    ];
+
+    var pathMap = {};
+    platformSplashScreens.forEach(function (item) {
+        var splash = splashScreens.getBySize(item.width, item.height);
+        if (splash) {
+            var target = path.join(splashScreensDir, item.dest);
+            pathMap[target] = splash.src;
+        }
+    });
+    return pathMap;
+}
+
+function getSplashScreensDir (projectRoot, platformProjDir) {
+    var splashScreensDir;
+    var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+
+    if (xcassetsExists) {
+        splashScreensDir = path.join(platformProjDir, 'Images.xcassets/LaunchImage.launchimage/');
+    } else {
+        splashScreensDir = path.join(platformProjDir, 'Resources/splash/');
+    }
+
+    return splashScreensDir;
+}
+
+function updateSplashScreens (cordovaProject, locations) {
+    var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
+
+    if (splashScreens.length === 0) {
+        events.emit('verbose', 'This app does not have splash screens defined');
+        return;
+    }
+
+    var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+    var splashScreensDir = getSplashScreensDir(cordovaProject.root, platformProjDir);
+    var resourceMap = mapSplashScreenResources(splashScreens, splashScreensDir);
+    events.emit('verbose', 'Updating splash screens at ' + splashScreensDir);
+    FileUpdater.updatePaths(
+        resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+}
+
+function cleanSplashScreens (projectRoot, projectConfig, locations) {
+    var splashScreens = projectConfig.getSplashScreens('ios');
+    if (splashScreens.length > 0) {
+        var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+        var splashScreensDir = getSplashScreensDir(projectRoot, platformProjDir);
+        var resourceMap = mapIconResources(splashScreens, splashScreensDir);
+        Object.keys(resourceMap).forEach(function (targetSplashPath) {
+            resourceMap[targetSplashPath] = null;
+        });
+        events.emit('verbose', 'Cleaning splash screens at ' + splashScreensDir);
+
+        // Source paths are removed from the map, so updatePaths() will delete the target files.
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+    }
+}
+
+function updateFileResources (cordovaProject, locations) {
+    const platformDir = path.relative(cordovaProject.root, locations.root);
+    const files = cordovaProject.projectConfig.getFileResources('ios');
+
+    const project = projectFile.parse(locations);
+
+    // if there are resource-file elements in config.xml
+    if (files.length === 0) {
+        events.emit('verbose', 'This app does not have additional resource files defined');
+        return;
+    }
+
+    let resourceMap = {};
+    files.forEach(function (res) {
+        let src = res.src;
+        let target = res.target;
+
+        if (!target) {
+            target = src;
+        }
+
+        let targetPath = path.join(project.resources_dir, target);
+        targetPath = path.relative(cordovaProject.root, targetPath);
+
+        if (!fs.existsSync(targetPath)) {
+            project.xcode.addResourceFile(target);
+        } else {
+            events.emit('warn', 'Overwriting existing resource file at ' + targetPath);
+        }
+
+        resourceMap[targetPath] = src;
+    });
+
+    events.emit('verbose', 'Updating resource files at ' + platformDir);
+    FileUpdater.updatePaths(
+        resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+
+    project.write();
+}
+
+function cleanFileResources (projectRoot, projectConfig, locations) {
+    const platformDir = path.relative(projectRoot, locations.root);
+    const files = projectConfig.getFileResources('ios', true);
+    if (files.length > 0) {
+        events.emit('verbose', 'Cleaning resource files at ' + platformDir);
+
+        const project = projectFile.parse(locations);
+
+        var resourceMap = {};
+        files.forEach(function (res) {
+            let src = res.src;
+            let target = res.target;
+
+            if (!target) {
+                target = src;
+            }
+
+            let targetPath = path.join(project.resources_dir, target);
+            targetPath = path.relative(projectRoot, targetPath);
+            const resfile = path.join('Resources', path.basename(targetPath));
+            project.xcode.removeResourceFile(resfile);
+
+            resourceMap[targetPath] = null;
+        });
+
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+
+        project.write();
+    }
+}
+
+/**
+ * Returns an array of images for each possible idiom, scale, and size class. The images themselves are
+ * located in the platform's splash images by their pattern (@scale~idiom~sizesize). All possible
+ * combinations are returned, but not all will have a `filename` property. If the latter isn't present,
+ * the device won't attempt to load an image matching the same traits. If the filename is present,
+ * the device will try to load the image if it corresponds to the traits.
+ *
+ * The resulting return looks like this:
+ *
+ *     [
+ *         {
+ *             idiom: 'universal|ipad|iphone',
+ *             scale: '1x|2x|3x',
+ *             width: 'any|com',
+ *             height: 'any|com',
+ *             filename: undefined|'Default@scale~idiom~widthheight.png',
+ *             src: undefined|'path/to/original/matched/image/from/splash/screens.png',
+ *             target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png'
+ *         }, ...
+ *     ]
+ *
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Array<Object>}
+ */
+function mapLaunchStoryboardContents (splashScreens, launchStoryboardImagesDir) {
+    var platformLaunchStoryboardImages = [];
+    var idioms = ['universal', 'ipad', 'iphone'];
+    var scalesForIdiom = {
+        universal: ['1x', '2x', '3x'],
+        ipad: ['1x', '2x'],
+        iphone: ['1x', '2x', '3x']
+    };
+    var sizes = ['com', 'any'];
+
+    idioms.forEach(function (idiom) {
+        scalesForIdiom[idiom].forEach(function (scale) {
+            sizes.forEach(function (width) {
+                sizes.forEach(function (height) {
+                    var item = {
+                        idiom: idiom,
+                        scale: scale,
+                        width: width,
+                        height: height
+                    };
+
+                    /* examples of the search pattern:
+                     *    scale   ~  idiom    ~   width    height
+                     *     @2x    ~ universal ~    any      any
+                     *     @3x    ~  iphone   ~    com      any
+                     *     @2x    ~   ipad    ~    com      any
+                     */
+                    var searchPattern = '@' + scale + '~' + idiom + '~' + width + height;
+
+                    /* because old node versions don't have Array.find, the below is
+                     * functionally equivalent to this:
+                     *     var launchStoryboardImage = splashScreens.find(function(item) {
+                     *         return item.src.indexOf(searchPattern) >= 0;
+                     *     });
+                     */
+                    var launchStoryboardImage = splashScreens.reduce(function (p, c) {
+                        return (c.src.indexOf(searchPattern) >= 0) ? c : p;
+                    }, undefined);
+
+                    if (launchStoryboardImage) {
+                        item.filename = 'Default' + searchPattern + '.png';
+                        item.src = launchStoryboardImage.src;
+                        item.target = path.join(launchStoryboardImagesDir, item.filename);
+                    }
+
+                    platformLaunchStoryboardImages.push(item);
+                });
+            });
+        });
+    });
+    return platformLaunchStoryboardImages;
+}
+
+/**
+ * Returns a dictionary representing the source and destination paths for the launch storyboard images
+ * that need to be copied.
+ *
+ * The resulting return looks like this:
+ *
+ *     {
+ *         'target-path': 'source-path',
+ *         ...
+ *     }
+ *
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Object}
+ */
+function mapLaunchStoryboardResources (splashScreens, launchStoryboardImagesDir) {
+    var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+    var pathMap = {};
+    platformLaunchStoryboardImages.forEach(function (item) {
+        if (item.target) {
+            pathMap[item.target] = item.src;
+        }
+    });
+    return pathMap;
+}
+
+/**
+ * Builds the object that represents the contents.json file for the LaunchStoryboard image set.
+ *
+ * The resulting return looks like this:
+ *
+ *     {
+ *         images: [
+ *             {
+ *                 idiom: 'universal|ipad|iphone',
+ *                 scale: '1x|2x|3x',
+ *                 width-class: undefined|'compact',
+ *                 height-class: undefined|'compact'
+ *             }, ...
+ *         ],
+ *         info: {
+ *             author: 'Xcode',
+ *             version: 1
+ *         }
+ *     }
+ *
+ * A bit of minor logic is used to map from the array of images returned from mapLaunchStoryboardContents
+ * to the format requried by Xcode.
+ *
+ * @param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
+ * @param  {string} launchStoryboardImagesDir    project-root/Images.xcassets/LaunchStoryboard.imageset/
+ * @return {Object}
+ */
+function getLaunchStoryboardContentsJSON (splashScreens, launchStoryboardImagesDir) {
+
+    var platformLaunchStoryboardImages = mapLaunchStoryboardContents(splashScreens, launchStoryboardImagesDir);
+    var contentsJSON = {
+        images: [],
+        info: {
+            author: 'Xcode',
+            version: 1
+        }
+    };
+    contentsJSON.images = platformLaunchStoryboardImages.map(function (item) {
+        var newItem = {
+            idiom: item.idiom,
+            scale: item.scale
+        };
+
+        // Xcode doesn't want any size class property if the class is "any"
+        // If our size class is "com", Xcode wants "compact".
+        if (item.width !== CDV_ANY_SIZE_CLASS) {
+            newItem['width-class'] = IMAGESET_COMPACT_SIZE_CLASS;
+        }
+        if (item.height !== CDV_ANY_SIZE_CLASS) {
+            newItem['height-class'] = IMAGESET_COMPACT_SIZE_CLASS;
+        }
+
+        // Xcode doesn't want a filename property if there's no image for these traits
+        if (item.filename) {
+            newItem.filename = item.filename;
+        }
+        return newItem;
+    });
+    return contentsJSON;
+}
+
+/**
+ * Determines if the project's build settings may need to be updated for launch storyboard support
+ *
+ */
+function checkIfBuildSettingsNeedUpdatedForLaunchStoryboard (platformConfig, infoPlist) {
+    var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig);
+    var hasLegacyLaunchImages = platformHasLegacyLaunchImages(platformConfig);
+    var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME];
+
+    if (hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) {
+        // don't need legacy launch images if we are using our launch storyboard
+        // so we do need to update the project file
+        events.emit('verbose', 'Need to update build settings because project is using our launch storyboard.');
+        return true;
+    } else if (hasLegacyLaunchImages && !currentLaunchStoryboard) {
+        // we do need to ensure legacy launch images are used if there's no launch storyboard present
+        // so we do need to update the project file
+        events.emit('verbose', 'Need to update build settings because project is using legacy launch images and no storyboard.');
+        return true;
+    }
+    events.emit('verbose', 'No need to update build settings for launch storyboard support.');
+    return false;
+}
+
+function updateBuildSettingsForLaunchStoryboard (proj, platformConfig, infoPlist) {
+    var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig);
+    var hasLegacyLaunchImages = platformHasLegacyLaunchImages(platformConfig);
+    var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME];
+
+    if (hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME && !hasLegacyLaunchImages) {
+        // don't need legacy launch images if we are using our launch storyboard
+        events.emit('verbose', 'Removed ' + LAUNCHIMAGE_BUILD_SETTING + ' because project is using our launch storyboard.');
+        proj.removeBuildProperty(LAUNCHIMAGE_BUILD_SETTING);
+    } else if (hasLegacyLaunchImages && !currentLaunchStoryboard) {
+        // we do need to ensure legacy launch images are used if there's no launch storyboard present
+        events.emit('verbose', 'Set ' + LAUNCHIMAGE_BUILD_SETTING + ' to ' + LAUNCHIMAGE_BUILD_SETTING_VALUE + ' because project is using legacy launch images and no storyboard.');
+        proj.updateBuildProperty(LAUNCHIMAGE_BUILD_SETTING, LAUNCHIMAGE_BUILD_SETTING_VALUE);
+    } else {
+        events.emit('verbose', 'Did not update build settings for launch storyboard support.');
+    }
+}
+
+function splashScreensHaveLaunchStoryboardImages (contentsJSON) {
+    /* do we have any launch images do we have for our launch storyboard?
+     * Again, for old Node versions, the below code is equivalent to this:
+     *     return !!contentsJSON.images.find(function (item) {
+     *        return item.filename !== undefined;
+     *     });
+     */
+    return !!contentsJSON.images.reduce(function (p, c) {
+        return (c.filename !== undefined) ? c : p;
+    }, undefined);
+}
+
+function platformHasLaunchStoryboardImages (platformConfig) {
+    var splashScreens = platformConfig.getSplashScreens('ios');
+    var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, ''); // note: we don't need a file path here; we're just counting
+    return splashScreensHaveLaunchStoryboardImages(contentsJSON);
+}
+
+function platformHasLegacyLaunchImages (platformConfig) {
+    var splashScreens = platformConfig.getSplashScreens('ios');
+    return !!splashScreens.reduce(function (p, c) {
+        return (c.width !== undefined || c.height !== undefined) ? c : p;
+    }, undefined);
+}
+
+/**
+ * Updates the project's plist based upon our launch storyboard images. If there are no images, then we should
+ * fall back to the regular launch images that might be supplied (that is, our app will be scaled on an iPad Pro),
+ * and if there are some images, we need to alter the UILaunchStoryboardName property to point to
+ * CDVLaunchScreen.
+ *
+ * There's some logic here to avoid overwriting changes the user might have made to their plist if they are using
+ * their own launch storyboard.
+ */
+function updateProjectPlistForLaunchStoryboard (platformConfig, infoPlist) {
+    var currentLaunchStoryboard = infoPlist[UI_LAUNCH_STORYBOARD_NAME];
+    events.emit('verbose', 'Current launch storyboard ' + currentLaunchStoryboard);
+
+    var hasLaunchStoryboardImages = platformHasLaunchStoryboardImages(platformConfig);
+
+    if (hasLaunchStoryboardImages && !currentLaunchStoryboard) {
+        // only change the launch storyboard if we have images to use AND the current value is blank
+        // if it's not blank, we've either done this before, or the user has their own launch storyboard
+        events.emit('verbose', 'Changing info plist to use our launch storyboard');
+        infoPlist[UI_LAUNCH_STORYBOARD_NAME] = CDV_LAUNCH_STORYBOARD_NAME;
+        return;
+    }
+
+    if (!hasLaunchStoryboardImages && currentLaunchStoryboard === CDV_LAUNCH_STORYBOARD_NAME) {
+        // only revert to using the launch images if we have don't have any images for the launch storyboard
+        // but only clear it if current launch storyboard is our storyboard; the user might be using their
+        // own storyboard instead.
+        events.emit('verbose', 'Changing info plist to use legacy launch images');
+        delete infoPlist[UI_LAUNCH_STORYBOARD_NAME];
+        return;
+    }
+    events.emit('verbose', 'Not changing launch storyboard setting in info plist.');
+}
+
+/**
+ * Returns the directory for the Launch Storyboard image set, if image sets are being used. If they aren't
+ * being used, returns null.
+ *
+ * @param  {string} projectRoot        The project's root directory
+ * @param  {string} platformProjDir    The platform's project directory
+ */
+function getLaunchStoryboardImagesDir (projectRoot, platformProjDir) {
+    var launchStoryboardImagesDir;
+    var xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Images.xcassets/'));
+
+    if (xcassetsExists) {
+        launchStoryboardImagesDir = path.join(platformProjDir, 'Images.xcassets/LaunchStoryboard.imageset/');
+    } else {
+        // if we don't have a asset library for images, we can't do the storyboard.
+        launchStoryboardImagesDir = null;
+    }
+
+    return launchStoryboardImagesDir;
+}
+
+/**
+ * Update the images for the Launch Storyboard and updates the image set's contents.json file appropriately.
+ *
+ * @param  {Object} cordovaProject     The cordova project
+ * @param  {Object} locations          A dictionary containing useful location paths
+ */
+function updateLaunchStoryboardImages (cordovaProject, locations) {
+    var splashScreens = cordovaProject.projectConfig.getSplashScreens('ios');
+    var platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
+    var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(cordovaProject.root, platformProjDir);
+
+    if (launchStoryboardImagesDir) {
+        var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+        var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+
+        events.emit('verbose', 'Updating launch storyboard images at ' + launchStoryboardImagesDir);
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+
+        events.emit('verbose', 'Updating Storyboard image set contents.json');
+        fs.writeFileSync(path.join(cordovaProject.root, launchStoryboardImagesDir, 'Contents.json'),
+            JSON.stringify(contentsJSON, null, 2));
+    }
+}
+
+/**
+ * Removes the images from the launch storyboard's image set and updates the image set's contents.json
+ * file appropriately.
+ *
+ * @param  {string} projectRoot        Path to the project root
+ * @param  {Object} projectConfig      The project's config.xml
+ * @param  {Object} locations          A dictionary containing useful location paths
+ */
+function cleanLaunchStoryboardImages (projectRoot, projectConfig, locations) {
+    var splashScreens = projectConfig.getSplashScreens('ios');
+    var platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+    var launchStoryboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir);
+    if (launchStoryboardImagesDir) {
+        var resourceMap = mapLaunchStoryboardResources(splashScreens, launchStoryboardImagesDir);
+        var contentsJSON = getLaunchStoryboardContentsJSON(splashScreens, launchStoryboardImagesDir);
+
+        Object.keys(resourceMap).forEach(function (targetPath) {
+            resourceMap[targetPath] = null;
+        });
+        events.emit('verbose', 'Cleaning storyboard image set at ' + launchStoryboardImagesDir);
+
+        // Source paths are removed from the map, so updatePaths() will delete the target files.
+        FileUpdater.updatePaths(
+            resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+
+        // delete filename from contents.json
+        contentsJSON.images.forEach(function (image) {
+            image.filename = undefined;
+        });
+
+        events.emit('verbose', 'Updating Storyboard image set contents.json');
+        fs.writeFileSync(path.join(projectRoot, launchStoryboardImagesDir, 'Contents.json'),
+            JSON.stringify(contentsJSON, null, 2));
+    }
+}
+
+/**
+ * Queries ConfigParser object for the orientation <preference> value. Warns if
+ *   global preference value is not supported by platform.
+ *
+ * @param  {Object} platformConfig    ConfigParser object
+ *
+ * @return {String}           Global/platform-specific orientation in lower-case
+ *   (or empty string if both are undefined).
+ */
+function getOrientationValue (platformConfig) {
+
+    var ORIENTATION_DEFAULT = 'default';
+
+    var orientation = platformConfig.getPreference('orientation');
+    if (!orientation) {
+        return '';
+    }
+
+    orientation = orientation.toLowerCase();
+
+    // Check if the given global orientation is supported
+    if (['default', 'portrait', 'landscape', 'all'].indexOf(orientation) >= 0) {
+        return orientation;
+    }
+
+    events.emit('warn', 'Unrecognized value for Orientation preference: ' + orientation +
+        '. Defaulting to value: ' + ORIENTATION_DEFAULT + '.');
+
+    return ORIENTATION_DEFAULT;
+}
+
+/*
+    Parses all <access> and <allow-navigation> entries and consolidates duplicates (for ATS).
+    Returns an object with a Hostname as the key, and the value an object with properties:
+        {
+            Hostname, // String
+            NSExceptionAllowsInsecureHTTPLoads, // boolean
+            NSIncludesSubdomains,  // boolean
+            NSExceptionMinimumTLSVersion, // String
+            NSExceptionRequiresForwardSecrecy, // boolean
+            NSRequiresCertificateTransparency, // boolean
+
+            // the three below _only_ show when the Hostname is '*'
+            // if any of the three are set, it disables setting NSAllowsArbitraryLoads
+            // (Apple already enforces this in ATS)
+            NSAllowsArbitraryLoadsInWebContent, // boolean (default: false)
+            NSAllowsLocalNetworking, // boolean (default: false)
+            NSAllowsArbitraryLoadsForMedia, // boolean (default:false)
+
+        }
+*/
+function processAccessAndAllowNavigationEntries (config) {
+    var accesses = config.getAccesses();
+    var allow_navigations = config.getAllowNavigations();
+
+    return allow_navigations
+    // we concat allow_navigations and accesses, after processing accesses
+        .concat(accesses.map(function (obj) {
+            // map accesses to a common key interface using 'href', not origin
+            obj.href = obj.origin;
+            delete obj.origin;
+            return obj;
+        }))
+        // we reduce the array to an object with all the entries processed (key is Hostname)
+        .reduce(function (previousReturn, currentElement) {
+            var options = {
+                minimum_tls_version: currentElement.minimum_tls_version,
+                requires_forward_secrecy: currentElement.requires_forward_secrecy,
+                requires_certificate_transparency: currentElement.requires_certificate_transparency,
+                allows_arbitrary_loads_for_media: currentElement.allows_arbitrary_loads_in_media || currentElement.allows_arbitrary_loads_for_media,
+                allows_arbitrary_loads_in_web_content: currentElement.allows_arbitrary_loads_in_web_content,
+                allows_local_networking: currentElement.allows_local_networking
+            };
+            var obj = parseWhitelistUrlForATS(currentElement.href, options);
+
+            if (obj) {
+                // we 'union' duplicate entries
+                var item = previousReturn[obj.Hostname];
+                if (!item) {
+                    item = {};
+                }
+                for (var o in obj) {
+                    if (obj.hasOwnProperty(o)) {
+                        item[o] = obj[o];
+                    }
+                }
+                previousReturn[obj.Hostname] = item;
+            }
+            return previousReturn;
+        }, {});
+}
+
+/*
+    Parses a URL and returns an object with these keys:
+        {
+            Hostname, // String
+            NSExceptionAllowsInsecureHTTPLoads, // boolean (default: false)
+            NSIncludesSubdomains,  // boolean (default: false)
+            NSExceptionMinimumTLSVersion, // String (default: 'TLSv1.2')
+            NSExceptionRequiresForwardSecrecy, // boolean (default: true)
+            NSRequiresCertificateTransparency, // boolean (default: false)
+
+            // the three below _only_ apply when the Hostname is '*'
+            // if any of the three are set, it disables setting NSAllowsArbitraryLoads
+            // (Apple already enforces this in ATS)
+            NSAllowsArbitraryLoadsInWebContent, // boolean (default: false)
+            NSAllowsLocalNetworking, // boolean (default: false)
+            NSAllowsArbitraryLoadsForMedia, // boolean (default:false)
+        }
+
+    null is returned if the URL cannot be parsed, or is to be skipped for ATS.
+*/
+function parseWhitelistUrlForATS (url, options) {
+    // @todo 'url.parse' was deprecated since v11.0.0. Use 'url.URL' constructor instead.
+    var href = URL.parse(url); // eslint-disable-line
+    var retObj = {};
+    retObj.Hostname = href.hostname;
+
+    // Guiding principle: we only set values in retObj if they are NOT the default
+
+    if (url === '*') {
+        retObj.Hostname = '*';
+        var val;
+
+        val = (options.allows_arbitrary_loads_in_web_content === 'true');
+        if (options.allows_arbitrary_loads_in_web_content && val) { // default is false
+            retObj.NSAllowsArbitraryLoadsInWebContent = true;
+        }
+
+        val = (options.allows_arbitrary_loads_for_media === 'true');
+        if (options.allows_arbitrary_loads_for_media && val) { // default is false
+            retObj.NSAllowsArbitraryLoadsForMedia = true;
+        }
+
+        val = (options.allows_local_networking === 'true');
+        if (options.allows_local_networking && val) { // default is false
+            retObj.NSAllowsLocalNetworking = true;
+        }
+
+        return retObj;
+    }
+
+    if (!retObj.Hostname) {
+        // check origin, if it allows subdomains (wildcard in hostname), we set NSIncludesSubdomains to YES. Default is NO
+        var subdomain1 = '/*.'; // wildcard in hostname
+        var subdomain2 = '*://*.'; // wildcard in hostname and protocol
+        var subdomain3 = '*://'; // wildcard in protocol only
+        if (!href.pathname) {
+            return null;
+        } else if (href.pathname.indexOf(subdomain1) === 0) {
+            retObj.NSIncludesSubdomains = true;
+            retObj.Hostname = href.pathname.substring(subdomain1.length);
+        } else if (href.pathname.indexOf(subdomain2) === 0) {
+            retObj.NSIncludesSubdomains = true;
+            retObj.Hostname = href.pathname.substring(subdomain2.length);
+        } else if (href.pathname.indexOf(subdomain3) === 0) {
+            retObj.Hostname = href.pathname.substring(subdomain3.length);
+        } else {
+            // Handling "scheme:*" case to avoid creating of a blank key in NSExceptionDomains.
+            return null;
+        }
+    }
+
+    if (options.minimum_tls_version && options.minimum_tls_version !== 'TLSv1.2') { // default is TLSv1.2
+        retObj.NSExceptionMinimumTLSVersion = options.minimum_tls_version;
+    }
+
+    var rfs = (options.requires_forward_secrecy === 'true');
+    if (options.requires_forward_secrecy && !rfs) { // default is true
+        retObj.NSExceptionRequiresForwardSecrecy = false;
+    }
+
+    var rct = (options.requires_certificate_transparency === 'true');
+    if (options.requires_certificate_transparency && rct) { // default is false
+        retObj.NSRequiresCertificateTransparency = true;
+    }
+
+    // if the scheme is HTTP, we set NSExceptionAllowsInsecureHTTPLoads to YES. Default is NO
+    if (href.protocol === 'http:') {
+        retObj.NSExceptionAllowsInsecureHTTPLoads = true;
+    } else if (!href.protocol && href.pathname.indexOf('*:/') === 0) { // wilcard in protocol
+        retObj.NSExceptionAllowsInsecureHTTPLoads = true;
+    }
+
+    return retObj;
+}
+
+/*
+    App Transport Security (ATS) writer from <access> and <allow-navigation> tags
+    in config.xml
+*/
+function writeATSEntries (config) {
+    var pObj = processAccessAndAllowNavigationEntries(config);
+
+    var ats = {};
+
+    for (var hostname in pObj) {
+        if (pObj.hasOwnProperty(hostname)) {
+            var entry = pObj[hostname];
+
+            // Guiding principle: we only set values if they are available
+
+            if (hostname === '*') {
+                // always write this, for iOS 9, since in iOS 10 it will be overriden if
+                // any of the other three keys are written
+                ats['NSAllowsArbitraryLoads'] = true;
+
+                // at least one of the overriding keys is present
+                if (entry.NSAllowsArbitraryLoadsInWebContent) {
+                    ats['NSAllowsArbitraryLoadsInWebContent'] = true;
+                }
+                if (entry.NSAllowsArbitraryLoadsForMedia) {
+                    ats['NSAllowsArbitraryLoadsForMedia'] = true;
+                }
+                if (entry.NSAllowsLocalNetworking) {
+                    ats['NSAllowsLocalNetworking'] = true;
+                }
+
+                continue;
+            }
+
+            var exceptionDomain = {};
+
+            for (var key in entry) {
+                if (entry.hasOwnProperty(key) && key !== 'Hostname') {
+                    exceptionDomain[key] = entry[key];
+                }
+            }
+
+            if (!ats['NSExceptionDomains']) {
+                ats['NSExceptionDomains'] = {};
+            }
+
+            ats['NSExceptionDomains'][hostname] = exceptionDomain;
+        }
+    }
+
+    return ats;
+}
+
+function folderExists (folderPath) {
+    try {
+        var stat = fs.statSync(folderPath);
+        return stat && stat.isDirectory();
+    } catch (e) {
+        return false;
+    }
+}
+
+// Construct a default value for CFBundleVersion as the version with any
+// -rclabel stripped=.
+function default_CFBundleVersion (version) {
+    return version.split('-')[0];
+}
+
+// Converts cordova specific representation of target device to XCode value
+function parseTargetDevicePreference (value) {
+    if (!value) return null;
+    var map = { 'universal': '"1,2"', 'handset': '"1"', 'tablet': '"2"' };
+    if (map[value.toLowerCase()]) {
+        return map[value.toLowerCase()];
+    }
+    events.emit('warn', 'Unrecognized value for target-device preference: ' + value + '.');
+    return null;
+}
diff --git a/platforms/ios/cordova/lib/projectFile.js b/platforms/ios/cordova/lib/projectFile.js
new file mode 100755
index 0000000..8a3f7e5
--- /dev/null
+++ b/platforms/ios/cordova/lib/projectFile.js
@@ -0,0 +1,134 @@
+/*
+       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.
+*/
+
+var xcode = require('xcode');
+var plist = require('plist');
+var _ = require('underscore');
+var path = require('path');
+var fs = require('fs');
+var shell = require('shelljs');
+
+var pluginHandlers = require('./plugman/pluginHandlers');
+var CordovaError = require('cordova-common').CordovaError;
+
+var cachedProjectFiles = {};
+
+function parseProjectFile (locations) {
+    var project_dir = locations.root;
+    var pbxPath = locations.pbxproj;
+
+    if (cachedProjectFiles[project_dir]) {
+        return cachedProjectFiles[project_dir];
+    }
+
+    var xcodeproj = xcode.project(pbxPath);
+    xcodeproj.parseSync();
+
+    var xcBuildConfiguration = xcodeproj.pbxXCBuildConfigurationSection();
+    var plist_file_entry = _.find(xcBuildConfiguration, function (entry) { return entry.buildSettings && entry.buildSettings.INFOPLIST_FILE; });
+    var plist_file = path.join(project_dir, plist_file_entry.buildSettings.INFOPLIST_FILE.replace(/^"(.*)"$/g, '$1').replace(/\\&/g, '&'));
+    var config_file = path.join(path.dirname(plist_file), 'config.xml');
+
+    if (!fs.existsSync(plist_file) || !fs.existsSync(config_file)) {
+        throw new CordovaError('Could not find *-Info.plist file, or config.xml file.');
+    }
+
+    var frameworks_file = path.join(project_dir, 'frameworks.json');
+    var frameworks = {};
+    try {
+        frameworks = require(frameworks_file);
+    } catch (e) { }
+
+    var xcode_dir = path.dirname(plist_file);
+    var pluginsDir = path.resolve(xcode_dir, 'Plugins');
+    var resourcesDir = path.resolve(xcode_dir, 'Resources');
+
+    cachedProjectFiles[project_dir] = {
+        plugins_dir: pluginsDir,
+        resources_dir: resourcesDir,
+        xcode: xcodeproj,
+        xcode_path: xcode_dir,
+        pbx: pbxPath,
+        projectDir: project_dir,
+        platformWww: path.join(project_dir, 'platform_www'),
+        www: path.join(project_dir, 'www'),
+        write: function () {
+            fs.writeFileSync(pbxPath, xcodeproj.writeSync());
+            if (Object.keys(this.frameworks).length === 0) {
+                // If there is no framework references remain in the project, just remove this file
+                shell.rm('-rf', frameworks_file);
+                return;
+            }
+            fs.writeFileSync(frameworks_file, JSON.stringify(this.frameworks, null, 4));
+        },
+        getPackageName: function () {
+            return plist.parse(fs.readFileSync(plist_file, 'utf8')).CFBundleIdentifier;
+        },
+        getInstaller: function (name) {
+            return pluginHandlers.getInstaller(name);
+        },
+        getUninstaller: function (name) {
+            return pluginHandlers.getUninstaller(name);
+        },
+        frameworks: frameworks
+    };
+    return cachedProjectFiles[project_dir];
+}
+
+function purgeProjectFileCache (project_dir) {
+    delete cachedProjectFiles[project_dir];
+}
+
+module.exports = {
+    parse: parseProjectFile,
+    purgeProjectFileCache: purgeProjectFileCache
+};
+
+xcode.project.prototype.pbxEmbedFrameworksBuildPhaseObj = function (target) {
+    return this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Frameworks', target);
+};
+
+xcode.project.prototype.addToPbxEmbedFrameworksBuildPhase = function (file) {
+    var sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target);
+    if (sources) {
+        sources.files.push(pbxBuildPhaseObj(file));
+    }
+};
+xcode.project.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) {
+    var sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target);
+    if (sources) {
+        sources.files = _.reject(sources.files, function (file) {
+            return file.comment === longComment(file);
+        });
+    }
+};
+
+// special handlers to add frameworks to the 'Embed Frameworks' build phase, needed for custom frameworks
+// see CB-9517. should probably be moved to node-xcode.
+var util = require('util');
+function pbxBuildPhaseObj (file) {
+    var obj = Object.create(null);
+    obj.value = file.uuid;
+    obj.comment = longComment(file);
+    return obj;
+}
+
+function longComment (file) {
+    return util.format('%s in %s', file.basename, file.group);
+}
diff --git a/platforms/ios/cordova/lib/run.js b/platforms/ios/cordova/lib/run.js
new file mode 100755
index 0000000..f21fee6
--- /dev/null
+++ b/platforms/ios/cordova/lib/run.js
@@ -0,0 +1,263 @@
+/*
+       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.
+*/
+
+var Q = require('q');
+var path = require('path');
+var build = require('./build');
+var shell = require('shelljs');
+var superspawn = require('cordova-common').superspawn;
+var check_reqs = require('./check_reqs');
+var fs = require('fs-extra');
+
+var events = require('cordova-common').events;
+
+var cordovaPath = path.join(__dirname, '..');
+var projectPath = path.join(__dirname, '..', '..');
+
+module.exports.run = function (runOptions) {
+
+    // Validate args
+    if (runOptions.device && runOptions.emulator) {
+        return Q.reject('Only one of "device"/"emulator" options should be specified');
+    }
+
+    // support for CB-8168 `cordova/run --list`
+    if (runOptions.list) {
+        if (runOptions.device) return module.exports.listDevices();
+        if (runOptions.emulator) return module.exports.listEmulators();
+        // if no --device or --emulator flag is specified, list both devices and emulators
+        return module.exports.listDevices().then(function () {
+            return module.exports.listEmulators();
+        });
+    }
+
+    var useDevice = !!runOptions.device;
+
+    return require('./list-devices').run()
+        .then(function (devices) {
+            if (devices.length > 0 && !(runOptions.emulator)) {
+                useDevice = true;
+                // we also explicitly set device flag in options as we pass
+                // those parameters to other api (build as an example)
+                runOptions.device = true;
+                return check_reqs.check_ios_deploy();
+            }
+        }).then(function () {
+            if (!runOptions.nobuild) {
+                return build.run(runOptions);
+            } else {
+                return Q.resolve();
+            }
+        }).then(function () {
+            return build.findXCodeProjectIn(projectPath);
+        }).then(function (projectName) {
+            var appPath = path.join(projectPath, 'build', 'emulator', projectName + '.app');
+            var buildOutputDir = path.join(projectPath, 'build', 'device');
+
+            // select command to run and arguments depending whether
+            // we're running on device/emulator
+            if (useDevice) {
+                return module.exports.checkDeviceConnected()
+                    .then(function () {
+                        // Unpack IPA
+                        var ipafile = path.join(buildOutputDir, projectName + '.ipa');
+
+                        // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder
+                        return superspawn.spawn('unzip', [ '-o', '-qq', ipafile ], { cwd: buildOutputDir, printCommand: true, stdio: 'inherit' });
+                    })
+                    .then(function () {
+                        // Uncompress IPA (zip file)
+                        var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app');
+                        var appFile = path.join(buildOutputDir, projectName + '.app');
+                        var payloadFolder = path.join(buildOutputDir, 'Payload');
+
+                        // delete the existing platform/ios/build/device/appname.app
+                        fs.removeSync(appFile);
+                        // move the platform/ios/build/device/Payload/appname.app to parent
+                        shell.mv('-f', appFileInflated, buildOutputDir);
+                        // delete the platform/ios/build/device/Payload folder
+                        shell.rm('-rf', payloadFolder);
+
+                        return null;
+                    })
+                    .then(function () {
+                        appPath = path.join(projectPath, 'build', 'device', projectName + '.app');
+                        var extraArgs = [];
+                        if (runOptions.argv) {
+                            // argv.slice(2) removes node and run.js, filterSupportedArgs removes the run.js args
+                            extraArgs = module.exports.filterSupportedArgs(runOptions.argv.slice(2));
+                        }
+                        return module.exports.deployToDevice(appPath, runOptions.target, extraArgs);
+                    }, function () {
+                        // if device connection check failed use emulator then
+                        return module.exports.deployToSim(appPath, runOptions.target);
+                    });
+            } else {
+                return module.exports.deployToSim(appPath, runOptions.target);
+            }
+        });
+};
+
+module.exports.filterSupportedArgs = filterSupportedArgs;
+module.exports.checkDeviceConnected = checkDeviceConnected;
+module.exports.deployToDevice = deployToDevice;
+module.exports.deployToSim = deployToSim;
+module.exports.startSim = startSim;
+module.exports.listDevices = listDevices;
+module.exports.listEmulators = listEmulators;
+
+/**
+ * Filters the args array and removes supported args for the 'run' command.
+ *
+ * @return {Array} array with unsupported args for the 'run' command
+ */
+function filterSupportedArgs (args) {
+    var filtered = [];
+    var sargs = ['--device', '--emulator', '--nobuild', '--list', '--target', '--debug', '--release'];
+    var re = new RegExp(sargs.join('|'));
+
+    args.forEach(function (element) {
+        // supported args not found, we add
+        // we do a regex search because --target can be "--target=XXX"
+        if (element.search(re) === -1) {
+            filtered.push(element);
+        }
+    }, this);
+
+    return filtered;
+}
+
+/**
+ * Checks if any iOS device is connected
+ * @return {Promise} Fullfilled when any device is connected, rejected otherwise
+ */
+function checkDeviceConnected () {
+    return superspawn.spawn('ios-deploy', ['-c', '-t', '1'], { printCommand: true, stdio: 'inherit' });
+}
+
+/**
+ * Deploy specified app package to connected device
+ * using ios-deploy command
+ * @param  {String} appPath Path to application package
+ * @return {Promise}        Resolves when deploy succeeds otherwise rejects
+ */
+function deployToDevice (appPath, target, extraArgs) {
+    events.emit('log', 'Deploying to device');
+    // Deploying to device...
+    if (target) {
+        return superspawn.spawn('ios-deploy', ['--justlaunch', '-d', '-b', appPath, '-i', target].concat(extraArgs), { printCommand: true, stdio: 'inherit' });
+    } else {
+        return superspawn.spawn('ios-deploy', ['--justlaunch', '--no-wifi', '-d', '-b', appPath].concat(extraArgs), { printCommand: true, stdio: 'inherit' });
+    }
+}
+
+/**
+ * Deploy specified app package to ios-sim simulator
+ * @param  {String} appPath Path to application package
+ * @param  {String} target  Target device type
+ * @return {Promise}        Resolves when deploy succeeds otherwise rejects
+ */
+function deployToSim (appPath, target) {
+    events.emit('log', 'Deploying to simulator');
+    if (!target) {
+        // Select target device for emulator
+        return require('./list-emulator-images').run()
+            .then(function (emulators) {
+                if (emulators.length > 0) {
+                    target = emulators[0];
+                }
+                emulators.forEach(function (emulator) {
+                    if (emulator.indexOf('iPhone') === 0) {
+                        target = emulator;
+                    }
+                });
+                events.emit('log', `No target specified for emulator. Deploying to "${target}" simulator.`);
+                return startSim(appPath, target);
+            });
+    } else {
+        return startSim(appPath, target);
+    }
+}
+
+function startSim (appPath, target) {
+    var logPath = path.join(cordovaPath, 'console.log');
+
+    return iossimLaunch(appPath, 'com.apple.CoreSimulator.SimDeviceType.' + target, logPath, '--exit');
+}
+
+function iossimLaunch (appPath, devicetypeid, log, exit) {
+    var f = path.resolve(path.dirname(require.resolve('ios-sim')), 'bin', 'ios-sim');
+    var params = ['launch', appPath, '--devicetypeid', devicetypeid, '--log', log, exit];
+
+    return superspawn.spawn(f, params, { cwd: projectPath, printCommand: true })
+        .progress(function (stdio) {
+            if (stdio.stderr) {
+                events.emit('error', `[ios-sim] ${stdio.stderr}`);
+            }
+            if (stdio.stdout) {
+                events.emit('log', `[ios-sim] ${stdio.stdout.trim()}`);
+            }
+        })
+        .then(function (result) {
+            events.emit('log', 'Simulator successfully started via `ios-sim`.');
+        });
+}
+
+function listDevices () {
+    return require('./list-devices').run()
+        .then(function (devices) {
+            events.emit('log', 'Available iOS Devices:');
+            devices.forEach(function (device) {
+                events.emit('log', '\t' + device);
+            });
+        });
+}
+
+function listEmulators () {
+    return require('./list-emulator-images').run()
+        .then(function (emulators) {
+            events.emit('log', 'Available iOS Simulators:');
+            emulators.forEach(function (emulator) {
+                events.emit('log', '\t' + emulator);
+            });
+        });
+}
+
+module.exports.help = function () {
+    console.log('\nUsage: run [ --device | [ --emulator [ --target=<id> ] ] ] [ --debug | --release | --nobuild ]');
+    // TODO: add support for building different archs
+    // console.log("           [ --archs=\"<list of target architectures>\" ] ");
+    console.log('    --device      : Deploys and runs the project on the connected device.');
+    console.log('    --emulator    : Deploys and runs the project on an emulator.');
+    console.log('    --target=<id> : Deploys and runs the project on the specified target.');
+    console.log('    --debug       : Builds project in debug mode. (Passed down to build command, if necessary)');
+    console.log('    --release     : Builds project in release mode. (Passed down to build command, if necessary)');
+    console.log('    --nobuild     : Uses pre-built package, or errors if project is not built.');
+    // TODO: add support for building different archs
+    // console.log("    --archs       : Specific chip architectures (`anycpu`, `arm`, `x86`, `x64`).");
+    console.log('');
+    console.log('Examples:');
+    console.log('    run');
+    console.log('    run --device');
+    console.log('    run --emulator --target=\"iPhone-6-Plus\"'); /* eslint no-useless-escape : 0 */
+    console.log('    run --device --release');
+    console.log('    run --emulator --debug');
+    console.log('');
+    process.exit(0);
+};
diff --git a/platforms/ios/cordova/lib/spawn.js b/platforms/ios/cordova/lib/spawn.js
new file mode 100755
index 0000000..321b04f
--- /dev/null
+++ b/platforms/ios/cordova/lib/spawn.js
@@ -0,0 +1,51 @@
+/*
+       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.
+*/
+
+var Q = require('q');
+var proc = require('child_process');
+
+/**
+ * Run specified command with arguments
+ * @param  {String} cmd           Command
+ * @param  {Array} args           Array of arguments that should be passed to command
+ * @param  {String} opt_cwd       Working directory for command
+ * @param  {String} opt_verbosity Verbosity level for command stdout output, "verbose" by default
+ * @return {Promise}              Promise either fullfilled or rejected with error code
+ * @deprecated Use `require('cordova-common').superspawn` instead.
+ */
+module.exports = function (cmd, args, opt_cwd) {
+    console.warn(
+        'This function is deprecated, may be removed from a future release. ' +
+        "Use `require('cordova-common').superspawn` instead.");
+    var d = Q.defer();
+    try {
+        var child = proc.spawn(cmd, args, { cwd: opt_cwd, stdio: 'inherit' });
+
+        child.on('exit', function (code) {
+            if (code) {
+                d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args);
+            } else {
+                d.resolve();
+            }
+        });
+    } catch (e) {
+        d.reject(e);
+    }
+    return d.promise;
+};
diff --git a/platforms/ios/cordova/lib/start-emulator b/platforms/ios/cordova/lib/start-emulator
new file mode 100755
index 0000000..624335b
--- /dev/null
+++ b/platforms/ios/cordova/lib/start-emulator
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash 
+#
+# 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.
+#
+# Run the below to get the device targets:
+#     xcrun instruments -s
+
+set -e
+
+
+DEFAULT_TARGET="iPhone 5s"
+TARGET=${1:-$DEFAULT_TARGET}
+LIB_PATH=$( cd "$( dirname "$0" )" && pwd -P)
+
+xcrun instruments -w "$TARGET" &> /dev/null
\ No newline at end of file
diff --git a/platforms/ios/cordova/lib/versions.js b/platforms/ios/cordova/lib/versions.js
new file mode 100755
index 0000000..d9ba5e3
--- /dev/null
+++ b/platforms/ios/cordova/lib/versions.js
@@ -0,0 +1,194 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+var child_process = require('child_process');
+var Q = require('q');
+
+exports.get_apple_ios_version = function () {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -showsdks', function (error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+
+    return d.promise.then(function (output) {
+        var regex = /[0-9]*\.[0-9]*/;
+        var versions = [];
+        var regexIOS = /^iOS \d+/;
+        output = output.split('\n');
+        for (var i = 0; i < output.length; i++) {
+            if (output[i].trim().match(regexIOS)) {
+                versions[versions.length] = parseFloat(output[i].match(regex)[0]);
+            }
+        }
+        versions.sort();
+        console.log(versions[0]);
+        return Q();
+    }, function (stderr) {
+        return Q.reject(stderr);
+    });
+};
+
+exports.get_apple_osx_version = function () {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -showsdks', function (error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+
+    return d.promise.then(function (output) {
+        var regex = /[0-9]*\.[0-9]*/;
+        var versions = [];
+        var regexOSX = /^macOS \d+/;
+        output = output.split('\n');
+        for (var i = 0; i < output.length; i++) {
+            if (output[i].trim().match(regexOSX)) {
+                versions[versions.length] = parseFloat(output[i].match(regex)[0]);
+            }
+        }
+        versions.sort();
+        console.log(versions[0]);
+        return Q();
+    }, function (stderr) {
+        return Q.reject(stderr);
+    });
+};
+
+exports.get_apple_xcode_version = function () {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -version', function (error, stdout, stderr) {
+        var versionMatch = /Xcode (.*)/.exec(stdout);
+        if (error || !versionMatch) {
+            d.reject(stderr);
+        } else {
+            d.resolve(versionMatch[1]);
+        }
+    });
+    return d.promise;
+};
+
+/**
+ * Gets ios-deploy util version
+ * @return {Promise} Promise that either resolved with ios-deploy version
+ *                           or rejected in case of error
+ */
+exports.get_ios_deploy_version = function () {
+    var d = Q.defer();
+    child_process.exec('ios-deploy --version', function (error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+    return d.promise;
+};
+
+/**
+ * Gets pod (CocoaPods) util version
+ * @return {Promise} Promise that either resolved with pod version
+ *                           or rejected in case of error
+ */
+exports.get_cocoapods_version = function () {
+    var d = Q.defer();
+    child_process.exec('pod --version', function (error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+    return d.promise;
+};
+
+/**
+ * Gets ios-sim util version
+ * @return {Promise} Promise that either resolved with ios-sim version
+ *                           or rejected in case of error
+ */
+exports.get_ios_sim_version = function () {
+    var d = Q.defer();
+    child_process.exec('ios-sim --version', function (error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        } else {
+            d.resolve(stdout);
+        }
+    });
+    return d.promise;
+};
+
+/**
+ * Gets specific tool version
+ * @param  {String} toolName Tool name to check. Known tools are 'xcodebuild', 'ios-sim' and 'ios-deploy'
+ * @return {Promise}         Promise that either resolved with tool version
+ *                                   or rejected in case of error
+ */
+exports.get_tool_version = function (toolName) {
+    switch (toolName) {
+    case 'xcodebuild': return exports.get_apple_xcode_version();
+    case 'ios-sim': return exports.get_ios_sim_version();
+    case 'ios-deploy': return exports.get_ios_deploy_version();
+    case 'pod': return exports.get_cocoapods_version();
+    default: return Q.reject(toolName + ' is not valid tool name. Valid names are: \'xcodebuild\', \'ios-sim\', \'ios-deploy\', and \'pod\'');
+    }
+};
+
+/**
+ * Compares two semver-notated version strings. Returns number
+ * that indicates equality of provided version strings.
+ * @param  {String} version1 Version to compare
+ * @param  {String} version2 Another version to compare
+ * @return {Number}          Negative number if first version is lower than the second,
+ *                                    positive otherwise and 0 if versions are equal.
+ */
+exports.compareVersions = function (version1, version2) {
+    function parseVer (version) {
+        return version.split('.').map(function (value) {
+            // try to convert version segment to Number
+            var parsed = Number(value);
+            // Number constructor is strict enough and will return NaN
+            // if conversion fails. In this case we won't be able to compare versions properly
+            if (isNaN(parsed)) {
+                throw 'Version should contain only numbers and dots';
+            }
+            return parsed;
+        });
+    }
+    var parsedVer1 = parseVer(version1);
+    var parsedVer2 = parseVer(version2);
+
+    // Compare corresponding segments of each version
+    for (var i = 0; i < Math.max(parsedVer1.length, parsedVer2.length); i++) {
+        // if segment is not specified, assume that it is 0
+        // E.g. 3.1 is equal to 3.1.0
+        var ret = (parsedVer1[i] || 0) - (parsedVer2[i] || 0);
+        // if segments are not equal, we're finished
+        if (ret !== 0) return ret;
+    }
+    return 0;
+};
diff --git a/platforms/ios/cordova/log b/platforms/ios/cordova/log
new file mode 100755
index 0000000..b235b09
--- /dev/null
+++ b/platforms/ios/cordova/log
@@ -0,0 +1,23 @@
+#! /bin/sh 
+#
+# 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.
+#
+
+CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd -P)
+
+tail -f "$CORDOVA_PATH/console.log"
diff --git a/platforms/ios/cordova/log.bat b/platforms/ios/cordova/log.bat
new file mode 100755
index 0000000..4710e57
--- /dev/null
+++ b/platforms/ios/cordova/log.bat
@@ -0,0 +1,19 @@
+:: 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
+
+@ECHO OFF
+ECHO WARN: The 'log' command is not available for cordova-ios on windows machines.>&2
diff --git a/platforms/ios/cordova/loggingHelper.js b/platforms/ios/cordova/loggingHelper.js
new file mode 100755
index 0000000..e353399
--- /dev/null
+++ b/platforms/ios/cordova/loggingHelper.js
@@ -0,0 +1,30 @@
+/**
+    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.
+*/
+
+var CordovaLogger = require('cordova-common').CordovaLogger;
+
+module.exports = {
+    adjustLoggerLevel: function (opts) {
+        if (opts.verbose || (Array.isArray(opts) && opts.indexOf('--verbose') !== -1)) {
+            CordovaLogger.get().setLevel('verbose');
+        } else if (opts.silent || (Array.isArray(opts) && opts.indexOf('--silent') !== -1)) {
+            CordovaLogger.get().setLevel('error');
+        }
+    }
+};
diff --git a/platforms/ios/cordova/run b/platforms/ios/cordova/run
new file mode 100755
index 0000000..c4cfca3
--- /dev/null
+++ b/platforms/ios/cordova/run
@@ -0,0 +1,64 @@
+#!/usr/bin/env node
+
+/*
+       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.
+*/
+
+
+var args = process.argv;
+var Api = require('./Api');
+var nopt = require('nopt');
+
+// Handle help flag
+if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
+    require('./lib/run').help();
+    process.exit(0);
+}
+
+// Parse arguments (includes build params as well)
+var opts = nopt({
+    'verbose' : Boolean,
+    'silent' : Boolean,
+    'debug': Boolean,
+    'release': Boolean,
+    'nobuild': Boolean,
+    'archs': String,
+    'list': Boolean,
+    'device': Boolean,
+    'emulator': Boolean,
+    'target' : String,
+    'codeSignIdentity': String,
+    'codeSignResourceRules': String,
+    'provisioningProfile': String,
+    'automaticProvisioning': Boolean,
+    'buildConfig' : String,
+    'noSign' : Boolean
+}, { 'd' : '--verbose' }, args);
+
+// Make options compatible with PlatformApi build method spec
+opts.argv = opts.argv.remain;
+
+require('./loggingHelper').adjustLoggerLevel(opts);
+
+new Api().run(opts).done(function() {
+        console.log('** RUN SUCCEEDED **');
+    }, function (err) {
+        var errorMessage = (err && err.stack) ? err.stack : err;
+        console.error(errorMessage);
+        process.exit(2);
+    });
diff --git a/platforms/ios/cordova/run.bat b/platforms/ios/cordova/run.bat
new file mode 100755
index 0000000..8a3cad2
--- /dev/null
+++ b/platforms/ios/cordova/run.bat
@@ -0,0 +1,19 @@
+:: 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
+
+@ECHO OFF
+ECHO WARN: The `run` is not available for cordova-ios on windows machines.>&2
diff --git a/platforms/ios/cordova/version b/platforms/ios/cordova/version
new file mode 100755
index 0000000..551b437
--- /dev/null
+++ b/platforms/ios/cordova/version
@@ -0,0 +1,35 @@
+#!/usr/bin/env node
+
+/*
+    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.
+*/
+
+/*
+
+    Returns the VERSION of CordovaLib used.
+    Note: it does not work if the --shared option was used to create the project.
+*/
+
+// Coho updates this line
+var VERSION="5.0.1";
+
+module.exports.version = VERSION;
+
+if (!module.parent) {
+    console.log(VERSION);
+}
diff --git a/platforms/ios/cordova/version.bat b/platforms/ios/cordova/version.bat
new file mode 100755
index 0000000..84c86b4
--- /dev/null
+++ b/platforms/ios/cordova/version.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script="%~dp0version"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)
diff --git a/platforms/ios/dlapp.xcarchive/Info.plist b/platforms/ios/dlapp.xcarchive/Info.plist
new file mode 100644
index 0000000..ae2c172
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Info.plist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ApplicationProperties</key>
+	<dict>
+		<key>ApplicationPath</key>
+		<string>Applications/dlapp.app</string>
+		<key>CFBundleIdentifier</key>
+		<string>com.supwisdom.dlapp</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0.0</string>
+		<key>CFBundleVersion</key>
+		<string>1.0.0</string>
+		<key>SigningIdentity</key>
+		<string>iPhone Developer: wang sheng (5Z23CVC58F)</string>
+		<key>Team</key>
+		<string>74UNETA6B2</string>
+	</dict>
+	<key>ArchiveVersion</key>
+	<integer>2</integer>
+	<key>CreationDate</key>
+	<date>2019-07-10T07:54:28Z</date>
+	<key>Name</key>
+	<string>dlapp</string>
+	<key>SchemeName</key>
+	<string>dlapp</string>
+</dict>
+</plist>
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x.png
new file mode 100644
index 0000000..89f0031
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x~ipad.png
new file mode 100644
index 0000000..89f0031
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@3x.png
new file mode 100644
index 0000000..b4f7708
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20~ipad.png
new file mode 100644
index 0000000..97fe2a7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon20x20~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29.png
new file mode 100644
index 0000000..26b9f7d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x.png
new file mode 100644
index 0000000..695a56a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x~ipad.png
new file mode 100644
index 0000000..695a56a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@3x.png
new file mode 100644
index 0000000..6856c41
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29~ipad.png
new file mode 100644
index 0000000..26b9f7d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon29x29~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x.png
new file mode 100644
index 0000000..5616521
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x~ipad.png
new file mode 100644
index 0000000..5616521
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@3x.png
new file mode 100644
index 0000000..d8be90e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40~ipad.png
new file mode 100644
index 0000000..89f0031
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon40x40~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50@2x~ipad.png
new file mode 100644
index 0000000..3c6aab8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50~ipad.png
new file mode 100644
index 0000000..fd39d52
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon50x50~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57.png
new file mode 100644
index 0000000..aac8369
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57@2x.png
new file mode 100644
index 0000000..122e1e5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon57x57@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@2x.png
new file mode 100644
index 0000000..d8be90e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@3x.png
new file mode 100644
index 0000000..5442493
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon60x60@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72@2x~ipad.png
new file mode 100644
index 0000000..4c9c847
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72~ipad.png
new file mode 100644
index 0000000..7b71834
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon72x72~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76@2x~ipad.png
new file mode 100644
index 0000000..11b7fce
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76~ipad.png
new file mode 100644
index 0000000..fa527b6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon76x76~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon83.5x83.5@2x~ipad.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon83.5x83.5@2x~ipad.png
new file mode 100644
index 0000000..6ece2a1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/AppIcon83.5x83.5@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Assets.car b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Assets.car
new file mode 100644
index 0000000..6f3a3a9
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Assets.car
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib
new file mode 100644
index 0000000..7f4b36a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/Info.plist b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/Info.plist
new file mode 100644
index 0000000..32288e8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/Info.plist
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib
new file mode 100644
index 0000000..a974fba
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/CDVLaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftAVFoundation.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftAVFoundation.dylib
new file mode 100755
index 0000000..a0b9479
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftAVFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCore.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCore.dylib
new file mode 100755
index 0000000..2e769e5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCore.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreAudio.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreAudio.dylib
new file mode 100755
index 0000000..b301244
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreAudio.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreFoundation.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreFoundation.dylib
new file mode 100755
index 0000000..35952fc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreGraphics.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreGraphics.dylib
new file mode 100755
index 0000000..372d21d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreGraphics.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreImage.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreImage.dylib
new file mode 100755
index 0000000..e1e0c91
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreImage.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreMedia.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreMedia.dylib
new file mode 100755
index 0000000..6bb4de4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftCoreMedia.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDarwin.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDarwin.dylib
new file mode 100755
index 0000000..f7162f8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDarwin.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDispatch.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDispatch.dylib
new file mode 100755
index 0000000..7a87a05
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftDispatch.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftFoundation.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftFoundation.dylib
new file mode 100755
index 0000000..437a5b6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftMetal.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftMetal.dylib
new file mode 100755
index 0000000..15d0acf
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftMetal.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftObjectiveC.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftObjectiveC.dylib
new file mode 100755
index 0000000..4bce6fa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftObjectiveC.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftQuartzCore.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftQuartzCore.dylib
new file mode 100755
index 0000000..57bcf31
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftQuartzCore.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftSwiftOnoneSupport.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftSwiftOnoneSupport.dylib
new file mode 100755
index 0000000..4117f2a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftSwiftOnoneSupport.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftUIKit.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftUIKit.dylib
new file mode 100755
index 0000000..6eb3de8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftUIKit.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftos.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftos.dylib
new file mode 100755
index 0000000..c398059
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftos.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftsimd.dylib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftsimd.dylib
new file mode 100755
index 0000000..166120d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Frameworks/libswiftsimd.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Info.plist b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Info.plist
new file mode 100644
index 0000000..7072b7a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/Info.plist
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Landscape-2436h@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Landscape-2436h@3x.png
new file mode 100644
index 0000000..f926b05
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Landscape-2436h@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Portrait-2436h@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Portrait-2436h@3x.png
new file mode 100644
index 0000000..483e491
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-1100-Portrait-2436h@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-568h@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-568h@2x.png
new file mode 100644
index 0000000..c3e9666
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-568h@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700-568h@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700-568h@2x.png
new file mode 100644
index 0000000..c3e9666
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700-568h@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700@2x.png
new file mode 100644
index 0000000..2ed9e12
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-700@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-667h@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-667h@2x.png
new file mode 100644
index 0000000..8ad05fb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-667h@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Landscape-736h@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Landscape-736h@3x.png
new file mode 100644
index 0000000..29a3120
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Landscape-736h@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Portrait-736h@3x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Portrait-736h@3x.png
new file mode 100644
index 0000000..1197c0d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage-800-Portrait-736h@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage.png
new file mode 100644
index 0000000..2b19050
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage@2x.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage@2x.png
new file mode 100644
index 0000000..2ed9e12
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/LaunchImage@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/MainViewController.nib b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/MainViewController.nib
new file mode 100644
index 0000000..50fcf8f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/MainViewController.nib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/PkgInfo b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/PkgInfo
@@ -0,0 +1 @@
+APPL????
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/_CodeSignature/CodeResources b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/_CodeSignature/CodeResources
new file mode 100644
index 0000000..38959cc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/_CodeSignature/CodeResources
@@ -0,0 +1,4096 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>AppIcon20x20@2x.png</key>
+		<data>
+		DjEAtviupMghxdL+fkyb3vVUBOI=
+		</data>
+		<key>AppIcon20x20@2x~ipad.png</key>
+		<data>
+		DjEAtviupMghxdL+fkyb3vVUBOI=
+		</data>
+		<key>AppIcon20x20@3x.png</key>
+		<data>
+		BfVRyLrHGHJm+0WuwuOPqz2aCas=
+		</data>
+		<key>AppIcon20x20~ipad.png</key>
+		<data>
+		H6rZilBJB9YKOyY97leKlTxy6XM=
+		</data>
+		<key>AppIcon29x29.png</key>
+		<data>
+		otncBRMMKVzMW+iwsSzrGJYek6w=
+		</data>
+		<key>AppIcon29x29@2x.png</key>
+		<data>
+		Ro2/nf0nqrSy4vCWu94qHBsgntU=
+		</data>
+		<key>AppIcon29x29@2x~ipad.png</key>
+		<data>
+		Ro2/nf0nqrSy4vCWu94qHBsgntU=
+		</data>
+		<key>AppIcon29x29@3x.png</key>
+		<data>
+		QDnu1K3zTpRFbUpH1pc06nQXP/4=
+		</data>
+		<key>AppIcon29x29~ipad.png</key>
+		<data>
+		otncBRMMKVzMW+iwsSzrGJYek6w=
+		</data>
+		<key>AppIcon40x40@2x.png</key>
+		<data>
+		bqhTfe/UUsLmwqwKtmYfpBNyHHE=
+		</data>
+		<key>AppIcon40x40@2x~ipad.png</key>
+		<data>
+		bqhTfe/UUsLmwqwKtmYfpBNyHHE=
+		</data>
+		<key>AppIcon40x40@3x.png</key>
+		<data>
+		7bf8dqKMlGV9BeNvI9Z4FC+62EU=
+		</data>
+		<key>AppIcon40x40~ipad.png</key>
+		<data>
+		DjEAtviupMghxdL+fkyb3vVUBOI=
+		</data>
+		<key>AppIcon50x50@2x~ipad.png</key>
+		<data>
+		04wFY+JbiDwIxpPmec88nEldiCY=
+		</data>
+		<key>AppIcon50x50~ipad.png</key>
+		<data>
+		+ULYPtkyH7TWwGxGEFNW6M8jLYE=
+		</data>
+		<key>AppIcon57x57.png</key>
+		<data>
+		PbF/1dvCpOLYNWV+g1MRQWl4WnE=
+		</data>
+		<key>AppIcon57x57@2x.png</key>
+		<data>
+		V0sslzjLj1HAL3zLlk8dvEctXT0=
+		</data>
+		<key>AppIcon60x60@2x.png</key>
+		<data>
+		7bf8dqKMlGV9BeNvI9Z4FC+62EU=
+		</data>
+		<key>AppIcon60x60@3x.png</key>
+		<data>
+		u4hDZJNq/M9gB/k7ZWPGCQh1dlY=
+		</data>
+		<key>AppIcon72x72@2x~ipad.png</key>
+		<data>
+		6XXlAQJ+2YZtK4XZVDeAXCGQAjs=
+		</data>
+		<key>AppIcon72x72~ipad.png</key>
+		<data>
+		qt7V3ayH99MYvDNK/r88oIVhpxI=
+		</data>
+		<key>AppIcon76x76@2x~ipad.png</key>
+		<data>
+		dPM76DtwjHUolue6BdDUn6RQXnQ=
+		</data>
+		<key>AppIcon76x76~ipad.png</key>
+		<data>
+		mVA2cm+ufolVC0dfMnpXBt7NFYw=
+		</data>
+		<key>AppIcon83.5x83.5@2x~ipad.png</key>
+		<data>
+		F3/BziTbXcn/vpTHvub/+Txde8U=
+		</data>
+		<key>Assets.car</key>
+		<data>
+		T757ffQVmm8esfKqnkpldn+gA+M=
+		</data>
+		<key>CDVLaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>
+		<data>
+		te5vytZWHWAPLMPk0EfV2v2GOck=
+		</data>
+		<key>CDVLaunchScreen.storyboardc/Info.plist</key>
+		<data>
+		n2t8gsDpfE6XkhG31p7IQJRxTxU=
+		</data>
+		<key>CDVLaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>
+		<data>
+		Qc8jkXDDI2czWCVnjtQcBQ3u3Cc=
+		</data>
+		<key>Frameworks/libswiftAVFoundation.dylib</key>
+		<data>
+		hQRQa4h2/Ke/Ec8h8zQINABOX+Y=
+		</data>
+		<key>Frameworks/libswiftCore.dylib</key>
+		<data>
+		KFt3m2PXf7KLtlPH/dFjRxZu/Dc=
+		</data>
+		<key>Frameworks/libswiftCoreAudio.dylib</key>
+		<data>
+		ylfqEtpPpH5bCkjEGK/7yn1I6Ts=
+		</data>
+		<key>Frameworks/libswiftCoreFoundation.dylib</key>
+		<data>
+		dOJd2grXqGYhIrz9CKpe2OXCdo0=
+		</data>
+		<key>Frameworks/libswiftCoreGraphics.dylib</key>
+		<data>
+		oKCWaSlRFg+oK78osXFZfQ3uDuI=
+		</data>
+		<key>Frameworks/libswiftCoreImage.dylib</key>
+		<data>
+		dG50HETdCOQfPRzU0Ic37vCc/9o=
+		</data>
+		<key>Frameworks/libswiftCoreMedia.dylib</key>
+		<data>
+		odFZruKElA+9a+XkB1apq2pyAKw=
+		</data>
+		<key>Frameworks/libswiftDarwin.dylib</key>
+		<data>
+		Ekbogs5rZiDaOKSVVOIKmv8yP2w=
+		</data>
+		<key>Frameworks/libswiftDispatch.dylib</key>
+		<data>
+		KZ/cE5kKCjjALrWnzi/IZiYkeBE=
+		</data>
+		<key>Frameworks/libswiftFoundation.dylib</key>
+		<data>
+		D4CHUkxS6fDieQm0JXhasUkIO3c=
+		</data>
+		<key>Frameworks/libswiftMetal.dylib</key>
+		<data>
+		DL0GBvhxifsCpExV32K3d37vZMk=
+		</data>
+		<key>Frameworks/libswiftObjectiveC.dylib</key>
+		<data>
+		X5Lb3FE34KNAL5snNyu8I7MppoE=
+		</data>
+		<key>Frameworks/libswiftQuartzCore.dylib</key>
+		<data>
+		wpPfT2ZYqDtV8LC7tvoOz5FIvWo=
+		</data>
+		<key>Frameworks/libswiftSwiftOnoneSupport.dylib</key>
+		<data>
+		D38ZqW/kqLjSdad8fvWunNuDSGs=
+		</data>
+		<key>Frameworks/libswiftUIKit.dylib</key>
+		<data>
+		5wMkr51pDRH8PDzP3Bjqk4Qy4cs=
+		</data>
+		<key>Frameworks/libswiftos.dylib</key>
+		<data>
+		Vnurcvfwt3SW/agfJlOdUi1diDY=
+		</data>
+		<key>Frameworks/libswiftsimd.dylib</key>
+		<data>
+		6Z28ZZWvGEuFgIwB9dKwPVtlKfQ=
+		</data>
+		<key>Info.plist</key>
+		<data>
+		A4Mfmv7TuPjhah3GagYVHZqgqJE=
+		</data>
+		<key>LaunchImage-1100-Landscape-2436h@3x.png</key>
+		<data>
+		LEdpganmedvHWweqF8iLow1TPLo=
+		</data>
+		<key>LaunchImage-1100-Portrait-2436h@3x.png</key>
+		<data>
+		1s+ysYN76gL1pE3B0EhXb01TzdA=
+		</data>
+		<key>LaunchImage-568h@2x.png</key>
+		<data>
+		uL21BlZJ/oQEajleUn14FTTZ7sM=
+		</data>
+		<key>LaunchImage-700-568h@2x.png</key>
+		<data>
+		uL21BlZJ/oQEajleUn14FTTZ7sM=
+		</data>
+		<key>LaunchImage-700@2x.png</key>
+		<data>
+		p3fC93dHhA5tenQ6Ms/OAzSmHGY=
+		</data>
+		<key>LaunchImage-800-667h@2x.png</key>
+		<data>
+		hS7N0w32F9JOazHaI7UvfliwaVM=
+		</data>
+		<key>LaunchImage-800-Landscape-736h@3x.png</key>
+		<data>
+		BMiTgfs0nCUuv79rKBlo9K6pP0I=
+		</data>
+		<key>LaunchImage-800-Portrait-736h@3x.png</key>
+		<data>
+		RV8pvGiU/AXzpWjjTuqPxdFYFAg=
+		</data>
+		<key>LaunchImage.png</key>
+		<data>
+		yGXeBtC8p4UEwup1J2ZWE3M8vdw=
+		</data>
+		<key>LaunchImage@2x.png</key>
+		<data>
+		p3fC93dHhA5tenQ6Ms/OAzSmHGY=
+		</data>
+		<key>MainViewController.nib</key>
+		<data>
+		HGQoZCqsnAcpXpUU2Euwer6XpSk=
+		</data>
+		<key>PkgInfo</key>
+		<data>
+		n57qDP4tZfLD1rCS43W0B4LQjzE=
+		</data>
+		<key>config.xml</key>
+		<data>
+		4Ey/jpgwhwU4OCZf57u3NVkF1xQ=
+		</data>
+		<key>embedded.mobileprovision</key>
+		<data>
+		WNm5zuPz65rrY9t5qIL1iJgFcQ8=
+		</data>
+		<key>www/bill.html</key>
+		<data>
+		1Q6bs+kjPSyg+Yl2MrIlAdkCDEM=
+		</data>
+		<key>www/billdetail.html</key>
+		<data>
+		y/BRy2p3Q5Cx9yIIKJSruC5hdVU=
+		</data>
+		<key>www/bindcard.html</key>
+		<data>
+		9PZ9wKXqzkXFm00p7Y0R3qjtldY=
+		</data>
+		<key>www/card.html</key>
+		<data>
+		kDKEBSjs2KNfSwut3SEeB63fJ34=
+		</data>
+		<key>www/cardinfor.html</key>
+		<data>
+		QQg8HZreHawxjyGafVvCyGhCGrw=
+		</data>
+		<key>www/cordova-js-src/exec.js</key>
+		<data>
+		3QDPaUQrAr8Wq2XcQhqcl8DLabQ=
+		</data>
+		<key>www/cordova-js-src/platform.js</key>
+		<data>
+		ujxMgcZCzzuK4VAjaNIfsORGeNU=
+		</data>
+		<key>www/cordova-js-src/plugin/ios/console.js</key>
+		<data>
+		QiM8MHQKHSj59wvBt/HHviQ0nms=
+		</data>
+		<key>www/cordova-js-src/plugin/ios/logger.js</key>
+		<data>
+		doSoID4yQ7Z8GrTg9sMfeIjMlDU=
+		</data>
+		<key>www/cordova.js</key>
+		<data>
+		m8O8WSj370y+bdGWAUF2JiU6Qnw=
+		</data>
+		<key>www/cordova_plugins.js</key>
+		<data>
+		5yQtgIC/T2E5OFopQG2kN+WdYrI=
+		</data>
+		<key>www/css/aui-iconfont.ttf</key>
+		<data>
+		bgBa9eNE+SIBMMSGsOaLdlkaqCo=
+		</data>
+		<key>www/css/aui.css</key>
+		<data>
+		6xyvpUD036ik6Mg3P+cYQ1NrzQ0=
+		</data>
+		<key>www/css/index.css</key>
+		<data>
+		303YwSwtG9jcxpjzgcZJ0eqHSKg=
+		</data>
+		<key>www/css/jquery-weui.min.css</key>
+		<data>
+		JJJVkVnNsjnLAe5ZCqLG6ihqAX4=
+		</data>
+		<key>www/css/weui.min.css</key>
+		<data>
+		xzTaeGLEw+pLemNK6/MLliqngZM=
+		</data>
+		<key>www/dobind.html</key>
+		<data>
+		bPlHLLWGMLQhGS93aI71OYjow/0=
+		</data>
+		<key>www/editpaypwd.html</key>
+		<data>
+		0auYgJFadz+CglQBW5qKxfebL/c=
+		</data>
+		<key>www/editpwd.html</key>
+		<data>
+		XoVr9QA+cY59iWDpWbw5olgSrXU=
+		</data>
+		<key>www/error.html</key>
+		<data>
+		UDoxz7BHRgnZPQOdYy1XRMxlqBE=
+		</data>
+		<key>www/findpaypwd.html</key>
+		<data>
+		dwUuT831xBqurx4U2tle0AgTbyQ=
+		</data>
+		<key>www/findpwd.html</key>
+		<data>
+		gC2QYIEKPpr5CDu0OZl7auJQIUo=
+		</data>
+		<key>www/img/back.png</key>
+		<data>
+		2Q/cRIn6pwRXGAOdeqfhxY/2imI=
+		</data>
+		<key>www/img/close.png</key>
+		<data>
+		0XukISSDdlZnyQv+QDff6qw52r8=
+		</data>
+		<key>www/img/close_1.png</key>
+		<data>
+		qEqPVoLhX1FBSsmzSYaIVwKYnsk=
+		</data>
+		<key>www/img/icon_auth.png</key>
+		<data>
+		G1UhJYGGEC6V8OKvE2goXDsiYP0=
+		</data>
+		<key>www/img/icon_bill.png</key>
+		<data>
+		EacO2/9ZXgO4asWq/ejNiv4oIF4=
+		</data>
+		<key>www/img/icon_car.png</key>
+		<data>
+		clao0p4qsWbdM8nSEpyuK7FNiMg=
+		</data>
+		<key>www/img/icon_card.png</key>
+		<data>
+		vCr7vtkPuVHx3XBpJF0QrFYmg48=
+		</data>
+		<key>www/img/icon_header.png</key>
+		<data>
+		4drNX8zyyrek1c2JXqfXQR2KfZI=
+		</data>
+		<key>www/img/icon_meal.png</key>
+		<data>
+		06mY5fqZWPnzDdCwe5IgbU3fDbw=
+		</data>
+		<key>www/img/icon_ok.png</key>
+		<data>
+		n5SPEi0cP0wnLbHN/9D04nL1Tb8=
+		</data>
+		<key>www/img/icon_qrcode.png</key>
+		<data>
+		Tkh150zO/sdywOPDrSK6ou4VQhk=
+		</data>
+		<key>www/img/icon_scan.png</key>
+		<data>
+		NK0zbLpB/729gkxvCiVBnj8R+so=
+		</data>
+		<key>www/img/icon_securty.png</key>
+		<data>
+		A/2jQ8YjXC0HrT2MT/zuS5HmlGQ=
+		</data>
+		<key>www/img/icon_water.png</key>
+		<data>
+		K7bemny8Y7OGsoLB7APPmep+KBc=
+		</data>
+		<key>www/img/light.png</key>
+		<data>
+		keI5n58zmYufnBljGJxgOOqdZPE=
+		</data>
+		<key>www/img/scanner.svg</key>
+		<data>
+		Url7I2VNTxsMJ+0yFoayWTFLnfw=
+		</data>
+		<key>www/index.html</key>
+		<data>
+		5T2zYcDtNLEO0qcTZGgyv5wCdsQ=
+		</data>
+		<key>www/js/bill.js</key>
+		<data>
+		PtiPisUNF3iV9vPSlzdIpHwidUg=
+		</data>
+		<key>www/js/billdetail.js</key>
+		<data>
+		Df3zwuOjyxYT1atvBcZGR3EVdh4=
+		</data>
+		<key>www/js/bindcard.js</key>
+		<data>
+		QcQm/WcOXL3pjL8WUEBsXTDLCmQ=
+		</data>
+		<key>www/js/card.js</key>
+		<data>
+		pIuWD/nNiuDsXe2wowI2s9+3FQE=
+		</data>
+		<key>www/js/cardinfor.js</key>
+		<data>
+		H5Qek3wUoBtXbL/Ry+v/gt4riXg=
+		</data>
+		<key>www/js/db.js</key>
+		<data>
+		Vb7u+G5BFFGhnbBNfdZiVfTDP4I=
+		</data>
+		<key>www/js/editpaypwd.js</key>
+		<data>
+		ZyqrsAJhe9yLp35qpeeVAMOMFNg=
+		</data>
+		<key>www/js/editpwd.js</key>
+		<data>
+		AONikpSnuBp7psEqpQTTZCTIu1w=
+		</data>
+		<key>www/js/findpaypwd.js</key>
+		<data>
+		tA9kUDZ60JHG/3d4R4N9DUkLAG0=
+		</data>
+		<key>www/js/findpwd.js</key>
+		<data>
+		ooTBY2pzkPyuCeBdjhpYIRQGHz4=
+		</data>
+		<key>www/js/index.js</key>
+		<data>
+		7VB6kBtU0FQ+JUAh0cbyy2dfHak=
+		</data>
+		<key>www/js/lib/aui-actionsheet.js</key>
+		<data>
+		k43Wv7PPTuTyR1EUlwbusit0uo4=
+		</data>
+		<key>www/js/lib/aui-collapse.js</key>
+		<data>
+		PcFD5a7aQGYMO9bDPOIhe18DEiM=
+		</data>
+		<key>www/js/lib/aui-dialog.js</key>
+		<data>
+		3fVPO33iXt4/iAMGp9qRYz9VzJw=
+		</data>
+		<key>www/js/lib/aui-lazyload.js</key>
+		<data>
+		X3pkec58gL2uj3v8nvsRT/zYnTI=
+		</data>
+		<key>www/js/lib/aui-list-swipe-backup.js</key>
+		<data>
+		zjTgZbyH1/qY9xlXJ777ggvHwSk=
+		</data>
+		<key>www/js/lib/aui-list-swipe.js</key>
+		<data>
+		RJSPeNc+3IoE9NG+nbmJovLvbBI=
+		</data>
+		<key>www/js/lib/aui-popup-new.js</key>
+		<data>
+		gXw6tzg/hrrBNpZSJBIER5Mv+S4=
+		</data>
+		<key>www/js/lib/aui-popup.js</key>
+		<data>
+		JXsvRZu82Fk7FCARmTJDmkP495c=
+		</data>
+		<key>www/js/lib/aui-pull-refresh.js</key>
+		<data>
+		VIyUsJMbzX81zEkOq6MjbnHqc7c=
+		</data>
+		<key>www/js/lib/aui-range.js</key>
+		<data>
+		cZf0K7lQ9CQ8DPN7+cXfbwewHjU=
+		</data>
+		<key>www/js/lib/aui-scroll.js</key>
+		<data>
+		rU2uqVzf52oVKPolaoq9muinl08=
+		</data>
+		<key>www/js/lib/aui-sharebox.js</key>
+		<data>
+		D/mRv8xXyZkdCn6xbBRpQXLyhlo=
+		</data>
+		<key>www/js/lib/aui-skin.js</key>
+		<data>
+		MXDxnju1mt2Es/Uqu/f1CqYdRqQ=
+		</data>
+		<key>www/js/lib/aui-slide.js</key>
+		<data>
+		xC+oaMpn8oCCLqxFx70HIxECU8M=
+		</data>
+		<key>www/js/lib/aui-tab.js</key>
+		<data>
+		D9KTddViayJQ1e+U5i1Ak+nBRE8=
+		</data>
+		<key>www/js/lib/aui-toast.js</key>
+		<data>
+		H8BfA5yAWFAiIieKsDh2VQP58B4=
+		</data>
+		<key>www/js/lib/city-picker.js</key>
+		<data>
+		83Okg34aIKXmAfjbwn8ghcAF04w=
+		</data>
+		<key>www/js/lib/city-picker.min.js</key>
+		<data>
+		tEME1JHsZSZX1OO/00AESKA1bJ8=
+		</data>
+		<key>www/js/lib/jquery-2.1.4.js</key>
+		<data>
+		D+1FrXpIrOhpvHJcpHSthqHvFWI=
+		</data>
+		<key>www/js/lib/jquery-weui.js</key>
+		<data>
+		+3joFaV28ZGz8NBkVgIq4M7tfhs=
+		</data>
+		<key>www/js/lib/jquery-weui.min.js</key>
+		<data>
+		JqNM+qw68fjSEeY2yiOFqA6nu/8=
+		</data>
+		<key>www/js/lib/jquery.mobile-1.4.5.min.js</key>
+		<data>
+		/FXTZ8cnK93oBw+FGvRYS7wQsug=
+		</data>
+		<key>www/js/lib/qrcode.min.js</key>
+		<data>
+		LQbB+CPzTBmYHGrgsOsPWGHF4Us=
+		</data>
+		<key>www/js/lib/swiper.js</key>
+		<data>
+		dpz0tV0hx3JqEehZho0/fwk5dE4=
+		</data>
+		<key>www/js/lib/swiper.min.js</key>
+		<data>
+		g7iXAN78S/xWzSRE7clYTjjw1hQ=
+		</data>
+		<key>www/js/login.js</key>
+		<data>
+		GnaACCIZ8j2xg8PJGAWxS4CymgM=
+		</data>
+		<key>www/js/main.js</key>
+		<data>
+		0LqnXw5oToAfNnPBWMOt3Pj41y4=
+		</data>
+		<key>www/js/mobile.js</key>
+		<data>
+		lmaKo3x9bgrYBEk7Fh2+/qAg6mI=
+		</data>
+		<key>www/js/paypwdmng.js</key>
+		<data>
+		A1a1mztONeZQbLMhwzbhc2/yv0k=
+		</data>
+		<key>www/js/paypwdset.js</key>
+		<data>
+		SMBcGN/6F4U5a2cmkI6W0Pn7apU=
+		</data>
+		<key>www/js/pwdset.js</key>
+		<data>
+		iVznXYlssRXP6OIfCRDZ9A/blF0=
+		</data>
+		<key>www/js/qrcode.js</key>
+		<data>
+		nUamfLQSBc/NAzOMJP5WwXnZGxI=
+		</data>
+		<key>www/js/register.js</key>
+		<data>
+		aPLw5ln4ElwhbTzbdXZpyILJBiY=
+		</data>
+		<key>www/js/scan.js</key>
+		<data>
+		FahF/fMDsR1+zrs4BFASK2HvtUE=
+		</data>
+		<key>www/js/security.js</key>
+		<data>
+		s52wwGEv5fJuX8ngkR5GGqdAXMg=
+		</data>
+		<key>www/js/server.js</key>
+		<data>
+		8l2vn+ra5zayhEwQQpy1806GZX8=
+		</data>
+		<key>www/js/signxy.js</key>
+		<data>
+		gDocQNgzvA/TxPmLCDCjG8iRQGQ=
+		</data>
+		<key>www/js/signxycheck.js</key>
+		<data>
+		gDocQNgzvA/TxPmLCDCjG8iRQGQ=
+		</data>
+		<key>www/js/uxy.js</key>
+		<data>
+		YV3C17xDBTm8vmpn5vtSah8uQVc=
+		</data>
+		<key>www/login.html</key>
+		<data>
+		MbU55+r7AuMxeK8D6a+pTzgRSU4=
+		</data>
+		<key>www/login1.html</key>
+		<data>
+		uf9qCJKdYuGpG6HiVEwnDhtuF/g=
+		</data>
+		<key>www/main.html</key>
+		<data>
+		gOippmPYY80xg/JnHqP8Kpg59H8=
+		</data>
+		<key>www/main1.html</key>
+		<data>
+		aTWSKs5RwWeuZBA1D5QOA0INVcY=
+		</data>
+		<key>www/mobileui/css/alert.min.css</key>
+		<data>
+		jYO6/4Av8ReiEsQqN2QGcbBRLXw=
+		</data>
+		<key>www/mobileui/css/base.min.css</key>
+		<data>
+		0QzpyxWU+iiFLLd6fIFNg/DHljA=
+		</data>
+		<key>www/mobileui/css/button.min.css</key>
+		<data>
+		lJJG/2v48hM67nFqihEQeZH8lhU=
+		</data>
+		<key>www/mobileui/css/chart-bar.min.css</key>
+		<data>
+		Iojhce0KFhtCMpxglUh4PEjGUyU=
+		</data>
+		<key>www/mobileui/css/chartist-plugin-tooltip.min.css</key>
+		<data>
+		4BLRESrZYbj5vw35KGvOE1ab8IQ=
+		</data>
+		<key>www/mobileui/css/chartist.min.css</key>
+		<data>
+		cHCZqIK22tK06U8yx7bHuJYZe3U=
+		</data>
+		<key>www/mobileui/css/chartjs.min.css</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/css/cover.min.css</key>
+		<data>
+		QE0+0dSOklJMlooYxEoptPCACUg=
+		</data>
+		<key>www/mobileui/css/fonts/ionicons.woff</key>
+		<data>
+		5GgZ6GOkZ1HWIsEZDE6Kg+vCBhI=
+		</data>
+		<key>www/mobileui/css/fonts/roboto.woff2</key>
+		<data>
+		HEy0LoEUSXT01k1W8XgHmkAfldM=
+		</data>
+		<key>www/mobileui/css/fonts/robotoblack.woff2</key>
+		<data>
+		lCeboh+O5pxgIIGxpfJcmKWz5F4=
+		</data>
+		<key>www/mobileui/css/fonts/robotolight.woff2</key>
+		<data>
+		vDVc3zziS5SAbNZcRDgP21RkluI=
+		</data>
+		<key>www/mobileui/css/gfont.css</key>
+		<data>
+		jA3wb2s1BfNIpZEYO76br1fCono=
+		</data>
+		<key>www/mobileui/css/grid.min.css</key>
+		<data>
+		aM0i6KhoWieRrg4EHW6d/om/RcA=
+		</data>
+		<key>www/mobileui/css/header.min.css</key>
+		<data>
+		n3mqFc12zN2mkpdsBu871X+TTUs=
+		</data>
+		<key>www/mobileui/css/horizontal-scroll.min.css</key>
+		<data>
+		uTFUDzDcpEjcSoKtO3q+S3jbA5o=
+		</data>
+		<key>www/mobileui/css/imports.css</key>
+		<data>
+		8xusdKfTeZmEhAq0LnzqLhG00dQ=
+		</data>
+		<key>www/mobileui/css/include.min.css</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/css/input.min.css</key>
+		<data>
+		ercWR2cY6OhncYzB3E24Bjvbrow=
+		</data>
+		<key>www/mobileui/css/list.min.css</key>
+		<data>
+		pcfSQo5LDs82DlAfqV0mW8lKvco=
+		</data>
+		<key>www/mobileui/css/loading.min.css</key>
+		<data>
+		ZkmT9wT87vx7CComvc1hX+6PWNo=
+		</data>
+		<key>www/mobileui/css/menu.min.css</key>
+		<data>
+		IuFE5Q8gSrEFlQgCq9LntKUPEVw=
+		</data>
+		<key>www/mobileui/css/mobileui-colors.min.css</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/css/mobileuijs.min.css</key>
+		<data>
+		GDBlbooCkiI7KrLQgIfqvNFXQhY=
+		</data>
+		<key>www/mobileui/css/page.min.css</key>
+		<data>
+		i61rcCBajdql9yqv+aHt86RSa68=
+		</data>
+		<key>www/mobileui/css/popover.min.css</key>
+		<data>
+		ZvJifglSJtqJVWaMjyav6RLyeOg=
+		</data>
+		<key>www/mobileui/css/progress-circle.min.css</key>
+		<data>
+		xab3Ea8xBjnXNilms8joImBqbnI=
+		</data>
+		<key>www/mobileui/css/progress-circular.min.css</key>
+		<data>
+		UoM8lLhFNSyQtvDxt0ibUgV/T2U=
+		</data>
+		<key>www/mobileui/css/progress-semicircle.min.css</key>
+		<data>
+		TYOuItvNSbnVKRAnUI2RsmkOfYw=
+		</data>
+		<key>www/mobileui/css/progressbarjs.min.css</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/css/swiper.min.css</key>
+		<data>
+		yb967T5eM7uJiyYS+0Vlw05Dvl8=
+		</data>
+		<key>www/mobileui/css/tab.min.css</key>
+		<data>
+		m5Pa+SPhOX2ZW+HvdpAVKgPxxYY=
+		</data>
+		<key>www/mobileui/css/timeline.min.css</key>
+		<data>
+		vlGLEQUQHfqmaLioRZgfUtZtdvs=
+		</data>
+		<key>www/mobileui/css/toast.min.css</key>
+		<data>
+		FOGYi6PxJdlnIyBljMUwYPIV9Pc=
+		</data>
+		<key>www/mobileui/js/alert.min.js</key>
+		<data>
+		LfHTnMVvCVNgOxX8kp8yUv0oAJU=
+		</data>
+		<key>www/mobileui/js/base.min.js</key>
+		<data>
+		kwq2Hvjo/B2LfAhJjBljw9OLe/o=
+		</data>
+		<key>www/mobileui/js/button.min.js</key>
+		<data>
+		PHkFHAPXrevpUvOpGV1OeLxSXM0=
+		</data>
+		<key>www/mobileui/js/chart-bar.min.js</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/js/chartist-plugin-tooltip.min.js</key>
+		<data>
+		IVoCnydBptGYwpUi7fja+xBCdS0=
+		</data>
+		<key>www/mobileui/js/chartist.min.js</key>
+		<data>
+		c6Me7+DxNGPEn5C9Dwtl/Tu9ONQ=
+		</data>
+		<key>www/mobileui/js/chartjs.min.js</key>
+		<data>
+		CxDapOKmSZQKlEFU/CreAX/Oowc=
+		</data>
+		<key>www/mobileui/js/include.min.js</key>
+		<data>
+		rQJkO7qNh7V6IRyVJ7G72XVIF8I=
+		</data>
+		<key>www/mobileui/js/input.min.js</key>
+		<data>
+		BaLNs6W7F9XN8yghwB8reYw0uc8=
+		</data>
+		<key>www/mobileui/js/jquery.min.js</key>
+		<data>
+		xGO1JUuE7CIisKPpNE0e+3OtQn8=
+		</data>
+		<key>www/mobileui/js/loading.min.js</key>
+		<data>
+		3AvjaNooLSHVduwWCty/ZKRHMnk=
+		</data>
+		<key>www/mobileui/js/menu.min.js</key>
+		<data>
+		6a/9f5KoapYzscm8YwHvJM0eQXs=
+		</data>
+		<key>www/mobileui/js/mobileui-colors.min.js</key>
+		<data>
+		1Rq4XGVDhTudtaSwNHsqFgEeKXU=
+		</data>
+		<key>www/mobileui/js/mobileuijs.min.js</key>
+		<data>
+		1lwAb8h1+O1HKaL5T/Qt2ZtcFTA=
+		</data>
+		<key>www/mobileui/js/momentjs.min.js</key>
+		<data>
+		4VJgVytpHZ/slyLzmCYeIzuWNQU=
+		</data>
+		<key>www/mobileui/js/page.min.js</key>
+		<data>
+		3gw3uDYgD8Y5xsjSB/8tjEiEzTk=
+		</data>
+		<key>www/mobileui/js/popover.min.js</key>
+		<data>
+		yGz5Ik/RAUbGr9x2LBSSvBMfXD4=
+		</data>
+		<key>www/mobileui/js/progress-circle.min.js</key>
+		<data>
+		chiZ1v273z4xiA6okgaS5zzlDs0=
+		</data>
+		<key>www/mobileui/js/progress-circular.min.js</key>
+		<data>
+		2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+		</data>
+		<key>www/mobileui/js/progress-semicircle.min.js</key>
+		<data>
+		h7qDXHoEJrTSEHaw9noGk0MJi9c=
+		</data>
+		<key>www/mobileui/js/progressbarjs.min.js</key>
+		<data>
+		qjjwCxEqt+D7o3UY9GSbfxcZBYk=
+		</data>
+		<key>www/mobileui/js/pulltorefresh.min.js</key>
+		<data>
+		hKuS2jMxIaJ7MyUCUHxlFuvq19s=
+		</data>
+		<key>www/mobileui/js/swiper.min.js</key>
+		<data>
+		nU+uUsS4VEnKzLC0B1OPDeLXut4=
+		</data>
+		<key>www/mobileui/js/tab.min.js</key>
+		<data>
+		kCGVo9TQHEaDIaM1SXtTnmC5ozQ=
+		</data>
+		<key>www/mobileui/js/toast.min.js</key>
+		<data>
+		5q7tLrz0Cd6KddL57WTWFL9tnq8=
+		</data>
+		<key>www/mobileui/mobileui.js</key>
+		<data>
+		g2anuCpLPUx/U3O/mFdaMI7m7a0=
+		</data>
+		<key>www/mobileui/style.css</key>
+		<data>
+		heGNNKQaZlidpB3qvXFXCW/7bX0=
+		</data>
+		<key>www/paypwdmng.html</key>
+		<data>
+		+Mjis5f4NK8v7VpKUbilfHxz4no=
+		</data>
+		<key>www/paypwdset.html</key>
+		<data>
+		jk0aykLVh641N2POWhpQBCd1gpw=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/advanced-http.js</key>
+		<data>
+		B8n20vLKxAKUZXJMxaWXV6gbh2g=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js</key>
+		<data>
+		oigj9UWbSZ7wilh4lNqA+/0zRi8=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/global-configs.js</key>
+		<data>
+		on11EqlCJXmxELeXuLpMjxXAoN4=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/helpers.js</key>
+		<data>
+		7zDV1mSEzs8Zrrge1l4b8uo0/Ms=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/js-util.js</key>
+		<data>
+		8SpJyt/PDx7N78EdBnsMGuyvVRY=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js</key>
+		<data>
+		Ehxxu28zPv4FNqoEmNEWWsAmcgU=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/lodash.js</key>
+		<data>
+		UYDd8AwVTHEkAY2Vuqarw4qHqNU=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/messages.js</key>
+		<data>
+		a+LSD4JskmzyBECg0xOc94fVEik=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/public-interface.js</key>
+		<data>
+		fxOWbnRNP19ezKuY8y92WUueT/8=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js</key>
+		<data>
+		LdGHCdPTclRj5d2Fie8n45Zrqos=
+		</data>
+		<key>www/plugins/cordova-plugin-advanced-http/www/url-util.js</key>
+		<data>
+		09a/If3TGPR46gxmzbSwdbcSvBc=
+		</data>
+		<key>www/plugins/cordova-plugin-camera/www/Camera.js</key>
+		<data>
+		/Tl12sGFo/UZbPqnupaaV0Hg0vU=
+		</data>
+		<key>www/plugins/cordova-plugin-camera/www/CameraConstants.js</key>
+		<data>
+		v2sA7ZeHf4g2R4hremuTEjIZPUY=
+		</data>
+		<key>www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js</key>
+		<data>
+		DFjhGlevsoLz/p7Ls+/7LBfept8=
+		</data>
+		<key>www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js</key>
+		<data>
+		koRc23xo1lElHctG97l7ayo1asw=
+		</data>
+		<key>www/plugins/cordova-plugin-device/www/device.js</key>
+		<data>
+		1GfO/IDwwyLde/veo05ABQB5yTk=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/DirectoryEntry.js</key>
+		<data>
+		9BG1PRAVfskBKfTqRqUcFP0XF9c=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/DirectoryReader.js</key>
+		<data>
+		55JSYGGn83vzv0lzH64YGshyORE=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/Entry.js</key>
+		<data>
+		ApUt9yA8EFcC9lNWD2XthcwuD90=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/File.js</key>
+		<data>
+		0LUBfKUsBSQvmUgurtpKYgJ9hTc=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileEntry.js</key>
+		<data>
+		ihG+3x+RWP1Qk72v0C0MZRzRpBM=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileError.js</key>
+		<data>
+		ybFlxPqO/jPqMsmoDwkc2rpE4pk=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileReader.js</key>
+		<data>
+		L5sKPsNlBpVIEJtZOnDhtA1g05M=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileSystem.js</key>
+		<data>
+		DmfGhjz4PYPDj99FWJ3nDLQzZFU=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileUploadOptions.js</key>
+		<data>
+		4mPbde3/XqIbBp41y0kN00aYZl4=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileUploadResult.js</key>
+		<data>
+		4CNnib6yO4/uwX7VyIeJgpFLHFU=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/FileWriter.js</key>
+		<data>
+		vbjAors/bOvXxKiKru01s/f2AxY=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/Flags.js</key>
+		<data>
+		Ysk6KgwRoqjZINAl/q0VjlC2vmA=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/LocalFileSystem.js</key>
+		<data>
+		kJtPgG7aLCq5neelEB+/sObHR1w=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/Metadata.js</key>
+		<data>
+		sNBGG0nAD0xDLoOYeaiDlfLVBBM=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/ProgressEvent.js</key>
+		<data>
+		blyr1jNE9lOGJJOyQkWfS+CB+7o=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/browser/isChrome.js</key>
+		<data>
+		ubIP1VXq/ILYzY1GaBx+PA7ZEEo=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/fileSystemPaths.js</key>
+		<data>
+		RhbxeeiCkMHVAnWLOaEFTyx3fVk=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/fileSystems-roots.js</key>
+		<data>
+		jPjM9Gkr4Fs2O+qPCdRiDfQRmF8=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/fileSystems.js</key>
+		<data>
+		GjxvyRube37zK13yXu3TWWdWPpQ=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/ios/FileSystem.js</key>
+		<data>
+		3ueSGiRIUcEFNSxl7V3z1JdmqWA=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/requestFileSystem.js</key>
+		<data>
+		ZVeb2nnbn/aetQV5ipRWH7M+Q9c=
+		</data>
+		<key>www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js</key>
+		<data>
+		p7A9a+/7es1E4aKJPkx0j6eQwuw=
+		</data>
+		<key>www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js</key>
+		<data>
+		I6HhWVv3fSBNmlXWaeqJGHD2g4c=
+		</data>
+		<key>www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js</key>
+		<data>
+		04BAdz7ulKVCu3lMDwCrtzoPTJA=
+		</data>
+		<key>www/plugins/cordova-plugin-qrscanner/www/www.min.js</key>
+		<data>
+		ufmAW+h1oKmygvcqG3eipjK7YXo=
+		</data>
+		<key>www/plugins/cordova-plugin-statusbar/www/statusbar.js</key>
+		<data>
+		hDT++3ZaOTp3t16AAFAibxtovj0=
+		</data>
+		<key>www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js</key>
+		<data>
+		TvdsWbaWx459ckVtYew11Fv3LHk=
+		</data>
+		<key>www/plugins/cordova-plugin-touch-id/www/TouchID.js</key>
+		<data>
+		oGafU2UdHnS6q3vnNz3WB2an0TY=
+		</data>
+		<key>www/pwdset.html</key>
+		<data>
+		V3rync0T0/WyYm1RxOmrQ0VHwls=
+		</data>
+		<key>www/qrcode.html</key>
+		<data>
+		/T8vAhNAeCOJv1Hw6L4detL0zZE=
+		</data>
+		<key>www/register.html</key>
+		<data>
+		j0E17LezraXxL2i9s0tnnWrl9vw=
+		</data>
+		<key>www/scan.html</key>
+		<data>
+		S7i5xbTkGWEkJnCEypdQTNWiAJs=
+		</data>
+		<key>www/security.html</key>
+		<data>
+		WAAOaAVzFhUpl9ay3iHsxkW83wo=
+		</data>
+		<key>www/signxy.html</key>
+		<data>
+		puCiWzwhuAhLymirq4ajsw8iYJw=
+		</data>
+		<key>www/signxycheck.html</key>
+		<data>
+		OC5VO7siXCVWFdZQFLrRkOG5Jdk=
+		</data>
+		<key>www/uxy.html</key>
+		<data>
+		jMDdxxafEFBcjhH4qe9hZ4Pytho=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>AppIcon20x20@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DjEAtviupMghxdL+fkyb3vVUBOI=
+			</data>
+			<key>hash2</key>
+			<data>
+			8gs3eoIb4H9cpuPaDkErBai6L4FZOZfyttI/pYM3Hw4=
+			</data>
+		</dict>
+		<key>AppIcon20x20@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DjEAtviupMghxdL+fkyb3vVUBOI=
+			</data>
+			<key>hash2</key>
+			<data>
+			8gs3eoIb4H9cpuPaDkErBai6L4FZOZfyttI/pYM3Hw4=
+			</data>
+		</dict>
+		<key>AppIcon20x20@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			BfVRyLrHGHJm+0WuwuOPqz2aCas=
+			</data>
+			<key>hash2</key>
+			<data>
+			wB8DRUnh3AMIUfOsoN2UakYsGsGtVsCMKPqymkIfzys=
+			</data>
+		</dict>
+		<key>AppIcon20x20~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			H6rZilBJB9YKOyY97leKlTxy6XM=
+			</data>
+			<key>hash2</key>
+			<data>
+			sDvITbxB8+WSbGLw2hi9wNucw935HeGWu6F47RDuyDo=
+			</data>
+		</dict>
+		<key>AppIcon29x29.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			otncBRMMKVzMW+iwsSzrGJYek6w=
+			</data>
+			<key>hash2</key>
+			<data>
+			j3+Oyaoj9BUqxemeJFSZ5I6ZMXcDWGER+zX0zKI5qXk=
+			</data>
+		</dict>
+		<key>AppIcon29x29@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Ro2/nf0nqrSy4vCWu94qHBsgntU=
+			</data>
+			<key>hash2</key>
+			<data>
+			bGGPXkSeFsyh7eAmq5YgeHYkFDjIsqsr4Yt3dpj09N0=
+			</data>
+		</dict>
+		<key>AppIcon29x29@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Ro2/nf0nqrSy4vCWu94qHBsgntU=
+			</data>
+			<key>hash2</key>
+			<data>
+			bGGPXkSeFsyh7eAmq5YgeHYkFDjIsqsr4Yt3dpj09N0=
+			</data>
+		</dict>
+		<key>AppIcon29x29@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			QDnu1K3zTpRFbUpH1pc06nQXP/4=
+			</data>
+			<key>hash2</key>
+			<data>
+			2TxWQw5j1QBbjE38vdn2xOMy4knvqkZ/nNLUWNt0sCI=
+			</data>
+		</dict>
+		<key>AppIcon29x29~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			otncBRMMKVzMW+iwsSzrGJYek6w=
+			</data>
+			<key>hash2</key>
+			<data>
+			j3+Oyaoj9BUqxemeJFSZ5I6ZMXcDWGER+zX0zKI5qXk=
+			</data>
+		</dict>
+		<key>AppIcon40x40@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			bqhTfe/UUsLmwqwKtmYfpBNyHHE=
+			</data>
+			<key>hash2</key>
+			<data>
+			tFvg6swsA5hwLRDfRCDi7CMI0P+ViFf6IgRScxSlb/0=
+			</data>
+		</dict>
+		<key>AppIcon40x40@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			bqhTfe/UUsLmwqwKtmYfpBNyHHE=
+			</data>
+			<key>hash2</key>
+			<data>
+			tFvg6swsA5hwLRDfRCDi7CMI0P+ViFf6IgRScxSlb/0=
+			</data>
+		</dict>
+		<key>AppIcon40x40@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			7bf8dqKMlGV9BeNvI9Z4FC+62EU=
+			</data>
+			<key>hash2</key>
+			<data>
+			5V8UjSCgkmKRVOYu+FRB0+yhTL1NtlVCTmBhpUNWgC0=
+			</data>
+		</dict>
+		<key>AppIcon40x40~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DjEAtviupMghxdL+fkyb3vVUBOI=
+			</data>
+			<key>hash2</key>
+			<data>
+			8gs3eoIb4H9cpuPaDkErBai6L4FZOZfyttI/pYM3Hw4=
+			</data>
+		</dict>
+		<key>AppIcon50x50@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			04wFY+JbiDwIxpPmec88nEldiCY=
+			</data>
+			<key>hash2</key>
+			<data>
+			Fgd22lgmtvaG3tzLwnbu57xZPQfGb7kA8fw+v4xYq7M=
+			</data>
+		</dict>
+		<key>AppIcon50x50~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			+ULYPtkyH7TWwGxGEFNW6M8jLYE=
+			</data>
+			<key>hash2</key>
+			<data>
+			EZireyXQZ2BAg+xIagkCS36vnwTAT9Gj4klrLYnBaK0=
+			</data>
+		</dict>
+		<key>AppIcon57x57.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			PbF/1dvCpOLYNWV+g1MRQWl4WnE=
+			</data>
+			<key>hash2</key>
+			<data>
+			iSorb6M7XrIIMpCBr6awOme1bCqhFhETsVuGfC9jVjo=
+			</data>
+		</dict>
+		<key>AppIcon57x57@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			V0sslzjLj1HAL3zLlk8dvEctXT0=
+			</data>
+			<key>hash2</key>
+			<data>
+			3GoBd/2HILd1AINYIZ2VN5SyJll0gGaeOlrrU1Ca78A=
+			</data>
+		</dict>
+		<key>AppIcon60x60@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			7bf8dqKMlGV9BeNvI9Z4FC+62EU=
+			</data>
+			<key>hash2</key>
+			<data>
+			5V8UjSCgkmKRVOYu+FRB0+yhTL1NtlVCTmBhpUNWgC0=
+			</data>
+		</dict>
+		<key>AppIcon60x60@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			u4hDZJNq/M9gB/k7ZWPGCQh1dlY=
+			</data>
+			<key>hash2</key>
+			<data>
+			r8K3AZPdn6icGj4YUVtCtXHNle4pibhlywI7n8aG/Io=
+			</data>
+		</dict>
+		<key>AppIcon72x72@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			6XXlAQJ+2YZtK4XZVDeAXCGQAjs=
+			</data>
+			<key>hash2</key>
+			<data>
+			5WyvqaFUnD6nIdPHQmezpma8HivvHieK/L954As389E=
+			</data>
+		</dict>
+		<key>AppIcon72x72~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			qt7V3ayH99MYvDNK/r88oIVhpxI=
+			</data>
+			<key>hash2</key>
+			<data>
+			/1yzmm2Ovvhnj5fOlzXwken4Gpd7Uskb1KN4X1Eh5wI=
+			</data>
+		</dict>
+		<key>AppIcon76x76@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			dPM76DtwjHUolue6BdDUn6RQXnQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			J9GAry/RDwypFKcWaJ/7THn0XDTXf1vkmuaPFHrNAuQ=
+			</data>
+		</dict>
+		<key>AppIcon76x76~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			mVA2cm+ufolVC0dfMnpXBt7NFYw=
+			</data>
+			<key>hash2</key>
+			<data>
+			nE7QwQcdQpQt4n1d27B67A4367MV7J8kEhrSETTNr3g=
+			</data>
+		</dict>
+		<key>AppIcon83.5x83.5@2x~ipad.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			F3/BziTbXcn/vpTHvub/+Txde8U=
+			</data>
+			<key>hash2</key>
+			<data>
+			+mzLV5S6RSIPr6LMndIfUYIEt1cTLOqITJ2VIkQ6SdM=
+			</data>
+		</dict>
+		<key>Assets.car</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			T757ffQVmm8esfKqnkpldn+gA+M=
+			</data>
+			<key>hash2</key>
+			<data>
+			Ku+cDs59/HjYJJpja26TQyeiItrJ+8ZlbToTlVWHYiQ=
+			</data>
+		</dict>
+		<key>CDVLaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			te5vytZWHWAPLMPk0EfV2v2GOck=
+			</data>
+			<key>hash2</key>
+			<data>
+			Aw1RArZ9rOj1lisqSjDWcxhUzEEqIzLYXUopbZW5Etg=
+			</data>
+		</dict>
+		<key>CDVLaunchScreen.storyboardc/Info.plist</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			n2t8gsDpfE6XkhG31p7IQJRxTxU=
+			</data>
+			<key>hash2</key>
+			<data>
+			HyVdXMU7Ux4/KalAao30mpWOK/lEPT4gvYN09wf31cg=
+			</data>
+		</dict>
+		<key>CDVLaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Qc8jkXDDI2czWCVnjtQcBQ3u3Cc=
+			</data>
+			<key>hash2</key>
+			<data>
+			vF+g3k9pp/g5XjaiGdk0xQgf9meorwXFLc9Z0O/jJj4=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftAVFoundation.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			hQRQa4h2/Ke/Ec8h8zQINABOX+Y=
+			</data>
+			<key>hash2</key>
+			<data>
+			h4BQUX9E7/EcPnvpVs69T6Kc9rAeGMtwGTJQWg6wjoc=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCore.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			KFt3m2PXf7KLtlPH/dFjRxZu/Dc=
+			</data>
+			<key>hash2</key>
+			<data>
+			J+PRWU14eyk9KnlvcdCp5fuWxTvS4AJ0wGxzgk2V5EE=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCoreAudio.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ylfqEtpPpH5bCkjEGK/7yn1I6Ts=
+			</data>
+			<key>hash2</key>
+			<data>
+			72WxqzL+FUPZX+6qj/y5WwHDir+kTJkIjy1cKQikDPE=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCoreFoundation.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			dOJd2grXqGYhIrz9CKpe2OXCdo0=
+			</data>
+			<key>hash2</key>
+			<data>
+			Iv12B9Qz0F1hYiVYR3VKSbVP2tDRKSclwkDiFAUmYgk=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCoreGraphics.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			oKCWaSlRFg+oK78osXFZfQ3uDuI=
+			</data>
+			<key>hash2</key>
+			<data>
+			l9W6YJb5T7JVJsXuEcNBJnFPe6LtWBYyI4b1+3EGQ70=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCoreImage.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			dG50HETdCOQfPRzU0Ic37vCc/9o=
+			</data>
+			<key>hash2</key>
+			<data>
+			aikde3796lmdat6d6burRj11GB0vumLYqKc76PTbaj8=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftCoreMedia.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			odFZruKElA+9a+XkB1apq2pyAKw=
+			</data>
+			<key>hash2</key>
+			<data>
+			SFsqCNcRX+lHNvggUNNbc2sA+8JbHLAK9A6Q2Y+7ftk=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftDarwin.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Ekbogs5rZiDaOKSVVOIKmv8yP2w=
+			</data>
+			<key>hash2</key>
+			<data>
+			1/h4UhOpPzpZ3LzlUnCxfT7A7CaNMIOiDOQGLDovTgo=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftDispatch.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			KZ/cE5kKCjjALrWnzi/IZiYkeBE=
+			</data>
+			<key>hash2</key>
+			<data>
+			60cC2TqB1pY0cNedaMqqV3vs0gCHm8UCQVLJ0jJzI28=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftFoundation.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			D4CHUkxS6fDieQm0JXhasUkIO3c=
+			</data>
+			<key>hash2</key>
+			<data>
+			wpLaOUTaB7F72+kJXBeAP0Xlyp1AkIpttOLYtvAO3RQ=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftMetal.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DL0GBvhxifsCpExV32K3d37vZMk=
+			</data>
+			<key>hash2</key>
+			<data>
+			3F/zfCdecs6GtkbzX7Xi07H2vc33qxEYkrIftLjEp64=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftObjectiveC.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			X5Lb3FE34KNAL5snNyu8I7MppoE=
+			</data>
+			<key>hash2</key>
+			<data>
+			4FiqTxl58ntIpY/WW/szZj0BnHXLqKAE4Cx3Z8txX+M=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftQuartzCore.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			wpPfT2ZYqDtV8LC7tvoOz5FIvWo=
+			</data>
+			<key>hash2</key>
+			<data>
+			ExtIoFyMZiTs/657o3qRioHH45FHNDzLMojsBB15V+E=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftSwiftOnoneSupport.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			D38ZqW/kqLjSdad8fvWunNuDSGs=
+			</data>
+			<key>hash2</key>
+			<data>
+			AbiqVf7dluuR8u/qmvrgktzGdgQ8N87eSJWZhqs9oHM=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftUIKit.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			5wMkr51pDRH8PDzP3Bjqk4Qy4cs=
+			</data>
+			<key>hash2</key>
+			<data>
+			xGyipgCx6JFkqlnfh6bj56jRFPKCauyRPM0KB6+Q5v8=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftos.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Vnurcvfwt3SW/agfJlOdUi1diDY=
+			</data>
+			<key>hash2</key>
+			<data>
+			DTwNnRNm9WO3Fkqz8CpP8dqCKlDZ9NODfsHb+qtB2YI=
+			</data>
+		</dict>
+		<key>Frameworks/libswiftsimd.dylib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			6Z28ZZWvGEuFgIwB9dKwPVtlKfQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			dgcyCjIvBdgopx5CPgmhALCIKpUrn3+ijEdFeQp57wk=
+			</data>
+		</dict>
+		<key>LaunchImage-1100-Landscape-2436h@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			LEdpganmedvHWweqF8iLow1TPLo=
+			</data>
+			<key>hash2</key>
+			<data>
+			PPZT2syYGfhgP0PvxPZVmlmG7SJrJoE4GBQIvY5+S2g=
+			</data>
+		</dict>
+		<key>LaunchImage-1100-Portrait-2436h@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			1s+ysYN76gL1pE3B0EhXb01TzdA=
+			</data>
+			<key>hash2</key>
+			<data>
+			ap08FxSz41QG5Q24DmNqTcUYlUWMhIwUV+ngx7btDlU=
+			</data>
+		</dict>
+		<key>LaunchImage-568h@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			uL21BlZJ/oQEajleUn14FTTZ7sM=
+			</data>
+			<key>hash2</key>
+			<data>
+			bNrMh4ALqv2m9CI+leebA+tjPBNmM/RsXmDLjUMd+gs=
+			</data>
+		</dict>
+		<key>LaunchImage-700-568h@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			uL21BlZJ/oQEajleUn14FTTZ7sM=
+			</data>
+			<key>hash2</key>
+			<data>
+			bNrMh4ALqv2m9CI+leebA+tjPBNmM/RsXmDLjUMd+gs=
+			</data>
+		</dict>
+		<key>LaunchImage-700@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			p3fC93dHhA5tenQ6Ms/OAzSmHGY=
+			</data>
+			<key>hash2</key>
+			<data>
+			K5PcUcy5CdaB5YZy6PvOvyDgcy4PPrpqvTqSAfMdV64=
+			</data>
+		</dict>
+		<key>LaunchImage-800-667h@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			hS7N0w32F9JOazHaI7UvfliwaVM=
+			</data>
+			<key>hash2</key>
+			<data>
+			RZthbVFNTjw6kbUIKs4y5nnDbJQeEuSsHk2VAb2E650=
+			</data>
+		</dict>
+		<key>LaunchImage-800-Landscape-736h@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			BMiTgfs0nCUuv79rKBlo9K6pP0I=
+			</data>
+			<key>hash2</key>
+			<data>
+			vgdcy9qvu96EGYslcKsA6twcA233PsI2NZezGV81ODU=
+			</data>
+		</dict>
+		<key>LaunchImage-800-Portrait-736h@3x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			RV8pvGiU/AXzpWjjTuqPxdFYFAg=
+			</data>
+			<key>hash2</key>
+			<data>
+			zUJ0ySJ86RLxjX6u9GQwqfkCdRGNW9YbqRnpg+NZ0LE=
+			</data>
+		</dict>
+		<key>LaunchImage.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			yGXeBtC8p4UEwup1J2ZWE3M8vdw=
+			</data>
+			<key>hash2</key>
+			<data>
+			YEYpAZ4SZAIlTn7D8i+xvyZdXZl0k9Tr3vewc0b2hWc=
+			</data>
+		</dict>
+		<key>LaunchImage@2x.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			p3fC93dHhA5tenQ6Ms/OAzSmHGY=
+			</data>
+			<key>hash2</key>
+			<data>
+			K5PcUcy5CdaB5YZy6PvOvyDgcy4PPrpqvTqSAfMdV64=
+			</data>
+		</dict>
+		<key>MainViewController.nib</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			HGQoZCqsnAcpXpUU2Euwer6XpSk=
+			</data>
+			<key>hash2</key>
+			<data>
+			nEOyqE9FxudLnnLxAn9w79r+pKez8o+lOXcbO0JyLHc=
+			</data>
+		</dict>
+		<key>config.xml</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4Ey/jpgwhwU4OCZf57u3NVkF1xQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			Wt4EjOKnK+exUViTV6Blq5TQRlJ5pGRa/NYR5WGdDGw=
+			</data>
+		</dict>
+		<key>embedded.mobileprovision</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			WNm5zuPz65rrY9t5qIL1iJgFcQ8=
+			</data>
+			<key>hash2</key>
+			<data>
+			8dIWw9eXozB2DtbVPRHN3hu7yhjI74L3184XxOY586k=
+			</data>
+		</dict>
+		<key>www/bill.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			1Q6bs+kjPSyg+Yl2MrIlAdkCDEM=
+			</data>
+			<key>hash2</key>
+			<data>
+			aQ18IOK1WD+xB0HoL1rOKcacc0APEyZB0ZArD4e0ZHA=
+			</data>
+		</dict>
+		<key>www/billdetail.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			y/BRy2p3Q5Cx9yIIKJSruC5hdVU=
+			</data>
+			<key>hash2</key>
+			<data>
+			0RTbZ8J/3k5IrHFIcDKDK/s36izM/vPn38xQ6QQBc7A=
+			</data>
+		</dict>
+		<key>www/bindcard.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			9PZ9wKXqzkXFm00p7Y0R3qjtldY=
+			</data>
+			<key>hash2</key>
+			<data>
+			zo8Ha9qzyk1B/L5POHRECSQv7lA0GI70kpuOSkDOxrQ=
+			</data>
+		</dict>
+		<key>www/card.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			kDKEBSjs2KNfSwut3SEeB63fJ34=
+			</data>
+			<key>hash2</key>
+			<data>
+			es8Rhi3kIypt9tBLnXGzBebN6aCODw7quowDT5rsQOc=
+			</data>
+		</dict>
+		<key>www/cardinfor.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			QQg8HZreHawxjyGafVvCyGhCGrw=
+			</data>
+			<key>hash2</key>
+			<data>
+			dLCHrYVEZUVA/9OSA1MYq9G/NQhW9Q6iTid44oVzVCc=
+			</data>
+		</dict>
+		<key>www/cordova-js-src/exec.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			3QDPaUQrAr8Wq2XcQhqcl8DLabQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			3k+JZ8ZeHITt5+/EQNMxMv9o6gJ7PJ7TdGiLTUKTJlU=
+			</data>
+		</dict>
+		<key>www/cordova-js-src/platform.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ujxMgcZCzzuK4VAjaNIfsORGeNU=
+			</data>
+			<key>hash2</key>
+			<data>
+			S9540sctUW+dAAN5RwT1Z2yqrUaLkOatC8izY2Pe4uA=
+			</data>
+		</dict>
+		<key>www/cordova-js-src/plugin/ios/console.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			QiM8MHQKHSj59wvBt/HHviQ0nms=
+			</data>
+			<key>hash2</key>
+			<data>
+			KW7Ld8hLblt9xwJYLxr8zUd7zWlelJFvhG4BneBhcsc=
+			</data>
+		</dict>
+		<key>www/cordova-js-src/plugin/ios/logger.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			doSoID4yQ7Z8GrTg9sMfeIjMlDU=
+			</data>
+			<key>hash2</key>
+			<data>
+			NtwIycT/TLukZ1w2dwy7zov83AF/eUvKVLMOhAsQmMA=
+			</data>
+		</dict>
+		<key>www/cordova.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			m8O8WSj370y+bdGWAUF2JiU6Qnw=
+			</data>
+			<key>hash2</key>
+			<data>
+			+8XBJUzt7mpcs+YfS0jgWvANZQxsmTGlB3UAF7C9JSE=
+			</data>
+		</dict>
+		<key>www/cordova_plugins.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			5yQtgIC/T2E5OFopQG2kN+WdYrI=
+			</data>
+			<key>hash2</key>
+			<data>
+			x1upHfUuBcJ6Tke/ngdf2mnxo6x26sRTpS6VlyHRa0U=
+			</data>
+		</dict>
+		<key>www/css/aui-iconfont.ttf</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			bgBa9eNE+SIBMMSGsOaLdlkaqCo=
+			</data>
+			<key>hash2</key>
+			<data>
+			wxoUzSaXcVLWKk/ryCp5DCfgEMu29wJLFksdOFHqHsQ=
+			</data>
+		</dict>
+		<key>www/css/aui.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			6xyvpUD036ik6Mg3P+cYQ1NrzQ0=
+			</data>
+			<key>hash2</key>
+			<data>
+			I5Or8h5V+2Rn2T7Bj5MJhzcGoRT5Vc1h5hRxVkEAhrY=
+			</data>
+		</dict>
+		<key>www/css/index.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			303YwSwtG9jcxpjzgcZJ0eqHSKg=
+			</data>
+			<key>hash2</key>
+			<data>
+			WVBUPcOg0x0Trc8/IE5+/4Y92K5FcBNLuBDO0A8V8Fk=
+			</data>
+		</dict>
+		<key>www/css/jquery-weui.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			JJJVkVnNsjnLAe5ZCqLG6ihqAX4=
+			</data>
+			<key>hash2</key>
+			<data>
+			QhfXnIGUDLXJT7y8Dqhi9jzuoWmybOvSgZ/W6AFv85g=
+			</data>
+		</dict>
+		<key>www/css/weui.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			xzTaeGLEw+pLemNK6/MLliqngZM=
+			</data>
+			<key>hash2</key>
+			<data>
+			3Q6GS9dgVljbGTAobvOt5RD45hus+DALLlXr1lLPYBU=
+			</data>
+		</dict>
+		<key>www/dobind.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			bPlHLLWGMLQhGS93aI71OYjow/0=
+			</data>
+			<key>hash2</key>
+			<data>
+			MNKL0C29kmXkHkBzb0VYuWX8MArQ3P74aqxU6osblgY=
+			</data>
+		</dict>
+		<key>www/editpaypwd.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			0auYgJFadz+CglQBW5qKxfebL/c=
+			</data>
+			<key>hash2</key>
+			<data>
+			Xxbfi/4WbcYijDvr5ZsiaNzppwe77y9LOEyc5Rp/z7Q=
+			</data>
+		</dict>
+		<key>www/editpwd.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			XoVr9QA+cY59iWDpWbw5olgSrXU=
+			</data>
+			<key>hash2</key>
+			<data>
+			+Rn9Gn8GZaq1e8jgjji/hLeCpq+sLZ6YUlmmGhtEIZo=
+			</data>
+		</dict>
+		<key>www/error.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			UDoxz7BHRgnZPQOdYy1XRMxlqBE=
+			</data>
+			<key>hash2</key>
+			<data>
+			X37yOrroTOHj3M1bqjwJnKXFjiXnoZypH+kta2Zp6B0=
+			</data>
+		</dict>
+		<key>www/findpaypwd.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			dwUuT831xBqurx4U2tle0AgTbyQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			v2Da0BZezNxBJLwaH2TM3OhbqsItOqUciwbQPn9SRTg=
+			</data>
+		</dict>
+		<key>www/findpwd.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			gC2QYIEKPpr5CDu0OZl7auJQIUo=
+			</data>
+			<key>hash2</key>
+			<data>
+			ZcjZNxrxtlB1HQudv8SWlTK4OADYgBLYFmdWCD0zkRI=
+			</data>
+		</dict>
+		<key>www/img/back.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2Q/cRIn6pwRXGAOdeqfhxY/2imI=
+			</data>
+			<key>hash2</key>
+			<data>
+			i94l91jssR49URmofKl9vyPK2Rm1RHlzDHdv3X0805M=
+			</data>
+		</dict>
+		<key>www/img/close.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			0XukISSDdlZnyQv+QDff6qw52r8=
+			</data>
+			<key>hash2</key>
+			<data>
+			xOg8ZfGk9171rdPzrg4cGKb5LccoElWVmBpolbRdLP4=
+			</data>
+		</dict>
+		<key>www/img/close_1.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			qEqPVoLhX1FBSsmzSYaIVwKYnsk=
+			</data>
+			<key>hash2</key>
+			<data>
+			3JU/OO6pTqPFDFz6E/sgZLEYh1zOamjFQSSw14eSInE=
+			</data>
+		</dict>
+		<key>www/img/icon_auth.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			G1UhJYGGEC6V8OKvE2goXDsiYP0=
+			</data>
+			<key>hash2</key>
+			<data>
+			96tmU4664BjOHLZjP+6seaOqe+e0c/XODBx9Ga2AaPM=
+			</data>
+		</dict>
+		<key>www/img/icon_bill.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			EacO2/9ZXgO4asWq/ejNiv4oIF4=
+			</data>
+			<key>hash2</key>
+			<data>
+			WcQv740yFpBLZgCoZ2CeipmyAuzoNvvUhGWVKw4ZDxc=
+			</data>
+		</dict>
+		<key>www/img/icon_car.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			clao0p4qsWbdM8nSEpyuK7FNiMg=
+			</data>
+			<key>hash2</key>
+			<data>
+			3NguLLGdkpjovdd2w0lbmPTpTrTQpCl7KPSiOz8aPGQ=
+			</data>
+		</dict>
+		<key>www/img/icon_card.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			vCr7vtkPuVHx3XBpJF0QrFYmg48=
+			</data>
+			<key>hash2</key>
+			<data>
+			hPSk5dHQm6MvF2+feqJSsDTJQNYGGQ3l11IWBmS4agA=
+			</data>
+		</dict>
+		<key>www/img/icon_header.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4drNX8zyyrek1c2JXqfXQR2KfZI=
+			</data>
+			<key>hash2</key>
+			<data>
+			ACTHNlucVMra0T3AsIvTUxNbK8YboVDs/5U6JUtpYuc=
+			</data>
+		</dict>
+		<key>www/img/icon_meal.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			06mY5fqZWPnzDdCwe5IgbU3fDbw=
+			</data>
+			<key>hash2</key>
+			<data>
+			IFmBlXWmeIuq5+60o71sR1dOGIKeitlyF7zXhrRQKHg=
+			</data>
+		</dict>
+		<key>www/img/icon_ok.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			n5SPEi0cP0wnLbHN/9D04nL1Tb8=
+			</data>
+			<key>hash2</key>
+			<data>
+			4sNYGXvZjX0V5ZGcdk/4xRvzT7nClsf6xxGhgDh6OtI=
+			</data>
+		</dict>
+		<key>www/img/icon_qrcode.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Tkh150zO/sdywOPDrSK6ou4VQhk=
+			</data>
+			<key>hash2</key>
+			<data>
+			BPFSORKkPjd3cH1WVG43u1/TmYroKO2XBP7cWs5kZf0=
+			</data>
+		</dict>
+		<key>www/img/icon_scan.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			NK0zbLpB/729gkxvCiVBnj8R+so=
+			</data>
+			<key>hash2</key>
+			<data>
+			LoHMx9TT82YHXj/RmuEP1zmGMefn+RRcdkza/pRNM+U=
+			</data>
+		</dict>
+		<key>www/img/icon_securty.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			A/2jQ8YjXC0HrT2MT/zuS5HmlGQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			SF4OBkWqOseOJDyoJU33ex4dCDda2ZJc9/BPxFZLWBA=
+			</data>
+		</dict>
+		<key>www/img/icon_water.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			K7bemny8Y7OGsoLB7APPmep+KBc=
+			</data>
+			<key>hash2</key>
+			<data>
+			CNX79yGp0dtbeWu2VOslh9GFxfiyCSp5r/WcU+HcWbM=
+			</data>
+		</dict>
+		<key>www/img/light.png</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			keI5n58zmYufnBljGJxgOOqdZPE=
+			</data>
+			<key>hash2</key>
+			<data>
+			TR3lVqr5//K4SegU2J3HkoS2h5P7r6CflS/vEBK/lSM=
+			</data>
+		</dict>
+		<key>www/img/scanner.svg</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Url7I2VNTxsMJ+0yFoayWTFLnfw=
+			</data>
+			<key>hash2</key>
+			<data>
+			W/VwrrNVcHhByPE18z5m8629ioIXqnfmziEq7aEm2y8=
+			</data>
+		</dict>
+		<key>www/index.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			5T2zYcDtNLEO0qcTZGgyv5wCdsQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			bbbTW+ZzNRuI2n8ez38NzoUEiSfP0QKFk7A+8LLG3u8=
+			</data>
+		</dict>
+		<key>www/js/bill.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			PtiPisUNF3iV9vPSlzdIpHwidUg=
+			</data>
+			<key>hash2</key>
+			<data>
+			EVNRbGJRHseLA3axCbgGcz29IGU6xOmdGFdvWIugfnE=
+			</data>
+		</dict>
+		<key>www/js/billdetail.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Df3zwuOjyxYT1atvBcZGR3EVdh4=
+			</data>
+			<key>hash2</key>
+			<data>
+			FyGdQXizxc01cqVOn0QqA1F59oAIlgBekP0GYYGdBn0=
+			</data>
+		</dict>
+		<key>www/js/bindcard.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			QcQm/WcOXL3pjL8WUEBsXTDLCmQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			6w5TbEgi58X6ax41nX5HNkseAndhXsBoDdMbkC5ZN0s=
+			</data>
+		</dict>
+		<key>www/js/card.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			pIuWD/nNiuDsXe2wowI2s9+3FQE=
+			</data>
+			<key>hash2</key>
+			<data>
+			0uPvlo+ps3yiA4Nr0TxLLLqbo7L/kbBlTasufVbwIBo=
+			</data>
+		</dict>
+		<key>www/js/cardinfor.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			H5Qek3wUoBtXbL/Ry+v/gt4riXg=
+			</data>
+			<key>hash2</key>
+			<data>
+			ImlzAkXWit52+Okzsr+w8kHaTnJMmM0IHcp5lU6u9zw=
+			</data>
+		</dict>
+		<key>www/js/db.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Vb7u+G5BFFGhnbBNfdZiVfTDP4I=
+			</data>
+			<key>hash2</key>
+			<data>
+			MY9eU+VhmfYjOGbes5oXrbw7pP0IzusAaXsw/8EeNZM=
+			</data>
+		</dict>
+		<key>www/js/editpaypwd.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ZyqrsAJhe9yLp35qpeeVAMOMFNg=
+			</data>
+			<key>hash2</key>
+			<data>
+			24eyXGL+tb2XRy1Y388w7UwgT8OUvQGEKRTFzGi5Gf4=
+			</data>
+		</dict>
+		<key>www/js/editpwd.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			AONikpSnuBp7psEqpQTTZCTIu1w=
+			</data>
+			<key>hash2</key>
+			<data>
+			V8pGttJb/OSzy43VKMB0VktiAMw1ZaY7S/Hm+mfJy10=
+			</data>
+		</dict>
+		<key>www/js/findpaypwd.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			tA9kUDZ60JHG/3d4R4N9DUkLAG0=
+			</data>
+			<key>hash2</key>
+			<data>
+			ON90eLaDYbbX/7dXDaPud+tTCXg8Gh+HJpZGd9EqIyo=
+			</data>
+		</dict>
+		<key>www/js/findpwd.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ooTBY2pzkPyuCeBdjhpYIRQGHz4=
+			</data>
+			<key>hash2</key>
+			<data>
+			1WbEeQpuP9M1LjNXcyx8tJ/QQwV6d9IcvYdCU+UaIoY=
+			</data>
+		</dict>
+		<key>www/js/index.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			7VB6kBtU0FQ+JUAh0cbyy2dfHak=
+			</data>
+			<key>hash2</key>
+			<data>
+			3NRfVaJToNjIzE5ZaKN6wU1XoXox/FthPuwx1DZcyTQ=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-actionsheet.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			k43Wv7PPTuTyR1EUlwbusit0uo4=
+			</data>
+			<key>hash2</key>
+			<data>
+			wfxX5zeh7YT9GRl0H1zLQ2u6/jEujsukNIqFHxaXDZY=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-collapse.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			PcFD5a7aQGYMO9bDPOIhe18DEiM=
+			</data>
+			<key>hash2</key>
+			<data>
+			JYWf9W+JzDrdygPl0ZR1k1+rNM8KdSeOjWrM9IDhApU=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-dialog.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			3fVPO33iXt4/iAMGp9qRYz9VzJw=
+			</data>
+			<key>hash2</key>
+			<data>
+			1GFAmckVSlSP7ZBFkf3SSx5OKDx4cROpF/VhgaU29wU=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-lazyload.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			X3pkec58gL2uj3v8nvsRT/zYnTI=
+			</data>
+			<key>hash2</key>
+			<data>
+			EuGZAflUk0KrUBMmVk7DhMXj55mZ2ocrfA5X4rHCXn4=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-list-swipe-backup.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			zjTgZbyH1/qY9xlXJ777ggvHwSk=
+			</data>
+			<key>hash2</key>
+			<data>
+			SkuJlA7UAAMe3S8LNEIq0Zwva3/nJFmE7Z7hobvqvZ8=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-list-swipe.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			RJSPeNc+3IoE9NG+nbmJovLvbBI=
+			</data>
+			<key>hash2</key>
+			<data>
+			qW2Olj/PDW4ibM93XeU6Y9PaC/KdBCy4BODlZX1Zdqo=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-popup-new.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			gXw6tzg/hrrBNpZSJBIER5Mv+S4=
+			</data>
+			<key>hash2</key>
+			<data>
+			hUricepCdTmTl7Ov488QnsNAR5jycOa+iyAt3Y6IdNg=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-popup.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			JXsvRZu82Fk7FCARmTJDmkP495c=
+			</data>
+			<key>hash2</key>
+			<data>
+			XW+MQqihOrtuYv3xKwn9S0dxqMTLQRrTtZ1aGc+a+8M=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-pull-refresh.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			VIyUsJMbzX81zEkOq6MjbnHqc7c=
+			</data>
+			<key>hash2</key>
+			<data>
+			u30gVMBg+I0Kou3+VEFP/m5hBCX8D7b4uwuXksgo1Ag=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-range.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			cZf0K7lQ9CQ8DPN7+cXfbwewHjU=
+			</data>
+			<key>hash2</key>
+			<data>
+			X/K7hbwr9BK1ywgWUMFggIJgWzNWw7XiAZYgiNvJyU4=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-scroll.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			rU2uqVzf52oVKPolaoq9muinl08=
+			</data>
+			<key>hash2</key>
+			<data>
+			lLmJntqeM3O2zFPiJZ28b7r0FXFr76lwJbykshWx1Yc=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-sharebox.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			D/mRv8xXyZkdCn6xbBRpQXLyhlo=
+			</data>
+			<key>hash2</key>
+			<data>
+			Pz2Y0sDNW1euF/1TyO3lOyTlljUpIrNaKGDTyy26otc=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-skin.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			MXDxnju1mt2Es/Uqu/f1CqYdRqQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			Yp8zUQ7of7yctdfsmK7U5jVonIfrp1U+xvmusqYu81E=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-slide.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			xC+oaMpn8oCCLqxFx70HIxECU8M=
+			</data>
+			<key>hash2</key>
+			<data>
+			ZRJymTc+otJWlrtWfUFWA6coEBXKOUMCc2xphDb35rw=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-tab.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			D9KTddViayJQ1e+U5i1Ak+nBRE8=
+			</data>
+			<key>hash2</key>
+			<data>
+			m/Sb724wbOUf5lbbCAAJA/evUDiAyqQ5zYXAnwTqSYQ=
+			</data>
+		</dict>
+		<key>www/js/lib/aui-toast.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			H8BfA5yAWFAiIieKsDh2VQP58B4=
+			</data>
+			<key>hash2</key>
+			<data>
+			wfcWYBgAHrBs16VGXxBLboel/eT6lPw0b0Rz97cJIx4=
+			</data>
+		</dict>
+		<key>www/js/lib/city-picker.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			83Okg34aIKXmAfjbwn8ghcAF04w=
+			</data>
+			<key>hash2</key>
+			<data>
+			KXbF8s3iFKyVunomD2LHDwqgd9+ldRBL/CqOXyp7IG4=
+			</data>
+		</dict>
+		<key>www/js/lib/city-picker.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			tEME1JHsZSZX1OO/00AESKA1bJ8=
+			</data>
+			<key>hash2</key>
+			<data>
+			vi3hzVW93Pfx8AmuYal8mNko+mvi480FDHNQg+101Tw=
+			</data>
+		</dict>
+		<key>www/js/lib/jquery-2.1.4.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			D+1FrXpIrOhpvHJcpHSthqHvFWI=
+			</data>
+			<key>hash2</key>
+			<data>
+			siFczlgw4jULnUICcdm9gjQPZkw/YPDqhQ9+nAOScE4=
+			</data>
+		</dict>
+		<key>www/js/lib/jquery-weui.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			+3joFaV28ZGz8NBkVgIq4M7tfhs=
+			</data>
+			<key>hash2</key>
+			<data>
+			9KPS+6ZRaNC8d8hLPB2Ma+B8U/LX8ClTpHFNfdNNCEI=
+			</data>
+		</dict>
+		<key>www/js/lib/jquery-weui.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			JqNM+qw68fjSEeY2yiOFqA6nu/8=
+			</data>
+			<key>hash2</key>
+			<data>
+			Hi63tZFg3Z3ZW/DFPkaCOO7rTHloNJTnxxRUiakWiQg=
+			</data>
+		</dict>
+		<key>www/js/lib/jquery.mobile-1.4.5.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			/FXTZ8cnK93oBw+FGvRYS7wQsug=
+			</data>
+			<key>hash2</key>
+			<data>
+			Lsk+CDPOzTapLoAzWW0G/WeQeViS3FMzywpzPZV8SXk=
+			</data>
+		</dict>
+		<key>www/js/lib/qrcode.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			LQbB+CPzTBmYHGrgsOsPWGHF4Us=
+			</data>
+			<key>hash2</key>
+			<data>
+			xUHvBjJ4hahBW8qN9gceFBibSFUzbe9PNttUvehITzY=
+			</data>
+		</dict>
+		<key>www/js/lib/swiper.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			dpz0tV0hx3JqEehZho0/fwk5dE4=
+			</data>
+			<key>hash2</key>
+			<data>
+			YPt73nJPsPJCf4c5gDSBNWAsAAZ4gFD8vlZYNIOjM78=
+			</data>
+		</dict>
+		<key>www/js/lib/swiper.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			g7iXAN78S/xWzSRE7clYTjjw1hQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			jMpqqeBS8gwsQvgJtRv7Nc4R2HrWvx0Mg1fYzDUjUtQ=
+			</data>
+		</dict>
+		<key>www/js/login.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			GnaACCIZ8j2xg8PJGAWxS4CymgM=
+			</data>
+			<key>hash2</key>
+			<data>
+			w2bwoTKwQ/CsM9LtLjMEPahT2ZOL7o02CiG2oiurI/Q=
+			</data>
+		</dict>
+		<key>www/js/main.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			0LqnXw5oToAfNnPBWMOt3Pj41y4=
+			</data>
+			<key>hash2</key>
+			<data>
+			Ax5z71inU53ze1vUxVRhaQ3jST+ysuyVQ6ft9GOkIp0=
+			</data>
+		</dict>
+		<key>www/js/mobile.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			lmaKo3x9bgrYBEk7Fh2+/qAg6mI=
+			</data>
+			<key>hash2</key>
+			<data>
+			v/+zWEdsogf5sPx1cB4rK3hoxRP7yZy5+Iimh/zifsQ=
+			</data>
+		</dict>
+		<key>www/js/paypwdmng.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			A1a1mztONeZQbLMhwzbhc2/yv0k=
+			</data>
+			<key>hash2</key>
+			<data>
+			Teqik7gzonK7UbQLXHP2nfh7OPrmsq53ZwO14JW0MOw=
+			</data>
+		</dict>
+		<key>www/js/paypwdset.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			SMBcGN/6F4U5a2cmkI6W0Pn7apU=
+			</data>
+			<key>hash2</key>
+			<data>
+			lML2DvaiJpMLiJwD/w+Sar+Huh9UH6OEc0WkhBBVRzY=
+			</data>
+		</dict>
+		<key>www/js/pwdset.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			iVznXYlssRXP6OIfCRDZ9A/blF0=
+			</data>
+			<key>hash2</key>
+			<data>
+			J/U/QrZC9QDS9K5z77EIyBxAM1g1x9+f8OyXo44oM6c=
+			</data>
+		</dict>
+		<key>www/js/qrcode.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			nUamfLQSBc/NAzOMJP5WwXnZGxI=
+			</data>
+			<key>hash2</key>
+			<data>
+			bonfkrWCjMv5LWiAp1sfmRvU0wFfN0bYRwBLbFijF/k=
+			</data>
+		</dict>
+		<key>www/js/register.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			aPLw5ln4ElwhbTzbdXZpyILJBiY=
+			</data>
+			<key>hash2</key>
+			<data>
+			iyaJXQRZwYysUd//j42epM6Y+Bqkm8S+ZOuGUwhfFn8=
+			</data>
+		</dict>
+		<key>www/js/scan.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			FahF/fMDsR1+zrs4BFASK2HvtUE=
+			</data>
+			<key>hash2</key>
+			<data>
+			NSekfExl5bEy5F9aBqNWO9CNF7llGgaRGhNra6ncWBQ=
+			</data>
+		</dict>
+		<key>www/js/security.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			s52wwGEv5fJuX8ngkR5GGqdAXMg=
+			</data>
+			<key>hash2</key>
+			<data>
+			sasPlhOHyLhEjRoUQpmieOq/IW8v9yLbzXcckfySGjg=
+			</data>
+		</dict>
+		<key>www/js/server.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			8l2vn+ra5zayhEwQQpy1806GZX8=
+			</data>
+			<key>hash2</key>
+			<data>
+			7xi+g6PEIs8+EcyXCCGlOwVJF4gL3Opbbe7Oj9KK08g=
+			</data>
+		</dict>
+		<key>www/js/signxy.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			gDocQNgzvA/TxPmLCDCjG8iRQGQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			Vh4NcgQQik+8mAFenFg/ixdjbZqqruikr/1UpMF7Lt0=
+			</data>
+		</dict>
+		<key>www/js/signxycheck.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			gDocQNgzvA/TxPmLCDCjG8iRQGQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			Vh4NcgQQik+8mAFenFg/ixdjbZqqruikr/1UpMF7Lt0=
+			</data>
+		</dict>
+		<key>www/js/uxy.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			YV3C17xDBTm8vmpn5vtSah8uQVc=
+			</data>
+			<key>hash2</key>
+			<data>
+			3FJ3HH0U1bnJqbx1esLPKdPWaYswCFnnR0SQnpzKjn8=
+			</data>
+		</dict>
+		<key>www/login.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			MbU55+r7AuMxeK8D6a+pTzgRSU4=
+			</data>
+			<key>hash2</key>
+			<data>
+			CthU7BfSi2HGHJg/X/vGzcuM5v2APNL9T6uMNTchDuo=
+			</data>
+		</dict>
+		<key>www/login1.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			uf9qCJKdYuGpG6HiVEwnDhtuF/g=
+			</data>
+			<key>hash2</key>
+			<data>
+			bMP5s35EVzqmVAg2sgre/MZxldr/DvV8IJpQ6HuyjVI=
+			</data>
+		</dict>
+		<key>www/main.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			gOippmPYY80xg/JnHqP8Kpg59H8=
+			</data>
+			<key>hash2</key>
+			<data>
+			FI8NhTNqHdUwCEkp/A4flZiB2KiUb7zmd9e95nWeBFM=
+			</data>
+		</dict>
+		<key>www/main1.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			aTWSKs5RwWeuZBA1D5QOA0INVcY=
+			</data>
+			<key>hash2</key>
+			<data>
+			m6ggJ73Vn76oFYd5XCTmnbW4Utut8RV/b3IbSubaoMo=
+			</data>
+		</dict>
+		<key>www/mobileui/css/alert.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			jYO6/4Av8ReiEsQqN2QGcbBRLXw=
+			</data>
+			<key>hash2</key>
+			<data>
+			FHg77bp9oc/AalO8U01ah+ZDzvB+AxlDnJyYISmV3qg=
+			</data>
+		</dict>
+		<key>www/mobileui/css/base.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			0QzpyxWU+iiFLLd6fIFNg/DHljA=
+			</data>
+			<key>hash2</key>
+			<data>
+			XNsZ1np66II7A+J6ozx4Q/3lkzU+6W+YUxRUIP5knGQ=
+			</data>
+		</dict>
+		<key>www/mobileui/css/button.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			lJJG/2v48hM67nFqihEQeZH8lhU=
+			</data>
+			<key>hash2</key>
+			<data>
+			2Fkq5o976UWeiNhu1/eN9SJA7lqI6haEoYGgyePP/G8=
+			</data>
+		</dict>
+		<key>www/mobileui/css/chart-bar.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Iojhce0KFhtCMpxglUh4PEjGUyU=
+			</data>
+			<key>hash2</key>
+			<data>
+			KK766cgQa1S0tikIJeqKQK1RvMl2/Vg6uxmOQZXaFkQ=
+			</data>
+		</dict>
+		<key>www/mobileui/css/chartist-plugin-tooltip.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4BLRESrZYbj5vw35KGvOE1ab8IQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			/3f7EH/zyY4mgklUvvv0hts83tYGsAaVBSNmXkZyAng=
+			</data>
+		</dict>
+		<key>www/mobileui/css/chartist.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			cHCZqIK22tK06U8yx7bHuJYZe3U=
+			</data>
+			<key>hash2</key>
+			<data>
+			Quhjc7zjAddypJJIC9+3ThPqUpUFWiCW0HdYfiaaAHg=
+			</data>
+		</dict>
+		<key>www/mobileui/css/chartjs.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/css/cover.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			QE0+0dSOklJMlooYxEoptPCACUg=
+			</data>
+			<key>hash2</key>
+			<data>
+			j3cgy/C23+wBtoqTJcwEbeROu6pqG6ZHohyh8kJbI2Q=
+			</data>
+		</dict>
+		<key>www/mobileui/css/fonts/ionicons.woff</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			5GgZ6GOkZ1HWIsEZDE6Kg+vCBhI=
+			</data>
+			<key>hash2</key>
+			<data>
+			cJ8nidqv9ECCDruXXTrkCa9FEhvexH456DUjSQsbwPw=
+			</data>
+		</dict>
+		<key>www/mobileui/css/fonts/roboto.woff2</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			HEy0LoEUSXT01k1W8XgHmkAfldM=
+			</data>
+			<key>hash2</key>
+			<data>
+			Pix46CEoflVsPWTTv2UzptHl9ueNfbigOOheiMyFwU4=
+			</data>
+		</dict>
+		<key>www/mobileui/css/fonts/robotoblack.woff2</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			lCeboh+O5pxgIIGxpfJcmKWz5F4=
+			</data>
+			<key>hash2</key>
+			<data>
+			CNwcC7Eq3HxYgMITOC3IcvepAYXMh5OkiDY2cG2MDR4=
+			</data>
+		</dict>
+		<key>www/mobileui/css/fonts/robotolight.woff2</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			vDVc3zziS5SAbNZcRDgP21RkluI=
+			</data>
+			<key>hash2</key>
+			<data>
+			L20bUMrRhFRDKkbjJ5KQXvomcXyhJ3eAwT7XlDVhsgw=
+			</data>
+		</dict>
+		<key>www/mobileui/css/gfont.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			jA3wb2s1BfNIpZEYO76br1fCono=
+			</data>
+			<key>hash2</key>
+			<data>
+			2+4tgRL/xw8bRwfUaBm6hXBCdkNsbCqOXkbPIA7yvhQ=
+			</data>
+		</dict>
+		<key>www/mobileui/css/grid.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			aM0i6KhoWieRrg4EHW6d/om/RcA=
+			</data>
+			<key>hash2</key>
+			<data>
+			y677xYAizqYLN30HcxW8MNZ/HSiFF8fKlyiAtJ8Hv58=
+			</data>
+		</dict>
+		<key>www/mobileui/css/header.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			n3mqFc12zN2mkpdsBu871X+TTUs=
+			</data>
+			<key>hash2</key>
+			<data>
+			QA2XjnjXuI5GGTY7kN3x8S9cbdTY+1Zrc+Ey0jlQiE0=
+			</data>
+		</dict>
+		<key>www/mobileui/css/horizontal-scroll.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			uTFUDzDcpEjcSoKtO3q+S3jbA5o=
+			</data>
+			<key>hash2</key>
+			<data>
+			Jo1uMs6alaZnIG+N/+RYkSSBa/iZNpYVu73USFRr/Lw=
+			</data>
+		</dict>
+		<key>www/mobileui/css/imports.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			8xusdKfTeZmEhAq0LnzqLhG00dQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			aDWnih2SYwyFYKm2XASEdDzK7MNhD8FJAvBQqxPg/Ww=
+			</data>
+		</dict>
+		<key>www/mobileui/css/include.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/css/input.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ercWR2cY6OhncYzB3E24Bjvbrow=
+			</data>
+			<key>hash2</key>
+			<data>
+			fKSBgj+SzhtCrFN4gla3tgPwr8TnkVqh1hKm6G80CLI=
+			</data>
+		</dict>
+		<key>www/mobileui/css/list.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			pcfSQo5LDs82DlAfqV0mW8lKvco=
+			</data>
+			<key>hash2</key>
+			<data>
+			Xzfzn8s+wQs93hXAnCIS8AB6ipOpU9o7GYo4tOyUq8o=
+			</data>
+		</dict>
+		<key>www/mobileui/css/loading.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ZkmT9wT87vx7CComvc1hX+6PWNo=
+			</data>
+			<key>hash2</key>
+			<data>
+			1ktThL3qO37lDgArNfJKuuNwgey6gHIsdnhojTWkWmk=
+			</data>
+		</dict>
+		<key>www/mobileui/css/menu.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			IuFE5Q8gSrEFlQgCq9LntKUPEVw=
+			</data>
+			<key>hash2</key>
+			<data>
+			+NNT2jFDX4IVtR23qpoJmFFAg9GvvBjV5+01kWnyj4s=
+			</data>
+		</dict>
+		<key>www/mobileui/css/mobileui-colors.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/css/mobileuijs.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			GDBlbooCkiI7KrLQgIfqvNFXQhY=
+			</data>
+			<key>hash2</key>
+			<data>
+			iRY1kNBDKaqrezL+YRQHeo6LUjgdjADxFY5/5oGxFII=
+			</data>
+		</dict>
+		<key>www/mobileui/css/page.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			i61rcCBajdql9yqv+aHt86RSa68=
+			</data>
+			<key>hash2</key>
+			<data>
+			JZdpQlCq9cTOM8O4i2HvwpgOUBf7QpcxuYBpvAi9H2Q=
+			</data>
+		</dict>
+		<key>www/mobileui/css/popover.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ZvJifglSJtqJVWaMjyav6RLyeOg=
+			</data>
+			<key>hash2</key>
+			<data>
+			Wq3b7rNgXdC6sOcygZiC7lEXyTXO0Xq7qrtJRWJmfSc=
+			</data>
+		</dict>
+		<key>www/mobileui/css/progress-circle.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			xab3Ea8xBjnXNilms8joImBqbnI=
+			</data>
+			<key>hash2</key>
+			<data>
+			hgzzIZh2zZpyuct6FlHKnnFsytgpPmIf1uN1uutcilg=
+			</data>
+		</dict>
+		<key>www/mobileui/css/progress-circular.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			UoM8lLhFNSyQtvDxt0ibUgV/T2U=
+			</data>
+			<key>hash2</key>
+			<data>
+			s+Go00Gje+Iesbt7yaYog1CllTlqUjQrMpfjLFe3nMQ=
+			</data>
+		</dict>
+		<key>www/mobileui/css/progress-semicircle.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			TYOuItvNSbnVKRAnUI2RsmkOfYw=
+			</data>
+			<key>hash2</key>
+			<data>
+			6MV/goDtQdVwof2BGqpfPR7xre/oUooPJUgLLtgHXy8=
+			</data>
+		</dict>
+		<key>www/mobileui/css/progressbarjs.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/css/swiper.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			yb967T5eM7uJiyYS+0Vlw05Dvl8=
+			</data>
+			<key>hash2</key>
+			<data>
+			XO0l5XK6ZfSl7yD5J1qXIw9wZvP1oXsynfCOQHAwF1c=
+			</data>
+		</dict>
+		<key>www/mobileui/css/tab.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			m5Pa+SPhOX2ZW+HvdpAVKgPxxYY=
+			</data>
+			<key>hash2</key>
+			<data>
+			t/y3Y7U1wjmm+fU6H3ERWzLlB5GNaSFNnSK9rXd2aIk=
+			</data>
+		</dict>
+		<key>www/mobileui/css/timeline.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			vlGLEQUQHfqmaLioRZgfUtZtdvs=
+			</data>
+			<key>hash2</key>
+			<data>
+			lm+7/Dh1NVr1GZJUPtpGj71AQ+yfYIw1PT3J4y/GzO8=
+			</data>
+		</dict>
+		<key>www/mobileui/css/toast.min.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			FOGYi6PxJdlnIyBljMUwYPIV9Pc=
+			</data>
+			<key>hash2</key>
+			<data>
+			pzDZU6saabpCS+Z6GEerB6jIcjwypQ9mJbHlP6l0rwI=
+			</data>
+		</dict>
+		<key>www/mobileui/js/alert.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			LfHTnMVvCVNgOxX8kp8yUv0oAJU=
+			</data>
+			<key>hash2</key>
+			<data>
+			Kep59yTnOsn6Q+wZ/F/9ypBTNIJ9ia8eKlXoOIFFoYQ=
+			</data>
+		</dict>
+		<key>www/mobileui/js/base.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			kwq2Hvjo/B2LfAhJjBljw9OLe/o=
+			</data>
+			<key>hash2</key>
+			<data>
+			zvyrxTjLREeOcdcADQ/BCXaVOGjBIR+Iku4asdiwIV4=
+			</data>
+		</dict>
+		<key>www/mobileui/js/button.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			PHkFHAPXrevpUvOpGV1OeLxSXM0=
+			</data>
+			<key>hash2</key>
+			<data>
+			CZAqRG3sz5UracnNo9nF9sTlynkzg0MZQXa2R+dgNGg=
+			</data>
+		</dict>
+		<key>www/mobileui/js/chart-bar.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/js/chartist-plugin-tooltip.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			IVoCnydBptGYwpUi7fja+xBCdS0=
+			</data>
+			<key>hash2</key>
+			<data>
+			TBa/6c8rNp5J1NblnWhz1Mb9XWhlgJ7hSThaHEHkNeI=
+			</data>
+		</dict>
+		<key>www/mobileui/js/chartist.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			c6Me7+DxNGPEn5C9Dwtl/Tu9ONQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			ZTn5kcgAiPHN5ZnzF3QfkFnZqbECj1ScrBKgTO02im4=
+			</data>
+		</dict>
+		<key>www/mobileui/js/chartjs.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			CxDapOKmSZQKlEFU/CreAX/Oowc=
+			</data>
+			<key>hash2</key>
+			<data>
+			6uHGN6QPnXGtCc8V20MwglNqI9yxtDbo2HJ4Me8x9pc=
+			</data>
+		</dict>
+		<key>www/mobileui/js/include.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			rQJkO7qNh7V6IRyVJ7G72XVIF8I=
+			</data>
+			<key>hash2</key>
+			<data>
+			fpkbg7hRqMB4Smao24DXVvhvLD7pDV8qkwUueb9KXjw=
+			</data>
+		</dict>
+		<key>www/mobileui/js/input.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			BaLNs6W7F9XN8yghwB8reYw0uc8=
+			</data>
+			<key>hash2</key>
+			<data>
+			CCr4rEucN18zaFvTbl9x912AANjfBdNFnMM8PKWzbn8=
+			</data>
+		</dict>
+		<key>www/mobileui/js/jquery.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			xGO1JUuE7CIisKPpNE0e+3OtQn8=
+			</data>
+			<key>hash2</key>
+			<data>
+			VqknYenKf1XowFlLCLrM2u2b6hjwJCvwY400EsuH3oM=
+			</data>
+		</dict>
+		<key>www/mobileui/js/loading.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			3AvjaNooLSHVduwWCty/ZKRHMnk=
+			</data>
+			<key>hash2</key>
+			<data>
+			8+ku/kbPIyr7henTBRgFsu/p9cgH6RqLjD3KoFRUwCQ=
+			</data>
+		</dict>
+		<key>www/mobileui/js/menu.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			6a/9f5KoapYzscm8YwHvJM0eQXs=
+			</data>
+			<key>hash2</key>
+			<data>
+			1y+ULp0H9fJWuc1bENDIc0Av4uTDN8eeguXSYPMS8wU=
+			</data>
+		</dict>
+		<key>www/mobileui/js/mobileui-colors.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			1Rq4XGVDhTudtaSwNHsqFgEeKXU=
+			</data>
+			<key>hash2</key>
+			<data>
+			pkAKYeR/SAzziNkaSWKH43O0xBAKokk+9zVg9U1PGZY=
+			</data>
+		</dict>
+		<key>www/mobileui/js/mobileuijs.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			1lwAb8h1+O1HKaL5T/Qt2ZtcFTA=
+			</data>
+			<key>hash2</key>
+			<data>
+			tYyFEGXyqDxYhg/8YkkHHxjPVakfx1lDyJzPZGQa+E8=
+			</data>
+		</dict>
+		<key>www/mobileui/js/momentjs.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4VJgVytpHZ/slyLzmCYeIzuWNQU=
+			</data>
+			<key>hash2</key>
+			<data>
+			WBnJEJ1t+yNxF7XSyaEjQ8wJWILDw70hVP5l5eXTfl8=
+			</data>
+		</dict>
+		<key>www/mobileui/js/page.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			3gw3uDYgD8Y5xsjSB/8tjEiEzTk=
+			</data>
+			<key>hash2</key>
+			<data>
+			DnqmO7hAb4aRDzmmlVqGBpVYA/EaGpROyNZQrEtSebw=
+			</data>
+		</dict>
+		<key>www/mobileui/js/popover.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			yGz5Ik/RAUbGr9x2LBSSvBMfXD4=
+			</data>
+			<key>hash2</key>
+			<data>
+			nuM1wlxFl/XWVUukn4RV+UwOJSXNmWFK35xiluvzxa0=
+			</data>
+		</dict>
+		<key>www/mobileui/js/progress-circle.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			chiZ1v273z4xiA6okgaS5zzlDs0=
+			</data>
+			<key>hash2</key>
+			<data>
+			R7zB2b1mMWhZqC0mn56N+0iWPlgU1vqogb9nZwhgvzY=
+			</data>
+		</dict>
+		<key>www/mobileui/js/progress-circular.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+			</data>
+			<key>hash2</key>
+			<data>
+			47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
+			</data>
+		</dict>
+		<key>www/mobileui/js/progress-semicircle.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			h7qDXHoEJrTSEHaw9noGk0MJi9c=
+			</data>
+			<key>hash2</key>
+			<data>
+			CBQ4gAYAyvtM1/ZaL6PzXCMgRgXarBBkLB5kzj7u0e4=
+			</data>
+		</dict>
+		<key>www/mobileui/js/progressbarjs.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			qjjwCxEqt+D7o3UY9GSbfxcZBYk=
+			</data>
+			<key>hash2</key>
+			<data>
+			qHCYshpFcvPUj7dn3dCCTGWrCtloByNcxSoQ0eFrBiw=
+			</data>
+		</dict>
+		<key>www/mobileui/js/pulltorefresh.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			hKuS2jMxIaJ7MyUCUHxlFuvq19s=
+			</data>
+			<key>hash2</key>
+			<data>
+			yvmS7MvmqOQKyLU6Om/mY+2l0CtDGVMtXs18YN40NxI=
+			</data>
+		</dict>
+		<key>www/mobileui/js/swiper.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			nU+uUsS4VEnKzLC0B1OPDeLXut4=
+			</data>
+			<key>hash2</key>
+			<data>
+			uNVb/8zfWKcoC9vcTQbMw9+FKqyn2Tl1yip2uEIHRNI=
+			</data>
+		</dict>
+		<key>www/mobileui/js/tab.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			kCGVo9TQHEaDIaM1SXtTnmC5ozQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			nZsI8a/SFQSjo79Jj1yYAiSuu7hEvcAny3HDAC6IL8s=
+			</data>
+		</dict>
+		<key>www/mobileui/js/toast.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			5q7tLrz0Cd6KddL57WTWFL9tnq8=
+			</data>
+			<key>hash2</key>
+			<data>
+			XForcgSew2hQasqv7TaCN9OcIgzNBOU7iFlGB+ieBb8=
+			</data>
+		</dict>
+		<key>www/mobileui/mobileui.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			g2anuCpLPUx/U3O/mFdaMI7m7a0=
+			</data>
+			<key>hash2</key>
+			<data>
+			MwlJMvfVhUjoG8iG/FsKfnjQKpzYRrnw3epRR89SKK8=
+			</data>
+		</dict>
+		<key>www/mobileui/style.css</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			heGNNKQaZlidpB3qvXFXCW/7bX0=
+			</data>
+			<key>hash2</key>
+			<data>
+			otER8eJerTAz1mG9IypR/8h6ZnJtH1dwz3H0eVsHA5M=
+			</data>
+		</dict>
+		<key>www/paypwdmng.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			+Mjis5f4NK8v7VpKUbilfHxz4no=
+			</data>
+			<key>hash2</key>
+			<data>
+			t0W8anxrvghR8qxr0xHYtJiQNxs5TF1z9sKXRD5nvzo=
+			</data>
+		</dict>
+		<key>www/paypwdset.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			jk0aykLVh641N2POWhpQBCd1gpw=
+			</data>
+			<key>hash2</key>
+			<data>
+			gHByyaVqbwUzNTY7n4oPTwKWnpaRCRl3zew03lOKNMk=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/advanced-http.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			B8n20vLKxAKUZXJMxaWXV6gbh2g=
+			</data>
+			<key>hash2</key>
+			<data>
+			Sj0ciU72BCIWewNiP8zmvVdXZcBCbpYKUsD6qwJtJwE=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			oigj9UWbSZ7wilh4lNqA+/0zRi8=
+			</data>
+			<key>hash2</key>
+			<data>
+			Rf4naep9IIYO3KmnvmTI5aVGGSshGmLru5xdOISml5A=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/global-configs.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			on11EqlCJXmxELeXuLpMjxXAoN4=
+			</data>
+			<key>hash2</key>
+			<data>
+			S5N1aT0JocjNRPHFTG5EZC543ZE9ozgIQ2M6Po7aBjc=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/helpers.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			7zDV1mSEzs8Zrrge1l4b8uo0/Ms=
+			</data>
+			<key>hash2</key>
+			<data>
+			u8AjmGyjYxtSRiSebg0oLtVjK2YALDpXUHSHrahTYYc=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/js-util.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			8SpJyt/PDx7N78EdBnsMGuyvVRY=
+			</data>
+			<key>hash2</key>
+			<data>
+			J8rz6WfCCQBS8Hf2d2465WMvQnzQbv7yM1DwbOyb8Xk=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Ehxxu28zPv4FNqoEmNEWWsAmcgU=
+			</data>
+			<key>hash2</key>
+			<data>
+			r5i6EDE/0Cd1mwxHaSyoD30K17wLb/dcpKZld2IXC5o=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/lodash.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			UYDd8AwVTHEkAY2Vuqarw4qHqNU=
+			</data>
+			<key>hash2</key>
+			<data>
+			7lmFGf/NQg1SVWp9V6fWLM9SSPuRGEyxNE6gPcqHFTM=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/messages.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			a+LSD4JskmzyBECg0xOc94fVEik=
+			</data>
+			<key>hash2</key>
+			<data>
+			ghwj8EDCj1XN+AGxa78iRjLO6kPHA2PjRCSBszjBA44=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/public-interface.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			fxOWbnRNP19ezKuY8y92WUueT/8=
+			</data>
+			<key>hash2</key>
+			<data>
+			cBlD32flyvXYZx+Teu/cgJLLu3ha+LZqWl2Txda34Ec=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			LdGHCdPTclRj5d2Fie8n45Zrqos=
+			</data>
+			<key>hash2</key>
+			<data>
+			4ORjR7StRhbLN1JUes4piZXx6W85JNIBDMGheyRjZnA=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-advanced-http/www/url-util.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			09a/If3TGPR46gxmzbSwdbcSvBc=
+			</data>
+			<key>hash2</key>
+			<data>
+			PwOMlqlVzVgIZXZ1SbMCjBbNhPUtIEmbS1IuHC4X+FE=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-camera/www/Camera.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			/Tl12sGFo/UZbPqnupaaV0Hg0vU=
+			</data>
+			<key>hash2</key>
+			<data>
+			/DpMZq7FrbVwiAPbYjr190ea8NHGPLsnbwbi8KjR3Ws=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-camera/www/CameraConstants.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			v2sA7ZeHf4g2R4hremuTEjIZPUY=
+			</data>
+			<key>hash2</key>
+			<data>
+			wkl+aO8lHNbXrlvHUVFvZ3XWmxJ5kE3QH9Cb1DKW2i4=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DFjhGlevsoLz/p7Ls+/7LBfept8=
+			</data>
+			<key>hash2</key>
+			<data>
+			rQlfvrBqSocgsPtkPqzytzsYymwS7jJHaaatC6XG0Fo=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			koRc23xo1lElHctG97l7ayo1asw=
+			</data>
+			<key>hash2</key>
+			<data>
+			9IOEZkfMOskH8iiS25t1CoLQOEpPsEj4j/xUN5HLHBM=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-device/www/device.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			1GfO/IDwwyLde/veo05ABQB5yTk=
+			</data>
+			<key>hash2</key>
+			<data>
+			lxEtW0KU6QKkPs5VCr3ZhsLIA3wAu5RMxZ4W4izq3gE=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/DirectoryEntry.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			9BG1PRAVfskBKfTqRqUcFP0XF9c=
+			</data>
+			<key>hash2</key>
+			<data>
+			QAqnXaChiHj3l+lUTDs6saHB8D7J1uDV1Ny8JVnxrjE=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/DirectoryReader.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			55JSYGGn83vzv0lzH64YGshyORE=
+			</data>
+			<key>hash2</key>
+			<data>
+			sCKl8gNHsNgxPznBN92CVBEB2gJwM1HSbOtj97arSCU=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/Entry.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ApUt9yA8EFcC9lNWD2XthcwuD90=
+			</data>
+			<key>hash2</key>
+			<data>
+			HTqrVkuqo4OmD+ZeuYUV5f25oaXnFnkCMMUt2QeSYiM=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/File.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			0LUBfKUsBSQvmUgurtpKYgJ9hTc=
+			</data>
+			<key>hash2</key>
+			<data>
+			vbuk8pkY+FlA2QWlncUHsMK6SlX3wWdFBxaRXw99cu8=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileEntry.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ihG+3x+RWP1Qk72v0C0MZRzRpBM=
+			</data>
+			<key>hash2</key>
+			<data>
+			aGB7ZIxrb5JelbnW/PXW9xWLEKwva3obGaIKSJvPW4M=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileError.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ybFlxPqO/jPqMsmoDwkc2rpE4pk=
+			</data>
+			<key>hash2</key>
+			<data>
+			S7iNf0zl91/UZNbxz8xXINq6StEX+BQBy4/Xhx2Oa2g=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileReader.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			L5sKPsNlBpVIEJtZOnDhtA1g05M=
+			</data>
+			<key>hash2</key>
+			<data>
+			UpQvww+xh9Gyk8c6o79tBlYZEVaJb8YwQwfHXFkn1Sk=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileSystem.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			DmfGhjz4PYPDj99FWJ3nDLQzZFU=
+			</data>
+			<key>hash2</key>
+			<data>
+			UD5gbb5uPbU7U8ZvxIMWzywAiI09zcMVRv67ASVnlUs=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileUploadOptions.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4mPbde3/XqIbBp41y0kN00aYZl4=
+			</data>
+			<key>hash2</key>
+			<data>
+			dBe0OI3UlfQusNagAlOcaimQEvK7mUEgtQlqQPKlRHU=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileUploadResult.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4CNnib6yO4/uwX7VyIeJgpFLHFU=
+			</data>
+			<key>hash2</key>
+			<data>
+			2GdXwcKcLcDGjnYW4nzK9ydUvbdwAaXsPzhNMA37bsQ=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/FileWriter.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			vbjAors/bOvXxKiKru01s/f2AxY=
+			</data>
+			<key>hash2</key>
+			<data>
+			DAUHhK18WDFC7hl0bGBtyg0HOZql2yEu1qNLwBfZGJ0=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/Flags.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			Ysk6KgwRoqjZINAl/q0VjlC2vmA=
+			</data>
+			<key>hash2</key>
+			<data>
+			NQZ/QSIoIrIJpIx3ZGfpWieK1Ihy2ELrkZUPLTJ6tog=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/LocalFileSystem.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			kJtPgG7aLCq5neelEB+/sObHR1w=
+			</data>
+			<key>hash2</key>
+			<data>
+			6Myhmkm3/vfKwbMIdFsp/4x/ZbLoYv9Fv1240nW/jr0=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/Metadata.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			sNBGG0nAD0xDLoOYeaiDlfLVBBM=
+			</data>
+			<key>hash2</key>
+			<data>
+			LGUbchqLzHcCMK5eiEnZ2iID+NqMJvBkB1MY8fzbqR8=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/ProgressEvent.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			blyr1jNE9lOGJJOyQkWfS+CB+7o=
+			</data>
+			<key>hash2</key>
+			<data>
+			vfs5XhNMkJT6m9AIsuXhDH4zqZhld2d5oGRATraBDJI=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/browser/isChrome.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ubIP1VXq/ILYzY1GaBx+PA7ZEEo=
+			</data>
+			<key>hash2</key>
+			<data>
+			3zcakG51eOwAQ/f3AZpyO+uhVUUBbSC7MMsD9LW/F74=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/fileSystemPaths.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			RhbxeeiCkMHVAnWLOaEFTyx3fVk=
+			</data>
+			<key>hash2</key>
+			<data>
+			6h/jjda1DuJmHTptgf/l0gFRI2zELCT4Tq/31J8+orI=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/fileSystems-roots.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			jPjM9Gkr4Fs2O+qPCdRiDfQRmF8=
+			</data>
+			<key>hash2</key>
+			<data>
+			Jw7sHq3hCASoXmvrPqjBT6huoxTKBUECp1v6B5Nap1A=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/fileSystems.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			GjxvyRube37zK13yXu3TWWdWPpQ=
+			</data>
+			<key>hash2</key>
+			<data>
+			frl3z+W6IW37ZtDP5/vp63ZqUnXqDwRXaOUo8EDiHgU=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/ios/FileSystem.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			3ueSGiRIUcEFNSxl7V3z1JdmqWA=
+			</data>
+			<key>hash2</key>
+			<data>
+			M/9OOdeH99vASy+n1QceXphEDEltxCdCRshnX0wRIOk=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/requestFileSystem.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ZVeb2nnbn/aetQV5ipRWH7M+Q9c=
+			</data>
+			<key>hash2</key>
+			<data>
+			urkokGlRGZ9dCt1soyOx46MJ2iaKCTHz7c9QUlPxbU4=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			p7A9a+/7es1E4aKJPkx0j6eQwuw=
+			</data>
+			<key>hash2</key>
+			<data>
+			2r19nzz0vvRYaDlexf+ZC0go3w4I74oCafncQ2Noe3U=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			I6HhWVv3fSBNmlXWaeqJGHD2g4c=
+			</data>
+			<key>hash2</key>
+			<data>
+			dP6AsIy3k69ipb7n/wzbRmOV40zjlLM+m3hHznn2wXo=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			04BAdz7ulKVCu3lMDwCrtzoPTJA=
+			</data>
+			<key>hash2</key>
+			<data>
+			FCu11gkLUdAX8FSq0fp81oMiQpBkqbX6AbJfNn5xmfs=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-qrscanner/www/www.min.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			ufmAW+h1oKmygvcqG3eipjK7YXo=
+			</data>
+			<key>hash2</key>
+			<data>
+			14jHmvEILVfcqBaCEhxxV4JSxHXdNSlE50j1F9JbTY4=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-statusbar/www/statusbar.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			hDT++3ZaOTp3t16AAFAibxtovj0=
+			</data>
+			<key>hash2</key>
+			<data>
+			JVFddhH/G0jM/7U0DOdpW1CvUNswIGcQB9WylyRtCBM=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			TvdsWbaWx459ckVtYew11Fv3LHk=
+			</data>
+			<key>hash2</key>
+			<data>
+			Ob7JvO8hSkdMJm/kHyW+KN2PlASi/3uMvu1a6WqOCbA=
+			</data>
+		</dict>
+		<key>www/plugins/cordova-plugin-touch-id/www/TouchID.js</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			oGafU2UdHnS6q3vnNz3WB2an0TY=
+			</data>
+			<key>hash2</key>
+			<data>
+			pw9ge6okwHZeP0dHYYlBTFuDJUkZQDPAKRM006KG8ek=
+			</data>
+		</dict>
+		<key>www/pwdset.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			V3rync0T0/WyYm1RxOmrQ0VHwls=
+			</data>
+			<key>hash2</key>
+			<data>
+			+UqU5skBCCBiflQIsGg1OBAYwWoZqx2cJUXNofB45EU=
+			</data>
+		</dict>
+		<key>www/qrcode.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			/T8vAhNAeCOJv1Hw6L4detL0zZE=
+			</data>
+			<key>hash2</key>
+			<data>
+			owfyBn4pS5DnYeA3edJ/WmjW1ANLhwT8SdO2fRM3yqQ=
+			</data>
+		</dict>
+		<key>www/register.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			j0E17LezraXxL2i9s0tnnWrl9vw=
+			</data>
+			<key>hash2</key>
+			<data>
+			Iu5z6Xp9qSJxhhkhGheMQI9Ns2tMH0hhOpULa3eMjek=
+			</data>
+		</dict>
+		<key>www/scan.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			S7i5xbTkGWEkJnCEypdQTNWiAJs=
+			</data>
+			<key>hash2</key>
+			<data>
+			7FGHF5M0Dj6lOnhWymuVGPKe4evIlO1HGnBpIJcq+eg=
+			</data>
+		</dict>
+		<key>www/security.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			WAAOaAVzFhUpl9ay3iHsxkW83wo=
+			</data>
+			<key>hash2</key>
+			<data>
+			PQQQEnclRlF/NWm1k2k7h+03o0vELPqdci0FJbjkxHE=
+			</data>
+		</dict>
+		<key>www/signxy.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			puCiWzwhuAhLymirq4ajsw8iYJw=
+			</data>
+			<key>hash2</key>
+			<data>
+			+skywbX5sF8t2T+934wL/OnZF4hJcqil6h1XQp06zRg=
+			</data>
+		</dict>
+		<key>www/signxycheck.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			OC5VO7siXCVWFdZQFLrRkOG5Jdk=
+			</data>
+			<key>hash2</key>
+			<data>
+			K+OIpvhIfjlVjmqcZ0zX2HKs3wgjAPTg2JdK+oCYhGg=
+			</data>
+		</dict>
+		<key>www/uxy.html</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			jMDdxxafEFBcjhH4qe9hZ4Pytho=
+			</data>
+			<key>hash2</key>
+			<data>
+			EJiYgJTHhlsW+92S9oDIy3U8xpY9Ph7yKtAy8DxiuSE=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/config.xml b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/config.xml
new file mode 100755
index 0000000..b9c0ba5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/config.xml
@@ -0,0 +1,104 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage" />
+    </feature>
+    <feature name="Console">
+        <param name="ios-package" value="CDVLogger" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="HandleOpenUrl">
+        <param name="ios-package" value="CDVHandleOpenURL" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="IntentAndNavigationFilter">
+        <param name="ios-package" value="CDVIntentAndNavigationFilter" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="GestureHandler">
+        <param name="ios-package" value="CDVGestureHandler" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="File">
+        <param name="ios-package" value="CDVFile" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="CordovaHttpPlugin">
+        <param name="ios-package" value="CordovaHttpPlugin" />
+    </feature>
+    <feature name="Fingerprint">
+        <param name="ios-package" value="Fingerprint" />
+    </feature>
+    <feature name="StatusBar">
+        <param name="ios-package" value="CDVStatusBar" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="TouchID">
+        <param name="ios-package" value="TouchID" />
+    </feature>
+    <feature name="DisableStatusbar">
+        <param name="ios-package" value="DisableStatusbar" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="QRScanner">
+        <param name="ios-package" value="QRScanner" />
+    </feature>
+    <feature name="Camera">
+        <param name="ios-package" value="CDVCamera" />
+    </feature>
+    <feature name="InAppBrowser">
+        <param name="ios-package" value="CDVInAppBrowser" />
+    </feature>
+    <feature name="Device">
+        <param name="ios-package" value="CDVDevice" />
+    </feature>
+    <feature name="ThemeableBrowser">
+        <param name="ios-package" value="CDVThemeableBrowser" />
+    </feature>
+    <name>dlapp</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <allow-intent href="http://*/*" />
+    <allow-intent href="https://*/*" />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*" />
+    <allow-intent href="geo:*" />
+    <allow-navigation href="http://*/*" />
+    <allow-navigation href="https://*/*" />
+    <allow-navigation href="data:*" />
+    <access origin="http://ip*" />
+    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+        <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+    </edit-config>
+    <allow-intent href="itms:*" />
+    <allow-intent href="itms-apps:*" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="BackupWebStorage" value="local" />
+    <preference name="DisallowOverscroll" value="true" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="SuppressesLongPressGesture" value="false" />
+    <preference name="Suppresses3DTouchGesture" value="false" />
+    <preference name="GapBetweenPages" value="0" />
+    <preference name="PageLength" value="0" />
+    <preference name="PaginationBreakingMode" value="page" />
+    <preference name="PaginationMode" value="unpaginated" />
+    <preference name="StatusBarOverlaysWebView" value="true" />
+    <preference name="StatusBarStyle" value="lightcontent" />
+    <preference name="CameraUsesGeolocation" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="SplashScreenDelay" value="0" />
+    <preference name="ErrorUrl" value="error.html" />
+    <preference name="Orientation" value="portrait" />
+    <preference name="UseSwiftLanguageVersion" value="4.0" />
+    <preference name="UIWebViewBounce" value="false" />
+</widget>
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/dlapp b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/dlapp
new file mode 100755
index 0000000..a189756
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/dlapp
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/embedded.mobileprovision b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/embedded.mobileprovision
new file mode 100644
index 0000000..abda867
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/embedded.mobileprovision
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bill.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bill.html
new file mode 100644
index 0000000..e70285f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bill.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>账单</title>
+</head>
+
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账单</div>
+    </header>
+    <div style="overflow: scroll;position: absolute;top:74px;bottom:0px;left: 0;right: 0">
+        <div class="aui-card-list" id="billcontent">
+            
+        </div>
+         <div class="aui-card-list-footer aui-text-center" id="loadNext" onclick="app.loadNext()" style="background:#fff;display: none;">
+            继续加载
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/bill.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/billdetail.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/billdetail.html
new file mode 100644
index 0000000..8bbde06
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/billdetail.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>账单详情</title>
+</head>
+
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账单详情</div>
+    </header>
+    <header class="demos-header">
+      <h1 class="demos-title" id="amount"></h1>
+      <h1 class="detail-title" id="status"></h1>
+    </header>
+    <div class="weui-form-preview">
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">交易名称</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="tranddes">&nbsp;</em>
+        </div>
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">交易时间</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="transtime">&nbsp;</em>
+        </div>
+        <div class="weui-form-preview__hd" style="padding: 5px 10px;">
+            <label class="weui-form-preview__label">订单编号</label>
+            <em class="weui-form-preview__value" style="font-size: 1.1em;" id="refno">&nbsp;</em>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/billdetail.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bindcard.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bindcard.html
new file mode 100644
index 0000000..3ec9d26
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/bindcard.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>绑定银行卡</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">绑定银行卡</div>
+    </header>
+    <div>
+        <div class="weui-cells__title">市民卡信息</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">姓名</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="text" id="name" style="font-size: 14px;" placeholder="请输入您的真实姓名">
+                </div>
+            </div>
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">银行卡号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="text" id="cardnum" style="font-size: 14px;" placeholder="市民卡对应的银行卡号">
+                </div>
+            </div>
+        </div>
+
+        <div class="weui-cells__title">短信验证市民卡预留的手机号</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" disabled="disabled" >
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">下一步</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/bindcard.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/card.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/card.html
new file mode 100644
index 0000000..3c48354
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/card.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>市民卡挂失</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">市民卡挂失</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd"  pattern="[0-9]*" placeholder="请输入支付密码" maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">挂失</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/card.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cardinfor.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cardinfor.html
new file mode 100644
index 0000000..19ea1df
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cardinfor.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>银行卡</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">银行卡</div>
+    </header>
+    <div>
+        <div class="weui-cells">
+            <div class="weui-cell">
+                <div class="weui-cell__bd">
+                    <p>姓名</p>
+                </div>
+                <div class="weui-cell__ft" id="name"></div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__bd">
+                    <p>银行卡号</p>
+                </div>
+                <div class="weui-cell__ft" id="cardnum"></div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__bd">
+                    <p>状态</p>
+                </div>
+                <div class="weui-cell__ft" id="cardstatus"></div>
+            </div>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/cardinfor.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/exec.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/exec.js
new file mode 100644
index 0000000..3fb7fa1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/exec.js
@@ -0,0 +1,262 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/*global require, module, atob, document */
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    execIframe,
+    commandQueue = [], // Contains pending JS->Native messages.
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
+
+function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+        return args;
+    }
+    var ret = [];
+    args.forEach(function(arg, i) {
+        if (utils.typeName(arg) == 'ArrayBuffer') {
+            ret.push({
+                'CDVType': 'ArrayBuffer',
+                'data': base64.fromArrayBuffer(arg)
+            });
+        } else {
+            ret.push(arg);
+        }
+    });
+    return ret;
+}
+
+function massageMessageNativeToJs(message) {
+    if (message.CDVType == 'ArrayBuffer') {
+        var stringToArrayBuffer = function(str) {
+            var ret = new Uint8Array(str.length);
+            for (var i = 0; i < str.length; i++) {
+                ret[i] = str.charCodeAt(i);
+            }
+            return ret.buffer;
+        };
+        var base64ToArrayBuffer = function(b64) {
+            return stringToArrayBuffer(atob(b64));
+        };
+        message = base64ToArrayBuffer(message.data);
+    }
+    return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+    var args = [];
+    if (!message || !message.hasOwnProperty('CDVType')) {
+        args.push(message);
+    } else if (message.CDVType == 'MultiPart') {
+        message.messages.forEach(function(e) {
+            args.push(massageMessageNativeToJs(e));
+        });
+    } else {
+        args.push(massageMessageNativeToJs(message));
+    }
+    return args;
+}
+
+function iOSExec() {
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== 'string') {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+            'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
+        );
+    }
+
+    // If actionArgs is not provided, default to an empty array
+    actionArgs = actionArgs || [];
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] =
+            {success:successCallback, fail:failCallback};
+    }
+
+    actionArgs = massageArgsJsToNative(actionArgs);
+
+    var command = [callbackId, service, action, actionArgs];
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    commandQueue.push(JSON.stringify(command));
+
+    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+    // then the queue will be flushed when it returns; no need for a poke.
+    // Also, if there is already a command in the queue, then we've already
+    // poked the native side, so there is no reason to do so again.
+    if (!isInContextOfEvalJs && commandQueue.length == 1) {
+        pokeNative();
+    }
+}
+
+// CB-10530
+function proxyChanged() {
+    var cexec = cordovaExec();
+       
+    return (execProxy !== cexec && // proxy objects are different
+            iOSExec !== cexec      // proxy object is not the current iOSExec
+            );
+}
+
+// CB-10106
+function handleBridgeChange() {
+    if (proxyChanged()) {
+        var commandString = commandQueue.shift();
+        while(commandString) {
+            var command = JSON.parse(commandString);
+            var callbackId = command[0];
+            var service = command[1];
+            var action = command[2];
+            var actionArgs = command[3];
+            var callbacks = cordova.callbacks[callbackId] || {};
+            
+            execProxy(callbacks.success, callbacks.fail, service, action, actionArgs);
+            
+            commandString = commandQueue.shift();
+        };
+        return true;
+    }
+    
+    return false;
+}
+
+function pokeNative() {
+    // CB-5488 - Don't attempt to create iframe before document.body is available.
+    if (!document.body) {
+        setTimeout(pokeNative);
+        return;
+    }
+    
+    // Check if they've removed it from the DOM, and put it back if so.
+    if (execIframe && execIframe.contentWindow) {
+        execIframe.contentWindow.location = 'gap://ready';
+    } else {
+        execIframe = document.createElement('iframe');
+        execIframe.style.display = 'none';
+        execIframe.src = 'gap://ready';
+        document.body.appendChild(execIframe);
+    }
+    // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+    // This makes the bridge ~ 7% slower, but works around the poke getting lost
+    // when the iframe is removed from the DOM.
+    // An onunload listener could be used in the case where the iframe has just been
+    // created, but since unload events fire only once, it doesn't work in the normal
+    // case of iframe reuse (where unload will have already fired due to the attempted
+    // navigation of the page).
+    failSafeTimerId = setTimeout(function() {
+        if (commandQueue.length) {
+            // CB-10106 - flush the queue on bridge change
+            if (!handleBridgeChange()) {
+                pokeNative();
+             }
+        }
+    }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+}
+
+iOSExec.nativeFetchMessages = function() {
+    // Stop listing for window detatch once native side confirms poke.
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
+    }
+    // Each entry in commandQueue is a JSON string already.
+    if (!commandQueue.length) {
+        return '';
+    }
+    var json = '[' + commandQueue.join(',') + ']';
+    commandQueue.length = 0;
+    return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+    return iOSExec.nativeEvalAndFetch(function() {
+        var success = status === 0 || status === 1;
+        var args = convertMessageToArgsNativeToJs(message);
+        function nc2() {
+            cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+        }
+        setTimeout(nc2, 0);
+    });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+    // This shouldn't be nested, but better to be safe.
+    isInContextOfEvalJs++;
+    try {
+        func();
+        return iOSExec.nativeFetchMessages();
+    } finally {
+        isInContextOfEvalJs--;
+    }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+    var cexec = require('cordova/exec');
+    var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+    return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+    cordovaExec().apply(null, arguments);
+};
+
+execProxy.nativeFetchMessages = function() {
+    return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+    return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+    return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/platform.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/platform.js
new file mode 100644
index 0000000..2345fa5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/platform.js
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+module.exports = {
+    id: 'ios',
+    bootstrap: function () {
+        // Attach the console polyfill that is iOS-only to window.console
+        // see the file under plugin/ios/console.js
+        require('cordova/modulemapper').clobbers('cordova/plugin/ios/console', 'window.console');
+
+        require('cordova/channel').onNativeReady.fire();
+    }
+};
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/console.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/console.js
new file mode 100644
index 0000000..6224fb4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/console.js
@@ -0,0 +1,186 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+//------------------------------------------------------------------------------
+
+var logger = require('cordova/plugin/ios/logger');
+
+//------------------------------------------------------------------------------
+// object that we're exporting
+//------------------------------------------------------------------------------
+var console = module.exports;
+
+//------------------------------------------------------------------------------
+// copy of the original console object
+//------------------------------------------------------------------------------
+var WinConsole = window.console;
+
+//------------------------------------------------------------------------------
+// whether to use the logger
+//------------------------------------------------------------------------------
+var UseLogger = false;
+
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+var Timers = {};
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+function noop() {}
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+console.useLogger = function (value) {
+    if (arguments.length) UseLogger = !!value;
+
+    if (UseLogger) {
+        if (logger.useConsole()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+    }
+
+    return UseLogger;
+};
+
+//------------------------------------------------------------------------------
+console.log = function() {
+    if (logger.useConsole()) return;
+    logger.log.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.error = function() {
+    if (logger.useConsole()) return;
+    logger.error.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.warn = function() {
+    if (logger.useConsole()) return;
+    logger.warn.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.info = function() {
+    if (logger.useConsole()) return;
+    logger.info.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.debug = function() {
+    if (logger.useConsole()) return;
+    logger.debug.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.assert = function(expression) {
+    if (expression) return;
+
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
+    console.log("ASSERT: " + message);
+};
+
+//------------------------------------------------------------------------------
+console.clear = function() {};
+
+//------------------------------------------------------------------------------
+console.dir = function(object) {
+    console.log("%o", object);
+};
+
+//------------------------------------------------------------------------------
+console.dirxml = function(node) {
+    console.log(node.innerHTML);
+};
+
+//------------------------------------------------------------------------------
+console.trace = noop;
+
+//------------------------------------------------------------------------------
+console.group = console.log;
+
+//------------------------------------------------------------------------------
+console.groupCollapsed = console.log;
+
+//------------------------------------------------------------------------------
+console.groupEnd = noop;
+
+//------------------------------------------------------------------------------
+console.time = function(name) {
+    Timers[name] = new Date().valueOf();
+};
+
+//------------------------------------------------------------------------------
+console.timeEnd = function(name) {
+    var timeStart = Timers[name];
+    if (!timeStart) {
+        console.warn("unknown timer: " + name);
+        return;
+    }
+
+    var timeElapsed = new Date().valueOf() - timeStart;
+    console.log(name + ": " + timeElapsed + "ms");
+};
+
+//------------------------------------------------------------------------------
+console.timeStamp = noop;
+
+//------------------------------------------------------------------------------
+console.profile = noop;
+
+//------------------------------------------------------------------------------
+console.profileEnd = noop;
+
+//------------------------------------------------------------------------------
+console.count = noop;
+
+//------------------------------------------------------------------------------
+console.exception = console.log;
+
+//------------------------------------------------------------------------------
+console.table = function(data, columns) {
+    console.log("%o", data);
+};
+
+//------------------------------------------------------------------------------
+// return a new function that calls both functions passed as args
+//------------------------------------------------------------------------------
+function wrappedOrigCall(orgFunc, newFunc) {
+    return function() {
+        var args = [].slice.call(arguments);
+        try { orgFunc.apply(WinConsole, args); } catch (e) {}
+        try { newFunc.apply(console,    args); } catch (e) {}
+    };
+}
+
+//------------------------------------------------------------------------------
+// For every function that exists in the original console object, that
+// also exists in the new console object, wrap the new console method
+// with one that calls both
+//------------------------------------------------------------------------------
+for (var key in console) {
+    if (typeof WinConsole[key] == "function") {
+        console[key] = wrappedOrigCall(WinConsole[key], console[key]);
+    }
+}
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/logger.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/logger.js
new file mode 100644
index 0000000..430d887
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova-js-src/plugin/ios/logger.js
@@ -0,0 +1,354 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports;
+
+var exec    = require('cordova/exec');
+
+var UseConsole   = false;
+var UseLogger    = true;
+var Queued       = [];
+var DeviceReady  = false;
+var CurrentLevel;
+
+var originalConsole = console;
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+];
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {};
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i];
+    LevelsMap[level] = i;
+    logger[level]    = level;
+}
+
+CurrentLevel = LevelsMap.WARN;
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  E.g., the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] === null) {
+            throw new Error("invalid logging level: " + value);
+        }
+        CurrentLevel = LevelsMap[value];
+    }
+
+    return Levels[CurrentLevel];
+};
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value;
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined");
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function");
+        }
+
+        if (typeof console.useLogger == "function") {
+            if (console.useLogger()) {
+                throw new Error("console and logger are too intertwingly");
+            }
+        }
+    }
+
+    return UseConsole;
+};
+
+/**
+ * Getter/Setter for the useLogger functionality
+ *
+ * When useLogger is true, the logger will log via the
+ * native Logger plugin.
+ */
+logger.useLogger = function (value) {
+    // Enforce boolean
+    if (arguments.length) UseLogger = !!value;
+    return UseLogger;
+};
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments); };
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments); };
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments); };
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    args = [level].concat([].slice.call(args));
+    logger.logLevel.apply(logger, args);
+}
+
+// return the correct formatString for an object
+function formatStringForMessage(message) {
+    return (typeof message === "string") ? "" : "%o"; 
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 1);
+    var fmtString = formatStringForMessage(formatArgs[0]);
+    if (fmtString.length > 0){
+        formatArgs.unshift(fmtString); // add formatString
+    }
+
+    var message    = logger.format.apply(logger.format, formatArgs);
+
+    if (LevelsMap[level] === null) {
+        throw new Error("invalid logging level: " + level);
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return;
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message]);
+        return;
+    }
+
+    // Log using the native logger if that is enabled
+    if (UseLogger) {
+        exec(null, null, "Console", "logLevel", [level, message]);
+    }
+
+    // Log using the console if that is enabled
+    if (UseConsole) {
+        // make sure console is not using logger
+        if (console.useLogger()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+
+        // log to the console
+        switch (level) {
+            case logger.LOG:   originalConsole.log(message); break;
+            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
+            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
+            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
+            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
+        }
+    }
+};
+
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return;
+
+    DeviceReady = true;
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i];
+        logger.logLevel(messageArgs[0], messageArgs[1]);
+    }
+
+    Queued = null;
+};
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false);
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova.js
new file mode 100644
index 0000000..2e2b33a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova.js
@@ -0,0 +1,2162 @@
+// Platform: ios
+// 948e932548412305aa7f24b3a90e386aa5c3d12c
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '5.0.1';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return { 'document': { 'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener },
+            'window': { 'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener } };
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/*global require, module, atob, document */
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    execIframe,
+    commandQueue = [], // Contains pending JS->Native messages.
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
+
+function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+        return args;
+    }
+    var ret = [];
+    args.forEach(function(arg, i) {
+        if (utils.typeName(arg) == 'ArrayBuffer') {
+            ret.push({
+                'CDVType': 'ArrayBuffer',
+                'data': base64.fromArrayBuffer(arg)
+            });
+        } else {
+            ret.push(arg);
+        }
+    });
+    return ret;
+}
+
+function massageMessageNativeToJs(message) {
+    if (message.CDVType == 'ArrayBuffer') {
+        var stringToArrayBuffer = function(str) {
+            var ret = new Uint8Array(str.length);
+            for (var i = 0; i < str.length; i++) {
+                ret[i] = str.charCodeAt(i);
+            }
+            return ret.buffer;
+        };
+        var base64ToArrayBuffer = function(b64) {
+            return stringToArrayBuffer(atob(b64));
+        };
+        message = base64ToArrayBuffer(message.data);
+    }
+    return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+    var args = [];
+    if (!message || !message.hasOwnProperty('CDVType')) {
+        args.push(message);
+    } else if (message.CDVType == 'MultiPart') {
+        message.messages.forEach(function(e) {
+            args.push(massageMessageNativeToJs(e));
+        });
+    } else {
+        args.push(massageMessageNativeToJs(message));
+    }
+    return args;
+}
+
+function iOSExec() {
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== 'string') {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+            'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
+        );
+    }
+
+    // If actionArgs is not provided, default to an empty array
+    actionArgs = actionArgs || [];
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] =
+            {success:successCallback, fail:failCallback};
+    }
+
+    actionArgs = massageArgsJsToNative(actionArgs);
+
+    var command = [callbackId, service, action, actionArgs];
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    commandQueue.push(JSON.stringify(command));
+
+    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+    // then the queue will be flushed when it returns; no need for a poke.
+    // Also, if there is already a command in the queue, then we've already
+    // poked the native side, so there is no reason to do so again.
+    if (!isInContextOfEvalJs && commandQueue.length == 1) {
+        pokeNative();
+    }
+}
+
+// CB-10530
+function proxyChanged() {
+    var cexec = cordovaExec();
+       
+    return (execProxy !== cexec && // proxy objects are different
+            iOSExec !== cexec      // proxy object is not the current iOSExec
+            );
+}
+
+// CB-10106
+function handleBridgeChange() {
+    if (proxyChanged()) {
+        var commandString = commandQueue.shift();
+        while(commandString) {
+            var command = JSON.parse(commandString);
+            var callbackId = command[0];
+            var service = command[1];
+            var action = command[2];
+            var actionArgs = command[3];
+            var callbacks = cordova.callbacks[callbackId] || {};
+            
+            execProxy(callbacks.success, callbacks.fail, service, action, actionArgs);
+            
+            commandString = commandQueue.shift();
+        };
+        return true;
+    }
+    
+    return false;
+}
+
+function pokeNative() {
+    // CB-5488 - Don't attempt to create iframe before document.body is available.
+    if (!document.body) {
+        setTimeout(pokeNative);
+        return;
+    }
+    
+    // Check if they've removed it from the DOM, and put it back if so.
+    if (execIframe && execIframe.contentWindow) {
+        execIframe.contentWindow.location = 'gap://ready';
+    } else {
+        execIframe = document.createElement('iframe');
+        execIframe.style.display = 'none';
+        execIframe.src = 'gap://ready';
+        document.body.appendChild(execIframe);
+    }
+    // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+    // This makes the bridge ~ 7% slower, but works around the poke getting lost
+    // when the iframe is removed from the DOM.
+    // An onunload listener could be used in the case where the iframe has just been
+    // created, but since unload events fire only once, it doesn't work in the normal
+    // case of iframe reuse (where unload will have already fired due to the attempted
+    // navigation of the page).
+    failSafeTimerId = setTimeout(function() {
+        if (commandQueue.length) {
+            // CB-10106 - flush the queue on bridge change
+            if (!handleBridgeChange()) {
+                pokeNative();
+             }
+        }
+    }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+}
+
+iOSExec.nativeFetchMessages = function() {
+    // Stop listing for window detatch once native side confirms poke.
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
+    }
+    // Each entry in commandQueue is a JSON string already.
+    if (!commandQueue.length) {
+        return '';
+    }
+    var json = '[' + commandQueue.join(',') + ']';
+    commandQueue.length = 0;
+    return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+    return iOSExec.nativeEvalAndFetch(function() {
+        var success = status === 0 || status === 1;
+        var args = convertMessageToArgsNativeToJs(message);
+        function nc2() {
+            cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+        }
+        setTimeout(nc2, 0);
+    });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+    // This shouldn't be nested, but better to be safe.
+    isInContextOfEvalJs++;
+    try {
+        func();
+        return iOSExec.nativeFetchMessages();
+    } finally {
+        isInContextOfEvalJs--;
+    }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+    var cexec = require('cordova/exec');
+    var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+    return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+    cordovaExec().apply(null, arguments);
+};
+
+execProxy.nativeFetchMessages = function() {
+    return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+    return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+    return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+    id: 'ios',
+    bootstrap: function () {
+        // Attach the console polyfill that is iOS-only to window.console
+        // see the file under plugin/ios/console.js
+        require('cordova/modulemapper').clobbers('cordova/plugin/ios/console', 'window.console');
+
+        require('cordova/channel').onNativeReady.fire();
+    }
+};
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/console.js
+define("cordova/plugin/ios/console", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+
+var logger = require('cordova/plugin/ios/logger');
+
+//------------------------------------------------------------------------------
+// object that we're exporting
+//------------------------------------------------------------------------------
+var console = module.exports;
+
+//------------------------------------------------------------------------------
+// copy of the original console object
+//------------------------------------------------------------------------------
+var WinConsole = window.console;
+
+//------------------------------------------------------------------------------
+// whether to use the logger
+//------------------------------------------------------------------------------
+var UseLogger = false;
+
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+var Timers = {};
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+function noop() {}
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+console.useLogger = function (value) {
+    if (arguments.length) UseLogger = !!value;
+
+    if (UseLogger) {
+        if (logger.useConsole()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+    }
+
+    return UseLogger;
+};
+
+//------------------------------------------------------------------------------
+console.log = function() {
+    if (logger.useConsole()) return;
+    logger.log.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.error = function() {
+    if (logger.useConsole()) return;
+    logger.error.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.warn = function() {
+    if (logger.useConsole()) return;
+    logger.warn.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.info = function() {
+    if (logger.useConsole()) return;
+    logger.info.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.debug = function() {
+    if (logger.useConsole()) return;
+    logger.debug.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.assert = function(expression) {
+    if (expression) return;
+
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
+    console.log("ASSERT: " + message);
+};
+
+//------------------------------------------------------------------------------
+console.clear = function() {};
+
+//------------------------------------------------------------------------------
+console.dir = function(object) {
+    console.log("%o", object);
+};
+
+//------------------------------------------------------------------------------
+console.dirxml = function(node) {
+    console.log(node.innerHTML);
+};
+
+//------------------------------------------------------------------------------
+console.trace = noop;
+
+//------------------------------------------------------------------------------
+console.group = console.log;
+
+//------------------------------------------------------------------------------
+console.groupCollapsed = console.log;
+
+//------------------------------------------------------------------------------
+console.groupEnd = noop;
+
+//------------------------------------------------------------------------------
+console.time = function(name) {
+    Timers[name] = new Date().valueOf();
+};
+
+//------------------------------------------------------------------------------
+console.timeEnd = function(name) {
+    var timeStart = Timers[name];
+    if (!timeStart) {
+        console.warn("unknown timer: " + name);
+        return;
+    }
+
+    var timeElapsed = new Date().valueOf() - timeStart;
+    console.log(name + ": " + timeElapsed + "ms");
+};
+
+//------------------------------------------------------------------------------
+console.timeStamp = noop;
+
+//------------------------------------------------------------------------------
+console.profile = noop;
+
+//------------------------------------------------------------------------------
+console.profileEnd = noop;
+
+//------------------------------------------------------------------------------
+console.count = noop;
+
+//------------------------------------------------------------------------------
+console.exception = console.log;
+
+//------------------------------------------------------------------------------
+console.table = function(data, columns) {
+    console.log("%o", data);
+};
+
+//------------------------------------------------------------------------------
+// return a new function that calls both functions passed as args
+//------------------------------------------------------------------------------
+function wrappedOrigCall(orgFunc, newFunc) {
+    return function() {
+        var args = [].slice.call(arguments);
+        try { orgFunc.apply(WinConsole, args); } catch (e) {}
+        try { newFunc.apply(console,    args); } catch (e) {}
+    };
+}
+
+//------------------------------------------------------------------------------
+// For every function that exists in the original console object, that
+// also exists in the new console object, wrap the new console method
+// with one that calls both
+//------------------------------------------------------------------------------
+for (var key in console) {
+    if (typeof WinConsole[key] == "function") {
+        console[key] = wrappedOrigCall(WinConsole[key], console[key]);
+    }
+}
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/logger.js
+define("cordova/plugin/ios/logger", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports;
+
+var exec    = require('cordova/exec');
+
+var UseConsole   = false;
+var UseLogger    = true;
+var Queued       = [];
+var DeviceReady  = false;
+var CurrentLevel;
+
+var originalConsole = console;
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+];
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {};
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i];
+    LevelsMap[level] = i;
+    logger[level]    = level;
+}
+
+CurrentLevel = LevelsMap.WARN;
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  E.g., the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] === null) {
+            throw new Error("invalid logging level: " + value);
+        }
+        CurrentLevel = LevelsMap[value];
+    }
+
+    return Levels[CurrentLevel];
+};
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value;
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined");
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function");
+        }
+
+        if (typeof console.useLogger == "function") {
+            if (console.useLogger()) {
+                throw new Error("console and logger are too intertwingly");
+            }
+        }
+    }
+
+    return UseConsole;
+};
+
+/**
+ * Getter/Setter for the useLogger functionality
+ *
+ * When useLogger is true, the logger will log via the
+ * native Logger plugin.
+ */
+logger.useLogger = function (value) {
+    // Enforce boolean
+    if (arguments.length) UseLogger = !!value;
+    return UseLogger;
+};
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments); };
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments); };
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments); };
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    args = [level].concat([].slice.call(args));
+    logger.logLevel.apply(logger, args);
+}
+
+// return the correct formatString for an object
+function formatStringForMessage(message) {
+    return (typeof message === "string") ? "" : "%o"; 
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 1);
+    var fmtString = formatStringForMessage(formatArgs[0]);
+    if (fmtString.length > 0){
+        formatArgs.unshift(fmtString); // add formatString
+    }
+
+    var message    = logger.format.apply(logger.format, formatArgs);
+
+    if (LevelsMap[level] === null) {
+        throw new Error("invalid logging level: " + level);
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return;
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message]);
+        return;
+    }
+
+    // Log using the native logger if that is enabled
+    if (UseLogger) {
+        exec(null, null, "Console", "logLevel", [level, message]);
+    }
+
+    // Log using the console if that is enabled
+    if (UseConsole) {
+        // make sure console is not using logger
+        if (console.useLogger()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+
+        // log to the console
+        switch (level) {
+            case logger.LOG:   originalConsole.log(message); break;
+            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
+            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
+            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
+            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
+        }
+    }
+};
+
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return;
+
+    DeviceReady = true;
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i];
+        logger.logLevel(messageArgs[0], messageArgs[1]);
+    }
+
+    Queued = null;
+};
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false);
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova_plugins.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova_plugins.js
new file mode 100644
index 0000000..79df2d5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/cordova_plugins.js
@@ -0,0 +1,339 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+  module.exports = [
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.iosFileSystem",
+      "file": "plugins/cordova-plugin-file/www/ios/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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/ios/CameraPopoverHandle.js",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "CameraPopoverHandle"
+      ]
+    },
+    {
+      "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-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ];
+  module.exports.metadata = {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  };
+});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui-iconfont.ttf b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui-iconfont.ttf
new file mode 100755
index 0000000..2c9d80e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui-iconfont.ttf
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui.css
new file mode 100644
index 0000000..c77e083
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/aui.css
@@ -0,0 +1,2731 @@
+/*

+ * =========================================================================

+ * APIClud - AUI UI 框架    流浪男  QQ:343757327  http://www.auicss.com

+ * Verson 2.1

+ * =========================================================================

+ */

+ /*初始化类*/

+@charset "UTF-8";

+html{

+	font-family: "Helvetica Neue", Helvetica, sans-serif;

+	font-size: 20px;

+}

+html,body {

+	-webkit-touch-callout:none;

+	-webkit-text-size-adjust:none;

+	-webkit-tap-highlight-color:rgba(0, 0, 0, 0);

+	-webkit-user-select:none;

+	width: 100%;

+}

+body {

+	line-height: 1.5;

+	font-size: 0.8rem;

+	color: #212121;

+	background-color: #f5f5f5;

+	outline: 0;

+}

+html,body,header,section,footer,div,ul,ol,li,img,a,span,em,del,legend,center,strong,var,fieldset,form,label,dl,dt,dd,cite,input,hr,time,mark,code,figcaption,figure,textarea,h1,h2,h3,h4,h5,h6,p{

+	margin:0;

+	border:0;

+	padding:0;

+	font-style:normal;

+}

+* {

+	-webkit-box-sizing: border-box;

+	      	box-sizing: border-box;

+	-webkit-user-select: none;

+	-webkit-tap-highlight-color: transparent;

+	outline: none;

+}

+@media only screen and (min-width: 400px) {

+	html {

+		font-size: 21.33333333px !important;

+	}

+}

+@media only screen and (min-width: 414px) {

+	html {

+		font-size: 21px !important;

+	}

+}

+@media only screen and (min-width: 480px) {

+	html {

+		font-size: 25.6px !important;

+	}

+}

+ul, li {

+	list-style: none;

+}

+p {

+	font-size: 0.7rem;

+	color: #757575;

+}

+a {

+	color: #0062cc;

+	text-decoration: none;

+	background-color: transparent;

+}

+textarea {

+	overflow: hidden;

+	resize: none;

+}

+button {

+	overflow: visible;

+}

+button,select {

+	text-transform: none;

+}

+button,input,select,textarea {

+	font: inherit;

+	color: inherit;

+}

+/*自动隐藏文字*/

+.aui-ellipsis-1 {

+	overflow: hidden;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+}

+.aui-ellipsis {

+	display: -webkit-box;

+	overflow: hidden;

+	text-overflow: ellipsis;

+	word-wrap: break-word;

+	word-break: break-all;

+	white-space: normal !important;

+	-webkit-line-clamp: 1;

+	-webkit-box-orient: vertical;

+}

+.aui-ellipsis-2 {

+	display: -webkit-box;

+	overflow: hidden;

+	text-overflow: ellipsis;

+	word-wrap: break-word;

+	word-break: break-all;

+	white-space: normal !important;

+	-webkit-line-clamp: 2;

+	-webkit-box-orient: vertical;

+}

+/*水平线*/

+.aui-hr {

+	width: 100%;

+	position: relative;

+	border-top: 1px solid #dddddd;

+	height: 1px;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-hr{

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+}

+/*内外边距类*/

+.aui-padded-0 {

+	padding: 0 !important;

+}

+.aui-padded-5 {

+	padding: 0.25rem !important;

+}

+.aui-padded-10 {

+	padding: 0.5rem !important;

+}

+.aui-padded-15 {

+	padding: 0.75rem !important;

+}

+.aui-padded-t-0 {

+	padding-top: 0 !important;

+}

+.aui-padded-t-5 {

+	padding-top: 0.25rem !important;

+}

+.aui-padded-t-10 {

+	padding-top: 0.5rem !important;

+}

+.aui-padded-t-15 {

+	padding-top: 0.75rem !important;

+}

+.aui-padded-b-0 {

+	padding-bottom: 0 !important;

+}

+.aui-padded-b-5 {

+	padding-bottom: 0.25rem !important;

+}

+.aui-padded-b-10 {

+	padding-bottom: 0.5rem !important;

+}

+.aui-padded-b-15 {

+	padding-bottom: 0.75rem !important;

+}

+.aui-padded-l-0 {

+	padding-left: 0 !important;

+}

+.aui-padded-l-5 {

+	padding-left: 0.25rem !important;

+}

+.aui-padded-l-10 {

+	padding-left: 0.5rem !important;

+}

+.aui-padded-l-15 {

+	padding-left: 0.75rem !important;

+}

+.aui-padded-r-0 {

+	padding-right: 0 !important;

+}

+.aui-padded-r-5 {

+	padding-right: 0.25rem !important;

+}

+.aui-padded-r-10 {

+	padding-right: 0.5rem !important;

+}

+.aui-padded-r-15 {

+	padding-right: 0.75rem !important;

+}

+.aui-margin-0 {

+	margin: 0 !important;

+}

+.aui-margin-5 {

+	margin: 0.25rem !important;

+}

+.aui-margin-10 {

+	margin: 0.5rem !important;

+}

+.aui-margin-15 {

+	margin: 0.75rem !important;

+}

+.aui-margin-t-0 {

+	margin-top: 0.25rem !important;

+}

+.aui-margin-t-5 {

+	margin-top: 0 !important;

+}

+.aui-margin-t-10 {

+	margin-top: 0.5rem !important;

+}

+.aui-margin-t-15 {

+	margin-top: 0.75rem !important;

+}

+.aui-margin-b-0 {

+	margin-bottom: 0 !important;

+}

+.aui-margin-b-5 {

+	margin-bottom: 0.25rem !important;

+}

+.aui-margin-b-10 {

+	margin-bottom: 0.5rem !important;

+}

+.aui-margin-b-15 {

+	margin-bottom: 0.75rem !important;

+}

+.aui-margin-l-0 {

+	margin-left: 0 !important;

+}

+.aui-margin-l-5 {

+	margin-left: 0.25rem !important;

+}

+.aui-margin-l-10 {

+	margin-left: 0.5rem !important;

+}

+.aui-margin-l-15 {

+	margin-left: 0.75rem !important;

+}

+.aui-margin-r-0 {

+	margin-right: 0 !important;

+}

+.aui-margin-r-5 {

+	margin-right: 0.25rem !important;

+}

+.aui-margin-r-10 {

+	margin-right: 0.5rem !important;

+}

+.aui-margin-r-15 {

+	margin-right: 0.75rem !important;

+}

+.aui-clearfix {

+	clear: both;

+}

+.aui-clearfix:before {

+	display: table;

+	content: " ";

+}

+.aui-clearfix:after {

+	clear: both;

+}

+/*文字对齐*/

+.aui-text-left {

+	text-align: left !important;

+}

+.aui-text-center {

+	text-align: center !important;

+}

+.aui-text-justify {

+	text-align: justify !important;

+}

+.aui-text-right {

+	text-align: right !important;

+}

+/*文字、背景颜色*/

+h1,h2,h3,h4,h5,h6 {

+	font-weight: 400;

+}

+h1 {

+	font-size: 1.2rem;

+}

+h2 {

+	font-size: 1rem;

+}

+h3 {

+	font-size: 0.8rem;

+}

+h4 {

+	font-size: 0.7rem;

+}

+h5 {

+	font-size: 0.7rem;

+	font-weight: normal;

+	color: #757575;

+}

+h6 {

+	font-size: 0.7rem;

+	font-weight: normal;

+	color: #757575;

+}

+h1 small,h2 small,h3 small,h4 small {

+	font-weight: normal;

+	line-height: 1;

+	color: #757575;

+}

+h5 small,h6 small {

+	font-weight: normal;

+	line-height: 1;

+	color: #757575;

+}

+h1 small,h2 small,h3 small {

+	font-size: 65%;

+}

+h4 small,h5 small,h6 small {

+	font-size: 75%;

+}

+img {

+	max-width: 100%;

+	display: block;

+}

+.aui-font-size-12 {

+	font-size: 0.6rem !important;

+}

+.aui-font-size-14 {

+	font-size: 0.7rem !important;

+}

+.aui-font-size-16 {

+	font-size: 0.8rem !important;

+}

+.aui-font-size-18 {

+	font-size: 0.9rem !important;

+}

+.aui-font-size-20 {

+	font-size: 1rem !important;

+}

+.aui-text-default {

+	color: #212121 !important;

+}

+.aui-text-white {

+	color: #ffffff !important;

+}

+.aui-text-primary {

+	color: #00bcd4 !important;

+}

+.aui-text-success {

+	color: #009688 !important;

+}

+.aui-text-info {

+	color: #03a9f4 !important;

+}

+.aui-text-warning {

+	color: #ffc107 !important;

+}

+.aui-text-danger {

+	color: #e51c23 !important;

+}

+.aui-text-pink {

+	color: #e91e63 !important;

+}

+.aui-text-purple {

+	color: #673ab7 !important;

+}

+.aui-text-indigo {

+	color: #3f51b5 !important;

+}

+.aui-text-green {

+	color: #7cba59 !important;

+}

+.aui-text-orange {

+	color: #e0620d !important;

+}

+.aui-bg-default {

+	background-color: #f5f5f5 !important;

+}

+.aui-bg-primary {

+	background-color: #00bcd4 !important;

+}

+.aui-bg-success {

+	background-color: #009688 !important;

+}

+.aui-bg-info {

+	background-color: #03a9f4 !important;

+}

+.aui-bg-warning {

+	background-color: #f1c40f !important;

+}

+.aui-bg-danger {

+	background-color: #e51c23 !important;

+}

+.aui-bg-pink {

+	background-color: #e91e63 !important;

+}

+.aui-bg-purple {

+	background-color: #673ab7 !important;

+}

+.aui-bg-indigo {

+	background-color: #3f51b5 !important;

+}

+.aui-bg-gray {

+	background-color: #8a8a8a !important;

+}

+

+/*警告、成功颜色*/

+.aui-warning,

+.aui-warning label,

+.aui-warning .aui-input,

+.aui-warning .aui-iconfont {

+	color: #e51c23 !important;

+}

+.aui-success,

+.aui-success label,

+.aui-success .aui-input,

+.aui-success .aui-iconfont {

+	color: #009688 !important;

+}

+/*对齐,显示,隐藏等*/

+.aui-pull-right {

+	float: right !important;

+}

+.aui-pull-left {

+	float: left !important;

+}

+.aui-hide {

+	display: none !important;

+}

+.aui-show {

+	display: block !important;

+}

+.aui-invisible {

+	visibility: hidden;

+}

+.aui-inline {

+	display: inline-block;

+	vertical-align: top;

+}

+.aui-mask {

+    position: fixed;

+    width: 100%;

+    height: 100%;

+    top: 0;

+    left: 0;

+    background: rgba(0, 0, 0, 0.3);

+    opacity: 0;

+    z-index: 8;

+    visibility: hidden;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+}

+.aui-mask.aui-mask-in {

+	visibility: visible;

+  	opacity: 1;

+}

+.aui-mask.aui-mask-out {

+	opacity: 0;

+}

+img.aui-img-round {

+	border-radius: 50%;

+}

+/*基本容器*/

+.aui-content {

+	-webkit-overflow-scrolling: touch;

+	overflow-x: hidden;

+	word-break: break-all;

+}

+.aui-content-padded {

+  	margin: 0.75rem;

+  	position: relative;

+  	word-break: break-all;

+  	-webkit-overflow-scrolling: touch;

+}

+/*栅格类*/

+.aui-row {

+	overflow: hidden;

+	margin: 0;

+}

+.aui-row-padded {

+	margin-left: -0.125rem;

+	margin-right: -0.125rem;

+}

+.aui-row-padded [class*=aui-col-xs-] {

+	padding: 0.125rem;

+}

+.aui-col-xs-1,.aui-col-xs-2,.aui-col-xs-3,.aui-col-xs-4,.aui-col-xs-5,.aui-col-xs-6,.aui-col-xs-7,.aui-col-xs-8,.aui-col-xs-9,.aui-col-xs-10,.aui-col-xs-11,.aui-col-5 {

+	position: relative;

+	float: left;

+}

+.aui-col-xs-12 {

+	width: 100%;

+	position: relative;

+}

+.aui-col-xs-11 {

+	width: 91.66666667%;

+}

+.aui-col-xs-10 {

+	width: 83.33333333%;

+}

+.aui-col-xs-9 {

+	width: 75%;

+}

+.aui-col-xs-8 {

+	width: 66.66666667%;

+}

+.aui-col-xs-7 {

+	width: 58.33333333%;

+}

+.aui-col-xs-6 {

+	width: 50%;

+}

+.aui-col-xs-5 {

+	width: 41.66666667%;

+}

+.aui-col-xs-4 {

+	width: 33.33333333%;

+}

+.aui-col-xs-3 {

+	width: 25%;

+}

+.aui-col-xs-2 {

+	width: 16.66666667%;

+}

+.aui-col-xs-1 {

+	width: 8.33333333%;

+}

+.aui-col-5 {

+	width: 20%;

+}

+/*标签*/

+.aui-label {

+	display: inline-block;

+	padding: 0.2em 0.25em;

+	font-size: 0.6rem;

+	line-height: 1;

+	color: #616161;

+    background-color: #dddddd;

+	text-align: center;

+	white-space: nowrap;

+	vertical-align: middle;

+	border-radius: 0.15em;

+	position: relative;

+}

+

+.aui-label-primary {

+	color: #ffffff;

+	background-color: #00bcd4;

+}

+.aui-label-success {

+	color: #ffffff;

+	background-color: #009688;

+}

+.aui-label-info {

+  color: #ffffff;

+  background-color: #03a9f4;

+}

+.aui-label-warning {

+	color: #ffffff;

+	background-color: #ffc107;

+}

+.aui-label-danger {

+	color: #ffffff;

+	background-color: #e51c23;

+}

+.aui-label-outlined {

+	background-color: transparent;

+	position: relative;

+}

+.aui-label-outlined:after {

+    -webkit-border-radius: 2px;

+    border-radius: 2px;

+    height: 200%;

+    content: '';

+    width: 200%;

+	border: 1px solid #d9d9d9;

+    position: absolute;

+    top: -1px;

+    left: -1px;

+    transform: scale(0.5);

+    -webkit-transform: scale(0.5);

+    transform-origin: 0 0;

+    -webkit-transform-origin: 0 0;

+    z-index: 1;

+}

+.aui-label-outlined.aui-label-primary,

+.aui-label-outlined.aui-label-primary:after {

+	color: #00bcd4;

+	border-color: #00bcd4;

+}

+.aui-label-outlined.aui-label-success,

+.aui-label-outlined.aui-label-success:after {

+	color: #009688;

+	border-color: #009688;

+}

+.aui-label-outlined.aui-label-info,

+.aui-label-outlined.aui-label-info:after {

+  	color: #03a9f4;

+  	border-color: #03a9f4;

+}

+.aui-label-outlined.aui-label-warning,

+.aui-label-outlined.aui-label-warning:after {

+	color: #ffc107;

+	border-color: #ffc107;

+}

+.aui-label-outlined.aui-label-danger,

+.aui-label-outlined.aui-label-danger:after {

+	color: #e51c23;

+	border-color: #e51c23;

+}

+.aui-label .aui-iconfont {

+	font-size: 0.6rem;

+}

+/*角标*/

+.aui-badge {

+	display: inline-block;

+	width: auto;

+	text-align: center;

+	min-width: 0.8rem;

+	height: 0.8rem;

+    line-height: 0.8rem;

+    padding: 0 0.2rem;

+    font-size: 0.6rem;

+    color: #ffffff;

+    background-color: #ff2600;

+    border-radius: 0.4rem;

+    position: absolute;

+    top: 0.2rem;

+    left: 60%;

+    z-index: 99;

+}

+.aui-dot {

+	display: inline-block;

+    width: 0.4rem;

+    height: 0.4rem;

+    background: #ff2600;

+    border-radius: 0.5rem;

+    position: absolute;

+    top: 0.3rem;

+    right: 20%;

+    z-index: 99;

+}

+/*按钮样式*/

+button, .aui-btn {

+	position: relative;

+	display: inline-block;

+	font-size: 0.7rem;

+	font-weight: 400;

+	font-family: inherit;

+	text-decoration: none;

+	text-align: center;

+	margin: 0;

+	background: #dddddd;

+	padding: 0 0.6rem;

+	height: 1.5rem;

+	line-height: 1.5rem;

+	border-radius: 0.2rem;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+	vertical-align: middle;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	-webkit-user-select: none;

+	      	user-select: none;

+}

+.aui-btn:active {

+	color: #212121;

+	background-color: #bdbdbd;

+}

+.aui-btn-primary {

+	color: #ffffff;

+	background-color: #00bcd4;

+}

+.aui-btn-primary.aui-active, .aui-btn-primary:active {

+	color: #ffffff;

+	background-color: #00acc1;

+}

+.aui-btn-success {

+	color: #ffffff;

+	background-color: #009688;

+}

+.aui-btn-success.aui-active, .aui-btn-success:active {

+	color: #fff;

+	background-color: #00897b;

+}

+.aui-btn-info {

+	color: #ffffff !important;

+	background-color: #03a9f4 !important;

+}

+.aui-btn-info.aui-active, .aui-btn-info:active {

+	color: #fff !important;

+	background-color: #067cb1 !important;

+}

+.aui-btn-warning {

+	color: #ffffff !important;

+	background-color: #ffc107 !important;

+}

+.aui-btn-warning.aui-active, .aui-btn-warning:active {

+	color: #ffffff !important;

+	background-color: #ffb300 !important;

+}

+.aui-btn-danger {

+	color: #ffffff !important;

+	background-color: #e51c23 !important;

+}

+.aui-btn-danger.aui-active, .aui-btn-danger:active {

+	color: #ffffff !important;

+	background-color: #dd191b !important;

+}

+.aui-btn-orangle {

+	color: #ffffff !important;

+	background-color: #efb336 !important;

+}

+.aui-btn-orangle.aui-active, .aui-btn-orangle:active {

+	color: #fff !important;

+	background-color: #e98f36 !important;

+}

+.aui-btn-blue {

+	color: #ffffff !important;

+	background-color: #17abe3 !important;

+}

+.aui-btn-blue.aui-active, .aui-btn-blue:active {

+	color: #fff !important;

+	background-color: #1195db !important;

+}

+.aui-btn-green {

+	color: #ffffff !important;

+	background-color: #36ab60 !important;

+}

+.aui-btn-green.aui-active, .aui-btn-green:active {

+	color: #fff !important;

+	background-color: #36ab60 !important;

+}

+.aui-btn-block {

+	display: block;

+	width: 100%;

+	height: 2.5rem;

+	line-height: 2.55rem;

+	margin-bottom: 0;

+	font-size: 0.9rem;

+}

+.aui-btn-block.aui-btn-sm {

+	font-size: 0.7rem;

+	height: 1.8rem;

+	line-height: 1.85rem;

+}

+.aui-btn .aui-iconfont, .aui-btn-block .aui-iconfont {

+	margin-right: 0.3rem;

+}

+.aui-btn .aui-badge, .aui-btn-block .aui-badge {

+	margin-left: 0.3rem;

+}

+.aui-btn-outlined {

+	background: transparent !important;

+	border: 1px solid #bdbdbd;

+}

+.aui-btn-outlined:active {

+	background: transparent !important;

+}

+.aui-btn-default.aui-btn-outlined {

+	color: #bdc3c7 !important;

+	border: 1px solid #dcdcdc !important;

+}

+.aui-btn-primary.aui-btn-outlined {

+	color: #00bcd4 !important;

+	border: 1px solid #00bcd4 !important;

+}

+.aui-btn-success.aui-btn-outlined {

+	color: #009688 !important;

+	border: 1px solid #009688 !important;

+}

+.aui-btn-info.aui-btn-outlined {

+	color: #03a9f4 !important;

+	border: 1px solid #03a9f4 !important;

+}

+.aui-btn-warning.aui-btn-outlined {

+	color: #ffc107 !important;

+	border: 1px solid #ffc107 !important;

+}

+.aui-btn-danger.aui-btn-outlined {

+	color: #e51c23 !important;

+	border: 1px solid #e51c23 !important;

+}

+/*

+*表单类\输入框\radio\checkbox

+**/

+.aui-input,

+input[type="text"],

+input[type="password"],

+input[type="search"],

+input[type="email"],

+input[type="tel"],

+input[type="url"],

+input[type="date"],

+input[type="datetime-local"],

+input[type="time"],

+input[type="number"],

+select,

+textarea {

+    border: none;

+    background-color: transparent;

+    border-radius: 0;

+    box-shadow: none;

+    display: block;

+    padding: 0;

+    margin: 0;

+    width: 100%;

+    height: 2.2rem;

+    line-height: normal;

+    color: #424242;

+    font-size: 0.8rem;

+    font-family: inherit;

+    box-sizing: border-box;

+    -webkit-user-select: text;

+            user-select: text;

+    -webkit-appearance: none;

+            appearance: none;

+}

+input[type="search"]::-webkit-search-cancel-button {

+	display: none;

+}

+.aui-scroll-x {

+	position: relative;

+	overflow-y: auto;

+	-webkit-overflow-scrolling: touch;

+}

+.aui-scroll-y {

+	position: relative;

+	width: 100%;

+	overflow-x: auto;

+	-webkit-overflow-scrolling: touch;

+}

+::-webkit-scrollbar{

+	width:0px;

+}

+/*列表*/

+.aui-list {

+    position: relative;

+    font-size: 0.8rem;

+    background-color: #ffffff;

+    border-top: 1px solid #dddddd;

+}

+.aui-list .aui-content {

+	overflow: hidden;

+}

+.aui-list.aui-list-noborder,

+.aui-list.aui-list-noborder {

+    border-top: none;

+}

+.aui-list .aui-list-header {

+    background-color: #dddddd;

+    color: #212121;

+    position: relative;

+    font-size: 0.6rem;

+    padding: 0.4rem 0.75rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item {

+    list-style: none;

+    margin: 0;

+    padding: 0;

+    padding-left: 0.75rem;

+    color: #212121;

+    border-bottom: 1px solid #f2f2f2;

+    position: relative;

+    min-height: 2.2rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+}

+.aui-list.aui-list-noborder .aui-list-item:last-child {

+    border-bottom: 0;

+}

+.aui-list .aui-list-item-inner {

+    position: relative;

+    min-height: 2.2rem;

+	padding-right: 0.75rem;

+    width: 100%;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-flex: 1;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+			justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+			align-items: center;

+}

+

+.aui-list .aui-list-item:active {

+    background-color: #f5f5f5;

+}

+.aui-list .aui-list-item-text {

+    font-size: 0.7rem;

+    color: #757575;

+    position: relative;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+            justify-content: space-between;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item-title {

+    font-size: 0.8rem;

+    position: relative;

+    max-width: 100%;

+    color: #212121;

+}

+.aui-list .aui-list-item-right,

+.aui-list-item-title-row em {

+	max-width: 50%;

+	position: relative;

+    font-size: 0.6rem;

+    color: #757575;

+    margin-left: 0.25rem;

+}

+.aui-list .aui-list-item-inner p {

+    overflow: hidden;

+}

+.aui-list .aui-list-media-list {

+    -webkit-box-orient: vertical;

+    -webkit-box-direction: normal;

+    -webkit-flex-direction: column;

+            flex-direction: column;

+}

+.aui-media-list-item-inner {

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+}

+.aui-media-list .aui-list-item {

+	display: block;

+}

+.aui-media-list .aui-list-item-inner {

+	display: block;

+	padding-top: 0.5rem;

+    padding-bottom: 0.5rem;

+}

+.aui-media-list-item-inner + .aui-info {

+	margin-right: 0.75rem;

+}

+.aui-list .aui-list-item-media {

+	width: 4.5rem;

+	position: relative;

+    padding: 0.5rem 0;

+    padding-right: 0.75rem;

+    display: inherit;

+    -webkit-flex-shrink: 0;

+    		flex-shrink: 0;

+    -webkit-flex-wrap: nowrap;

+    		flex-wrap: nowrap;

+    -webkit-box-align: center;

+    -webkit-align-items: flex-start;

+            align-items: flex-start;

+}

+.aui-list .aui-list-item-media img {

+	width: 100%;

+    display: block;

+}

+.aui-list .aui-list-item-media-list {

+	margin-top: 0.25rem;

+	padding-right: 0;

+	display: block;

+}

+.aui-list [class*=aui-col-xs-] img{

+    max-width: 100%;

+    width: 100%;

+    display: block;

+}

+.aui-list-item-middle .aui-list-item-inner:after {

+	display: block;

+}

+.aui-list .aui-list-item-middle > .aui-list-item-media,

+.aui-list .aui-list-item-middle > .aui-list-item-inner,

+.aui-list .aui-list-item-middle > * {

+    -webkit-box-align: center;

+    		box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-list .aui-list-item-center > .aui-list-item-media,

+.aui-list .aui-list-item-center > .aui-list-item-inner,

+.aui-list .aui-list-item-center {

+    -webkit-box-pack: center;

+    -webkit-justify-content: center;

+        	justify-content: center;

+}

+.aui-list .aui-list-item i.aui-iconfont {

+    -webkit-align-self: center;

+            align-self: center;

+    font-size: 0.8rem;

+}

+.aui-list-item-inner.aui-list-item-arrow {

+    overflow: hidden;

+    padding-right: 1.5rem;

+}

+.aui-list-item-arrow:before {

+    content: '';

+    width: 0.4rem;

+    height: 0.4rem;

+    position: absolute;

+    top: 50%;

+    right: 0.75rem;

+    margin-top: -0.2rem;

+    background: transparent;

+    border: 1px solid #dddddd;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-135deg);

+            transform: rotate(-135deg);

+}

+.aui-list-item.aui-list-item-arrow {

+    padding-right: 0.75rem;

+}

+.aui-list label {

+    line-height: 1.3rem;

+}

+.aui-list.aui-form-list .aui-list-item:active {

+	background-color: #ffffff;

+}

+.aui-list.aui-form-list .aui-list-item-inner {

+	-webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+	padding: 0;

+}

+.aui-list .aui-list-item-label,

+.aui-list .aui-list-item-label-icon {

+	color: #212121;

+    width: 35%;

+    min-width: 1.5rem;

+    margin: 0;

+    padding: 0;

+    padding-right: 0.25rem;

+    line-height: 2.2rem;

+    position: relative;

+    overflow: hidden;

+    white-space: nowrap;

+    max-width: 100%;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-list .aui-list-item-label-icon {

+    width: auto;

+    padding-right: 0.75rem;

+}

+.aui-list .aui-list-item-input {

+    width: 100%;

+    padding: 0;

+    padding-right: 0.75rem;

+    -webkit-box-flex: 1;

+            box-flex: 1;

+    -webkit-flex-shrink: 1;

+            flex-shrink: 1;

+}

+.aui-list.aui-select-list .aui-list-item:active {

+	background-color: #ffffff;

+}

+.aui-list.aui-select-list .aui-list-item-inner {

+    display: block;

+    padding-top: 0.5rem;

+    padding-bottom: 0.5rem;

+    -webkit-align-self: stretch;

+    		align-self: stretch;

+}

+.aui-list.aui-select-list .aui-list-item-label {

+	width: auto;

+	min-width: 2.2rem;

+    padding: 0.5rem 0;

+    padding-right: 0.75rem;

+}

+.aui-list.aui-form-list .aui-list-item-btn {

+	padding: 0.75rem 0.75rem 0.75rem 0;

+}

+.aui-list textarea {

+    overflow: auto;

+    margin: 0.5rem 0;

+    height: 3rem;

+    line-height: 1rem;

+    resize: none;

+}

+.aui-list .aui-list-item-right .aui-badge,

+.aui-list .aui-list-item-right .aui-dot {

+	display: inherit;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-list {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-list .aui-list-item {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+

+	.aui-list.aui-list-in .aui-list-item {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: 0.75rem bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-list.aui-list-in .aui-list-item:last-child {

+		background-position: bottom;

+	}

+	.aui-list.aui-list-noborder,

+	.aui-list.aui-list-noborder .aui-list-item:last-child {

+		border: none;

+        background-size: 100% 0;

+        background-image: none;

+	}

+}

+/*tab切换类*/

+.aui-tab {

+	position: relative;

+    background-color: #ffffff;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-flex-wrap: nowrap;

+            flex-wrap: nowrap;

+    -webkit-align-self: center;

+            align-self: center;

+}

+.aui-tab-item {

+    width: 100%;

+    height: 2.2rem;

+    line-height: 2.2rem;

+    position: relative;

+    font-size: 0.7rem;

+    text-align: center;

+    color: #212121;

+    margin-left: -1px;

+    -webkit-box-flex: 1;

+            box-flex: 1;

+}

+.aui-tab-item.aui-active {

+    color: #03a9f4;

+    border-bottom: 2px solid #03a9f4;

+}

+/*卡片列表布局*/

+.aui-card-list {

+	position: relative;

+    margin-bottom: 0.35rem;

+    background: #ffffff;

+}

+.aui-card-list-header,

+.aui-card-list-footer {

+	position: relative;

+	min-height: 2.2rem;

+    padding: 0.5rem 0.75rem;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-card-list-header {

+	font-size: 0.8rem;

+	color: #212121;

+}

+.aui-card-list-header.aui-card-list-user {

+	display: block;

+}

+.aui-card-list-user-avatar {

+	width: 2rem;

+	float: left;

+	margin-right: 0.5rem;

+}

+.aui-card-list-user-avatar img {

+	width: 100%;

+	display: block;

+}

+.aui-card-list-user-name {

+	color: #212121;

+	position: relative;

+	font-size: 0.7rem;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-card-list-user-name > *,

+.aui-card-list-user-name small {

+	position: relative;

+}

+.aui-card-list-user-name small {

+	color: #757575;

+}

+.aui-card-list-user-info {

+	color: #757575;

+	font-size: 0.6rem;

+}

+.aui-card-list-content {

+	position: relative;

+}

+.aui-card-list-content-padded {

+	position: relative;

+	padding: 0.5rem 0.75rem;

+}

+.aui-card-list-content,

+.aui-card-list-content-padded {

+	word-break: break-all;

+	font-size: 0.7rem;

+	color: #212121;

+}

+.aui-card-list-content img,

+.aui-card-list-content-padded img {

+	width: 100%;

+	display: block;

+}

+.aui-card-list-footer {

+	font-size: 0.7rem;

+	color: #757575;

+}

+.aui-card-list-footer > * {

+	position: relative;

+}

+.aui-card-list-footer.aui-text-center {

+	display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+	-webkit-box-pack: center;

+    box-pack: center;

+    -webkit-justify-content: center;

+    justify-content: center;

+}

+.aui-card-list-footer .aui-iconfont {

+	font-size: 0.9rem;

+}

+/*宫格布局*/

+.aui-grid {

+	width: 100%;

+	background-color: #ffffff;

+	display: table;

+	table-layout: fixed;

+}

+.aui-grid [class*=aui-col-] {

+	display: table-cell;

+	position: relative;

+    text-align: center;

+    vertical-align: middle;

+    padding: 0.6rem 0;

+}

+.aui-grid [class*=aui-col-xs-]:active {

+	background-color: #f5f5f5;

+}

+.aui-grid [class*=top-btn]:active {

+	background-color: #048cca;

+}

+.aui-grid .aui-iconfont {

+	position: relative;

+    z-index: 20;

+    top: 0;

+    height: 1.4rem;

+    font-size: 1.4rem;

+    line-height: 1.4rem;

+}

+.aui-grid .aui-grid-label {

+	display: block;

+    font-size: 0.7rem;

+    position: relative;

+    margin-top: 0.25rem;

+}

+.aui-grid .aui-badge {

+	position: absolute;

+    top: 0.5rem;

+    left: 60%;

+    z-index: 99;

+}

+.aui-grid .aui-dot {

+	position: absolute;

+    top: 0.5rem;

+    right: 20%;

+    z-index: 99;

+}

+/*单选、多选、开关*/

+.aui-radio,

+.aui-checkbox {

+    width: 1.2rem;

+    height: 1.2rem;

+    background-color: #ffffff;

+    border: solid 1px #dddddd;

+    -webkit-border-radius: 0.6rem;

+    border-radius: 0.6rem;

+    font-size: 0.8rem;

+    margin: 0;

+    padding: 0;

+    position: relative;

+    display: inline-block;

+    vertical-align: top;

+    cursor: default;

+    -webkit-appearance: none;

+    -webkit-user-select: none;

+            user-select: none;

+    -webkit-transition: background-color ease 0.1s;

+            transition: background-color ease 0.1s;

+}

+.aui-checkbox {

+    border-radius: 0.1rem;

+}

+.aui-radio:checked,

+.aui-radio.aui-checked,

+.aui-checkbox:checked,

+.aui-checkbox.aui-checked {

+    background-color: #03a9f4;

+    border: solid 1px #03a9f4;

+    text-align: center;

+    background-clip: padding-box;

+}

+.aui-radio:checked:before,

+.aui-radio.aui-checked:before,

+.aui-checkbox:checked:before,

+.aui-checkbox.aui-checked:before,

+.aui-radio:checked:after,

+.aui-radio.aui-checked:after,

+.aui-checkbox:checked:after,

+.aui-checkbox.aui-checked:after {

+    content: '';

+    width: 0.5rem;

+    height: 0.3rem;

+    position: absolute;

+    top: 50%;

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.25rem;

+    background: transparent;

+    border: 1px solid #ffffff;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+}

+.aui-radio:disabled,

+.aui-radio.aui-disabled,

+.aui-checkbox:disabled,

+.aui-checkbox.aui-disabled {

+    background-color: #dddddd;

+    border: solid 1px #dddddd;

+}

+.aui-radio:disabled:before,

+.aui-radio.aui-disabled:before,

+.aui-radio:disabled:after,

+.aui-radio.aui-disabled:after,

+.aui-checkbox:disabled:before,

+.aui-checkbox.aui-disabled:before,

+.aui-checkbox:disabled:after,

+.aui-checkbox.aui-disabled:after {

+    content: '';

+    width: 0.5rem;

+    height: 0.3rem;

+    position: absolute;

+    top: 50%;

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.25rem;

+    background: transparent;

+    border: 1px solid #ffffff;

+    border-top: none;

+    border-right: none;

+    z-index: 2;

+    -webkit-border-radius: 0;

+            border-radius: 0;

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+}

+.aui-switch {

+    width: 2.3rem;

+    height: 1.2rem;

+    position: relative;

+    vertical-align: top;

+    border: 1px solid #dddddd;

+    background-color: #dddddd;

+    border-radius: 0.6rem;

+    background-clip: content-box;

+    display: inline-block;

+    outline: none;

+    -webkit-appearance: none;

+            appearance: none;

+    -webkit-user-select: none;

+            user-select: none;

+    -webkit-box-sizing: border-box;

+            box-sizing: border-box;

+    -webkit-background-clip: padding-box;

+            background-clip: padding-box;

+    -webkit-transition: all 0.2s linear;

+            transition: all 0.2s linear;

+}

+.aui-switch:before {

+    width: 1.1rem;

+    height: 1.1rem;

+    position: absolute;

+    top: 0;

+    left: 0;

+    border-radius: 0.6rem;

+    background-color: #fff;

+    content: '';

+    -webkit-transition: left 0.2s;

+            transition: left 0.2s;

+}

+.aui-switch:checked {

+    border-color: #03a9f4;

+    background-color: #03a9f4;

+}

+.aui-switch:checked:before {

+    left: 1.1rem;

+}

+/*导航栏*/

+.aui-bar {

+	position: relative;

+	top: 0;

+	right: 0;

+	left: 0;

+	z-index: 10;

+	width: 100%;

+	min-height: 2.25rem;

+	font-size: 0.9rem;

+	text-align: center;

+	display: table;

+}

+.aui-bar-nav {

+	top: 0;

+	line-height: 2.25rem;

+	background-color: #03a9f4;

+	color: #ffffff;

+}

+.aui-title a {

+	color: inherit;

+}

+.aui-bar-nav .aui-title {

+	min-height: 2.25rem;

+	position: absolute;

+	margin: 0;

+	text-align: center;

+	white-space: nowrap;

+	right: 2rem;

+	left: 2rem;

+	width: auto;

+	overflow: hidden;

+	/*text-overflow: ellipsis;*/

+	z-index: 2;

+}

+.aui-bar-nav a {

+	color: #ffffff;

+}

+.aui-bar-nav .aui-iconfont {

+	position: relative;

+	z-index: 20;

+	font-size: 0.9rem;

+	color: #ffffff;

+	font-weight: 400;

+	line-height: 2.25rem;

+}

+.aui-bar-nav .aui-pull-left {

+	padding: 0 0.5rem;

+	font-size: 0.8rem;

+	font-weight: 400;

+	z-index: 2;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-bar-nav .aui-pull-right {

+	padding: 0 0.5rem;

+	font-size: 0.8rem;

+	font-weight: 400;

+	z-index: 2;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-align-items: center;

+            align-items: center;

+}

+.aui-bar-nav .aui-btn {

+	position: relative;

+	z-index: 20;

+	height: 2.25rem;

+	line-height: 2.25rem;

+	padding-top: 0;

+	padding-bottom: 0;

+	margin: 0;

+	border-radius: 0.1rem;

+	border-width: 0;

+	background: transparent !important;

+}

+.aui-bar-nav .aui-btn.aui-btn-outlined {

+	position: relative;

+	padding: 0 0.15rem;

+	margin: 0.5rem;

+	height: 1.25rem;

+	line-height: 1.25rem;

+	border-width: 1px;

+	background: transparent !important;

+	border-color: #ffffff;

+}

+.aui-bar-nav .aui-btn:active {

+	background: none;

+}

+.aui-bar-nav .aui-btn .aui-iconfont {

+	font-size: 0.9rem;

+	line-height: 1.25rem;

+	padding: 0;

+	margin: 0;

+	color: #ffffff;

+}

+.aui-bar-light {

+	color: #03a9f4;

+	background-color: #ffffff;

+	border-bottom: 1px solid #dddddd;

+}

+.aui-bar-nav.aui-bar-light .aui-iconfont {

+	color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-btn-outlined {

+	border-color: #03a9f4;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-bar.aui-bar-light {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+}

+/*底部切换栏*/

+.aui-bar-tab {

+	position: fixed;

+	top: auto;

+	bottom: 0;

+	table-layout: fixed;

+	background-color: #ffffff;

+	color: #757575;

+}

+.aui-bar-tab .aui-bar-tab-item {

+	display: table-cell;

+	position: relative;

+    width: 1%;

+    height: 2.5rem;

+    text-align: center;

+    vertical-align: middle;

+}

+.aui-bar-tab .aui-active {

+	color: #03a9f4;

+}

+.aui-bar-tab .aui-bar-tab-item .aui-iconfont {

+	position: relative;

+    z-index: 20;

+    top: 0.1rem;

+    height: 1.2rem;

+    font-size: 1rem;

+    line-height: 1rem;

+}

+.aui-bar-tab .aui-bar-tab-label {

+	display: block;

+    font-size: 0.6rem;

+    position: relative;

+}

+.aui-bar-tab .aui-badge {

+    position: absolute;

+    top: 0.1rem;

+    left: 55%;

+    z-index: 99;

+}

+.aui-bar-tab .aui-dot {

+    position: absolute;

+    top: 0.1rem;

+    right: 30%;

+    z-index: 99;

+}

+/*按钮工具栏*/

+.aui-bar-btn {

+	position: relative;

+    font-size: 0.7rem;

+    display: table;

+    white-space: nowrap;

+    margin: 0 auto;

+    padding: 0;

+    border: none;

+    width: 100%;

+    min-height: 1.8rem;

+}

+.aui-bar-btn-item {

+    display: table-cell;

+    position: relative;

+    width: 1%;

+    line-height: 1.6rem;

+    text-align: center;

+    vertical-align: middle;

+    border-radius: 0;

+    position: relative;

+    border-width: 1px;

+    border-style: solid;

+    border-color: #03a9f4;

+    border-left-width: 0;

+}

+.aui-bar-btn .aui-input,

+.aui-bar-btn input,

+.aui-bar-btn select {

+	padding-left: 0.25rem;

+	padding-right: 0.25rem;

+    height: 1.8rem;

+}

+.aui-bar-btn-sm {

+    min-height: 1.3rem;

+}

+.aui-bar-btn.aui-bar-btn-sm  .aui-input,

+.aui-bar-btn.aui-bar-btn-sm  input,

+.aui-bar-btn.aui-bar-btn-sm  select {

+    height: 1.2rem;

+}

+.aui-bar-btn-sm .aui-bar-btn-item {

+    line-height: 1.3rem;

+    font-size: 0.6rem;

+}

+.aui-bar-btn-item.aui-active {

+    background-color: #03a9f4;

+    color: #ffffff;

+}

+.aui-bar-btn-item:first-child {

+    border-left-width: 1px;

+    border-top-left-radius: 0.2rem;

+    border-bottom-left-radius: 0.2rem;

+}

+.aui-bar-btn-item:last-child {

+    border-top-right-radius: 0.2rem;

+    border-bottom-right-radius: 0.2rem;

+    border-left: 0px;

+}

+.aui-bar-btn.aui-bar-btn-full .aui-bar-btn-item:first-child {

+    border-left-width: 0;

+    border-top-left-radius: 0;

+    border-bottom-left-radius: 0;

+}

+.aui-bar-btn.aui-bar-btn-full .aui-bar-btn-item:last-child {

+    border-right-width: 0;

+    border-top-right-radius: 0;

+    border-bottom-right-radius: 0;

+}

+.aui-bar-btn.aui-bar-btn-round .aui-bar-btn-item:first-child {

+    border-top-left-radius: 1.5rem;

+    border-bottom-left-radius: 1.5rem;

+}

+.aui-bar-btn.aui-bar-btn-round .aui-bar-btn-item:last-child {

+    border-top-right-radius: 1.5rem;

+    border-bottom-right-radius: 1.5rem;

+}

+.aui-bar-nav .aui-bar-btn {

+	margin-top: 0.45rem;

+	margin-bottom: 0.4rem;

+    min-height: 1.3rem;

+}

+.aui-bar-nav .aui-bar-btn-item {

+    line-height: 1.3rem;

+    border-color: #ffffff;

+}

+.aui-bar-nav .aui-bar-btn-item.aui-active {

+    background-color: #ffffff;

+    color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-bar-btn-item {

+    border-color: #03a9f4;

+}

+.aui-bar-nav.aui-bar-light .aui-bar-btn-item.aui-active {

+    background-color: #03a9f4;

+    color: #ffffff;

+}

+.aui-bar-nav > .aui-bar-btn {

+	width: 50%;

+}

+.aui-info {

+	position: relative;

+    padding: 0.5rem 0;

+    font-size: 0.7rem;

+    color: #757575;

+    background-color: transparent;

+    -webkit-box-sizing: border-box;

+    		box-sizing: border-box;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+    		justify-content: space-between;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+

+}

+.aui-info-item {

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-align: center;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-info-item > *,

+.aui-info > * {

+	display: inherit;

+	position: relative;

+}

+/*进度条*/

+.aui-progress {

+	width: 100%;

+	height: 1rem;

+	border-radius: 0.2rem;

+	overflow: hidden;

+	background-color: #f0f0f0;

+}

+.aui-progress-bar {

+	float: left;

+	width: 0;

+	height: 100%;

+	font-size: 0.6rem;

+	line-height: 1rem;

+	color: #ffffff;

+	text-align: center;

+	background-color: #03a9f4;

+}

+.aui-progress.sm,

+.aui-progress-sm {

+	height: 0.5rem;

+}

+.aui-progress.sm,

+.aui-progress-sm,

+.aui-progress.sm .aui-progress-bar,

+.aui-progress-sm .aui-progress-bar {

+	border-radius: 1px;

+}

+.aui-progress.xs,

+.aui-progress-xs {

+	height: 0.35rem;

+}

+.aui-progress.xs,

+.aui-progress-xs,

+.aui-progress.xs .progress-bar,

+.aui-progress-xs .progress-bar {

+	border-radius: 1px;

+}

+.aui-progress.xxs,

+.aui-progress-xxs {

+	height: 0.15rem;

+}

+.aui-progress.xxs,

+.aui-progress-xxs,

+.aui-progress.xxs .progress-bar,

+.aui-progress-xxs .progress-bar {

+	border-radius: 1px;

+}

+/*滑块*/

+.aui-range {

+    position: relative;

+    display: inline-block;

+}

+.aui-range input[type='range']{

+    height: 0.2rem;

+    border: 0;

+    border-radius: 2px;

+    background-color: #f0f0f0;

+    position: relative;

+    -webkit-appearance: none !important;

+}

+.aui-range input[type='range']::-webkit-slider-thumb {

+    width: 1.2rem;

+    height: 1.2rem;

+    border-radius: 50%;

+    border-color: #03a9f4;

+    background-color: #03a9f4;

+    -webkit-appearance: none !important;

+}

+.aui-range .aui-range-tip {

+    font-size: 1rem;

+    position: absolute;

+    z-index: 999;

+    top: -1.5rem;

+    width: 2.4rem;

+    height: 1.5rem;

+    line-height: 1.5rem;

+    text-align: center;

+    color: #666666;

+    border: 1px solid #dddddd;

+    border-radius: 0.3rem;

+    background-color: #ffffff;

+}

+.aui-input-row .aui-range input[type='range'] {

+	width: 90%;

+	margin-left: 5%;

+}

+/*搜索条*/

+.aui-searchbar {

+    display: -webkit-box;

+    -webkit-box-pack: center;

+    -webkit-box-align: center;

+    height: 2.2rem;

+    overflow: hidden;

+    width: 100%;

+    background-color: #ebeced;

+    color: #9e9e9e;

+    -webkit-backface-visibility: hidden;

+  			backface-visibility: hidden;

+}

+.aui-searchbar.focus {

+    -webkit-box-pack: start;

+}

+.aui-searchbar-input {

+    margin: 0 0.5rem;

+	background-color: #ffffff;

+    border-radius: 0.25rem;

+    height: 1.4rem;

+    line-height: 1.4rem;

+    font-size: 0.7rem;

+    position: relative;

+    padding-left: 0.5rem;

+    display: -webkit-box;

+    -webkit-box-flex: 1;

+}

+.aui-searchbar form {

+	width: 90%;

+}

+.aui-searchbar-input input {

+    color: #666666;

+    width: 80%;

+    padding: 0;

+    margin: 0;

+    height: 1.4rem;

+    line-height: normal;

+    border: 0;

+    -webkit-appearance: none;

+    font-size: 0.7rem;

+}

+.aui-searchbar input::-webkit-input-placeholder {

+	color: #ccc;

+}

+.aui-searchbar .aui-iconfont {

+    line-height: 1.4rem;

+    margin-right: 0.25rem;

+    color: #9e9e9e !important;

+}

+.aui-searchbar .aui-searchbar-btn {

+	font-size: 0.7rem;

+	color: #666666;

+	margin-right: -2.2rem;

+	width: 2.2rem;

+	height: 1.4rem;

+	padding-right: 0.5rem;

+	line-height: 1.4rem;

+	text-align: center;

+	-webkit-transition: all .3s;

+	      	transition: all .3s;

+}

+.aui-searchbar-clear-btn {

+	position: absolute;

+	right: 5px;

+	top: 3px;

+	width: 1.1rem;

+	height: 1.1rem;

+	background: #eeeeee;

+	border-radius: 50%;

+	line-height: 0.6rem;

+	text-align: center;

+	display: none;

+}

+.aui-searchbar-clear-btn .aui-iconfont {

+	font-size: 0.6rem;

+	margin: 0 auto;

+	position: relative;

+	top: -2px;

+}

+.aui-searchbar .aui-searchbar-btn .aui-iconfont {

+	color: #666666;

+}

+/*信息提示条*/

+.aui-tips {

+    padding: 0 0.75rem;

+    width: 100%;

+    z-index: 99;

+    height: 1.9rem;

+    line-height: 1.9rem;

+   	position: relative;

+    background-color: rgba(0,0,0,.6);

+    color: #ffffff;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: justify;

+    -webkit-justify-content: space-between;

+            justify-content: space-between;

+    -webkit-align-items: center;

+    		align-items: center;

+}

+.aui-tips .aui-tips-title {

+	padding: 0 0.5rem;

+	font-size: 0.7rem;

+    position: relative;

+    max-width: 100%;

+}

+/*toast*/

+.aui-toast {

+	background: rgba(0, 0, 0, 0.7);

+	text-align: center;

+	border-radius: 0.25rem;

+	color: #ffffff;

+	position: fixed;

+	z-index: 300;

+	top: 45%;

+	left: 50%;

+	width: 7.5em;

+	min-height: 6em;

+	margin-left: -3.75em;

+	margin-top: -4rem;

+	display: none;

+}

+.aui-toast .aui-iconfont {

+	margin-top: 0.2rem;

+	display: block;

+	font-size: 2.6rem;

+}

+.aui-toast-content {

+  margin: 0 0 0.75rem;

+}

+.aui-toast-loading {

+    background-color: #ffffff;

+    border-radius: 100%;

+    margin: 0.75rem 0;

+    -webkit-animation-fill-mode: both;

+        	animation-fill-mode: both;

+    border: 2px solid #ffffff;

+    border-bottom-color: transparent;

+    height: 2.25rem;

+    width: 2.25rem;

+    background: transparent !important;

+    display: inline-block;

+    -webkit-animation: rotate 1s 0s linear infinite;

+        	animation: rotate 1s 0s linear infinite;

+}

+/*dialog*/

+.aui-dialog {

+	width: 13.5rem;

+	text-align: center;

+	position: fixed;

+	z-index: 999;

+	left: 50%;

+	margin-left: -6.75rem;

+	margin-top: 0;

+	top: 45%;

+	border-radius: 0.3rem;

+	opacity: 0;

+	background-color: #ffffff;

+	-webkit-transform: translate3d(0, 0, 0) scale(1.2);

+          	transform: translate3d(0, 0, 0) scale(1.2);

+ 	-webkit-transition-property: -webkit-transform, opacity;

+          	transition-property: transform, opacity;

+    /*display: none;*/

+}

+.aui-dialog-header {

+    padding: 0.5rem 0.75rem 0 0.75rem;

+    text-align: center;

+    font-size: 1em;

+    color: #212121;

+}

+.aui-dialog-body {

+    padding: 0.75rem;

+    overflow: hidden;

+    font-size: 0.875em;

+    color: #757575;

+}

+.aui-dialog-body input {

+	border: 1px solid #dddddd;

+	height: 1.8rem;

+	line-height: 1.8rem;

+	min-height: 1.8rem;

+	padding-left: 0.25rem;

+	padding-right: 0.25rem;

+}

+.aui-dialog-footer {

+    position: relative;

+    font-size: 1em;

+    border-top: 1px solid #dddddd;

+    display: -webkit-box;

+    display: -webkit-flex;

+    display: flex;

+    -webkit-box-pack: center;

+	-webkit-justify-content: center;

+			justify-content: center;

+}

+.aui-dialog-btn {

+	position: relative;

+	display: block;

+    width: 100%;

+	padding: 0 0.25rem;

+	height: 2.2rem;

+	font-size: 0.8rem;

+	line-height: 2.2rem;

+	text-align: center;

+	color: #0894ec;

+	border-right: 1px solid #dddddd;

+	white-space: nowrap;

+	text-overflow: ellipsis;

+	overflow: hidden;

+	-webkit-box-sizing: border-box;

+			box-sizing: border-box;

+	-webkit-box-flex: 1;

+			box-flex: 1;

+}

+.aui-dialog-btn:last-child {

+	border-right: none;

+}

+.aui-dialog.aui-dialog-in {

+	opacity: 1;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+	-webkit-transform: translate3d(0, 0, 0) scale(1);

+	      transform: translate3d(0, 0, 0) scale(1);

+}

+.aui-dialog.aui-dialog-out {

+	opacity: 0;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+	-webkit-transform: translate3d(0, 0, 0) scale(0.815);

+	      transform: translate3d(0, 0, 0) scale(0.815);

+}

+@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {

+    .aui-dialog-footer {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-dialog-btn {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: right;

+	}

+	.aui-dialog-btn:last-child {

+		border: none;

+        background-size: 0 100%;

+	}

+	.aui-dialog-body input {

+        border: none;

+        background-image: -webkit-linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(0, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%;

+        background-repeat: no-repeat;

+        background-position: top, right top, bottom, left top;

+    }

+}

+/*popup*/

+.aui-popup {

+    padding: 0;

+    margin: 0;

+    background: transparent;

+    position: fixed;

+    height: auto;

+    min-width: 7rem;

+    min-height: 4.5rem;

+    z-index: 999;

+    opacity: 0;

+ 	-webkit-transition-property: -webkit-transform, opacity;

+          	transition-property: transform, opacity;

+}

+.aui-popup.aui-popup-in {

+	opacity: 1;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+}

+.aui-popup.aui-popup-out {

+	opacity: 0;

+	-webkit-transition-duration: 300ms;

+	      transition-duration: 300ms;

+}

+.aui-popup-right {

+    right: 0.75rem;

+}

+.aui-popup-content {

+    background-color: #ffffff;

+    border-radius: 0.2rem;

+    overflow: hidden;

+    min-height: 4.5rem;

+    height: 100%;

+}

+.aui-popup-top,

+.aui-popup-top-left,

+.aui-popup-top-right {

+    top: 0.45rem;

+}

+.aui-popup-top {

+    left: 50%;

+    margin-left: -3.5rem;

+}

+.aui-popup-top-left {

+    left: 0.45rem;

+}

+.aui-popup-top-right {

+    right: 0.45rem;

+}

+.aui-popup-arrow {

+    position: absolute;

+    width: 10px;

+    height: 10px;

+    -webkit-transform-origin: 50% 50% 0;

+            transform-origin: 50% 50% 0;

+    background-color: transparent;

+    background-image: -webkit-linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+}

+.aui-popup-top .aui-popup-arrow,

+.aui-popup-top-left .aui-popup-arrow,

+.aui-popup-top-right .aui-popup-arrow {

+    top: 0.2rem;

+    -webkit-transform: rotate(135deg);

+            transform: rotate(135deg);

+}

+.aui-popup-top .aui-popup-arrow {

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-top-left .aui-popup-arrow {

+    left: 0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-top-right .aui-popup-arrow {

+    right: 0.25rem;

+    margin-top: -0.4rem;

+}

+.aui-popup-bottom,

+.aui-popup-bottom-left,

+.aui-popup-bottom-right {

+    bottom: 0.45rem;

+}

+.aui-popup-bottom {

+    left: 50%;

+    margin-left: -3.5rem;

+}

+.aui-popup-bottom-left {

+    left: 0.45rem;

+}

+.aui-popup-bottom-right {

+    right: 0.45rem;

+}

+.aui-popup-bottom .aui-popup-arrow,

+.aui-popup-bottom-left .aui-popup-arrow,

+.aui-popup-bottom-right .aui-popup-arrow {

+    -webkit-transform: rotate(-45deg);

+            transform: rotate(-45deg);

+    bottom: 0.2rem;

+}

+.aui-popup-bottom .aui-popup-arrow {

+    left: 50%;

+    margin-left: -0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup-bottom-left .aui-popup-arrow {

+    left: 0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup-bottom-right .aui-popup-arrow {

+    right: 0.25rem;

+    margin-bottom: -0.4rem;

+}

+.aui-popup .aui-list {

+	background: transparent;

+}

+.aui-popup-content .aui-list img {

+	display: block;

+	width: 1rem;

+}

+/*actionsheet*/

+.aui-actionsheet {

+    width: 100%;

+    position: fixed;

+    bottom: 0;

+    left: 0;

+    padding: 0 0.5rem;

+    z-index: 999;

+    opacity: 0;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+    -webkit-transform: translate3d(0,100%,0);

+    transform: translate3d(0,100%,0);

+}

+.aui-actionsheet-btn {

+    background-color: #ffffff;

+    border-radius: 6px;

+    text-align: center;

+    margin-bottom: 0.5rem;

+}

+.aui-actionsheet-title {

+    font-size: 0.6rem;

+    color: #999999;

+    line-height: 1.8rem;

+}

+.aui-actionsheet-btn-item {

+    height: 2.2rem;

+    line-height: 2.2rem;

+    color: #0075f0;

+}

+/*sharebox*/

+.aui-sharebox {

+    width: 100%;

+    position: fixed;

+    bottom: 0;

+    left: 0;

+    z-index: 999;

+    background-color: #ffffff;

+    opacity: 0;

+    -webkit-transition: opacity .3s,-webkit-transform .3s;

+    transition: opacity .3s,transform .3s;

+    -webkit-transform: translate3d(0,100%,0);

+    transform: translate3d(0,100%,0);

+}

+.aui-sharebox .aui-row {

+    padding: 0.5rem 0;

+}

+.aui-sharebox img {

+    display: block;

+    width: 50%;

+    margin: 0 auto;

+}

+.aui-sharebox.aui-grid [class*=aui-col-] {

+    padding: 0.5rem 0;

+}

+.aui-sharebox.aui-grid .aui-grid-label {

+    font-size: 0.6rem;

+    color: #757575;

+}

+.aui-sharebox-close-btn {

+    width: 100%;

+    height: 2.2rem;

+    line-height: 2.2rem;

+    color: #757575;

+    text-align: center;

+    font-size: 0.7rem;

+}

+/*折叠菜单*/

+.aui-collapse-header.aui-active {

+    background: #ececec;

+}

+.aui-collapse .aui-list-item:active{

+    background: #ececec;

+}

+.aui-collapse-content {

+    display: none;

+}

+.aui-collapse-content .aui-list-item:last-child {

+    border-bottom: 0;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+    .aui-collapse-content .aui-list-item:last-child {

+        background-position: bottom;

+    }

+    .aui-list.aui-collapse.aui-list-noborder,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-content:last-child .aui-list-item:last-child {

+        border: none;

+        background-size: 100% 1px;

+        background-repeat: no-repeat;

+        background-position: 0 bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+    }

+    .aui-list.aui-collapse.aui-list-noborder,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-item:last-child .aui-list-item:last-child {

+        border: none;

+        background-size: 100% 0;

+        background-image: none;

+    }

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-item:last-child .aui-list-item.aui-collapse-header,

+    .aui-list.aui-collapse.aui-list-noborder .aui-collapse-content .aui-list-item:last-child  {

+        border: none;

+        background-size: 100% 0;

+        background-image: none;

+    }

+}

+.aui-collapse-header.aui-active .aui-collapse-arrow {

+    display: block;

+    transform: rotate(180deg);

+    -webkit-transform: rotate(180deg);

+}

+/*聊天气泡*/

+.aui-chat {

+    width: 100%;

+    height: 100%;

+    padding: 0.5rem;

+}

+.aui-chat .aui-chat-item {

+    position: relative;

+    width: 100%;

+    margin-bottom: 0.75rem;

+    overflow: hidden;

+    display: block;

+}

+.aui-chat .aui-chat-header {

+    width: 100%;

+    text-align: center;

+    margin-bottom: 0.75rem;

+    font-size: 0.6rem;

+    color: #757575;

+}

+.aui-chat .aui-chat-left {

+    float: left;

+}

+.aui-chat .aui-chat-right {

+    float: right;

+}

+.aui-chat .aui-chat-media {

+    display: inline-block;

+    max-width: 2rem;

+}

+.aui-chat .aui-chat-media img {

+    width: 100%;

+    border-radius: 50%;

+}

+.aui-chat .aui-chat-inner {

+    position: relative;

+    overflow: hidden;

+    display: inherit;

+}

+.aui-chat .aui-chat-arrow {

+    content: '';

+    position: absolute;

+    width: 0.6rem;

+    height: 0.6rem;

+    top: 0.2rem;

+    -webkit-transform-origin: 50% 50% 0;

+            transform-origin: 50% 50% 0;

+    background-color: transparent;

+}

+.aui-chat .aui-chat-left .aui-chat-arrow {

+    background-image: -webkit-linear-gradient(45deg, #b3e5fc, #b3e5fc 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #b3e5fc, #b3e5fc 50%, transparent 50%);

+    -webkit-transform: rotate(45deg);

+            transform: rotate(45deg);

+    left: -0.25rem;

+}

+.aui-chat .aui-chat-right .aui-chat-arrow {

+    background-image: -webkit-linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    background-image: linear-gradient(45deg, #ffffff, #ffffff 50%, transparent 50%);

+    -webkit-transform: rotate(-135deg);

+            transform: rotate(-135deg);

+    right: -0.25rem;

+}

+.aui-chat .aui-chat-content {

+    color: #212121;

+    font-size: 0.7rem;

+    border-radius: 0.2rem;

+    min-height: 2rem;

+    position: relative;

+    padding: 0.5rem;

+    max-width: 80%;

+    word-break: break-all;

+    word-wrap: break-word;

+}

+.aui-chat .aui-chat-content img {

+    max-width: 100%;

+    display: block;

+}

+.aui-chat .aui-chat-status {

+    position: relative;

+    width: 2rem;

+    height: 2rem;

+    line-height: 2rem;

+    text-align: center;

+}

+.aui-chat .aui-chat-name {

+    width: 100%;

+    position: relative;

+    font-size: 0.6rem;

+    color: #757575;

+    margin-bottom: 0.25rem;

+}

+.aui-chat .aui-chat-left .aui-chat-name {

+    left: 0.5rem;

+}

+.aui-chat .aui-chat-left .aui-chat-status {

+    left: 0.5rem;

+    float: left;

+}

+.aui-chat .aui-chat-left .aui-chat-media {

+    width: 2rem;

+    float: left;

+}

+.aui-chat .aui-chat-left .aui-chat-inner {

+    max-width: 70%;

+}

+.aui-chat .aui-chat-left .aui-chat-content{

+    background-color: #b3e5fc;

+    float: left;

+    left: 0.5rem;

+}

+.aui-chat .aui-chat-right .aui-chat-media {

+    width: 2rem;

+    float: right;

+}

+.aui-chat .aui-chat-right .aui-chat-inner {

+    float: right;

+    max-width: 70%;

+}

+.aui-chat .aui-chat-right .aui-chat-name {

+    float: right;

+    right: 0.5rem;

+    text-align: right;

+}

+.aui-chat .aui-chat-right .aui-chat-content {

+    background-color: #ffffff;

+    right: 0.5rem;

+    float: right;

+}

+.aui-chat .aui-chat-right .aui-chat-status {

+    float: right;

+    right: 0.5rem;

+}

+/*边框样式*/

+.aui-border-l {

+    border-left: 1px solid #dddddd;

+}

+.aui-border-r {

+    border-right: 1px solid #dddddd;

+}

+.aui-border-t {

+    border-top: 1px solid #dddddd;

+}

+.aui-border-b {

+    border-bottom: 1px solid #dddddd;

+}

+.aui-border {

+    border: 1px solid #dddddd;

+}

+@media screen and (-webkit-min-device-pixel-ratio:1.5) {

+	.aui-border-l {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: left;

+	}

+	.aui-border-r {

+		border: none;

+        background-image: -webkit-linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 1px 100%;

+        background-repeat: no-repeat;

+        background-position: right;

+	}

+	.aui-border-t{

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: top;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-border-b {

+		border: none;

+        background-size: 100% 1px;

+		background-repeat: no-repeat;

+		background-position: bottom;

+        background-image: linear-gradient(0,#dddddd,#dddddd 50%,transparent 50%);

+        background-image: -webkit-linear-gradient(90deg,#dddddd,#dddddd 50%,transparent 50%);

+	}

+	.aui-border{

+        border: none;

+        background-image: -webkit-linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%), -webkit-linear-gradient(0, #dddddd, #dddddd 50%, transparent 50%);

+        background-image: linear-gradient(180deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(270deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(0deg, #dddddd, #dddddd 50%, transparent 50%), linear-gradient(90deg, #dddddd, #dddddd 50%, transparent 50%);

+        background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%;

+        background-repeat: no-repeat;

+        background-position: top, right top, bottom, left top;

+    }

+}

+/*时间轴*/

+.aui-timeline {

+    position: relative;

+    padding: 0;

+    list-style: none;

+}

+.aui-timeline:before {

+    content: '';

+    position: absolute;

+    top: 0;

+    left: 1.85rem;

+    width: 2px;

+    height: 100%;

+    background: #ececec;

+    z-index: 0;

+}

+.aui-timeline .aui-timeline-item {

+    position: relative;

+    margin-bottom: 0.35rem;

+}

+.aui-timeline .aui-timeline-item-header {

+	background-color: #ececec;

+	padding: 0.2rem 0.5rem;

+	margin: 0.75rem;

+    text-align: center;

+    display: inline-block;

+    position: relative;

+    z-index: 1;

+    font-size: 0.7rem;

+}

+.aui-timeline .aui-timeline-item-label {

+    width: 2.5rem;

+    height: 1.5rem;

+    line-height: 1.5rem;

+    font-size: 0.7em;

+    background-color: #ececec;

+    position: absolute;

+    text-align: center;

+    left: 0.75rem;

+    top: 0;

+}

+.aui-timeline .aui-timeline-item-label-icon {

+    width: 1.5rem;

+    height: 1.5rem;

+    font-size: 0.7rem;

+    line-height: 1.5rem;

+    background-color: #ececec;

+    position: absolute;

+    border-radius: 50%;

+    text-align: center;

+    left: 1.15rem;

+    top: 0;

+}

+.aui-timeline .aui-timeline-item-inner {

+    margin-left: 3.75rem;

+    margin-right: 0.75rem;

+    padding: 0;

+    position: relative;

+}

+/*基础动画类*/

+@keyframes rotate {

+    0% {

+        -webkit-transform: rotate(0deg) scale(1);

+            	transform: rotate(0deg) scale(1);

+    }

+    50% {

+        -webkit-transform: rotate(180deg) scale(1);

+            	transform: rotate(180deg) scale(1);

+    }

+    100% {

+        -webkit-transform: rotate(360deg) scale(1);

+            	transform: rotate(360deg) scale(1);

+    }

+}

+@-webkit-keyframes rotate {

+    0% {

+        -webkit-transform: rotate(0deg) scale(1);

+            	transform: rotate(0deg) scale(1);

+    }

+    50% {

+        -webkit-transform: rotate(180deg) scale(1);

+            	transform: rotate(180deg) scale(1);

+    }

+    100% {

+        -webkit-transform: rotate(360deg) scale(1);

+            	transform: rotate(360deg) scale(1);

+    }

+}

+@keyframes bounce {

+	0%, 100% {

+	-webkit-transform: scale(0.0);

+			transform: scale(0.0);

+	}

+	50% {

+	-webkit-transform: scale(1.0);

+			transform: scale(1.0);

+	}

+}

+@-webkit-keyframes bounce {

+	0%, 100% {

+		-webkit-transform: scale(0.0);

+				transform: scale(0.0);

+	}

+	50% {

+		-webkit-transform: scale(1.0);

+				transform: scale(1.0);

+	}

+}

+@keyframes fadeIn {

+    from { opacity: 0.3; }

+    to { opacity: 1; }

+}

+@-webkit-keyframes fadeIn {

+    from { opacity: 0.3; }

+    to { opacity: 1; }

+}

+@font-face {

+	font-family: "aui_iconfont";

+	src: url('aui-iconfont.ttf') format('truetype');

+}

+.aui-iconfont {

+	position: relative;

+	font-family:"aui_iconfont" !important;

+	font-size: 0.7rem;

+	font-style:normal;

+	-webkit-font-smoothing: antialiased;

+	-moz-osx-font-smoothing: grayscale;

+}

+.aui-icon-menu:before { content: "\e6eb"; }

+.aui-icon-paper:before { content: "\e6ec"; }

+.aui-icon-info:before { content: "\e6ed"; }

+.aui-icon-question:before { content: "\e6ee"; }

+.aui-icon-left:before { content: "\e6f4"; }

+.aui-icon-right:before { content: "\e6f5"; }

+.aui-icon-top:before { content: "\e6f6"; }

+.aui-icon-down:before { content: "\e6f7"; }

+.aui-icon-share:before { content: "\e700"; }

+.aui-icon-comment:before { content: "\e701"; }

+.aui-icon-edit:before { content: "\e6d3"; }

+.aui-icon-trash:before { content: "\e6d4"; }

+.aui-icon-recovery:before { content: "\e6dc"; }

+.aui-icon-refresh:before { content: "\e6dd"; }

+.aui-icon-close:before { content: "\e6d8"; }

+.aui-icon-cart:before { content: "\e6df"; }

+.aui-icon-star:before { content: "\e6e0"; }

+.aui-icon-plus:before { content: "\e6e3"; }

+.aui-icon-minus:before { content: "\e62d"; }

+.aui-icon-correct:before { content: "\e6e5"; }

+.aui-icon-search:before { content: "\e6e6"; }

+.aui-icon-gear:before { content: "\e6e8"; }

+.aui-icon-map:before { content: "\e6d2"; }

+.aui-icon-location:before { content: "\e6d1"; }

+.aui-icon-image:before { content: "\e6ce"; }

+.aui-icon-phone:before { content: "\e6c4"; }

+.aui-icon-camera:before { content: "\e6cd"; }

+.aui-icon-video:before { content: "\e6cc"; }

+.aui-icon-qq:before { content: "\e6cb"; }

+.aui-icon-wechat:before { content: "\e6c9"; }

+.aui-icon-weibo:before { content: "\e6c8"; }

+.aui-icon-note:before { content: "\e6c6"; }

+.aui-icon-mail:before { content: "\e6c5"; }

+.aui-icon-wechat-circle:before { content: "\e6ca"; }

+.aui-icon-home:before { content: "\e706"; }

+.aui-icon-forward:before { content: "\e6d9"; }

+.aui-icon-back:before { content: "\e6da"; }

+.aui-icon-laud:before { content: "\e64b"; }

+.aui-icon-lock:before { content: "\e6ef"; }

+.aui-icon-unlock:before { content: "\e62f"; }

+.aui-icon-like:before { content: "\e62b"; }

+.aui-icon-my:before { content: "\e610"; }

+.aui-icon-more:before { content: "\e625"; }

+.aui-icon-mobile:before { content: "\e697"; }

+.aui-icon-calendar:before { content: "\e68a"; }

+.aui-icon-date:before { content: "\e68c"; }

+.aui-icon-display:before { content: "\e612"; }

+.aui-icon-hide:before { content: "\e624"; }

+.aui-icon-pencil:before { content: "\e615"; }

+.aui-icon-flag:before { content: "\e6f1"; }

+.aui-icon-cert:before { content: "\e704"; }

+

+.aui-card-list-user:after {

+	width: 100%;

+    height: 1px;

+    background-color: #f2f2f2;

+    display: block;

+    content: '';

+    position: absolute;

+    top: auto;

+    right: auto;

+    bottom: 0;

+    left: 0;

+    z-index: 2;

+    -webkit-transform-origin: 50% 100%;

+            transform-origin: 50% 100%;

+    pointer-events: none;

+}

+.aui-list [class*=top-btn]:active {

+	background-color: #048cca;

+}

diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/index.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/index.css
new file mode 100644
index 0000000..b23e33c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/index.css
@@ -0,0 +1,149 @@
+body {
+    background: #F1F4F4;
+}
+
+.mainbg {
+    background: #03a9f4;
+}
+
+.lightbg {
+    background: #54C8FF;
+}
+
+.tab-bottom button.active::after {
+    background-color: transparent;
+}
+
+.maincolor {
+    color: #03a9f4;
+}
+
+.qrscanner {
+    width: 100%;
+    background: transparent none !important;
+    padding-top: 52px;
+}
+
+.qrscanner-area {
+    height: 100mm;
+    background: url(../img/scanner.svg) no-repeat center center;
+    background-size: contain;
+}
+
+.through-line {
+    left: 20%;
+    width: 60%;
+    height: 2px;
+    background: red;
+    position: absolute;
+    animation: myfirst 2s linear infinite alternate;
+}
+
+@keyframes myfirst {
+    0% {
+        background: #03a9f4;
+        top: 180px;
+    }
+
+    25% {
+        background: #03a9f4;
+        top: 215px;
+    }
+
+    50% {
+        background: #03a9f4;
+        top: 250px;
+    }
+
+    75% {
+        background: #03a9f4;
+        top: 285px;
+    }
+
+    100% {
+        background: #03a9f4;
+        top: 320px;
+    }
+}
+
+.button-bottom {
+    width: 128px;
+    position: absolute;
+    left: 50%;
+    bottom: 80px;
+    margin-left: -64px;
+}
+
+.icon-camera {
+    float: left;
+}
+
+.vcodedisabled {
+    color: #999 !important;
+}
+
+.login-top {
+    height: 200px;
+    background: #03a9f4;
+    color: #fff;
+    font-size: 36px;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+}
+
+.weui-toast_content {
+    color: #fff;
+}
+
+.center-in {
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    display: flex;
+}
+
+.top-title {
+    color: #fff;
+    font-size: 20px !important;
+    margin-top: 5px;
+}
+
+.user-info {
+    width: 150%;
+    position: relative;
+    left: -25%;
+    padding-left: 25%;
+    border-bottom-left-radius: 50%;
+    border-bottom-right-radius: 50%;
+    padding-bottom: 1.5rem;
+}
+
+.text-white {
+    color: #ffffff !important;
+}
+
+.text-light {
+    color: #999 !important;
+}
+
+.bg-white {
+    background-color: #ffffff;
+}
+.demos-header {
+    padding: 20px 0;
+    background-color: #03a9f4;
+}
+.demos-title {
+    text-align: center;
+    font-size: 40px;
+    color: #fff;
+    font-weight: 400;
+    margin: 0 15%;
+}
+.detail-title{
+    text-align: center;
+    font-size: 16px;
+    color: #fff;
+}
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/jquery-weui.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/jquery-weui.min.css
new file mode 100755
index 0000000..145c336
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/jquery-weui.min.css
@@ -0,0 +1,6 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+.preloader{width:20px;height:20px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:preloader-spin 1s steps(12,end) infinite;animation:preloader-spin 1s steps(12,end) infinite}.preloader:after{display:block;width:100%;height:100%;content:"";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-repeat:no-repeat;background-position:50%;background-size:100%}@-webkit-keyframes preloader-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}label>*{pointer-events:none}html{font-size:20px}body{font-size:16px}@media only screen and (min-width:400px){html{font-size:21.33px!important}}@media only screen and (min-width:414px){html{font-size:22.08px!important}}@media only screen and (min-width:480px){html{font-size:25.6px!important}}.weui_navbar{z-index:10}.weui-mask,.weui-popup-container,.weui-popup-overlay{z-index:1000}.weui-row{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.weui-row>[class*=col-]{box-sizing:border-box}.weui-row .col-auto{width:100%}.weui-row .weui-col-100{width:100%;width:calc((100% - 15px*0)/ 1)}.weui-row.weui-no-gutter .weui-col-100{width:100%}.weui-row .weui-col-95{width:95%;width:calc((100% - 15px*.05263157894736836)/ 1.0526315789473684)}.weui-row.weui-no-gutter .weui-col-95{width:95%}.weui-row .weui-col-90{width:90%;width:calc((100% - 15px*.11111111111111116)/ 1.1111111111111112)}.weui-row.weui-no-gutter .weui-col-90{width:90%}.weui-row .weui-col-85{width:85%;width:calc((100% - 15px*.17647058823529416)/ 1.1764705882352942)}.weui-row.weui-no-gutter .weui-col-85{width:85%}.weui-row .weui-col-80{width:80%;width:calc((100% - 15px*.25)/ 1.25)}.weui-row.weui-no-gutter .weui-col-80{width:80%}.weui-row .weui-col-75{width:75%;width:calc((100% - 15px*.33333333333333326)/ 1.3333333333333333)}.weui-row.weui-no-gutter .weui-col-75{width:75%}.weui-row .weui-col-66{width:66.66666666666666%;width:calc((100% - 15px*.5000000000000002)/ 1.5000000000000002)}.weui-row.weui-no-gutter .weui-col-66{width:66.66666666666666%}.weui-row .weui-col-60{width:60%;width:calc((100% - 15px*.6666666666666667)/ 1.6666666666666667)}.weui-row.weui-no-gutter .weui-col-60{width:60%}.weui-row .weui-col-50{width:50%;width:calc((100% - 15px*1)/ 2)}.weui-row.weui-no-gutter .weui-col-50{width:50%}.weui-row .weui-col-40{width:40%;width:calc((100% - 15px*1.5)/ 2.5)}.weui-row.weui-no-gutter .weui-col-40{width:40%}.weui-row .weui-col-33{width:33.333333333333336%;width:calc((100% - 15px*2)/ 3)}.weui-row.weui-no-gutter .weui-col-33{width:33.333333333333336%}.weui-row .weui-col-25{width:25%;width:calc((100% - 15px*3)/ 4)}.weui-row.weui-no-gutter .weui-col-25{width:25%}.weui-row .weui-col-20{width:20%;width:calc((100% - 15px*4)/ 5)}.weui-row.weui-no-gutter .weui-col-20{width:20%}.weui-row .weui-col-15{width:15%;width:calc((100% - 15px*5.666666666666667)/ 6.666666666666667)}.weui-row.weui-no-gutter .weui-col-15{width:15%}.weui-row .weui-col-10{width:10%;width:calc((100% - 15px*9)/ 10)}.weui-row.weui-no-gutter .weui-col-10{width:10%}.weui-row .weui-col-5{width:5%;width:calc((100% - 15px*19)/ 20)}.weui-row.weui-no-gutter .weui-col-5{width:5%}.weui-row .weui-col-auto:nth-last-child(1),.weui-row .weui-col-auto:nth-last-child(1)~.weui-col-auto{width:100%;width:calc((100% - 15px*0)/ 1)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(1),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(1)~.weui-col-auto{width:100%}.weui-row .weui-col-auto:nth-last-child(2),.weui-row .weui-col-auto:nth-last-child(2)~.weui-col-auto{width:50%;width:calc((100% - 15px*1)/ 2)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(2),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(2)~.weui-col-auto{width:50%}.weui-row .weui-col-auto:nth-last-child(3),.weui-row .weui-col-auto:nth-last-child(3)~.weui-col-auto{width:33.33333333%;width:calc((100% - 15px*2)/ 3)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(3),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(3)~.weui-col-auto{width:33.33333333%}.weui-row .weui-col-auto:nth-last-child(4),.weui-row .weui-col-auto:nth-last-child(4)~.weui-col-auto{width:25%;width:calc((100% - 15px*3)/ 4)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(4),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(4)~.weui-col-auto{width:25%}.weui-row .weui-col-auto:nth-last-child(5),.weui-row .weui-col-auto:nth-last-child(5)~.weui-col-auto{width:20%;width:calc((100% - 15px*4)/ 5)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(5),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(5)~.weui-col-auto{width:20%}.weui-row .weui-col-auto:nth-last-child(6),.weui-row .weui-col-auto:nth-last-child(6)~.weui-col-auto{width:16.66666667%;width:calc((100% - 15px*5)/ 6)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(6),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(6)~.weui-col-auto{width:16.66666667%}.weui-row .weui-col-auto:nth-last-child(7),.weui-row .weui-col-auto:nth-last-child(7)~.weui-col-auto{width:14.28571429%;width:calc((100% - 15px*6)/ 7)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(7),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(7)~.weui-col-auto{width:14.28571429%}.weui-row .weui-col-auto:nth-last-child(8),.weui-row .weui-col-auto:nth-last-child(8)~.weui-col-auto{width:12.5%;width:calc((100% - 15px*7)/ 8)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(8),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(8)~.weui-col-auto{width:12.5%}.weui-row .weui-col-auto:nth-last-child(9),.weui-row .weui-col-auto:nth-last-child(9)~.weui-col-auto{width:11.11111111%;width:calc((100% - 15px*8)/ 9)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(9),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(9)~.weui-col-auto{width:11.11111111%}.weui-row .weui-col-auto:nth-last-child(10),.weui-row .weui-col-auto:nth-last-child(10)~.weui-col-auto{width:10%;width:calc((100% - 15px*9)/ 10)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(10),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(10)~.weui-col-auto{width:10%}.weui-row .weui-col-auto:nth-last-child(11),.weui-row .weui-col-auto:nth-last-child(11)~.weui-col-auto{width:9.09090909%;width:calc((100% - 15px*10)/ 11)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(11),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(11)~.weui-col-auto{width:9.09090909%}.weui-row .weui-col-auto:nth-last-child(12),.weui-row .weui-col-auto:nth-last-child(12)~.weui-col-auto{width:8.33333333%;width:calc((100% - 15px*11)/ 12)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(12),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(12)~.weui-col-auto{width:8.33333333%}.weui-row .weui-col-auto:nth-last-child(13),.weui-row .weui-col-auto:nth-last-child(13)~.weui-col-auto{width:7.69230769%;width:calc((100% - 15px*12)/ 13)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(13),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(13)~.weui-col-auto{width:7.69230769%}.weui-row .weui-col-auto:nth-last-child(14),.weui-row .weui-col-auto:nth-last-child(14)~.weui-col-auto{width:7.14285714%;width:calc((100% - 15px*13)/ 14)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(14),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(14)~.weui-col-auto{width:7.14285714%}.weui-row .weui-col-auto:nth-last-child(15),.weui-row .weui-col-auto:nth-last-child(15)~.weui-col-auto{width:6.66666667%;width:calc((100% - 15px*14)/ 15)}.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(15),.weui-row.weui-no-gutter .weui-col-auto:nth-last-child(15)~.weui-col-auto{width:6.66666667%}@media all and (min-width:768px){.row .tablet-100{width:100%;width:calc((100% - 15px*0)/ 1)}.row.no-gutter .tablet-100{width:100%}.row .tablet-95{width:95%;width:calc((100% - 15px*.05263157894736836)/ 1.0526315789473684)}.row.no-gutter .tablet-95{width:95%}.row .tablet-90{width:90%;width:calc((100% - 15px*.11111111111111116)/ 1.1111111111111112)}.row.no-gutter .tablet-90{width:90%}.row .tablet-85{width:85%;width:calc((100% - 15px*.17647058823529416)/ 1.1764705882352942)}.row.no-gutter .tablet-85{width:85%}.row .tablet-80{width:80%;width:calc((100% - 15px*.25)/ 1.25)}.row.no-gutter .tablet-80{width:80%}.row .tablet-75{width:75%;width:calc((100% - 15px*.33333333333333326)/ 1.3333333333333333)}.row.no-gutter .tablet-75{width:75%}.row .tablet-66{width:66.66666666666666%;width:calc((100% - 15px*.5000000000000002)/ 1.5000000000000002)}.row.no-gutter .tablet-66{width:66.66666666666666%}.row .tablet-60{width:60%;width:calc((100% - 15px*.6666666666666667)/ 1.6666666666666667)}.row.no-gutter .tablet-60{width:60%}.row .tablet-50{width:50%;width:calc((100% - 15px*1)/ 2)}.row.no-gutter .tablet-50{width:50%}.row .tablet-40{width:40%;width:calc((100% - 15px*1.5)/ 2.5)}.row.no-gutter .tablet-40{width:40%}.row .tablet-33{width:33.333333333333336%;width:calc((100% - 15px*2)/ 3)}.row.no-gutter .tablet-33{width:33.333333333333336%}.row .tablet-25{width:25%;width:calc((100% - 15px*3)/ 4)}.row.no-gutter .tablet-25{width:25%}.row .tablet-20{width:20%;width:calc((100% - 15px*4)/ 5)}.row.no-gutter .tablet-20{width:20%}.row .tablet-15{width:15%;width:calc((100% - 15px*5.666666666666667)/ 6.666666666666667)}.row.no-gutter .tablet-15{width:15%}.row .tablet-10{width:10%;width:calc((100% - 15px*9)/ 10)}.row.no-gutter .tablet-10{width:10%}.row .tablet-5{width:5%;width:calc((100% - 15px*19)/ 20)}.row.no-gutter .tablet-5{width:5%}.row .tablet-auto:nth-last-child(1),.row .tablet-auto:nth-last-child(1)~.col-auto{width:100%;width:calc((100% - 15px*0)/ 1)}.row.no-gutter .tablet-auto:nth-last-child(1),.row.no-gutter .tablet-auto:nth-last-child(1)~.tablet-auto{width:100%}.row .tablet-auto:nth-last-child(2),.row .tablet-auto:nth-last-child(2)~.col-auto{width:50%;width:calc((100% - 15px*1)/ 2)}.row.no-gutter .tablet-auto:nth-last-child(2),.row.no-gutter .tablet-auto:nth-last-child(2)~.tablet-auto{width:50%}.row .tablet-auto:nth-last-child(3),.row .tablet-auto:nth-last-child(3)~.col-auto{width:33.33333333%;width:calc((100% - 15px*2)/ 3)}.row.no-gutter .tablet-auto:nth-last-child(3),.row.no-gutter .tablet-auto:nth-last-child(3)~.tablet-auto{width:33.33333333%}.row .tablet-auto:nth-last-child(4),.row .tablet-auto:nth-last-child(4)~.col-auto{width:25%;width:calc((100% - 15px*3)/ 4)}.row.no-gutter .tablet-auto:nth-last-child(4),.row.no-gutter .tablet-auto:nth-last-child(4)~.tablet-auto{width:25%}.row .tablet-auto:nth-last-child(5),.row .tablet-auto:nth-last-child(5)~.col-auto{width:20%;width:calc((100% - 15px*4)/ 5)}.row.no-gutter .tablet-auto:nth-last-child(5),.row.no-gutter .tablet-auto:nth-last-child(5)~.tablet-auto{width:20%}.row .tablet-auto:nth-last-child(6),.row .tablet-auto:nth-last-child(6)~.col-auto{width:16.66666667%;width:calc((100% - 15px*5)/ 6)}.row.no-gutter .tablet-auto:nth-last-child(6),.row.no-gutter .tablet-auto:nth-last-child(6)~.tablet-auto{width:16.66666667%}.row .tablet-auto:nth-last-child(7),.row .tablet-auto:nth-last-child(7)~.col-auto{width:14.28571429%;width:calc((100% - 15px*6)/ 7)}.row.no-gutter .tablet-auto:nth-last-child(7),.row.no-gutter .tablet-auto:nth-last-child(7)~.tablet-auto{width:14.28571429%}.row .tablet-auto:nth-last-child(8),.row .tablet-auto:nth-last-child(8)~.col-auto{width:12.5%;width:calc((100% - 15px*7)/ 8)}.row.no-gutter .tablet-auto:nth-last-child(8),.row.no-gutter .tablet-auto:nth-last-child(8)~.tablet-auto{width:12.5%}.row .tablet-auto:nth-last-child(9),.row .tablet-auto:nth-last-child(9)~.col-auto{width:11.11111111%;width:calc((100% - 15px*8)/ 9)}.row.no-gutter .tablet-auto:nth-last-child(9),.row.no-gutter .tablet-auto:nth-last-child(9)~.tablet-auto{width:11.11111111%}.row .tablet-auto:nth-last-child(10),.row .tablet-auto:nth-last-child(10)~.col-auto{width:10%;width:calc((100% - 15px*9)/ 10)}.row.no-gutter .tablet-auto:nth-last-child(10),.row.no-gutter .tablet-auto:nth-last-child(10)~.tablet-auto{width:10%}.row .tablet-auto:nth-last-child(11),.row .tablet-auto:nth-last-child(11)~.col-auto{width:9.09090909%;width:calc((100% - 15px*10)/ 11)}.row.no-gutter .tablet-auto:nth-last-child(11),.row.no-gutter .tablet-auto:nth-last-child(11)~.tablet-auto{width:9.09090909%}.row .tablet-auto:nth-last-child(12),.row .tablet-auto:nth-last-child(12)~.col-auto{width:8.33333333%;width:calc((100% - 15px*11)/ 12)}.row.no-gutter .tablet-auto:nth-last-child(12),.row.no-gutter .tablet-auto:nth-last-child(12)~.tablet-auto{width:8.33333333%}.row .tablet-auto:nth-last-child(13),.row .tablet-auto:nth-last-child(13)~.col-auto{width:7.69230769%;width:calc((100% - 15px*12)/ 13)}.row.no-gutter .tablet-auto:nth-last-child(13),.row.no-gutter .tablet-auto:nth-last-child(13)~.tablet-auto{width:7.69230769%}.row .tablet-auto:nth-last-child(14),.row .tablet-auto:nth-last-child(14)~.col-auto{width:7.14285714%;width:calc((100% - 15px*13)/ 14)}.row.no-gutter .tablet-auto:nth-last-child(14),.row.no-gutter .tablet-auto:nth-last-child(14)~.tablet-auto{width:7.14285714%}.row .tablet-auto:nth-last-child(15),.row .tablet-auto:nth-last-child(15)~.col-auto{width:6.66666667%;width:calc((100% - 15px*14)/ 15)}.row.no-gutter .tablet-auto:nth-last-child(15),.row.no-gutter .tablet-auto:nth-last-child(15)~.tablet-auto{width:6.66666667%}}.weui-cell__hd img{display:block;margin-right:5px}.weui-cell_swiped .weui-cell__bd{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.swipeout-touching .weui-cell__bd{-webkit-transition:none;transition:none}.weui-dialog,.weui-toast{-webkit-transition-duration:.2s;transition-duration:.2s;opacity:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:0 0;transform-origin:0 0;visibility:hidden;margin:0;top:45%;z-index:2000}.weui-dialog .weui-dialog__btn.default,.weui-toast .weui-dialog__btn.default{color:#5f646e}.weui-dialog .weui-dialog__btn+.weui-dialog__btn,.weui-toast .weui-dialog__btn+.weui-dialog__btn{position:relative}.weui-dialog .weui-dialog__btn+.weui-dialog__btn:after,.weui-toast .weui-dialog__btn+.weui-dialog__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;height:100%;border-left:1px solid #D5D5D6;color:#D5D5D6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-dialog.weui-dialog--visible,.weui-dialog.weui-toast--visible,.weui-toast.weui-dialog--visible,.weui-toast.weui-toast--visible{opacity:1;visibility:visible}.weui-toast_forbidden{color:#F76260}.weui-toast_cancel .weui-icon-toast:before{content:"\EA0D"}.weui-toast_forbidden .weui-icon-toast:before{content:"\EA0B";color:#F76260}.weui-toast_text{min-height:1em;width:auto;height:45px;border-radius:25px;margin-left:0;-webkit-transform:scale(.9) translate3d(-50%,0,0);transform:scale(.9) translate3d(-50%,0,0);-webkit-transform-origin:left;transform-origin:left}.weui-toast_text.weui-toast--visible{-webkit-transform:scale(1) translate3d(-50%,0,0);transform:scale(1) translate3d(-50%,0,0)}.weui-toast_text .weui-icon-toast{display:none}.weui-toast_text .weui-toast_content{margin:10px 15px}.weui-mask{opacity:0;-webkit-transition-duration:.3s;transition-duration:.3s;visibility:hidden}.weui-mask.weui-mask--visible{opacity:1;visibility:visible}.weui-prompt-input{padding:4px 6px;border:1px solid #ccc;box-sizing:border-box;height:2em;width:80%;margin-top:10px}.weui-pull-to-refresh{margin-top:-50px;-webkit-transition:-webkit-transform .4s;transition:-webkit-transform .4s;transition:transform .4s;transition:transform .4s,-webkit-transform .4s}.weui-pull-to-refresh.refreshing{-webkit-transform:translate3d(0,50px,0);transform:translate3d(0,50px,0)}.weui-pull-to-refresh.touching{-webkit-transition-duration:0s;transition-duration:0s}.weui-pull-to-refresh__layer{height:30px;line-height:30px;padding:10px;text-align:center}.weui-pull-to-refresh__layer .down{display:inline-block}.weui-pull-to-refresh__layer .refresh,.weui-pull-to-refresh__layer .up{display:none}.weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:inline-block;z-index:10;width:20px;height:20px;margin-right:4px;vertical-align:-4px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2026%2040'%3E%3Cpolygon%20points%3D'9%2C22%209%2C0%2017%2C0%2017%2C22%2026%2C22%2013.5%2C40%200%2C22'%20fill%3D'%238c8c8c'%2F%3E%3C%2Fsvg%3E") center no-repeat;background-size:13px 20px;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:rotate(0) translate3d(0,0,0);transform:rotate(0) translate3d(0,0,0)}.weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader{display:none;vertical-align:-4px;margin-right:4px;width:20px;height:20px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:preloader-spin 1s steps(12,end) infinite;animation:preloader-spin 1s steps(12,end) infinite}.weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader:after{display:block;width:100%;height:100%;content:"";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-repeat:no-repeat;background-position:50%;background-size:100%}.pull-up .weui-pull-to-refresh__layer .down,.refreshing .weui-pull-to-refresh__layer .down{display:none}.pull-up .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:inline-block;-webkit-transform:rotate(180deg) translate3d(0,0,0);transform:rotate(180deg) translate3d(0,0,0)}.pull-down .weui-pull-to-refresh__layer .down,.pull-down .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow,.pull-up .weui-pull-to-refresh__layer .up{display:inline-block}.refreshing .weui-pull-to-refresh__layer .weui-pull-to-refresh__arrow{display:none}.refreshing .weui-pull-to-refresh__layer .refresh,.refreshing .weui-pull-to-refresh__layer .weui-pull-to-refresh__preloader{display:inline-block}@keyframes preloader-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.weui-tab__bd-item.weui-pull-to-refresh{position:absolute;top:50px}.toolbar,.weui-tabbar__item{position:relative}.weui-tabbar__item.weui-bar__item--on .weui-tabbar__label{color:#04BE02}.weui-navbar__item{color:#888}.weui-navbar__item.weui-bar__item--on{color:#666;background-color:#f1f1f1}.toolbar,.toolbar .title{font-size:.85rem;color:#3d4145;width:100%}.weui-tab__bd{box-sizing:border-box;height:100%}.weui-tab__bd .weui-tab__bd-item{display:none;height:100%;overflow:auto}.weui-tab__bd .weui-tab__bd-item.weui-tab__bd-item--active{display:block}.weui-navbar+.weui-tab__bd{padding-top:50px}.toolbar{line-height:1.5;background:#f7f7f8}.toolbar:before{content:'';position:absolute;left:0;top:0;bottom:auto;right:auto;height:1px;width:100%;background-color:#d9d9d9;display:block;z-index:15;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.toolbar:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.toolbar:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.toolbar .toolbar-inner{height:2.2rem;display:-webkit-box;display:-ms-flexbox;display:flex;text-align:center}.toolbar .title{position:absolute;display:block;padding:0;font-weight:400;line-height:2.2rem;text-align:center;white-space:nowrap}.toolbar .picker-button{position:absolute;right:0;box-sizing:border-box;height:2.2rem;line-height:2.2rem;color:#04BE02;z-index:1;padding:0 .5rem}.weui-picker-modal{width:100%;position:absolute;bottom:0;text-align:center;border-radius:0;opacity:.6;color:#3d4145;-webkit-transition-duration:.3s;transition-duration:.3s;height:13rem;background:#EFEFF4;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.weui-picker-modal.picker-modal-inline{height:10.8rem;opacity:1;position:static;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-picker-modal.picker-modal-inline .toolbar{display:none}.weui-picker-modal.picker-columns-single .picker-items-col{width:100%}.weui-picker-modal.weui-picker-modal-visible{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-picker-modal .picker-modal-inner{position:relative;height:10.8rem}.weui-picker-modal .picker-columns{width:100%;height:13rem;z-index:11500}.popover .weui-picker-modal .picker-columns,.weui-picker-modal .picker-columns.picker-modal-inline{height:10rem}@media (orientation:landscape) and (max-height:415px){.weui-picker-modal .picker-columns:not(.picker-modal-inline){height:10rem}}.weui-picker-modal .popover.popover-picker-columns{width:14rem}.weui-picker-modal .picker-items{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%;padding:0;text-align:right;font-size:1rem;font-weight:400;-webkit-mask-box-image:-webkit-linear-gradient(bottom,transparent,transparent 5%,#fff 20%,#fff 80%,transparent 95%,transparent);-webkit-mask-box-image:linear-gradient(to top,transparent,transparent 5%,#fff 20%,#fff 80%,transparent 95%,transparent)}.weui-picker-modal .bar+.picker-items{height:10.8rem}.weui-picker-modal .picker-items-col{overflow:hidden;position:relative;max-height:100%}.weui-picker-modal .picker-items-col.picker-items-col-left{text-align:left}.weui-picker-modal .picker-items-col.picker-items-col-center{text-align:center}.weui-picker-modal .picker-items-col.picker-items-col-right{text-align:right}.weui-picker-modal .picker-items-col.picker-items-col-divider{color:#3d4145;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.weui-picker-modal .picker-items-col-wrapper{-webkit-transition:.3s;transition:.3s;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.weui-picker-modal .picker-item{height:32px;line-height:32px;padding:0 10px;white-space:nowrap;position:relative;overflow:hidden;text-overflow:ellipsis;color:#9b9b9b;left:0;top:0;width:100%;box-sizing:border-box;-webkit-transition:.3s;transition:.3s}.picker-items-col-absolute .weui-picker-modal .picker-item{position:absolute}.weui-picker-modal .picker-item.picker-item-far{pointer-events:none}.weui-picker-modal .picker-item.picker-selected{color:#3d4145;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transform:rotateX(0);transform:rotateX(0)}.weui-picker-modal .picker-center-highlight{height:32px;box-sizing:border-box;position:absolute;left:0;width:100%;top:50%;margin-top:-16px;pointer-events:none}.weui-picker-modal .picker-center-highlight:after,.weui-picker-modal .picker-center-highlight:before{content:'';position:absolute;right:auto;height:1px;background-color:#D9D9D9;display:block;z-index:15;left:0;width:100%}.weui-picker-modal .picker-center-highlight:before{top:0;bottom:auto;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.weui-picker-modal .picker-center-highlight:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.weui-picker-modal .picker-center-highlight:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-center-highlight:after{bottom:0;top:auto;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.weui-picker-modal .picker-center-highlight:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.weui-picker-modal .picker-center-highlight:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-3d .picker-items{overflow:hidden;-webkit-perspective:1200px;perspective:1200px}.weui-picker-modal .picker-3d .picker-item,.weui-picker-modal .picker-3d .picker-items-col,.weui-picker-modal .picker-3d .picker-items-col-wrapper{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.weui-picker-modal .picker-3d .picker-items-col{overflow:visible}.weui-picker-modal .picker-3d .picker-item{-webkit-transform-origin:center center -110px;transform-origin:center center -110px;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.weui-picker-container,.weui-picker-overlay{position:fixed;bottom:0;left:0;right:0;height:0;width:100%;z-index:1000}.picker-calendar-row:after,.picker-calendar-week-days:after{content:'';z-index:15;left:0;right:auto}.city-picker .picker-items-col{-webkit-box-flex:1;-ms-flex:1;flex:1;max-width:7rem}.weui-picker-container .weui-cells{margin:0;text-align:left}.datetime-picker .picker-item{text-overflow:initial}.weui-select-modal{height:auto}.weui-select-modal .weui-cells{margin:0;text-align:left;overflow-y:auto;overflow-x:hidden;max-height:16rem}.weui-select-modal .weui-cells:after{display:none}.weui-picker-calendar{background:#fff;height:15rem;width:100%;overflow:hidden}.weui-picker-calendar .picker-modal-inner{overflow:hidden;height:12.8rem}.picker-calendar-week-days{height:.9rem;background:#f7f7f8;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:11px;box-sizing:border-box;position:relative}.picker-calendar-week-days:after{position:absolute;bottom:0;top:auto;height:1px;width:100%;background-color:#c4c4c4;display:block;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar-week-days:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar-week-days:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.picker-calendar-week-days .picker-calendar-week-day{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;width:14.28571429%;width:calc(100% / 7);line-height:17px;text-align:center}.picker-calendar-week-days+.picker-calendar-months{height:11.9rem}.picker-calendar-months{width:100%;height:100%;overflow:hidden;position:relative}.picker-calendar-months-wrapper{position:relative;width:100%;height:100%;-webkit-transition:.3s;transition:.3s}.picker-calendar-month{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column;width:100%;height:100%;position:absolute;left:0;top:0}.picker-calendar-row{height:16.66666667%;height:calc(100% / 6);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;width:100%;position:relative}.picker-calendar-row:after{position:absolute;bottom:0;top:auto;height:1px;width:100%;background-color:#ccc;display:block;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar-row:after{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar-row:after{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.weui-picker-modal .picker-calendar-row:last-child:after{display:none}.picker-calendar-day{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;box-sizing:border-box;width:14.28571429%;width:calc(100% / 7);text-align:center;color:#3d4145;font-size:15px;cursor:pointer}.picker-calendar-day.picker-calendar-day-next,.picker-calendar-day.picker-calendar-day-prev{color:#ccc}.picker-calendar-day.picker-calendar-day-disabled{color:#d4d4d4;cursor:auto}.picker-calendar-day.picker-calendar-day-today span{background:#e3e3e3}.picker-calendar-day.picker-calendar-day-selected span{background:#04BE02;color:#fff}.picker-calendar-day span{display:inline-block;border-radius:100%;width:30px;height:30px;line-height:30px}.picker-calendar-month-picker,.picker-calendar-year-picker{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:50%;max-width:200px;-webkit-flex-shrink:10;-ms-flex-negative:10;flex-shrink:10}.picker-calendar-month-picker span,.picker-calendar-year-picker span{-webkit-flex-shrink:1;-ms-flex:0 1 auto;-ms-flex-negative:1;flex-shrink:1;position:relative;overflow:hidden;text-overflow:ellipsis}.picker-calendar.picker-modal-inline .picker-calendar-week-days,.popover .picker-calendar .picker-calendar-week-days{background:0 0}.swiper-button-next,.swiper-button-prev,i.icon{background-position:center;background-repeat:no-repeat}.picker-calendar.picker-modal-inline .picker-calendar-week-days:after,.picker-calendar.picker-modal-inline .picker-calendar-week-days:before,.picker-calendar.picker-modal-inline .toolbar:after,.picker-calendar.picker-modal-inline .toolbar:before,.popover .picker-calendar .picker-calendar-week-days:after,.popover .picker-calendar .picker-calendar-week-days:before,.popover .picker-calendar .toolbar:after,.popover .picker-calendar .toolbar:before{display:none}.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{content:'';position:absolute;left:0;top:0;bottom:auto;right:auto;height:1px;width:100%;background-color:#c4c4c4;display:block;z-index:15;-webkit-transform-origin:50% 0;transform-origin:50% 0}@media only screen and (-webkit-min-device-pixel-ratio:2){.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{-webkit-transform:scaleY(.5);transform:scaleY(.5)}}@media only screen and (-webkit-min-device-pixel-ratio:3){.picker-calendar.picker-modal-inline .picker-calendar-week-days~.picker-calendar-months:before,.picker-calendar.picker-modal-inline .toolbar~.picker-modal-inner .picker-calendar-months:before,.popover .picker-calendar .picker-calendar-week-days~.picker-calendar-months:before,.popover .picker-calendar .toolbar~.picker-modal-inner .picker-calendar-months:before{-webkit-transform:scaleY(.33);transform:scaleY(.33)}}.picker-calendar-month-picker,.picker-calendar-year-picker{display:block;line-height:2.2rem;-webkit-box-flex:1;-ms-flex:1;flex:1}.picker-calendar-month-picker a.icon-only,.picker-calendar-year-picker a.icon-only{min-width:36px;float:left;width:25%;height:2.2rem;line-height:2rem}.picker-calendar-month-picker .current-month-value,.picker-calendar-month-picker .current-year-value,.picker-calendar-year-picker .current-month-value,.picker-calendar-year-picker .current-year-value{float:left;width:50%;height:2.2rem}i.icon{display:inline-block;vertical-align:middle;background-size:100% auto;font-style:normal;position:relative}i.icon.icon-next,i.icon.icon-prev{width:.75rem;height:.75rem}.swiper-slide,.swiper-wrapper{width:100%;height:100%;position:relative}i.icon.icon-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%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%2304BE02'%20d%3D'M1%2C1.6l11.8%2C5.8L1%2C13.4V1.6%20M0%2C0v15l15-7.6L0%2C0L0%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}i.icon.icon-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%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%2304BE02'%20d%3D'M14%2C1.6v11.8L2.2%2C7.6L14%2C1.6%20M15%2C0L0%2C7.6L15%2C15V0L15%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}.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;-ms-flex-direction:column;flex-direction:column}.swiper-wrapper{z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-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;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{-webkit-flex-shrink:0;-ms-flex:0 0 auto;-ms-flex-negative:0;flex-shrink:0}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-webkit-transition-property:height,-webkit-transform;transition-property:height,-webkit-transform;transition-property:transform,height;transition-property:transform,height,-webkit-transform}.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;background-size:27px 44px}.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;transition:.3s;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.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;background:#04BE02}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.swiper-container-3d{-webkit-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;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: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: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: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:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-coverflow .swiper-wrapper,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.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,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-slide{visibility:hidden;-webkit-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-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-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-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none;-webkit-transition-property:opacity;transition-property:opacity}.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-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%;transform-origin:50%;-webkit-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%;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%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.weui-actionsheet{z-index:10000}.weui-popup__container,.weui-popup__overlay{position:fixed;bottom:0;left:0;right:0;width:100%;height:100%;z-index:10}.weui-popup__overlay{background-color:rgba(0,0,0,.6);opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-popup__container{display:none}.weui-popup__container.weui-popup__container--visible{display:block}.weui-popup__container .weui-cells{margin:0;text-align:left}.weui-popup__modal{width:100%;position:absolute;z-index:100;bottom:0;border-radius:0;opacity:.6;color:#3d4145;-webkit-transition-duration:.3s;transition-duration:.3s;height:100%;background:#EFEFF4;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;overflow-x:hidden;overflow-y:auto}.popup-bottom .weui-popup__modal{height:auto}.weui-popup__modal .toolbar{position:absolute;left:0;top:0;right:0;z-index:1}.weui-popup__modal .modal-content{height:100%;padding-top:2.2rem;overflow:auto;box-sizing:border-box}.weui-popup__container--visible .weui-popup__overlay{opacity:1}.weui-popup__container--visible .weui-popup__modal{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-notification{position:fixed;width:100%;min-height:3.4rem;top:-2rem;padding-top:2rem;left:0;right:0;z-index:9999;background-color:rgba(0,0,0,.85);color:#fff;font-size:.65rem;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);-webkit-transition:.4s;transition:.4s}.weui-notification.weui-notification--in{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.weui-notification.weui-notification--touching{-webkit-transition-duration:0s;transition-duration:0s}.weui-notification .weui-notification__inner{padding:.4rem .6rem 1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.weui-notification .weui-notification__content{width:100%;margin:0 .4rem}.weui-notification .weui-notification__title{font-weight:700}.weui-notification .weui-notification__text{line-height:1}.weui-notification .weui-notification__media{height:1rem;width:1rem}.weui-notification .weui-notification__media img{width:100%}.weui-notification .weui-notification__handle-bar{position:absolute;bottom:.2rem;left:50%;-webkit-transform:translate3d(-50%,0,0);transform:translate3d(-50%,0,0);width:2rem;height:.3rem;border-radius:.15rem;background:#fff;opacity:.5}.weui-photo-browser-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:#000;display:none;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-photo-browser-modal.weui-photo-browser-modal-visible{opacity:1}.weui-photo-browser-modal .swiper-container{height:100%;-webkit-transform:scale(.2);transform:scale(.2);-webkit-transition:-webkit-transform .5s;transition:-webkit-transform .5s;transition:transform .5s;transition:transform .5s,-webkit-transform .5s}.weui-photo-browser-modal .swiper-container .swiper-pagination-bullet{background:#fff;visibility:hidden}.weui-photo-browser-modal .swiper-container.swiper-container-visible{-webkit-transform:scale(1);transform:scale(1)}.weui-photo-browser-modal .swiper-container.swiper-container-visible .swiper-pagination-bullet{visibility:visible;-webkit-transition-property:visibility;transition-property:visibility;-webkit-transition-delay:.5s;transition-delay:.5s}.weui-photo-browser-modal .swiper-container .swiper-pagination{bottom:10px;left:0;width:100%}.weui-photo-browser-modal .photo-container{height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:hidden}.weui-photo-browser-modal .photo-container img{max-width:100%;margin-top:-30px}.weui-photo-browser-modal .caption{position:absolute;bottom:40px;left:0;right:0;color:#fff;text-align:center;padding:0 12px;min-height:3rem;font-size:14px;z-index:10;-webkit-transition:opacity .3s;transition:opacity .3s;-webkit-transition-delay:.5s;transition-delay:.5s;opacity:0}.weui-photo-browser-modal .caption .caption-item{display:none;opacity:0;-webkit-transition:opacity .15s;transition:opacity .15s}.weui-photo-browser-modal .caption .caption-item.active{display:block;opacity:1}.weui-photo-browser-modal .swiper-container-visible .caption{opacity:1}.color-primary{color:#04BE02}.color-danger,.color-error{color:#f6383a}.color-warning{color:#f60}.color-success{color:#4cd964}.bg-danger,.bg-error,.bg-primary,.bg-success,.bg-warning{color:#fff}.bg-primary{background-color:#04BE02}.bg-danger,.bg-error{background-color:#f6383a}.bg-warning{background-color:#f60}.bg-success{background-color:#4cd964}.weui-toptips{z-index:100;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.weui-toptips.weui-toptips_visible{opacity:1}.weui-icon_toast{font-size:55px;color:#fff;margin-bottom:6px}.weui-toast--forbidden .weui-icon_toast{color:#f6383a}.weui-toast--text{min-height:initial;font-size:18px;padding:8px 16px;width:auto;top:40%}.weui-toast--text .weui-icon_toast{display:none}.weui-count{display:inline-block;height:25px;line-height:25px}.weui-count .weui-count__btn{height:21px;width:21px;line-height:21px;display:inline-block;position:relative;border:1px solid #04BE02;border-radius:50%;vertical-align:-6px}.weui-count .weui-count__btn:after,.weui-count .weui-count__btn:before{content:" ";position:absolute;height:1px;width:11px;background-color:#04BE02;left:50%;top:50%;margin-left:-5.5px}.weui-count .weui-count__btn:after{height:11px;width:1px;margin-top:-5.5px;margin-left:-1px}.weui-count .weui-count__decrease:after{display:none}.weui-count .weui-count__increase{background-color:#04BE02}.weui-count .weui-count__increase:after,.weui-count .weui-count__increase:before{background-color:#fff}.weui-count .weui-count__number{background-color:transparent;font-size:.8rem;border:0;width:1.3rem;text-align:center;color:#5f646e}.weui-panel .weui-media-box__title-after{color:#9b9b9b;font-size:.65rem;float:right}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/weui.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/weui.min.css
new file mode 100755
index 0000000..1371e18
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/css/weui.min.css
@@ -0,0 +1,5 @@
+/*!
+ * WeUI v1.1.3 (https://github.com/weui/weui)
+ * Copyright 2018 Tencent, Inc.
+ * Licensed under the MIT license
+ */html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{line-height:1.6;font-family:-apple-system-font,Helvetica Neue,sans-serif}*{margin:0;padding:0}a img{border:0}a{text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}@font-face{font-weight:400;font-style:normal;font-family:weui;src:url('data:application/octet-stream;base64,AAEAAAALAIAAAwAwR1NVQrD+s+0AAAE4AAAAQk9TLzJAKEx+AAABfAAAAFZjbWFw65cFHQAAAhwAAAJQZ2x5ZvCRR/EAAASUAAAKtGhlYWQMPROtAAAA4AAAADZoaGVhCCwD+gAAALwAAAAkaG10eEJo//8AAAHUAAAASGxvY2EYqhW4AAAEbAAAACZtYXhwASEAVQAAARgAAAAgbmFtZeNcHtgAAA9IAAAB5nBvc3T6bLhLAAARMAAAAOYAAQAAA+gAAABaA+j/////A+kAAQAAAAAAAAAAAAAAAAAAABIAAQAAAAEAACbZbxtfDzz1AAsD6AAAAADUm2dvAAAAANSbZ2///wAAA+kD6gAAAAgAAgAAAAAAAAABAAAAEgBJAAUAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKAB4ALAABREZMVAAIAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAAAAQOwAZAABQAIAnoCvAAAAIwCegK8AAAB4AAxAQIAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA6gHqEQPoAAAAWgPqAAAAAAABAAAAAAAAAAAAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+gAAAPoAAAD6AAAA+j//wPoAAAD6AAAAAAABQAAAAMAAAAsAAAABAAAAXQAAQAAAAAAbgADAAEAAAAsAAMACgAAAXQABABCAAAABAAEAAEAAOoR//8AAOoB//8AAAABAAQAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAAAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAANwAAAAAAAAAEQAA6gEAAOoBAAAAAQAA6gIAAOoCAAAAAgAA6gMAAOoDAAAAAwAA6gQAAOoEAAAABAAA6gUAAOoFAAAABQAA6gYAAOoGAAAABgAA6gcAAOoHAAAABwAA6ggAAOoIAAAACAAA6gkAAOoJAAAACQAA6goAAOoKAAAACgAA6gsAAOoLAAAACwAA6gwAAOoMAAAADAAA6g0AAOoNAAAADQAA6g4AAOoOAAAADgAA6g8AAOoPAAAADwAA6hAAAOoQAAAAEAAA6hEAAOoRAAAAEQAAAAAARgCMANIBJAF4AcQCMgJgAqgC/ANIA6YD/gROBKAE9AVaAAAAAgAAAAADrwOtABQAKQAAASIHBgcGFBcWFxYyNzY3NjQnJicmAyInJicmNDc2NzYyFxYXFhQHBgcGAfV4Z2Q7PDw7ZGfwZmQ7PDw7ZGZ4bl5bNjc3Nlte215bNjc3NlteA608O2Rn8GdjOzw8O2Nn8GdkOzz8rzc1W17bXlw1Nzc1XF7bXls1NwAAAAACAAAAAAOzA7MAFwAtAAABIgcGBwYVFBcWFxYzMjc2NzY1NCcmJyYTBwYiLwEmNjsBETQ2OwEyFhURMzIWAe52Z2Q7PT07ZGd2fGpmOz4+O2ZpIXYOKA52Dg0XXQsHJgcLXRcNA7M+O2ZqfHZnZDs9PTtkZ3Z9aWY7Pv3wmhISmhIaARcICwsI/ukaAAMAAAAAA+UD5QAXACMALAAAASIHBgcGFRQXFhcWMzI3Njc2NTQnJicmAxQrASI1AzQ7ATIHJyImNDYyFhQGAe6Ecm9BRERBb3KEiXZxQkREQnF1aQIxAwgCQgMBIxIZGSQZGQPkREJxdomEcm9BRERBb3KEinVxQkT9HQICAWICAjEZIxkZIxkAAAAAAgAAAAADsQPkABkALgAAAQYHBgc2BREUFxYXFhc2NzY3NjURJBcmJyYTAQYvASY/ATYyHwEWNjclNjIfARYB9VVVQk+v/tFHPmxebGxdbT1I/tGvT0JVo/7VBASKAwMSAQUBcQEFAgESAgUBEQQD4xMYEhk3YP6sjnVlSD8cHD9IZXWOAVRgNxkSGP62/tkDA48EBBkCAVYCAQHlAQIQBAAAAAADAAAAAAOxA+QAGwAqADMAAAEGBwYHBgcGNxEUFxYXFhc2NzY3NjURJBcmJyYHMzIWFQMUBisBIicDNDYTIiY0NjIWFAYB9UFBODssO38gRz5sXmxsXW09SP7YqFBBVW80BAYMAwImBQELBh4PFhYeFRUD5A8SDhIOEikK/q2PdWRJPh0dPklkdY8BU141GRIY/AYE/sYCAwUBOgQG/kAVHxUVHxUAAAACAAAAAAPkA+QAFwAtAAABIgcGBwYVFBcWFxYzMjc2NzY1NCcmJyYTAQYiLwEmPwE2Mh8BFjI3ATYyHwEWAe6Ecm9BQ0NCbnODiXVxQkREQnF1kf6gAQUBowMDFgEFAYUCBQEBQwIFARUEA+NEQnF1iYNzbkJDQ0FvcoSJdXFCRP6j/qUBAagEBR4CAWYBAQENAgIVBAAAAAQAAAAAA68DrQAUACkAPwBDAAABIgcGBwYUFxYXFjI3Njc2NCcmJyYDIicmJyY0NzY3NjIXFhcWFAcGBwYTBQ4BLwEmBg8BBhYfARYyNwE+ASYiFzAfAQH1eGdkOzw8O2Rn8GZkOzw8O2RmeG5eWzY3NzZbXtteWzY3NzZbXmn+9gYSBmAGDwUDBQEGfQUQBgElBQELEBUBAQOtPDtkZ/BnYzs8PDtjZ/BnZDs8/K83NVte215cNTc3NVxe215bNTcCJt0FAQVJBQIGBAcRBoAGBQEhBQ8LBAEBAAABAAAAAAO7AzoAFwAAEy4BPwE+AR8BFjY3ATYWFycWFAcBBiInPQoGBwUHGgzLDCELAh0LHwsNCgr9uQoeCgGzCyEOCw0HCZMJAQoBvgkCCg0LHQv9sQsKAAAAAAIAAAAAA+UD5gAXACwAAAEiBwYHBhUUFxYXFjMyNzY3NjU0JyYnJhMHBi8BJicmNRM0NjsBMhYVExceAQHvhHJvQUNDQm5zg4l1cUJEREJxdVcQAwT6AwIEEAMCKwIDDsUCAQPlREJxdYmDc25CQ0NBb3KEiXVxQkT9VhwEAncCAgMGAXoCAwMC/q2FAgQAAAQAAAAAA68DrQADABgALQAzAAABMB8BAyIHBgcGFBcWFxYyNzY3NjQnJicmAyInJicmNDc2NzYyFxYXFhQHBgcGAyMVMzUjAuUBAfJ4Z2Q7PDw7ZGfwZmQ7PDw7ZGZ4bl5bNjc3Nlte215bNjc3NltemyT92QKDAQEBLDw7ZGfwZ2M7PDw7Y2fwZ2Q7PPyvNzVbXtteXDU3NzVcXtteWzU3AjH9JAAAAAMAAAAAA+QD5AAXACcAMAAAASIHBgcGFRQXFhcWMzI3Njc2NTQnJicmAzMyFhUDFAYrASImNQM0NhMiJjQ2MhYUBgHuhHJvQUNDQm5zg4l1cUJEREJxdZ42BAYMAwInAwMMBh8PFhYeFhYD40RCcXWJg3NuQkNDQW9yhIl1cUJE/vYGBf7AAgMDAgFABQb+NhYfFhYfFgAABAAAAAADwAPAAAgAEgAoAD0AAAEyNjQmIgYUFhcjFTMRIxUzNSMDIgcGBwYVFBYXFjMyNzY3NjU0Jy4BAyInJicmNDc2NzYyFxYXFhQHBgcGAfQYISEwISFRjzk5yTorhG5rPT99am+DdmhlPD4+PMyFbV5bNTc3NVte2l5bNTc3NVteAqAiLyIiLyI5Hf7EHBwCsT89a26Ed8w8Pj48ZWh2g29qffyjNzVbXtpeWzU3NzVbXtpeWzU3AAADAAAAAAOoA6gACwAgADUAAAEHJwcXBxc3FzcnNwMiBwYHBhQXFhcWMjc2NzY0JyYnJgMiJyYnJjQ3Njc2MhcWFxYUBwYHBgKOmpocmpocmpocmpq2dmZiOjs7OmJm7GZiOjs7OmJmdmtdWTQ2NjRZXdZdWTQ2NjRZXQKqmpocmpocmpocmpoBGTs6YmbsZmI6Ozs6YmbsZmI6O/zCNjRZXdZdWTQ2NjRZXdZdWTQ2AAMAAAAAA+kD6gAaAC8AMAAAAQYHBiMiJyYnJjQ3Njc2MhcWFxYVFAcGBwEHATI3Njc2NCcmJyYiBwYHBhQXFhcWMwKONUBCR21dWjU3NzVaXdpdWzU2GBcrASM5/eBXS0grKysrSEuuSkkqLCwqSUpXASMrFxg2NVtd2l1aNTc3NVpdbUdCQDX+3jkBGSsrSEuuSkkqLCwqSUquS0grKwAC//8AAAPoA+gAFAAwAAABIgcGBwYQFxYXFiA3Njc2ECcmJyYTFg4BIi8BBwYuATQ/AScmPgEWHwE3Nh4BBg8BAfSIdHFDRERDcXQBEHRxQ0REQ3F0SQoBFBsKoqgKGxMKqKIKARQbCqKoChsUAQqoA+hEQ3F0/vB0cUNERENxdAEQdHFDRP1jChsTCqiiCgEUGwqiqAobFAEKqKIKARQbCqIAAAIAAAAAA+QD5AAXADQAAAEiBwYHBhUUFxYXFjMyNzY3NjU0JyYnJhMUBiMFFxYUDwEGLwEuAT8BNh8BFhQPAQUyFh0BAe6Ecm9BQ0NCbnODiXVxQkREQnF1fwQC/pGDAQEVAwTsAgEC7AQEFAIBhAFwAgMD40RCcXWJg3NuQkNDQW9yhIl1cUJE/fYCAwuVAgQCFAQE0AIFAtEEBBQCBQGVCwMDJwAAAAUAAAAAA9QD0wAjACcANwBHAEgAAAERFAYjISImNREjIiY9ATQ2MyE1NDYzITIWHQEhMhYdARQGIyERIREHIgYVERQWOwEyNjURNCYjISIGFREUFjsBMjY1ETQmKwEDeyYb/XYbJkMJDQ0JAQYZEgEvExkBBgkNDQn9CQJc0QkNDQktCQ0NCf7sCQ0NCS0JDQ0JLQMi/TQbJiYbAswMCiwJDS4SGRkSLg0JLAoM/UwCtGsNCf5NCQ0NCQGzCQ0NCf5NCQ0NCQGzCQ0AAAAAEADGAAEAAAAAAAEABAAAAAEAAAAAAAIABwAEAAEAAAAAAAMABAALAAEAAAAAAAQABAAPAAEAAAAAAAUACwATAAEAAAAAAAYABAAeAAEAAAAAAAoAKwAiAAEAAAAAAAsAEwBNAAMAAQQJAAEACABgAAMAAQQJAAIADgBoAAMAAQQJAAMACAB2AAMAAQQJAAQACAB+AAMAAQQJAAUAFgCGAAMAAQQJAAYACACcAAMAAQQJAAoAVgCkAAMAAQQJAAsAJgD6d2V1aVJlZ3VsYXJ3ZXVpd2V1aVZlcnNpb24gMS4wd2V1aUdlbmVyYXRlZCBieSBzdmcydHRmIGZyb20gRm9udGVsbG8gcHJvamVjdC5odHRwOi8vZm9udGVsbG8uY29tAHcAZQB1AGkAUgBlAGcAdQBsAGEAcgB3AGUAdQBpAHcAZQB1AGkAVgBlAHIAcwBpAG8AbgAgADEALgAwAHcAZQB1AGkARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAgAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAQIBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETAAZjaXJjbGUIZG93bmxvYWQEaW5mbwxzYWZlX3N1Y2Nlc3MJc2FmZV93YXJuB3N1Y2Nlc3MOc3VjY2Vzcy1jaXJjbGURc3VjY2Vzcy1uby1jaXJjbGUHd2FpdGluZw53YWl0aW5nLWNpcmNsZQR3YXJuC2luZm8tY2lyY2xlBmNhbmNlbAZzZWFyY2gFY2xlYXIEYmFjawZkZWxldGUAAAAA') format('truetype')}[class*=" weui-icon-"],[class^=weui-icon-]{display:inline-block;vertical-align:middle;font:normal normal normal 14px/1 weui;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}[class*=" weui-icon-"]:before,[class^=weui-icon-]:before{display:inline-block;margin-left:.2em;margin-right:.2em}.weui-icon-circle:before{content:"\EA01"}.weui-icon-download:before{content:"\EA02"}.weui-icon-info:before{content:"\EA03"}.weui-icon-safe-success:before{content:"\EA04"}.weui-icon-safe-warn:before{content:"\EA05"}.weui-icon-success:before{content:"\EA06"}.weui-icon-success-circle:before{content:"\EA07"}.weui-icon-success-no-circle:before{content:"\EA08"}.weui-icon-waiting:before{content:"\EA09"}.weui-icon-waiting-circle:before{content:"\EA0A"}.weui-icon-warn:before{content:"\EA0B"}.weui-icon-info-circle:before{content:"\EA0C"}.weui-icon-cancel:before{content:"\EA0D"}.weui-icon-search:before{content:"\EA0E"}.weui-icon-clear:before{content:"\EA0F"}.weui-icon-back:before{content:"\EA10"}.weui-icon-delete:before{content:"\EA11"}[class*=" weui-icon_"]:before,[class^=weui-icon_]:before{margin:0}.weui-icon-success{font-size:23px;color:#09bb07}.weui-icon-waiting{font-size:23px;color:#10aeff}.weui-icon-warn{font-size:23px;color:#f43530}.weui-icon-info{font-size:23px;color:#10aeff}.weui-icon-success-circle,.weui-icon-success-no-circle{font-size:23px;color:#09bb07}.weui-icon-waiting-circle{font-size:23px;color:#10aeff}.weui-icon-circle{font-size:23px;color:#c9c9c9}.weui-icon-download,.weui-icon-info-circle{font-size:23px;color:#09bb07}.weui-icon-safe-success{color:#09bb07}.weui-icon-safe-warn{color:#ffbe00}.weui-icon-cancel{color:#f43530;font-size:22px}.weui-icon-clear,.weui-icon-search{color:#b2b2b2;font-size:14px}.weui-icon-delete.weui-icon_gallery-delete{color:#fff;font-size:22px}.weui-icon_msg{font-size:93px}.weui-icon_msg.weui-icon-warn{color:#f76260}.weui-icon_msg-primary{font-size:93px}.weui-icon_msg-primary.weui-icon-warn{color:#ffbe00}.weui-btn{position:relative;display:block;margin-left:auto;margin-right:auto;padding-left:14px;padding-right:14px;box-sizing:border-box;font-size:18px;text-align:center;text-decoration:none;color:#fff;line-height:2.55555556;border-radius:5px;-webkit-tap-highlight-color:rgba(0,0,0,0);overflow:hidden}.weui-btn:after{content:" ";width:200%;height:200%;position:absolute;top:0;left:0;border:1px solid rgba(0,0,0,.2);-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;box-sizing:border-box;border-radius:10px}.weui-btn_inline{display:inline-block}.weui-btn_default{color:#000;background-color:#f8f8f8}.weui-btn_default:not(.weui-btn_disabled):visited{color:#000}.weui-btn_default:not(.weui-btn_disabled):active{color:rgba(0,0,0,.6);background-color:#dedede}.weui-btn_primary{background-color:#1aad19}.weui-btn_primary:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_primary:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#179b16}.weui-btn_warn{background-color:#e64340}.weui-btn_warn:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_warn:not(.weui-btn_disabled):active{color:hsla(0,0%,100%,.6);background-color:#ce3c39}.weui-btn_disabled{color:hsla(0,0%,100%,.6)}.weui-btn_disabled.weui-btn_default{color:rgba(0,0,0,.3);background-color:#f7f7f7}.weui-btn_disabled.weui-btn_primary{background-color:#9ed99d}.weui-btn_disabled.weui-btn_warn{background-color:#ec8b89}.weui-btn_loading .weui-loading{margin:-.2em .34em 0 0}.weui-btn_loading.weui-btn_primary,.weui-btn_loading.weui-btn_warn{color:hsla(0,0%,100%,.6)}.weui-btn_loading.weui-btn_primary{background-color:#179b16}.weui-btn_loading.weui-btn_warn{background-color:#ce3c39}.weui-btn_plain-primary{color:#1aad19;border:1px solid #1aad19}.weui-btn_plain-primary:not(.weui-btn_plain-disabled):active{color:rgba(26,173,25,.6);border-color:rgba(26,173,25,.6)}.weui-btn_plain-primary:after{border-width:0}.weui-btn_plain-default{color:#353535;border:1px solid #353535}.weui-btn_plain-default:not(.weui-btn_plain-disabled):active{color:rgba(53,53,53,.6);border-color:rgba(53,53,53,.6)}.weui-btn_plain-default:after{border-width:0}.weui-btn_plain-disabled{color:rgba(0,0,0,.2);border-color:rgba(0,0,0,.2)}button.weui-btn,input.weui-btn{width:100%;border-width:0;outline:0;-webkit-appearance:none}button.weui-btn:focus,input.weui-btn:focus{outline:0}button.weui-btn_inline,button.weui-btn_mini,input.weui-btn_inline,input.weui-btn_mini{width:auto}button.weui-btn_plain-default,button.weui-btn_plain-primary,input.weui-btn_plain-default,input.weui-btn_plain-primary{border-width:1px;background-color:transparent}.weui-btn_mini{display:inline-block;padding:0 1.32em;line-height:2.3;font-size:13px}.weui-btn+.weui-btn{margin-top:15px}.weui-btn.weui-btn_inline+.weui-btn.weui-btn_inline{margin-top:auto;margin-left:15px}.weui-btn-area{margin:1.17647059em 15px .3em}.weui-btn-area_inline{display:-webkit-box;display:-webkit-flex;display:flex}.weui-btn-area_inline .weui-btn{margin-top:auto;margin-right:15px;width:100%;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-btn-area_inline .weui-btn:last-child{margin-right:0}.weui-cells{margin-top:1.17647059em;background-color:#fff;line-height:1.47058824;font-size:17px;overflow:hidden;position:relative}.weui-cells:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells:after,.weui-cells:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5;z-index:2}.weui-cells:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-cells__title{margin-top:.77em;margin-bottom:.3em;padding-left:15px;padding-right:15px;color:#999;font-size:14px}.weui-cells__title+.weui-cells{margin-top:0}.weui-cells__tips{margin-top:.3em;color:#999;padding-left:15px;padding-right:15px;font-size:14px}.weui-cell{padding:10px 15px;position:relative;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px;z-index:2}.weui-cell:first-child:before{display:none}.weui-cell_primary{-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start}.weui-cell__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-cell__ft{text-align:right;color:#999}.weui-cell_swiped{display:block;padding:0}.weui-cell_swiped>.weui-cell__bd{position:relative;z-index:1;background-color:#fff}.weui-cell_swiped>.weui-cell__ft{position:absolute;right:0;top:0;bottom:0;display:-webkit-box;display:-webkit-flex;display:flex;color:#fff}.weui-swiped-btn{display:block;padding:10px 1em;line-height:1.47058824;color:inherit}.weui-swiped-btn_default{background-color:#c7c7cc}.weui-swiped-btn_warn{background-color:#ff3b30}.weui-cell_access{-webkit-tap-highlight-color:rgba(0,0,0,0);color:inherit}.weui-cell_access:active{background-color:#ececec}.weui-cell_access .weui-cell__ft{padding-right:13px;position:relative}.weui-cell_access .weui-cell__ft:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;margin-top:-4px;right:2px}.weui-cell_link{color:#586c94;font-size:14px}.weui-cell_link:first-child:before{display:block}.weui-check__label{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-check__label:active{background-color:#ececec}.weui-check{position:absolute;left:-9999em}.weui-cells_radio .weui-cell__ft{padding-left:.35em}.weui-cells_radio .weui-check+.weui-icon-checked{min-width:16px}.weui-cells_radio .weui-check:checked+.weui-icon-checked:before{display:block;content:'\EA08';color:#09bb07;font-size:16px}.weui-cells_checkbox .weui-cell__hd{padding-right:.35em}.weui-cells_checkbox .weui-icon-checked:before{content:'\EA01';color:#c9c9c9;font-size:23px;display:block}.weui-cells_checkbox .weui-check:checked+.weui-icon-checked:before{content:'\EA06';color:#09bb07}.weui-label{display:block;width:105px;word-wrap:break-word;word-break:break-all}.weui-input{width:100%;border:0;outline:0;-webkit-appearance:none;background-color:transparent;font-size:inherit;color:inherit;height:1.47058824em;line-height:1.47058824}.weui-input::-webkit-inner-spin-button,.weui-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.weui-textarea{display:block;border:0;resize:none;width:100%;color:inherit;font-size:1em;line-height:inherit;outline:0}.weui-textarea-counter{color:#b2b2b2;text-align:right}.weui-cell_warn .weui-textarea-counter{color:#e64340}.weui-toptips{display:none;position:fixed;-webkit-transform:translateZ(0);transform:translateZ(0);top:0;left:0;right:0;padding:5px;font-size:14px;text-align:center;color:#fff;z-index:5000;word-wrap:break-word;word-break:break-all}.weui-toptips_warn{background-color:#e64340}.weui-cells_form .weui-cell__ft{font-size:0}.weui-cells_form .weui-icon-warn{display:none}.weui-cells_form input,.weui-cells_form label[for],.weui-cells_form textarea{-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-cell_warn{color:#e64340}.weui-cell_warn .weui-icon-warn{display:inline-block}.weui-form-preview{position:relative;background-color:#fff}.weui-form-preview:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview:after,.weui-form-preview:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-form-preview:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__hd{position:relative;padding:10px 15px;text-align:right;line-height:2.5em}.weui-form-preview__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-form-preview__hd .weui-form-preview__value{font-style:normal;font-size:1.6em}.weui-form-preview__bd{padding:10px 15px;font-size:.9em;text-align:right;color:#999;line-height:2}.weui-form-preview__ft{position:relative;line-height:50px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-form-preview__ft:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-form-preview__item{overflow:hidden}.weui-form-preview__label{float:left;margin-right:1em;min-width:4em;color:#999;text-align:justify;text-align-last:justify}.weui-form-preview__value{display:block;overflow:hidden;word-break:normal;word-wrap:break-word}.weui-form-preview__btn{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}button.weui-form-preview__btn{background-color:transparent;border:0;outline:0;line-height:inherit;font-size:inherit}.weui-form-preview__btn:active{background-color:#eee}.weui-form-preview__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-form-preview__btn:first-child:after{display:none}.weui-form-preview__btn_default{color:#999}.weui-form-preview__btn_primary{color:#0bb20c}.weui-cell_select{padding:0}.weui-cell_select .weui-select{padding-right:30px}.weui-cell_select .weui-cell__bd:after{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-select{-webkit-appearance:none;border:0;outline:0;background-color:transparent;width:100%;font-size:inherit;height:45px;line-height:45px;position:relative;z-index:1;padding-left:15px}.weui-cell_select-before{padding-right:15px}.weui-cell_select-before .weui-select{width:105px;box-sizing:border-box}.weui-cell_select-before .weui-cell__hd{position:relative}.weui-cell_select-before .weui-cell__hd:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-cell_select-before .weui-cell__hd:before{content:" ";display:inline-block;height:6px;width:6px;border-width:2px 2px 0 0;border-color:#c8c8cd;border-style:solid;-webkit-transform:matrix(.71,.71,-.71,.71,0,0);transform:matrix(.71,.71,-.71,.71,0,0);position:relative;top:-2px;position:absolute;top:50%;right:15px;margin-top:-4px}.weui-cell_select-before .weui-cell__bd{padding-left:15px}.weui-cell_select-before .weui-cell__bd:after{display:none}.weui-cell_select-after{padding-left:15px}.weui-cell_select-after .weui-select{padding-left:0}.weui-cell_vcode{padding-top:0;padding-right:0;padding-bottom:0}.weui-vcode-btn,.weui-vcode-img{margin-left:5px;height:45px;vertical-align:middle}.weui-vcode-btn{display:inline-block;padding:0 .6em 0 .7em;border-left:1px solid #e5e5e5;line-height:45px;font-size:17px;color:#3cc51f}button.weui-vcode-btn{background-color:transparent;border-top:0;border-right:0;border-bottom:0;outline:0}.weui-vcode-btn:active{color:#52a341}.weui-gallery{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000;z-index:1000}.weui-gallery__img{position:absolute;top:0;right:0;bottom:60px;left:0;background:50% no-repeat;background-size:contain}.weui-gallery__opr{position:absolute;right:0;bottom:0;left:0;background-color:#0d0d0d;color:#fff;line-height:60px;text-align:center}.weui-gallery__del{display:block}.weui-cell_switch{padding-top:6.5px;padding-bottom:6.5px}.weui-switch{-webkit-appearance:none;appearance:none}.weui-switch,.weui-switch-cp__box{position:relative;width:52px;height:32px;border:1px solid #dfdfdf;outline:0;border-radius:16px;box-sizing:border-box;background-color:#dfdfdf;-webkit-transition:background-color .1s,border .1s;transition:background-color .1s,border .1s}.weui-switch-cp__box:before,.weui-switch:before{content:" ";position:absolute;top:0;left:0;width:50px;height:30px;border-radius:15px;background-color:#fdfdfd;-webkit-transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:-webkit-transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1);transition:transform .35s cubic-bezier(.45,1,.4,1),-webkit-transform .35s cubic-bezier(.45,1,.4,1)}.weui-switch-cp__box:after,.weui-switch:after{content:" ";position:absolute;top:0;left:0;width:30px;height:30px;border-radius:15px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);-webkit-transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35);transition:transform .35s cubic-bezier(.4,.4,.25,1.35),-webkit-transform .35s cubic-bezier(.4,.4,.25,1.35)}.weui-switch-cp__input:checked~.weui-switch-cp__box,.weui-switch:checked{border-color:#04be02;background-color:#04be02}.weui-switch-cp__input:checked~.weui-switch-cp__box:before,.weui-switch:checked:before{-webkit-transform:scale(0);transform:scale(0)}.weui-switch-cp__input:checked~.weui-switch-cp__box:after,.weui-switch:checked:after{-webkit-transform:translateX(20px);transform:translateX(20px)}.weui-switch-cp__input{position:absolute;left:-9999px}.weui-switch-cp__box{display:block}.weui-uploader__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding-bottom:10px;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-uploader__title{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-uploader__info{color:#b2b2b2}.weui-uploader__bd{margin-bottom:-4px;margin-right:-9px;overflow:hidden}.weui-uploader__files{list-style:none}.weui-uploader__file{float:left;margin-right:9px;margin-bottom:9px;width:79px;height:79px;background:no-repeat 50%;background-size:cover}.weui-uploader__file_status{position:relative}.weui-uploader__file_status:before{content:" ";position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.5)}.weui-uploader__file_status .weui-uploader__file-content{display:block}.weui-uploader__file-content{display:none;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#fff}.weui-uploader__file-content .weui-icon-warn{display:inline-block}.weui-uploader__input-box{float:left;position:relative;margin-right:9px;margin-bottom:9px;width:77px;height:77px;border:1px solid #d9d9d9}.weui-uploader__input-box:after,.weui-uploader__input-box:before{content:" ";position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#d9d9d9}.weui-uploader__input-box:before{width:2px;height:39.5px}.weui-uploader__input-box:after{width:39.5px;height:2px}.weui-uploader__input-box:active{border-color:#999}.weui-uploader__input-box:active:after,.weui-uploader__input-box:active:before{background-color:#999}.weui-uploader__input{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;opacity:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-msg{padding-top:36px;text-align:center}.weui-msg__icon-area{margin-bottom:30px}.weui-msg__text-area{margin-bottom:25px;padding:0 20px}.weui-msg__text-area a{color:#586c94}.weui-msg__title{margin-bottom:5px;font-weight:400;font-size:20px}.weui-msg__desc,.weui-msg__title{word-wrap:break-word;word-break:break-all}.weui-msg__desc{font-size:14px;color:#999}.weui-msg__opr-area{margin-bottom:25px}.weui-msg__extra-area{margin-bottom:15px;font-size:14px;color:#999}.weui-msg__extra-area a{color:#586c94}@media screen and (min-height:438px){.weui-msg__extra-area{position:fixed;left:0;bottom:0;width:100%;text-align:center}}@media only screen and (device-width:375px) and (device-height:812px) and (-webkit-device-pixel-ratio:3){.weui-msg__extra-area{margin-bottom:49px}}.weui-article{padding:20px 15px;font-size:15px}.weui-article section{margin-bottom:1.5em}.weui-article h1{font-size:18px;font-weight:400;margin-bottom:.9em}.weui-article h2{font-size:16px}.weui-article h2,.weui-article h3{font-weight:400;margin-bottom:.34em}.weui-article h3{font-size:15px}.weui-article *{max-width:100%;box-sizing:border-box;word-wrap:break-word}.weui-article p{margin:0 0 .8em}.weui-tabbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;bottom:0;width:100%;background-color:#f7f7fa}.weui-tabbar:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #c0bfc4;color:#c0bfc4;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-tabbar__item{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:5px 0 0;font-size:0;color:#999;text-align:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon>i,.weui-tabbar__item.weui-bar__item_on .weui-tabbar__label{color:#09bb07}.weui-tabbar__icon{display:inline-block;width:27px;height:27px}.weui-tabbar__icon>i,i.weui-tabbar__icon{font-size:24px;color:#999}.weui-tabbar__icon img{width:100%;height:100%}.weui-tabbar__label{text-align:center;color:#999;font-size:10px;line-height:1.8}.weui-navbar{display:-webkit-box;display:-webkit-flex;display:flex;position:absolute;z-index:500;top:0;width:100%;background-color:#fafafa}.weui-navbar:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #ccc;color:#ccc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-navbar+.weui-tab__panel{padding-top:50px;padding-bottom:0}.weui-navbar__item{position:relative;display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;padding:13px 0;text-align:center;font-size:15px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.weui-navbar__item:active{background-color:#ededed}.weui-navbar__item.weui-bar__item_on{background-color:#eaeaea}.weui-navbar__item:after{content:" ";position:absolute;right:0;top:0;width:1px;bottom:0;border-right:1px solid #ccc;color:#ccc;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-navbar__item:last-child:after{display:none}.weui-tab{position:relative;height:100%}.weui-tab__panel{box-sizing:border-box;height:100%;padding-bottom:50px;overflow:auto;-webkit-overflow-scrolling:touch}.weui-tab__content{display:none}.weui-progress{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-progress__bar{background-color:#ebebeb;height:3px;-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-progress__inner-bar{width:0;height:100%;background-color:#09bb07}.weui-progress__opr{display:block;margin-left:15px;font-size:0}.weui-panel{background-color:#fff;margin-top:10px;position:relative;overflow:hidden}.weui-panel:first-child{margin-top:0}.weui-panel:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel:after,.weui-panel:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-panel:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-panel__hd{padding:14px 15px 10px;color:#999;font-size:13px;position:relative}.weui-panel__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box{padding:15px;position:relative}.weui-media-box:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5);left:15px}.weui-media-box:first-child:before{display:none}a.weui-media-box{color:#000;-webkit-tap-highlight-color:rgba(0,0,0,0)}a.weui-media-box:active{background-color:#ececec}.weui-media-box__title{font-weight:400;font-size:17px;width:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;word-wrap:break-word;word-break:break-all}.weui-media-box__desc{color:#999;font-size:13px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-media-box__info{margin-top:15px;padding-bottom:5px;font-size:13px;color:#cecece;line-height:1em;list-style:none;overflow:hidden}.weui-media-box__info__meta{float:left;padding-right:1em}.weui-media-box__info__meta_extra{padding-left:1em;border-left:1px solid #cecece}.weui-media-box_text .weui-media-box__title{margin-bottom:8px}.weui-media-box_appmsg{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-media-box_appmsg .weui-media-box__hd{margin-right:.8em;width:60px;height:60px;line-height:60px;text-align:center}.weui-media-box_appmsg .weui-media-box__thumb{width:100%;max-height:100%;vertical-align:top}.weui-media-box_appmsg .weui-media-box__bd{-webkit-box-flex:1;-webkit-flex:1;flex:1;min-width:0}.weui-media-box_small-appmsg{padding:0}.weui-media-box_small-appmsg .weui-cells{margin-top:0}.weui-media-box_small-appmsg .weui-cells:before{display:none}.weui-grids{position:relative;overflow:hidden}.weui-grids:before{right:0;height:1px;border-top:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grids:after,.weui-grids:before{content:" ";position:absolute;left:0;top:0;color:#d9d9d9}.weui-grids:after{width:1px;bottom:0;border-left:1px solid #d9d9d9;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid{position:relative;float:left;padding:20px 10px;width:33.33333333%;box-sizing:border-box}.weui-grid:before{top:0;width:1px;border-right:1px solid #d9d9d9;-webkit-transform-origin:100% 0;transform-origin:100% 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-grid:after,.weui-grid:before{content:" ";position:absolute;right:0;bottom:0;color:#d9d9d9}.weui-grid:after{left:0;height:1px;border-bottom:1px solid #d9d9d9;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-grid:active{background-color:#ececec}.weui-grid__icon{width:28px;height:28px;margin:0 auto}.weui-grid__icon img{display:block;width:100%;height:100%}.weui-grid__icon+.weui-grid__label{margin-top:5px}.weui-grid__label{display:block;color:#000;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.weui-footer,.weui-grid__label{text-align:center;font-size:14px}.weui-footer{color:#999}.weui-footer a{color:#586c94}.weui-footer_fixed-bottom{position:fixed;bottom:.52em;left:0;right:0}.weui-footer__links{font-size:0}.weui-footer__link{display:inline-block;vertical-align:top;margin:0 .62em;position:relative;font-size:14px}.weui-footer__link:before{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #c7c7c7;color:#c7c7c7;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5);left:-.65em;top:.36em;bottom:.36em}.weui-footer__link:first-child:before{display:none}.weui-footer__text{padding:0 .34em;font-size:12px}.weui-flex{display:-webkit-box;display:-webkit-flex;display:flex}.weui-flex__item{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-dialog{position:fixed;z-index:5000;width:80%;max-width:300px;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);background-color:#fff;text-align:center;border-radius:3px;overflow:hidden}.weui-dialog__hd{padding:1.3em 1.6em .5em}.weui-dialog__title{font-weight:400;font-size:18px}.weui-dialog__bd{padding:0 1.6em .8em;min-height:40px;font-size:15px;line-height:1.3;word-wrap:break-word;word-break:break-all;color:#999}.weui-dialog__bd:first-child{padding:2.7em 20px 1.7em;color:#353535}.weui-dialog__ft{position:relative;line-height:48px;font-size:18px;display:-webkit-box;display:-webkit-flex;display:flex}.weui-dialog__ft:after{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-dialog__btn{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#3cc51f;text-decoration:none;-webkit-tap-highlight-color:rgba(0,0,0,0);position:relative}.weui-dialog__btn:active{background-color:#eee}.weui-dialog__btn:after{content:" ";position:absolute;left:0;top:0;width:1px;bottom:0;border-left:1px solid #d5d5d6;color:#d5d5d6;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleX(.5);transform:scaleX(.5)}.weui-dialog__btn:first-child:after{display:none}.weui-dialog__btn_default{color:#353535}.weui-dialog__btn_primary{color:#0bb20c}.weui-skin_android .weui-dialog{text-align:left;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-dialog__title{font-size:21px}.weui-skin_android .weui-dialog__hd{text-align:left}.weui-skin_android .weui-dialog__bd{color:#999;padding:.25em 1.6em 2em;font-size:17px;text-align:left}.weui-skin_android .weui-dialog__bd:first-child{padding:1.6em 1.6em 2em;color:#353535}.weui-skin_android .weui-dialog__ft{display:block;text-align:right;line-height:42px;font-size:16px;padding:0 1.6em .7em}.weui-skin_android .weui-dialog__ft:after{display:none}.weui-skin_android .weui-dialog__btn{display:inline-block;vertical-align:top;padding:0 .8em}.weui-skin_android .weui-dialog__btn:after{display:none}.weui-skin_android .weui-dialog__btn:active,.weui-skin_android .weui-dialog__btn:visited{background-color:rgba(0,0,0,.06)}.weui-skin_android .weui-dialog__btn:last-child{margin-right:-.8em}.weui-skin_android .weui-dialog__btn_default{color:gray}@media screen and (min-width:1024px){.weui-dialog{width:35%}}.weui-toast{position:fixed;z-index:5000;width:7.6em;min-height:7.6em;top:180px;left:50%;margin-left:-3.8em;background:hsla(0,0%,7%,.7);text-align:center;border-radius:5px;color:#fff}.weui-icon_toast{margin:22px 0 0;display:block}.weui-icon_toast.weui-icon-success-no-circle:before{color:#fff;font-size:55px}.weui-icon_toast.weui-loading{margin:30px 0 0;width:38px;height:38px;vertical-align:baseline}.weui-toast__content{margin:0 0 15px}.weui-mask{background:rgba(0,0,0,.6)}.weui-mask,.weui-mask_transparent{position:fixed;z-index:1000;top:0;right:0;left:0;bottom:0}.weui-actionsheet{position:fixed;left:0;bottom:0;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:5000;width:100%;background-color:#efeff4;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-actionsheet__title{position:relative;height:65px;padding:0 20px;line-height:1.4;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;flex-direction:column;text-align:center;font-size:14px;color:#888;background:#fcfcfd}.weui-actionsheet__title:before{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-actionsheet__title .weui-actionsheet__title-text{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.weui-actionsheet__menu{background-color:#fcfcfd}.weui-actionsheet__action{margin-top:6px;background-color:#fcfcfd}.weui-actionsheet__cell{position:relative;padding:10px 0;text-align:center;font-size:18px}.weui-actionsheet__cell:before{content:" ";position:absolute;left:0;top:0;right:0;height:1px;border-top:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-actionsheet__cell:active{background-color:#ececec}.weui-actionsheet__cell:first-child:before{display:none}.weui-skin_android .weui-actionsheet{position:fixed;left:50%;top:50%;bottom:auto;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:274px;box-sizing:border-box;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:transparent;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-skin_android .weui-actionsheet__action{display:none}.weui-skin_android .weui-actionsheet__menu{border-radius:2px;box-shadow:0 6px 30px 0 rgba(0,0,0,.1)}.weui-skin_android .weui-actionsheet__cell{padding:13px 24px;font-size:16px;line-height:1.4;text-align:left}.weui-skin_android .weui-actionsheet__cell:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.weui-skin_android .weui-actionsheet__cell:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.weui-actionsheet_toggle{-webkit-transform:translate(0);transform:translate(0)}.weui-loadmore{width:65%;margin:1.5em auto;line-height:1.6em;font-size:14px;text-align:center}.weui-loadmore__tips{display:inline-block;vertical-align:middle}.weui-loadmore_line{border-top:1px solid #e5e5e5;margin-top:2.4em}.weui-loadmore_line .weui-loadmore__tips{position:relative;top:-.9em;padding:0 .55em;background-color:#fff;color:#999}.weui-loadmore_dot .weui-loadmore__tips{padding:0 .16em}.weui-loadmore_dot .weui-loadmore__tips:before{content:" ";width:4px;height:4px;border-radius:50%;background-color:#e5e5e5;display:inline-block;position:relative;vertical-align:0;top:-.16em}.weui-badge{display:inline-block;padding:.15em .4em;min-width:8px;border-radius:18px;background-color:#f43530;color:#fff;line-height:1.2;text-align:center;font-size:12px;vertical-align:middle}.weui-badge_dot{padding:.4em;min-width:0}.weui-search-bar{position:relative;padding:8px 10px;display:-webkit-box;display:-webkit-flex;display:flex;box-sizing:border-box;background-color:#efeff4;-webkit-text-size-adjust:100%;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-search-bar:before{top:0;border-top:1px solid #d7d6dc;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar:after,.weui-search-bar:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#d7d6dc}.weui-search-bar:after{bottom:0;border-bottom:1px solid #d7d6dc;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__cancel-btn{display:block}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__label{display:none}.weui-search-bar__form{position:relative;-webkit-box-flex:1;-webkit-flex:auto;flex:auto;background-color:#efeff4}.weui-search-bar__form:after{content:'';position:absolute;left:0;top:0;width:200%;height:200%;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:0 0;transform-origin:0 0;border-radius:10px;border:1px solid #e6e6ea;box-sizing:border-box;background:#fff}.weui-search-bar__box{position:relative;padding-left:30px;padding-right:30px;height:100%;width:100%;box-sizing:border-box;z-index:1}.weui-search-bar__box .weui-search-bar__input{padding:4px 0;width:100%;height:1.42857143em;border:0;font-size:14px;line-height:1.42857143em;box-sizing:content-box;background:transparent}.weui-search-bar__box .weui-search-bar__input:focus{outline:none}.weui-search-bar__box .weui-icon-search{position:absolute;top:50%;left:10px;margin-top:-14px;line-height:28px}.weui-search-bar__box .weui-icon-clear{position:absolute;top:50%;right:0;margin-top:-14px;padding:0 10px;line-height:28px}.weui-search-bar__label{position:absolute;top:1px;right:1px;bottom:1px;left:1px;z-index:2;border-radius:3px;text-align:center;color:#9b9b9b;background:#fff}.weui-search-bar__label span{display:inline-block;font-size:14px;vertical-align:middle}.weui-search-bar__label .weui-icon-search{margin-right:5px}.weui-search-bar__cancel-btn{display:none;margin-left:10px;line-height:28px;color:#09bb07;white-space:nowrap}.weui-search-bar__input:not(:valid)~.weui-icon-clear{display:none}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none}.weui-picker{position:fixed;width:100%;left:0;bottom:0;z-index:5000;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.weui-picker__hd{display:-webkit-box;display:-webkit-flex;display:flex;padding:9px 15px;background-color:#fff;position:relative;text-align:center;font-size:17px}.weui-picker__hd:after{content:" ";position:absolute;left:0;bottom:0;right:0;height:1px;border-bottom:1px solid #e5e5e5;color:#e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__action{display:block;-webkit-box-flex:1;-webkit-flex:1;flex:1;color:#1aad19}.weui-picker__action:first-child{text-align:left;color:#888}.weui-picker__action:last-child{text-align:right}.weui-picker__bd{display:-webkit-box;display:-webkit-flex;display:flex;position:relative;background-color:#fff;height:238px;overflow:hidden}.weui-picker__group{-webkit-box-flex:1;-webkit-flex:1;flex:1;position:relative;height:100%}.weui-picker__mask{top:0;height:100%;margin:0 auto;background:-webkit-linear-gradient(top,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),-webkit-linear-gradient(bottom,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background:linear-gradient(180deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6)),linear-gradient(0deg,hsla(0,0%,100%,.95),hsla(0,0%,100%,.6));background-position:top,bottom;background-size:100% 102px;background-repeat:no-repeat;-webkit-transform:translateZ(0);transform:translateZ(0)}.weui-picker__indicator,.weui-picker__mask{position:absolute;left:0;width:100%;z-index:3}.weui-picker__indicator{height:34px;top:102px}.weui-picker__indicator:before{top:0;border-top:1px solid #e5e5e5;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__indicator:after,.weui-picker__indicator:before{content:" ";position:absolute;left:0;right:0;height:1px;color:#e5e5e5}.weui-picker__indicator:after{bottom:0;border-bottom:1px solid #e5e5e5;-webkit-transform-origin:0 100%;transform-origin:0 100%;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.weui-picker__content{position:absolute;top:0;left:0;width:100%}.weui-picker__item{padding:0;height:34px;line-height:34px;text-align:center;color:#000;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.weui-picker__item_disabled{color:#999}@-webkit-keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes a{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.weui-animate-slide-up{-webkit-animation:a ease .3s forwards;animation:a ease .3s forwards}@-webkit-keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes b{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.weui-animate-slide-down{-webkit-animation:b ease .3s forwards;animation:b ease .3s forwards}@-webkit-keyframes c{0%{opacity:0}to{opacity:1}}@keyframes c{0%{opacity:0}to{opacity:1}}.weui-animate-fade-in{-webkit-animation:c ease .3s forwards;animation:c ease .3s forwards}@-webkit-keyframes d{0%{opacity:1}to{opacity:0}}@keyframes d{0%{opacity:1}to{opacity:0}}.weui-animate-fade-out{-webkit-animation:d ease .3s forwards;animation:d ease .3s forwards}.weui-agree{display:block;padding:.5em 15px;font-size:13px}.weui-agree a{color:#586c94}.weui-agree__text{color:#999}.weui-agree__checkbox{-webkit-appearance:none;appearance:none;outline:0;font-size:0;border:1px solid #d1d1d1;background-color:#fff;border-radius:3px;width:13px;height:13px;position:relative;vertical-align:0;top:2px}.weui-agree__checkbox:checked:before{font-family:weui;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-align:center;speak:none;display:inline-block;vertical-align:middle;text-decoration:inherit;content:"\EA08";color:#09bb07;font-size:13px;position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-48%) scale(.73);transform:translate(-50%,-48%) scale(.73)}.weui-agree__checkbox:disabled{background-color:#e1e1e1}.weui-agree__checkbox:disabled:before{color:#adadad}.weui-loading{width:20px;height:20px;display:inline-block;vertical-align:middle;-webkit-animation:e 1s steps(12) infinite;animation:e 1s steps(12) infinite;background:transparent url("data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E9E9E9' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23989697' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%239B999A' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23A3A1A2' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23ABA9AA' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23B2B2B2' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23BAB8B9' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23C2C0C1' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23CBCBCB' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23D2D2D2' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23DADADA' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E2E2E2' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E") no-repeat;background-size:100%}.weui-btn_loading.weui-btn_primary .weui-loading,.weui-btn_loading.weui-btn_warn .weui-loading,.weui-loading.weui-loading_transparent{background-image:url("data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E")}@-webkit-keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes e{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.weui-slider{padding:15px 18px;-webkit-user-select:none;user-select:none}.weui-slider__inner{position:relative;height:2px;background-color:#e9e9e9}.weui-slider__track{height:2px;background-color:#1aad19;width:0}.weui-slider__handler{position:absolute;left:0;top:50%;width:28px;height:28px;margin-left:-14px;margin-top:-14px;border-radius:50%;background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.2)}.weui-slider-box{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-slider-box .weui-slider{-webkit-box-flex:1;-webkit-flex:1;flex:1}.weui-slider-box__value{margin-left:.5em;min-width:24px;color:#888;text-align:center;font-size:14px}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/dobind.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/dobind.html
new file mode 100644
index 0000000..6d377b9
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/dobind.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>绑定银行卡</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="bindcard.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">绑定银行卡</div>
+    </header>
+    <div>
+        <div class="weui-cells__title">验证市民卡预留的手机号</div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" disabled="disabled" value="13402184553">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="number" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">绑定</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/register.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpaypwd.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpaypwd.html
new file mode 100644
index 0000000..2a7b9d8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpaypwd.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>修改支付密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back();">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">修改支付密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">原支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="oldpwd" pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">新支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd" pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd" placeholder="请再次确认密码" pattern="[0-9]*"  maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">确认修改</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/editpaypwd.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpwd.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpwd.html
new file mode 100644
index 0000000..3ea8cfa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/editpwd.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>修改登录密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back();">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">修改登录密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">原登录密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="oldpwd" placeholder="6位以上字符">
+                </div>
+            </div>
+        </div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">新登录密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd" placeholder="6位以上字符">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd" placeholder="请再次确认密码">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">确认修改</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/editpwd.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/error.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/error.html
new file mode 100644
index 0000000..4902b3b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/error.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>错误</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back();">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">错误</div>
+    </header>
+    <p style="padding:10px;text-align: center;">系统错误</p>
+    <script type="text/javascript" src="cordova.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpaypwd.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpaypwd.html
new file mode 100644
index 0000000..17a68d8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpaypwd.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>找回支付密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back();">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">找回支付密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" maxlength="11"  disabled="disabled">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doNext()">下一步</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/findpaypwd.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpwd.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpwd.html
new file mode 100644
index 0000000..ea9e5d5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/findpwd.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>找回登录密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">找回登录密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" maxlength="11">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doRegister()">下一步</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/findpwd.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/back.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/back.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close.png
new file mode 100644
index 0000000..418ff2f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close_1.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close_1.png
new file mode 100644
index 0000000..d71579d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/close_1.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_auth.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_auth.png
new file mode 100644
index 0000000..97d950d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_auth.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_bill.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_bill.png
new file mode 100644
index 0000000..37d5d65
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_bill.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_car.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_car.png
new file mode 100644
index 0000000..d04eacc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_car.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_card.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_card.png
new file mode 100644
index 0000000..595945e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_card.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_header.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_header.png
new file mode 100644
index 0000000..b3a7ebe
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_header.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_meal.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_meal.png
new file mode 100644
index 0000000..f503a14
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_meal.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_ok.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_ok.png
new file mode 100644
index 0000000..e21b78a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_ok.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_qrcode.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_qrcode.png
new file mode 100644
index 0000000..bc1dfc7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_qrcode.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_scan.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_scan.png
new file mode 100644
index 0000000..40b59db
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_scan.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_securty.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_securty.png
new file mode 100644
index 0000000..16b4ddc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_securty.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_water.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_water.png
new file mode 100644
index 0000000..a65df7e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/icon_water.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/light.png b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/light.png
new file mode 100644
index 0000000..2d7bab0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/light.png
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/scanner.svg b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/scanner.svg
new file mode 100644
index 0000000..a13c92b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/img/scanner.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="210mm"
+   height="297mm"
+   viewBox="0 0 744.09448819 1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="aaa.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.7"
+     inkscape:cx="635.5236"
+     inkscape:cy="495.53637"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1017"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     showguides="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Ebene 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 139.32394,274.20898 c -2.43478,0 -4.74475,0.50716 -6.83985,1.41211 -1.96625,0.82082 -3.73345,2.01806 -5.21093,3.50391 -3.1756,3.1164 -5.14454,7.45787 -5.14454,12.2793 l 0,90.91406 c 0,9.5259 7.66941,17.19336 17.19532,17.19336 9.5259,0 17.19336,-7.66746 17.19336,-17.19336 l 0,-75.67774 75.13867,0 c 8.93724,0 16.13281,-7.19361 16.13281,-16.13085 0,-8.93723 -7.19557,-16.13282 -16.13281,-16.13282 l -90.04297,0 c -0.75087,-0.0994 -1.51019,-0.16797 -2.28906,-0.16797 z"
+       id="rect3338"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 631.50851,291.04712 c 0,-2.43478 -0.50716,-4.74475 -1.41211,-6.83985 -0.82082,-1.96625 -2.01806,-3.73345 -3.50391,-5.21093 -3.1164,-3.1756 -7.45787,-5.14454 -12.2793,-5.14454 l -90.91406,0 c -9.5259,0 -17.19336,7.66941 -17.19336,17.19532 0,9.5259 7.66746,17.19336 17.19336,17.19336 l 75.67774,0 0,75.13867 c 0,8.93724 7.19361,16.13281 16.13085,16.13281 8.93723,0 16.13282,-7.19557 16.13282,-16.13281 l 0,-90.04297 c 0.0994,-0.75087 0.16797,-1.51019 0.16797,-2.28906 z"
+       id="rect3338-2" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 122.12824,684.96063 c 0,2.43478 0.50716,4.74475 1.41211,6.83985 0.82082,1.96626 2.01806,3.73346 3.50391,5.21094 3.1164,3.1756 7.45787,5.14454 12.2793,5.14454 l 90.91406,0 c 9.5259,0 17.19336,-7.66941 17.19336,-17.19533 0,-9.5259 -7.66746,-17.19336 -17.19336,-17.19336 l -75.67774,0 0,-75.13866 c 0,-8.93724 -7.19361,-16.13281 -16.13085,-16.13281 -8.93723,0 -16.13282,7.19557 -16.13282,16.13281 l 0,90.04296 c -0.0994,0.75087 -0.16797,1.51019 -0.16797,2.28906 z"
+       id="rect3338-6" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#333333;fill-opacity:0.45098039;fill-rule:evenodd;stroke:#333333;stroke-width:1.06048119px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
+       d="m 614.67107,702.15643 c 2.43478,0 4.74475,-0.50716 6.83985,-1.41211 1.96626,-0.82082 3.73346,-2.01806 5.21094,-3.50391 3.1756,-3.1164 5.14454,-7.45787 5.14454,-12.2793 l 0,-90.91406 c 0,-9.5259 -7.66941,-17.19336 -17.19533,-17.19336 -9.5259,0 -17.19336,7.66746 -17.19336,17.19336 l 0,75.67774 -75.13866,0 c -8.93724,0 -16.13281,7.19361 -16.13281,16.13085 0,8.93723 7.19557,16.13282 16.13281,16.13282 l 90.04296,0 c 0.75087,0.0994 1.51019,0.16797 2.28906,0.16797 z"
+       id="rect3338-6-1" />
+  </g>
+</svg>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/index.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/index.html
new file mode 100644
index 0000000..4afb0bf
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>大理市民卡</title>
+</head>
+<body class="mainbg">
+    <div class="weui-footer weui-footer_fixed-bottom">
+        <p class="weui-footer__links">
+            <a href="#" class="weui-footer__link" style="color: white">大理市民卡</a>
+        </p>
+        <p class="weui-footer__text" style="color: white">© 2019 上海树维</p>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/index.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.min.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript">
+</script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bill.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bill.js
new file mode 100644
index 0000000..4b0bca5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bill.js
@@ -0,0 +1,69 @@
+var curpage=1;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+    onDeviceReady: function() {
+        curpage = 1;
+        this.loadBill(curpage)
+    },
+    loadBill:function(pageno){
+        $.showLoading("加载中");
+        var param={
+            "pageno":pageno
+        }
+        V1Bills(param,function(ok,ret){
+            if(ok){
+                if(ret.code==200){
+                    if(ret.page&&ret.page.count>0){
+                        app.initBillView(ret.page)
+                    }else{
+                        $.alert("暂无数据", "提示"); 
+                    }    
+                }else{
+                    $.hideLoading();
+                    $.alert("数据加载异常,请稍后再试", "错误");
+                }
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
+            }            
+        })
+    },
+    initBillView:function(page){
+        //TODO img src
+        var data = page.data
+        var html ='';
+        for(var i=0;i<data.length;i++){
+            var bean=data[i]
+            html +='<div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail(\''+bean.refno+'\')">';
+            html +='<div class="aui-card-list-user-avatar"><img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />';
+            html +='</div><div class="aui-card-list-user-name">';
+            html +='<div>'+bean.transdesc+'</div>';
+           if(bean.tradeflag=='in'){
+                html +='<div class="aui-list-item-right">+'+bean.amount+'</div>';
+            }else{
+                html +='<div class="aui-list-item-right">'+bean.amount+'</div>';
+            }
+            html +='</div><div class="aui-card-list-user-info">'+formatDateNoYear(bean.transdate,bean.transtime)+'</div></div>';
+        }
+        $("#billcontent").append(html);
+        if(page.data.length==0){
+            $("#loadNext").hide();
+        }else{
+            $("#loadNext").show();
+        }
+        $.hideLoading();
+    },
+    toBillDetail: function(refno) {
+        window.localStorage.setItem("currentrefno",refno);
+        window.location='billdetail.html';
+    },
+    loadNext:function(){
+        curpage++;
+        this.loadBill(curpage)
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/billdetail.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/billdetail.js
new file mode 100644
index 0000000..057b106
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/billdetail.js
@@ -0,0 +1,58 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        this.loadBill()
+    },
+    loadBill: function() {
+        var refno = window.localStorage.getItem("currentrefno");
+        if (isEmpty(refno)) {
+            $.alert("加载失败了", "提示");
+            return;
+        }
+        $.showLoading("加载中");
+        var param = {
+            "billid": refno
+        }
+        V1Billdetail(param, function(ok, ret) {
+            if (ok) {
+                if (ret.code == 200) {
+                    if (ret.dtl == null) {
+                        $.hideLoading();
+                        $.alert("数据加载异常,请稍后再试", "错误");
+                    } else {
+                        app.initBillView(ret.dtl)
+                    }
+                } else {
+                    $.hideLoading();
+                    $.alert("数据加载异常,请稍后再试", "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status + "请稍后再试", "错误");
+            }
+        })
+    },
+    initBillView: function(data) {
+        console.log(data);
+        if (data.tradeflag == 'in') {
+            $("#amount").text('+' + data.amount)
+        } else {
+            $("#amount").text(data.amount)
+        }
+        if (data.status == 'success') {
+            $("#status").text("交易成功");
+        } else {
+            $("#status").text("交易失败");
+        }
+        $("#tranddes").text(data.transdesc);
+        $("#transtime").text(formatDate(data.transdate + '' + data.transtime, true));
+        $("#refno").text(data.refno);
+        $.hideLoading();
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bindcard.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bindcard.js
new file mode 100644
index 0000000..53ac0cf
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/bindcard.js
@@ -0,0 +1,89 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        var phone =  window.localStorage.getItem("phoneX");
+        if(!isEmpty(phone)){
+            $("#phone").val(phone)
+        }else{
+            phone =  window.localStorage.getItem("phone");
+            $("#phone").val(phone)
+        }
+    },
+    doNext: function() {
+        var code =  $("#code").val();
+        var cardnum =  $("#cardnum").val();
+        var name =  $("#name").val();
+        if(isEmpty(name)||isEmpty(code)||isEmpty(cardnum)){
+            return;
+        }
+        /*var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意用户协议与隐私条款", "提示");
+            return;
+        }*/
+        $.showLoading("正在处理");
+        var param={
+            "card":cardnum,
+            "code":code,
+            "name":name
+        }
+        V1Bindcard(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                console.log(ret)
+                if(ret.code==200){
+                     window.localStorage.setItem("paypwdtype","new"); 
+                     window.localStorage.setItem("userid",ret.userid);
+                     window.localStorage.setItem("signed",ret.signed); 
+                     window.localStorage.setItem("name",name); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     if(ret.paypwdset){
+                        if(!isEmpty(ret.signed)&&signed=='yes'){
+                            window.location='main.html'
+                        }else{
+                            window.location='signxy.html'
+                        }
+                     }else{
+                        window.location="paypwdset.html";
+                     }
+                }else{
+                    if(ret.code==-1){
+                        $.alert(ret.msg, "提示",function(){
+                            window.location="main.html"
+                        });
+                    }else{
+                       $.alert(ret.msg, "错误");
+                    }
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了 "+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        $.showLoading("请求中");
+        V1Code(function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/card.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/card.js
new file mode 100644
index 0000000..0c0a91e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/card.js
@@ -0,0 +1,49 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doNext: function() {
+        var pwd =  $("#pwd").val();
+        if(isEmpty(pwd)){
+            return;
+        }
+        if(pwd.length!=6){
+            $.alert("支付密码为6位数字", "提示");
+            return;
+        }
+        var cum = new auiDialog({});
+        var confirm = cum.alert({
+            title: "提示",
+            msg: '确定挂失吗',
+            buttons: ['取消', '确定']
+        }, function(ret) {
+            if (ret.buttonIndex == 2) {
+                $.showLoading("正在处理");
+                var param={
+                    "paypwd":pwd
+                }
+                V1CardLost(param,function(ok,ret){
+                    if(ok){
+                        $.hideLoading();
+                        if(ret.code==200){
+                             $.alert("卡片挂失成功", "提示");
+                        }else{
+                            $.alert(ret.msg, "错误");
+                        } 
+                    }else{
+                        $.hideLoading();
+                        $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+                    }
+                })
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/cardinfor.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/cardinfor.js
new file mode 100644
index 0000000..3d8f675
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/cardinfor.js
@@ -0,0 +1,27 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        $.showLoading("加载中");
+        V1Cardinfor(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#name").text(ret.name);
+                    $("#cardnum").text(ret.cardno);
+                    $("#cardstatus").text(ret.cardstatus);
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("加载失败了:" + ret.status, "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/db.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/db.js
new file mode 100644
index 0000000..d9f0e9b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/db.js
@@ -0,0 +1,8 @@
+var db = null;
+
+document.addEventListener('deviceready', function() {
+  db = window.sqlitePlugin.openDatabase({
+    name: 'my.db',
+    location: 'default',
+  });
+});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpaypwd.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpaypwd.js
new file mode 100644
index 0000000..b7065cb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpaypwd.js
@@ -0,0 +1,49 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+    },
+    doNext: function() {
+        var oldpwd = $("#oldpwd").val();
+        var pwd = $("#pwd").val();
+        var repwd = $("#repwd").val();
+        if (isEmpty(pwd) || isEmpty(repwd)||isEmpty(oldpwd)) {
+            return;
+        }
+        if (pwd.length < 6) {
+            $.alert("密码至少6位以上字符", "提示");
+            return;
+        }
+        if (pwd != repwd) {
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        $.showLoading("正在保存");
+        var param = {
+            "pwd": pwd,
+            "repwd": repwd,
+            "type":"renew",
+            "oldpwd": oldpwd
+        }
+        V1Paypwd(param, function(ok, ret) {
+            if (ok) {
+                $.hideLoading();
+                if (ret.code == 200) {
+                    $.alert("密码修改成功", "提示", function() {
+                        window.location = "security.html";
+                    });
+                } else {
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了" + ret.status + ",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpwd.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpwd.js
new file mode 100644
index 0000000..9d7d045
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/editpwd.js
@@ -0,0 +1,55 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+    },
+    doNext: function() {
+        var oldpwd = $("#oldpwd").val();
+        var pwd = $("#pwd").val();
+        var repwd = $("#repwd").val();
+        if (isEmpty(pwd) || isEmpty(repwd)||isEmpty(oldpwd)) {
+            return;
+        }
+        if (pwd.length < 6) {
+            $.alert("密码至少6位以上字符", "提示");
+            return;
+        }
+        if (pwd != repwd) {
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        $.showLoading("正在保存");
+        var param = {
+            "newpwd": pwd,
+            "renewpwd": repwd,
+            "oldpwd": oldpwd
+        }
+        V1Pwdset(param, function(ok, ret) {
+            if (ok) {
+                $.hideLoading();
+                if (ret.code == 200) {
+                    $.alert("密码修改成功", "提示", function() {
+                        window.location = "security.html";
+                    });
+                } else {
+                    if (ret.code == -1) {
+                      window.localStorage.removeItem("token");
+                      $.alert(ret.msg, "提示", function() {
+                          window.location = "login.html";
+                      });
+                    } else {
+                        $.alert(ret.msg, "错误");
+                    }
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了" + ret.status + ",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpaypwd.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpaypwd.js
new file mode 100644
index 0000000..1eef6e4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpaypwd.js
@@ -0,0 +1,61 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var phone =  window.localStorage.getItem("phoneX");
+        if(!isEmpty(phone)){
+            $("#phone").val(phone)
+        }else{
+            phone =  window.localStorage.getItem("phone");
+            $("#phone").val(phone)
+        }
+    },
+    doNext: function() {
+        var code =  $("#code").val();
+        if(isEmpty(code)){
+            return;
+        }
+        $.showLoading("正在处理");
+        var param={
+            "code":code
+        }
+        V1Checkcode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                     window.localStorage.setItem("randomcode",ret.randcode); 
+                     window.localStorage.setItem("paypwdtype","find"); 
+                     window.location="paypwdset.html";
+                }else{
+                     $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        $.showLoading("请求中");
+        V1Code(function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpwd.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpwd.js
new file mode 100644
index 0000000..1cb4fc2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/findpwd.js
@@ -0,0 +1,72 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doRegister: function() {
+        var phone =  $("#phone").val();
+        var code =  $("#code").val();
+        if(isEmpty(phone)||isEmpty(code)){
+            return;
+        }
+        $.showLoading("正在处理");
+        var param={
+            "phone":phone,
+            "code":code,
+            "platform":device.name+","+device.platform+","+device.version,
+            "uuid":device.uuid
+        }
+        console.log(param)
+        ICheckCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                console.log(ret)
+                if(ret.code==200){
+                     window.localStorage.setItem("phone",phone); 
+                     window.localStorage.setItem("uid",ret.uid); 
+                     window.localStorage.setItem("code",ret.randcode); 
+                     window.localStorage.removeItem("name"); 
+                     window.location="pwdset.html";
+                }else{
+                     $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        var phone =  $("#phone").val();
+        if(isEmpty(phone)){
+            return;            
+        }
+        $.showLoading("请求中");
+        var param={
+            "phone":phone,
+            "type":"find"
+        }
+        IGetCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/index.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/index.js
new file mode 100644
index 0000000..ba4ea86
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/index.js
@@ -0,0 +1,63 @@
+var app = {
+    /*
+    thirdapp:
+    closeBrowser(){
+        if(history.length==1){
+            window.open('mobile/close');
+        }else{
+            history.back();
+        }
+    }
+    <a href="javascript:;" onclick="closeBrowser()">Close</a>
+
+
+    client:
+    var ref = window.open(encodeURI(url), '_blank','location=no');
+     ref.addEventListener('loadstart', function(event) {
+         if (event.url.match("mobile/close")) {
+             ref.close();
+         }
+     });
+    */
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        if (isEmpty(uid)) {
+            window.location = "login.html";
+        } else {
+            //尝试登陆
+            V1Infor(function(ok, ret) {
+                console.log(ret)
+                if (ok) {
+                    if(ret.code==200){
+                        var exp =  window.localStorage.getItem("tokenexpire");
+                        var t = parseInt(exp);
+                        //token 小于10分钟了,需要刷新
+                        console.log((ret.now-t))
+                        if(ret.now-t>1000*60*10){
+                             window.location = "login.html";
+                        }else{
+                             
+                             window.location = "main.html";
+                        }
+                    }
+                } else {
+                    //alert('无法请求到服务器,请检查网络并稍后再试');
+                    if (ret.status == 401) {
+                        //need login
+                        window.location = "login.html";
+                    } else {
+                        //TODO ,没有网络
+                        
+                        window.location = "main.html";
+                    }
+                }
+            })
+        }
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-actionsheet.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-actionsheet.js
new file mode 100644
index 0000000..82b97a1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-actionsheet.js
@@ -0,0 +1,118 @@
+/**
+ * aui-actionsheet.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiActionsheet = function() {
+    };
+    var isShow = false;
+    auiActionsheet.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.title = params.title;
+            this.buttons = params.buttons;
+            this.cancelTitle = params.cancelTitle;
+            this.destructiveTitle = params.destructiveTitle;
+            this.maskDiv;
+            this.actionsheetDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var titleHtml='',buttonsHtml='',destructiveHtml='',cancelHtml='',btnHtml='';
+        	var self = this;
+            if(self.actionsheetDiv || (!self.title && !self.buttons && !self.cancelTitle && !self.destructiveTitle))return;
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            self.actionsheetDiv = document.createElement("div");
+            self.actionsheetDiv.className = "aui-actionsheet";
+            document.body.appendChild(self.actionsheetDiv);
+            if(self.title){
+                titleHtml = '<div class="aui-actionsheet-title aui-border-b aui-font-size-12">'+self.title+'</div>';
+            }
+            if(self.buttons && self.buttons.length){
+                for(var i = 0; i < self.buttons.length;i++){
+                    if(i == self.buttons.length-1){
+                        buttonsHtml += '<div class="aui-actionsheet-btn-item">'+self.buttons[i]+'</div>';
+                    }else{
+                        buttonsHtml += '<div class="aui-actionsheet-btn-item aui-border-b">'+self.buttons[i]+'</div>';
+                    }
+                }
+            }
+            if(self.destructiveTitle){
+                destructiveHtml = '<div class="aui-actionsheet-btn-item aui-border-t aui-text-danger">'+self.destructiveTitle+'</div>';
+            }else{
+                var destructiveHtml = '';
+            }
+            if(self.title || (self.buttons && self.buttons.length)){
+                btnHtml = '<div class="aui-actionsheet-btn">'+titleHtml+''+buttonsHtml+''+destructiveHtml+'</div>';
+            }
+            if(self.cancelTitle){
+                cancelHtml = '<div class="aui-actionsheet-btn"><div class="aui-actionsheet-btn-item">'+self.cancelTitle+'</div></div>';
+            }
+            self.actionsheetDiv.insertAdjacentHTML('beforeend', btnHtml+cancelHtml);
+            var actionsheetHeight = document.querySelector(".aui-actionsheet").offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.actionsheetDiv.style.webkitTransform = self.actionsheetDiv.style.transform = "translate3d(0,0,0)";
+            self.actionsheetDiv.style.opacity = 1;
+            self.actionsheetDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var actionsheetButtons = document.querySelectorAll(".aui-actionsheet-btn-item");
+            if(actionsheetButtons && actionsheetButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < actionsheetButtons.length; ii++){
+                        (function(e){
+                            actionsheetButtons[e].onclick = function(){
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonTitle: this.textContent
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+            }
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.actionsheetDiv){
+                var actionsheetHeight = self.actionsheetDiv.offsetHeight;
+                self.actionsheetDiv.style.webkitTransform = self.actionsheetDiv.style.transform = "translate3d(0,"+actionsheetHeight+"px,0)";
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.actionsheetDiv.parentNode.removeChild(self.actionsheetDiv);
+                    self.actionsheetDiv = self.maskDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiActionsheet = auiActionsheet;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-collapse.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-collapse.js
new file mode 100644
index 0000000..491100f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-collapse.js
@@ -0,0 +1,44 @@
+/**
+ * aui-collapse.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiCollapse = function(params) {
+        this.init(params);
+    };
+    auiCollapse.prototype = {
+        init: function(params,callback){
+            var collapseHeader = document.querySelectorAll(".aui-collapse-header");
+            if(collapseHeader.length){
+                for(var i=0;i<collapseHeader.length;i++){
+                    (function(e){
+                        collapseHeader[e].onclick = function(){
+                            if(collapseHeader[e].nextSibling.nextElementSibling.className.indexOf("aui-collapse-content") > -1){
+                                if(collapseHeader[e].nextSibling.nextElementSibling.className.indexOf("aui-show") > -1){
+                                    collapseHeader[e].nextSibling.nextElementSibling.classList.remove("aui-show");
+                                    collapseHeader[e].classList.remove("aui-active");
+                                }else{
+                                    if(params.autoHide){
+                                        if(document.querySelector(".aui-collapse-header.aui-active")){
+                                            document.querySelector(".aui-collapse-header.aui-active").classList.remove("aui-active");
+                                        }
+                                        if(document.querySelector(".aui-collapse-content.aui-show")){
+                                            document.querySelector(".aui-collapse-content.aui-show").classList.remove("aui-show");
+                                        }
+                                    }
+
+                                    collapseHeader[e].nextSibling.nextElementSibling.classList.toggle("aui-show");
+                                    collapseHeader[e].classList.toggle("aui-active");
+                                }
+                            }
+                        }
+                    })(i)
+                }
+            }
+        }
+    };
+	window.auiCollapse = auiCollapse;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-dialog.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-dialog.js
new file mode 100644
index 0000000..90e85aa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-dialog.js
@@ -0,0 +1,125 @@
+/**
+ * aui-dialog.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiDialog = function() {
+    };
+    var isShow = false;
+    auiDialog.prototype = {
+        params: {
+            title:'',
+            msg:'',
+            buttons: ['取消','确定'],
+            input:false
+        },
+        create: function(params,callback) {
+        	var self = this;
+            var dialogHtml = '';
+            var buttonsHtml = '';
+            var headerHtml = params.title ? '<div class="aui-dialog-header">' + params.title + '</div>' : '<div class="aui-dialog-header">' + self.params.title + '</div>';
+            if(params.input){
+                params.text = params.text ? params.text: '';
+                var msgHtml = '<div class="aui-dialog-body"><input type="text" placeholder="'+params.text+'"></div>';
+            }else{
+                var msgHtml = params.msg ? '<div class="aui-dialog-body">' + params.msg + '</div>' : '<div class="aui-dialog-body">' + self.params.msg + '</div>';
+            }
+            var buttons = params.buttons ? params.buttons : self.params.buttons;
+            if (buttons && buttons.length > 0) {
+                for (var i = 0; i < buttons.length; i++) {
+                    buttonsHtml += '<div class="aui-dialog-btn" tapmode button-index="'+i+'">'+buttons[i]+'</div>';
+                }
+            }
+            var footerHtml = '<div class="aui-dialog-footer">'+buttonsHtml+'</div>';
+            dialogHtml = '<div class="aui-dialog">'+headerHtml+msgHtml+footerHtml+'</div>';
+            document.body.insertAdjacentHTML('beforeend', dialogHtml);
+            // listen buttons click
+            var dialogButtons = document.querySelectorAll(".aui-dialog-btn");
+            if(dialogButtons && dialogButtons.length > 0){
+                for(var ii = 0; ii < dialogButtons.length; ii++){
+                    dialogButtons[ii].onclick = function(){
+                        if(callback){
+                            if(params.input){
+                                callback({
+                                    buttonIndex: parseInt(this.getAttribute("button-index"))+1,
+                                    text: document.querySelector("input").value
+                                });
+                            }else{
+                                callback({
+                                    buttonIndex: parseInt(this.getAttribute("button-index"))+1
+                                });
+                            }
+                        };
+                        self.close();
+                        return;
+                    }
+                }
+            }
+            self.open();
+        },
+        open: function(){
+            if(!document.querySelector(".aui-dialog"))return;
+            var self = this;
+            document.querySelector(".aui-dialog").style.marginTop =  "-"+Math.round(document.querySelector(".aui-dialog").offsetHeight/2)+"px";
+            if(!document.querySelector(".aui-mask")){
+                var maskHtml = '<div class="aui-mask"></div>';
+                document.body.insertAdjacentHTML('beforeend', maskHtml);
+            }
+            // document.querySelector(".aui-dialog").style.display = "block";
+            setTimeout(function(){
+                document.querySelector(".aui-dialog").classList.add("aui-dialog-in");
+                document.querySelector(".aui-mask").classList.add("aui-mask-in");
+                document.querySelector(".aui-dialog").classList.add("aui-dialog-in");
+            }, 10)
+            document.querySelector(".aui-mask").addEventListener("touchmove", function(e){
+                e.preventDefault();
+            })
+            document.querySelector(".aui-dialog").addEventListener("touchmove", function(e){
+                e.preventDefault();
+            })
+            return;
+        },
+        close: function(){
+            var self = this;
+            document.querySelector(".aui-mask").classList.remove("aui-mask-in");
+            document.querySelector(".aui-dialog").classList.remove("aui-dialog-in");
+            document.querySelector(".aui-dialog").classList.add("aui-dialog-out");
+            if (document.querySelector(".aui-dialog:not(.aui-dialog-out)")) {
+                setTimeout(function(){
+                    if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+                    self.open();
+                    return true;
+                },200)
+            }else{
+                document.querySelector(".aui-mask").classList.add("aui-mask-out");
+                document.querySelector(".aui-dialog").addEventListener("webkitTransitionEnd", function(){
+                    self.remove();
+                })
+                document.querySelector(".aui-dialog").addEventListener("transitionend", function(){
+                    self.remove();
+                })
+            }
+        },
+        remove: function(){
+            if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+            if(document.querySelector(".aui-mask")){
+                document.querySelector(".aui-mask").classList.remove("aui-mask-out");
+            }
+            return true;
+        },
+        alert: function(params,callback){
+        	var self = this;
+            return self.create(params,callback);
+        },
+        prompt:function(params,callback){
+            var self = this;
+            params.input = true;
+            return self.create(params,callback);
+        }
+    };
+	window.auiDialog = auiDialog;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-lazyload.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-lazyload.js
new file mode 100644
index 0000000..17e24f0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-lazyload.js
@@ -0,0 +1,48 @@
+/**

+ * aui-lazyload.js

+ * @author 流浪男

+ * Licensed under the MIT license.

+ * http://www.opensource.org/licenses/mit-license.php

+ */

+(function( window, undefined ) {

+    "use strict";

+    var _loadImgNodes;

+    var auiLazyload = function(params) {

+        this.errorImage = params.errorImage||false;

+        this._init(params);

+    };

+    auiLazyload.prototype = {

+        _init: function(params) {

+            var self = this;

+            _loadImgNodes = document.querySelectorAll('[data-src]');

+            self._judgeImages();

+            window.addEventListener('scroll', function(){

+                _loadImgNodes = document.querySelectorAll('[data-src]');

+                self._judgeImages();

+            }, false);

+        },

+        _judgeImages:function() {

+            var self = this;

+            if(_loadImgNodes.length){

+                for(var i = 0;  i < _loadImgNodes.length; i++){

+                    if (_loadImgNodes[i].getBoundingClientRect().top < window.innerHeight) {

+                        self._loadImage(_loadImgNodes[i]);

+                    }

+                }

+            }

+        },

+        _loadImage:function(el){

+            var self = this;

+            var img = new Image();

+            img.src = el.getAttribute('data-src');

+            el.src = el.getAttribute('data-src');

+            el.removeAttribute("data-src");

+            // // 图片加载失败

+            img.onerror = function() {

+                el.src = self.errorImage || el.getAttribute('src');

+                el.removeAttribute("data-src");

+            };

+        }

+    }

+    window.auiLazyload = auiLazyload;

+})(window);

diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe-backup.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe-backup.js
new file mode 100644
index 0000000..7bffd23
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe-backup.js
@@ -0,0 +1,243 @@
+/**
+ * aui-list-swipe.js 列表页滑动菜单
+ * verson 0.0.3
+ * @author 流浪男 && Beck
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+ (function(window) {
+	"use strict";
+	var translateVal,
+		friction = 1,
+		firstTouchX,
+		firstTouchxy,
+		firstTouchY,
+		firstTouch,
+		firstTouchTime,
+		touchXDelta,
+		handleTranslateVal;
+	var TranslateZero = "translate3d(0,0,0)",
+		TranslateCent = "translate3d(100%,0,0)";
+	var swipeHandle = false,
+		btnWidth = false,
+		swipeBtnsRight = false;
+	var isMoved = false,isOpened=false;
+	var d = false;
+	var auiListSwipe = function (callback) {
+		this._init(callback);
+	}
+	auiListSwipe.prototype = {
+		// var self = this;
+		_init: function(callback){
+			var self = this;
+			// var d = document.querySelectorAll("selectors")
+			window.addEventListener('touchstart', function(event){
+				if(isOpened){
+					console.log(1)
+					// return;
+					isOpened = false;
+					return;
+				}
+				if(swipeHandle){
+					event.preventDefault();
+					self.setTranslate(swipeHandle,"0px");
+					swipeHandle.classList.remove("aui-swipe-opened");
+					swipeHandle = false;
+					return;
+				}
+				isMoved = false;
+				swipeHandle = false;
+				var target = event.target;
+				// 过滤点击
+				for(; target && target !== document; target = target.parentNode){
+					// console.log(target.classList)
+					if (target.classList){
+						if (target.classList.contains("aui-swipe-handle")) {
+							swipeHandle = target;
+							firstTouch = event.changedTouches[0];
+							firstTouchX = firstTouch.clientX;
+							firstTouchY = firstTouch.clientY;
+							firstTouchTime = event.timeStamp;
+							if(swipeHandle.className.indexOf("aui-swipe-opened") > -1){
+							// 	console.log(1)
+								// self.setTranslate(swipeHandle,"0px");
+								// swipeHandle.classList.remove("aui-swipe-opened");
+								event.preventDefault();
+								return;
+							}else{
+								// setTimeout(function(){
+									self.toggleEvents(swipeHandle,callback);
+								// }, 100)
+
+							}
+
+						}
+					}
+				}
+
+
+			})
+			// window.addEventListener('touchmove', function(event){
+			// 	if(swipeHandle){
+			// 		// event.preventDefault();
+			// 		// self.setTranslate(swipeHandle,"0px");
+			// 		// swipeHandle.classList.remove("aui-swipe-opened");
+			// 		// swipeHandle = false;
+			// 		// return;
+			// 	}
+			// 	if(document.querySelector(".aui-swipe-opened")){
+			// 		event.preventDefault();
+			// 		if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+			// 			self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			//         	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			//         	isOpened = false;
+
+			//         	event.stopPropagation()
+			//         	return;
+			// 		}
+			// 	}
+			// })
+			window.addEventListener("touchmove", function(){
+
+			})
+		},
+		toggleEvents:function(element,callback){
+			if(!swipeHandle){
+				return;
+			}
+			var self = this;
+			self.setTransform(element,300);
+			element.addEventListener('touchstart', function(event){
+				// if(element.className.indexOf("aui-swipe-opened") > -1){
+				// 	self.setTranslate(element,"0px");
+				// 	element.classList.remove("aui-swipe-opened");
+				// 	return;
+				// }
+				//:active样式引起列表背景色冲突
+
+				element.parentNode.style.backgroundColor = "#ffffff";
+				if(!element.nextSibling)return;
+			},false)
+			element.addEventListener('touchmove', function(event){
+				if(document.querySelector(".aui-swipe-opened")){
+					event.preventDefault();
+					if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+						self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			        	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			        	isOpened = false;
+			        	event.stopPropagation()
+			        	return;
+					}
+				}
+				// self.getAngle(event)
+				self.setTransform(element,0);
+				// if(element.className.indexOf("aui-swipe-opened") > -1)return;
+
+				if(element.parentNode.querySelector(".aui-swipe-btn")){
+					btnWidth = element.parentNode.querySelector(".aui-swipe-btn").offsetWidth;
+				}
+				// 列表触摸滑动时如果有已经显示的将其关闭,并退出。
+				var touchMoveObj = event.changedTouches[0],
+					touchX = touchMoveObj.clientX;
+				touchXDelta = -Math.pow(firstTouchX-touchX, 0.85);
+				handleTranslateVal = touchXDelta/friction;
+				// touchXDelta = touchX - firstTouchX;
+				// handleTranslateVal = touchXDelta/0.15;
+				// console.log(handleTranslateVal)
+		        var moveX = touchMoveObj.clientX - firstTouchX;
+		        var moveY = touchMoveObj.clientY - firstTouchY;
+		        var direction = self.getDirection(moveX,moveY);
+		        var angle = self.getAngle(Math.abs(moveX),Math.abs(moveY));
+		        // console.log(isMoved);
+
+		        // // 解决滑动屏幕返回时事件冲突,主要针对部分特殊机型
+		        // if(touchMoveObj.screenX < 0){
+		        // 	firstTouchxy = '';
+		        // }
+		        if(direction == "right"){
+		        	isMoved = false;
+		        	event.preventDefault();
+		        }
+		        if(direction == "top" || direction == "down"){
+		        	isMoved = false;
+		        	return;
+		        }
+		        if(angle <= 15 && direction === 'left'){
+		        	event.preventDefault()
+		        	isMoved = true;
+		        }
+		        // console.log(handleTranslateVal)
+		        // if(isMoved)self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+		        if((event.timeStamp - firstTouchTime) >= 100 && touchXDelta < 0 && touchMoveObj.screenX > 0 && isMoved){
+		        	// event.stopPropagation();
+		        	// element.classList.add("aui-swipe-moving");
+		        	// event.preventDefault();
+		        	if(element.className.indexOf("aui-swipe-opened") <= -1){
+						if((handleTranslateVal+10) > -btnWidth){
+				        	self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+				        }
+					}else{
+						return
+					}
+
+			    }
+			},false)
+			element.addEventListener('touchend', function(event){
+				self.setTransform(element,300);
+				var touchEndObj = event.changedTouches[0];
+				var touchEndxy = {
+						x: touchEndObj.clientX || 0,
+						y: touchEndObj.clientY || 0
+					};
+				var toucheEndX = touchEndObj.clientX - firstTouchX;
+		        var toucheEndY = touchEndObj.clientY - firstTouchY;
+		        var direction = self.getDirection(toucheEndX,toucheEndY);
+		        // element.classList.remove("aui-swipe-moving");
+	        	if(direction=='left' && handleTranslateVal < (-btnWidth/3) && isMoved){
+		        	self.setTranslate(element,""+-btnWidth+"px");
+		        	element.classList.add("aui-swipe-opened");
+		        	callback({
+		        		'status':true,
+		        		'dom':element
+		        	})
+		        	isOpened = true;
+				}else{
+					element.classList.remove("aui-swipe-opened");
+		        	self.setTranslate(element,"0px");
+		        	isOpened = false;
+				}
+				// isMoved = false;
+				console.log(isOpened)
+			},true)
+		},
+		setTransform : function (el,value){
+			el.style.webkitTransitionDuration = el.style.transitionDuration = value+'ms';
+		},
+		setTranslate : function (el,value){
+			if(el)el.style.webkitTransform = el.style.transform = "translate3d("+value+",0,0)";
+		},
+		getDistance : function(p1, p2, props) {
+			if (!props) { props = ['x', 'y'];}
+			var x = p2[props[0]] - p1[props[0]];
+			var y = p2[props[1]] - p1[props[1]];
+			return Math.sqrt((x * x) + (y * y));
+		},
+		getAngle:function(moveX, moveY){
+		       // var x = Math.abs(x1 - x2);
+		       // var y = Math.abs(y1 - y2);
+		       var z = Math.sqrt(moveX*moveX + moveY*moveY);
+		       return  Math.round((Math.asin(moveY / z) / Math.PI*180));
+		},
+		getDirection : function(x, y) {
+			if (x === y) { return '';}
+			if (Math.abs(x) >= Math.abs(y)) {
+	            return x > 0 ? 'right' : 'left';
+	        } else {
+	           	return y > 0 ? 'down' : 'up';
+	        }
+		}
+	}
+	window.auiListSwipe = auiListSwipe;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe.js
new file mode 100755
index 0000000..3669b70
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-list-swipe.js
@@ -0,0 +1,221 @@
+/**
+ * aui-list-swipe.js 列表页滑动菜单
+ * verson 0.0.3
+ * @author 流浪男 && Beck
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+ (function(window) {
+	"use strict";
+	var translateVal,
+		friction = 1,
+		firstTouchX,
+		firstTouchxy,
+		firstTouchY,
+		firstTouch,
+		firstTouchTime,
+		touchXDelta,
+		handleTranslateVal;
+	var TranslateZero = "translate3d(0,0,0)",
+		TranslateCent = "translate3d(100%,0,0)";
+	var swipeHandle = false,
+		btnWidth = false,
+		swipeBtnsRight = false;
+	var isMoved = false,isOpened=false;
+	var d = false;
+	var auiListSwipe = function (callback) {
+		this._init(callback);
+	}
+	auiListSwipe.prototype = {
+		// var self = this;
+		_init: function(callback){
+			var self = this;
+			// var d = document.querySelectorAll("selectors")
+			window.addEventListener('touchstart', function(event){
+				// 如果已经打开,将已经打开的关闭
+				if(isOpened && swipeHandle){
+					// isOpened = false;
+					self.setTranslate(swipeHandle,"0px");
+					swipeHandle.classList.remove("aui-swipe-opened");
+					return;
+				}else{
+					var target = event.target;
+					// 过滤点击
+					for(; target && target !== document; target = target.parentNode){
+						// console.log(target.classList)
+						if (target.classList){
+							if (target.classList.contains("aui-swipe-handle")) {
+								swipeHandle = target;
+								firstTouch = event.changedTouches[0];
+								firstTouchX = firstTouch.clientX;
+								firstTouchY = firstTouch.clientY;
+								firstTouchTime = event.timeStamp;
+								if(swipeHandle.className.indexOf("aui-swipe-opened") > -1){
+								// 	console.log(1)
+									// self.setTranslate(swipeHandle,"0px");
+									// swipeHandle.classList.remove("aui-swipe-opened");
+									event.preventDefault();
+									return;
+								}else{
+									// setTimeout(function(){
+										self.toggleEvents(swipeHandle,callback);
+									// }, 100)
+
+								}
+
+							}
+						}
+					}
+				}
+				// if(swipeHandle){
+				// 	event.preventDefault();
+				// 	self.setTranslate(swipeHandle,"0px");
+				// 	swipeHandle.classList.remove("aui-swipe-opened");
+				// 	swipeHandle = false;
+				// 	return;
+				// }
+				// isMoved = false;
+				// swipeHandle = false;
+			})
+		},
+		toggleEvents:function(element,callback){
+			if(!swipeHandle){
+				return;
+			}
+			var self = this;
+			self.setTransform(element,300);
+			element.addEventListener('touchstart', function(event){
+				// if(element.className.indexOf("aui-swipe-opened") > -1){
+				// 	self.setTranslate(element,"0px");
+				// 	element.classList.remove("aui-swipe-opened");
+				// 	return;
+				// }
+				//:active样式引起列表背景色冲突
+
+				element.parentNode.style.backgroundColor = "#ffffff";
+				if(!element.nextSibling)return;
+			},false)
+			element.addEventListener('touchmove', function(event){
+				event.preventDefault();
+				if(document.querySelector(".aui-swipe-opened")){
+					event.preventDefault();
+					if(swipeHandle != document.querySelector(".aui-swipe-opened")){
+						self.setTranslate(document.querySelector(".aui-swipe-opened"),"0px");
+			        	document.querySelector(".aui-swipe-opened").classList.remove("aui-swipe-opened");
+			        	isOpened = false;
+			        	event.stopPropagation()
+			        	return;
+					}
+				}
+				// self.getAngle(event)
+				self.setTransform(element,0);
+				// if(element.className.indexOf("aui-swipe-opened") > -1)return;
+
+				if(element.parentNode.querySelector(".aui-swipe-btn")){
+					btnWidth = element.parentNode.querySelector(".aui-swipe-btn").offsetWidth;
+				}
+				// 列表触摸滑动时如果有已经显示的将其关闭,并退出。
+				var touchMoveObj = event.changedTouches[0],
+					touchX = touchMoveObj.clientX;
+				touchXDelta = -Math.pow(firstTouchX-touchX, 0.85);
+				handleTranslateVal = touchXDelta/friction;
+				// touchXDelta = touchX - firstTouchX;
+				// handleTranslateVal = touchXDelta/0.15;
+				// console.log(handleTranslateVal)
+		        var moveX = touchMoveObj.clientX - firstTouchX;
+		        var moveY = touchMoveObj.clientY - firstTouchY;
+		        var direction = self.getDirection(moveX,moveY);
+		        var angle = self.getAngle(Math.abs(moveX),Math.abs(moveY));
+		        // console.log(isMoved);
+
+		        // // 解决滑动屏幕返回时事件冲突,主要针对部分特殊机型
+		        // if(touchMoveObj.screenX < 0){
+		        // 	firstTouchxy = '';
+		        // }
+		        if(direction == "right"){
+		        	isMoved = false;
+		        	event.preventDefault();
+		        }
+		        if(direction == "top" || direction == "down"){
+		        	isMoved = false;
+		        	return;
+		        }
+		        if(angle <= 15 && direction === 'left'){
+		        	event.preventDefault()
+		        	isMoved = true;
+		        }
+		        // console.log(handleTranslateVal)
+		        // if(isMoved)self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+		        if((event.timeStamp - firstTouchTime) >= 100 && touchXDelta < 0 && touchMoveObj.screenX > 0 && isMoved){
+		        	// event.stopPropagation();
+		        	// element.classList.add("aui-swipe-moving");
+		        	// event.preventDefault();
+		        	if(element.className.indexOf("aui-swipe-opened") <= -1){
+						if((handleTranslateVal+10) > -btnWidth){
+				        	self.setTranslate(element,""+(handleTranslateVal+10)+"px");
+				        }
+					}else{
+						return
+					}
+
+			    }
+			},false)
+			element.addEventListener('touchend', function(event){
+				self.setTransform(element,300);
+				var touchEndObj = event.changedTouches[0];
+				var touchEndxy = {
+						x: touchEndObj.clientX || 0,
+						y: touchEndObj.clientY || 0
+					};
+				var toucheEndX = touchEndObj.clientX - firstTouchX;
+		        var toucheEndY = touchEndObj.clientY - firstTouchY;
+		        var direction = self.getDirection(toucheEndX,toucheEndY);
+		        // element.classList.remove("aui-swipe-moving");
+	        	if(direction=='left' && handleTranslateVal < (-btnWidth/3) && isMoved){
+		        	self.setTranslate(element,""+-btnWidth+"px");
+		        	element.classList.add("aui-swipe-opened");
+		        	callback({
+		        		'status':true,
+		        		'dom':element
+		        	})
+		        	// isOpened = true;
+				}else{
+					element.classList.remove("aui-swipe-opened");
+		        	self.setTranslate(element,"0px");
+		        	isOpened = false;
+				}
+				// isMoved = false;
+				console.log(isOpened)
+			},true)
+		},
+		setTransform : function (el,value){
+			el.style.webkitTransitionDuration = el.style.transitionDuration = value+'ms';
+		},
+		setTranslate : function (el,value){
+			if(el)el.style.webkitTransform = el.style.transform = "translate3d("+value+",0,0)";
+		},
+		getDistance : function(p1, p2, props) {
+			if (!props) { props = ['x', 'y'];}
+			var x = p2[props[0]] - p1[props[0]];
+			var y = p2[props[1]] - p1[props[1]];
+			return Math.sqrt((x * x) + (y * y));
+		},
+		getAngle:function(moveX, moveY){
+		       // var x = Math.abs(x1 - x2);
+		       // var y = Math.abs(y1 - y2);
+		       var z = Math.sqrt(moveX*moveX + moveY*moveY);
+		       return  Math.round((Math.asin(moveY / z) / Math.PI*180));
+		},
+		getDirection : function(x, y) {
+			if (x === y) { return '';}
+			if (Math.abs(x) >= Math.abs(y)) {
+	            return x > 0 ? 'right' : 'left';
+	        } else {
+	           	return y > 0 ? 'down' : 'up';
+	        }
+		}
+	}
+	window.auiListSwipe = auiListSwipe;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup-new.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup-new.js
new file mode 100644
index 0000000..3c1a128
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup-new.js
@@ -0,0 +1,135 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiPopup = function() {
+    };
+    var isShow = false;
+    auiPopup.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.location = params.location;
+            this.buttons = params.buttons;
+            this.maskDiv;
+            this.popupDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var buttonsHtml='',locationClass = 'aui-popup-top';
+        	var self = this;
+            if(self.popupDiv){
+                self.close();
+                return;
+            }
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            switch (self.location) {
+                case "top":
+                    locationClass = 'aui-popup-top';
+                    break;
+                case "top-left":
+                    locationClass = 'aui-popup-top-left';
+                    break;
+                case "top-right":
+                    locationClass = 'aui-popup-top-right';
+                    break;
+                case "bottom":
+                    locationClass = 'aui-popup-bottom';
+                    break;
+                case "bottom-left":
+                    locationClass = 'aui-popup-bottom-left';
+                    break;
+                case "bottom-right":
+                    locationClass = 'aui-popup-bottom-right';
+                    break;
+                default:
+                    locationClass = 'aui-popup-top';
+                    break;
+            }
+            self.popupDiv = document.createElement("div");
+            self.popupDiv.className = "aui-popup "+locationClass;
+            self.popupDiv.innerHTML = '<div class="aui-popup-arrow"></div><div class="aui-popup-content"></div>';
+            document.body.appendChild(self.popupDiv);
+            if(self.buttons && self.buttons.length){
+                buttonsHtml += '<ul class="aui-list aui-list-noborder">';
+                for(var i = 0; i < self.buttons.length;i++){
+                    buttonsHtml += '<li class="aui-list-item aui-list-item-middle">';
+                    buttonsHtml += '<div class="aui-list-item-label-icon"><img src="'+self.buttons[i].image+'"></div>';
+                    buttonsHtml += '<div class="aui-list-item-inner">'+self.buttons[i].text+'</div>';
+                    buttonsHtml += '</li>';
+                }
+                buttonsHtml += '</ul>';
+            }
+            document.querySelector(".aui-popup .aui-popup-content").insertAdjacentHTML('beforeend', buttonsHtml);
+            var actionsheetHeight = document.querySelector(".aui-popup").offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.popupDiv.classList.add("aui-popup-in");
+            self.popupDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var popupButtons = document.querySelectorAll(".aui-popup .aui-list-item");
+            if(popupButtons && popupButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < popupButtons.length; ii++){
+                        (function(e){
+                            popupButtons[e].onclick = function(){
+                                if(self.buttons[e].value){
+                                    var _value = self.buttons[e].value;
+                                }else{
+                                    var _value = null;
+                                }
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonTitle: this.textContent,
+                                        buttonValue: _value
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+            }
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.popupDiv){
+                var actionsheetHeight = self.popupDiv.offsetHeight;
+                self.popupDiv.classList.add("aui-popup-out");
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.popupDiv.parentNode.removeChild(self.popupDiv);
+                    self.maskDiv = self.popupDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiPopup = auiPopup;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup.js
new file mode 100644
index 0000000..fe26259
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-popup.js
@@ -0,0 +1,94 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiPopup = function() {
+        this._init();
+    };
+    var	CLASS_MASK = "aui-mask",
+    	CLASS_MASK_IN = 'aui-mask-in',
+    	CLASS_MASK_OUT = 'aui-mask-out',
+        CLASS_POPUP = 'aui-popup',
+    	CLASS_POPUP_IN = 'aui-popup-in',
+    	CLASS_POPUP_OUT = 'aui-popup-out',
+    	CLASS_POPUP_FOR = 'aui-popup-for';
+    var	__MASK = '.'+CLASS_MASK,
+    	__MASK_IN = '.'+CLASS_MASK_IN,
+    	__MASK_OUT = '.'+CLASS_MASK_OUT,
+        __POPUP = '.'+CLASS_POPUP,
+    	__POPUP_IN = '.'+CLASS_POPUP_IN,
+    	__POPUP_OUT = '.'+CLASS_POPUP_OUT;
+    var popupStatus = false;
+    auiPopup.prototype = {
+        _init: function() {
+        	var self = this;
+        	var _btn = document.querySelectorAll("["+CLASS_POPUP_FOR+"]");
+        	if(_btn){
+        		for(var i=0;i<_btn.length;i++){
+        			_btn[i].setAttribute("tapmode", "");
+        			_btn[i].onclick = function(e){
+        				var popupId = this.getAttribute(CLASS_POPUP_FOR);
+        				var popupDom = document.getElementById(popupId);
+        				if(popupDom){
+							if(popupDom.className.indexOf(CLASS_POPUP_IN) > -1 || document.querySelector(__POPUP_IN)){
+					            self.hide(popupDom);
+					        }else{
+					        	self.show(popupDom);
+					        }
+        				}else{
+        					return;
+        				}
+					}
+        		}
+        	}
+        },
+        show: function(el){
+        	var self = this;
+        	if(el.className.indexOf(CLASS_POPUP_IN) > -1 || document.querySelector(__POPUP_IN)){
+	            self.hide(el);
+	            return;
+	        }
+            if(popupStatus) return;
+        	if(!document.querySelector(__MASK)){
+				var maskHtml = '<div class="aui-mask"></div>';
+				document.body.insertAdjacentHTML('beforeend', maskHtml);
+			}
+        	el.style.display = "block";
+        	setTimeout(function(){
+        		document.querySelector(__MASK).classList.add(CLASS_MASK_IN);
+	            el.classList.add(CLASS_POPUP_IN);
+                popupStatus = true;
+	        }, 10)
+	        document.querySelector(__MASK).addEventListener("touchstart", function(event){
+	        	event.preventDefault();
+	        	self.hide(el);
+	        })
+            el.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            },false)
+        },
+        hide: function(el){
+            if(!popupStatus) return;
+        	document.querySelector(__MASK).classList.remove(CLASS_MASK_IN);
+        	document.querySelector(__MASK).classList.add(CLASS_MASK_OUT);
+        	if(!document.querySelector(__POPUP_IN))return;
+            document.querySelector(__POPUP_IN).classList.add(CLASS_POPUP_OUT);
+            document.querySelector(__POPUP_IN).classList.remove(CLASS_POPUP_IN);
+	        setTimeout(function(){
+                if(!document.querySelector(__POPUP_OUT))return;
+	        	document.querySelector(__POPUP_OUT).style.display = "none";
+	            document.querySelector(__POPUP_OUT).classList.remove(CLASS_POPUP_OUT);
+	            if(document.querySelector(__MASK)){
+					document.querySelector(__MASK).parentNode.removeChild(document.querySelector(__MASK));
+				}
+                popupStatus = false;
+	        }, 300)
+        }
+    };
+	window.auiPopup = auiPopup;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-pull-refresh.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-pull-refresh.js
new file mode 100644
index 0000000..8f3bba3
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-pull-refresh.js
@@ -0,0 +1,174 @@
+/**
+ * aui-pull-refresh.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	'use strict';
+	/**
+	 * Extend obj function
+	 *
+	 * This is an object extender function. It allows us to extend an object
+	 * by passing in additional variables and overwriting the defaults.
+	 */
+	var auiPullToRefresh = function (params,callback) {
+		this.extend(this.params, params);
+		this._init(callback);
+	}
+	var touchYDelta;
+	var isLoading = false;
+	var docElem = window.document.documentElement,
+		loadWrapH,
+		win = {width: window.innerWidth, height: window.innerHeight},
+		winfactor= 0.2,
+		translateVal,
+		isMoved = false,
+		firstTouchY, initialScroll;
+	auiPullToRefresh.prototype = {
+		params: {
+            container: document.querySelector('.aui-refresh-content'),
+			friction: 2.5,
+			triggerDistance: 100,
+			callback:false
+        },
+        _init : function(callback) {
+			var self = this;
+			var loadingHtml = '<div class="aui-refresh-load"><div class="aui-refresh-pull-arrow"></div></div>';
+			self.params.container.insertAdjacentHTML('afterbegin', loadingHtml);
+			self.params.container.addEventListener('touchstart', function(ev){
+				self.touchStart(ev)
+			});
+			self.params.container.addEventListener('touchmove', function(ev){
+				self.touchMove(ev)
+			});
+			self.params.container.addEventListener('touchend', function(ev){
+				self.touchEnd(ev,callback);
+			});
+		},
+		touchStart : function(ev) {
+			// this.params.container.classList.remove("refreshing");
+			if (isLoading) {
+				return;
+			}
+			isMoved = false;
+			this.params.container.style.webkitTransitionDuration =
+		    this.params.container.style.transitionDuration = '0ms';
+			touchYDelta = '';
+			var touchobj = ev.changedTouches[0];
+			// register first touch "y"
+			firstTouchY = parseInt(touchobj.clientY);
+			initialScroll = this.scrollY();
+		},
+		touchMove : function (ev) {
+			if (isLoading) {
+				ev.preventDefault();
+				return;
+			}
+			var self = this;
+			var moving = function() {
+				var touchobj = ev.changedTouches[0], // reference first touch point for this event
+					touchY = parseInt(touchobj.clientY);
+					touchYDelta = touchY - firstTouchY;
+				if ( self.scrollY() === 0 && touchYDelta > 0  ) {
+					ev.preventDefault();
+				}
+				if ( initialScroll > 0 || self.scrollY() > 0 || self.scrollY() === 0 && touchYDelta < 0 ) {
+					firstTouchY = touchY;
+					return;
+				}
+				translateVal = Math.pow(touchYDelta, 0.85);
+				self.params.container.style.webkitTransform = self.params.container.style.transform = 'translate3d(0, ' + translateVal + 'px, 0)';
+				isMoved = true;
+				if(touchYDelta > self.params.triggerDistance){
+					self.params.container.classList.add("aui-refresh-pull-up");
+					self.params.container.classList.remove("aui-refresh-pull-down");
+				}else{
+					self.params.container.classList.add("aui-refresh-pull-down");
+					self.params.container.classList.remove("aui-refresh-pull-up");
+				}
+			};
+			this.throttle(moving(), 20);
+		},
+		touchEnd : function (ev,callback) {
+			var self =this;
+			if (isLoading|| !isMoved) {
+				isMoved = false;
+				return;
+			}
+			// 根据下拉高度判断是否加载
+			if( touchYDelta >= this.params.triggerDistance) {
+				isLoading = true; //正在加载中
+				ev.preventDefault();
+				this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '300ms';
+				this.params.container.style.webkitTransform =
+				this.params.container.style.transform = 'translate3d(0,60px,0)';
+				document.querySelector(".aui-refresh-pull-arrow").style.webkitTransitionDuration =
+		    	document.querySelector(".aui-refresh-pull-arrow").style.transitionDuration = '0ms';
+				self.params.container.classList.add("aui-refreshing");
+				if(callback){
+					callback({
+						status:"success"
+					});
+				}
+			}else{
+				this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '300ms';
+				this.params.container.style.webkitTransform =
+				this.params.container.style.transform = 'translate3d(0,0,0)';
+				if(callback){
+					callback({
+						status:"fail"
+					});
+				}
+			}
+			isMoved = false;
+			return;
+		},
+		cancelLoading : function () {
+			var self =this;
+			isLoading = false;
+			self.params.container.classList.remove("aui-refreshing");
+			document.querySelector(".aui-refresh-pull-arrow").style.webkitTransitionDuration =
+		    	document.querySelector(".aui-refresh-pull-arrow").style.transitionDuration = '300ms';
+			this.params.container.style.webkitTransitionDuration =
+		    	this.params.container.style.transitionDuration = '0ms';
+			self.params.container.style.webkitTransform =
+			self.params.container.style.transform = 'translate3d(0,0,0)';
+			self.params.container.classList.remove("aui-refresh-pull-up");
+			self.params.container.classList.add("aui-refresh-pull-down");
+			return;
+		},
+		scrollY : function() {
+			return window.pageYOffset || docElem.scrollTop;
+		},
+		throttle : function(fn, delay) {
+			var allowSample = true;
+			return function(e) {
+				if (allowSample) {
+					allowSample = false;
+					setTimeout(function() { allowSample = true; }, delay);
+					fn(e);
+				}
+			};
+		},
+		winresize : function () {
+			var resize = function() {
+				win = {width: window.innerWidth, height: window.innerHeight};
+			};
+			throttle(resize(), 10);
+		},
+		extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		 }
+	}
+	window.auiPullToRefresh = auiPullToRefresh;
+
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-range.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-range.js
new file mode 100644
index 0000000..ed42002
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-range.js
@@ -0,0 +1,53 @@
+/*

+ * AUI JAVASCRIPT PLUGIN

+ * 滑动 aui-range

+ * Copyright (c) 2015 auicss.com @流浪男  QQ:343757327  群:344869952

+ */

+ (function( window, undefined ) {

+    "use strict";

+    var auiRange = function(params,callback) {

+        this._init(params,callback);

+    };

+    var time=null;

+    var distance,offsetLeft,tooltipWidth;

+    auiRange.prototype = {

+        _init: function(params,callback) {

+            var self = this;

+            distance = Math.abs(params.element.max - params.element.min);

+            offsetLeft = params.element.offsetLeft;

+            tooltipWidth = params.element.offsetWidth - 28;

+            params.element.insertAdjacentHTML('afterend','<div class="aui-range-tip aui-hide">'+params.element.value+'</div>');

+            var scaleWidth = (tooltipWidth / distance) * Math.abs(params.element.value - params.element.min);

+            params.element.nextSibling.style.left = (offsetLeft + scaleWidth - 11)+'px';

+            params.element.addEventListener("input",function(){

+                self._showTip(params.element,callback);

+            });

+            params.element.addEventListener("touchmove",function(){

+                self._showTip(params.element,callback);

+            });

+            params.element.addEventListener("touchend",function(){

+                self._hideTip(params.element);

+            });

+        },

+        _showTip: function(el,callback){

+            el.nextSibling.classList.remove("aui-hide");

+            var scaleWidth = (tooltipWidth / distance) * Math.abs(el.value - el.min);

+            el.nextSibling.style.left = (offsetLeft + scaleWidth - 11)+'px';

+            el.nextSibling.innerText = el.value;

+            callback({

+                value:el.value

+            });

+        },

+        _hideTip : function(el){

+            if (time) {

+                clearTimeout(time);

+            }

+            time = setTimeout(function() {

+                el.nextSibling.classList.add("aui-hide");

+            }, 1500);

+        }

+    }

+    window.auiRange = auiRange;

+})(window);

+

+

diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-scroll.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-scroll.js
new file mode 100644
index 0000000..88cd0c6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-scroll.js
@@ -0,0 +1,66 @@
+/**
+ * aui-scroll.js
+ * @author  流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	'use strict';
+	var isToBottom = false,isMoved = false;
+	var auiScroll = function (params,callback) {
+		this.extend(this.params, params);
+		this._init(params,callback);
+	}
+	auiScroll.prototype = {
+		params: {
+			listren:false,
+            distance: 100
+        },
+		_init : function(params,callback) {
+			var self = this;
+			if(self.params.listen){
+				document.body.addEventListener("touchmove", function(e){
+					self.scroll(callback);
+				});
+				document.body.addEventListener("touchend", function(e){
+					self.scroll(callback);
+				});
+			}
+			window.onscroll = function(){
+				self.scroll(callback);
+			}
+		},
+		scroll : function (callback) {
+			var self = this;
+			var clientHeight = document.documentElement.scrollTop === 0 ? document.body.clientHeight : document.documentElement.clientHeight;
+			var scrollTop = document.documentElement.scrollTop === 0 ? document.body.scrollTop : document.documentElement.scrollTop;
+			var scrollHeight = document.documentElement.scrollTop === 0 ? document.body.scrollHeight : document.documentElement.scrollHeight;
+
+			if (scrollHeight-scrollTop-self.params.distance <= window.innerHeight) {
+	        	isToBottom = true;
+	        	if(isToBottom){
+	        		callback({
+	        			"scrollTop":scrollTop,
+	        			"isToBottom":true
+	        		})
+	        	}
+	        }else{
+	        	isToBottom = false;
+	        	callback({
+        			"scrollTop":scrollTop,
+        			"isToBottom":false
+        		})
+	        }
+		},
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+	}
+	window.auiScroll = auiScroll;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-sharebox.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-sharebox.js
new file mode 100644
index 0000000..45b1513
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-sharebox.js
@@ -0,0 +1,119 @@
+/**
+ * aui-sharebox.js
+ * @author 流浪男
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiSharebox = function() {
+    };
+    var isShow = false;
+    auiSharebox.prototype = {
+        init: function(params,callback){
+            this.frameBounces = params.frameBounces;
+            this.col = params.col;
+            this.buttons = params.buttons;
+            this.cancelTitle = params.cancelTitle;
+            this.maskDiv;
+            this.shareBoxDiv;
+            var self = this;
+            self.open(params,callback);
+        },
+        open: function(params,callback) {
+            var shareboxHtml='',buttonsHtml = '';
+        	var self = this;
+            if(self.shareBoxDiv || !self.buttons)return;
+            if(!self.maskDiv){
+                self.maskDiv = document.createElement("div");
+                self.maskDiv.className = "aui-mask";
+                document.body.appendChild(self.maskDiv);
+            }
+            if(!self.col)self.col = 5;
+            self.shareBoxDiv = document.createElement("div");
+            self.shareBoxDiv.className = "aui-sharebox aui-grid";
+            document.body.appendChild(self.shareBoxDiv);
+            if(self.buttons && self.buttons.length){
+                buttonsHtml = '<div class="aui-row aui-row-padded">';
+                for(var i = 0; i < self.buttons.length;i++){
+                    if(self.col == 5){
+                        buttonsHtml += '<div class="aui-col-5 aui-sharebox-btn">';
+                    }else{
+                        buttonsHtml += '<div class="aui-col-xs-'+(12/self.col)+' aui-sharebox-btn">';
+                    }
+                    if(self.buttons[i].image)buttonsHtml += '<img src="'+self.buttons[i].image+'">';
+                    if(self.buttons[i].text)buttonsHtml += '<div class="aui-grid-label">'+self.buttons[i].text+'</div>';
+                    buttonsHtml += '</div>';
+                }
+                buttonsHtml += '</div>';
+            }
+            if(self.cancelTitle){
+                buttonsHtml += '<div class="aui-sharebox-close-btn aui-border-t">'+this.cancelTitle+'</div>';
+            }
+            self.shareBoxDiv.innerHTML = buttonsHtml;
+            var actionsheetHeight = self.shareBoxDiv.offsetHeight;
+            self.maskDiv.classList.add("aui-mask-in");
+            self.shareBoxDiv.style.webkitTransform = self.shareBoxDiv.style.transform = "translate3d(0,0,0)";
+            self.shareBoxDiv.style.opacity = 1;
+            self.shareBoxDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            self.maskDiv.addEventListener("touchmove", function(event){
+                event.preventDefault();
+            })
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:false
+                });
+            }
+            var shareboxButtons = document.querySelectorAll(".aui-sharebox-btn");
+            if(shareboxButtons && shareboxButtons.length > 0){
+                setTimeout(function(){
+                    self.maskDiv.onclick = function(){self.close();return;};
+                    for(var ii = 0; ii < shareboxButtons.length; ii++){
+                        (function(e){
+                            shareboxButtons[e].onclick = function(){
+                                if(self.buttons[e].value){
+                                    var _value = self.buttons[e].value;
+                                }else{
+                                    var _value = null;
+                                }
+                                if(callback){
+                                    callback({
+                                        buttonIndex: e+1,
+                                        buttonValue:_value
+                                    });
+                                };
+                                self.close();
+                                return;
+                            }
+                        })(ii)
+                    }
+                }, 350)
+
+            }
+            document.querySelector(".aui-sharebox-close-btn").onclick = function(){self.close();return;};
+        },
+        close: function(){
+            var self = this;
+            if(typeof(api) != 'undefined' && typeof(api) == 'object' && self.frameBounces){
+                api.setFrameAttr({
+                    bounces:true
+                });
+            }
+            if(self.shareBoxDiv){
+                var actionsheetHeight = self.shareBoxDiv.offsetHeight;
+                self.shareBoxDiv.style.webkitTransform = self.shareBoxDiv.style.transform = "translate3d(0,"+actionsheetHeight+"px,0)";
+                self.maskDiv.style.opacity = 0;
+                setTimeout(function(){
+                    if(self.maskDiv){
+                        self.maskDiv.parentNode.removeChild(self.maskDiv);
+                    }
+                    self.shareBoxDiv.parentNode.removeChild(self.shareBoxDiv);
+                    self.maskDiv = self.shareBoxDiv = false;
+                }, 300)
+            }
+        }
+    };
+	window.auiSharebox = auiSharebox;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-skin.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-skin.js
new file mode 100644
index 0000000..1bf6039
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-skin.js
@@ -0,0 +1,89 @@
+/**
+ * aui-skin.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiSkin = function(params) {
+    	this.extend(this.params, params);
+        this._init();
+    };
+    var fileRef;
+    auiSkin.prototype = {
+        params: {
+            name: "", //主题名字
+            skinPath:  "",//主题路径
+            default:   false, //默认是否立即使用
+            beginTime: "",//开始时间
+            endTime:   ""//结束时间
+        },
+        _init: function() {
+        	var self = this;
+            if(!self.params.name)return;
+        	if(!self.params.skinPath)return;
+            fileRef = document.createElement('link');
+            fileRef.setAttribute("rel","stylesheet");
+            fileRef.setAttribute("type","text/css");
+            fileRef.setAttribute("aui-skin-name",self.params.name);
+            fileRef.setAttribute("href",self.params.skinPath);
+            if(self.params.default){
+                document.getElementsByTagName("head")[0].appendChild(fileRef);
+            }else{
+                if(!self.params.beginTime || !self.params.endTime)return;
+                if(!self.check(self.params.beginTime,self.params.endTime))return;
+                var _date = new Date();
+                if(_date.getMinutes() < 10){
+                    var nowM = "0"+_date.getMinutes();
+                }else{
+                    var nowM = _date.getMinutes();
+                }
+                var nowTime = _date.getHours()+":"+nowM;
+                var b = parseInt(self.params.beginTime.replace(":", ''));
+                var e = parseInt(self.params.endTime.replace(":", ''));
+                var n = parseInt(nowTime.replace(":", ''));
+                if(b > e){
+                    if(n >= b || n <= e)self.setSkin();
+                }else if(b < e){
+                    if(n >= b && n <= e)self.setSkin();
+                }else{
+                    self.removeSkin();
+                }
+            }
+        },
+        setSkin:function(){
+            document.getElementsByTagName("head")[0].appendChild(fileRef);
+        },
+        removeSkin:function(){
+            var self = this;
+            if(document.querySelector("link[aui-skin-name='"+self.params.name+"']"))
+            document.querySelector("link[aui-skin-name='"+self.params.name+"']").parentNode.removeChild(document.querySelector("link[aui-skin-name='"+self.params.name+"']"));
+        },
+        check:function(beginTime,endTime){
+            var strb = beginTime.split (":");
+            if (strb.length != 2)return false;
+            var stre = endTime.split (":");
+            if (stre.length != 2)return false;
+            var b = new Date ();
+            var e = new Date ();
+            b.setHours (strb[0]);
+            b.setMinutes (strb[1]);
+            e.setHours (stre[0]);
+            e.setMinutes (stre[1]);
+            if(strb[0] > 24 || strb[0] < 0 || stre[0] > 24 || stre[0] < 0)return false;
+            if(strb[1] > 59 || strb[1] < 0 || stre[1] > 59 || stre[1] < 0)return false;
+            return true;
+        },
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+    };
+	window.auiSkin = auiSkin;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-slide.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-slide.js
new file mode 100644
index 0000000..2f44157
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-slide.js
@@ -0,0 +1,333 @@
+/**
+ * aui-slide.js 轮播组件
+ * @author 流浪男
+ * http://www.auicss.com
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function(window) {
+	"use strict";
+
+	var translateVal,
+		firstTouchX,
+		firstTouchY,
+		touchXDelta,
+		handleTranslateVal;
+	var touchStartTime; //开始触摸事件
+	var offsetX,
+		offsetY,
+		isScrolling;
+	// CLASS 组装
+	var	CLASS_SLIDER_NODE = "aui-slide-node",
+		CLASS_SLIDE_PAGE_WRAP = "aui-slide-page-wrap",
+		CLASS_SLIDE_PAGE = "aui-slide-page",
+		CLASS_SLIDE_PAGE_ACTIVE = "aui-slide-page-active",
+		CLASS_SLIDE_PAGE_DOT = "aui-slide-page-dot",
+		CLASS_SLIDE_PAGE_LINE = "aui-slide-page-line";
+
+	var __SLIDER_NODE = "."+CLASS_SLIDER_NODE,
+		__SLIDE_PAGE_WRAP = "."+CLASS_SLIDE_PAGE_WRAP,
+		__SLIDE_PAGE = "."+CLASS_SLIDE_PAGE,
+		__SLIDE_PAGE_ACTIVE = "."+CLASS_SLIDE_PAGE_ACTIVE;
+
+	auiSlide.prototype.options = {
+		container:'',
+		width:'auto',
+		height:'auto',
+		speed: 300, //滑动速速
+		autoPlay: 0, //自动播放
+		pageShow: true, //是否显示分页器
+		pageStyle: 'dot',
+		dotPosition: 'center',
+		friction:1, //阻力
+		loop:true,
+		currentPage:false,
+		PageCount:false
+	};
+	auiSlide.prototype._init = function(options) {
+		extend(this.options, options);
+		if(!this.options.container){
+			return;
+		}
+		this.index = 0; //索引值
+		this.continuous = true;//用于判断长度为2时的特殊处理
+		this.container = this.options.container;
+		// console.log(this.options.loop);
+		this.loop = this.options.loop;
+		this.speed = this.options.speed;
+		this.container.style.position = "relative";
+		this.container.style.width = this.options.width+"px";
+		this.container.style.height = this.options.height+"px";
+
+		var element = this.container.children[0];
+		this.slideWrap = element;
+		this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
+		if(!element || !this.slideNodeList){
+			return;
+		}
+		// this.options.pageCount(this.slideNodeList.length);
+		this.slideWrapWidth = this.slideWrap.offsetWidth;
+		this.slideNodeListLength = this.slideNodeList.length;
+
+		if (this.slideNodeListLength == 2) { //当长度为2时作特殊处理
+			element.appendChild(this.slideWrap.children[0].cloneNode(true));
+			element.appendChild(this.slideWrap.children[1].cloneNode(true));
+			this.slideWrap = element;
+			this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
+	    	this.slideNodeListLength = this.slideNodeList.length;
+	    	this.continuous = false;
+	    }
+		for (var i = 0; i < this.slideNodeListLength; i++) {
+			this.slideNodeList[i] && (this.slideNodeList[i].style.webkitTransform = this.slideNodeList[i].style.transform = "translate3d("+(this.slideWrapWidth*i)+"px,0,0)");
+		}
+
+		if(this.slideNodeListLength > 1) {
+			if(this.options.pageShow){
+				this.createPagination(0);
+				this.setPageDotPosition();
+			}
+			if(this.options.autoPlay > 500 && this.loop){
+				this.autoPlay(0);
+			}
+			this.slideWrap.addEventListener('touchstart', this.touchStart.bind(this), false);
+			this.slideWrap.addEventListener('touchmove', this.touchMove.bind(this), false);
+			this.slideWrap.addEventListener('touchend', this.touchEnd.bind(this), false);
+		}
+	};
+	// 当分页器为圆点时位置设置
+	auiSlide.prototype.setPageDotPosition = function(){
+		var self = this;
+		var pageDotPosition = self.options.dotPosition;
+		this.container.querySelector(__SLIDE_PAGE_WRAP).style.textAlign = pageDotPosition;
+	};
+	// 自动播放
+	auiSlide.prototype.autoPlay = function (index) {
+		var self = this;
+		setInterval(function(){
+			self.slideTo(self.getCircle(self.index-1), -self.slideWrapWidth, 0);
+	        self.slideTo(self.getCircle(self.index+2), self.slideWrapWidth, 0);
+	        self.slideTo(self.index, -self.slideWrapWidth, self.options.speed);
+	        self.slideTo(self.getCircle(self.index+1), 0, self.options.speed);
+	        self.index = self.getCircle(self.index+1);
+	        self.setPaginationActive(self.index);
+		}, self.options.autoPlay)
+	};
+	// 设置当前分页
+	auiSlide.prototype.setPaginationActive = function(index){
+		var self = this;
+		if(self.options.currentPage){
+			self.options.currentPage(index);
+		}
+		if(!this.container.querySelector(__SLIDE_PAGE_WRAP)){
+			return;
+		}
+		var pageList = this.container.querySelectorAll(__SLIDE_PAGE);
+		if(this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE)){
+			this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE).classList.remove(CLASS_SLIDE_PAGE_ACTIVE);
+		}
+		if(!this.continuous){
+			if(this.index == 3){
+				pageList[1].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}else if(this.index==2){
+				pageList[0].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}else{
+				pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+			}
+		}else{
+			pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
+		}
+
+	};
+	// 创建分页器
+	auiSlide.prototype.createPagination = function(index){
+		var self = this;
+		var pageWrap = this.container.querySelector(__SLIDE_PAGE_WRAP);
+		if(!pageWrap){
+			return;
+		}
+		pageWrap.innerHTML = '';
+		var pageShowHtml = '';
+		switch (self.options.pageStyle) {
+			case "dot":// 原点
+						if (!this.continuous) {
+							for (var i = 0; i < 2; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
+							}
+						}else{
+							for (var i = 0; i < this.slideNodeListLength; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
+							}
+						}
+						pageWrap.innerHTML = pageShowHtml;
+						self.setPaginationActive(0);
+				break;
+			case "line":// 线条
+						if (!this.continuous) {
+							for (var i = 0; i < 2; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:50%"></span>';
+							}
+						}else{
+							for (var i = 0; i < this.slideNodeListLength; i++) {
+								pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:'+(100/this.slideNodeListLength)+'%"></span>';
+							}
+						}
+						pageWrap.innerHTML = pageShowHtml;
+						self.setPaginationActive(0);
+				break;
+		}
+	};
+	// 总页数
+	auiSlide.prototype.pageCount = function() {
+		var self = this;
+		return self.slideNodeList.length;
+	};
+	auiSlide.prototype.touchStart = function(event) {
+		touchStartTime = new Date() * 1;
+		firstTouchX = parseInt(event.changedTouches[0].pageX);
+		firstTouchY = parseInt(event.changedTouches[0].pageY);
+		isScrolling = undefined;
+	};
+	auiSlide.prototype.touchMove = function(event) {
+		var touchMoveObj = event.changedTouches[0],
+				touchX = parseInt(touchMoveObj.pageX);
+			touchXDelta = touchX - firstTouchX;
+			handleTranslateVal = touchXDelta/this.options.friction;
+		//  滑动位移
+		offsetX = parseInt(touchMoveObj.pageX) - firstTouchX;
+        offsetY = parseInt(touchMoveObj.pageY) - firstTouchY;
+        var direction = this.getDirection(offsetX,offsetY);
+        if ( typeof isScrolling == 'undefined') {
+			isScrolling = !!( isScrolling || Math.abs(offsetX) < Math.abs(offsetY) );
+		}
+		if(!isScrolling){
+			event.preventDefault();
+			if(!this.loop){ //不循环
+				if(!this.continuous && this.index==1 && direction=='left'){
+					return;
+				}
+				if(!this.continuous && this.index==0 && direction=='right'){
+					return;
+				}
+				if(this.index == this.slideNodeList.length-1){
+					if(handleTranslateVal <= 0){
+						return;
+					}
+					this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
+				}else if(this.index == 0){
+					if(handleTranslateVal >= 0){
+						return;
+					}
+					this.setTranslate(this.getCircle(this.index+1), this.slideWrapWidth, 0);
+				}
+			}
+
+			this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
+			this.setTranslate(this.index, handleTranslateVal , 0);
+			this.setTranslate(this.getCircle(this.index+1), handleTranslateVal + this.slideWrapWidth, 0);
+
+		}
+	};
+	auiSlide.prototype.touchEnd = function(event) {
+		var touchEndObj = event.changedTouches[0];
+		var touchEndX = parseInt(touchEndObj.pageX) - firstTouchX;
+        var touchEndY = parseInt(touchEndObj.pageY) - firstTouchY;
+		var touchEndxy = {
+				x: touchEndObj.pageX || 0,
+				y: touchEndObj.pageY || 0
+			};
+		var moveDirection = this.getDirection(touchEndX,touchEndY); //滑动方向
+		var boundary = this.slideWrapWidth/4;
+		var duration = (new Date() * 1) - touchStartTime;
+		var isValid = Number(duration) < 250 && Math.abs(offsetX) > 20 || Math.abs(offsetX) > boundary;
+		if (isScrolling) {
+			return;
+		}
+        if(isValid){
+			if(offsetX < 0){
+				if(!this.loop && this.index == this.slideNodeList.length-1){
+					return;
+				}
+
+				if(!this.loop && !this.continuous && this.index==1){
+					return;
+				}
+
+	        	if(offsetX < -boundary && moveDirection == 'left'){
+	        		// left
+					this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, 0);
+		            this.slideTo(this.getCircle(this.index+2), this.slideWrapWidth, 0);
+		            this.slideTo(this.index, -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), 0, this.speed);
+		            this.index = this.getCircle(this.index+1);
+				}else{
+					// this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.index, 0, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+				}
+	        }else if(offsetX > 0){
+	        	if(!this.loop && this.index == 0){
+					return;
+				}
+				if(!this.loop && !this.continuous && this.index==0){
+					return;
+				}
+	        	if(offsetX > boundary && moveDirection == 'right'){
+	        		// right
+		        	this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, 0);
+		            this.slideTo(this.getCircle(this.index-2), -this.slideWrapWidth, 0);
+		            this.slideTo(this.index, this.slideWrapWidth, this.speed);
+		            this.slideTo(this.getCircle(this.index-1), 0, this.speed);
+		            this.index = this.getCircle(this.index-1);
+	        	}else{
+	        		// this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+		            this.slideTo(this.index, 0, this.speed);
+		            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+	        	}
+	        }
+        }else{
+        	if(offsetX){
+        		this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
+	            this.slideTo(this.index, 0, this.speed);
+	            this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
+        	}
+
+        }
+        this.setPaginationActive(this.index);
+	};
+	auiSlide.prototype.setTranslate = function (index,dist,speed){
+		if(this.slideNodeList[index]){
+			this.slideNodeList[index].style.webkitTransitionDuration =
+	    	this.slideNodeList[index].style.transitionDuration = speed + 'ms';
+	    	this.slideNodeList[index].style.webkitTransform =
+	    	this.slideNodeList[index].style.transform = "translate3d("+dist+"px,0,0)";
+		}
+	};
+	auiSlide.prototype.slideTo = function (index, dist, speed) {
+		this.setTranslate(index, dist, speed);
+		// index = dist;
+	};
+	auiSlide.prototype.getCircle = function (index) {
+	    return (this.slideNodeListLength + (index % this.slideNodeListLength)) % this.slideNodeListLength;
+	};
+	auiSlide.prototype.getDirection = function(x, y) {
+		if (x === y) { return '';}
+		if (Math.abs(x) >= Math.abs(y)) {
+            return x > 0 ? 'right' : 'left';
+        } else {
+           	return y > 0 ? 'down' : 'up';
+        }
+	}
+	function extend (a, b) {
+		for (var key in b) {
+		  	if (b.hasOwnProperty(key)) {
+		  		a[key] = b[key];
+		  	}
+	  	}
+	  	return a;
+	}
+	function auiSlide (options) {
+		this._init(options);
+	}
+	window.auiSlide = auiSlide;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-tab.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-tab.js
new file mode 100644
index 0000000..cb228c4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-tab.js
@@ -0,0 +1,69 @@
+/**
+ * aui-tab.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiTab = function(params,callback) {
+    	this.extend(this.params, params);
+        this._init(callback);
+    };
+    var tabItems;
+    auiTab.prototype = {
+        params: {
+            element: false,
+            index: 1, //默认选中
+            repeatClick: false //是否允许重复点击
+        },
+        _init: function(callback) {
+        	var self = this;
+        	if(!self.params.element || self.params.element.nodeType!=1){
+        		return;
+        	}
+        	tabItems = self.params.element.children;
+        	if(tabItems){
+        		self.setActive();
+        		for(var i=0; i<tabItems.length; i++){
+        			tabItems[i].setAttribute("tapmode","");
+        			tabItems[i].setAttribute("data-item-order",i);
+        			tabItems[i].onclick = function(e){
+                        if(!self.params.repeatClick){
+                            if(this.className.indexOf("aui-active") > -1)return;
+                        }
+        				if(callback){
+                            callback({
+                                index: parseInt(this.getAttribute("data-item-order"))+1,
+                                dom:this
+                            })
+                        };
+        				this.parentNode.querySelector(".aui-active").classList.remove("aui-active");
+            			this.classList.add("aui-active");
+        			}
+        		}
+        	}
+        },
+        setRepeat:function(value){
+            var self = this;
+            self.params.repeatClick = value ? value : false;
+        },
+        setActive: function(index){
+        	var self = this;
+        	index = index ? index : self.params.index;
+        	var _tab = tabItems[index-1];
+        	if(_tab.parentNode.querySelector(".aui-active"))_tab.parentNode.querySelector(".aui-active").classList.remove("aui-active");
+        	_tab.classList.add("aui-active");
+        },
+        extend: function(a, b) {
+			for (var key in b) {
+			  	if (b.hasOwnProperty(key)) {
+			  		a[key] = b[key];
+			  	}
+		  	}
+		  	return a;
+		}
+    };
+	window.auiTab = auiTab;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-toast.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-toast.js
new file mode 100644
index 0000000..68d41f6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/aui-toast.js
@@ -0,0 +1,92 @@
+/**
+ * aui-popup.js
+ * @author 流浪男
+ * @todo more things to abstract, e.g. Loading css etc.
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function( window, undefined ) {
+    "use strict";
+    var auiToast = function() {
+        // this.create();
+    };
+    var isShow = false;
+    auiToast.prototype = {
+        create: function(params,callback) {
+            var self = this;
+            var toastHtml = '';
+            switch (params.type) {
+                case "success":
+                    var iconHtml = '<i class="aui-iconfont aui-icon-correct"></i>';
+                    break;
+                case "fail":
+                    var iconHtml = '<i class="aui-iconfont aui-icon-close"></i>';
+                    break;
+                case "custom":
+                    var iconHtml = params.html;
+                    break;
+                case "loading":
+                    var iconHtml = '<div class="aui-toast-loading"></div>';
+                    break;
+            }
+
+            var titleHtml = params.title ? '<div class="aui-toast-content">'+params.title+'</div>' : '';
+            toastHtml = '<div class="aui-toast">'+iconHtml+titleHtml+'</div>';
+            if(document.querySelector(".aui-toast"))return;
+            document.body.insertAdjacentHTML('beforeend', toastHtml);
+            var duration = params.duration ? params.duration : "2000";
+            self.show();
+            if(params.type == 'loading'){
+                if(callback){
+                    callback({
+                        status: "success"
+                    });
+                };
+            }else{
+                setTimeout(function(){
+                    self.hide();
+                }, duration)
+            }
+        },
+        show: function(){
+            var self = this;
+            document.querySelector(".aui-toast").style.display = "block";
+            document.querySelector(".aui-toast").style.marginTop =  "-"+Math.round(document.querySelector(".aui-toast").offsetHeight/2)+"px";
+            if(document.querySelector(".aui-toast"))return;
+        },
+        hide: function(){
+            var self = this;
+            if(document.querySelector(".aui-toast")){
+                document.querySelector(".aui-toast").parentNode.removeChild(document.querySelector(".aui-toast"));
+            }
+        },
+        remove: function(){
+            if(document.querySelector(".aui-dialog"))document.querySelector(".aui-dialog").parentNode.removeChild(document.querySelector(".aui-dialog"));
+            if(document.querySelector(".aui-mask")){
+                document.querySelector(".aui-mask").classList.remove("aui-mask-out");
+            }
+            return true;
+        },
+        success: function(params,callback){
+            var self = this;
+            params.type = "success";
+            return self.create(params,callback);
+        },
+        fail: function(params,callback){
+            var self = this;
+            params.type = "fail";
+            return self.create(params,callback);
+        },
+        custom:function(params,callback){
+            var self = this;
+            params.type = "custom";
+            return self.create(params,callback);
+        },
+        loading:function(params,callback){
+            var self = this;
+            params.type = "loading";
+            return self.create(params,callback);
+        }
+    };
+    window.auiToast = auiToast;
+})(window);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.js
new file mode 100755
index 0000000..129755d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.js
@@ -0,0 +1,16713 @@
+// jshint ignore: start
++function($){
+
+$.rawCitiesData = [
+  {
+    "name":"北京",
+    "code":"110000",
+    "sub": [
+      {
+        "name": "北京市",
+        "code": "110000",
+        "sub":[
+            {
+              "name":"东城区",
+              "code":"110101"
+            },
+            {
+              "name":"西城区",
+              "code":"110102"
+            },
+            {
+              "name":"朝阳区",
+              "code":"110105"
+            },
+            {
+              "name":"丰台区",
+              "code":"110106"
+            },
+            {
+              "name":"石景山区",
+              "code":"110107"
+            },
+            {
+              "name":"海淀区",
+              "code":"110108"
+            },
+            {
+              "name":"门头沟区",
+              "code":"110109"
+            },
+            {
+              "name":"房山区",
+              "code":"110111"
+            },
+            {
+              "name":"通州区",
+              "code":"110112"
+            },
+            {
+              "name":"顺义区",
+              "code":"110113"
+            },
+            {
+              "name":"昌平区",
+              "code":"110114"
+            },
+            {
+              "name":"大兴区",
+              "code":"110115"
+            },
+            {
+              "name":"怀柔区",
+              "code":"110116"
+            },
+            {
+              "name":"平谷区",
+              "code":"110117"
+            },
+            {
+              "name":"密云县",
+              "code":"110228"
+            },
+            {
+              "name":"延庆县",
+              "code":"110229"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"天津",
+    "code":"120000",
+    "sub": [
+      {
+        "name": "天津市",
+        "code": "120000",
+        "sub":[
+            {
+              "name":"和平区",
+              "code":"120101"
+            },
+            {
+              "name":"河东区",
+              "code":"120102"
+            },
+            {
+              "name":"河西区",
+              "code":"120103"
+            },
+            {
+              "name":"南开区",
+              "code":"120104"
+            },
+            {
+              "name":"河北区",
+              "code":"120105"
+            },
+            {
+              "name":"红桥区",
+              "code":"120106"
+            },
+            {
+              "name":"东丽区",
+              "code":"120110"
+            },
+            {
+              "name":"西青区",
+              "code":"120111"
+            },
+            {
+              "name":"津南区",
+              "code":"120112"
+            },
+            {
+              "name":"北辰区",
+              "code":"120113"
+            },
+            {
+              "name":"武清区",
+              "code":"120114"
+            },
+            {
+              "name":"宝坻区",
+              "code":"120115"
+            },
+            {
+              "name":"滨海新区",
+              "code":"120116"
+            },
+            {
+              "name":"宁河县",
+              "code":"120221"
+            },
+            {
+              "name":"静海县",
+              "code":"120223"
+            },
+            {
+              "name":"蓟县",
+              "code":"120225"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"河北省",
+    "code":"130000",
+    "sub":[
+      {
+        "name":"石家庄市",
+        "code":"130100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130101"
+          },
+          {
+            "name":"长安区",
+            "code":"130102"
+          },
+          {
+            "name":"桥西区",
+            "code":"130104"
+          },
+          {
+            "name":"新华区",
+            "code":"130105"
+          },
+          {
+            "name":"井陉矿区",
+            "code":"130107"
+          },
+          {
+            "name":"裕华区",
+            "code":"130108"
+          },
+          {
+            "name":"藁城区",
+            "code":"130109"
+          },
+          {
+            "name":"鹿泉区",
+            "code":"130110"
+          },
+          {
+            "name":"栾城区",
+            "code":"130111"
+          },
+          {
+            "name":"井陉县",
+            "code":"130121"
+          },
+          {
+            "name":"正定县",
+            "code":"130123"
+          },
+          {
+            "name":"行唐县",
+            "code":"130125"
+          },
+          {
+            "name":"灵寿县",
+            "code":"130126"
+          },
+          {
+            "name":"高邑县",
+            "code":"130127"
+          },
+          {
+            "name":"深泽县",
+            "code":"130128"
+          },
+          {
+            "name":"赞皇县",
+            "code":"130129"
+          },
+          {
+            "name":"无极县",
+            "code":"130130"
+          },
+          {
+            "name":"平山县",
+            "code":"130131"
+          },
+          {
+            "name":"元氏县",
+            "code":"130132"
+          },
+          {
+            "name":"赵县",
+            "code":"130133"
+          },
+          {
+            "name":"辛集市",
+            "code":"130181"
+          },
+          {
+            "name":"晋州市",
+            "code":"130183"
+          },
+          {
+            "name":"新乐市",
+            "code":"130184"
+          }
+        ]
+      },
+      {
+        "name":"唐山市",
+        "code":"130200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130201"
+          },
+          {
+            "name":"路南区",
+            "code":"130202"
+          },
+          {
+            "name":"路北区",
+            "code":"130203"
+          },
+          {
+            "name":"古冶区",
+            "code":"130204"
+          },
+          {
+            "name":"开平区",
+            "code":"130205"
+          },
+          {
+            "name":"丰南区",
+            "code":"130207"
+          },
+          {
+            "name":"丰润区",
+            "code":"130208"
+          },
+          {
+            "name":"曹妃甸区",
+            "code":"130209"
+          },
+          {
+            "name":"滦县",
+            "code":"130223"
+          },
+          {
+            "name":"滦南县",
+            "code":"130224"
+          },
+          {
+            "name":"乐亭县",
+            "code":"130225"
+          },
+          {
+            "name":"迁西县",
+            "code":"130227"
+          },
+          {
+            "name":"玉田县",
+            "code":"130229"
+          },
+          {
+            "name":"遵化市",
+            "code":"130281"
+          },
+          {
+            "name":"迁安市",
+            "code":"130283"
+          }
+        ]
+      },
+      {
+        "name":"秦皇岛市",
+        "code":"130300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130301"
+          },
+          {
+            "name":"海港区",
+            "code":"130302"
+          },
+          {
+            "name":"山海关区",
+            "code":"130303"
+          },
+          {
+            "name":"北戴河区",
+            "code":"130304"
+          },
+          {
+            "name":"青龙满族自治县",
+            "code":"130321"
+          },
+          {
+            "name":"昌黎县",
+            "code":"130322"
+          },
+          {
+            "name":"抚宁县",
+            "code":"130323"
+          },
+          {
+            "name":"卢龙县",
+            "code":"130324"
+          }
+        ]
+      },
+      {
+        "name":"邯郸市",
+        "code":"130400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130401"
+          },
+          {
+            "name":"邯山区",
+            "code":"130402"
+          },
+          {
+            "name":"丛台区",
+            "code":"130403"
+          },
+          {
+            "name":"复兴区",
+            "code":"130404"
+          },
+          {
+            "name":"峰峰矿区",
+            "code":"130406"
+          },
+          {
+            "name":"邯郸县",
+            "code":"130421"
+          },
+          {
+            "name":"临漳县",
+            "code":"130423"
+          },
+          {
+            "name":"成安县",
+            "code":"130424"
+          },
+          {
+            "name":"大名县",
+            "code":"130425"
+          },
+          {
+            "name":"涉县",
+            "code":"130426"
+          },
+          {
+            "name":"磁县",
+            "code":"130427"
+          },
+          {
+            "name":"肥乡县",
+            "code":"130428"
+          },
+          {
+            "name":"永年县",
+            "code":"130429"
+          },
+          {
+            "name":"邱县",
+            "code":"130430"
+          },
+          {
+            "name":"鸡泽县",
+            "code":"130431"
+          },
+          {
+            "name":"广平县",
+            "code":"130432"
+          },
+          {
+            "name":"馆陶县",
+            "code":"130433"
+          },
+          {
+            "name":"魏县",
+            "code":"130434"
+          },
+          {
+            "name":"曲周县",
+            "code":"130435"
+          },
+          {
+            "name":"武安市",
+            "code":"130481"
+          }
+        ]
+      },
+      {
+        "name":"邢台市",
+        "code":"130500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130501"
+          },
+          {
+            "name":"桥东区",
+            "code":"130502"
+          },
+          {
+            "name":"桥西区",
+            "code":"130503"
+          },
+          {
+            "name":"邢台县",
+            "code":"130521"
+          },
+          {
+            "name":"临城县",
+            "code":"130522"
+          },
+          {
+            "name":"内丘县",
+            "code":"130523"
+          },
+          {
+            "name":"柏乡县",
+            "code":"130524"
+          },
+          {
+            "name":"隆尧县",
+            "code":"130525"
+          },
+          {
+            "name":"任县",
+            "code":"130526"
+          },
+          {
+            "name":"南和县",
+            "code":"130527"
+          },
+          {
+            "name":"宁晋县",
+            "code":"130528"
+          },
+          {
+            "name":"巨鹿县",
+            "code":"130529"
+          },
+          {
+            "name":"新河县",
+            "code":"130530"
+          },
+          {
+            "name":"广宗县",
+            "code":"130531"
+          },
+          {
+            "name":"平乡县",
+            "code":"130532"
+          },
+          {
+            "name":"威县",
+            "code":"130533"
+          },
+          {
+            "name":"清河县",
+            "code":"130534"
+          },
+          {
+            "name":"临西县",
+            "code":"130535"
+          },
+          {
+            "name":"南宫市",
+            "code":"130581"
+          },
+          {
+            "name":"沙河市",
+            "code":"130582"
+          }
+        ]
+      },
+      {
+        "name":"保定市",
+        "code":"130600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130601"
+          },
+          {
+            "name":"新市区",
+            "code":"130602"
+          },
+          {
+            "name":"北市区",
+            "code":"130603"
+          },
+          {
+            "name":"南市区",
+            "code":"130604"
+          },
+          {
+            "name":"满城县",
+            "code":"130621"
+          },
+          {
+            "name":"清苑县",
+            "code":"130622"
+          },
+          {
+            "name":"涞水县",
+            "code":"130623"
+          },
+          {
+            "name":"阜平县",
+            "code":"130624"
+          },
+          {
+            "name":"徐水县",
+            "code":"130625"
+          },
+          {
+            "name":"定兴县",
+            "code":"130626"
+          },
+          {
+            "name":"唐县",
+            "code":"130627"
+          },
+          {
+            "name":"高阳县",
+            "code":"130628"
+          },
+          {
+            "name":"容城县",
+            "code":"130629"
+          },
+          {
+            "name":"涞源县",
+            "code":"130630"
+          },
+          {
+            "name":"望都县",
+            "code":"130631"
+          },
+          {
+            "name":"安新县",
+            "code":"130632"
+          },
+          {
+            "name":"易县",
+            "code":"130633"
+          },
+          {
+            "name":"曲阳县",
+            "code":"130634"
+          },
+          {
+            "name":"蠡县",
+            "code":"130635"
+          },
+          {
+            "name":"顺平县",
+            "code":"130636"
+          },
+          {
+            "name":"博野县",
+            "code":"130637"
+          },
+          {
+            "name":"雄县",
+            "code":"130638"
+          },
+          {
+            "name":"涿州市",
+            "code":"130681"
+          },
+          {
+            "name":"定州市",
+            "code":"130682"
+          },
+          {
+            "name":"安国市",
+            "code":"130683"
+          },
+          {
+            "name":"高碑店市",
+            "code":"130684"
+          }
+        ]
+      },
+      {
+        "name":"张家口市",
+        "code":"130700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130701"
+          },
+          {
+            "name":"桥东区",
+            "code":"130702"
+          },
+          {
+            "name":"桥西区",
+            "code":"130703"
+          },
+          {
+            "name":"宣化区",
+            "code":"130705"
+          },
+          {
+            "name":"下花园区",
+            "code":"130706"
+          },
+          {
+            "name":"宣化县",
+            "code":"130721"
+          },
+          {
+            "name":"张北县",
+            "code":"130722"
+          },
+          {
+            "name":"康保县",
+            "code":"130723"
+          },
+          {
+            "name":"沽源县",
+            "code":"130724"
+          },
+          {
+            "name":"尚义县",
+            "code":"130725"
+          },
+          {
+            "name":"蔚县",
+            "code":"130726"
+          },
+          {
+            "name":"阳原县",
+            "code":"130727"
+          },
+          {
+            "name":"怀安县",
+            "code":"130728"
+          },
+          {
+            "name":"万全县",
+            "code":"130729"
+          },
+          {
+            "name":"怀来县",
+            "code":"130730"
+          },
+          {
+            "name":"涿鹿县",
+            "code":"130731"
+          },
+          {
+            "name":"赤城县",
+            "code":"130732"
+          },
+          {
+            "name":"崇礼县",
+            "code":"130733"
+          }
+        ]
+      },
+      {
+        "name":"承德市",
+        "code":"130800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130801"
+          },
+          {
+            "name":"双桥区",
+            "code":"130802"
+          },
+          {
+            "name":"双滦区",
+            "code":"130803"
+          },
+          {
+            "name":"鹰手营子矿区",
+            "code":"130804"
+          },
+          {
+            "name":"承德县",
+            "code":"130821"
+          },
+          {
+            "name":"兴隆县",
+            "code":"130822"
+          },
+          {
+            "name":"平泉县",
+            "code":"130823"
+          },
+          {
+            "name":"滦平县",
+            "code":"130824"
+          },
+          {
+            "name":"隆化县",
+            "code":"130825"
+          },
+          {
+            "name":"丰宁满族自治县",
+            "code":"130826"
+          },
+          {
+            "name":"宽城满族自治县",
+            "code":"130827"
+          },
+          {
+            "name":"围场满族蒙古族自治县",
+            "code":"130828"
+          }
+        ]
+      },
+      {
+        "name":"沧州市",
+        "code":"130900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"130901"
+          },
+          {
+            "name":"新华区",
+            "code":"130902"
+          },
+          {
+            "name":"运河区",
+            "code":"130903"
+          },
+          {
+            "name":"沧县",
+            "code":"130921"
+          },
+          {
+            "name":"青县",
+            "code":"130922"
+          },
+          {
+            "name":"东光县",
+            "code":"130923"
+          },
+          {
+            "name":"海兴县",
+            "code":"130924"
+          },
+          {
+            "name":"盐山县",
+            "code":"130925"
+          },
+          {
+            "name":"肃宁县",
+            "code":"130926"
+          },
+          {
+            "name":"南皮县",
+            "code":"130927"
+          },
+          {
+            "name":"吴桥县",
+            "code":"130928"
+          },
+          {
+            "name":"献县",
+            "code":"130929"
+          },
+          {
+            "name":"孟村回族自治县",
+            "code":"130930"
+          },
+          {
+            "name":"泊头市",
+            "code":"130981"
+          },
+          {
+            "name":"任丘市",
+            "code":"130982"
+          },
+          {
+            "name":"黄骅市",
+            "code":"130983"
+          },
+          {
+            "name":"河间市",
+            "code":"130984"
+          }
+        ]
+      },
+      {
+        "name":"廊坊市",
+        "code":"131000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"131001"
+          },
+          {
+            "name":"安次区",
+            "code":"131002"
+          },
+          {
+            "name":"广阳区",
+            "code":"131003"
+          },
+          {
+            "name":"固安县",
+            "code":"131022"
+          },
+          {
+            "name":"永清县",
+            "code":"131023"
+          },
+          {
+            "name":"香河县",
+            "code":"131024"
+          },
+          {
+            "name":"大城县",
+            "code":"131025"
+          },
+          {
+            "name":"文安县",
+            "code":"131026"
+          },
+          {
+            "name":"大厂回族自治县",
+            "code":"131028"
+          },
+          {
+            "name":"霸州市",
+            "code":"131081"
+          },
+          {
+            "name":"三河市",
+            "code":"131082"
+          }
+        ]
+      },
+      {
+        "name":"衡水市",
+        "code":"131100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"131101"
+          },
+          {
+            "name":"桃城区",
+            "code":"131102"
+          },
+          {
+            "name":"枣强县",
+            "code":"131121"
+          },
+          {
+            "name":"武邑县",
+            "code":"131122"
+          },
+          {
+            "name":"武强县",
+            "code":"131123"
+          },
+          {
+            "name":"饶阳县",
+            "code":"131124"
+          },
+          {
+            "name":"安平县",
+            "code":"131125"
+          },
+          {
+            "name":"故城县",
+            "code":"131126"
+          },
+          {
+            "name":"景县",
+            "code":"131127"
+          },
+          {
+            "name":"阜城县",
+            "code":"131128"
+          },
+          {
+            "name":"冀州市",
+            "code":"131181"
+          },
+          {
+            "name":"深州市",
+            "code":"131182"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"山西省",
+    "code":"140000",
+    "sub":[
+      {
+        "name":"太原市",
+        "code":"140100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140101"
+          },
+          {
+            "name":"小店区",
+            "code":"140105"
+          },
+          {
+            "name":"迎泽区",
+            "code":"140106"
+          },
+          {
+            "name":"杏花岭区",
+            "code":"140107"
+          },
+          {
+            "name":"尖草坪区",
+            "code":"140108"
+          },
+          {
+            "name":"万柏林区",
+            "code":"140109"
+          },
+          {
+            "name":"晋源区",
+            "code":"140110"
+          },
+          {
+            "name":"清徐县",
+            "code":"140121"
+          },
+          {
+            "name":"阳曲县",
+            "code":"140122"
+          },
+          {
+            "name":"娄烦县",
+            "code":"140123"
+          },
+          {
+            "name":"古交市",
+            "code":"140181"
+          }
+        ]
+      },
+      {
+        "name":"大同市",
+        "code":"140200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140201"
+          },
+          {
+            "name":"城区",
+            "code":"140202"
+          },
+          {
+            "name":"矿区",
+            "code":"140203"
+          },
+          {
+            "name":"南郊区",
+            "code":"140211"
+          },
+          {
+            "name":"新荣区",
+            "code":"140212"
+          },
+          {
+            "name":"阳高县",
+            "code":"140221"
+          },
+          {
+            "name":"天镇县",
+            "code":"140222"
+          },
+          {
+            "name":"广灵县",
+            "code":"140223"
+          },
+          {
+            "name":"灵丘县",
+            "code":"140224"
+          },
+          {
+            "name":"浑源县",
+            "code":"140225"
+          },
+          {
+            "name":"左云县",
+            "code":"140226"
+          },
+          {
+            "name":"大同县",
+            "code":"140227"
+          }
+        ]
+      },
+      {
+        "name":"阳泉市",
+        "code":"140300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140301"
+          },
+          {
+            "name":"城区",
+            "code":"140302"
+          },
+          {
+            "name":"矿区",
+            "code":"140303"
+          },
+          {
+            "name":"郊区",
+            "code":"140311"
+          },
+          {
+            "name":"平定县",
+            "code":"140321"
+          },
+          {
+            "name":"盂县",
+            "code":"140322"
+          }
+        ]
+      },
+      {
+        "name":"长治市",
+        "code":"140400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140401"
+          },
+          {
+            "name":"城区",
+            "code":"140402"
+          },
+          {
+            "name":"郊区",
+            "code":"140411"
+          },
+          {
+            "name":"长治县",
+            "code":"140421"
+          },
+          {
+            "name":"襄垣县",
+            "code":"140423"
+          },
+          {
+            "name":"屯留县",
+            "code":"140424"
+          },
+          {
+            "name":"平顺县",
+            "code":"140425"
+          },
+          {
+            "name":"黎城县",
+            "code":"140426"
+          },
+          {
+            "name":"壶关县",
+            "code":"140427"
+          },
+          {
+            "name":"长子县",
+            "code":"140428"
+          },
+          {
+            "name":"武乡县",
+            "code":"140429"
+          },
+          {
+            "name":"沁县",
+            "code":"140430"
+          },
+          {
+            "name":"沁源县",
+            "code":"140431"
+          },
+          {
+            "name":"潞城市",
+            "code":"140481"
+          }
+        ]
+      },
+      {
+        "name":"晋城市",
+        "code":"140500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140501"
+          },
+          {
+            "name":"城区",
+            "code":"140502"
+          },
+          {
+            "name":"沁水县",
+            "code":"140521"
+          },
+          {
+            "name":"阳城县",
+            "code":"140522"
+          },
+          {
+            "name":"陵川县",
+            "code":"140524"
+          },
+          {
+            "name":"泽州县",
+            "code":"140525"
+          },
+          {
+            "name":"高平市",
+            "code":"140581"
+          }
+        ]
+      },
+      {
+        "name":"朔州市",
+        "code":"140600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140601"
+          },
+          {
+            "name":"朔城区",
+            "code":"140602"
+          },
+          {
+            "name":"平鲁区",
+            "code":"140603"
+          },
+          {
+            "name":"山阴县",
+            "code":"140621"
+          },
+          {
+            "name":"应县",
+            "code":"140622"
+          },
+          {
+            "name":"右玉县",
+            "code":"140623"
+          },
+          {
+            "name":"怀仁县",
+            "code":"140624"
+          }
+        ]
+      },
+      {
+        "name":"晋中市",
+        "code":"140700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140701"
+          },
+          {
+            "name":"榆次区",
+            "code":"140702"
+          },
+          {
+            "name":"榆社县",
+            "code":"140721"
+          },
+          {
+            "name":"左权县",
+            "code":"140722"
+          },
+          {
+            "name":"和顺县",
+            "code":"140723"
+          },
+          {
+            "name":"昔阳县",
+            "code":"140724"
+          },
+          {
+            "name":"寿阳县",
+            "code":"140725"
+          },
+          {
+            "name":"太谷县",
+            "code":"140726"
+          },
+          {
+            "name":"祁县",
+            "code":"140727"
+          },
+          {
+            "name":"平遥县",
+            "code":"140728"
+          },
+          {
+            "name":"灵石县",
+            "code":"140729"
+          },
+          {
+            "name":"介休市",
+            "code":"140781"
+          }
+        ]
+      },
+      {
+        "name":"运城市",
+        "code":"140800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140801"
+          },
+          {
+            "name":"盐湖区",
+            "code":"140802"
+          },
+          {
+            "name":"临猗县",
+            "code":"140821"
+          },
+          {
+            "name":"万荣县",
+            "code":"140822"
+          },
+          {
+            "name":"闻喜县",
+            "code":"140823"
+          },
+          {
+            "name":"稷山县",
+            "code":"140824"
+          },
+          {
+            "name":"新绛县",
+            "code":"140825"
+          },
+          {
+            "name":"绛县",
+            "code":"140826"
+          },
+          {
+            "name":"垣曲县",
+            "code":"140827"
+          },
+          {
+            "name":"夏县",
+            "code":"140828"
+          },
+          {
+            "name":"平陆县",
+            "code":"140829"
+          },
+          {
+            "name":"芮城县",
+            "code":"140830"
+          },
+          {
+            "name":"永济市",
+            "code":"140881"
+          },
+          {
+            "name":"河津市",
+            "code":"140882"
+          }
+        ]
+      },
+      {
+        "name":"忻州市",
+        "code":"140900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"140901"
+          },
+          {
+            "name":"忻府区",
+            "code":"140902"
+          },
+          {
+            "name":"定襄县",
+            "code":"140921"
+          },
+          {
+            "name":"五台县",
+            "code":"140922"
+          },
+          {
+            "name":"代县",
+            "code":"140923"
+          },
+          {
+            "name":"繁峙县",
+            "code":"140924"
+          },
+          {
+            "name":"宁武县",
+            "code":"140925"
+          },
+          {
+            "name":"静乐县",
+            "code":"140926"
+          },
+          {
+            "name":"神池县",
+            "code":"140927"
+          },
+          {
+            "name":"五寨县",
+            "code":"140928"
+          },
+          {
+            "name":"岢岚县",
+            "code":"140929"
+          },
+          {
+            "name":"河曲县",
+            "code":"140930"
+          },
+          {
+            "name":"保德县",
+            "code":"140931"
+          },
+          {
+            "name":"偏关县",
+            "code":"140932"
+          },
+          {
+            "name":"原平市",
+            "code":"140981"
+          }
+        ]
+      },
+      {
+        "name":"临汾市",
+        "code":"141000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"141001"
+          },
+          {
+            "name":"尧都区",
+            "code":"141002"
+          },
+          {
+            "name":"曲沃县",
+            "code":"141021"
+          },
+          {
+            "name":"翼城县",
+            "code":"141022"
+          },
+          {
+            "name":"襄汾县",
+            "code":"141023"
+          },
+          {
+            "name":"洪洞县",
+            "code":"141024"
+          },
+          {
+            "name":"古县",
+            "code":"141025"
+          },
+          {
+            "name":"安泽县",
+            "code":"141026"
+          },
+          {
+            "name":"浮山县",
+            "code":"141027"
+          },
+          {
+            "name":"吉县",
+            "code":"141028"
+          },
+          {
+            "name":"乡宁县",
+            "code":"141029"
+          },
+          {
+            "name":"大宁县",
+            "code":"141030"
+          },
+          {
+            "name":"隰县",
+            "code":"141031"
+          },
+          {
+            "name":"永和县",
+            "code":"141032"
+          },
+          {
+            "name":"蒲县",
+            "code":"141033"
+          },
+          {
+            "name":"汾西县",
+            "code":"141034"
+          },
+          {
+            "name":"侯马市",
+            "code":"141081"
+          },
+          {
+            "name":"霍州市",
+            "code":"141082"
+          }
+        ]
+      },
+      {
+        "name":"吕梁市",
+        "code":"141100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"141101"
+          },
+          {
+            "name":"离石区",
+            "code":"141102"
+          },
+          {
+            "name":"文水县",
+            "code":"141121"
+          },
+          {
+            "name":"交城县",
+            "code":"141122"
+          },
+          {
+            "name":"兴县",
+            "code":"141123"
+          },
+          {
+            "name":"临县",
+            "code":"141124"
+          },
+          {
+            "name":"柳林县",
+            "code":"141125"
+          },
+          {
+            "name":"石楼县",
+            "code":"141126"
+          },
+          {
+            "name":"岚县",
+            "code":"141127"
+          },
+          {
+            "name":"方山县",
+            "code":"141128"
+          },
+          {
+            "name":"中阳县",
+            "code":"141129"
+          },
+          {
+            "name":"交口县",
+            "code":"141130"
+          },
+          {
+            "name":"孝义市",
+            "code":"141181"
+          },
+          {
+            "name":"汾阳市",
+            "code":"141182"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"内蒙古自治区",
+    "code":"150000",
+    "sub":[
+      {
+        "name":"呼和浩特市",
+        "code":"150100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150101"
+          },
+          {
+            "name":"新城区",
+            "code":"150102"
+          },
+          {
+            "name":"回民区",
+            "code":"150103"
+          },
+          {
+            "name":"玉泉区",
+            "code":"150104"
+          },
+          {
+            "name":"赛罕区",
+            "code":"150105"
+          },
+          {
+            "name":"土默特左旗",
+            "code":"150121"
+          },
+          {
+            "name":"托克托县",
+            "code":"150122"
+          },
+          {
+            "name":"和林格尔县",
+            "code":"150123"
+          },
+          {
+            "name":"清水河县",
+            "code":"150124"
+          },
+          {
+            "name":"武川县",
+            "code":"150125"
+          }
+        ]
+      },
+      {
+        "name":"包头市",
+        "code":"150200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150201"
+          },
+          {
+            "name":"东河区",
+            "code":"150202"
+          },
+          {
+            "name":"昆都仑区",
+            "code":"150203"
+          },
+          {
+            "name":"青山区",
+            "code":"150204"
+          },
+          {
+            "name":"石拐区",
+            "code":"150205"
+          },
+          {
+            "name":"白云鄂博矿区",
+            "code":"150206"
+          },
+          {
+            "name":"九原区",
+            "code":"150207"
+          },
+          {
+            "name":"土默特右旗",
+            "code":"150221"
+          },
+          {
+            "name":"固阳县",
+            "code":"150222"
+          },
+          {
+            "name":"达尔罕茂明安联合旗",
+            "code":"150223"
+          }
+        ]
+      },
+      {
+        "name":"乌海市",
+        "code":"150300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150301"
+          },
+          {
+            "name":"海勃湾区",
+            "code":"150302"
+          },
+          {
+            "name":"海南区",
+            "code":"150303"
+          },
+          {
+            "name":"乌达区",
+            "code":"150304"
+          }
+        ]
+      },
+      {
+        "name":"赤峰市",
+        "code":"150400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150401"
+          },
+          {
+            "name":"红山区",
+            "code":"150402"
+          },
+          {
+            "name":"元宝山区",
+            "code":"150403"
+          },
+          {
+            "name":"松山区",
+            "code":"150404"
+          },
+          {
+            "name":"阿鲁科尔沁旗",
+            "code":"150421"
+          },
+          {
+            "name":"巴林左旗",
+            "code":"150422"
+          },
+          {
+            "name":"巴林右旗",
+            "code":"150423"
+          },
+          {
+            "name":"林西县",
+            "code":"150424"
+          },
+          {
+            "name":"克什克腾旗",
+            "code":"150425"
+          },
+          {
+            "name":"翁牛特旗",
+            "code":"150426"
+          },
+          {
+            "name":"喀喇沁旗",
+            "code":"150428"
+          },
+          {
+            "name":"宁城县",
+            "code":"150429"
+          },
+          {
+            "name":"敖汉旗",
+            "code":"150430"
+          }
+        ]
+      },
+      {
+        "name":"通辽市",
+        "code":"150500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150501"
+          },
+          {
+            "name":"科尔沁区",
+            "code":"150502"
+          },
+          {
+            "name":"科尔沁左翼中旗",
+            "code":"150521"
+          },
+          {
+            "name":"科尔沁左翼后旗",
+            "code":"150522"
+          },
+          {
+            "name":"开鲁县",
+            "code":"150523"
+          },
+          {
+            "name":"库伦旗",
+            "code":"150524"
+          },
+          {
+            "name":"奈曼旗",
+            "code":"150525"
+          },
+          {
+            "name":"扎鲁特旗",
+            "code":"150526"
+          },
+          {
+            "name":"霍林郭勒市",
+            "code":"150581"
+          }
+        ]
+      },
+      {
+        "name":"鄂尔多斯市",
+        "code":"150600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150601"
+          },
+          {
+            "name":"东胜区",
+            "code":"150602"
+          },
+          {
+            "name":"达拉特旗",
+            "code":"150621"
+          },
+          {
+            "name":"准格尔旗",
+            "code":"150622"
+          },
+          {
+            "name":"鄂托克前旗",
+            "code":"150623"
+          },
+          {
+            "name":"鄂托克旗",
+            "code":"150624"
+          },
+          {
+            "name":"杭锦旗",
+            "code":"150625"
+          },
+          {
+            "name":"乌审旗",
+            "code":"150626"
+          },
+          {
+            "name":"伊金霍洛旗",
+            "code":"150627"
+          }
+        ]
+      },
+      {
+        "name":"呼伦贝尔市",
+        "code":"150700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150701"
+          },
+          {
+            "name":"海拉尔区",
+            "code":"150702"
+          },
+          {
+            "name":"扎赉诺尔区",
+            "code":"150703"
+          },
+          {
+            "name":"阿荣旗",
+            "code":"150721"
+          },
+          {
+            "name":"莫力达瓦达斡尔族自治旗",
+            "code":"150722"
+          },
+          {
+            "name":"鄂伦春自治旗",
+            "code":"150723"
+          },
+          {
+            "name":"鄂温克族自治旗",
+            "code":"150724"
+          },
+          {
+            "name":"陈巴尔虎旗",
+            "code":"150725"
+          },
+          {
+            "name":"新巴尔虎左旗",
+            "code":"150726"
+          },
+          {
+            "name":"新巴尔虎右旗",
+            "code":"150727"
+          },
+          {
+            "name":"满洲里市",
+            "code":"150781"
+          },
+          {
+            "name":"牙克石市",
+            "code":"150782"
+          },
+          {
+            "name":"扎兰屯市",
+            "code":"150783"
+          },
+          {
+            "name":"额尔古纳市",
+            "code":"150784"
+          },
+          {
+            "name":"根河市",
+            "code":"150785"
+          }
+        ]
+      },
+      {
+        "name":"巴彦淖尔市",
+        "code":"150800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150801"
+          },
+          {
+            "name":"临河区",
+            "code":"150802"
+          },
+          {
+            "name":"五原县",
+            "code":"150821"
+          },
+          {
+            "name":"磴口县",
+            "code":"150822"
+          },
+          {
+            "name":"乌拉特前旗",
+            "code":"150823"
+          },
+          {
+            "name":"乌拉特中旗",
+            "code":"150824"
+          },
+          {
+            "name":"乌拉特后旗",
+            "code":"150825"
+          },
+          {
+            "name":"杭锦后旗",
+            "code":"150826"
+          }
+        ]
+      },
+      {
+        "name":"乌兰察布市",
+        "code":"150900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"150901"
+          },
+          {
+            "name":"集宁区",
+            "code":"150902"
+          },
+          {
+            "name":"卓资县",
+            "code":"150921"
+          },
+          {
+            "name":"化德县",
+            "code":"150922"
+          },
+          {
+            "name":"商都县",
+            "code":"150923"
+          },
+          {
+            "name":"兴和县",
+            "code":"150924"
+          },
+          {
+            "name":"凉城县",
+            "code":"150925"
+          },
+          {
+            "name":"察哈尔右翼前旗",
+            "code":"150926"
+          },
+          {
+            "name":"察哈尔右翼中旗",
+            "code":"150927"
+          },
+          {
+            "name":"察哈尔右翼后旗",
+            "code":"150928"
+          },
+          {
+            "name":"四子王旗",
+            "code":"150929"
+          },
+          {
+            "name":"丰镇市",
+            "code":"150981"
+          }
+        ]
+      },
+      {
+        "name":"兴安盟",
+        "code":"152200",
+        "sub":[
+          {
+            "name":"乌兰浩特市",
+            "code":"152201"
+          },
+          {
+            "name":"阿尔山市",
+            "code":"152202"
+          },
+          {
+            "name":"科尔沁右翼前旗",
+            "code":"152221"
+          },
+          {
+            "name":"科尔沁右翼中旗",
+            "code":"152222"
+          },
+          {
+            "name":"扎赉特旗",
+            "code":"152223"
+          },
+          {
+            "name":"突泉县",
+            "code":"152224"
+          }
+        ]
+      },
+      {
+        "name":"锡林郭勒盟",
+        "code":"152500",
+        "sub":[
+          {
+            "name":"二连浩特市",
+            "code":"152501"
+          },
+          {
+            "name":"锡林浩特市",
+            "code":"152502"
+          },
+          {
+            "name":"阿巴嘎旗",
+            "code":"152522"
+          },
+          {
+            "name":"苏尼特左旗",
+            "code":"152523"
+          },
+          {
+            "name":"苏尼特右旗",
+            "code":"152524"
+          },
+          {
+            "name":"东乌珠穆沁旗",
+            "code":"152525"
+          },
+          {
+            "name":"西乌珠穆沁旗",
+            "code":"152526"
+          },
+          {
+            "name":"太仆寺旗",
+            "code":"152527"
+          },
+          {
+            "name":"镶黄旗",
+            "code":"152528"
+          },
+          {
+            "name":"正镶白旗",
+            "code":"152529"
+          },
+          {
+            "name":"正蓝旗",
+            "code":"152530"
+          },
+          {
+            "name":"多伦县",
+            "code":"152531"
+          }
+        ]
+      },
+      {
+        "name":"阿拉善盟",
+        "code":"152900",
+        "sub":[
+          {
+            "name":"阿拉善左旗",
+            "code":"152921"
+          },
+          {
+            "name":"阿拉善右旗",
+            "code":"152922"
+          },
+          {
+            "name":"额济纳旗",
+            "code":"152923"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"辽宁省",
+    "code":"210000",
+    "sub":[
+      {
+        "name":"沈阳市",
+        "code":"210100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210101"
+          },
+          {
+            "name":"和平区",
+            "code":"210102"
+          },
+          {
+            "name":"沈河区",
+            "code":"210103"
+          },
+          {
+            "name":"大东区",
+            "code":"210104"
+          },
+          {
+            "name":"皇姑区",
+            "code":"210105"
+          },
+          {
+            "name":"铁西区",
+            "code":"210106"
+          },
+          {
+            "name":"苏家屯区",
+            "code":"210111"
+          },
+          {
+            "name":"浑南区",
+            "code":"210112"
+          },
+          {
+            "name":"沈北新区",
+            "code":"210113"
+          },
+          {
+            "name":"于洪区",
+            "code":"210114"
+          },
+          {
+            "name":"辽中县",
+            "code":"210122"
+          },
+          {
+            "name":"康平县",
+            "code":"210123"
+          },
+          {
+            "name":"法库县",
+            "code":"210124"
+          },
+          {
+            "name":"新民市",
+            "code":"210181"
+          }
+        ]
+      },
+      {
+        "name":"大连市",
+        "code":"210200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210201"
+          },
+          {
+            "name":"中山区",
+            "code":"210202"
+          },
+          {
+            "name":"西岗区",
+            "code":"210203"
+          },
+          {
+            "name":"沙河口区",
+            "code":"210204"
+          },
+          {
+            "name":"甘井子区",
+            "code":"210211"
+          },
+          {
+            "name":"旅顺口区",
+            "code":"210212"
+          },
+          {
+            "name":"金州区",
+            "code":"210213"
+          },
+          {
+            "name":"长海县",
+            "code":"210224"
+          },
+          {
+            "name":"瓦房店市",
+            "code":"210281"
+          },
+          {
+            "name":"普兰店市",
+            "code":"210282"
+          },
+          {
+            "name":"庄河市",
+            "code":"210283"
+          }
+        ]
+      },
+      {
+        "name":"鞍山市",
+        "code":"210300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210301"
+          },
+          {
+            "name":"铁东区",
+            "code":"210302"
+          },
+          {
+            "name":"铁西区",
+            "code":"210303"
+          },
+          {
+            "name":"立山区",
+            "code":"210304"
+          },
+          {
+            "name":"千山区",
+            "code":"210311"
+          },
+          {
+            "name":"台安县",
+            "code":"210321"
+          },
+          {
+            "name":"岫岩满族自治县",
+            "code":"210323"
+          },
+          {
+            "name":"海城市",
+            "code":"210381"
+          }
+        ]
+      },
+      {
+        "name":"抚顺市",
+        "code":"210400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210401"
+          },
+          {
+            "name":"新抚区",
+            "code":"210402"
+          },
+          {
+            "name":"东洲区",
+            "code":"210403"
+          },
+          {
+            "name":"望花区",
+            "code":"210404"
+          },
+          {
+            "name":"顺城区",
+            "code":"210411"
+          },
+          {
+            "name":"抚顺县",
+            "code":"210421"
+          },
+          {
+            "name":"新宾满族自治县",
+            "code":"210422"
+          },
+          {
+            "name":"清原满族自治县",
+            "code":"210423"
+          }
+        ]
+      },
+      {
+        "name":"本溪市",
+        "code":"210500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210501"
+          },
+          {
+            "name":"平山区",
+            "code":"210502"
+          },
+          {
+            "name":"溪湖区",
+            "code":"210503"
+          },
+          {
+            "name":"明山区",
+            "code":"210504"
+          },
+          {
+            "name":"南芬区",
+            "code":"210505"
+          },
+          {
+            "name":"本溪满族自治县",
+            "code":"210521"
+          },
+          {
+            "name":"桓仁满族自治县",
+            "code":"210522"
+          }
+        ]
+      },
+      {
+        "name":"丹东市",
+        "code":"210600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210601"
+          },
+          {
+            "name":"元宝区",
+            "code":"210602"
+          },
+          {
+            "name":"振兴区",
+            "code":"210603"
+          },
+          {
+            "name":"振安区",
+            "code":"210604"
+          },
+          {
+            "name":"宽甸满族自治县",
+            "code":"210624"
+          },
+          {
+            "name":"东港市",
+            "code":"210681"
+          },
+          {
+            "name":"凤城市",
+            "code":"210682"
+          }
+        ]
+      },
+      {
+        "name":"锦州市",
+        "code":"210700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210701"
+          },
+          {
+            "name":"古塔区",
+            "code":"210702"
+          },
+          {
+            "name":"凌河区",
+            "code":"210703"
+          },
+          {
+            "name":"太和区",
+            "code":"210711"
+          },
+          {
+            "name":"黑山县",
+            "code":"210726"
+          },
+          {
+            "name":"义县",
+            "code":"210727"
+          },
+          {
+            "name":"凌海市",
+            "code":"210781"
+          },
+          {
+            "name":"北镇市",
+            "code":"210782"
+          }
+        ]
+      },
+      {
+        "name":"营口市",
+        "code":"210800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210801"
+          },
+          {
+            "name":"站前区",
+            "code":"210802"
+          },
+          {
+            "name":"西市区",
+            "code":"210803"
+          },
+          {
+            "name":"鲅鱼圈区",
+            "code":"210804"
+          },
+          {
+            "name":"老边区",
+            "code":"210811"
+          },
+          {
+            "name":"盖州市",
+            "code":"210881"
+          },
+          {
+            "name":"大石桥市",
+            "code":"210882"
+          }
+        ]
+      },
+      {
+        "name":"阜新市",
+        "code":"210900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"210901"
+          },
+          {
+            "name":"海州区",
+            "code":"210902"
+          },
+          {
+            "name":"新邱区",
+            "code":"210903"
+          },
+          {
+            "name":"太平区",
+            "code":"210904"
+          },
+          {
+            "name":"清河门区",
+            "code":"210905"
+          },
+          {
+            "name":"细河区",
+            "code":"210911"
+          },
+          {
+            "name":"阜新蒙古族自治县",
+            "code":"210921"
+          },
+          {
+            "name":"彰武县",
+            "code":"210922"
+          }
+        ]
+      },
+      {
+        "name":"辽阳市",
+        "code":"211000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211001"
+          },
+          {
+            "name":"白塔区",
+            "code":"211002"
+          },
+          {
+            "name":"文圣区",
+            "code":"211003"
+          },
+          {
+            "name":"宏伟区",
+            "code":"211004"
+          },
+          {
+            "name":"弓长岭区",
+            "code":"211005"
+          },
+          {
+            "name":"太子河区",
+            "code":"211011"
+          },
+          {
+            "name":"辽阳县",
+            "code":"211021"
+          },
+          {
+            "name":"灯塔市",
+            "code":"211081"
+          }
+        ]
+      },
+      {
+        "name":"盘锦市",
+        "code":"211100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211101"
+          },
+          {
+            "name":"双台子区",
+            "code":"211102"
+          },
+          {
+            "name":"兴隆台区",
+            "code":"211103"
+          },
+          {
+            "name":"大洼县",
+            "code":"211121"
+          },
+          {
+            "name":"盘山县",
+            "code":"211122"
+          }
+        ]
+      },
+      {
+        "name":"铁岭市",
+        "code":"211200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211201"
+          },
+          {
+            "name":"银州区",
+            "code":"211202"
+          },
+          {
+            "name":"清河区",
+            "code":"211204"
+          },
+          {
+            "name":"铁岭县",
+            "code":"211221"
+          },
+          {
+            "name":"西丰县",
+            "code":"211223"
+          },
+          {
+            "name":"昌图县",
+            "code":"211224"
+          },
+          {
+            "name":"调兵山市",
+            "code":"211281"
+          },
+          {
+            "name":"开原市",
+            "code":"211282"
+          }
+        ]
+      },
+      {
+        "name":"朝阳市",
+        "code":"211300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211301"
+          },
+          {
+            "name":"双塔区",
+            "code":"211302"
+          },
+          {
+            "name":"龙城区",
+            "code":"211303"
+          },
+          {
+            "name":"朝阳县",
+            "code":"211321"
+          },
+          {
+            "name":"建平县",
+            "code":"211322"
+          },
+          {
+            "name":"喀喇沁左翼蒙古族自治县",
+            "code":"211324"
+          },
+          {
+            "name":"北票市",
+            "code":"211381"
+          },
+          {
+            "name":"凌源市",
+            "code":"211382"
+          }
+        ]
+      },
+      {
+        "name":"葫芦岛市",
+        "code":"211400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"211401"
+          },
+          {
+            "name":"连山区",
+            "code":"211402"
+          },
+          {
+            "name":"龙港区",
+            "code":"211403"
+          },
+          {
+            "name":"南票区",
+            "code":"211404"
+          },
+          {
+            "name":"绥中县",
+            "code":"211421"
+          },
+          {
+            "name":"建昌县",
+            "code":"211422"
+          },
+          {
+            "name":"兴城市",
+            "code":"211481"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"吉林省",
+    "code":"220000",
+    "sub":[
+      {
+        "name":"长春市",
+        "code":"220100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220101"
+          },
+          {
+            "name":"南关区",
+            "code":"220102"
+          },
+          {
+            "name":"宽城区",
+            "code":"220103"
+          },
+          {
+            "name":"朝阳区",
+            "code":"220104"
+          },
+          {
+            "name":"二道区",
+            "code":"220105"
+          },
+          {
+            "name":"绿园区",
+            "code":"220106"
+          },
+          {
+            "name":"双阳区",
+            "code":"220112"
+          },
+          {
+            "name":"九台区",
+            "code":"220113"
+          },
+          {
+            "name":"农安县",
+            "code":"220122"
+          },
+          {
+            "name":"榆树市",
+            "code":"220182"
+          },
+          {
+            "name":"德惠市",
+            "code":"220183"
+          }
+        ]
+      },
+      {
+        "name":"吉林市",
+        "code":"220200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220201"
+          },
+          {
+            "name":"昌邑区",
+            "code":"220202"
+          },
+          {
+            "name":"龙潭区",
+            "code":"220203"
+          },
+          {
+            "name":"船营区",
+            "code":"220204"
+          },
+          {
+            "name":"丰满区",
+            "code":"220211"
+          },
+          {
+            "name":"永吉县",
+            "code":"220221"
+          },
+          {
+            "name":"蛟河市",
+            "code":"220281"
+          },
+          {
+            "name":"桦甸市",
+            "code":"220282"
+          },
+          {
+            "name":"舒兰市",
+            "code":"220283"
+          },
+          {
+            "name":"磐石市",
+            "code":"220284"
+          }
+        ]
+      },
+      {
+        "name":"四平市",
+        "code":"220300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220301"
+          },
+          {
+            "name":"铁西区",
+            "code":"220302"
+          },
+          {
+            "name":"铁东区",
+            "code":"220303"
+          },
+          {
+            "name":"梨树县",
+            "code":"220322"
+          },
+          {
+            "name":"伊通满族自治县",
+            "code":"220323"
+          },
+          {
+            "name":"公主岭市",
+            "code":"220381"
+          },
+          {
+            "name":"双辽市",
+            "code":"220382"
+          }
+        ]
+      },
+      {
+        "name":"辽源市",
+        "code":"220400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220401"
+          },
+          {
+            "name":"龙山区",
+            "code":"220402"
+          },
+          {
+            "name":"西安区",
+            "code":"220403"
+          },
+          {
+            "name":"东丰县",
+            "code":"220421"
+          },
+          {
+            "name":"东辽县",
+            "code":"220422"
+          }
+        ]
+      },
+      {
+        "name":"通化市",
+        "code":"220500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220501"
+          },
+          {
+            "name":"东昌区",
+            "code":"220502"
+          },
+          {
+            "name":"二道江区",
+            "code":"220503"
+          },
+          {
+            "name":"通化县",
+            "code":"220521"
+          },
+          {
+            "name":"辉南县",
+            "code":"220523"
+          },
+          {
+            "name":"柳河县",
+            "code":"220524"
+          },
+          {
+            "name":"梅河口市",
+            "code":"220581"
+          },
+          {
+            "name":"集安市",
+            "code":"220582"
+          }
+        ]
+      },
+      {
+        "name":"白山市",
+        "code":"220600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220601"
+          },
+          {
+            "name":"浑江区",
+            "code":"220602"
+          },
+          {
+            "name":"江源区",
+            "code":"220605"
+          },
+          {
+            "name":"抚松县",
+            "code":"220621"
+          },
+          {
+            "name":"靖宇县",
+            "code":"220622"
+          },
+          {
+            "name":"长白朝鲜族自治县",
+            "code":"220623"
+          },
+          {
+            "name":"临江市",
+            "code":"220681"
+          }
+        ]
+      },
+      {
+        "name":"松原市",
+        "code":"220700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220701"
+          },
+          {
+            "name":"宁江区",
+            "code":"220702"
+          },
+          {
+            "name":"前郭尔罗斯蒙古族自治县",
+            "code":"220721"
+          },
+          {
+            "name":"长岭县",
+            "code":"220722"
+          },
+          {
+            "name":"乾安县",
+            "code":"220723"
+          },
+          {
+            "name":"扶余市",
+            "code":"220781"
+          }
+        ]
+      },
+      {
+        "name":"白城市",
+        "code":"220800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"220801"
+          },
+          {
+            "name":"洮北区",
+            "code":"220802"
+          },
+          {
+            "name":"镇赉县",
+            "code":"220821"
+          },
+          {
+            "name":"通榆县",
+            "code":"220822"
+          },
+          {
+            "name":"洮南市",
+            "code":"220881"
+          },
+          {
+            "name":"大安市",
+            "code":"220882"
+          }
+        ]
+      },
+      {
+        "name":"延边朝鲜族自治州",
+        "code":"222400",
+        "sub":[
+          {
+            "name":"延吉市",
+            "code":"222401"
+          },
+          {
+            "name":"图们市",
+            "code":"222402"
+          },
+          {
+            "name":"敦化市",
+            "code":"222403"
+          },
+          {
+            "name":"珲春市",
+            "code":"222404"
+          },
+          {
+            "name":"龙井市",
+            "code":"222405"
+          },
+          {
+            "name":"和龙市",
+            "code":"222406"
+          },
+          {
+            "name":"汪清县",
+            "code":"222424"
+          },
+          {
+            "name":"安图县",
+            "code":"222426"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"黑龙江省",
+    "code":"230000",
+    "sub":[
+      {
+        "name":"哈尔滨市",
+        "code":"230100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230101"
+          },
+          {
+            "name":"道里区",
+            "code":"230102"
+          },
+          {
+            "name":"南岗区",
+            "code":"230103"
+          },
+          {
+            "name":"道外区",
+            "code":"230104"
+          },
+          {
+            "name":"平房区",
+            "code":"230108"
+          },
+          {
+            "name":"松北区",
+            "code":"230109"
+          },
+          {
+            "name":"香坊区",
+            "code":"230110"
+          },
+          {
+            "name":"呼兰区",
+            "code":"230111"
+          },
+          {
+            "name":"阿城区",
+            "code":"230112"
+          },
+          {
+            "name":"双城区",
+            "code":"230113"
+          },
+          {
+            "name":"依兰县",
+            "code":"230123"
+          },
+          {
+            "name":"方正县",
+            "code":"230124"
+          },
+          {
+            "name":"宾县",
+            "code":"230125"
+          },
+          {
+            "name":"巴彦县",
+            "code":"230126"
+          },
+          {
+            "name":"木兰县",
+            "code":"230127"
+          },
+          {
+            "name":"通河县",
+            "code":"230128"
+          },
+          {
+            "name":"延寿县",
+            "code":"230129"
+          },
+          {
+            "name":"尚志市",
+            "code":"230183"
+          },
+          {
+            "name":"五常市",
+            "code":"230184"
+          }
+        ]
+      },
+      {
+        "name":"齐齐哈尔市",
+        "code":"230200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230201"
+          },
+          {
+            "name":"龙沙区",
+            "code":"230202"
+          },
+          {
+            "name":"建华区",
+            "code":"230203"
+          },
+          {
+            "name":"铁锋区",
+            "code":"230204"
+          },
+          {
+            "name":"昂昂溪区",
+            "code":"230205"
+          },
+          {
+            "name":"富拉尔基区",
+            "code":"230206"
+          },
+          {
+            "name":"碾子山区",
+            "code":"230207"
+          },
+          {
+            "name":"梅里斯达斡尔族区",
+            "code":"230208"
+          },
+          {
+            "name":"龙江县",
+            "code":"230221"
+          },
+          {
+            "name":"依安县",
+            "code":"230223"
+          },
+          {
+            "name":"泰来县",
+            "code":"230224"
+          },
+          {
+            "name":"甘南县",
+            "code":"230225"
+          },
+          {
+            "name":"富裕县",
+            "code":"230227"
+          },
+          {
+            "name":"克山县",
+            "code":"230229"
+          },
+          {
+            "name":"克东县",
+            "code":"230230"
+          },
+          {
+            "name":"拜泉县",
+            "code":"230231"
+          },
+          {
+            "name":"讷河市",
+            "code":"230281"
+          }
+        ]
+      },
+      {
+        "name":"鸡西市",
+        "code":"230300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230301"
+          },
+          {
+            "name":"鸡冠区",
+            "code":"230302"
+          },
+          {
+            "name":"恒山区",
+            "code":"230303"
+          },
+          {
+            "name":"滴道区",
+            "code":"230304"
+          },
+          {
+            "name":"梨树区",
+            "code":"230305"
+          },
+          {
+            "name":"城子河区",
+            "code":"230306"
+          },
+          {
+            "name":"麻山区",
+            "code":"230307"
+          },
+          {
+            "name":"鸡东县",
+            "code":"230321"
+          },
+          {
+            "name":"虎林市",
+            "code":"230381"
+          },
+          {
+            "name":"密山市",
+            "code":"230382"
+          }
+        ]
+      },
+      {
+        "name":"鹤岗市",
+        "code":"230400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230401"
+          },
+          {
+            "name":"向阳区",
+            "code":"230402"
+          },
+          {
+            "name":"工农区",
+            "code":"230403"
+          },
+          {
+            "name":"南山区",
+            "code":"230404"
+          },
+          {
+            "name":"兴安区",
+            "code":"230405"
+          },
+          {
+            "name":"东山区",
+            "code":"230406"
+          },
+          {
+            "name":"兴山区",
+            "code":"230407"
+          },
+          {
+            "name":"萝北县",
+            "code":"230421"
+          },
+          {
+            "name":"绥滨县",
+            "code":"230422"
+          }
+        ]
+      },
+      {
+        "name":"双鸭山市",
+        "code":"230500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230501"
+          },
+          {
+            "name":"尖山区",
+            "code":"230502"
+          },
+          {
+            "name":"岭东区",
+            "code":"230503"
+          },
+          {
+            "name":"四方台区",
+            "code":"230505"
+          },
+          {
+            "name":"宝山区",
+            "code":"230506"
+          },
+          {
+            "name":"集贤县",
+            "code":"230521"
+          },
+          {
+            "name":"友谊县",
+            "code":"230522"
+          },
+          {
+            "name":"宝清县",
+            "code":"230523"
+          },
+          {
+            "name":"饶河县",
+            "code":"230524"
+          }
+        ]
+      },
+      {
+        "name":"大庆市",
+        "code":"230600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230601"
+          },
+          {
+            "name":"萨尔图区",
+            "code":"230602"
+          },
+          {
+            "name":"龙凤区",
+            "code":"230603"
+          },
+          {
+            "name":"让胡路区",
+            "code":"230604"
+          },
+          {
+            "name":"红岗区",
+            "code":"230605"
+          },
+          {
+            "name":"大同区",
+            "code":"230606"
+          },
+          {
+            "name":"肇州县",
+            "code":"230621"
+          },
+          {
+            "name":"肇源县",
+            "code":"230622"
+          },
+          {
+            "name":"林甸县",
+            "code":"230623"
+          },
+          {
+            "name":"杜尔伯特蒙古族自治县",
+            "code":"230624"
+          }
+        ]
+      },
+      {
+        "name":"伊春市",
+        "code":"230700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230701"
+          },
+          {
+            "name":"伊春区",
+            "code":"230702"
+          },
+          {
+            "name":"南岔区",
+            "code":"230703"
+          },
+          {
+            "name":"友好区",
+            "code":"230704"
+          },
+          {
+            "name":"西林区",
+            "code":"230705"
+          },
+          {
+            "name":"翠峦区",
+            "code":"230706"
+          },
+          {
+            "name":"新青区",
+            "code":"230707"
+          },
+          {
+            "name":"美溪区",
+            "code":"230708"
+          },
+          {
+            "name":"金山屯区",
+            "code":"230709"
+          },
+          {
+            "name":"五营区",
+            "code":"230710"
+          },
+          {
+            "name":"乌马河区",
+            "code":"230711"
+          },
+          {
+            "name":"汤旺河区",
+            "code":"230712"
+          },
+          {
+            "name":"带岭区",
+            "code":"230713"
+          },
+          {
+            "name":"乌伊岭区",
+            "code":"230714"
+          },
+          {
+            "name":"红星区",
+            "code":"230715"
+          },
+          {
+            "name":"上甘岭区",
+            "code":"230716"
+          },
+          {
+            "name":"嘉荫县",
+            "code":"230722"
+          },
+          {
+            "name":"铁力市",
+            "code":"230781"
+          }
+        ]
+      },
+      {
+        "name":"佳木斯市",
+        "code":"230800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230801"
+          },
+          {
+            "name":"向阳区",
+            "code":"230803"
+          },
+          {
+            "name":"前进区",
+            "code":"230804"
+          },
+          {
+            "name":"东风区",
+            "code":"230805"
+          },
+          {
+            "name":"郊区",
+            "code":"230811"
+          },
+          {
+            "name":"桦南县",
+            "code":"230822"
+          },
+          {
+            "name":"桦川县",
+            "code":"230826"
+          },
+          {
+            "name":"汤原县",
+            "code":"230828"
+          },
+          {
+            "name":"抚远县",
+            "code":"230833"
+          },
+          {
+            "name":"同江市",
+            "code":"230881"
+          },
+          {
+            "name":"富锦市",
+            "code":"230882"
+          }
+        ]
+      },
+      {
+        "name":"七台河市",
+        "code":"230900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"230901"
+          },
+          {
+            "name":"新兴区",
+            "code":"230902"
+          },
+          {
+            "name":"桃山区",
+            "code":"230903"
+          },
+          {
+            "name":"茄子河区",
+            "code":"230904"
+          },
+          {
+            "name":"勃利县",
+            "code":"230921"
+          }
+        ]
+      },
+      {
+        "name":"牡丹江市",
+        "code":"231000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231001"
+          },
+          {
+            "name":"东安区",
+            "code":"231002"
+          },
+          {
+            "name":"阳明区",
+            "code":"231003"
+          },
+          {
+            "name":"爱民区",
+            "code":"231004"
+          },
+          {
+            "name":"西安区",
+            "code":"231005"
+          },
+          {
+            "name":"东宁县",
+            "code":"231024"
+          },
+          {
+            "name":"林口县",
+            "code":"231025"
+          },
+          {
+            "name":"绥芬河市",
+            "code":"231081"
+          },
+          {
+            "name":"海林市",
+            "code":"231083"
+          },
+          {
+            "name":"宁安市",
+            "code":"231084"
+          },
+          {
+            "name":"穆棱市",
+            "code":"231085"
+          }
+        ]
+      },
+      {
+        "name":"黑河市",
+        "code":"231100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231101"
+          },
+          {
+            "name":"爱辉区",
+            "code":"231102"
+          },
+          {
+            "name":"嫩江县",
+            "code":"231121"
+          },
+          {
+            "name":"逊克县",
+            "code":"231123"
+          },
+          {
+            "name":"孙吴县",
+            "code":"231124"
+          },
+          {
+            "name":"北安市",
+            "code":"231181"
+          },
+          {
+            "name":"五大连池市",
+            "code":"231182"
+          }
+        ]
+      },
+      {
+        "name":"绥化市",
+        "code":"231200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"231201"
+          },
+          {
+            "name":"北林区",
+            "code":"231202"
+          },
+          {
+            "name":"望奎县",
+            "code":"231221"
+          },
+          {
+            "name":"兰西县",
+            "code":"231222"
+          },
+          {
+            "name":"青冈县",
+            "code":"231223"
+          },
+          {
+            "name":"庆安县",
+            "code":"231224"
+          },
+          {
+            "name":"明水县",
+            "code":"231225"
+          },
+          {
+            "name":"绥棱县",
+            "code":"231226"
+          },
+          {
+            "name":"安达市",
+            "code":"231281"
+          },
+          {
+            "name":"肇东市",
+            "code":"231282"
+          },
+          {
+            "name":"海伦市",
+            "code":"231283"
+          }
+        ]
+      },
+      {
+        "name":"大兴安岭地区",
+        "code":"232700",
+        "sub":[
+          {
+            "name":"呼玛县",
+            "code":"232721"
+          },
+          {
+            "name":"塔河县",
+            "code":"232722"
+          },
+          {
+            "name":"漠河县",
+            "code":"232723"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"上海",
+    "code":"310000",
+    "sub": [
+      {
+        "name":"上海市",
+        "code": "310000",
+        "sub":[
+            {
+              "name":"黄浦区",
+              "code":"310101"
+            },
+            {
+              "name":"徐汇区",
+              "code":"310104"
+            },
+            {
+              "name":"长宁区",
+              "code":"310105"
+            },
+            {
+              "name":"静安区",
+              "code":"310106"
+            },
+            {
+              "name":"普陀区",
+              "code":"310107"
+            },
+            {
+              "name":"闸北区",
+              "code":"310108"
+            },
+            {
+              "name":"虹口区",
+              "code":"310109"
+            },
+            {
+              "name":"杨浦区",
+              "code":"310110"
+            },
+            {
+              "name":"闵行区",
+              "code":"310112"
+            },
+            {
+              "name":"宝山区",
+              "code":"310113"
+            },
+            {
+              "name":"嘉定区",
+              "code":"310114"
+            },
+            {
+              "name":"浦东新区",
+              "code":"310115"
+            },
+            {
+              "name":"金山区",
+              "code":"310116"
+            },
+            {
+              "name":"松江区",
+              "code":"310117"
+            },
+            {
+              "name":"青浦区",
+              "code":"310118"
+            },
+            {
+              "name":"奉贤区",
+              "code":"310120"
+            },
+            {
+              "name":"崇明县",
+              "code":"310230"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"江苏省",
+    "code":"320000",
+    "sub":[
+      {
+        "name":"南京市",
+        "code":"320100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320101"
+          },
+          {
+            "name":"玄武区",
+            "code":"320102"
+          },
+          {
+            "name":"秦淮区",
+            "code":"320104"
+          },
+          {
+            "name":"建邺区",
+            "code":"320105"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"320106"
+          },
+          {
+            "name":"浦口区",
+            "code":"320111"
+          },
+          {
+            "name":"栖霞区",
+            "code":"320113"
+          },
+          {
+            "name":"雨花台区",
+            "code":"320114"
+          },
+          {
+            "name":"江宁区",
+            "code":"320115"
+          },
+          {
+            "name":"六合区",
+            "code":"320116"
+          },
+          {
+            "name":"溧水区",
+            "code":"320117"
+          },
+          {
+            "name":"高淳区",
+            "code":"320118"
+          }
+        ]
+      },
+      {
+        "name":"无锡市",
+        "code":"320200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320201"
+          },
+          {
+            "name":"崇安区",
+            "code":"320202"
+          },
+          {
+            "name":"南长区",
+            "code":"320203"
+          },
+          {
+            "name":"北塘区",
+            "code":"320204"
+          },
+          {
+            "name":"锡山区",
+            "code":"320205"
+          },
+          {
+            "name":"惠山区",
+            "code":"320206"
+          },
+          {
+            "name":"滨湖区",
+            "code":"320211"
+          },
+          {
+            "name":"江阴市",
+            "code":"320281"
+          },
+          {
+            "name":"宜兴市",
+            "code":"320282"
+          }
+        ]
+      },
+      {
+        "name":"徐州市",
+        "code":"320300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320301"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"320302"
+          },
+          {
+            "name":"云龙区",
+            "code":"320303"
+          },
+          {
+            "name":"贾汪区",
+            "code":"320305"
+          },
+          {
+            "name":"泉山区",
+            "code":"320311"
+          },
+          {
+            "name":"铜山区",
+            "code":"320312"
+          },
+          {
+            "name":"丰县",
+            "code":"320321"
+          },
+          {
+            "name":"沛县",
+            "code":"320322"
+          },
+          {
+            "name":"睢宁县",
+            "code":"320324"
+          },
+          {
+            "name":"新沂市",
+            "code":"320381"
+          },
+          {
+            "name":"邳州市",
+            "code":"320382"
+          }
+        ]
+      },
+      {
+        "name":"常州市",
+        "code":"320400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320401"
+          },
+          {
+            "name":"天宁区",
+            "code":"320402"
+          },
+          {
+            "name":"钟楼区",
+            "code":"320404"
+          },
+          {
+            "name":"戚墅堰区",
+            "code":"320405"
+          },
+          {
+            "name":"新北区",
+            "code":"320411"
+          },
+          {
+            "name":"武进区",
+            "code":"320412"
+          },
+          {
+            "name":"溧阳市",
+            "code":"320481"
+          },
+          {
+            "name":"金坛市",
+            "code":"320482"
+          }
+        ]
+      },
+      {
+        "name":"苏州市",
+        "code":"320500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320501"
+          },
+          {
+            "name":"虎丘区",
+            "code":"320505"
+          },
+          {
+            "name":"吴中区",
+            "code":"320506"
+          },
+          {
+            "name":"相城区",
+            "code":"320507"
+          },
+          {
+            "name":"姑苏区",
+            "code":"320508"
+          },
+          {
+            "name":"吴江区",
+            "code":"320509"
+          },
+          {
+            "name":"常熟市",
+            "code":"320581"
+          },
+          {
+            "name":"张家港市",
+            "code":"320582"
+          },
+          {
+            "name":"昆山市",
+            "code":"320583"
+          },
+          {
+            "name":"太仓市",
+            "code":"320585"
+          }
+        ]
+      },
+      {
+        "name":"南通市",
+        "code":"320600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320601"
+          },
+          {
+            "name":"崇川区",
+            "code":"320602"
+          },
+          {
+            "name":"港闸区",
+            "code":"320611"
+          },
+          {
+            "name":"通州区",
+            "code":"320612"
+          },
+          {
+            "name":"海安县",
+            "code":"320621"
+          },
+          {
+            "name":"如东县",
+            "code":"320623"
+          },
+          {
+            "name":"启东市",
+            "code":"320681"
+          },
+          {
+            "name":"如皋市",
+            "code":"320682"
+          },
+          {
+            "name":"海门市",
+            "code":"320684"
+          }
+        ]
+      },
+      {
+        "name":"连云港市",
+        "code":"320700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320701"
+          },
+          {
+            "name":"连云区",
+            "code":"320703"
+          },
+          {
+            "name":"海州区",
+            "code":"320706"
+          },
+          {
+            "name":"赣榆区",
+            "code":"320707"
+          },
+          {
+            "name":"东海县",
+            "code":"320722"
+          },
+          {
+            "name":"灌云县",
+            "code":"320723"
+          },
+          {
+            "name":"灌南县",
+            "code":"320724"
+          }
+        ]
+      },
+      {
+        "name":"淮安市",
+        "code":"320800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320801"
+          },
+          {
+            "name":"清河区",
+            "code":"320802"
+          },
+          {
+            "name":"淮安区",
+            "code":"320803"
+          },
+          {
+            "name":"淮阴区",
+            "code":"320804"
+          },
+          {
+            "name":"清浦区",
+            "code":"320811"
+          },
+          {
+            "name":"涟水县",
+            "code":"320826"
+          },
+          {
+            "name":"洪泽县",
+            "code":"320829"
+          },
+          {
+            "name":"盱眙县",
+            "code":"320830"
+          },
+          {
+            "name":"金湖县",
+            "code":"320831"
+          }
+        ]
+      },
+      {
+        "name":"盐城市",
+        "code":"320900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"320901"
+          },
+          {
+            "name":"亭湖区",
+            "code":"320902"
+          },
+          {
+            "name":"盐都区",
+            "code":"320903"
+          },
+          {
+            "name":"响水县",
+            "code":"320921"
+          },
+          {
+            "name":"滨海县",
+            "code":"320922"
+          },
+          {
+            "name":"阜宁县",
+            "code":"320923"
+          },
+          {
+            "name":"射阳县",
+            "code":"320924"
+          },
+          {
+            "name":"建湖县",
+            "code":"320925"
+          },
+          {
+            "name":"东台市",
+            "code":"320981"
+          },
+          {
+            "name":"大丰市",
+            "code":"320982"
+          }
+        ]
+      },
+      {
+        "name":"扬州市",
+        "code":"321000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321001"
+          },
+          {
+            "name":"广陵区",
+            "code":"321002"
+          },
+          {
+            "name":"邗江区",
+            "code":"321003"
+          },
+          {
+            "name":"江都区",
+            "code":"321012"
+          },
+          {
+            "name":"宝应县",
+            "code":"321023"
+          },
+          {
+            "name":"仪征市",
+            "code":"321081"
+          },
+          {
+            "name":"高邮市",
+            "code":"321084"
+          }
+        ]
+      },
+      {
+        "name":"镇江市",
+        "code":"321100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321101"
+          },
+          {
+            "name":"京口区",
+            "code":"321102"
+          },
+          {
+            "name":"润州区",
+            "code":"321111"
+          },
+          {
+            "name":"丹徒区",
+            "code":"321112"
+          },
+          {
+            "name":"丹阳市",
+            "code":"321181"
+          },
+          {
+            "name":"扬中市",
+            "code":"321182"
+          },
+          {
+            "name":"句容市",
+            "code":"321183"
+          }
+        ]
+      },
+      {
+        "name":"泰州市",
+        "code":"321200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321201"
+          },
+          {
+            "name":"海陵区",
+            "code":"321202"
+          },
+          {
+            "name":"高港区",
+            "code":"321203"
+          },
+          {
+            "name":"姜堰区",
+            "code":"321204"
+          },
+          {
+            "name":"兴化市",
+            "code":"321281"
+          },
+          {
+            "name":"靖江市",
+            "code":"321282"
+          },
+          {
+            "name":"泰兴市",
+            "code":"321283"
+          }
+        ]
+      },
+      {
+        "name":"宿迁市",
+        "code":"321300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"321301"
+          },
+          {
+            "name":"宿城区",
+            "code":"321302"
+          },
+          {
+            "name":"宿豫区",
+            "code":"321311"
+          },
+          {
+            "name":"沭阳县",
+            "code":"321322"
+          },
+          {
+            "name":"泗阳县",
+            "code":"321323"
+          },
+          {
+            "name":"泗洪县",
+            "code":"321324"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"浙江省",
+    "code":"330000",
+    "sub":[
+      {
+        "name":"杭州市",
+        "code":"330100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330101"
+          },
+          {
+            "name":"上城区",
+            "code":"330102"
+          },
+          {
+            "name":"下城区",
+            "code":"330103"
+          },
+          {
+            "name":"江干区",
+            "code":"330104"
+          },
+          {
+            "name":"拱墅区",
+            "code":"330105"
+          },
+          {
+            "name":"西湖区",
+            "code":"330106"
+          },
+          {
+            "name":"滨江区",
+            "code":"330108"
+          },
+          {
+            "name":"萧山区",
+            "code":"330109"
+          },
+          {
+            "name":"余杭区",
+            "code":"330110"
+          },
+          {
+            "name":"富阳区",
+            "code":"330111"
+          },
+          {
+            "name":"桐庐县",
+            "code":"330122"
+          },
+          {
+            "name":"淳安县",
+            "code":"330127"
+          },
+          {
+            "name":"建德市",
+            "code":"330182"
+          },
+          {
+            "name":"临安市",
+            "code":"330185"
+          }
+        ]
+      },
+      {
+        "name":"宁波市",
+        "code":"330200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330201"
+          },
+          {
+            "name":"海曙区",
+            "code":"330203"
+          },
+          {
+            "name":"江东区",
+            "code":"330204"
+          },
+          {
+            "name":"江北区",
+            "code":"330205"
+          },
+          {
+            "name":"北仑区",
+            "code":"330206"
+          },
+          {
+            "name":"镇海区",
+            "code":"330211"
+          },
+          {
+            "name":"鄞州区",
+            "code":"330212"
+          },
+          {
+            "name":"象山县",
+            "code":"330225"
+          },
+          {
+            "name":"宁海县",
+            "code":"330226"
+          },
+          {
+            "name":"余姚市",
+            "code":"330281"
+          },
+          {
+            "name":"慈溪市",
+            "code":"330282"
+          },
+          {
+            "name":"奉化市",
+            "code":"330283"
+          }
+        ]
+      },
+      {
+        "name":"温州市",
+        "code":"330300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330301"
+          },
+          {
+            "name":"鹿城区",
+            "code":"330302"
+          },
+          {
+            "name":"龙湾区",
+            "code":"330303"
+          },
+          {
+            "name":"瓯海区",
+            "code":"330304"
+          },
+          {
+            "name":"洞头县",
+            "code":"330322"
+          },
+          {
+            "name":"永嘉县",
+            "code":"330324"
+          },
+          {
+            "name":"平阳县",
+            "code":"330326"
+          },
+          {
+            "name":"苍南县",
+            "code":"330327"
+          },
+          {
+            "name":"文成县",
+            "code":"330328"
+          },
+          {
+            "name":"泰顺县",
+            "code":"330329"
+          },
+          {
+            "name":"瑞安市",
+            "code":"330381"
+          },
+          {
+            "name":"乐清市",
+            "code":"330382"
+          }
+        ]
+      },
+      {
+        "name":"嘉兴市",
+        "code":"330400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330401"
+          },
+          {
+            "name":"南湖区",
+            "code":"330402"
+          },
+          {
+            "name":"秀洲区",
+            "code":"330411"
+          },
+          {
+            "name":"嘉善县",
+            "code":"330421"
+          },
+          {
+            "name":"海盐县",
+            "code":"330424"
+          },
+          {
+            "name":"海宁市",
+            "code":"330481"
+          },
+          {
+            "name":"平湖市",
+            "code":"330482"
+          },
+          {
+            "name":"桐乡市",
+            "code":"330483"
+          }
+        ]
+      },
+      {
+        "name":"湖州市",
+        "code":"330500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330501"
+          },
+          {
+            "name":"吴兴区",
+            "code":"330502"
+          },
+          {
+            "name":"南浔区",
+            "code":"330503"
+          },
+          {
+            "name":"德清县",
+            "code":"330521"
+          },
+          {
+            "name":"长兴县",
+            "code":"330522"
+          },
+          {
+            "name":"安吉县",
+            "code":"330523"
+          }
+        ]
+      },
+      {
+        "name":"绍兴市",
+        "code":"330600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330601"
+          },
+          {
+            "name":"越城区",
+            "code":"330602"
+          },
+          {
+            "name":"柯桥区",
+            "code":"330603"
+          },
+          {
+            "name":"上虞区",
+            "code":"330604"
+          },
+          {
+            "name":"新昌县",
+            "code":"330624"
+          },
+          {
+            "name":"诸暨市",
+            "code":"330681"
+          },
+          {
+            "name":"嵊州市",
+            "code":"330683"
+          }
+        ]
+      },
+      {
+        "name":"金华市",
+        "code":"330700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330701"
+          },
+          {
+            "name":"婺城区",
+            "code":"330702"
+          },
+          {
+            "name":"金东区",
+            "code":"330703"
+          },
+          {
+            "name":"武义县",
+            "code":"330723"
+          },
+          {
+            "name":"浦江县",
+            "code":"330726"
+          },
+          {
+            "name":"磐安县",
+            "code":"330727"
+          },
+          {
+            "name":"兰溪市",
+            "code":"330781"
+          },
+          {
+            "name":"义乌市",
+            "code":"330782"
+          },
+          {
+            "name":"东阳市",
+            "code":"330783"
+          },
+          {
+            "name":"永康市",
+            "code":"330784"
+          }
+        ]
+      },
+      {
+        "name":"衢州市",
+        "code":"330800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330801"
+          },
+          {
+            "name":"柯城区",
+            "code":"330802"
+          },
+          {
+            "name":"衢江区",
+            "code":"330803"
+          },
+          {
+            "name":"常山县",
+            "code":"330822"
+          },
+          {
+            "name":"开化县",
+            "code":"330824"
+          },
+          {
+            "name":"龙游县",
+            "code":"330825"
+          },
+          {
+            "name":"江山市",
+            "code":"330881"
+          }
+        ]
+      },
+      {
+        "name":"舟山市",
+        "code":"330900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"330901"
+          },
+          {
+            "name":"定海区",
+            "code":"330902"
+          },
+          {
+            "name":"普陀区",
+            "code":"330903"
+          },
+          {
+            "name":"岱山县",
+            "code":"330921"
+          },
+          {
+            "name":"嵊泗县",
+            "code":"330922"
+          }
+        ]
+      },
+      {
+        "name":"台州市",
+        "code":"331000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"331001"
+          },
+          {
+            "name":"椒江区",
+            "code":"331002"
+          },
+          {
+            "name":"黄岩区",
+            "code":"331003"
+          },
+          {
+            "name":"路桥区",
+            "code":"331004"
+          },
+          {
+            "name":"玉环县",
+            "code":"331021"
+          },
+          {
+            "name":"三门县",
+            "code":"331022"
+          },
+          {
+            "name":"天台县",
+            "code":"331023"
+          },
+          {
+            "name":"仙居县",
+            "code":"331024"
+          },
+          {
+            "name":"温岭市",
+            "code":"331081"
+          },
+          {
+            "name":"临海市",
+            "code":"331082"
+          }
+        ]
+      },
+      {
+        "name":"丽水市",
+        "code":"331100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"331101"
+          },
+          {
+            "name":"莲都区",
+            "code":"331102"
+          },
+          {
+            "name":"青田县",
+            "code":"331121"
+          },
+          {
+            "name":"缙云县",
+            "code":"331122"
+          },
+          {
+            "name":"遂昌县",
+            "code":"331123"
+          },
+          {
+            "name":"松阳县",
+            "code":"331124"
+          },
+          {
+            "name":"云和县",
+            "code":"331125"
+          },
+          {
+            "name":"庆元县",
+            "code":"331126"
+          },
+          {
+            "name":"景宁畲族自治县",
+            "code":"331127"
+          },
+          {
+            "name":"龙泉市",
+            "code":"331181"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"安徽省",
+    "code":"340000",
+    "sub":[
+      {
+        "name":"合肥市",
+        "code":"340100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340101"
+          },
+          {
+            "name":"瑶海区",
+            "code":"340102"
+          },
+          {
+            "name":"庐阳区",
+            "code":"340103"
+          },
+          {
+            "name":"蜀山区",
+            "code":"340104"
+          },
+          {
+            "name":"包河区",
+            "code":"340111"
+          },
+          {
+            "name":"长丰县",
+            "code":"340121"
+          },
+          {
+            "name":"肥东县",
+            "code":"340122"
+          },
+          {
+            "name":"肥西县",
+            "code":"340123"
+          },
+          {
+            "name":"庐江县",
+            "code":"340124"
+          },
+          {
+            "name":"巢湖市",
+            "code":"340181"
+          }
+        ]
+      },
+      {
+        "name":"芜湖市",
+        "code":"340200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340201"
+          },
+          {
+            "name":"镜湖区",
+            "code":"340202"
+          },
+          {
+            "name":"弋江区",
+            "code":"340203"
+          },
+          {
+            "name":"鸠江区",
+            "code":"340207"
+          },
+          {
+            "name":"三山区",
+            "code":"340208"
+          },
+          {
+            "name":"芜湖县",
+            "code":"340221"
+          },
+          {
+            "name":"繁昌县",
+            "code":"340222"
+          },
+          {
+            "name":"南陵县",
+            "code":"340223"
+          },
+          {
+            "name":"无为县",
+            "code":"340225"
+          }
+        ]
+      },
+      {
+        "name":"蚌埠市",
+        "code":"340300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340301"
+          },
+          {
+            "name":"龙子湖区",
+            "code":"340302"
+          },
+          {
+            "name":"蚌山区",
+            "code":"340303"
+          },
+          {
+            "name":"禹会区",
+            "code":"340304"
+          },
+          {
+            "name":"淮上区",
+            "code":"340311"
+          },
+          {
+            "name":"怀远县",
+            "code":"340321"
+          },
+          {
+            "name":"五河县",
+            "code":"340322"
+          },
+          {
+            "name":"固镇县",
+            "code":"340323"
+          }
+        ]
+      },
+      {
+        "name":"淮南市",
+        "code":"340400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340401"
+          },
+          {
+            "name":"大通区",
+            "code":"340402"
+          },
+          {
+            "name":"田家庵区",
+            "code":"340403"
+          },
+          {
+            "name":"谢家集区",
+            "code":"340404"
+          },
+          {
+            "name":"八公山区",
+            "code":"340405"
+          },
+          {
+            "name":"潘集区",
+            "code":"340406"
+          },
+          {
+            "name":"凤台县",
+            "code":"340421"
+          }
+        ]
+      },
+      {
+        "name":"马鞍山市",
+        "code":"340500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340501"
+          },
+          {
+            "name":"花山区",
+            "code":"340503"
+          },
+          {
+            "name":"雨山区",
+            "code":"340504"
+          },
+          {
+            "name":"博望区",
+            "code":"340506"
+          },
+          {
+            "name":"当涂县",
+            "code":"340521"
+          },
+          {
+            "name":"含山县",
+            "code":"340522"
+          },
+          {
+            "name":"和县",
+            "code":"340523"
+          }
+        ]
+      },
+      {
+        "name":"淮北市",
+        "code":"340600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340601"
+          },
+          {
+            "name":"杜集区",
+            "code":"340602"
+          },
+          {
+            "name":"相山区",
+            "code":"340603"
+          },
+          {
+            "name":"烈山区",
+            "code":"340604"
+          },
+          {
+            "name":"濉溪县",
+            "code":"340621"
+          }
+        ]
+      },
+      {
+        "name":"铜陵市",
+        "code":"340700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340701"
+          },
+          {
+            "name":"铜官山区",
+            "code":"340702"
+          },
+          {
+            "name":"狮子山区",
+            "code":"340703"
+          },
+          {
+            "name":"郊区",
+            "code":"340711"
+          },
+          {
+            "name":"铜陵县",
+            "code":"340721"
+          }
+        ]
+      },
+      {
+        "name":"安庆市",
+        "code":"340800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"340801"
+          },
+          {
+            "name":"迎江区",
+            "code":"340802"
+          },
+          {
+            "name":"大观区",
+            "code":"340803"
+          },
+          {
+            "name":"宜秀区",
+            "code":"340811"
+          },
+          {
+            "name":"怀宁县",
+            "code":"340822"
+          },
+          {
+            "name":"枞阳县",
+            "code":"340823"
+          },
+          {
+            "name":"潜山县",
+            "code":"340824"
+          },
+          {
+            "name":"太湖县",
+            "code":"340825"
+          },
+          {
+            "name":"宿松县",
+            "code":"340826"
+          },
+          {
+            "name":"望江县",
+            "code":"340827"
+          },
+          {
+            "name":"岳西县",
+            "code":"340828"
+          },
+          {
+            "name":"桐城市",
+            "code":"340881"
+          }
+        ]
+      },
+      {
+        "name":"黄山市",
+        "code":"341000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341001"
+          },
+          {
+            "name":"屯溪区",
+            "code":"341002"
+          },
+          {
+            "name":"黄山区",
+            "code":"341003"
+          },
+          {
+            "name":"徽州区",
+            "code":"341004"
+          },
+          {
+            "name":"歙县",
+            "code":"341021"
+          },
+          {
+            "name":"休宁县",
+            "code":"341022"
+          },
+          {
+            "name":"黟县",
+            "code":"341023"
+          },
+          {
+            "name":"祁门县",
+            "code":"341024"
+          }
+        ]
+      },
+      {
+        "name":"滁州市",
+        "code":"341100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341101"
+          },
+          {
+            "name":"琅琊区",
+            "code":"341102"
+          },
+          {
+            "name":"南谯区",
+            "code":"341103"
+          },
+          {
+            "name":"来安县",
+            "code":"341122"
+          },
+          {
+            "name":"全椒县",
+            "code":"341124"
+          },
+          {
+            "name":"定远县",
+            "code":"341125"
+          },
+          {
+            "name":"凤阳县",
+            "code":"341126"
+          },
+          {
+            "name":"天长市",
+            "code":"341181"
+          },
+          {
+            "name":"明光市",
+            "code":"341182"
+          }
+        ]
+      },
+      {
+        "name":"阜阳市",
+        "code":"341200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341201"
+          },
+          {
+            "name":"颍州区",
+            "code":"341202"
+          },
+          {
+            "name":"颍东区",
+            "code":"341203"
+          },
+          {
+            "name":"颍泉区",
+            "code":"341204"
+          },
+          {
+            "name":"临泉县",
+            "code":"341221"
+          },
+          {
+            "name":"太和县",
+            "code":"341222"
+          },
+          {
+            "name":"阜南县",
+            "code":"341225"
+          },
+          {
+            "name":"颍上县",
+            "code":"341226"
+          },
+          {
+            "name":"界首市",
+            "code":"341282"
+          }
+        ]
+      },
+      {
+        "name":"宿州市",
+        "code":"341300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341301"
+          },
+          {
+            "name":"埇桥区",
+            "code":"341302"
+          },
+          {
+            "name":"砀山县",
+            "code":"341321"
+          },
+          {
+            "name":"萧县",
+            "code":"341322"
+          },
+          {
+            "name":"灵璧县",
+            "code":"341323"
+          },
+          {
+            "name":"泗县",
+            "code":"341324"
+          }
+        ]
+      },
+      {
+        "name":"六安市",
+        "code":"341500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341501"
+          },
+          {
+            "name":"金安区",
+            "code":"341502"
+          },
+          {
+            "name":"裕安区",
+            "code":"341503"
+          },
+          {
+            "name":"寿县",
+            "code":"341521"
+          },
+          {
+            "name":"霍邱县",
+            "code":"341522"
+          },
+          {
+            "name":"舒城县",
+            "code":"341523"
+          },
+          {
+            "name":"金寨县",
+            "code":"341524"
+          },
+          {
+            "name":"霍山县",
+            "code":"341525"
+          }
+        ]
+      },
+      {
+        "name":"亳州市",
+        "code":"341600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341601"
+          },
+          {
+            "name":"谯城区",
+            "code":"341602"
+          },
+          {
+            "name":"涡阳县",
+            "code":"341621"
+          },
+          {
+            "name":"蒙城县",
+            "code":"341622"
+          },
+          {
+            "name":"利辛县",
+            "code":"341623"
+          }
+        ]
+      },
+      {
+        "name":"池州市",
+        "code":"341700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341701"
+          },
+          {
+            "name":"贵池区",
+            "code":"341702"
+          },
+          {
+            "name":"东至县",
+            "code":"341721"
+          },
+          {
+            "name":"石台县",
+            "code":"341722"
+          },
+          {
+            "name":"青阳县",
+            "code":"341723"
+          }
+        ]
+      },
+      {
+        "name":"宣城市",
+        "code":"341800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"341801"
+          },
+          {
+            "name":"宣州区",
+            "code":"341802"
+          },
+          {
+            "name":"郎溪县",
+            "code":"341821"
+          },
+          {
+            "name":"广德县",
+            "code":"341822"
+          },
+          {
+            "name":"泾县",
+            "code":"341823"
+          },
+          {
+            "name":"绩溪县",
+            "code":"341824"
+          },
+          {
+            "name":"旌德县",
+            "code":"341825"
+          },
+          {
+            "name":"宁国市",
+            "code":"341881"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"福建省",
+    "code":"350000",
+    "sub":[
+      {
+        "name":"福州市",
+        "code":"350100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350101"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"350102"
+          },
+          {
+            "name":"台江区",
+            "code":"350103"
+          },
+          {
+            "name":"仓山区",
+            "code":"350104"
+          },
+          {
+            "name":"马尾区",
+            "code":"350105"
+          },
+          {
+            "name":"晋安区",
+            "code":"350111"
+          },
+          {
+            "name":"闽侯县",
+            "code":"350121"
+          },
+          {
+            "name":"连江县",
+            "code":"350122"
+          },
+          {
+            "name":"罗源县",
+            "code":"350123"
+          },
+          {
+            "name":"闽清县",
+            "code":"350124"
+          },
+          {
+            "name":"永泰县",
+            "code":"350125"
+          },
+          {
+            "name":"平潭县",
+            "code":"350128"
+          },
+          {
+            "name":"福清市",
+            "code":"350181"
+          },
+          {
+            "name":"长乐市",
+            "code":"350182"
+          }
+        ]
+      },
+      {
+        "name":"厦门市",
+        "code":"350200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350201"
+          },
+          {
+            "name":"思明区",
+            "code":"350203"
+          },
+          {
+            "name":"海沧区",
+            "code":"350205"
+          },
+          {
+            "name":"湖里区",
+            "code":"350206"
+          },
+          {
+            "name":"集美区",
+            "code":"350211"
+          },
+          {
+            "name":"同安区",
+            "code":"350212"
+          },
+          {
+            "name":"翔安区",
+            "code":"350213"
+          }
+        ]
+      },
+      {
+        "name":"莆田市",
+        "code":"350300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350301"
+          },
+          {
+            "name":"城厢区",
+            "code":"350302"
+          },
+          {
+            "name":"涵江区",
+            "code":"350303"
+          },
+          {
+            "name":"荔城区",
+            "code":"350304"
+          },
+          {
+            "name":"秀屿区",
+            "code":"350305"
+          },
+          {
+            "name":"仙游县",
+            "code":"350322"
+          }
+        ]
+      },
+      {
+        "name":"三明市",
+        "code":"350400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350401"
+          },
+          {
+            "name":"梅列区",
+            "code":"350402"
+          },
+          {
+            "name":"三元区",
+            "code":"350403"
+          },
+          {
+            "name":"明溪县",
+            "code":"350421"
+          },
+          {
+            "name":"清流县",
+            "code":"350423"
+          },
+          {
+            "name":"宁化县",
+            "code":"350424"
+          },
+          {
+            "name":"大田县",
+            "code":"350425"
+          },
+          {
+            "name":"尤溪县",
+            "code":"350426"
+          },
+          {
+            "name":"沙县",
+            "code":"350427"
+          },
+          {
+            "name":"将乐县",
+            "code":"350428"
+          },
+          {
+            "name":"泰宁县",
+            "code":"350429"
+          },
+          {
+            "name":"建宁县",
+            "code":"350430"
+          },
+          {
+            "name":"永安市",
+            "code":"350481"
+          }
+        ]
+      },
+      {
+        "name":"泉州市",
+        "code":"350500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350501"
+          },
+          {
+            "name":"鲤城区",
+            "code":"350502"
+          },
+          {
+            "name":"丰泽区",
+            "code":"350503"
+          },
+          {
+            "name":"洛江区",
+            "code":"350504"
+          },
+          {
+            "name":"泉港区",
+            "code":"350505"
+          },
+          {
+            "name":"惠安县",
+            "code":"350521"
+          },
+          {
+            "name":"安溪县",
+            "code":"350524"
+          },
+          {
+            "name":"永春县",
+            "code":"350525"
+          },
+          {
+            "name":"德化县",
+            "code":"350526"
+          },
+          {
+            "name":"金门县",
+            "code":"350527"
+          },
+          {
+            "name":"石狮市",
+            "code":"350581"
+          },
+          {
+            "name":"晋江市",
+            "code":"350582"
+          },
+          {
+            "name":"南安市",
+            "code":"350583"
+          }
+        ]
+      },
+      {
+        "name":"漳州市",
+        "code":"350600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350601"
+          },
+          {
+            "name":"芗城区",
+            "code":"350602"
+          },
+          {
+            "name":"龙文区",
+            "code":"350603"
+          },
+          {
+            "name":"云霄县",
+            "code":"350622"
+          },
+          {
+            "name":"漳浦县",
+            "code":"350623"
+          },
+          {
+            "name":"诏安县",
+            "code":"350624"
+          },
+          {
+            "name":"长泰县",
+            "code":"350625"
+          },
+          {
+            "name":"东山县",
+            "code":"350626"
+          },
+          {
+            "name":"南靖县",
+            "code":"350627"
+          },
+          {
+            "name":"平和县",
+            "code":"350628"
+          },
+          {
+            "name":"华安县",
+            "code":"350629"
+          },
+          {
+            "name":"龙海市",
+            "code":"350681"
+          }
+        ]
+      },
+      {
+        "name":"南平市",
+        "code":"350700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350701"
+          },
+          {
+            "name":"延平区",
+            "code":"350702"
+          },
+          {
+            "name":"建阳区",
+            "code":"350703"
+          },
+          {
+            "name":"顺昌县",
+            "code":"350721"
+          },
+          {
+            "name":"浦城县",
+            "code":"350722"
+          },
+          {
+            "name":"光泽县",
+            "code":"350723"
+          },
+          {
+            "name":"松溪县",
+            "code":"350724"
+          },
+          {
+            "name":"政和县",
+            "code":"350725"
+          },
+          {
+            "name":"邵武市",
+            "code":"350781"
+          },
+          {
+            "name":"武夷山市",
+            "code":"350782"
+          },
+          {
+            "name":"建瓯市",
+            "code":"350783"
+          }
+        ]
+      },
+      {
+        "name":"龙岩市",
+        "code":"350800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350801"
+          },
+          {
+            "name":"新罗区",
+            "code":"350802"
+          },
+          {
+            "name":"永定区",
+            "code":"350803"
+          },
+          {
+            "name":"长汀县",
+            "code":"350821"
+          },
+          {
+            "name":"上杭县",
+            "code":"350823"
+          },
+          {
+            "name":"武平县",
+            "code":"350824"
+          },
+          {
+            "name":"连城县",
+            "code":"350825"
+          },
+          {
+            "name":"漳平市",
+            "code":"350881"
+          }
+        ]
+      },
+      {
+        "name":"宁德市",
+        "code":"350900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"350901"
+          },
+          {
+            "name":"蕉城区",
+            "code":"350902"
+          },
+          {
+            "name":"霞浦县",
+            "code":"350921"
+          },
+          {
+            "name":"古田县",
+            "code":"350922"
+          },
+          {
+            "name":"屏南县",
+            "code":"350923"
+          },
+          {
+            "name":"寿宁县",
+            "code":"350924"
+          },
+          {
+            "name":"周宁县",
+            "code":"350925"
+          },
+          {
+            "name":"柘荣县",
+            "code":"350926"
+          },
+          {
+            "name":"福安市",
+            "code":"350981"
+          },
+          {
+            "name":"福鼎市",
+            "code":"350982"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"江西省",
+    "code":"360000",
+    "sub":[
+      {
+        "name":"南昌市",
+        "code":"360100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360101"
+          },
+          {
+            "name":"东湖区",
+            "code":"360102"
+          },
+          {
+            "name":"西湖区",
+            "code":"360103"
+          },
+          {
+            "name":"青云谱区",
+            "code":"360104"
+          },
+          {
+            "name":"湾里区",
+            "code":"360105"
+          },
+          {
+            "name":"青山湖区",
+            "code":"360111"
+          },
+          {
+            "name":"南昌县",
+            "code":"360121"
+          },
+          {
+            "name":"新建县",
+            "code":"360122"
+          },
+          {
+            "name":"安义县",
+            "code":"360123"
+          },
+          {
+            "name":"进贤县",
+            "code":"360124"
+          }
+        ]
+      },
+      {
+        "name":"景德镇市",
+        "code":"360200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360201"
+          },
+          {
+            "name":"昌江区",
+            "code":"360202"
+          },
+          {
+            "name":"珠山区",
+            "code":"360203"
+          },
+          {
+            "name":"浮梁县",
+            "code":"360222"
+          },
+          {
+            "name":"乐平市",
+            "code":"360281"
+          }
+        ]
+      },
+      {
+        "name":"萍乡市",
+        "code":"360300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360301"
+          },
+          {
+            "name":"安源区",
+            "code":"360302"
+          },
+          {
+            "name":"湘东区",
+            "code":"360313"
+          },
+          {
+            "name":"莲花县",
+            "code":"360321"
+          },
+          {
+            "name":"上栗县",
+            "code":"360322"
+          },
+          {
+            "name":"芦溪县",
+            "code":"360323"
+          }
+        ]
+      },
+      {
+        "name":"九江市",
+        "code":"360400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360401"
+          },
+          {
+            "name":"庐山区",
+            "code":"360402"
+          },
+          {
+            "name":"浔阳区",
+            "code":"360403"
+          },
+          {
+            "name":"九江县",
+            "code":"360421"
+          },
+          {
+            "name":"武宁县",
+            "code":"360423"
+          },
+          {
+            "name":"修水县",
+            "code":"360424"
+          },
+          {
+            "name":"永修县",
+            "code":"360425"
+          },
+          {
+            "name":"德安县",
+            "code":"360426"
+          },
+          {
+            "name":"星子县",
+            "code":"360427"
+          },
+          {
+            "name":"都昌县",
+            "code":"360428"
+          },
+          {
+            "name":"湖口县",
+            "code":"360429"
+          },
+          {
+            "name":"彭泽县",
+            "code":"360430"
+          },
+          {
+            "name":"瑞昌市",
+            "code":"360481"
+          },
+          {
+            "name":"共青城市",
+            "code":"360482"
+          }
+        ]
+      },
+      {
+        "name":"新余市",
+        "code":"360500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360501"
+          },
+          {
+            "name":"渝水区",
+            "code":"360502"
+          },
+          {
+            "name":"分宜县",
+            "code":"360521"
+          }
+        ]
+      },
+      {
+        "name":"鹰潭市",
+        "code":"360600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360601"
+          },
+          {
+            "name":"月湖区",
+            "code":"360602"
+          },
+          {
+            "name":"余江县",
+            "code":"360622"
+          },
+          {
+            "name":"贵溪市",
+            "code":"360681"
+          }
+        ]
+      },
+      {
+        "name":"赣州市",
+        "code":"360700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360701"
+          },
+          {
+            "name":"章贡区",
+            "code":"360702"
+          },
+          {
+            "name":"南康区",
+            "code":"360703"
+          },
+          {
+            "name":"赣县",
+            "code":"360721"
+          },
+          {
+            "name":"信丰县",
+            "code":"360722"
+          },
+          {
+            "name":"大余县",
+            "code":"360723"
+          },
+          {
+            "name":"上犹县",
+            "code":"360724"
+          },
+          {
+            "name":"崇义县",
+            "code":"360725"
+          },
+          {
+            "name":"安远县",
+            "code":"360726"
+          },
+          {
+            "name":"龙南县",
+            "code":"360727"
+          },
+          {
+            "name":"定南县",
+            "code":"360728"
+          },
+          {
+            "name":"全南县",
+            "code":"360729"
+          },
+          {
+            "name":"宁都县",
+            "code":"360730"
+          },
+          {
+            "name":"于都县",
+            "code":"360731"
+          },
+          {
+            "name":"兴国县",
+            "code":"360732"
+          },
+          {
+            "name":"会昌县",
+            "code":"360733"
+          },
+          {
+            "name":"寻乌县",
+            "code":"360734"
+          },
+          {
+            "name":"石城县",
+            "code":"360735"
+          },
+          {
+            "name":"瑞金市",
+            "code":"360781"
+          }
+        ]
+      },
+      {
+        "name":"吉安市",
+        "code":"360800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360801"
+          },
+          {
+            "name":"吉州区",
+            "code":"360802"
+          },
+          {
+            "name":"青原区",
+            "code":"360803"
+          },
+          {
+            "name":"吉安县",
+            "code":"360821"
+          },
+          {
+            "name":"吉水县",
+            "code":"360822"
+          },
+          {
+            "name":"峡江县",
+            "code":"360823"
+          },
+          {
+            "name":"新干县",
+            "code":"360824"
+          },
+          {
+            "name":"永丰县",
+            "code":"360825"
+          },
+          {
+            "name":"泰和县",
+            "code":"360826"
+          },
+          {
+            "name":"遂川县",
+            "code":"360827"
+          },
+          {
+            "name":"万安县",
+            "code":"360828"
+          },
+          {
+            "name":"安福县",
+            "code":"360829"
+          },
+          {
+            "name":"永新县",
+            "code":"360830"
+          },
+          {
+            "name":"井冈山市",
+            "code":"360881"
+          }
+        ]
+      },
+      {
+        "name":"宜春市",
+        "code":"360900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"360901"
+          },
+          {
+            "name":"袁州区",
+            "code":"360902"
+          },
+          {
+            "name":"奉新县",
+            "code":"360921"
+          },
+          {
+            "name":"万载县",
+            "code":"360922"
+          },
+          {
+            "name":"上高县",
+            "code":"360923"
+          },
+          {
+            "name":"宜丰县",
+            "code":"360924"
+          },
+          {
+            "name":"靖安县",
+            "code":"360925"
+          },
+          {
+            "name":"铜鼓县",
+            "code":"360926"
+          },
+          {
+            "name":"丰城市",
+            "code":"360981"
+          },
+          {
+            "name":"樟树市",
+            "code":"360982"
+          },
+          {
+            "name":"高安市",
+            "code":"360983"
+          }
+        ]
+      },
+      {
+        "name":"抚州市",
+        "code":"361000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"361001"
+          },
+          {
+            "name":"临川区",
+            "code":"361002"
+          },
+          {
+            "name":"南城县",
+            "code":"361021"
+          },
+          {
+            "name":"黎川县",
+            "code":"361022"
+          },
+          {
+            "name":"南丰县",
+            "code":"361023"
+          },
+          {
+            "name":"崇仁县",
+            "code":"361024"
+          },
+          {
+            "name":"乐安县",
+            "code":"361025"
+          },
+          {
+            "name":"宜黄县",
+            "code":"361026"
+          },
+          {
+            "name":"金溪县",
+            "code":"361027"
+          },
+          {
+            "name":"资溪县",
+            "code":"361028"
+          },
+          {
+            "name":"东乡县",
+            "code":"361029"
+          },
+          {
+            "name":"广昌县",
+            "code":"361030"
+          }
+        ]
+      },
+      {
+        "name":"上饶市",
+        "code":"361100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"361101"
+          },
+          {
+            "name":"信州区",
+            "code":"361102"
+          },
+          {
+            "name":"上饶县",
+            "code":"361121"
+          },
+          {
+            "name":"广丰县",
+            "code":"361122"
+          },
+          {
+            "name":"玉山县",
+            "code":"361123"
+          },
+          {
+            "name":"铅山县",
+            "code":"361124"
+          },
+          {
+            "name":"横峰县",
+            "code":"361125"
+          },
+          {
+            "name":"弋阳县",
+            "code":"361126"
+          },
+          {
+            "name":"余干县",
+            "code":"361127"
+          },
+          {
+            "name":"鄱阳县",
+            "code":"361128"
+          },
+          {
+            "name":"万年县",
+            "code":"361129"
+          },
+          {
+            "name":"婺源县",
+            "code":"361130"
+          },
+          {
+            "name":"德兴市",
+            "code":"361181"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"山东省",
+    "code":"370000",
+    "sub":[
+      {
+        "name":"济南市",
+        "code":"370100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370101"
+          },
+          {
+            "name":"历下区",
+            "code":"370102"
+          },
+          {
+            "name":"市中区",
+            "code":"370103"
+          },
+          {
+            "name":"槐荫区",
+            "code":"370104"
+          },
+          {
+            "name":"天桥区",
+            "code":"370105"
+          },
+          {
+            "name":"历城区",
+            "code":"370112"
+          },
+          {
+            "name":"长清区",
+            "code":"370113"
+          },
+          {
+            "name":"平阴县",
+            "code":"370124"
+          },
+          {
+            "name":"济阳县",
+            "code":"370125"
+          },
+          {
+            "name":"商河县",
+            "code":"370126"
+          },
+          {
+            "name":"章丘市",
+            "code":"370181"
+          }
+        ]
+      },
+      {
+        "name":"青岛市",
+        "code":"370200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370201"
+          },
+          {
+            "name":"市南区",
+            "code":"370202"
+          },
+          {
+            "name":"市北区",
+            "code":"370203"
+          },
+          {
+            "name":"黄岛区",
+            "code":"370211"
+          },
+          {
+            "name":"崂山区",
+            "code":"370212"
+          },
+          {
+            "name":"李沧区",
+            "code":"370213"
+          },
+          {
+            "name":"城阳区",
+            "code":"370214"
+          },
+          {
+            "name":"胶州市",
+            "code":"370281"
+          },
+          {
+            "name":"即墨市",
+            "code":"370282"
+          },
+          {
+            "name":"平度市",
+            "code":"370283"
+          },
+          {
+            "name":"莱西市",
+            "code":"370285"
+          }
+        ]
+      },
+      {
+        "name":"淄博市",
+        "code":"370300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370301"
+          },
+          {
+            "name":"淄川区",
+            "code":"370302"
+          },
+          {
+            "name":"张店区",
+            "code":"370303"
+          },
+          {
+            "name":"博山区",
+            "code":"370304"
+          },
+          {
+            "name":"临淄区",
+            "code":"370305"
+          },
+          {
+            "name":"周村区",
+            "code":"370306"
+          },
+          {
+            "name":"桓台县",
+            "code":"370321"
+          },
+          {
+            "name":"高青县",
+            "code":"370322"
+          },
+          {
+            "name":"沂源县",
+            "code":"370323"
+          }
+        ]
+      },
+      {
+        "name":"枣庄市",
+        "code":"370400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370401"
+          },
+          {
+            "name":"市中区",
+            "code":"370402"
+          },
+          {
+            "name":"薛城区",
+            "code":"370403"
+          },
+          {
+            "name":"峄城区",
+            "code":"370404"
+          },
+          {
+            "name":"台儿庄区",
+            "code":"370405"
+          },
+          {
+            "name":"山亭区",
+            "code":"370406"
+          },
+          {
+            "name":"滕州市",
+            "code":"370481"
+          }
+        ]
+      },
+      {
+        "name":"东营市",
+        "code":"370500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370501"
+          },
+          {
+            "name":"东营区",
+            "code":"370502"
+          },
+          {
+            "name":"河口区",
+            "code":"370503"
+          },
+          {
+            "name":"垦利县",
+            "code":"370521"
+          },
+          {
+            "name":"利津县",
+            "code":"370522"
+          },
+          {
+            "name":"广饶县",
+            "code":"370523"
+          }
+        ]
+      },
+      {
+        "name":"烟台市",
+        "code":"370600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370601"
+          },
+          {
+            "name":"芝罘区",
+            "code":"370602"
+          },
+          {
+            "name":"福山区",
+            "code":"370611"
+          },
+          {
+            "name":"牟平区",
+            "code":"370612"
+          },
+          {
+            "name":"莱山区",
+            "code":"370613"
+          },
+          {
+            "name":"长岛县",
+            "code":"370634"
+          },
+          {
+            "name":"龙口市",
+            "code":"370681"
+          },
+          {
+            "name":"莱阳市",
+            "code":"370682"
+          },
+          {
+            "name":"莱州市",
+            "code":"370683"
+          },
+          {
+            "name":"蓬莱市",
+            "code":"370684"
+          },
+          {
+            "name":"招远市",
+            "code":"370685"
+          },
+          {
+            "name":"栖霞市",
+            "code":"370686"
+          },
+          {
+            "name":"海阳市",
+            "code":"370687"
+          }
+        ]
+      },
+      {
+        "name":"潍坊市",
+        "code":"370700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370701"
+          },
+          {
+            "name":"潍城区",
+            "code":"370702"
+          },
+          {
+            "name":"寒亭区",
+            "code":"370703"
+          },
+          {
+            "name":"坊子区",
+            "code":"370704"
+          },
+          {
+            "name":"奎文区",
+            "code":"370705"
+          },
+          {
+            "name":"临朐县",
+            "code":"370724"
+          },
+          {
+            "name":"昌乐县",
+            "code":"370725"
+          },
+          {
+            "name":"青州市",
+            "code":"370781"
+          },
+          {
+            "name":"诸城市",
+            "code":"370782"
+          },
+          {
+            "name":"寿光市",
+            "code":"370783"
+          },
+          {
+            "name":"安丘市",
+            "code":"370784"
+          },
+          {
+            "name":"高密市",
+            "code":"370785"
+          },
+          {
+            "name":"昌邑市",
+            "code":"370786"
+          }
+        ]
+      },
+      {
+        "name":"济宁市",
+        "code":"370800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370801"
+          },
+          {
+            "name":"任城区",
+            "code":"370811"
+          },
+          {
+            "name":"兖州区",
+            "code":"370812"
+          },
+          {
+            "name":"微山县",
+            "code":"370826"
+          },
+          {
+            "name":"鱼台县",
+            "code":"370827"
+          },
+          {
+            "name":"金乡县",
+            "code":"370828"
+          },
+          {
+            "name":"嘉祥县",
+            "code":"370829"
+          },
+          {
+            "name":"汶上县",
+            "code":"370830"
+          },
+          {
+            "name":"泗水县",
+            "code":"370831"
+          },
+          {
+            "name":"梁山县",
+            "code":"370832"
+          },
+          {
+            "name":"曲阜市",
+            "code":"370881"
+          },
+          {
+            "name":"邹城市",
+            "code":"370883"
+          }
+        ]
+      },
+      {
+        "name":"泰安市",
+        "code":"370900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"370901"
+          },
+          {
+            "name":"泰山区",
+            "code":"370902"
+          },
+          {
+            "name":"岱岳区",
+            "code":"370911"
+          },
+          {
+            "name":"宁阳县",
+            "code":"370921"
+          },
+          {
+            "name":"东平县",
+            "code":"370923"
+          },
+          {
+            "name":"新泰市",
+            "code":"370982"
+          },
+          {
+            "name":"肥城市",
+            "code":"370983"
+          }
+        ]
+      },
+      {
+        "name":"威海市",
+        "code":"371000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371001"
+          },
+          {
+            "name":"环翠区",
+            "code":"371002"
+          },
+          {
+            "name":"文登市",
+            "code":"371081"
+          },
+          {
+            "name":"荣成市",
+            "code":"371082"
+          },
+          {
+            "name":"乳山市",
+            "code":"371083"
+          }
+        ]
+      },
+      {
+        "name":"日照市",
+        "code":"371100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371101"
+          },
+          {
+            "name":"东港区",
+            "code":"371102"
+          },
+          {
+            "name":"岚山区",
+            "code":"371103"
+          },
+          {
+            "name":"五莲县",
+            "code":"371121"
+          },
+          {
+            "name":"莒县",
+            "code":"371122"
+          }
+        ]
+      },
+      {
+        "name":"莱芜市",
+        "code":"371200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371201"
+          },
+          {
+            "name":"莱城区",
+            "code":"371202"
+          },
+          {
+            "name":"钢城区",
+            "code":"371203"
+          }
+        ]
+      },
+      {
+        "name":"临沂市",
+        "code":"371300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371301"
+          },
+          {
+            "name":"兰山区",
+            "code":"371302"
+          },
+          {
+            "name":"罗庄区",
+            "code":"371311"
+          },
+          {
+            "name":"河东区",
+            "code":"371312"
+          },
+          {
+            "name":"沂南县",
+            "code":"371321"
+          },
+          {
+            "name":"郯城县",
+            "code":"371322"
+          },
+          {
+            "name":"沂水县",
+            "code":"371323"
+          },
+          {
+            "name":"兰陵县",
+            "code":"371324"
+          },
+          {
+            "name":"费县",
+            "code":"371325"
+          },
+          {
+            "name":"平邑县",
+            "code":"371326"
+          },
+          {
+            "name":"莒南县",
+            "code":"371327"
+          },
+          {
+            "name":"蒙阴县",
+            "code":"371328"
+          },
+          {
+            "name":"临沭县",
+            "code":"371329"
+          }
+        ]
+      },
+      {
+        "name":"德州市",
+        "code":"371400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371401"
+          },
+          {
+            "name":"德城区",
+            "code":"371402"
+          },
+          {
+            "name":"陵城区",
+            "code":"371403"
+          },
+          {
+            "name":"宁津县",
+            "code":"371422"
+          },
+          {
+            "name":"庆云县",
+            "code":"371423"
+          },
+          {
+            "name":"临邑县",
+            "code":"371424"
+          },
+          {
+            "name":"齐河县",
+            "code":"371425"
+          },
+          {
+            "name":"平原县",
+            "code":"371426"
+          },
+          {
+            "name":"夏津县",
+            "code":"371427"
+          },
+          {
+            "name":"武城县",
+            "code":"371428"
+          },
+          {
+            "name":"乐陵市",
+            "code":"371481"
+          },
+          {
+            "name":"禹城市",
+            "code":"371482"
+          }
+        ]
+      },
+      {
+        "name":"聊城市",
+        "code":"371500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371501"
+          },
+          {
+            "name":"东昌府区",
+            "code":"371502"
+          },
+          {
+            "name":"阳谷县",
+            "code":"371521"
+          },
+          {
+            "name":"莘县",
+            "code":"371522"
+          },
+          {
+            "name":"茌平县",
+            "code":"371523"
+          },
+          {
+            "name":"东阿县",
+            "code":"371524"
+          },
+          {
+            "name":"冠县",
+            "code":"371525"
+          },
+          {
+            "name":"高唐县",
+            "code":"371526"
+          },
+          {
+            "name":"临清市",
+            "code":"371581"
+          }
+        ]
+      },
+      {
+        "name":"滨州市",
+        "code":"371600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371601"
+          },
+          {
+            "name":"滨城区",
+            "code":"371602"
+          },
+          {
+            "name":"沾化区",
+            "code":"371603"
+          },
+          {
+            "name":"惠民县",
+            "code":"371621"
+          },
+          {
+            "name":"阳信县",
+            "code":"371622"
+          },
+          {
+            "name":"无棣县",
+            "code":"371623"
+          },
+          {
+            "name":"博兴县",
+            "code":"371625"
+          },
+          {
+            "name":"邹平县",
+            "code":"371626"
+          }
+        ]
+      },
+      {
+        "name":"菏泽市",
+        "code":"371700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"371701"
+          },
+          {
+            "name":"牡丹区",
+            "code":"371702"
+          },
+          {
+            "name":"曹县",
+            "code":"371721"
+          },
+          {
+            "name":"单县",
+            "code":"371722"
+          },
+          {
+            "name":"成武县",
+            "code":"371723"
+          },
+          {
+            "name":"巨野县",
+            "code":"371724"
+          },
+          {
+            "name":"郓城县",
+            "code":"371725"
+          },
+          {
+            "name":"鄄城县",
+            "code":"371726"
+          },
+          {
+            "name":"定陶县",
+            "code":"371727"
+          },
+          {
+            "name":"东明县",
+            "code":"371728"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"河南省",
+    "code":"410000",
+    "sub":[
+      {
+        "name":"郑州市",
+        "code":"410100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410101"
+          },
+          {
+            "name":"中原区",
+            "code":"410102"
+          },
+          {
+            "name":"二七区",
+            "code":"410103"
+          },
+          {
+            "name":"管城回族区",
+            "code":"410104"
+          },
+          {
+            "name":"金水区",
+            "code":"410105"
+          },
+          {
+            "name":"上街区",
+            "code":"410106"
+          },
+          {
+            "name":"惠济区",
+            "code":"410108"
+          },
+          {
+            "name":"中牟县",
+            "code":"410122"
+          },
+          {
+            "name":"巩义市",
+            "code":"410181"
+          },
+          {
+            "name":"荥阳市",
+            "code":"410182"
+          },
+          {
+            "name":"新密市",
+            "code":"410183"
+          },
+          {
+            "name":"新郑市",
+            "code":"410184"
+          },
+          {
+            "name":"登封市",
+            "code":"410185"
+          }
+        ]
+      },
+      {
+        "name":"开封市",
+        "code":"410200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410201"
+          },
+          {
+            "name":"龙亭区",
+            "code":"410202"
+          },
+          {
+            "name":"顺河回族区",
+            "code":"410203"
+          },
+          {
+            "name":"鼓楼区",
+            "code":"410204"
+          },
+          {
+            "name":"禹王台区",
+            "code":"410205"
+          },
+          {
+            "name":"祥符区",
+            "code":"410212"
+          },
+          {
+            "name":"杞县",
+            "code":"410221"
+          },
+          {
+            "name":"通许县",
+            "code":"410222"
+          },
+          {
+            "name":"尉氏县",
+            "code":"410223"
+          },
+          {
+            "name":"兰考县",
+            "code":"410225"
+          }
+        ]
+      },
+      {
+        "name":"洛阳市",
+        "code":"410300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410301"
+          },
+          {
+            "name":"老城区",
+            "code":"410302"
+          },
+          {
+            "name":"西工区",
+            "code":"410303"
+          },
+          {
+            "name":"瀍河回族区",
+            "code":"410304"
+          },
+          {
+            "name":"涧西区",
+            "code":"410305"
+          },
+          {
+            "name":"吉利区",
+            "code":"410306"
+          },
+          {
+            "name":"洛龙区",
+            "code":"410311"
+          },
+          {
+            "name":"孟津县",
+            "code":"410322"
+          },
+          {
+            "name":"新安县",
+            "code":"410323"
+          },
+          {
+            "name":"栾川县",
+            "code":"410324"
+          },
+          {
+            "name":"嵩县",
+            "code":"410325"
+          },
+          {
+            "name":"汝阳县",
+            "code":"410326"
+          },
+          {
+            "name":"宜阳县",
+            "code":"410327"
+          },
+          {
+            "name":"洛宁县",
+            "code":"410328"
+          },
+          {
+            "name":"伊川县",
+            "code":"410329"
+          },
+          {
+            "name":"偃师市",
+            "code":"410381"
+          }
+        ]
+      },
+      {
+        "name":"平顶山市",
+        "code":"410400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410401"
+          },
+          {
+            "name":"新华区",
+            "code":"410402"
+          },
+          {
+            "name":"卫东区",
+            "code":"410403"
+          },
+          {
+            "name":"石龙区",
+            "code":"410404"
+          },
+          {
+            "name":"湛河区",
+            "code":"410411"
+          },
+          {
+            "name":"宝丰县",
+            "code":"410421"
+          },
+          {
+            "name":"叶县",
+            "code":"410422"
+          },
+          {
+            "name":"鲁山县",
+            "code":"410423"
+          },
+          {
+            "name":"郏县",
+            "code":"410425"
+          },
+          {
+            "name":"舞钢市",
+            "code":"410481"
+          },
+          {
+            "name":"汝州市",
+            "code":"410482"
+          }
+        ]
+      },
+      {
+        "name":"安阳市",
+        "code":"410500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410501"
+          },
+          {
+            "name":"文峰区",
+            "code":"410502"
+          },
+          {
+            "name":"北关区",
+            "code":"410503"
+          },
+          {
+            "name":"殷都区",
+            "code":"410505"
+          },
+          {
+            "name":"龙安区",
+            "code":"410506"
+          },
+          {
+            "name":"安阳县",
+            "code":"410522"
+          },
+          {
+            "name":"汤阴县",
+            "code":"410523"
+          },
+          {
+            "name":"滑县",
+            "code":"410526"
+          },
+          {
+            "name":"内黄县",
+            "code":"410527"
+          },
+          {
+            "name":"林州市",
+            "code":"410581"
+          }
+        ]
+      },
+      {
+        "name":"鹤壁市",
+        "code":"410600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410601"
+          },
+          {
+            "name":"鹤山区",
+            "code":"410602"
+          },
+          {
+            "name":"山城区",
+            "code":"410603"
+          },
+          {
+            "name":"淇滨区",
+            "code":"410611"
+          },
+          {
+            "name":"浚县",
+            "code":"410621"
+          },
+          {
+            "name":"淇县",
+            "code":"410622"
+          }
+        ]
+      },
+      {
+        "name":"新乡市",
+        "code":"410700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410701"
+          },
+          {
+            "name":"红旗区",
+            "code":"410702"
+          },
+          {
+            "name":"卫滨区",
+            "code":"410703"
+          },
+          {
+            "name":"凤泉区",
+            "code":"410704"
+          },
+          {
+            "name":"牧野区",
+            "code":"410711"
+          },
+          {
+            "name":"新乡县",
+            "code":"410721"
+          },
+          {
+            "name":"获嘉县",
+            "code":"410724"
+          },
+          {
+            "name":"原阳县",
+            "code":"410725"
+          },
+          {
+            "name":"延津县",
+            "code":"410726"
+          },
+          {
+            "name":"封丘县",
+            "code":"410727"
+          },
+          {
+            "name":"长垣县",
+            "code":"410728"
+          },
+          {
+            "name":"卫辉市",
+            "code":"410781"
+          },
+          {
+            "name":"辉县市",
+            "code":"410782"
+          }
+        ]
+      },
+      {
+        "name":"焦作市",
+        "code":"410800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410801"
+          },
+          {
+            "name":"解放区",
+            "code":"410802"
+          },
+          {
+            "name":"中站区",
+            "code":"410803"
+          },
+          {
+            "name":"马村区",
+            "code":"410804"
+          },
+          {
+            "name":"山阳区",
+            "code":"410811"
+          },
+          {
+            "name":"修武县",
+            "code":"410821"
+          },
+          {
+            "name":"博爱县",
+            "code":"410822"
+          },
+          {
+            "name":"武陟县",
+            "code":"410823"
+          },
+          {
+            "name":"温县",
+            "code":"410825"
+          },
+          {
+            "name":"沁阳市",
+            "code":"410882"
+          },
+          {
+            "name":"孟州市",
+            "code":"410883"
+          }
+        ]
+      },
+      {
+        "name":"濮阳市",
+        "code":"410900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"410901"
+          },
+          {
+            "name":"华龙区",
+            "code":"410902"
+          },
+          {
+            "name":"清丰县",
+            "code":"410922"
+          },
+          {
+            "name":"南乐县",
+            "code":"410923"
+          },
+          {
+            "name":"范县",
+            "code":"410926"
+          },
+          {
+            "name":"台前县",
+            "code":"410927"
+          },
+          {
+            "name":"濮阳县",
+            "code":"410928"
+          }
+        ]
+      },
+      {
+        "name":"许昌市",
+        "code":"411000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411001"
+          },
+          {
+            "name":"魏都区",
+            "code":"411002"
+          },
+          {
+            "name":"许昌县",
+            "code":"411023"
+          },
+          {
+            "name":"鄢陵县",
+            "code":"411024"
+          },
+          {
+            "name":"襄城县",
+            "code":"411025"
+          },
+          {
+            "name":"禹州市",
+            "code":"411081"
+          },
+          {
+            "name":"长葛市",
+            "code":"411082"
+          }
+        ]
+      },
+      {
+        "name":"漯河市",
+        "code":"411100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411101"
+          },
+          {
+            "name":"源汇区",
+            "code":"411102"
+          },
+          {
+            "name":"郾城区",
+            "code":"411103"
+          },
+          {
+            "name":"召陵区",
+            "code":"411104"
+          },
+          {
+            "name":"舞阳县",
+            "code":"411121"
+          },
+          {
+            "name":"临颍县",
+            "code":"411122"
+          }
+        ]
+      },
+      {
+        "name":"三门峡市",
+        "code":"411200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411201"
+          },
+          {
+            "name":"湖滨区",
+            "code":"411202"
+          },
+          {
+            "name":"渑池县",
+            "code":"411221"
+          },
+          {
+            "name":"陕县",
+            "code":"411222"
+          },
+          {
+            "name":"卢氏县",
+            "code":"411224"
+          },
+          {
+            "name":"义马市",
+            "code":"411281"
+          },
+          {
+            "name":"灵宝市",
+            "code":"411282"
+          }
+        ]
+      },
+      {
+        "name":"南阳市",
+        "code":"411300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411301"
+          },
+          {
+            "name":"宛城区",
+            "code":"411302"
+          },
+          {
+            "name":"卧龙区",
+            "code":"411303"
+          },
+          {
+            "name":"南召县",
+            "code":"411321"
+          },
+          {
+            "name":"方城县",
+            "code":"411322"
+          },
+          {
+            "name":"西峡县",
+            "code":"411323"
+          },
+          {
+            "name":"镇平县",
+            "code":"411324"
+          },
+          {
+            "name":"内乡县",
+            "code":"411325"
+          },
+          {
+            "name":"淅川县",
+            "code":"411326"
+          },
+          {
+            "name":"社旗县",
+            "code":"411327"
+          },
+          {
+            "name":"唐河县",
+            "code":"411328"
+          },
+          {
+            "name":"新野县",
+            "code":"411329"
+          },
+          {
+            "name":"桐柏县",
+            "code":"411330"
+          },
+          {
+            "name":"邓州市",
+            "code":"411381"
+          }
+        ]
+      },
+      {
+        "name":"商丘市",
+        "code":"411400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411401"
+          },
+          {
+            "name":"梁园区",
+            "code":"411402"
+          },
+          {
+            "name":"睢阳区",
+            "code":"411403"
+          },
+          {
+            "name":"民权县",
+            "code":"411421"
+          },
+          {
+            "name":"睢县",
+            "code":"411422"
+          },
+          {
+            "name":"宁陵县",
+            "code":"411423"
+          },
+          {
+            "name":"柘城县",
+            "code":"411424"
+          },
+          {
+            "name":"虞城县",
+            "code":"411425"
+          },
+          {
+            "name":"夏邑县",
+            "code":"411426"
+          },
+          {
+            "name":"永城市",
+            "code":"411481"
+          }
+        ]
+      },
+      {
+        "name":"信阳市",
+        "code":"411500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411501"
+          },
+          {
+            "name":"浉河区",
+            "code":"411502"
+          },
+          {
+            "name":"平桥区",
+            "code":"411503"
+          },
+          {
+            "name":"罗山县",
+            "code":"411521"
+          },
+          {
+            "name":"光山县",
+            "code":"411522"
+          },
+          {
+            "name":"新县",
+            "code":"411523"
+          },
+          {
+            "name":"商城县",
+            "code":"411524"
+          },
+          {
+            "name":"固始县",
+            "code":"411525"
+          },
+          {
+            "name":"潢川县",
+            "code":"411526"
+          },
+          {
+            "name":"淮滨县",
+            "code":"411527"
+          },
+          {
+            "name":"息县",
+            "code":"411528"
+          }
+        ]
+      },
+      {
+        "name":"周口市",
+        "code":"411600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411601"
+          },
+          {
+            "name":"川汇区",
+            "code":"411602"
+          },
+          {
+            "name":"扶沟县",
+            "code":"411621"
+          },
+          {
+            "name":"西华县",
+            "code":"411622"
+          },
+          {
+            "name":"商水县",
+            "code":"411623"
+          },
+          {
+            "name":"沈丘县",
+            "code":"411624"
+          },
+          {
+            "name":"郸城县",
+            "code":"411625"
+          },
+          {
+            "name":"淮阳县",
+            "code":"411626"
+          },
+          {
+            "name":"太康县",
+            "code":"411627"
+          },
+          {
+            "name":"鹿邑县",
+            "code":"411628"
+          },
+          {
+            "name":"项城市",
+            "code":"411681"
+          }
+        ]
+      },
+      {
+        "name":"驻马店市",
+        "code":"411700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"411701"
+          },
+          {
+            "name":"驿城区",
+            "code":"411702"
+          },
+          {
+            "name":"西平县",
+            "code":"411721"
+          },
+          {
+            "name":"上蔡县",
+            "code":"411722"
+          },
+          {
+            "name":"平舆县",
+            "code":"411723"
+          },
+          {
+            "name":"正阳县",
+            "code":"411724"
+          },
+          {
+            "name":"确山县",
+            "code":"411725"
+          },
+          {
+            "name":"泌阳县",
+            "code":"411726"
+          },
+          {
+            "name":"汝南县",
+            "code":"411727"
+          },
+          {
+            "name":"遂平县",
+            "code":"411728"
+          },
+          {
+            "name":"新蔡县",
+            "code":"411729"
+          }
+        ]
+      },
+      {
+        "name":"济源市",
+        "code":"419001"
+      }
+    ]
+  },
+  {
+    "name":"湖北省",
+    "code":"420000",
+    "sub":[
+      {
+        "name":"武汉市",
+        "code":"420100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420101"
+          },
+          {
+            "name":"江岸区",
+            "code":"420102"
+          },
+          {
+            "name":"江汉区",
+            "code":"420103"
+          },
+          {
+            "name":"硚口区",
+            "code":"420104"
+          },
+          {
+            "name":"汉阳区",
+            "code":"420105"
+          },
+          {
+            "name":"武昌区",
+            "code":"420106"
+          },
+          {
+            "name":"青山区",
+            "code":"420107"
+          },
+          {
+            "name":"洪山区",
+            "code":"420111"
+          },
+          {
+            "name":"东西湖区",
+            "code":"420112"
+          },
+          {
+            "name":"汉南区",
+            "code":"420113"
+          },
+          {
+            "name":"蔡甸区",
+            "code":"420114"
+          },
+          {
+            "name":"江夏区",
+            "code":"420115"
+          },
+          {
+            "name":"黄陂区",
+            "code":"420116"
+          },
+          {
+            "name":"新洲区",
+            "code":"420117"
+          }
+        ]
+      },
+      {
+        "name":"黄石市",
+        "code":"420200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420201"
+          },
+          {
+            "name":"黄石港区",
+            "code":"420202"
+          },
+          {
+            "name":"西塞山区",
+            "code":"420203"
+          },
+          {
+            "name":"下陆区",
+            "code":"420204"
+          },
+          {
+            "name":"铁山区",
+            "code":"420205"
+          },
+          {
+            "name":"阳新县",
+            "code":"420222"
+          },
+          {
+            "name":"大冶市",
+            "code":"420281"
+          }
+        ]
+      },
+      {
+        "name":"十堰市",
+        "code":"420300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420301"
+          },
+          {
+            "name":"茅箭区",
+            "code":"420302"
+          },
+          {
+            "name":"张湾区",
+            "code":"420303"
+          },
+          {
+            "name":"郧阳区",
+            "code":"420304"
+          },
+          {
+            "name":"郧西县",
+            "code":"420322"
+          },
+          {
+            "name":"竹山县",
+            "code":"420323"
+          },
+          {
+            "name":"竹溪县",
+            "code":"420324"
+          },
+          {
+            "name":"房县",
+            "code":"420325"
+          },
+          {
+            "name":"丹江口市",
+            "code":"420381"
+          }
+        ]
+      },
+      {
+        "name":"宜昌市",
+        "code":"420500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420501"
+          },
+          {
+            "name":"西陵区",
+            "code":"420502"
+          },
+          {
+            "name":"伍家岗区",
+            "code":"420503"
+          },
+          {
+            "name":"点军区",
+            "code":"420504"
+          },
+          {
+            "name":"猇亭区",
+            "code":"420505"
+          },
+          {
+            "name":"夷陵区",
+            "code":"420506"
+          },
+          {
+            "name":"远安县",
+            "code":"420525"
+          },
+          {
+            "name":"兴山县",
+            "code":"420526"
+          },
+          {
+            "name":"秭归县",
+            "code":"420527"
+          },
+          {
+            "name":"长阳土家族自治县",
+            "code":"420528"
+          },
+          {
+            "name":"五峰土家族自治县",
+            "code":"420529"
+          },
+          {
+            "name":"宜都市",
+            "code":"420581"
+          },
+          {
+            "name":"当阳市",
+            "code":"420582"
+          },
+          {
+            "name":"枝江市",
+            "code":"420583"
+          }
+        ]
+      },
+      {
+        "name":"襄阳市",
+        "code":"420600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420601"
+          },
+          {
+            "name":"襄城区",
+            "code":"420602"
+          },
+          {
+            "name":"樊城区",
+            "code":"420606"
+          },
+          {
+            "name":"襄州区",
+            "code":"420607"
+          },
+          {
+            "name":"南漳县",
+            "code":"420624"
+          },
+          {
+            "name":"谷城县",
+            "code":"420625"
+          },
+          {
+            "name":"保康县",
+            "code":"420626"
+          },
+          {
+            "name":"老河口市",
+            "code":"420682"
+          },
+          {
+            "name":"枣阳市",
+            "code":"420683"
+          },
+          {
+            "name":"宜城市",
+            "code":"420684"
+          }
+        ]
+      },
+      {
+        "name":"鄂州市",
+        "code":"420700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420701"
+          },
+          {
+            "name":"梁子湖区",
+            "code":"420702"
+          },
+          {
+            "name":"华容区",
+            "code":"420703"
+          },
+          {
+            "name":"鄂城区",
+            "code":"420704"
+          }
+        ]
+      },
+      {
+        "name":"荆门市",
+        "code":"420800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420801"
+          },
+          {
+            "name":"东宝区",
+            "code":"420802"
+          },
+          {
+            "name":"掇刀区",
+            "code":"420804"
+          },
+          {
+            "name":"京山县",
+            "code":"420821"
+          },
+          {
+            "name":"沙洋县",
+            "code":"420822"
+          },
+          {
+            "name":"钟祥市",
+            "code":"420881"
+          }
+        ]
+      },
+      {
+        "name":"孝感市",
+        "code":"420900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"420901"
+          },
+          {
+            "name":"孝南区",
+            "code":"420902"
+          },
+          {
+            "name":"孝昌县",
+            "code":"420921"
+          },
+          {
+            "name":"大悟县",
+            "code":"420922"
+          },
+          {
+            "name":"云梦县",
+            "code":"420923"
+          },
+          {
+            "name":"应城市",
+            "code":"420981"
+          },
+          {
+            "name":"安陆市",
+            "code":"420982"
+          },
+          {
+            "name":"汉川市",
+            "code":"420984"
+          }
+        ]
+      },
+      {
+        "name":"荆州市",
+        "code":"421000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421001"
+          },
+          {
+            "name":"沙市区",
+            "code":"421002"
+          },
+          {
+            "name":"荆州区",
+            "code":"421003"
+          },
+          {
+            "name":"公安县",
+            "code":"421022"
+          },
+          {
+            "name":"监利县",
+            "code":"421023"
+          },
+          {
+            "name":"江陵县",
+            "code":"421024"
+          },
+          {
+            "name":"石首市",
+            "code":"421081"
+          },
+          {
+            "name":"洪湖市",
+            "code":"421083"
+          },
+          {
+            "name":"松滋市",
+            "code":"421087"
+          }
+        ]
+      },
+      {
+        "name":"黄冈市",
+        "code":"421100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421101"
+          },
+          {
+            "name":"黄州区",
+            "code":"421102"
+          },
+          {
+            "name":"团风县",
+            "code":"421121"
+          },
+          {
+            "name":"红安县",
+            "code":"421122"
+          },
+          {
+            "name":"罗田县",
+            "code":"421123"
+          },
+          {
+            "name":"英山县",
+            "code":"421124"
+          },
+          {
+            "name":"浠水县",
+            "code":"421125"
+          },
+          {
+            "name":"蕲春县",
+            "code":"421126"
+          },
+          {
+            "name":"黄梅县",
+            "code":"421127"
+          },
+          {
+            "name":"麻城市",
+            "code":"421181"
+          },
+          {
+            "name":"武穴市",
+            "code":"421182"
+          }
+        ]
+      },
+      {
+        "name":"咸宁市",
+        "code":"421200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421201"
+          },
+          {
+            "name":"咸安区",
+            "code":"421202"
+          },
+          {
+            "name":"嘉鱼县",
+            "code":"421221"
+          },
+          {
+            "name":"通城县",
+            "code":"421222"
+          },
+          {
+            "name":"崇阳县",
+            "code":"421223"
+          },
+          {
+            "name":"通山县",
+            "code":"421224"
+          },
+          {
+            "name":"赤壁市",
+            "code":"421281"
+          }
+        ]
+      },
+      {
+        "name":"随州市",
+        "code":"421300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"421301"
+          },
+          {
+            "name":"曾都区",
+            "code":"421303"
+          },
+          {
+            "name":"随县",
+            "code":"421321"
+          },
+          {
+            "name":"广水市",
+            "code":"421381"
+          }
+        ]
+      },
+      {
+        "name":"恩施土家族苗族自治州",
+        "code":"422800",
+        "sub":[
+          {
+            "name":"恩施市",
+            "code":"422801"
+          },
+          {
+            "name":"利川市",
+            "code":"422802"
+          },
+          {
+            "name":"建始县",
+            "code":"422822"
+          },
+          {
+            "name":"巴东县",
+            "code":"422823"
+          },
+          {
+            "name":"宣恩县",
+            "code":"422825"
+          },
+          {
+            "name":"咸丰县",
+            "code":"422826"
+          },
+          {
+            "name":"来凤县",
+            "code":"422827"
+          },
+          {
+            "name":"鹤峰县",
+            "code":"422828"
+          }
+        ]
+      },
+      {
+        "name":"仙桃市",
+        "code":"429004"
+      },
+      {
+        "name":"潜江市",
+        "code":"429005"
+      },
+      {
+        "name":"天门市",
+        "code":"429006"
+      },
+      {
+        "name":"神农架林区",
+        "code":"429021"
+      }
+    ]
+  },
+  {
+    "name":"湖南省",
+    "code":"430000",
+    "sub":[
+      {
+        "name":"长沙市",
+        "code":"430100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430101"
+          },
+          {
+            "name":"芙蓉区",
+            "code":"430102"
+          },
+          {
+            "name":"天心区",
+            "code":"430103"
+          },
+          {
+            "name":"岳麓区",
+            "code":"430104"
+          },
+          {
+            "name":"开福区",
+            "code":"430105"
+          },
+          {
+            "name":"雨花区",
+            "code":"430111"
+          },
+          {
+            "name":"望城区",
+            "code":"430112"
+          },
+          {
+            "name":"长沙县",
+            "code":"430121"
+          },
+          {
+            "name":"宁乡县",
+            "code":"430124"
+          },
+          {
+            "name":"浏阳市",
+            "code":"430181"
+          }
+        ]
+      },
+      {
+        "name":"株洲市",
+        "code":"430200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430201"
+          },
+          {
+            "name":"荷塘区",
+            "code":"430202"
+          },
+          {
+            "name":"芦淞区",
+            "code":"430203"
+          },
+          {
+            "name":"石峰区",
+            "code":"430204"
+          },
+          {
+            "name":"天元区",
+            "code":"430211"
+          },
+          {
+            "name":"株洲县",
+            "code":"430221"
+          },
+          {
+            "name":"攸县",
+            "code":"430223"
+          },
+          {
+            "name":"茶陵县",
+            "code":"430224"
+          },
+          {
+            "name":"炎陵县",
+            "code":"430225"
+          },
+          {
+            "name":"醴陵市",
+            "code":"430281"
+          }
+        ]
+      },
+      {
+        "name":"湘潭市",
+        "code":"430300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430301"
+          },
+          {
+            "name":"雨湖区",
+            "code":"430302"
+          },
+          {
+            "name":"岳塘区",
+            "code":"430304"
+          },
+          {
+            "name":"湘潭县",
+            "code":"430321"
+          },
+          {
+            "name":"湘乡市",
+            "code":"430381"
+          },
+          {
+            "name":"韶山市",
+            "code":"430382"
+          }
+        ]
+      },
+      {
+        "name":"衡阳市",
+        "code":"430400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430401"
+          },
+          {
+            "name":"珠晖区",
+            "code":"430405"
+          },
+          {
+            "name":"雁峰区",
+            "code":"430406"
+          },
+          {
+            "name":"石鼓区",
+            "code":"430407"
+          },
+          {
+            "name":"蒸湘区",
+            "code":"430408"
+          },
+          {
+            "name":"南岳区",
+            "code":"430412"
+          },
+          {
+            "name":"衡阳县",
+            "code":"430421"
+          },
+          {
+            "name":"衡南县",
+            "code":"430422"
+          },
+          {
+            "name":"衡山县",
+            "code":"430423"
+          },
+          {
+            "name":"衡东县",
+            "code":"430424"
+          },
+          {
+            "name":"祁东县",
+            "code":"430426"
+          },
+          {
+            "name":"耒阳市",
+            "code":"430481"
+          },
+          {
+            "name":"常宁市",
+            "code":"430482"
+          }
+        ]
+      },
+      {
+        "name":"邵阳市",
+        "code":"430500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430501"
+          },
+          {
+            "name":"双清区",
+            "code":"430502"
+          },
+          {
+            "name":"大祥区",
+            "code":"430503"
+          },
+          {
+            "name":"北塔区",
+            "code":"430511"
+          },
+          {
+            "name":"邵东县",
+            "code":"430521"
+          },
+          {
+            "name":"新邵县",
+            "code":"430522"
+          },
+          {
+            "name":"邵阳县",
+            "code":"430523"
+          },
+          {
+            "name":"隆回县",
+            "code":"430524"
+          },
+          {
+            "name":"洞口县",
+            "code":"430525"
+          },
+          {
+            "name":"绥宁县",
+            "code":"430527"
+          },
+          {
+            "name":"新宁县",
+            "code":"430528"
+          },
+          {
+            "name":"城步苗族自治县",
+            "code":"430529"
+          },
+          {
+            "name":"武冈市",
+            "code":"430581"
+          }
+        ]
+      },
+      {
+        "name":"岳阳市",
+        "code":"430600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430601"
+          },
+          {
+            "name":"岳阳楼区",
+            "code":"430602"
+          },
+          {
+            "name":"云溪区",
+            "code":"430603"
+          },
+          {
+            "name":"君山区",
+            "code":"430611"
+          },
+          {
+            "name":"岳阳县",
+            "code":"430621"
+          },
+          {
+            "name":"华容县",
+            "code":"430623"
+          },
+          {
+            "name":"湘阴县",
+            "code":"430624"
+          },
+          {
+            "name":"平江县",
+            "code":"430626"
+          },
+          {
+            "name":"汨罗市",
+            "code":"430681"
+          },
+          {
+            "name":"临湘市",
+            "code":"430682"
+          }
+        ]
+      },
+      {
+        "name":"常德市",
+        "code":"430700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430701"
+          },
+          {
+            "name":"武陵区",
+            "code":"430702"
+          },
+          {
+            "name":"鼎城区",
+            "code":"430703"
+          },
+          {
+            "name":"安乡县",
+            "code":"430721"
+          },
+          {
+            "name":"汉寿县",
+            "code":"430722"
+          },
+          {
+            "name":"澧县",
+            "code":"430723"
+          },
+          {
+            "name":"临澧县",
+            "code":"430724"
+          },
+          {
+            "name":"桃源县",
+            "code":"430725"
+          },
+          {
+            "name":"石门县",
+            "code":"430726"
+          },
+          {
+            "name":"津市市",
+            "code":"430781"
+          }
+        ]
+      },
+      {
+        "name":"张家界市",
+        "code":"430800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430801"
+          },
+          {
+            "name":"永定区",
+            "code":"430802"
+          },
+          {
+            "name":"武陵源区",
+            "code":"430811"
+          },
+          {
+            "name":"慈利县",
+            "code":"430821"
+          },
+          {
+            "name":"桑植县",
+            "code":"430822"
+          }
+        ]
+      },
+      {
+        "name":"益阳市",
+        "code":"430900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"430901"
+          },
+          {
+            "name":"资阳区",
+            "code":"430902"
+          },
+          {
+            "name":"赫山区",
+            "code":"430903"
+          },
+          {
+            "name":"南县",
+            "code":"430921"
+          },
+          {
+            "name":"桃江县",
+            "code":"430922"
+          },
+          {
+            "name":"安化县",
+            "code":"430923"
+          },
+          {
+            "name":"沅江市",
+            "code":"430981"
+          }
+        ]
+      },
+      {
+        "name":"郴州市",
+        "code":"431000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431001"
+          },
+          {
+            "name":"北湖区",
+            "code":"431002"
+          },
+          {
+            "name":"苏仙区",
+            "code":"431003"
+          },
+          {
+            "name":"桂阳县",
+            "code":"431021"
+          },
+          {
+            "name":"宜章县",
+            "code":"431022"
+          },
+          {
+            "name":"永兴县",
+            "code":"431023"
+          },
+          {
+            "name":"嘉禾县",
+            "code":"431024"
+          },
+          {
+            "name":"临武县",
+            "code":"431025"
+          },
+          {
+            "name":"汝城县",
+            "code":"431026"
+          },
+          {
+            "name":"桂东县",
+            "code":"431027"
+          },
+          {
+            "name":"安仁县",
+            "code":"431028"
+          },
+          {
+            "name":"资兴市",
+            "code":"431081"
+          }
+        ]
+      },
+      {
+        "name":"永州市",
+        "code":"431100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431101"
+          },
+          {
+            "name":"零陵区",
+            "code":"431102"
+          },
+          {
+            "name":"冷水滩区",
+            "code":"431103"
+          },
+          {
+            "name":"祁阳县",
+            "code":"431121"
+          },
+          {
+            "name":"东安县",
+            "code":"431122"
+          },
+          {
+            "name":"双牌县",
+            "code":"431123"
+          },
+          {
+            "name":"道县",
+            "code":"431124"
+          },
+          {
+            "name":"江永县",
+            "code":"431125"
+          },
+          {
+            "name":"宁远县",
+            "code":"431126"
+          },
+          {
+            "name":"蓝山县",
+            "code":"431127"
+          },
+          {
+            "name":"新田县",
+            "code":"431128"
+          },
+          {
+            "name":"江华瑶族自治县",
+            "code":"431129"
+          }
+        ]
+      },
+      {
+        "name":"怀化市",
+        "code":"431200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431201"
+          },
+          {
+            "name":"鹤城区",
+            "code":"431202"
+          },
+          {
+            "name":"中方县",
+            "code":"431221"
+          },
+          {
+            "name":"沅陵县",
+            "code":"431222"
+          },
+          {
+            "name":"辰溪县",
+            "code":"431223"
+          },
+          {
+            "name":"溆浦县",
+            "code":"431224"
+          },
+          {
+            "name":"会同县",
+            "code":"431225"
+          },
+          {
+            "name":"麻阳苗族自治县",
+            "code":"431226"
+          },
+          {
+            "name":"新晃侗族自治县",
+            "code":"431227"
+          },
+          {
+            "name":"芷江侗族自治县",
+            "code":"431228"
+          },
+          {
+            "name":"靖州苗族侗族自治县",
+            "code":"431229"
+          },
+          {
+            "name":"通道侗族自治县",
+            "code":"431230"
+          },
+          {
+            "name":"洪江市",
+            "code":"431281"
+          }
+        ]
+      },
+      {
+        "name":"娄底市",
+        "code":"431300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"431301"
+          },
+          {
+            "name":"娄星区",
+            "code":"431302"
+          },
+          {
+            "name":"双峰县",
+            "code":"431321"
+          },
+          {
+            "name":"新化县",
+            "code":"431322"
+          },
+          {
+            "name":"冷水江市",
+            "code":"431381"
+          },
+          {
+            "name":"涟源市",
+            "code":"431382"
+          }
+        ]
+      },
+      {
+        "name":"湘西土家族苗族自治州",
+        "code":"433100",
+        "sub":[
+          {
+            "name":"吉首市",
+            "code":"433101"
+          },
+          {
+            "name":"泸溪县",
+            "code":"433122"
+          },
+          {
+            "name":"凤凰县",
+            "code":"433123"
+          },
+          {
+            "name":"花垣县",
+            "code":"433124"
+          },
+          {
+            "name":"保靖县",
+            "code":"433125"
+          },
+          {
+            "name":"古丈县",
+            "code":"433126"
+          },
+          {
+            "name":"永顺县",
+            "code":"433127"
+          },
+          {
+            "name":"龙山县",
+            "code":"433130"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"广东省",
+    "code":"440000",
+    "sub":[
+      {
+        "name":"广州市",
+        "code":"440100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440101"
+          },
+          {
+            "name":"荔湾区",
+            "code":"440103"
+          },
+          {
+            "name":"越秀区",
+            "code":"440104"
+          },
+          {
+            "name":"海珠区",
+            "code":"440105"
+          },
+          {
+            "name":"天河区",
+            "code":"440106"
+          },
+          {
+            "name":"白云区",
+            "code":"440111"
+          },
+          {
+            "name":"黄埔区",
+            "code":"440112"
+          },
+          {
+            "name":"番禺区",
+            "code":"440113"
+          },
+          {
+            "name":"花都区",
+            "code":"440114"
+          },
+          {
+            "name":"南沙区",
+            "code":"440115"
+          },
+          {
+            "name":"从化区",
+            "code":"440117"
+          },
+          {
+            "name":"增城区",
+            "code":"440118"
+          }
+        ]
+      },
+      {
+        "name":"韶关市",
+        "code":"440200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440201"
+          },
+          {
+            "name":"武江区",
+            "code":"440203"
+          },
+          {
+            "name":"浈江区",
+            "code":"440204"
+          },
+          {
+            "name":"曲江区",
+            "code":"440205"
+          },
+          {
+            "name":"始兴县",
+            "code":"440222"
+          },
+          {
+            "name":"仁化县",
+            "code":"440224"
+          },
+          {
+            "name":"翁源县",
+            "code":"440229"
+          },
+          {
+            "name":"乳源瑶族自治县",
+            "code":"440232"
+          },
+          {
+            "name":"新丰县",
+            "code":"440233"
+          },
+          {
+            "name":"乐昌市",
+            "code":"440281"
+          },
+          {
+            "name":"南雄市",
+            "code":"440282"
+          }
+        ]
+      },
+      {
+        "name":"深圳市",
+        "code":"440300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440301"
+          },
+          {
+            "name":"罗湖区",
+            "code":"440303"
+          },
+          {
+            "name":"福田区",
+            "code":"440304"
+          },
+          {
+            "name":"南山区",
+            "code":"440305"
+          },
+          {
+            "name":"宝安区",
+            "code":"440306"
+          },
+          {
+            "name":"龙岗区",
+            "code":"440307"
+          },
+          {
+            "name":"盐田区",
+            "code":"440308"
+          }
+        ]
+      },
+      {
+        "name":"珠海市",
+        "code":"440400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440401"
+          },
+          {
+            "name":"香洲区",
+            "code":"440402"
+          },
+          {
+            "name":"斗门区",
+            "code":"440403"
+          },
+          {
+            "name":"金湾区",
+            "code":"440404"
+          }
+        ]
+      },
+      {
+        "name":"汕头市",
+        "code":"440500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440501"
+          },
+          {
+            "name":"龙湖区",
+            "code":"440507"
+          },
+          {
+            "name":"金平区",
+            "code":"440511"
+          },
+          {
+            "name":"濠江区",
+            "code":"440512"
+          },
+          {
+            "name":"潮阳区",
+            "code":"440513"
+          },
+          {
+            "name":"潮南区",
+            "code":"440514"
+          },
+          {
+            "name":"澄海区",
+            "code":"440515"
+          },
+          {
+            "name":"南澳县",
+            "code":"440523"
+          }
+        ]
+      },
+      {
+        "name":"佛山市",
+        "code":"440600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440601"
+          },
+          {
+            "name":"禅城区",
+            "code":"440604"
+          },
+          {
+            "name":"南海区",
+            "code":"440605"
+          },
+          {
+            "name":"顺德区",
+            "code":"440606"
+          },
+          {
+            "name":"三水区",
+            "code":"440607"
+          },
+          {
+            "name":"高明区",
+            "code":"440608"
+          }
+        ]
+      },
+      {
+        "name":"江门市",
+        "code":"440700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440701"
+          },
+          {
+            "name":"蓬江区",
+            "code":"440703"
+          },
+          {
+            "name":"江海区",
+            "code":"440704"
+          },
+          {
+            "name":"新会区",
+            "code":"440705"
+          },
+          {
+            "name":"台山市",
+            "code":"440781"
+          },
+          {
+            "name":"开平市",
+            "code":"440783"
+          },
+          {
+            "name":"鹤山市",
+            "code":"440784"
+          },
+          {
+            "name":"恩平市",
+            "code":"440785"
+          }
+        ]
+      },
+      {
+        "name":"湛江市",
+        "code":"440800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440801"
+          },
+          {
+            "name":"赤坎区",
+            "code":"440802"
+          },
+          {
+            "name":"霞山区",
+            "code":"440803"
+          },
+          {
+            "name":"坡头区",
+            "code":"440804"
+          },
+          {
+            "name":"麻章区",
+            "code":"440811"
+          },
+          {
+            "name":"遂溪县",
+            "code":"440823"
+          },
+          {
+            "name":"徐闻县",
+            "code":"440825"
+          },
+          {
+            "name":"廉江市",
+            "code":"440881"
+          },
+          {
+            "name":"雷州市",
+            "code":"440882"
+          },
+          {
+            "name":"吴川市",
+            "code":"440883"
+          }
+        ]
+      },
+      {
+        "name":"茂名市",
+        "code":"440900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"440901"
+          },
+          {
+            "name":"茂南区",
+            "code":"440902"
+          },
+          {
+            "name":"电白区",
+            "code":"440904"
+          },
+          {
+            "name":"高州市",
+            "code":"440981"
+          },
+          {
+            "name":"化州市",
+            "code":"440982"
+          },
+          {
+            "name":"信宜市",
+            "code":"440983"
+          }
+        ]
+      },
+      {
+        "name":"肇庆市",
+        "code":"441200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441201"
+          },
+          {
+            "name":"端州区",
+            "code":"441202"
+          },
+          {
+            "name":"鼎湖区",
+            "code":"441203"
+          },
+          {
+            "name":"广宁县",
+            "code":"441223"
+          },
+          {
+            "name":"怀集县",
+            "code":"441224"
+          },
+          {
+            "name":"封开县",
+            "code":"441225"
+          },
+          {
+            "name":"德庆县",
+            "code":"441226"
+          },
+          {
+            "name":"高要市",
+            "code":"441283"
+          },
+          {
+            "name":"四会市",
+            "code":"441284"
+          }
+        ]
+      },
+      {
+        "name":"惠州市",
+        "code":"441300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441301"
+          },
+          {
+            "name":"惠城区",
+            "code":"441302"
+          },
+          {
+            "name":"惠阳区",
+            "code":"441303"
+          },
+          {
+            "name":"博罗县",
+            "code":"441322"
+          },
+          {
+            "name":"惠东县",
+            "code":"441323"
+          },
+          {
+            "name":"龙门县",
+            "code":"441324"
+          }
+        ]
+      },
+      {
+        "name":"梅州市",
+        "code":"441400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441401"
+          },
+          {
+            "name":"梅江区",
+            "code":"441402"
+          },
+          {
+            "name":"梅县区",
+            "code":"441403"
+          },
+          {
+            "name":"大埔县",
+            "code":"441422"
+          },
+          {
+            "name":"丰顺县",
+            "code":"441423"
+          },
+          {
+            "name":"五华县",
+            "code":"441424"
+          },
+          {
+            "name":"平远县",
+            "code":"441426"
+          },
+          {
+            "name":"蕉岭县",
+            "code":"441427"
+          },
+          {
+            "name":"兴宁市",
+            "code":"441481"
+          }
+        ]
+      },
+      {
+        "name":"汕尾市",
+        "code":"441500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441501"
+          },
+          {
+            "name":"城区",
+            "code":"441502"
+          },
+          {
+            "name":"海丰县",
+            "code":"441521"
+          },
+          {
+            "name":"陆河县",
+            "code":"441523"
+          },
+          {
+            "name":"陆丰市",
+            "code":"441581"
+          }
+        ]
+      },
+      {
+        "name":"河源市",
+        "code":"441600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441601"
+          },
+          {
+            "name":"源城区",
+            "code":"441602"
+          },
+          {
+            "name":"紫金县",
+            "code":"441621"
+          },
+          {
+            "name":"龙川县",
+            "code":"441622"
+          },
+          {
+            "name":"连平县",
+            "code":"441623"
+          },
+          {
+            "name":"和平县",
+            "code":"441624"
+          },
+          {
+            "name":"东源县",
+            "code":"441625"
+          }
+        ]
+      },
+      {
+        "name":"阳江市",
+        "code":"441700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441701"
+          },
+          {
+            "name":"江城区",
+            "code":"441702"
+          },
+          {
+            "name":"阳东区",
+            "code":"441704"
+          },
+          {
+            "name":"阳西县",
+            "code":"441721"
+          },
+          {
+            "name":"阳春市",
+            "code":"441781"
+          }
+        ]
+      },
+      {
+        "name":"清远市",
+        "code":"441800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"441801"
+          },
+          {
+            "name":"清城区",
+            "code":"441802"
+          },
+          {
+            "name":"清新区",
+            "code":"441803"
+          },
+          {
+            "name":"佛冈县",
+            "code":"441821"
+          },
+          {
+            "name":"阳山县",
+            "code":"441823"
+          },
+          {
+            "name":"连山壮族瑶族自治县",
+            "code":"441825"
+          },
+          {
+            "name":"连南瑶族自治县",
+            "code":"441826"
+          },
+          {
+            "name":"英德市",
+            "code":"441881"
+          },
+          {
+            "name":"连州市",
+            "code":"441882"
+          }
+        ]
+      },
+      {
+        "name":"东莞市",
+        "code":"441900",
+        "sub":[
+
+        ]
+      },
+      {
+        "name":"中山市",
+        "code":"442000",
+        "sub":[
+
+        ]
+      },
+      {
+        "name":"潮州市",
+        "code":"445100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445101"
+          },
+          {
+            "name":"湘桥区",
+            "code":"445102"
+          },
+          {
+            "name":"潮安区",
+            "code":"445103"
+          },
+          {
+            "name":"饶平县",
+            "code":"445122"
+          }
+        ]
+      },
+      {
+        "name":"揭阳市",
+        "code":"445200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445201"
+          },
+          {
+            "name":"榕城区",
+            "code":"445202"
+          },
+          {
+            "name":"揭东区",
+            "code":"445203"
+          },
+          {
+            "name":"揭西县",
+            "code":"445222"
+          },
+          {
+            "name":"惠来县",
+            "code":"445224"
+          },
+          {
+            "name":"普宁市",
+            "code":"445281"
+          }
+        ]
+      },
+      {
+        "name":"云浮市",
+        "code":"445300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"445301"
+          },
+          {
+            "name":"云城区",
+            "code":"445302"
+          },
+          {
+            "name":"云安区",
+            "code":"445303"
+          },
+          {
+            "name":"新兴县",
+            "code":"445321"
+          },
+          {
+            "name":"郁南县",
+            "code":"445322"
+          },
+          {
+            "name":"罗定市",
+            "code":"445381"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"广西壮族自治区",
+    "code":"450000",
+    "sub":[
+      {
+        "name":"南宁市",
+        "code":"450100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450101"
+          },
+          {
+            "name":"兴宁区",
+            "code":"450102"
+          },
+          {
+            "name":"青秀区",
+            "code":"450103"
+          },
+          {
+            "name":"江南区",
+            "code":"450105"
+          },
+          {
+            "name":"西乡塘区",
+            "code":"450107"
+          },
+          {
+            "name":"良庆区",
+            "code":"450108"
+          },
+          {
+            "name":"邕宁区",
+            "code":"450109"
+          },
+          {
+            "name":"武鸣县",
+            "code":"450122"
+          },
+          {
+            "name":"隆安县",
+            "code":"450123"
+          },
+          {
+            "name":"马山县",
+            "code":"450124"
+          },
+          {
+            "name":"上林县",
+            "code":"450125"
+          },
+          {
+            "name":"宾阳县",
+            "code":"450126"
+          },
+          {
+            "name":"横县",
+            "code":"450127"
+          }
+        ]
+      },
+      {
+        "name":"柳州市",
+        "code":"450200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450201"
+          },
+          {
+            "name":"城中区",
+            "code":"450202"
+          },
+          {
+            "name":"鱼峰区",
+            "code":"450203"
+          },
+          {
+            "name":"柳南区",
+            "code":"450204"
+          },
+          {
+            "name":"柳北区",
+            "code":"450205"
+          },
+          {
+            "name":"柳江县",
+            "code":"450221"
+          },
+          {
+            "name":"柳城县",
+            "code":"450222"
+          },
+          {
+            "name":"鹿寨县",
+            "code":"450223"
+          },
+          {
+            "name":"融安县",
+            "code":"450224"
+          },
+          {
+            "name":"融水苗族自治县",
+            "code":"450225"
+          },
+          {
+            "name":"三江侗族自治县",
+            "code":"450226"
+          }
+        ]
+      },
+      {
+        "name":"桂林市",
+        "code":"450300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450301"
+          },
+          {
+            "name":"秀峰区",
+            "code":"450302"
+          },
+          {
+            "name":"叠彩区",
+            "code":"450303"
+          },
+          {
+            "name":"象山区",
+            "code":"450304"
+          },
+          {
+            "name":"七星区",
+            "code":"450305"
+          },
+          {
+            "name":"雁山区",
+            "code":"450311"
+          },
+          {
+            "name":"临桂区",
+            "code":"450312"
+          },
+          {
+            "name":"阳朔县",
+            "code":"450321"
+          },
+          {
+            "name":"灵川县",
+            "code":"450323"
+          },
+          {
+            "name":"全州县",
+            "code":"450324"
+          },
+          {
+            "name":"兴安县",
+            "code":"450325"
+          },
+          {
+            "name":"永福县",
+            "code":"450326"
+          },
+          {
+            "name":"灌阳县",
+            "code":"450327"
+          },
+          {
+            "name":"龙胜各族自治县",
+            "code":"450328"
+          },
+          {
+            "name":"资源县",
+            "code":"450329"
+          },
+          {
+            "name":"平乐县",
+            "code":"450330"
+          },
+          {
+            "name":"荔浦县",
+            "code":"450331"
+          },
+          {
+            "name":"恭城瑶族自治县",
+            "code":"450332"
+          }
+        ]
+      },
+      {
+        "name":"梧州市",
+        "code":"450400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450401"
+          },
+          {
+            "name":"万秀区",
+            "code":"450403"
+          },
+          {
+            "name":"长洲区",
+            "code":"450405"
+          },
+          {
+            "name":"龙圩区",
+            "code":"450406"
+          },
+          {
+            "name":"苍梧县",
+            "code":"450421"
+          },
+          {
+            "name":"藤县",
+            "code":"450422"
+          },
+          {
+            "name":"蒙山县",
+            "code":"450423"
+          },
+          {
+            "name":"岑溪市",
+            "code":"450481"
+          }
+        ]
+      },
+      {
+        "name":"北海市",
+        "code":"450500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450501"
+          },
+          {
+            "name":"海城区",
+            "code":"450502"
+          },
+          {
+            "name":"银海区",
+            "code":"450503"
+          },
+          {
+            "name":"铁山港区",
+            "code":"450512"
+          },
+          {
+            "name":"合浦县",
+            "code":"450521"
+          }
+        ]
+      },
+      {
+        "name":"防城港市",
+        "code":"450600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450601"
+          },
+          {
+            "name":"港口区",
+            "code":"450602"
+          },
+          {
+            "name":"防城区",
+            "code":"450603"
+          },
+          {
+            "name":"上思县",
+            "code":"450621"
+          },
+          {
+            "name":"东兴市",
+            "code":"450681"
+          }
+        ]
+      },
+      {
+        "name":"钦州市",
+        "code":"450700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450701"
+          },
+          {
+            "name":"钦南区",
+            "code":"450702"
+          },
+          {
+            "name":"钦北区",
+            "code":"450703"
+          },
+          {
+            "name":"灵山县",
+            "code":"450721"
+          },
+          {
+            "name":"浦北县",
+            "code":"450722"
+          }
+        ]
+      },
+      {
+        "name":"贵港市",
+        "code":"450800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450801"
+          },
+          {
+            "name":"港北区",
+            "code":"450802"
+          },
+          {
+            "name":"港南区",
+            "code":"450803"
+          },
+          {
+            "name":"覃塘区",
+            "code":"450804"
+          },
+          {
+            "name":"平南县",
+            "code":"450821"
+          },
+          {
+            "name":"桂平市",
+            "code":"450881"
+          }
+        ]
+      },
+      {
+        "name":"玉林市",
+        "code":"450900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"450901"
+          },
+          {
+            "name":"玉州区",
+            "code":"450902"
+          },
+          {
+            "name":"福绵区",
+            "code":"450903"
+          },
+          {
+            "name":"容县",
+            "code":"450921"
+          },
+          {
+            "name":"陆川县",
+            "code":"450922"
+          },
+          {
+            "name":"博白县",
+            "code":"450923"
+          },
+          {
+            "name":"兴业县",
+            "code":"450924"
+          },
+          {
+            "name":"北流市",
+            "code":"450981"
+          }
+        ]
+      },
+      {
+        "name":"百色市",
+        "code":"451000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451001"
+          },
+          {
+            "name":"右江区",
+            "code":"451002"
+          },
+          {
+            "name":"田阳县",
+            "code":"451021"
+          },
+          {
+            "name":"田东县",
+            "code":"451022"
+          },
+          {
+            "name":"平果县",
+            "code":"451023"
+          },
+          {
+            "name":"德保县",
+            "code":"451024"
+          },
+          {
+            "name":"靖西县",
+            "code":"451025"
+          },
+          {
+            "name":"那坡县",
+            "code":"451026"
+          },
+          {
+            "name":"凌云县",
+            "code":"451027"
+          },
+          {
+            "name":"乐业县",
+            "code":"451028"
+          },
+          {
+            "name":"田林县",
+            "code":"451029"
+          },
+          {
+            "name":"西林县",
+            "code":"451030"
+          },
+          {
+            "name":"隆林各族自治县",
+            "code":"451031"
+          }
+        ]
+      },
+      {
+        "name":"贺州市",
+        "code":"451100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451101"
+          },
+          {
+            "name":"八步区",
+            "code":"451102"
+          },
+          {
+            "name":"平桂管理区",
+            "code":"451119"
+          },
+          {
+            "name":"昭平县",
+            "code":"451121"
+          },
+          {
+            "name":"钟山县",
+            "code":"451122"
+          },
+          {
+            "name":"富川瑶族自治县",
+            "code":"451123"
+          }
+        ]
+      },
+      {
+        "name":"河池市",
+        "code":"451200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451201"
+          },
+          {
+            "name":"金城江区",
+            "code":"451202"
+          },
+          {
+            "name":"南丹县",
+            "code":"451221"
+          },
+          {
+            "name":"天峨县",
+            "code":"451222"
+          },
+          {
+            "name":"凤山县",
+            "code":"451223"
+          },
+          {
+            "name":"东兰县",
+            "code":"451224"
+          },
+          {
+            "name":"罗城仫佬族自治县",
+            "code":"451225"
+          },
+          {
+            "name":"环江毛南族自治县",
+            "code":"451226"
+          },
+          {
+            "name":"巴马瑶族自治县",
+            "code":"451227"
+          },
+          {
+            "name":"都安瑶族自治县",
+            "code":"451228"
+          },
+          {
+            "name":"大化瑶族自治县",
+            "code":"451229"
+          },
+          {
+            "name":"宜州市",
+            "code":"451281"
+          }
+        ]
+      },
+      {
+        "name":"来宾市",
+        "code":"451300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451301"
+          },
+          {
+            "name":"兴宾区",
+            "code":"451302"
+          },
+          {
+            "name":"忻城县",
+            "code":"451321"
+          },
+          {
+            "name":"象州县",
+            "code":"451322"
+          },
+          {
+            "name":"武宣县",
+            "code":"451323"
+          },
+          {
+            "name":"金秀瑶族自治县",
+            "code":"451324"
+          },
+          {
+            "name":"合山市",
+            "code":"451381"
+          }
+        ]
+      },
+      {
+        "name":"崇左市",
+        "code":"451400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"451401"
+          },
+          {
+            "name":"江州区",
+            "code":"451402"
+          },
+          {
+            "name":"扶绥县",
+            "code":"451421"
+          },
+          {
+            "name":"宁明县",
+            "code":"451422"
+          },
+          {
+            "name":"龙州县",
+            "code":"451423"
+          },
+          {
+            "name":"大新县",
+            "code":"451424"
+          },
+          {
+            "name":"天等县",
+            "code":"451425"
+          },
+          {
+            "name":"凭祥市",
+            "code":"451481"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"海南省",
+    "code":"460000",
+    "sub":[
+      {
+        "name":"海口市",
+        "code":"460100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"460101"
+          },
+          {
+            "name":"秀英区",
+            "code":"460105"
+          },
+          {
+            "name":"龙华区",
+            "code":"460106"
+          },
+          {
+            "name":"琼山区",
+            "code":"460107"
+          },
+          {
+            "name":"美兰区",
+            "code":"460108"
+          }
+        ]
+      },
+      {
+        "name":"三亚市",
+        "code":"460200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"460201"
+          },
+          {
+            "name":"海棠区",
+            "code":"460202"
+          },
+          {
+            "name":"吉阳区",
+            "code":"460203"
+          },
+          {
+            "name":"天涯区",
+            "code":"460204"
+          },
+          {
+            "name":"崖州区",
+            "code":"460205"
+          }
+        ]
+      },
+      {
+        "name":"三沙市",
+        "code":"460300",
+        "sub":[
+          {
+            "name":"西沙群岛",
+            "code":"460321"
+          },
+          {
+            "name":"南沙群岛",
+            "code":"460322"
+          },
+          {
+            "name":"中沙群岛的岛礁及其海域",
+            "code":"460323"
+          }
+        ]
+      },
+      {
+        "name":"五指山市",
+        "code":"469001"
+      },
+      {
+        "name":"琼海市",
+        "code":"469002"
+      },
+      {
+        "name":"儋州市",
+        "code":"469003"
+      },
+      {
+        "name":"文昌市",
+        "code":"469005"
+      },
+      {
+        "name":"万宁市",
+        "code":"469006"
+      },
+      {
+        "name":"东方市",
+        "code":"469007"
+      },
+      {
+        "name":"定安县",
+        "code":"469021"
+      },
+      {
+        "name":"屯昌县",
+        "code":"469022"
+      },
+      {
+        "name":"澄迈县",
+        "code":"469023"
+      },
+      {
+        "name":"临高县",
+        "code":"469024"
+      },
+      {
+        "name":"白沙黎族自治县",
+        "code":"469025"
+      },
+      {
+        "name":"昌江黎族自治县",
+        "code":"469026"
+      },
+      {
+        "name":"乐东黎族自治县",
+        "code":"469027"
+      },
+      {
+        "name":"陵水黎族自治县",
+        "code":"469028"
+      },
+      {
+        "name":"保亭黎族苗族自治县",
+        "code":"469029"
+      },
+      {
+        "name":"琼中黎族苗族自治县",
+        "code":"469030"
+      }
+    ]
+  },
+  {
+    "name":"重庆",
+    "code":"500000",
+    "sub": [
+      {
+        "name": "重庆市",
+        "code": "500000",
+        "sub":[
+            {
+              "name":"万州区",
+              "code":"500101"
+            },
+            {
+              "name":"涪陵区",
+              "code":"500102"
+            },
+            {
+              "name":"渝中区",
+              "code":"500103"
+            },
+            {
+              "name":"大渡口区",
+              "code":"500104"
+            },
+            {
+              "name":"江北区",
+              "code":"500105"
+            },
+            {
+              "name":"沙坪坝区",
+              "code":"500106"
+            },
+            {
+              "name":"九龙坡区",
+              "code":"500107"
+            },
+            {
+              "name":"南岸区",
+              "code":"500108"
+            },
+            {
+              "name":"北碚区",
+              "code":"500109"
+            },
+            {
+              "name":"綦江区",
+              "code":"500110"
+            },
+            {
+              "name":"大足区",
+              "code":"500111"
+            },
+            {
+              "name":"渝北区",
+              "code":"500112"
+            },
+            {
+              "name":"巴南区",
+              "code":"500113"
+            },
+            {
+              "name":"黔江区",
+              "code":"500114"
+            },
+            {
+              "name":"长寿区",
+              "code":"500115"
+            },
+            {
+              "name":"江津区",
+              "code":"500116"
+            },
+            {
+              "name":"合川区",
+              "code":"500117"
+            },
+            {
+              "name":"永川区",
+              "code":"500118"
+            },
+            {
+              "name":"南川区",
+              "code":"500119"
+            },
+            {
+              "name":"璧山区",
+              "code":"500120"
+            },
+            {
+              "name":"铜梁区",
+              "code":"500151"
+            },
+            {
+              "name":"潼南县",
+              "code":"500223"
+            },
+            {
+              "name":"荣昌县",
+              "code":"500226"
+            },
+            {
+              "name":"梁平县",
+              "code":"500228"
+            },
+            {
+              "name":"城口县",
+              "code":"500229"
+            },
+            {
+              "name":"丰都县",
+              "code":"500230"
+            },
+            {
+              "name":"垫江县",
+              "code":"500231"
+            },
+            {
+              "name":"武隆县",
+              "code":"500232"
+            },
+            {
+              "name":"忠县",
+              "code":"500233"
+            },
+            {
+              "name":"开县",
+              "code":"500234"
+            },
+            {
+              "name":"云阳县",
+              "code":"500235"
+            },
+            {
+              "name":"奉节县",
+              "code":"500236"
+            },
+            {
+              "name":"巫山县",
+              "code":"500237"
+            },
+            {
+              "name":"巫溪县",
+              "code":"500238"
+            },
+            {
+              "name":"石柱土家族自治县",
+              "code":"500240"
+            },
+            {
+              "name":"秀山土家族苗族自治县",
+              "code":"500241"
+            },
+            {
+              "name":"酉阳土家族苗族自治县",
+              "code":"500242"
+            },
+            {
+              "name":"彭水苗族土家族自治县",
+              "code":"500243"
+            }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"四川省",
+    "code":"510000",
+    "sub":[
+      {
+        "name":"成都市",
+        "code":"510100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510101"
+          },
+          {
+            "name":"锦江区",
+            "code":"510104"
+          },
+          {
+            "name":"青羊区",
+            "code":"510105"
+          },
+          {
+            "name":"金牛区",
+            "code":"510106"
+          },
+          {
+            "name":"武侯区",
+            "code":"510107"
+          },
+          {
+            "name":"成华区",
+            "code":"510108"
+          },
+          {
+            "name":"龙泉驿区",
+            "code":"510112"
+          },
+          {
+            "name":"青白江区",
+            "code":"510113"
+          },
+          {
+            "name":"新都区",
+            "code":"510114"
+          },
+          {
+            "name":"温江区",
+            "code":"510115"
+          },
+          {
+            "name":"金堂县",
+            "code":"510121"
+          },
+          {
+            "name":"双流县",
+            "code":"510122"
+          },
+          {
+            "name":"郫县",
+            "code":"510124"
+          },
+          {
+            "name":"大邑县",
+            "code":"510129"
+          },
+          {
+            "name":"蒲江县",
+            "code":"510131"
+          },
+          {
+            "name":"新津县",
+            "code":"510132"
+          },
+          {
+            "name":"都江堰市",
+            "code":"510181"
+          },
+          {
+            "name":"彭州市",
+            "code":"510182"
+          },
+          {
+            "name":"邛崃市",
+            "code":"510183"
+          },
+          {
+            "name":"崇州市",
+            "code":"510184"
+          }
+        ]
+      },
+      {
+        "name":"自贡市",
+        "code":"510300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510301"
+          },
+          {
+            "name":"自流井区",
+            "code":"510302"
+          },
+          {
+            "name":"贡井区",
+            "code":"510303"
+          },
+          {
+            "name":"大安区",
+            "code":"510304"
+          },
+          {
+            "name":"沿滩区",
+            "code":"510311"
+          },
+          {
+            "name":"荣县",
+            "code":"510321"
+          },
+          {
+            "name":"富顺县",
+            "code":"510322"
+          }
+        ]
+      },
+      {
+        "name":"攀枝花市",
+        "code":"510400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510401"
+          },
+          {
+            "name":"东区",
+            "code":"510402"
+          },
+          {
+            "name":"西区",
+            "code":"510403"
+          },
+          {
+            "name":"仁和区",
+            "code":"510411"
+          },
+          {
+            "name":"米易县",
+            "code":"510421"
+          },
+          {
+            "name":"盐边县",
+            "code":"510422"
+          }
+        ]
+      },
+      {
+        "name":"泸州市",
+        "code":"510500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510501"
+          },
+          {
+            "name":"江阳区",
+            "code":"510502"
+          },
+          {
+            "name":"纳溪区",
+            "code":"510503"
+          },
+          {
+            "name":"龙马潭区",
+            "code":"510504"
+          },
+          {
+            "name":"泸县",
+            "code":"510521"
+          },
+          {
+            "name":"合江县",
+            "code":"510522"
+          },
+          {
+            "name":"叙永县",
+            "code":"510524"
+          },
+          {
+            "name":"古蔺县",
+            "code":"510525"
+          }
+        ]
+      },
+      {
+        "name":"德阳市",
+        "code":"510600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510601"
+          },
+          {
+            "name":"旌阳区",
+            "code":"510603"
+          },
+          {
+            "name":"中江县",
+            "code":"510623"
+          },
+          {
+            "name":"罗江县",
+            "code":"510626"
+          },
+          {
+            "name":"广汉市",
+            "code":"510681"
+          },
+          {
+            "name":"什邡市",
+            "code":"510682"
+          },
+          {
+            "name":"绵竹市",
+            "code":"510683"
+          }
+        ]
+      },
+      {
+        "name":"绵阳市",
+        "code":"510700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510701"
+          },
+          {
+            "name":"涪城区",
+            "code":"510703"
+          },
+          {
+            "name":"游仙区",
+            "code":"510704"
+          },
+          {
+            "name":"三台县",
+            "code":"510722"
+          },
+          {
+            "name":"盐亭县",
+            "code":"510723"
+          },
+          {
+            "name":"安县",
+            "code":"510724"
+          },
+          {
+            "name":"梓潼县",
+            "code":"510725"
+          },
+          {
+            "name":"北川羌族自治县",
+            "code":"510726"
+          },
+          {
+            "name":"平武县",
+            "code":"510727"
+          },
+          {
+            "name":"江油市",
+            "code":"510781"
+          }
+        ]
+      },
+      {
+        "name":"广元市",
+        "code":"510800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510801"
+          },
+          {
+            "name":"利州区",
+            "code":"510802"
+          },
+          {
+            "name":"昭化区",
+            "code":"510811"
+          },
+          {
+            "name":"朝天区",
+            "code":"510812"
+          },
+          {
+            "name":"旺苍县",
+            "code":"510821"
+          },
+          {
+            "name":"青川县",
+            "code":"510822"
+          },
+          {
+            "name":"剑阁县",
+            "code":"510823"
+          },
+          {
+            "name":"苍溪县",
+            "code":"510824"
+          }
+        ]
+      },
+      {
+        "name":"遂宁市",
+        "code":"510900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"510901"
+          },
+          {
+            "name":"船山区",
+            "code":"510903"
+          },
+          {
+            "name":"安居区",
+            "code":"510904"
+          },
+          {
+            "name":"蓬溪县",
+            "code":"510921"
+          },
+          {
+            "name":"射洪县",
+            "code":"510922"
+          },
+          {
+            "name":"大英县",
+            "code":"510923"
+          }
+        ]
+      },
+      {
+        "name":"内江市",
+        "code":"511000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511001"
+          },
+          {
+            "name":"市中区",
+            "code":"511002"
+          },
+          {
+            "name":"东兴区",
+            "code":"511011"
+          },
+          {
+            "name":"威远县",
+            "code":"511024"
+          },
+          {
+            "name":"资中县",
+            "code":"511025"
+          },
+          {
+            "name":"隆昌县",
+            "code":"511028"
+          }
+        ]
+      },
+      {
+        "name":"乐山市",
+        "code":"511100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511101"
+          },
+          {
+            "name":"市中区",
+            "code":"511102"
+          },
+          {
+            "name":"沙湾区",
+            "code":"511111"
+          },
+          {
+            "name":"五通桥区",
+            "code":"511112"
+          },
+          {
+            "name":"金口河区",
+            "code":"511113"
+          },
+          {
+            "name":"犍为县",
+            "code":"511123"
+          },
+          {
+            "name":"井研县",
+            "code":"511124"
+          },
+          {
+            "name":"夹江县",
+            "code":"511126"
+          },
+          {
+            "name":"沐川县",
+            "code":"511129"
+          },
+          {
+            "name":"峨边彝族自治县",
+            "code":"511132"
+          },
+          {
+            "name":"马边彝族自治县",
+            "code":"511133"
+          },
+          {
+            "name":"峨眉山市",
+            "code":"511181"
+          }
+        ]
+      },
+      {
+        "name":"南充市",
+        "code":"511300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511301"
+          },
+          {
+            "name":"顺庆区",
+            "code":"511302"
+          },
+          {
+            "name":"高坪区",
+            "code":"511303"
+          },
+          {
+            "name":"嘉陵区",
+            "code":"511304"
+          },
+          {
+            "name":"南部县",
+            "code":"511321"
+          },
+          {
+            "name":"营山县",
+            "code":"511322"
+          },
+          {
+            "name":"蓬安县",
+            "code":"511323"
+          },
+          {
+            "name":"仪陇县",
+            "code":"511324"
+          },
+          {
+            "name":"西充县",
+            "code":"511325"
+          },
+          {
+            "name":"阆中市",
+            "code":"511381"
+          }
+        ]
+      },
+      {
+        "name":"眉山市",
+        "code":"511400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511401"
+          },
+          {
+            "name":"东坡区",
+            "code":"511402"
+          },
+          {
+            "name":"彭山区",
+            "code":"511403"
+          },
+          {
+            "name":"仁寿县",
+            "code":"511421"
+          },
+          {
+            "name":"洪雅县",
+            "code":"511423"
+          },
+          {
+            "name":"丹棱县",
+            "code":"511424"
+          },
+          {
+            "name":"青神县",
+            "code":"511425"
+          }
+        ]
+      },
+      {
+        "name":"宜宾市",
+        "code":"511500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511501"
+          },
+          {
+            "name":"翠屏区",
+            "code":"511502"
+          },
+          {
+            "name":"南溪区",
+            "code":"511503"
+          },
+          {
+            "name":"宜宾县",
+            "code":"511521"
+          },
+          {
+            "name":"江安县",
+            "code":"511523"
+          },
+          {
+            "name":"长宁县",
+            "code":"511524"
+          },
+          {
+            "name":"高县",
+            "code":"511525"
+          },
+          {
+            "name":"珙县",
+            "code":"511526"
+          },
+          {
+            "name":"筠连县",
+            "code":"511527"
+          },
+          {
+            "name":"兴文县",
+            "code":"511528"
+          },
+          {
+            "name":"屏山县",
+            "code":"511529"
+          }
+        ]
+      },
+      {
+        "name":"广安市",
+        "code":"511600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511601"
+          },
+          {
+            "name":"广安区",
+            "code":"511602"
+          },
+          {
+            "name":"前锋区",
+            "code":"511603"
+          },
+          {
+            "name":"岳池县",
+            "code":"511621"
+          },
+          {
+            "name":"武胜县",
+            "code":"511622"
+          },
+          {
+            "name":"邻水县",
+            "code":"511623"
+          },
+          {
+            "name":"华蓥市",
+            "code":"511681"
+          }
+        ]
+      },
+      {
+        "name":"达州市",
+        "code":"511700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511701"
+          },
+          {
+            "name":"通川区",
+            "code":"511702"
+          },
+          {
+            "name":"达川区",
+            "code":"511703"
+          },
+          {
+            "name":"宣汉县",
+            "code":"511722"
+          },
+          {
+            "name":"开江县",
+            "code":"511723"
+          },
+          {
+            "name":"大竹县",
+            "code":"511724"
+          },
+          {
+            "name":"渠县",
+            "code":"511725"
+          },
+          {
+            "name":"万源市",
+            "code":"511781"
+          }
+        ]
+      },
+      {
+        "name":"雅安市",
+        "code":"511800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511801"
+          },
+          {
+            "name":"雨城区",
+            "code":"511802"
+          },
+          {
+            "name":"名山区",
+            "code":"511803"
+          },
+          {
+            "name":"荥经县",
+            "code":"511822"
+          },
+          {
+            "name":"汉源县",
+            "code":"511823"
+          },
+          {
+            "name":"石棉县",
+            "code":"511824"
+          },
+          {
+            "name":"天全县",
+            "code":"511825"
+          },
+          {
+            "name":"芦山县",
+            "code":"511826"
+          },
+          {
+            "name":"宝兴县",
+            "code":"511827"
+          }
+        ]
+      },
+      {
+        "name":"巴中市",
+        "code":"511900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"511901"
+          },
+          {
+            "name":"巴州区",
+            "code":"511902"
+          },
+          {
+            "name":"恩阳区",
+            "code":"511903"
+          },
+          {
+            "name":"通江县",
+            "code":"511921"
+          },
+          {
+            "name":"南江县",
+            "code":"511922"
+          },
+          {
+            "name":"平昌县",
+            "code":"511923"
+          }
+        ]
+      },
+      {
+        "name":"资阳市",
+        "code":"512000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"512001"
+          },
+          {
+            "name":"雁江区",
+            "code":"512002"
+          },
+          {
+            "name":"安岳县",
+            "code":"512021"
+          },
+          {
+            "name":"乐至县",
+            "code":"512022"
+          },
+          {
+            "name":"简阳市",
+            "code":"512081"
+          }
+        ]
+      },
+      {
+        "name":"阿坝藏族羌族自治州",
+        "code":"513200",
+        "sub":[
+          {
+            "name":"汶川县",
+            "code":"513221"
+          },
+          {
+            "name":"理县",
+            "code":"513222"
+          },
+          {
+            "name":"茂县",
+            "code":"513223"
+          },
+          {
+            "name":"松潘县",
+            "code":"513224"
+          },
+          {
+            "name":"九寨沟县",
+            "code":"513225"
+          },
+          {
+            "name":"金川县",
+            "code":"513226"
+          },
+          {
+            "name":"小金县",
+            "code":"513227"
+          },
+          {
+            "name":"黑水县",
+            "code":"513228"
+          },
+          {
+            "name":"马尔康县",
+            "code":"513229"
+          },
+          {
+            "name":"壤塘县",
+            "code":"513230"
+          },
+          {
+            "name":"阿坝县",
+            "code":"513231"
+          },
+          {
+            "name":"若尔盖县",
+            "code":"513232"
+          },
+          {
+            "name":"红原县",
+            "code":"513233"
+          }
+        ]
+      },
+      {
+        "name":"甘孜藏族自治州",
+        "code":"513300",
+        "sub":[
+          {
+            "name":"康定县",
+            "code":"513321"
+          },
+          {
+            "name":"泸定县",
+            "code":"513322"
+          },
+          {
+            "name":"丹巴县",
+            "code":"513323"
+          },
+          {
+            "name":"九龙县",
+            "code":"513324"
+          },
+          {
+            "name":"雅江县",
+            "code":"513325"
+          },
+          {
+            "name":"道孚县",
+            "code":"513326"
+          },
+          {
+            "name":"炉霍县",
+            "code":"513327"
+          },
+          {
+            "name":"甘孜县",
+            "code":"513328"
+          },
+          {
+            "name":"新龙县",
+            "code":"513329"
+          },
+          {
+            "name":"德格县",
+            "code":"513330"
+          },
+          {
+            "name":"白玉县",
+            "code":"513331"
+          },
+          {
+            "name":"石渠县",
+            "code":"513332"
+          },
+          {
+            "name":"色达县",
+            "code":"513333"
+          },
+          {
+            "name":"理塘县",
+            "code":"513334"
+          },
+          {
+            "name":"巴塘县",
+            "code":"513335"
+          },
+          {
+            "name":"乡城县",
+            "code":"513336"
+          },
+          {
+            "name":"稻城县",
+            "code":"513337"
+          },
+          {
+            "name":"得荣县",
+            "code":"513338"
+          }
+        ]
+      },
+      {
+        "name":"凉山彝族自治州",
+        "code":"513400",
+        "sub":[
+          {
+            "name":"西昌市",
+            "code":"513401"
+          },
+          {
+            "name":"木里藏族自治县",
+            "code":"513422"
+          },
+          {
+            "name":"盐源县",
+            "code":"513423"
+          },
+          {
+            "name":"德昌县",
+            "code":"513424"
+          },
+          {
+            "name":"会理县",
+            "code":"513425"
+          },
+          {
+            "name":"会东县",
+            "code":"513426"
+          },
+          {
+            "name":"宁南县",
+            "code":"513427"
+          },
+          {
+            "name":"普格县",
+            "code":"513428"
+          },
+          {
+            "name":"布拖县",
+            "code":"513429"
+          },
+          {
+            "name":"金阳县",
+            "code":"513430"
+          },
+          {
+            "name":"昭觉县",
+            "code":"513431"
+          },
+          {
+            "name":"喜德县",
+            "code":"513432"
+          },
+          {
+            "name":"冕宁县",
+            "code":"513433"
+          },
+          {
+            "name":"越西县",
+            "code":"513434"
+          },
+          {
+            "name":"甘洛县",
+            "code":"513435"
+          },
+          {
+            "name":"美姑县",
+            "code":"513436"
+          },
+          {
+            "name":"雷波县",
+            "code":"513437"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"贵州省",
+    "code":"520000",
+    "sub":[
+      {
+        "name":"贵阳市",
+        "code":"520100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520101"
+          },
+          {
+            "name":"南明区",
+            "code":"520102"
+          },
+          {
+            "name":"云岩区",
+            "code":"520103"
+          },
+          {
+            "name":"花溪区",
+            "code":"520111"
+          },
+          {
+            "name":"乌当区",
+            "code":"520112"
+          },
+          {
+            "name":"白云区",
+            "code":"520113"
+          },
+          {
+            "name":"观山湖区",
+            "code":"520115"
+          },
+          {
+            "name":"开阳县",
+            "code":"520121"
+          },
+          {
+            "name":"息烽县",
+            "code":"520122"
+          },
+          {
+            "name":"修文县",
+            "code":"520123"
+          },
+          {
+            "name":"清镇市",
+            "code":"520181"
+          }
+        ]
+      },
+      {
+        "name":"六盘水市",
+        "code":"520200",
+        "sub":[
+          {
+            "name":"钟山区",
+            "code":"520201"
+          },
+          {
+            "name":"六枝特区",
+            "code":"520203"
+          },
+          {
+            "name":"水城县",
+            "code":"520221"
+          },
+          {
+            "name":"盘县",
+            "code":"520222"
+          }
+        ]
+      },
+      {
+        "name":"遵义市",
+        "code":"520300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520301"
+          },
+          {
+            "name":"红花岗区",
+            "code":"520302"
+          },
+          {
+            "name":"汇川区",
+            "code":"520303"
+          },
+          {
+            "name":"遵义县",
+            "code":"520321"
+          },
+          {
+            "name":"桐梓县",
+            "code":"520322"
+          },
+          {
+            "name":"绥阳县",
+            "code":"520323"
+          },
+          {
+            "name":"正安县",
+            "code":"520324"
+          },
+          {
+            "name":"道真仡佬族苗族自治县",
+            "code":"520325"
+          },
+          {
+            "name":"务川仡佬族苗族自治县",
+            "code":"520326"
+          },
+          {
+            "name":"凤冈县",
+            "code":"520327"
+          },
+          {
+            "name":"湄潭县",
+            "code":"520328"
+          },
+          {
+            "name":"余庆县",
+            "code":"520329"
+          },
+          {
+            "name":"习水县",
+            "code":"520330"
+          },
+          {
+            "name":"赤水市",
+            "code":"520381"
+          },
+          {
+            "name":"仁怀市",
+            "code":"520382"
+          }
+        ]
+      },
+      {
+        "name":"安顺市",
+        "code":"520400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520401"
+          },
+          {
+            "name":"西秀区",
+            "code":"520402"
+          },
+          {
+            "name":"平坝区",
+            "code":"520403"
+          },
+          {
+            "name":"普定县",
+            "code":"520422"
+          },
+          {
+            "name":"镇宁布依族苗族自治县",
+            "code":"520423"
+          },
+          {
+            "name":"关岭布依族苗族自治县",
+            "code":"520424"
+          },
+          {
+            "name":"紫云苗族布依族自治县",
+            "code":"520425"
+          }
+        ]
+      },
+      {
+        "name":"毕节市",
+        "code":"520500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520501"
+          },
+          {
+            "name":"七星关区",
+            "code":"520502"
+          },
+          {
+            "name":"大方县",
+            "code":"520521"
+          },
+          {
+            "name":"黔西县",
+            "code":"520522"
+          },
+          {
+            "name":"金沙县",
+            "code":"520523"
+          },
+          {
+            "name":"织金县",
+            "code":"520524"
+          },
+          {
+            "name":"纳雍县",
+            "code":"520525"
+          },
+          {
+            "name":"威宁彝族回族苗族自治县",
+            "code":"520526"
+          },
+          {
+            "name":"赫章县",
+            "code":"520527"
+          }
+        ]
+      },
+      {
+        "name":"铜仁市",
+        "code":"520600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"520601"
+          },
+          {
+            "name":"碧江区",
+            "code":"520602"
+          },
+          {
+            "name":"万山区",
+            "code":"520603"
+          },
+          {
+            "name":"江口县",
+            "code":"520621"
+          },
+          {
+            "name":"玉屏侗族自治县",
+            "code":"520622"
+          },
+          {
+            "name":"石阡县",
+            "code":"520623"
+          },
+          {
+            "name":"思南县",
+            "code":"520624"
+          },
+          {
+            "name":"印江土家族苗族自治县",
+            "code":"520625"
+          },
+          {
+            "name":"德江县",
+            "code":"520626"
+          },
+          {
+            "name":"沿河土家族自治县",
+            "code":"520627"
+          },
+          {
+            "name":"松桃苗族自治县",
+            "code":"520628"
+          }
+        ]
+      },
+      {
+        "name":"黔西南布依族苗族自治州",
+        "code":"522300",
+        "sub":[
+          {
+            "name":"兴义市",
+            "code":"522301"
+          },
+          {
+            "name":"兴仁县",
+            "code":"522322"
+          },
+          {
+            "name":"普安县",
+            "code":"522323"
+          },
+          {
+            "name":"晴隆县",
+            "code":"522324"
+          },
+          {
+            "name":"贞丰县",
+            "code":"522325"
+          },
+          {
+            "name":"望谟县",
+            "code":"522326"
+          },
+          {
+            "name":"册亨县",
+            "code":"522327"
+          },
+          {
+            "name":"安龙县",
+            "code":"522328"
+          }
+        ]
+      },
+      {
+        "name":"黔东南苗族侗族自治州",
+        "code":"522600",
+        "sub":[
+          {
+            "name":"凯里市",
+            "code":"522601"
+          },
+          {
+            "name":"黄平县",
+            "code":"522622"
+          },
+          {
+            "name":"施秉县",
+            "code":"522623"
+          },
+          {
+            "name":"三穗县",
+            "code":"522624"
+          },
+          {
+            "name":"镇远县",
+            "code":"522625"
+          },
+          {
+            "name":"岑巩县",
+            "code":"522626"
+          },
+          {
+            "name":"天柱县",
+            "code":"522627"
+          },
+          {
+            "name":"锦屏县",
+            "code":"522628"
+          },
+          {
+            "name":"剑河县",
+            "code":"522629"
+          },
+          {
+            "name":"台江县",
+            "code":"522630"
+          },
+          {
+            "name":"黎平县",
+            "code":"522631"
+          },
+          {
+            "name":"榕江县",
+            "code":"522632"
+          },
+          {
+            "name":"从江县",
+            "code":"522633"
+          },
+          {
+            "name":"雷山县",
+            "code":"522634"
+          },
+          {
+            "name":"麻江县",
+            "code":"522635"
+          },
+          {
+            "name":"丹寨县",
+            "code":"522636"
+          }
+        ]
+      },
+      {
+        "name":"黔南布依族苗族自治州",
+        "code":"522700",
+        "sub":[
+          {
+            "name":"都匀市",
+            "code":"522701"
+          },
+          {
+            "name":"福泉市",
+            "code":"522702"
+          },
+          {
+            "name":"荔波县",
+            "code":"522722"
+          },
+          {
+            "name":"贵定县",
+            "code":"522723"
+          },
+          {
+            "name":"瓮安县",
+            "code":"522725"
+          },
+          {
+            "name":"独山县",
+            "code":"522726"
+          },
+          {
+            "name":"平塘县",
+            "code":"522727"
+          },
+          {
+            "name":"罗甸县",
+            "code":"522728"
+          },
+          {
+            "name":"长顺县",
+            "code":"522729"
+          },
+          {
+            "name":"龙里县",
+            "code":"522730"
+          },
+          {
+            "name":"惠水县",
+            "code":"522731"
+          },
+          {
+            "name":"三都水族自治县",
+            "code":"522732"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"云南省",
+    "code":"530000",
+    "sub":[
+      {
+        "name":"昆明市",
+        "code":"530100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530101"
+          },
+          {
+            "name":"五华区",
+            "code":"530102"
+          },
+          {
+            "name":"盘龙区",
+            "code":"530103"
+          },
+          {
+            "name":"官渡区",
+            "code":"530111"
+          },
+          {
+            "name":"西山区",
+            "code":"530112"
+          },
+          {
+            "name":"东川区",
+            "code":"530113"
+          },
+          {
+            "name":"呈贡区",
+            "code":"530114"
+          },
+          {
+            "name":"晋宁县",
+            "code":"530122"
+          },
+          {
+            "name":"富民县",
+            "code":"530124"
+          },
+          {
+            "name":"宜良县",
+            "code":"530125"
+          },
+          {
+            "name":"石林彝族自治县",
+            "code":"530126"
+          },
+          {
+            "name":"嵩明县",
+            "code":"530127"
+          },
+          {
+            "name":"禄劝彝族苗族自治县",
+            "code":"530128"
+          },
+          {
+            "name":"寻甸回族彝族自治县",
+            "code":"530129"
+          },
+          {
+            "name":"安宁市",
+            "code":"530181"
+          }
+        ]
+      },
+      {
+        "name":"曲靖市",
+        "code":"530300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530301"
+          },
+          {
+            "name":"麒麟区",
+            "code":"530302"
+          },
+          {
+            "name":"马龙县",
+            "code":"530321"
+          },
+          {
+            "name":"陆良县",
+            "code":"530322"
+          },
+          {
+            "name":"师宗县",
+            "code":"530323"
+          },
+          {
+            "name":"罗平县",
+            "code":"530324"
+          },
+          {
+            "name":"富源县",
+            "code":"530325"
+          },
+          {
+            "name":"会泽县",
+            "code":"530326"
+          },
+          {
+            "name":"沾益县",
+            "code":"530328"
+          },
+          {
+            "name":"宣威市",
+            "code":"530381"
+          }
+        ]
+      },
+      {
+        "name":"玉溪市",
+        "code":"530400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530401"
+          },
+          {
+            "name":"红塔区",
+            "code":"530402"
+          },
+          {
+            "name":"江川县",
+            "code":"530421"
+          },
+          {
+            "name":"澄江县",
+            "code":"530422"
+          },
+          {
+            "name":"通海县",
+            "code":"530423"
+          },
+          {
+            "name":"华宁县",
+            "code":"530424"
+          },
+          {
+            "name":"易门县",
+            "code":"530425"
+          },
+          {
+            "name":"峨山彝族自治县",
+            "code":"530426"
+          },
+          {
+            "name":"新平彝族傣族自治县",
+            "code":"530427"
+          },
+          {
+            "name":"元江哈尼族彝族傣族自治县",
+            "code":"530428"
+          }
+        ]
+      },
+      {
+        "name":"保山市",
+        "code":"530500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530501"
+          },
+          {
+            "name":"隆阳区",
+            "code":"530502"
+          },
+          {
+            "name":"施甸县",
+            "code":"530521"
+          },
+          {
+            "name":"腾冲县",
+            "code":"530522"
+          },
+          {
+            "name":"龙陵县",
+            "code":"530523"
+          },
+          {
+            "name":"昌宁县",
+            "code":"530524"
+          }
+        ]
+      },
+      {
+        "name":"昭通市",
+        "code":"530600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530601"
+          },
+          {
+            "name":"昭阳区",
+            "code":"530602"
+          },
+          {
+            "name":"鲁甸县",
+            "code":"530621"
+          },
+          {
+            "name":"巧家县",
+            "code":"530622"
+          },
+          {
+            "name":"盐津县",
+            "code":"530623"
+          },
+          {
+            "name":"大关县",
+            "code":"530624"
+          },
+          {
+            "name":"永善县",
+            "code":"530625"
+          },
+          {
+            "name":"绥江县",
+            "code":"530626"
+          },
+          {
+            "name":"镇雄县",
+            "code":"530627"
+          },
+          {
+            "name":"彝良县",
+            "code":"530628"
+          },
+          {
+            "name":"威信县",
+            "code":"530629"
+          },
+          {
+            "name":"水富县",
+            "code":"530630"
+          }
+        ]
+      },
+      {
+        "name":"丽江市",
+        "code":"530700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530701"
+          },
+          {
+            "name":"古城区",
+            "code":"530702"
+          },
+          {
+            "name":"玉龙纳西族自治县",
+            "code":"530721"
+          },
+          {
+            "name":"永胜县",
+            "code":"530722"
+          },
+          {
+            "name":"华坪县",
+            "code":"530723"
+          },
+          {
+            "name":"宁蒗彝族自治县",
+            "code":"530724"
+          }
+        ]
+      },
+      {
+        "name":"普洱市",
+        "code":"530800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530801"
+          },
+          {
+            "name":"思茅区",
+            "code":"530802"
+          },
+          {
+            "name":"宁洱哈尼族彝族自治县",
+            "code":"530821"
+          },
+          {
+            "name":"墨江哈尼族自治县",
+            "code":"530822"
+          },
+          {
+            "name":"景东彝族自治县",
+            "code":"530823"
+          },
+          {
+            "name":"景谷傣族彝族自治县",
+            "code":"530824"
+          },
+          {
+            "name":"镇沅彝族哈尼族拉祜族自治县",
+            "code":"530825"
+          },
+          {
+            "name":"江城哈尼族彝族自治县",
+            "code":"530826"
+          },
+          {
+            "name":"孟连傣族拉祜族佤族自治县",
+            "code":"530827"
+          },
+          {
+            "name":"澜沧拉祜族自治县",
+            "code":"530828"
+          },
+          {
+            "name":"西盟佤族自治县",
+            "code":"530829"
+          }
+        ]
+      },
+      {
+        "name":"临沧市",
+        "code":"530900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"530901"
+          },
+          {
+            "name":"临翔区",
+            "code":"530902"
+          },
+          {
+            "name":"凤庆县",
+            "code":"530921"
+          },
+          {
+            "name":"云县",
+            "code":"530922"
+          },
+          {
+            "name":"永德县",
+            "code":"530923"
+          },
+          {
+            "name":"镇康县",
+            "code":"530924"
+          },
+          {
+            "name":"双江拉祜族佤族布朗族傣族自治县",
+            "code":"530925"
+          },
+          {
+            "name":"耿马傣族佤族自治县",
+            "code":"530926"
+          },
+          {
+            "name":"沧源佤族自治县",
+            "code":"530927"
+          }
+        ]
+      },
+      {
+        "name":"楚雄彝族自治州",
+        "code":"532300",
+        "sub":[
+          {
+            "name":"楚雄市",
+            "code":"532301"
+          },
+          {
+            "name":"双柏县",
+            "code":"532322"
+          },
+          {
+            "name":"牟定县",
+            "code":"532323"
+          },
+          {
+            "name":"南华县",
+            "code":"532324"
+          },
+          {
+            "name":"姚安县",
+            "code":"532325"
+          },
+          {
+            "name":"大姚县",
+            "code":"532326"
+          },
+          {
+            "name":"永仁县",
+            "code":"532327"
+          },
+          {
+            "name":"元谋县",
+            "code":"532328"
+          },
+          {
+            "name":"武定县",
+            "code":"532329"
+          },
+          {
+            "name":"禄丰县",
+            "code":"532331"
+          }
+        ]
+      },
+      {
+        "name":"红河哈尼族彝族自治州",
+        "code":"532500",
+        "sub":[
+          {
+            "name":"个旧市",
+            "code":"532501"
+          },
+          {
+            "name":"开远市",
+            "code":"532502"
+          },
+          {
+            "name":"蒙自市",
+            "code":"532503"
+          },
+          {
+            "name":"弥勒市",
+            "code":"532504"
+          },
+          {
+            "name":"屏边苗族自治县",
+            "code":"532523"
+          },
+          {
+            "name":"建水县",
+            "code":"532524"
+          },
+          {
+            "name":"石屏县",
+            "code":"532525"
+          },
+          {
+            "name":"泸西县",
+            "code":"532527"
+          },
+          {
+            "name":"元阳县",
+            "code":"532528"
+          },
+          {
+            "name":"红河县",
+            "code":"532529"
+          },
+          {
+            "name":"金平苗族瑶族傣族自治县",
+            "code":"532530"
+          },
+          {
+            "name":"绿春县",
+            "code":"532531"
+          },
+          {
+            "name":"河口瑶族自治县",
+            "code":"532532"
+          }
+        ]
+      },
+      {
+        "name":"文山壮族苗族自治州",
+        "code":"532600",
+        "sub":[
+          {
+            "name":"文山市",
+            "code":"532601"
+          },
+          {
+            "name":"砚山县",
+            "code":"532622"
+          },
+          {
+            "name":"西畴县",
+            "code":"532623"
+          },
+          {
+            "name":"麻栗坡县",
+            "code":"532624"
+          },
+          {
+            "name":"马关县",
+            "code":"532625"
+          },
+          {
+            "name":"丘北县",
+            "code":"532626"
+          },
+          {
+            "name":"广南县",
+            "code":"532627"
+          },
+          {
+            "name":"富宁县",
+            "code":"532628"
+          }
+        ]
+      },
+      {
+        "name":"西双版纳傣族自治州",
+        "code":"532800",
+        "sub":[
+          {
+            "name":"景洪市",
+            "code":"532801"
+          },
+          {
+            "name":"勐海县",
+            "code":"532822"
+          },
+          {
+            "name":"勐腊县",
+            "code":"532823"
+          }
+        ]
+      },
+      {
+        "name":"大理白族自治州",
+        "code":"532900",
+        "sub":[
+          {
+            "name":"大理市",
+            "code":"532901"
+          },
+          {
+            "name":"漾濞彝族自治县",
+            "code":"532922"
+          },
+          {
+            "name":"祥云县",
+            "code":"532923"
+          },
+          {
+            "name":"宾川县",
+            "code":"532924"
+          },
+          {
+            "name":"弥渡县",
+            "code":"532925"
+          },
+          {
+            "name":"南涧彝族自治县",
+            "code":"532926"
+          },
+          {
+            "name":"巍山彝族回族自治县",
+            "code":"532927"
+          },
+          {
+            "name":"永平县",
+            "code":"532928"
+          },
+          {
+            "name":"云龙县",
+            "code":"532929"
+          },
+          {
+            "name":"洱源县",
+            "code":"532930"
+          },
+          {
+            "name":"剑川县",
+            "code":"532931"
+          },
+          {
+            "name":"鹤庆县",
+            "code":"532932"
+          }
+        ]
+      },
+      {
+        "name":"德宏傣族景颇族自治州",
+        "code":"533100",
+        "sub":[
+          {
+            "name":"瑞丽市",
+            "code":"533102"
+          },
+          {
+            "name":"芒市",
+            "code":"533103"
+          },
+          {
+            "name":"梁河县",
+            "code":"533122"
+          },
+          {
+            "name":"盈江县",
+            "code":"533123"
+          },
+          {
+            "name":"陇川县",
+            "code":"533124"
+          }
+        ]
+      },
+      {
+        "name":"怒江傈僳族自治州",
+        "code":"533300",
+        "sub":[
+          {
+            "name":"泸水县",
+            "code":"533321"
+          },
+          {
+            "name":"福贡县",
+            "code":"533323"
+          },
+          {
+            "name":"贡山独龙族怒族自治县",
+            "code":"533324"
+          },
+          {
+            "name":"兰坪白族普米族自治县",
+            "code":"533325"
+          }
+        ]
+      },
+      {
+        "name":"迪庆藏族自治州",
+        "code":"533400",
+        "sub":[
+          {
+            "name":"香格里拉市",
+            "code":"533401"
+          },
+          {
+            "name":"德钦县",
+            "code":"533422"
+          },
+          {
+            "name":"维西傈僳族自治县",
+            "code":"533423"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"西藏自治区",
+    "code":"540000",
+    "sub":[
+      {
+        "name":"拉萨市",
+        "code":"540100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540101"
+          },
+          {
+            "name":"城关区",
+            "code":"540102"
+          },
+          {
+            "name":"林周县",
+            "code":"540121"
+          },
+          {
+            "name":"当雄县",
+            "code":"540122"
+          },
+          {
+            "name":"尼木县",
+            "code":"540123"
+          },
+          {
+            "name":"曲水县",
+            "code":"540124"
+          },
+          {
+            "name":"堆龙德庆县",
+            "code":"540125"
+          },
+          {
+            "name":"达孜县",
+            "code":"540126"
+          },
+          {
+            "name":"墨竹工卡县",
+            "code":"540127"
+          }
+        ]
+      },
+      {
+        "name":"日喀则市",
+        "code":"540200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540201"
+          },
+          {
+            "name":"桑珠孜区",
+            "code":"540202"
+          },
+          {
+            "name":"南木林县",
+            "code":"540221"
+          },
+          {
+            "name":"江孜县",
+            "code":"540222"
+          },
+          {
+            "name":"定日县",
+            "code":"540223"
+          },
+          {
+            "name":"萨迦县",
+            "code":"540224"
+          },
+          {
+            "name":"拉孜县",
+            "code":"540225"
+          },
+          {
+            "name":"昂仁县",
+            "code":"540226"
+          },
+          {
+            "name":"谢通门县",
+            "code":"540227"
+          },
+          {
+            "name":"白朗县",
+            "code":"540228"
+          },
+          {
+            "name":"仁布县",
+            "code":"540229"
+          },
+          {
+            "name":"康马县",
+            "code":"540230"
+          },
+          {
+            "name":"定结县",
+            "code":"540231"
+          },
+          {
+            "name":"仲巴县",
+            "code":"540232"
+          },
+          {
+            "name":"亚东县",
+            "code":"540233"
+          },
+          {
+            "name":"吉隆县",
+            "code":"540234"
+          },
+          {
+            "name":"聂拉木县",
+            "code":"540235"
+          },
+          {
+            "name":"萨嘎县",
+            "code":"540236"
+          },
+          {
+            "name":"岗巴县",
+            "code":"540237"
+          }
+        ]
+      },
+      {
+        "name":"昌都市",
+        "code":"540300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"540301"
+          },
+          {
+            "name":"卡若区",
+            "code":"540302"
+          },
+          {
+            "name":"江达县",
+            "code":"540321"
+          },
+          {
+            "name":"贡觉县",
+            "code":"540322"
+          },
+          {
+            "name":"类乌齐县",
+            "code":"540323"
+          },
+          {
+            "name":"丁青县",
+            "code":"540324"
+          },
+          {
+            "name":"察雅县",
+            "code":"540325"
+          },
+          {
+            "name":"八宿县",
+            "code":"540326"
+          },
+          {
+            "name":"左贡县",
+            "code":"540327"
+          },
+          {
+            "name":"芒康县",
+            "code":"540328"
+          },
+          {
+            "name":"洛隆县",
+            "code":"540329"
+          },
+          {
+            "name":"边坝县",
+            "code":"540330"
+          }
+        ]
+      },
+      {
+        "name":"山南地区",
+        "code":"542200",
+        "sub":[
+          {
+            "name":"乃东县",
+            "code":"542221"
+          },
+          {
+            "name":"扎囊县",
+            "code":"542222"
+          },
+          {
+            "name":"贡嘎县",
+            "code":"542223"
+          },
+          {
+            "name":"桑日县",
+            "code":"542224"
+          },
+          {
+            "name":"琼结县",
+            "code":"542225"
+          },
+          {
+            "name":"曲松县",
+            "code":"542226"
+          },
+          {
+            "name":"措美县",
+            "code":"542227"
+          },
+          {
+            "name":"洛扎县",
+            "code":"542228"
+          },
+          {
+            "name":"加查县",
+            "code":"542229"
+          },
+          {
+            "name":"隆子县",
+            "code":"542231"
+          },
+          {
+            "name":"错那县",
+            "code":"542232"
+          },
+          {
+            "name":"浪卡子县",
+            "code":"542233"
+          }
+        ]
+      },
+      {
+        "name":"那曲地区",
+        "code":"542400",
+        "sub":[
+          {
+            "name":"那曲县",
+            "code":"542421"
+          },
+          {
+            "name":"嘉黎县",
+            "code":"542422"
+          },
+          {
+            "name":"比如县",
+            "code":"542423"
+          },
+          {
+            "name":"聂荣县",
+            "code":"542424"
+          },
+          {
+            "name":"安多县",
+            "code":"542425"
+          },
+          {
+            "name":"申扎县",
+            "code":"542426"
+          },
+          {
+            "name":"索县",
+            "code":"542427"
+          },
+          {
+            "name":"班戈县",
+            "code":"542428"
+          },
+          {
+            "name":"巴青县",
+            "code":"542429"
+          },
+          {
+            "name":"尼玛县",
+            "code":"542430"
+          },
+          {
+            "name":"双湖县",
+            "code":"542431"
+          }
+        ]
+      },
+      {
+        "name":"阿里地区",
+        "code":"542500",
+        "sub":[
+          {
+            "name":"普兰县",
+            "code":"542521"
+          },
+          {
+            "name":"札达县",
+            "code":"542522"
+          },
+          {
+            "name":"噶尔县",
+            "code":"542523"
+          },
+          {
+            "name":"日土县",
+            "code":"542524"
+          },
+          {
+            "name":"革吉县",
+            "code":"542525"
+          },
+          {
+            "name":"改则县",
+            "code":"542526"
+          },
+          {
+            "name":"措勤县",
+            "code":"542527"
+          }
+        ]
+      },
+      {
+        "name":"林芝地区",
+        "code":"542600",
+        "sub":[
+          {
+            "name":"林芝县",
+            "code":"542621"
+          },
+          {
+            "name":"工布江达县",
+            "code":"542622"
+          },
+          {
+            "name":"米林县",
+            "code":"542623"
+          },
+          {
+            "name":"墨脱县",
+            "code":"542624"
+          },
+          {
+            "name":"波密县",
+            "code":"542625"
+          },
+          {
+            "name":"察隅县",
+            "code":"542626"
+          },
+          {
+            "name":"朗县",
+            "code":"542627"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"陕西省",
+    "code":"610000",
+    "sub":[
+      {
+        "name":"西安市",
+        "code":"610100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610101"
+          },
+          {
+            "name":"新城区",
+            "code":"610102"
+          },
+          {
+            "name":"碑林区",
+            "code":"610103"
+          },
+          {
+            "name":"莲湖区",
+            "code":"610104"
+          },
+          {
+            "name":"灞桥区",
+            "code":"610111"
+          },
+          {
+            "name":"未央区",
+            "code":"610112"
+          },
+          {
+            "name":"雁塔区",
+            "code":"610113"
+          },
+          {
+            "name":"阎良区",
+            "code":"610114"
+          },
+          {
+            "name":"临潼区",
+            "code":"610115"
+          },
+          {
+            "name":"长安区",
+            "code":"610116"
+          },
+          {
+            "name":"高陵区",
+            "code":"610117"
+          },
+          {
+            "name":"蓝田县",
+            "code":"610122"
+          },
+          {
+            "name":"周至县",
+            "code":"610124"
+          },
+          {
+            "name":"户县",
+            "code":"610125"
+          }
+        ]
+      },
+      {
+        "name":"铜川市",
+        "code":"610200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610201"
+          },
+          {
+            "name":"王益区",
+            "code":"610202"
+          },
+          {
+            "name":"印台区",
+            "code":"610203"
+          },
+          {
+            "name":"耀州区",
+            "code":"610204"
+          },
+          {
+            "name":"宜君县",
+            "code":"610222"
+          }
+        ]
+      },
+      {
+        "name":"宝鸡市",
+        "code":"610300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610301"
+          },
+          {
+            "name":"渭滨区",
+            "code":"610302"
+          },
+          {
+            "name":"金台区",
+            "code":"610303"
+          },
+          {
+            "name":"陈仓区",
+            "code":"610304"
+          },
+          {
+            "name":"凤翔县",
+            "code":"610322"
+          },
+          {
+            "name":"岐山县",
+            "code":"610323"
+          },
+          {
+            "name":"扶风县",
+            "code":"610324"
+          },
+          {
+            "name":"眉县",
+            "code":"610326"
+          },
+          {
+            "name":"陇县",
+            "code":"610327"
+          },
+          {
+            "name":"千阳县",
+            "code":"610328"
+          },
+          {
+            "name":"麟游县",
+            "code":"610329"
+          },
+          {
+            "name":"凤县",
+            "code":"610330"
+          },
+          {
+            "name":"太白县",
+            "code":"610331"
+          }
+        ]
+      },
+      {
+        "name":"咸阳市",
+        "code":"610400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610401"
+          },
+          {
+            "name":"秦都区",
+            "code":"610402"
+          },
+          {
+            "name":"杨陵区",
+            "code":"610403"
+          },
+          {
+            "name":"渭城区",
+            "code":"610404"
+          },
+          {
+            "name":"三原县",
+            "code":"610422"
+          },
+          {
+            "name":"泾阳县",
+            "code":"610423"
+          },
+          {
+            "name":"乾县",
+            "code":"610424"
+          },
+          {
+            "name":"礼泉县",
+            "code":"610425"
+          },
+          {
+            "name":"永寿县",
+            "code":"610426"
+          },
+          {
+            "name":"彬县",
+            "code":"610427"
+          },
+          {
+            "name":"长武县",
+            "code":"610428"
+          },
+          {
+            "name":"旬邑县",
+            "code":"610429"
+          },
+          {
+            "name":"淳化县",
+            "code":"610430"
+          },
+          {
+            "name":"武功县",
+            "code":"610431"
+          },
+          {
+            "name":"兴平市",
+            "code":"610481"
+          }
+        ]
+      },
+      {
+        "name":"渭南市",
+        "code":"610500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610501"
+          },
+          {
+            "name":"临渭区",
+            "code":"610502"
+          },
+          {
+            "name":"华县",
+            "code":"610521"
+          },
+          {
+            "name":"潼关县",
+            "code":"610522"
+          },
+          {
+            "name":"大荔县",
+            "code":"610523"
+          },
+          {
+            "name":"合阳县",
+            "code":"610524"
+          },
+          {
+            "name":"澄城县",
+            "code":"610525"
+          },
+          {
+            "name":"蒲城县",
+            "code":"610526"
+          },
+          {
+            "name":"白水县",
+            "code":"610527"
+          },
+          {
+            "name":"富平县",
+            "code":"610528"
+          },
+          {
+            "name":"韩城市",
+            "code":"610581"
+          },
+          {
+            "name":"华阴市",
+            "code":"610582"
+          }
+        ]
+      },
+      {
+        "name":"延安市",
+        "code":"610600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610601"
+          },
+          {
+            "name":"宝塔区",
+            "code":"610602"
+          },
+          {
+            "name":"延长县",
+            "code":"610621"
+          },
+          {
+            "name":"延川县",
+            "code":"610622"
+          },
+          {
+            "name":"子长县",
+            "code":"610623"
+          },
+          {
+            "name":"安塞县",
+            "code":"610624"
+          },
+          {
+            "name":"志丹县",
+            "code":"610625"
+          },
+          {
+            "name":"吴起县",
+            "code":"610626"
+          },
+          {
+            "name":"甘泉县",
+            "code":"610627"
+          },
+          {
+            "name":"富县",
+            "code":"610628"
+          },
+          {
+            "name":"洛川县",
+            "code":"610629"
+          },
+          {
+            "name":"宜川县",
+            "code":"610630"
+          },
+          {
+            "name":"黄龙县",
+            "code":"610631"
+          },
+          {
+            "name":"黄陵县",
+            "code":"610632"
+          }
+        ]
+      },
+      {
+        "name":"汉中市",
+        "code":"610700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610701"
+          },
+          {
+            "name":"汉台区",
+            "code":"610702"
+          },
+          {
+            "name":"南郑县",
+            "code":"610721"
+          },
+          {
+            "name":"城固县",
+            "code":"610722"
+          },
+          {
+            "name":"洋县",
+            "code":"610723"
+          },
+          {
+            "name":"西乡县",
+            "code":"610724"
+          },
+          {
+            "name":"勉县",
+            "code":"610725"
+          },
+          {
+            "name":"宁强县",
+            "code":"610726"
+          },
+          {
+            "name":"略阳县",
+            "code":"610727"
+          },
+          {
+            "name":"镇巴县",
+            "code":"610728"
+          },
+          {
+            "name":"留坝县",
+            "code":"610729"
+          },
+          {
+            "name":"佛坪县",
+            "code":"610730"
+          }
+        ]
+      },
+      {
+        "name":"榆林市",
+        "code":"610800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610801"
+          },
+          {
+            "name":"榆阳区",
+            "code":"610802"
+          },
+          {
+            "name":"神木县",
+            "code":"610821"
+          },
+          {
+            "name":"府谷县",
+            "code":"610822"
+          },
+          {
+            "name":"横山县",
+            "code":"610823"
+          },
+          {
+            "name":"靖边县",
+            "code":"610824"
+          },
+          {
+            "name":"定边县",
+            "code":"610825"
+          },
+          {
+            "name":"绥德县",
+            "code":"610826"
+          },
+          {
+            "name":"米脂县",
+            "code":"610827"
+          },
+          {
+            "name":"佳县",
+            "code":"610828"
+          },
+          {
+            "name":"吴堡县",
+            "code":"610829"
+          },
+          {
+            "name":"清涧县",
+            "code":"610830"
+          },
+          {
+            "name":"子洲县",
+            "code":"610831"
+          }
+        ]
+      },
+      {
+        "name":"安康市",
+        "code":"610900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"610901"
+          },
+          {
+            "name":"汉阴县",
+            "code":"610921"
+          },
+          {
+            "name":"石泉县",
+            "code":"610922"
+          },
+          {
+            "name":"宁陕县",
+            "code":"610923"
+          },
+          {
+            "name":"紫阳县",
+            "code":"610924"
+          },
+          {
+            "name":"岚皋县",
+            "code":"610925"
+          },
+          {
+            "name":"平利县",
+            "code":"610926"
+          },
+          {
+            "name":"镇坪县",
+            "code":"610927"
+          },
+          {
+            "name":"旬阳县",
+            "code":"610928"
+          },
+          {
+            "name":"白河县",
+            "code":"610929"
+          }
+        ]
+      },
+      {
+        "name":"商洛市",
+        "code":"611000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"611001"
+          },
+          {
+            "name":"商州区",
+            "code":"611002"
+          },
+          {
+            "name":"洛南县",
+            "code":"611021"
+          },
+          {
+            "name":"丹凤县",
+            "code":"611022"
+          },
+          {
+            "name":"商南县",
+            "code":"611023"
+          },
+          {
+            "name":"山阳县",
+            "code":"611024"
+          },
+          {
+            "name":"镇安县",
+            "code":"611025"
+          },
+          {
+            "name":"柞水县",
+            "code":"611026"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"甘肃省",
+    "code":"620000",
+    "sub":[
+      {
+        "name":"兰州市",
+        "code":"620100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620101"
+          },
+          {
+            "name":"城关区",
+            "code":"620102"
+          },
+          {
+            "name":"七里河区",
+            "code":"620103"
+          },
+          {
+            "name":"西固区",
+            "code":"620104"
+          },
+          {
+            "name":"安宁区",
+            "code":"620105"
+          },
+          {
+            "name":"红古区",
+            "code":"620111"
+          },
+          {
+            "name":"永登县",
+            "code":"620121"
+          },
+          {
+            "name":"皋兰县",
+            "code":"620122"
+          },
+          {
+            "name":"榆中县",
+            "code":"620123"
+          }
+        ]
+      },
+      {
+        "name":"嘉峪关市",
+        "code":"620200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620201"
+          }
+        ]
+      },
+      {
+        "name":"金昌市",
+        "code":"620300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620301"
+          },
+          {
+            "name":"金川区",
+            "code":"620302"
+          },
+          {
+            "name":"永昌县",
+            "code":"620321"
+          }
+        ]
+      },
+      {
+        "name":"白银市",
+        "code":"620400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620401"
+          },
+          {
+            "name":"白银区",
+            "code":"620402"
+          },
+          {
+            "name":"平川区",
+            "code":"620403"
+          },
+          {
+            "name":"靖远县",
+            "code":"620421"
+          },
+          {
+            "name":"会宁县",
+            "code":"620422"
+          },
+          {
+            "name":"景泰县",
+            "code":"620423"
+          }
+        ]
+      },
+      {
+        "name":"天水市",
+        "code":"620500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620501"
+          },
+          {
+            "name":"秦州区",
+            "code":"620502"
+          },
+          {
+            "name":"麦积区",
+            "code":"620503"
+          },
+          {
+            "name":"清水县",
+            "code":"620521"
+          },
+          {
+            "name":"秦安县",
+            "code":"620522"
+          },
+          {
+            "name":"甘谷县",
+            "code":"620523"
+          },
+          {
+            "name":"武山县",
+            "code":"620524"
+          },
+          {
+            "name":"张家川回族自治县",
+            "code":"620525"
+          }
+        ]
+      },
+      {
+        "name":"武威市",
+        "code":"620600",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620601"
+          },
+          {
+            "name":"凉州区",
+            "code":"620602"
+          },
+          {
+            "name":"民勤县",
+            "code":"620621"
+          },
+          {
+            "name":"古浪县",
+            "code":"620622"
+          },
+          {
+            "name":"天祝藏族自治县",
+            "code":"620623"
+          }
+        ]
+      },
+      {
+        "name":"张掖市",
+        "code":"620700",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620701"
+          },
+          {
+            "name":"甘州区",
+            "code":"620702"
+          },
+          {
+            "name":"肃南裕固族自治县",
+            "code":"620721"
+          },
+          {
+            "name":"民乐县",
+            "code":"620722"
+          },
+          {
+            "name":"临泽县",
+            "code":"620723"
+          },
+          {
+            "name":"高台县",
+            "code":"620724"
+          },
+          {
+            "name":"山丹县",
+            "code":"620725"
+          }
+        ]
+      },
+      {
+        "name":"平凉市",
+        "code":"620800",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620801"
+          },
+          {
+            "name":"崆峒区",
+            "code":"620802"
+          },
+          {
+            "name":"泾川县",
+            "code":"620821"
+          },
+          {
+            "name":"灵台县",
+            "code":"620822"
+          },
+          {
+            "name":"崇信县",
+            "code":"620823"
+          },
+          {
+            "name":"华亭县",
+            "code":"620824"
+          },
+          {
+            "name":"庄浪县",
+            "code":"620825"
+          },
+          {
+            "name":"静宁县",
+            "code":"620826"
+          }
+        ]
+      },
+      {
+        "name":"酒泉市",
+        "code":"620900",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"620901"
+          },
+          {
+            "name":"肃州区",
+            "code":"620902"
+          },
+          {
+            "name":"金塔县",
+            "code":"620921"
+          },
+          {
+            "name":"瓜州县",
+            "code":"620922"
+          },
+          {
+            "name":"肃北蒙古族自治县",
+            "code":"620923"
+          },
+          {
+            "name":"阿克塞哈萨克族自治县",
+            "code":"620924"
+          },
+          {
+            "name":"玉门市",
+            "code":"620981"
+          },
+          {
+            "name":"敦煌市",
+            "code":"620982"
+          }
+        ]
+      },
+      {
+        "name":"庆阳市",
+        "code":"621000",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621001"
+          },
+          {
+            "name":"西峰区",
+            "code":"621002"
+          },
+          {
+            "name":"庆城县",
+            "code":"621021"
+          },
+          {
+            "name":"环县",
+            "code":"621022"
+          },
+          {
+            "name":"华池县",
+            "code":"621023"
+          },
+          {
+            "name":"合水县",
+            "code":"621024"
+          },
+          {
+            "name":"正宁县",
+            "code":"621025"
+          },
+          {
+            "name":"宁县",
+            "code":"621026"
+          },
+          {
+            "name":"镇原县",
+            "code":"621027"
+          }
+        ]
+      },
+      {
+        "name":"定西市",
+        "code":"621100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621101"
+          },
+          {
+            "name":"安定区",
+            "code":"621102"
+          },
+          {
+            "name":"通渭县",
+            "code":"621121"
+          },
+          {
+            "name":"陇西县",
+            "code":"621122"
+          },
+          {
+            "name":"渭源县",
+            "code":"621123"
+          },
+          {
+            "name":"临洮县",
+            "code":"621124"
+          },
+          {
+            "name":"漳县",
+            "code":"621125"
+          },
+          {
+            "name":"岷县",
+            "code":"621126"
+          }
+        ]
+      },
+      {
+        "name":"陇南市",
+        "code":"621200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"621201"
+          },
+          {
+            "name":"武都区",
+            "code":"621202"
+          },
+          {
+            "name":"成县",
+            "code":"621221"
+          },
+          {
+            "name":"文县",
+            "code":"621222"
+          },
+          {
+            "name":"宕昌县",
+            "code":"621223"
+          },
+          {
+            "name":"康县",
+            "code":"621224"
+          },
+          {
+            "name":"西和县",
+            "code":"621225"
+          },
+          {
+            "name":"礼县",
+            "code":"621226"
+          },
+          {
+            "name":"徽县",
+            "code":"621227"
+          },
+          {
+            "name":"两当县",
+            "code":"621228"
+          }
+        ]
+      },
+      {
+        "name":"临夏回族自治州",
+        "code":"622900",
+        "sub":[
+          {
+            "name":"临夏市",
+            "code":"622901"
+          },
+          {
+            "name":"临夏县",
+            "code":"622921"
+          },
+          {
+            "name":"康乐县",
+            "code":"622922"
+          },
+          {
+            "name":"永靖县",
+            "code":"622923"
+          },
+          {
+            "name":"广河县",
+            "code":"622924"
+          },
+          {
+            "name":"和政县",
+            "code":"622925"
+          },
+          {
+            "name":"东乡族自治县",
+            "code":"622926"
+          },
+          {
+            "name":"积石山保安族东乡族撒拉族自治县",
+            "code":"622927"
+          }
+        ]
+      },
+      {
+        "name":"甘南藏族自治州",
+        "code":"623000",
+        "sub":[
+          {
+            "name":"合作市",
+            "code":"623001"
+          },
+          {
+            "name":"临潭县",
+            "code":"623021"
+          },
+          {
+            "name":"卓尼县",
+            "code":"623022"
+          },
+          {
+            "name":"舟曲县",
+            "code":"623023"
+          },
+          {
+            "name":"迭部县",
+            "code":"623024"
+          },
+          {
+            "name":"玛曲县",
+            "code":"623025"
+          },
+          {
+            "name":"碌曲县",
+            "code":"623026"
+          },
+          {
+            "name":"夏河县",
+            "code":"623027"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"青海省",
+    "code":"630000",
+    "sub":[
+      {
+        "name":"西宁市",
+        "code":"630100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"630101"
+          },
+          {
+            "name":"城东区",
+            "code":"630102"
+          },
+          {
+            "name":"城中区",
+            "code":"630103"
+          },
+          {
+            "name":"城西区",
+            "code":"630104"
+          },
+          {
+            "name":"城北区",
+            "code":"630105"
+          },
+          {
+            "name":"大通回族土族自治县",
+            "code":"630121"
+          },
+          {
+            "name":"湟中县",
+            "code":"630122"
+          },
+          {
+            "name":"湟源县",
+            "code":"630123"
+          }
+        ]
+      },
+      {
+        "name":"海东市",
+        "code":"630200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"630201"
+          },
+          {
+            "name":"乐都区",
+            "code":"630202"
+          },
+          {
+            "name":"平安县",
+            "code":"630221"
+          },
+          {
+            "name":"民和回族土族自治县",
+            "code":"630222"
+          },
+          {
+            "name":"互助土族自治县",
+            "code":"630223"
+          },
+          {
+            "name":"化隆回族自治县",
+            "code":"630224"
+          },
+          {
+            "name":"循化撒拉族自治县",
+            "code":"630225"
+          }
+        ]
+      },
+      {
+        "name":"海北藏族自治州",
+        "code":"632200",
+        "sub":[
+          {
+            "name":"门源回族自治县",
+            "code":"632221"
+          },
+          {
+            "name":"祁连县",
+            "code":"632222"
+          },
+          {
+            "name":"海晏县",
+            "code":"632223"
+          },
+          {
+            "name":"刚察县",
+            "code":"632224"
+          }
+        ]
+      },
+      {
+        "name":"黄南藏族自治州",
+        "code":"632300",
+        "sub":[
+          {
+            "name":"同仁县",
+            "code":"632321"
+          },
+          {
+            "name":"尖扎县",
+            "code":"632322"
+          },
+          {
+            "name":"泽库县",
+            "code":"632323"
+          },
+          {
+            "name":"河南蒙古族自治县",
+            "code":"632324"
+          }
+        ]
+      },
+      {
+        "name":"海南藏族自治州",
+        "code":"632500",
+        "sub":[
+          {
+            "name":"共和县",
+            "code":"632521"
+          },
+          {
+            "name":"同德县",
+            "code":"632522"
+          },
+          {
+            "name":"贵德县",
+            "code":"632523"
+          },
+          {
+            "name":"兴海县",
+            "code":"632524"
+          },
+          {
+            "name":"贵南县",
+            "code":"632525"
+          }
+        ]
+      },
+      {
+        "name":"果洛藏族自治州",
+        "code":"632600",
+        "sub":[
+          {
+            "name":"玛沁县",
+            "code":"632621"
+          },
+          {
+            "name":"班玛县",
+            "code":"632622"
+          },
+          {
+            "name":"甘德县",
+            "code":"632623"
+          },
+          {
+            "name":"达日县",
+            "code":"632624"
+          },
+          {
+            "name":"久治县",
+            "code":"632625"
+          },
+          {
+            "name":"玛多县",
+            "code":"632626"
+          }
+        ]
+      },
+      {
+        "name":"玉树藏族自治州",
+        "code":"632700",
+        "sub":[
+          {
+            "name":"玉树市",
+            "code":"632701"
+          },
+          {
+            "name":"杂多县",
+            "code":"632722"
+          },
+          {
+            "name":"称多县",
+            "code":"632723"
+          },
+          {
+            "name":"治多县",
+            "code":"632724"
+          },
+          {
+            "name":"囊谦县",
+            "code":"632725"
+          },
+          {
+            "name":"曲麻莱县",
+            "code":"632726"
+          }
+        ]
+      },
+      {
+        "name":"海西蒙古族藏族自治州",
+        "code":"632800",
+        "sub":[
+          {
+            "name":"格尔木市",
+            "code":"632801"
+          },
+          {
+            "name":"德令哈市",
+            "code":"632802"
+          },
+          {
+            "name":"乌兰县",
+            "code":"632821"
+          },
+          {
+            "name":"都兰县",
+            "code":"632822"
+          },
+          {
+            "name":"天峻县",
+            "code":"632823"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"宁夏回族自治区",
+    "code":"640000",
+    "sub":[
+      {
+        "name":"银川市",
+        "code":"640100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640101"
+          },
+          {
+            "name":"兴庆区",
+            "code":"640104"
+          },
+          {
+            "name":"西夏区",
+            "code":"640105"
+          },
+          {
+            "name":"金凤区",
+            "code":"640106"
+          },
+          {
+            "name":"永宁县",
+            "code":"640121"
+          },
+          {
+            "name":"贺兰县",
+            "code":"640122"
+          },
+          {
+            "name":"灵武市",
+            "code":"640181"
+          }
+        ]
+      },
+      {
+        "name":"石嘴山市",
+        "code":"640200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640201"
+          },
+          {
+            "name":"大武口区",
+            "code":"640202"
+          },
+          {
+            "name":"惠农区",
+            "code":"640205"
+          },
+          {
+            "name":"平罗县",
+            "code":"640221"
+          }
+        ]
+      },
+      {
+        "name":"吴忠市",
+        "code":"640300",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640301"
+          },
+          {
+            "name":"利通区",
+            "code":"640302"
+          },
+          {
+            "name":"红寺堡区",
+            "code":"640303"
+          },
+          {
+            "name":"盐池县",
+            "code":"640323"
+          },
+          {
+            "name":"同心县",
+            "code":"640324"
+          },
+          {
+            "name":"青铜峡市",
+            "code":"640381"
+          }
+        ]
+      },
+      {
+        "name":"固原市",
+        "code":"640400",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640401"
+          },
+          {
+            "name":"原州区",
+            "code":"640402"
+          },
+          {
+            "name":"西吉县",
+            "code":"640422"
+          },
+          {
+            "name":"隆德县",
+            "code":"640423"
+          },
+          {
+            "name":"泾源县",
+            "code":"640424"
+          },
+          {
+            "name":"彭阳县",
+            "code":"640425"
+          }
+        ]
+      },
+      {
+        "name":"中卫市",
+        "code":"640500",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"640501"
+          },
+          {
+            "name":"沙坡头区",
+            "code":"640502"
+          },
+          {
+            "name":"中宁县",
+            "code":"640521"
+          },
+          {
+            "name":"海原县",
+            "code":"640522"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"新疆维吾尔自治区",
+    "code":"650000",
+    "sub":[
+      {
+        "name":"乌鲁木齐市",
+        "code":"650100",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"650101"
+          },
+          {
+            "name":"天山区",
+            "code":"650102"
+          },
+          {
+            "name":"沙依巴克区",
+            "code":"650103"
+          },
+          {
+            "name":"新市区",
+            "code":"650104"
+          },
+          {
+            "name":"水磨沟区",
+            "code":"650105"
+          },
+          {
+            "name":"头屯河区",
+            "code":"650106"
+          },
+          {
+            "name":"达坂城区",
+            "code":"650107"
+          },
+          {
+            "name":"米东区",
+            "code":"650109"
+          },
+          {
+            "name":"乌鲁木齐县",
+            "code":"650121"
+          }
+        ]
+      },
+      {
+        "name":"克拉玛依市",
+        "code":"650200",
+        "sub":[
+          {
+            "name":"市辖区",
+            "code":"650201"
+          },
+          {
+            "name":"独山子区",
+            "code":"650202"
+          },
+          {
+            "name":"克拉玛依区",
+            "code":"650203"
+          },
+          {
+            "name":"白碱滩区",
+            "code":"650204"
+          },
+          {
+            "name":"乌尔禾区",
+            "code":"650205"
+          }
+        ]
+      },
+      {
+        "name":"吐鲁番地区",
+        "code":"652100",
+        "sub":[
+          {
+            "name":"吐鲁番市",
+            "code":"652101"
+          },
+          {
+            "name":"鄯善县",
+            "code":"652122"
+          },
+          {
+            "name":"托克逊县",
+            "code":"652123"
+          }
+        ]
+      },
+      {
+        "name":"哈密地区",
+        "code":"652200",
+        "sub":[
+          {
+            "name":"哈密市",
+            "code":"652201"
+          },
+          {
+            "name":"巴里坤哈萨克自治县",
+            "code":"652222"
+          },
+          {
+            "name":"伊吾县",
+            "code":"652223"
+          }
+        ]
+      },
+      {
+        "name":"昌吉回族自治州",
+        "code":"652300",
+        "sub":[
+          {
+            "name":"昌吉市",
+            "code":"652301"
+          },
+          {
+            "name":"阜康市",
+            "code":"652302"
+          },
+          {
+            "name":"呼图壁县",
+            "code":"652323"
+          },
+          {
+            "name":"玛纳斯县",
+            "code":"652324"
+          },
+          {
+            "name":"奇台县",
+            "code":"652325"
+          },
+          {
+            "name":"吉木萨尔县",
+            "code":"652327"
+          },
+          {
+            "name":"木垒哈萨克自治县",
+            "code":"652328"
+          }
+        ]
+      },
+      {
+        "name":"博尔塔拉蒙古自治州",
+        "code":"652700",
+        "sub":[
+          {
+            "name":"博乐市",
+            "code":"652701"
+          },
+          {
+            "name":"阿拉山口市",
+            "code":"652702"
+          },
+          {
+            "name":"精河县",
+            "code":"652722"
+          },
+          {
+            "name":"温泉县",
+            "code":"652723"
+          }
+        ]
+      },
+      {
+        "name":"巴音郭楞蒙古自治州",
+        "code":"652800",
+        "sub":[
+          {
+            "name":"库尔勒市",
+            "code":"652801"
+          },
+          {
+            "name":"轮台县",
+            "code":"652822"
+          },
+          {
+            "name":"尉犁县",
+            "code":"652823"
+          },
+          {
+            "name":"若羌县",
+            "code":"652824"
+          },
+          {
+            "name":"且末县",
+            "code":"652825"
+          },
+          {
+            "name":"焉耆回族自治县",
+            "code":"652826"
+          },
+          {
+            "name":"和静县",
+            "code":"652827"
+          },
+          {
+            "name":"和硕县",
+            "code":"652828"
+          },
+          {
+            "name":"博湖县",
+            "code":"652829"
+          }
+        ]
+      },
+      {
+        "name":"阿克苏地区",
+        "code":"652900",
+        "sub":[
+          {
+            "name":"阿克苏市",
+            "code":"652901"
+          },
+          {
+            "name":"温宿县",
+            "code":"652922"
+          },
+          {
+            "name":"库车县",
+            "code":"652923"
+          },
+          {
+            "name":"沙雅县",
+            "code":"652924"
+          },
+          {
+            "name":"新和县",
+            "code":"652925"
+          },
+          {
+            "name":"拜城县",
+            "code":"652926"
+          },
+          {
+            "name":"乌什县",
+            "code":"652927"
+          },
+          {
+            "name":"阿瓦提县",
+            "code":"652928"
+          },
+          {
+            "name":"柯坪县",
+            "code":"652929"
+          }
+        ]
+      },
+      {
+        "name":"克孜勒苏柯尔克孜自治州",
+        "code":"653000",
+        "sub":[
+          {
+            "name":"阿图什市",
+            "code":"653001"
+          },
+          {
+            "name":"阿克陶县",
+            "code":"653022"
+          },
+          {
+            "name":"阿合奇县",
+            "code":"653023"
+          },
+          {
+            "name":"乌恰县",
+            "code":"653024"
+          }
+        ]
+      },
+      {
+        "name":"喀什地区",
+        "code":"653100",
+        "sub":[
+          {
+            "name":"喀什市",
+            "code":"653101"
+          },
+          {
+            "name":"疏附县",
+            "code":"653121"
+          },
+          {
+            "name":"疏勒县",
+            "code":"653122"
+          },
+          {
+            "name":"英吉沙县",
+            "code":"653123"
+          },
+          {
+            "name":"泽普县",
+            "code":"653124"
+          },
+          {
+            "name":"莎车县",
+            "code":"653125"
+          },
+          {
+            "name":"叶城县",
+            "code":"653126"
+          },
+          {
+            "name":"麦盖提县",
+            "code":"653127"
+          },
+          {
+            "name":"岳普湖县",
+            "code":"653128"
+          },
+          {
+            "name":"伽师县",
+            "code":"653129"
+          },
+          {
+            "name":"巴楚县",
+            "code":"653130"
+          },
+          {
+            "name":"塔什库尔干塔吉克自治县",
+            "code":"653131"
+          }
+        ]
+      },
+      {
+        "name":"和田地区",
+        "code":"653200",
+        "sub":[
+          {
+            "name":"和田市",
+            "code":"653201"
+          },
+          {
+            "name":"和田县",
+            "code":"653221"
+          },
+          {
+            "name":"墨玉县",
+            "code":"653222"
+          },
+          {
+            "name":"皮山县",
+            "code":"653223"
+          },
+          {
+            "name":"洛浦县",
+            "code":"653224"
+          },
+          {
+            "name":"策勒县",
+            "code":"653225"
+          },
+          {
+            "name":"于田县",
+            "code":"653226"
+          },
+          {
+            "name":"民丰县",
+            "code":"653227"
+          }
+        ]
+      },
+      {
+        "name":"伊犁哈萨克自治州",
+        "code":"654000",
+        "sub":[
+          {
+            "name":"伊宁市",
+            "code":"654002"
+          },
+          {
+            "name":"奎屯市",
+            "code":"654003"
+          },
+          {
+            "name":"霍尔果斯市",
+            "code":"654004"
+          },
+          {
+            "name":"伊宁县",
+            "code":"654021"
+          },
+          {
+            "name":"察布查尔锡伯自治县",
+            "code":"654022"
+          },
+          {
+            "name":"霍城县",
+            "code":"654023"
+          },
+          {
+            "name":"巩留县",
+            "code":"654024"
+          },
+          {
+            "name":"新源县",
+            "code":"654025"
+          },
+          {
+            "name":"昭苏县",
+            "code":"654026"
+          },
+          {
+            "name":"特克斯县",
+            "code":"654027"
+          },
+          {
+            "name":"尼勒克县",
+            "code":"654028"
+          },
+          {
+            "name":"塔城地区",
+            "code":"654200"
+          },
+          {
+            "name":"塔城市",
+            "code":"654201"
+          },
+          {
+            "name":"乌苏市",
+            "code":"654202"
+          },
+          {
+            "name":"额敏县",
+            "code":"654221"
+          },
+          {
+            "name":"沙湾县",
+            "code":"654223"
+          },
+          {
+            "name":"托里县",
+            "code":"654224"
+          },
+          {
+            "name":"裕民县",
+            "code":"654225"
+          },
+          {
+            "name":"和布克赛尔蒙古自治县",
+            "code":"654226"
+          },
+          {
+            "name":"阿勒泰地区",
+            "code":"654300"
+          },
+          {
+            "name":"阿勒泰市",
+            "code":"654301"
+          },
+          {
+            "name":"布尔津县",
+            "code":"654321"
+          },
+          {
+            "name":"富蕴县",
+            "code":"654322"
+          },
+          {
+            "name":"福海县",
+            "code":"654323"
+          },
+          {
+            "name":"哈巴河县",
+            "code":"654324"
+          },
+          {
+            "name":"青河县",
+            "code":"654325"
+          },
+          {
+            "name":"吉木乃县",
+            "code":"654326"
+          }
+        ]
+      },
+      {
+        "name":"自治区直辖县级行政区划",
+        "code":"659000",
+        "sub":[
+          {
+            "name":"石河子市",
+            "code":"659001"
+          },
+          {
+            "name":"阿拉尔市",
+            "code":"659002"
+          },
+          {
+            "name":"图木舒克市",
+            "code":"659003"
+          },
+          {
+            "name":"五家渠市",
+            "code":"659004"
+          },
+          {
+            "name":"北屯市",
+            "code":"659005"
+          },
+          {
+            "name":"铁门关市",
+            "code":"659006"
+          },
+          {
+            "name":"双河市",
+            "code":"659007"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"台湾省",
+    "code":"710000",
+    "sub":[
+      {
+        "name":"台北市",
+        "code":"710100",
+        "sub":[
+          {
+            "name":"松山区",
+            "code":"710101"
+          },
+          {
+            "name":"信义区",
+            "code":"710102"
+          },
+          {
+            "name":"大安区",
+            "code":"710103"
+          },
+          {
+            "name":"中山区",
+            "code":"710104"
+          },
+          {
+            "name":"中正区",
+            "code":"710105"
+          },
+          {
+            "name":"大同区",
+            "code":"710106"
+          },
+          {
+            "name":"万华区",
+            "code":"710107"
+          },
+          {
+            "name":"文山区",
+            "code":"710108"
+          },
+          {
+            "name":"南港区",
+            "code":"710109"
+          },
+          {
+            "name":"内湖区",
+            "code":"710110"
+          },
+          {
+            "name":"士林区",
+            "code":"710111"
+          },
+          {
+            "name":"北投区",
+            "code":"710112"
+          }
+        ]
+      },
+      {
+        "name":"高雄市",
+        "code":"710200",
+        "sub":[
+          {
+            "name":"盐埕区",
+            "code":"710201"
+          },
+          {
+            "name":"鼓山区",
+            "code":"710202"
+          },
+          {
+            "name":"左营区",
+            "code":"710203"
+          },
+          {
+            "name":"楠梓区",
+            "code":"710204"
+          },
+          {
+            "name":"三民区",
+            "code":"710205"
+          },
+          {
+            "name":"新兴区",
+            "code":"710206"
+          },
+          {
+            "name":"前金区",
+            "code":"710207"
+          },
+          {
+            "name":"苓雅区",
+            "code":"710208"
+          },
+          {
+            "name":"前镇区",
+            "code":"710209"
+          },
+          {
+            "name":"旗津区",
+            "code":"710210"
+          },
+          {
+            "name":"小港区",
+            "code":"710211"
+          },
+          {
+            "name":"凤山区",
+            "code":"710212"
+          },
+          {
+            "name":"林园区",
+            "code":"710213"
+          },
+          {
+            "name":"大寮区",
+            "code":"710214"
+          },
+          {
+            "name":"大树区",
+            "code":"710215"
+          },
+          {
+            "name":"大社区",
+            "code":"710216"
+          },
+          {
+            "name":"仁武区",
+            "code":"710217"
+          },
+          {
+            "name":"鸟松区",
+            "code":"710218"
+          },
+          {
+            "name":"冈山区",
+            "code":"710219"
+          },
+          {
+            "name":"桥头区",
+            "code":"710220"
+          },
+          {
+            "name":"燕巢区",
+            "code":"710221"
+          },
+          {
+            "name":"田寮区",
+            "code":"710222"
+          },
+          {
+            "name":"阿莲区",
+            "code":"710223"
+          },
+          {
+            "name":"路竹区",
+            "code":"710224"
+          },
+          {
+            "name":"湖内区",
+            "code":"710225"
+          },
+          {
+            "name":"茄萣区",
+            "code":"710226"
+          },
+          {
+            "name":"永安区",
+            "code":"710227"
+          },
+          {
+            "name":"弥陀区",
+            "code":"710228"
+          },
+          {
+            "name":"梓官区",
+            "code":"710229"
+          },
+          {
+            "name":"旗山区",
+            "code":"710230"
+          },
+          {
+            "name":"美浓区",
+            "code":"710231"
+          },
+          {
+            "name":"六龟区",
+            "code":"710232"
+          },
+          {
+            "name":"甲仙区",
+            "code":"710233"
+          },
+          {
+            "name":"杉林区",
+            "code":"710234"
+          },
+          {
+            "name":"内门区",
+            "code":"710235"
+          },
+          {
+            "name":"茂林区",
+            "code":"710236"
+          },
+          {
+            "name":"桃源区",
+            "code":"710237"
+          },
+          {
+            "name":"那玛夏区",
+            "code":"710238"
+          }
+        ]
+      },
+      {
+        "name":"基隆市",
+        "code":"710300",
+        "sub":[
+          {
+            "name":"中正区",
+            "code":"710301"
+          },
+          {
+            "name":"七堵区",
+            "code":"710302"
+          },
+          {
+            "name":"暖暖区",
+            "code":"710303"
+          },
+          {
+            "name":"仁爱区",
+            "code":"710304"
+          },
+          {
+            "name":"中山区",
+            "code":"710305"
+          },
+          {
+            "name":"安乐区",
+            "code":"710306"
+          },
+          {
+            "name":"信义区",
+            "code":"710307"
+          }
+        ]
+      },
+      {
+        "name":"台中市",
+        "code":"710400",
+        "sub":[
+          {
+            "name":"中区",
+            "code":"710401"
+          },
+          {
+            "name":"东区",
+            "code":"710402"
+          },
+          {
+            "name":"南区",
+            "code":"710403"
+          },
+          {
+            "name":"西区",
+            "code":"710404"
+          },
+          {
+            "name":"北区",
+            "code":"710405"
+          },
+          {
+            "name":"西屯区",
+            "code":"710406"
+          },
+          {
+            "name":"南屯区",
+            "code":"710407"
+          },
+          {
+            "name":"北屯区",
+            "code":"710408"
+          },
+          {
+            "name":"丰原区",
+            "code":"710409"
+          },
+          {
+            "name":"东势区",
+            "code":"710410"
+          },
+          {
+            "name":"大甲区",
+            "code":"710411"
+          },
+          {
+            "name":"清水区",
+            "code":"710412"
+          },
+          {
+            "name":"沙鹿区",
+            "code":"710413"
+          },
+          {
+            "name":"梧栖区",
+            "code":"710414"
+          },
+          {
+            "name":"后里区",
+            "code":"710415"
+          },
+          {
+            "name":"神冈区",
+            "code":"710416"
+          },
+          {
+            "name":"潭子区",
+            "code":"710417"
+          },
+          {
+            "name":"大雅区",
+            "code":"710418"
+          },
+          {
+            "name":"新社区",
+            "code":"710419"
+          },
+          {
+            "name":"石冈区",
+            "code":"710420"
+          },
+          {
+            "name":"外埔区",
+            "code":"710421"
+          },
+          {
+            "name":"大安区",
+            "code":"710422"
+          },
+          {
+            "name":"乌日区",
+            "code":"710423"
+          },
+          {
+            "name":"大肚区",
+            "code":"710424"
+          },
+          {
+            "name":"龙井区",
+            "code":"710425"
+          },
+          {
+            "name":"雾峰区",
+            "code":"710426"
+          },
+          {
+            "name":"太平区",
+            "code":"710427"
+          },
+          {
+            "name":"大里区",
+            "code":"710428"
+          },
+          {
+            "name":"和平区",
+            "code":"710429"
+          }
+        ]
+      },
+      {
+        "name":"台南市",
+        "code":"710500",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710501"
+          },
+          {
+            "name":"南区",
+            "code":"710502"
+          },
+          {
+            "name":"北区",
+            "code":"710504"
+          },
+          {
+            "name":"安南区",
+            "code":"710506"
+          },
+          {
+            "name":"安平区",
+            "code":"710507"
+          },
+          {
+            "name":"中西区",
+            "code":"710508"
+          },
+          {
+            "name":"新营区",
+            "code":"710509"
+          },
+          {
+            "name":"盐水区",
+            "code":"710510"
+          },
+          {
+            "name":"白河区",
+            "code":"710511"
+          },
+          {
+            "name":"柳营区",
+            "code":"710512"
+          },
+          {
+            "name":"后壁区",
+            "code":"710513"
+          },
+          {
+            "name":"东山区",
+            "code":"710514"
+          },
+          {
+            "name":"麻豆区",
+            "code":"710515"
+          },
+          {
+            "name":"下营区",
+            "code":"710516"
+          },
+          {
+            "name":"六甲区",
+            "code":"710517"
+          },
+          {
+            "name":"官田区",
+            "code":"710518"
+          },
+          {
+            "name":"大内区",
+            "code":"710519"
+          },
+          {
+            "name":"佳里区",
+            "code":"710520"
+          },
+          {
+            "name":"学甲区",
+            "code":"710521"
+          },
+          {
+            "name":"西港区",
+            "code":"710522"
+          },
+          {
+            "name":"七股区",
+            "code":"710523"
+          },
+          {
+            "name":"将军区",
+            "code":"710524"
+          },
+          {
+            "name":"北门区",
+            "code":"710525"
+          },
+          {
+            "name":"新化区",
+            "code":"710526"
+          },
+          {
+            "name":"善化区",
+            "code":"710527"
+          },
+          {
+            "name":"新市区",
+            "code":"710528"
+          },
+          {
+            "name":"安定区",
+            "code":"710529"
+          },
+          {
+            "name":"山上区",
+            "code":"710530"
+          },
+          {
+            "name":"玉井区",
+            "code":"710531"
+          },
+          {
+            "name":"楠西区",
+            "code":"710532"
+          },
+          {
+            "name":"南化区",
+            "code":"710533"
+          },
+          {
+            "name":"左镇区",
+            "code":"710534"
+          },
+          {
+            "name":"仁德区",
+            "code":"710535"
+          },
+          {
+            "name":"归仁区",
+            "code":"710536"
+          },
+          {
+            "name":"关庙区",
+            "code":"710537"
+          },
+          {
+            "name":"龙崎区",
+            "code":"710538"
+          },
+          {
+            "name":"永康区",
+            "code":"710539"
+          }
+        ]
+      },
+      {
+        "name":"新竹市",
+        "code":"710600",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710601"
+          },
+          {
+            "name":"北区",
+            "code":"710602"
+          },
+          {
+            "name":"香山区",
+            "code":"710603"
+          }
+        ]
+      },
+      {
+        "name":"嘉义市",
+        "code":"710700",
+        "sub":[
+          {
+            "name":"东区",
+            "code":"710701"
+          },
+          {
+            "name":"西区",
+            "code":"710702"
+          }
+        ]
+      },
+      {
+        "name":"新北市",
+        "code":"710800",
+        "sub":[
+          {
+            "name":"板桥区",
+            "code":"710801"
+          },
+          {
+            "name":"三重区",
+            "code":"710802"
+          },
+          {
+            "name":"中和区",
+            "code":"710803"
+          },
+          {
+            "name":"永和区",
+            "code":"710804"
+          },
+          {
+            "name":"新庄区",
+            "code":"710805"
+          },
+          {
+            "name":"新店区",
+            "code":"710806"
+          },
+          {
+            "name":"树林区",
+            "code":"710807"
+          },
+          {
+            "name":"莺歌区",
+            "code":"710808"
+          },
+          {
+            "name":"三峡区",
+            "code":"710809"
+          },
+          {
+            "name":"淡水区",
+            "code":"710810"
+          },
+          {
+            "name":"汐止区",
+            "code":"710811"
+          },
+          {
+            "name":"瑞芳区",
+            "code":"710812"
+          },
+          {
+            "name":"土城区",
+            "code":"710813"
+          },
+          {
+            "name":"芦洲区",
+            "code":"710814"
+          },
+          {
+            "name":"五股区",
+            "code":"710815"
+          },
+          {
+            "name":"泰山区",
+            "code":"710816"
+          },
+          {
+            "name":"林口区",
+            "code":"710817"
+          },
+          {
+            "name":"深坑区",
+            "code":"710818"
+          },
+          {
+            "name":"石碇区",
+            "code":"710819"
+          },
+          {
+            "name":"坪林区",
+            "code":"710820"
+          },
+          {
+            "name":"三芝区",
+            "code":"710821"
+          },
+          {
+            "name":"石门区",
+            "code":"710822"
+          },
+          {
+            "name":"八里区",
+            "code":"710823"
+          },
+          {
+            "name":"平溪区",
+            "code":"710824"
+          },
+          {
+            "name":"双溪区",
+            "code":"710825"
+          },
+          {
+            "name":"贡寮区",
+            "code":"710826"
+          },
+          {
+            "name":"金山区",
+            "code":"710827"
+          },
+          {
+            "name":"万里区",
+            "code":"710828"
+          },
+          {
+            "name":"乌来区",
+            "code":"710829"
+          }
+        ]
+      },
+      {
+        "name":"宜兰县",
+        "code":"712200",
+        "sub":[
+          {
+            "name":"宜兰市",
+            "code":"712201"
+          },
+          {
+            "name":"罗东镇",
+            "code":"712221"
+          },
+          {
+            "name":"苏澳镇",
+            "code":"712222"
+          },
+          {
+            "name":"头城镇",
+            "code":"712223"
+          },
+          {
+            "name":"礁溪乡",
+            "code":"712224"
+          },
+          {
+            "name":"壮围乡",
+            "code":"712225"
+          },
+          {
+            "name":"员山乡",
+            "code":"712226"
+          },
+          {
+            "name":"冬山乡",
+            "code":"712227"
+          },
+          {
+            "name":"五结乡",
+            "code":"712228"
+          },
+          {
+            "name":"三星乡",
+            "code":"712229"
+          },
+          {
+            "name":"大同乡",
+            "code":"712230"
+          },
+          {
+            "name":"南澳乡",
+            "code":"712231"
+          }
+        ]
+      },
+      {
+        "name":"桃园县",
+        "code":"712300",
+        "sub":[
+          {
+            "name":"桃园市",
+            "code":"712301"
+          },
+          {
+            "name":"中坜市",
+            "code":"712302"
+          },
+          {
+            "name":"平镇市",
+            "code":"712303"
+          },
+          {
+            "name":"八德市",
+            "code":"712304"
+          },
+          {
+            "name":"杨梅市",
+            "code":"712305"
+          },
+          {
+            "name":"大溪镇",
+            "code":"712321"
+          },
+          {
+            "name":"芦竹乡",
+            "code":"712323"
+          },
+          {
+            "name":"大园乡",
+            "code":"712324"
+          },
+          {
+            "name":"龟山乡",
+            "code":"712325"
+          },
+          {
+            "name":"龙潭乡",
+            "code":"712327"
+          },
+          {
+            "name":"新屋乡",
+            "code":"712329"
+          },
+          {
+            "name":"观音乡",
+            "code":"712330"
+          },
+          {
+            "name":"复兴乡",
+            "code":"712331"
+          }
+        ]
+      },
+      {
+        "name":"新竹县",
+        "code":"712400",
+        "sub":[
+          {
+            "name":"竹北市",
+            "code":"712401"
+          },
+          {
+            "name":"竹东镇",
+            "code":"712421"
+          },
+          {
+            "name":"新埔镇",
+            "code":"712422"
+          },
+          {
+            "name":"关西镇",
+            "code":"712423"
+          },
+          {
+            "name":"湖口乡",
+            "code":"712424"
+          },
+          {
+            "name":"新丰乡",
+            "code":"712425"
+          },
+          {
+            "name":"芎林乡",
+            "code":"712426"
+          },
+          {
+            "name":"橫山乡",
+            "code":"712427"
+          },
+          {
+            "name":"北埔乡",
+            "code":"712428"
+          },
+          {
+            "name":"宝山乡",
+            "code":"712429"
+          },
+          {
+            "name":"峨眉乡",
+            "code":"712430"
+          },
+          {
+            "name":"尖石乡",
+            "code":"712431"
+          },
+          {
+            "name":"五峰乡",
+            "code":"712432"
+          }
+        ]
+      },
+      {
+        "name":"苗栗县",
+        "code":"712500",
+        "sub":[
+          {
+            "name":"苗栗市",
+            "code":"712501"
+          },
+          {
+            "name":"苑里镇",
+            "code":"712521"
+          },
+          {
+            "name":"通霄镇",
+            "code":"712522"
+          },
+          {
+            "name":"竹南镇",
+            "code":"712523"
+          },
+          {
+            "name":"头份镇",
+            "code":"712524"
+          },
+          {
+            "name":"后龙镇",
+            "code":"712525"
+          },
+          {
+            "name":"卓兰镇",
+            "code":"712526"
+          },
+          {
+            "name":"大湖乡",
+            "code":"712527"
+          },
+          {
+            "name":"公馆乡",
+            "code":"712528"
+          },
+          {
+            "name":"铜锣乡",
+            "code":"712529"
+          },
+          {
+            "name":"南庄乡",
+            "code":"712530"
+          },
+          {
+            "name":"头屋乡",
+            "code":"712531"
+          },
+          {
+            "name":"三义乡",
+            "code":"712532"
+          },
+          {
+            "name":"西湖乡",
+            "code":"712533"
+          },
+          {
+            "name":"造桥乡",
+            "code":"712534"
+          },
+          {
+            "name":"三湾乡",
+            "code":"712535"
+          },
+          {
+            "name":"狮潭乡",
+            "code":"712536"
+          },
+          {
+            "name":"泰安乡",
+            "code":"712537"
+          }
+        ]
+      },
+      {
+        "name":"彰化县",
+        "code":"712700",
+        "sub":[
+          {
+            "name":"彰化市",
+            "code":"712701"
+          },
+          {
+            "name":"鹿港镇",
+            "code":"712721"
+          },
+          {
+            "name":"和美镇",
+            "code":"712722"
+          },
+          {
+            "name":"线西乡",
+            "code":"712723"
+          },
+          {
+            "name":"伸港乡",
+            "code":"712724"
+          },
+          {
+            "name":"福兴乡",
+            "code":"712725"
+          },
+          {
+            "name":"秀水乡",
+            "code":"712726"
+          },
+          {
+            "name":"花坛乡",
+            "code":"712727"
+          },
+          {
+            "name":"芬园乡",
+            "code":"712728"
+          },
+          {
+            "name":"员林镇",
+            "code":"712729"
+          },
+          {
+            "name":"溪湖镇",
+            "code":"712730"
+          },
+          {
+            "name":"田中镇",
+            "code":"712731"
+          },
+          {
+            "name":"大村乡",
+            "code":"712732"
+          },
+          {
+            "name":"埔盐乡",
+            "code":"712733"
+          },
+          {
+            "name":"埔心乡",
+            "code":"712734"
+          },
+          {
+            "name":"永靖乡",
+            "code":"712735"
+          },
+          {
+            "name":"社头乡",
+            "code":"712736"
+          },
+          {
+            "name":"二水乡",
+            "code":"712737"
+          },
+          {
+            "name":"北斗镇",
+            "code":"712738"
+          },
+          {
+            "name":"二林镇",
+            "code":"712739"
+          },
+          {
+            "name":"田尾乡",
+            "code":"712740"
+          },
+          {
+            "name":"埤头乡",
+            "code":"712741"
+          },
+          {
+            "name":"芳苑乡",
+            "code":"712742"
+          },
+          {
+            "name":"大城乡",
+            "code":"712743"
+          },
+          {
+            "name":"竹塘乡",
+            "code":"712744"
+          },
+          {
+            "name":"溪州乡",
+            "code":"712745"
+          }
+        ]
+      },
+      {
+        "name":"南投县",
+        "code":"712800",
+        "sub":[
+          {
+            "name":"南投市",
+            "code":"712801"
+          },
+          {
+            "name":"埔里镇",
+            "code":"712821"
+          },
+          {
+            "name":"草屯镇",
+            "code":"712822"
+          },
+          {
+            "name":"竹山镇",
+            "code":"712823"
+          },
+          {
+            "name":"集集镇",
+            "code":"712824"
+          },
+          {
+            "name":"名间乡",
+            "code":"712825"
+          },
+          {
+            "name":"鹿谷乡",
+            "code":"712826"
+          },
+          {
+            "name":"中寮乡",
+            "code":"712827"
+          },
+          {
+            "name":"鱼池乡",
+            "code":"712828"
+          },
+          {
+            "name":"国姓乡",
+            "code":"712829"
+          },
+          {
+            "name":"水里乡",
+            "code":"712830"
+          },
+          {
+            "name":"信义乡",
+            "code":"712831"
+          },
+          {
+            "name":"仁爱乡",
+            "code":"712832"
+          }
+        ]
+      },
+      {
+        "name":"云林县",
+        "code":"712900",
+        "sub":[
+          {
+            "name":"斗六市",
+            "code":"712901"
+          },
+          {
+            "name":"斗南镇",
+            "code":"712921"
+          },
+          {
+            "name":"虎尾镇",
+            "code":"712922"
+          },
+          {
+            "name":"西螺镇",
+            "code":"712923"
+          },
+          {
+            "name":"土库镇",
+            "code":"712924"
+          },
+          {
+            "name":"北港镇",
+            "code":"712925"
+          },
+          {
+            "name":"古坑乡",
+            "code":"712926"
+          },
+          {
+            "name":"大埤乡",
+            "code":"712927"
+          },
+          {
+            "name":"莿桐乡",
+            "code":"712928"
+          },
+          {
+            "name":"林内乡",
+            "code":"712929"
+          },
+          {
+            "name":"二仑乡",
+            "code":"712930"
+          },
+          {
+            "name":"仑背乡",
+            "code":"712931"
+          },
+          {
+            "name":"麦寮乡",
+            "code":"712932"
+          },
+          {
+            "name":"东势乡",
+            "code":"712933"
+          },
+          {
+            "name":"褒忠乡",
+            "code":"712934"
+          },
+          {
+            "name":"台西乡",
+            "code":"712935"
+          },
+          {
+            "name":"元长乡",
+            "code":"712936"
+          },
+          {
+            "name":"四湖乡",
+            "code":"712937"
+          },
+          {
+            "name":"口湖乡",
+            "code":"712938"
+          },
+          {
+            "name":"水林乡",
+            "code":"712939"
+          }
+        ]
+      },
+      {
+        "name":"嘉义县",
+        "code":"713000",
+        "sub":[
+          {
+            "name":"太保市",
+            "code":"713001"
+          },
+          {
+            "name":"朴子市",
+            "code":"713002"
+          },
+          {
+            "name":"布袋镇",
+            "code":"713023"
+          },
+          {
+            "name":"大林镇",
+            "code":"713024"
+          },
+          {
+            "name":"民雄乡",
+            "code":"713025"
+          },
+          {
+            "name":"溪口乡",
+            "code":"713026"
+          },
+          {
+            "name":"新港乡",
+            "code":"713027"
+          },
+          {
+            "name":"六脚乡",
+            "code":"713028"
+          },
+          {
+            "name":"东石乡",
+            "code":"713029"
+          },
+          {
+            "name":"义竹乡",
+            "code":"713030"
+          },
+          {
+            "name":"鹿草乡",
+            "code":"713031"
+          },
+          {
+            "name":"水上乡",
+            "code":"713032"
+          },
+          {
+            "name":"中埔乡",
+            "code":"713033"
+          },
+          {
+            "name":"竹崎乡",
+            "code":"713034"
+          },
+          {
+            "name":"梅山乡",
+            "code":"713035"
+          },
+          {
+            "name":"番路乡",
+            "code":"713036"
+          },
+          {
+            "name":"大埔乡",
+            "code":"713037"
+          },
+          {
+            "name":"阿里山乡",
+            "code":"713038"
+          }
+        ]
+      },
+      {
+        "name":"屏东县",
+        "code":"713300",
+        "sub":[
+          {
+            "name":"屏东市",
+            "code":"713301"
+          },
+          {
+            "name":"潮州镇",
+            "code":"713321"
+          },
+          {
+            "name":"东港镇",
+            "code":"713322"
+          },
+          {
+            "name":"恒春镇",
+            "code":"713323"
+          },
+          {
+            "name":"万丹乡",
+            "code":"713324"
+          },
+          {
+            "name":"长治乡",
+            "code":"713325"
+          },
+          {
+            "name":"麟洛乡",
+            "code":"713326"
+          },
+          {
+            "name":"九如乡",
+            "code":"713327"
+          },
+          {
+            "name":"里港乡",
+            "code":"713328"
+          },
+          {
+            "name":"盐埔乡",
+            "code":"713329"
+          },
+          {
+            "name":"高树乡",
+            "code":"713330"
+          },
+          {
+            "name":"万峦乡",
+            "code":"713331"
+          },
+          {
+            "name":"内埔乡",
+            "code":"713332"
+          },
+          {
+            "name":"竹田乡",
+            "code":"713333"
+          },
+          {
+            "name":"新埤乡",
+            "code":"713334"
+          },
+          {
+            "name":"枋寮乡",
+            "code":"713335"
+          },
+          {
+            "name":"新园乡",
+            "code":"713336"
+          },
+          {
+            "name":"崁顶乡",
+            "code":"713337"
+          },
+          {
+            "name":"林边乡",
+            "code":"713338"
+          },
+          {
+            "name":"南州乡",
+            "code":"713339"
+          },
+          {
+            "name":"佳冬乡",
+            "code":"713340"
+          },
+          {
+            "name":"琉球乡",
+            "code":"713341"
+          },
+          {
+            "name":"车城乡",
+            "code":"713342"
+          },
+          {
+            "name":"满州乡",
+            "code":"713343"
+          },
+          {
+            "name":"枋山乡",
+            "code":"713344"
+          },
+          {
+            "name":"三地门乡",
+            "code":"713345"
+          },
+          {
+            "name":"雾台乡",
+            "code":"713346"
+          },
+          {
+            "name":"玛家乡",
+            "code":"713347"
+          },
+          {
+            "name":"泰武乡",
+            "code":"713348"
+          },
+          {
+            "name":"来义乡",
+            "code":"713349"
+          },
+          {
+            "name":"春日乡",
+            "code":"713350"
+          },
+          {
+            "name":"狮子乡",
+            "code":"713351"
+          },
+          {
+            "name":"牡丹乡",
+            "code":"713352"
+          }
+        ]
+      },
+      {
+        "name":"台东县",
+        "code":"713400",
+        "sub":[
+          {
+            "name":"台东市",
+            "code":"713401"
+          },
+          {
+            "name":"成功镇",
+            "code":"713421"
+          },
+          {
+            "name":"关山镇",
+            "code":"713422"
+          },
+          {
+            "name":"卑南乡",
+            "code":"713423"
+          },
+          {
+            "name":"鹿野乡",
+            "code":"713424"
+          },
+          {
+            "name":"池上乡",
+            "code":"713425"
+          },
+          {
+            "name":"东河乡",
+            "code":"713426"
+          },
+          {
+            "name":"长滨乡",
+            "code":"713427"
+          },
+          {
+            "name":"太麻里乡",
+            "code":"713428"
+          },
+          {
+            "name":"大武乡",
+            "code":"713429"
+          },
+          {
+            "name":"绿岛乡",
+            "code":"713430"
+          },
+          {
+            "name":"海端乡",
+            "code":"713431"
+          },
+          {
+            "name":"延平乡",
+            "code":"713432"
+          },
+          {
+            "name":"金峰乡",
+            "code":"713433"
+          },
+          {
+            "name":"达仁乡",
+            "code":"713434"
+          },
+          {
+            "name":"兰屿乡",
+            "code":"713435"
+          }
+        ]
+      },
+      {
+        "name":"花莲县",
+        "code":"713500",
+        "sub":[
+          {
+            "name":"花莲市",
+            "code":"713501"
+          },
+          {
+            "name":"凤林镇",
+            "code":"713521"
+          },
+          {
+            "name":"玉里镇",
+            "code":"713522"
+          },
+          {
+            "name":"新城乡",
+            "code":"713523"
+          },
+          {
+            "name":"吉安乡",
+            "code":"713524"
+          },
+          {
+            "name":"寿丰乡",
+            "code":"713525"
+          },
+          {
+            "name":"光复乡",
+            "code":"713526"
+          },
+          {
+            "name":"丰滨乡",
+            "code":"713527"
+          },
+          {
+            "name":"瑞穗乡",
+            "code":"713528"
+          },
+          {
+            "name":"富里乡",
+            "code":"713529"
+          },
+          {
+            "name":"秀林乡",
+            "code":"713530"
+          },
+          {
+            "name":"万荣乡",
+            "code":"713531"
+          },
+          {
+            "name":"卓溪乡",
+            "code":"713532"
+          }
+        ]
+      },
+      {
+        "name":"澎湖县",
+        "code":"713600",
+        "sub":[
+          {
+            "name":"马公市",
+            "code":"713601"
+          },
+          {
+            "name":"湖西乡",
+            "code":"713621"
+          },
+          {
+            "name":"白沙乡",
+            "code":"713622"
+          },
+          {
+            "name":"西屿乡",
+            "code":"713623"
+          },
+          {
+            "name":"望安乡",
+            "code":"713624"
+          },
+          {
+            "name":"七美乡",
+            "code":"713625"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"香港特别行政区",
+    "code":"810000",
+    "sub":[
+      {
+        "name":"香港岛",
+        "code":"810100",
+        "sub":[
+          {
+            "name":"中西区",
+            "code":"810101"
+          },
+          {
+            "name":"湾仔区",
+            "code":"810102"
+          },
+          {
+            "name":"东区",
+            "code":"810103"
+          },
+          {
+            "name":"南区",
+            "code":"810104"
+          }
+        ]
+      },
+      {
+        "name":"九龙",
+        "code":"810200",
+        "sub":[
+          {
+            "name":"油尖旺区",
+            "code":"810201"
+          },
+          {
+            "name":"深水埗区",
+            "code":"810202"
+          },
+          {
+            "name":"九龙城区",
+            "code":"810203"
+          },
+          {
+            "name":"黄大仙区",
+            "code":"810204"
+          },
+          {
+            "name":"观塘区",
+            "code":"810205"
+          }
+        ]
+      },
+      {
+        "name":"新界",
+        "code":"810300",
+        "sub":[
+          {
+            "name":"荃湾区",
+            "code":"810301"
+          },
+          {
+            "name":"屯门区",
+            "code":"810302"
+          },
+          {
+            "name":"元朗区",
+            "code":"810303"
+          },
+          {
+            "name":"北区",
+            "code":"810304"
+          },
+          {
+            "name":"大埔区",
+            "code":"810305"
+          },
+          {
+            "name":"西贡区",
+            "code":"810306"
+          },
+          {
+            "name":"沙田区",
+            "code":"810307"
+          },
+          {
+            "name":"葵青区",
+            "code":"810308"
+          },
+          {
+            "name":"离岛区",
+            "code":"810309"
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "name":"澳门特别行政区",
+    "code":"820000",
+    "sub":[
+      {
+        "name":"澳门半岛",
+        "code":"820100",
+        "sub":[
+          {
+            "name":"花地玛堂区",
+            "code":"820101"
+          },
+          {
+            "name":"圣安多尼堂区",
+            "code":"820102"
+          },
+          {
+            "name":"大堂区",
+            "code":"820103"
+          },
+          {
+            "name":"望德堂区",
+            "code":"820104"
+          },
+          {
+            "name":"风顺堂区",
+            "code":"820105"
+          }
+        ]
+      },
+      {
+        "name":"氹仔岛",
+        "code":"820200",
+        "sub":[
+          {
+            "name":"嘉模堂区",
+            "code":"820201"
+          }
+        ]
+      },
+      {
+        "name":"路环岛",
+        "code":"820300",
+        "sub":[
+          {
+            "name":"圣方济各堂区",
+            "code":"820301"
+          }
+        ]
+      }
+    ]
+  }
+
+];
+}($);
+// jshint ignore: end
+
+/* global $:true */
+/* jshint unused:false*/
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  var raw = $.rawCitiesData;
+
+  var format = function(data) {
+    var result = [];
+    for(var i=0;i<data.length;i++) {
+      var d = data[i];
+      if(/^请选择|市辖区/.test(d.name)) continue;
+      result.push(d);
+    }
+    if(result.length) return result;
+    return [];
+  };
+
+  var sub = function(data) {
+    if(!data.sub) return [{ name: '', code: data.code }];  // 有可能某些县级市没有区
+    return format(data.sub);
+  };
+
+  var getCities = function(d) {
+    for(var i=0;i< raw.length;i++) {
+      if(raw[i].code === d || raw[i].name === d) return sub(raw[i]);
+    }
+    return [];
+  };
+
+  var getDistricts = function(p, c) {
+    for(var i=0;i< raw.length;i++) {
+      if(raw[i].code === p || raw[i].name === p) {
+        for(var j=0;j< raw[i].sub.length;j++) {
+          if(raw[i].sub[j].code === c || raw[i].sub[j].name === c) {
+            return sub(raw[i].sub[j]);
+          }
+        }
+      }
+    }
+  };
+
+  var parseInitValue = function (val) {
+    var p = raw[0], c, d;
+    var tokens = val.split(' ');
+    raw.map(function (t) {
+      if (t.name === tokens[0]) p = t;
+    });
+
+    p.sub.map(function (t) {
+      if (t.name === tokens[1]) c = t;
+    })
+
+    if (tokens[2]) {
+      c.sub.map(function (t) {
+        if (t.name === tokens[2]) d = t;
+      })
+    }
+
+    if (d) return [p.code, c.code, d.code];
+    return [p.code, c.code];
+  }
+
+  $.fn.cityPicker = function(params) {
+    params = $.extend({}, defaults, params);
+    return this.each(function() {
+      var self = this;
+      
+      var provincesName = raw.map(function(d) {
+        return d.name;
+      });
+      var provincesCode = raw.map(function(d) {
+        return d.code;
+      });
+      var initCities = sub(raw[0]);
+      var initCitiesName = initCities.map(function (c) {
+        return c.name;
+      });
+      var initCitiesCode = initCities.map(function (c) {
+        return c.code;
+      });
+      var initDistricts = sub(raw[0].sub[0]);
+
+      var initDistrictsName = initDistricts.map(function (c) {
+        return c.name;
+      });
+      var initDistrictsCode = initDistricts.map(function (c) {
+        return c.code;
+      });
+
+      var currentProvince = provincesName[0];
+      var currentCity = initCitiesName[0];
+      var currentDistrict = initDistrictsName[0];
+
+      var cols = [
+          {
+            displayValues: provincesName,
+            values: provincesCode,
+            cssClass: "col-province"
+          },
+          {
+            displayValues: initCitiesName,
+            values: initCitiesCode,
+            cssClass: "col-city"
+          }
+        ];
+
+        if(params.showDistrict) cols.push({
+          values: initDistrictsCode,
+          displayValues: initDistrictsName,
+          cssClass: "col-district"
+        });
+
+      var config = {
+
+        cssClass: "city-picker",
+        rotateEffect: false,  //为了性能
+        formatValue: function (p, values, displayValues) {
+          return displayValues.join(' ');
+        },
+        onChange: function (picker, values, displayValues) {
+          var newProvince = picker.cols[0].displayValue;
+          var newCity;
+          if(newProvince !== currentProvince) {
+            var newCities = getCities(newProvince);
+            newCity = newCities[0].name;
+            var newDistricts = getDistricts(newProvince, newCity);
+            picker.cols[1].replaceValues(newCities.map(function (c) {
+              return c.code;
+            }), newCities.map(function (c) {
+              return c.name;
+            }));
+            if(params.showDistrict) picker.cols[2].replaceValues(newDistricts.map(function (d) {
+              return d.code;
+            }), newDistricts.map(function (d) {
+              return d.name;
+            }));
+            currentProvince = newProvince;
+            currentCity = newCity;
+            picker.updateValue();
+            return false; // 因为数据未更新完,所以这里不进行后序的值的处理
+          } else {
+            if(params.showDistrict) {
+              newCity = picker.cols[1].displayValue;
+              if(newCity !== currentCity) {
+                var districts = getDistricts(newProvince, newCity);
+                picker.cols[2].replaceValues(districts.map(function (d) {
+                  return d.code;
+                }), districts.map(function (d) {
+                  return d.name;
+                }));
+                currentCity = newCity;
+                picker.updateValue();
+                return false; // 因为数据未更新完,所以这里不进行后序的值的处理
+              }
+            }
+          }
+          //如果最后一列是空的,那么取倒数第二列
+          var len = (values[values.length-1] ? values.length - 1 : values.length - 2)
+          $(self).attr('data-code', values[len]);
+          $(self).attr('data-codes', values.join(','));
+          if (params.onChange) {
+            params.onChange.call(self, picker, values, displayValues);
+          }
+        },
+
+        cols: cols
+      };
+
+      if(!this) return;
+      var p = $.extend({}, params, config);
+      //计算value
+      var val = $(this).val();
+      if (!val) val = '北京 北京市 东城区';
+      currentProvince = val.split(" ")[0];
+      currentCity = val.split(" ")[1];
+      currentDistrict= val.split(" ")[2];
+      if(val) {
+        p.value = parseInitValue(val);
+        if(p.value[0]) {
+          var cities = getCities(p.value[0]);
+          p.cols[1].values = cities.map(function (c) {
+            return c.code;
+          });
+          p.cols[1].displayValues = cities.map(function (c) {
+            return c.name;
+          });
+        }
+
+        if(p.value[1]) {
+          if (params.showDistrict) {
+            var dis = getDistricts(p.value[0], p.value[1]);
+            p.cols[2].values = dis.map(function (d) {
+              return d.code;
+            });
+            p.cols[2].displayValues = dis.map(function (d) {
+              return d.name;
+            });
+          }
+        } else {
+          if (params.showDistrict) {
+            var dis = getDistricts(p.value[0], p.cols[1].values[0]);
+            p.cols[2].values = dis.map(function (d) {
+              return d.code;
+            });
+            p.cols[2].displayValues = dis.map(function (d) {
+              return d.name;
+            });
+          }
+        }
+      }
+      $(this).picker(p);
+    });
+  };
+
+  defaults = $.fn.cityPicker.prototype.defaults = {
+    showDistrict: true //是否显示地区选择
+  };
+
+}($);
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.min.js
new file mode 100755
index 0000000..8091f11
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/city-picker.min.js
@@ -0,0 +1,5 @@
+// jshint ignore: start
++function(e){e.rawCitiesData=[{name:"北京",code:"110000",sub:[{name:"北京市",code:"110000",sub:[{name:"东城区",code:"110101"},{name:"西城区",code:"110102"},{name:"朝阳区",code:"110105"},{name:"丰台区",code:"110106"},{name:"石景山区",code:"110107"},{name:"海淀区",code:"110108"},{name:"门头沟区",code:"110109"},{name:"房山区",code:"110111"},{name:"通州区",code:"110112"},{name:"顺义区",code:"110113"},{name:"昌平区",code:"110114"},{name:"大兴区",code:"110115"},{name:"怀柔区",code:"110116"},{name:"平谷区",code:"110117"},{name:"密云县",code:"110228"},{name:"延庆县",code:"110229"}]}]},{name:"天津",code:"120000",sub:[{name:"天津市",code:"120000",sub:[{name:"和平区",code:"120101"},{name:"河东区",code:"120102"},{name:"河西区",code:"120103"},{name:"南开区",code:"120104"},{name:"河北区",code:"120105"},{name:"红桥区",code:"120106"},{name:"东丽区",code:"120110"},{name:"西青区",code:"120111"},{name:"津南区",code:"120112"},{name:"北辰区",code:"120113"},{name:"武清区",code:"120114"},{name:"宝坻区",code:"120115"},{name:"滨海新区",code:"120116"},{name:"宁河县",code:"120221"},{name:"静海县",code:"120223"},{name:"蓟县",code:"120225"}]}]},{name:"河北省",code:"130000",sub:[{name:"石家庄市",code:"130100",sub:[{name:"市辖区",code:"130101"},{name:"长安区",code:"130102"},{name:"桥西区",code:"130104"},{name:"新华区",code:"130105"},{name:"井陉矿区",code:"130107"},{name:"裕华区",code:"130108"},{name:"藁城区",code:"130109"},{name:"鹿泉区",code:"130110"},{name:"栾城区",code:"130111"},{name:"井陉县",code:"130121"},{name:"正定县",code:"130123"},{name:"行唐县",code:"130125"},{name:"灵寿县",code:"130126"},{name:"高邑县",code:"130127"},{name:"深泽县",code:"130128"},{name:"赞皇县",code:"130129"},{name:"无极县",code:"130130"},{name:"平山县",code:"130131"},{name:"元氏县",code:"130132"},{name:"赵县",code:"130133"},{name:"辛集市",code:"130181"},{name:"晋州市",code:"130183"},{name:"新乐市",code:"130184"}]},{name:"唐山市",code:"130200",sub:[{name:"市辖区",code:"130201"},{name:"路南区",code:"130202"},{name:"路北区",code:"130203"},{name:"古冶区",code:"130204"},{name:"开平区",code:"130205"},{name:"丰南区",code:"130207"},{name:"丰润区",code:"130208"},{name:"曹妃甸区",code:"130209"},{name:"滦县",code:"130223"},{name:"滦南县",code:"130224"},{name:"乐亭县",code:"130225"},{name:"迁西县",code:"130227"},{name:"玉田县",code:"130229"},{name:"遵化市",code:"130281"},{name:"迁安市",code:"130283"}]},{name:"秦皇岛市",code:"130300",sub:[{name:"市辖区",code:"130301"},{name:"海港区",code:"130302"},{name:"山海关区",code:"130303"},{name:"北戴河区",code:"130304"},{name:"青龙满族自治县",code:"130321"},{name:"昌黎县",code:"130322"},{name:"抚宁县",code:"130323"},{name:"卢龙县",code:"130324"}]},{name:"邯郸市",code:"130400",sub:[{name:"市辖区",code:"130401"},{name:"邯山区",code:"130402"},{name:"丛台区",code:"130403"},{name:"复兴区",code:"130404"},{name:"峰峰矿区",code:"130406"},{name:"邯郸县",code:"130421"},{name:"临漳县",code:"130423"},{name:"成安县",code:"130424"},{name:"大名县",code:"130425"},{name:"涉县",code:"130426"},{name:"磁县",code:"130427"},{name:"肥乡县",code:"130428"},{name:"永年县",code:"130429"},{name:"邱县",code:"130430"},{name:"鸡泽县",code:"130431"},{name:"广平县",code:"130432"},{name:"馆陶县",code:"130433"},{name:"魏县",code:"130434"},{name:"曲周县",code:"130435"},{name:"武安市",code:"130481"}]},{name:"邢台市",code:"130500",sub:[{name:"市辖区",code:"130501"},{name:"桥东区",code:"130502"},{name:"桥西区",code:"130503"},{name:"邢台县",code:"130521"},{name:"临城县",code:"130522"},{name:"内丘县",code:"130523"},{name:"柏乡县",code:"130524"},{name:"隆尧县",code:"130525"},{name:"任县",code:"130526"},{name:"南和县",code:"130527"},{name:"宁晋县",code:"130528"},{name:"巨鹿县",code:"130529"},{name:"新河县",code:"130530"},{name:"广宗县",code:"130531"},{name:"平乡县",code:"130532"},{name:"威县",code:"130533"},{name:"清河县",code:"130534"},{name:"临西县",code:"130535"},{name:"南宫市",code:"130581"},{name:"沙河市",code:"130582"}]},{name:"保定市",code:"130600",sub:[{name:"市辖区",code:"130601"},{name:"新市区",code:"130602"},{name:"北市区",code:"130603"},{name:"南市区",code:"130604"},{name:"满城县",code:"130621"},{name:"清苑县",code:"130622"},{name:"涞水县",code:"130623"},{name:"阜平县",code:"130624"},{name:"徐水县",code:"130625"},{name:"定兴县",code:"130626"},{name:"唐县",code:"130627"},{name:"高阳县",code:"130628"},{name:"容城县",code:"130629"},{name:"涞源县",code:"130630"},{name:"望都县",code:"130631"},{name:"安新县",code:"130632"},{name:"易县",code:"130633"},{name:"曲阳县",code:"130634"},{name:"蠡县",code:"130635"},{name:"顺平县",code:"130636"},{name:"博野县",code:"130637"},{name:"雄县",code:"130638"},{name:"涿州市",code:"130681"},{name:"定州市",code:"130682"},{name:"安国市",code:"130683"},{name:"高碑店市",code:"130684"}]},{name:"张家口市",code:"130700",sub:[{name:"市辖区",code:"130701"},{name:"桥东区",code:"130702"},{name:"桥西区",code:"130703"},{name:"宣化区",code:"130705"},{name:"下花园区",code:"130706"},{name:"宣化县",code:"130721"},{name:"张北县",code:"130722"},{name:"康保县",code:"130723"},{name:"沽源县",code:"130724"},{name:"尚义县",code:"130725"},{name:"蔚县",code:"130726"},{name:"阳原县",code:"130727"},{name:"怀安县",code:"130728"},{name:"万全县",code:"130729"},{name:"怀来县",code:"130730"},{name:"涿鹿县",code:"130731"},{name:"赤城县",code:"130732"},{name:"崇礼县",code:"130733"}]},{name:"承德市",code:"130800",sub:[{name:"市辖区",code:"130801"},{name:"双桥区",code:"130802"},{name:"双滦区",code:"130803"},{name:"鹰手营子矿区",code:"130804"},{name:"承德县",code:"130821"},{name:"兴隆县",code:"130822"},{name:"平泉县",code:"130823"},{name:"滦平县",code:"130824"},{name:"隆化县",code:"130825"},{name:"丰宁满族自治县",code:"130826"},{name:"宽城满族自治县",code:"130827"},{name:"围场满族蒙古族自治县",code:"130828"}]},{name:"沧州市",code:"130900",sub:[{name:"市辖区",code:"130901"},{name:"新华区",code:"130902"},{name:"运河区",code:"130903"},{name:"沧县",code:"130921"},{name:"青县",code:"130922"},{name:"东光县",code:"130923"},{name:"海兴县",code:"130924"},{name:"盐山县",code:"130925"},{name:"肃宁县",code:"130926"},{name:"南皮县",code:"130927"},{name:"吴桥县",code:"130928"},{name:"献县",code:"130929"},{name:"孟村回族自治县",code:"130930"},{name:"泊头市",code:"130981"},{name:"任丘市",code:"130982"},{name:"黄骅市",code:"130983"},{name:"河间市",code:"130984"}]},{name:"廊坊市",code:"131000",sub:[{name:"市辖区",code:"131001"},{name:"安次区",code:"131002"},{name:"广阳区",code:"131003"},{name:"固安县",code:"131022"},{name:"永清县",code:"131023"},{name:"香河县",code:"131024"},{name:"大城县",code:"131025"},{name:"文安县",code:"131026"},{name:"大厂回族自治县",code:"131028"},{name:"霸州市",code:"131081"},{name:"三河市",code:"131082"}]},{name:"衡水市",code:"131100",sub:[{name:"市辖区",code:"131101"},{name:"桃城区",code:"131102"},{name:"枣强县",code:"131121"},{name:"武邑县",code:"131122"},{name:"武强县",code:"131123"},{name:"饶阳县",code:"131124"},{name:"安平县",code:"131125"},{name:"故城县",code:"131126"},{name:"景县",code:"131127"},{name:"阜城县",code:"131128"},{name:"冀州市",code:"131181"},{name:"深州市",code:"131182"}]}]},{name:"山西省",code:"140000",sub:[{name:"太原市",code:"140100",sub:[{name:"市辖区",code:"140101"},{name:"小店区",code:"140105"},{name:"迎泽区",code:"140106"},{name:"杏花岭区",code:"140107"},{name:"尖草坪区",code:"140108"},{name:"万柏林区",code:"140109"},{name:"晋源区",code:"140110"},{name:"清徐县",code:"140121"},{name:"阳曲县",code:"140122"},{name:"娄烦县",code:"140123"},{name:"古交市",code:"140181"}]},{name:"大同市",code:"140200",sub:[{name:"市辖区",code:"140201"},{name:"城区",code:"140202"},{name:"矿区",code:"140203"},{name:"南郊区",code:"140211"},{name:"新荣区",code:"140212"},{name:"阳高县",code:"140221"},{name:"天镇县",code:"140222"},{name:"广灵县",code:"140223"},{name:"灵丘县",code:"140224"},{name:"浑源县",code:"140225"},{name:"左云县",code:"140226"},{name:"大同县",code:"140227"}]},{name:"阳泉市",code:"140300",sub:[{name:"市辖区",code:"140301"},{name:"城区",code:"140302"},{name:"矿区",code:"140303"},{name:"郊区",code:"140311"},{name:"平定县",code:"140321"},{name:"盂县",code:"140322"}]},{name:"长治市",code:"140400",sub:[{name:"市辖区",code:"140401"},{name:"城区",code:"140402"},{name:"郊区",code:"140411"},{name:"长治县",code:"140421"},{name:"襄垣县",code:"140423"},{name:"屯留县",code:"140424"},{name:"平顺县",code:"140425"},{name:"黎城县",code:"140426"},{name:"壶关县",code:"140427"},{name:"长子县",code:"140428"},{name:"武乡县",code:"140429"},{name:"沁县",code:"140430"},{name:"沁源县",code:"140431"},{name:"潞城市",code:"140481"}]},{name:"晋城市",code:"140500",sub:[{name:"市辖区",code:"140501"},{name:"城区",code:"140502"},{name:"沁水县",code:"140521"},{name:"阳城县",code:"140522"},{name:"陵川县",code:"140524"},{name:"泽州县",code:"140525"},{name:"高平市",code:"140581"}]},{name:"朔州市",code:"140600",sub:[{name:"市辖区",code:"140601"},{name:"朔城区",code:"140602"},{name:"平鲁区",code:"140603"},{name:"山阴县",code:"140621"},{name:"应县",code:"140622"},{name:"右玉县",code:"140623"},{name:"怀仁县",code:"140624"}]},{name:"晋中市",code:"140700",sub:[{name:"市辖区",code:"140701"},{name:"榆次区",code:"140702"},{name:"榆社县",code:"140721"},{name:"左权县",code:"140722"},{name:"和顺县",code:"140723"},{name:"昔阳县",code:"140724"},{name:"寿阳县",code:"140725"},{name:"太谷县",code:"140726"},{name:"祁县",code:"140727"},{name:"平遥县",code:"140728"},{name:"灵石县",code:"140729"},{name:"介休市",code:"140781"}]},{name:"运城市",code:"140800",sub:[{name:"市辖区",code:"140801"},{name:"盐湖区",code:"140802"},{name:"临猗县",code:"140821"},{name:"万荣县",code:"140822"},{name:"闻喜县",code:"140823"},{name:"稷山县",code:"140824"},{name:"新绛县",code:"140825"},{name:"绛县",code:"140826"},{name:"垣曲县",code:"140827"},{name:"夏县",code:"140828"},{name:"平陆县",code:"140829"},{name:"芮城县",code:"140830"},{name:"永济市",code:"140881"},{name:"河津市",code:"140882"}]},{name:"忻州市",code:"140900",sub:[{name:"市辖区",code:"140901"},{name:"忻府区",code:"140902"},{name:"定襄县",code:"140921"},{name:"五台县",code:"140922"},{name:"代县",code:"140923"},{name:"繁峙县",code:"140924"},{name:"宁武县",code:"140925"},{name:"静乐县",code:"140926"},{name:"神池县",code:"140927"},{name:"五寨县",code:"140928"},{name:"岢岚县",code:"140929"},{name:"河曲县",code:"140930"},{name:"保德县",code:"140931"},{name:"偏关县",code:"140932"},{name:"原平市",code:"140981"}]},{name:"临汾市",code:"141000",sub:[{name:"市辖区",code:"141001"},{name:"尧都区",code:"141002"},{name:"曲沃县",code:"141021"},{name:"翼城县",code:"141022"},{name:"襄汾县",code:"141023"},{name:"洪洞县",code:"141024"},{name:"古县",code:"141025"},{name:"安泽县",code:"141026"},{name:"浮山县",code:"141027"},{name:"吉县",code:"141028"},{name:"乡宁县",code:"141029"},{name:"大宁县",code:"141030"},{name:"隰县",code:"141031"},{name:"永和县",code:"141032"},{name:"蒲县",code:"141033"},{name:"汾西县",code:"141034"},{name:"侯马市",code:"141081"},{name:"霍州市",code:"141082"}]},{name:"吕梁市",code:"141100",sub:[{name:"市辖区",code:"141101"},{name:"离石区",code:"141102"},{name:"文水县",code:"141121"},{name:"交城县",code:"141122"},{name:"兴县",code:"141123"},{name:"临县",code:"141124"},{name:"柳林县",code:"141125"},{name:"石楼县",code:"141126"},{name:"岚县",code:"141127"},{name:"方山县",code:"141128"},{name:"中阳县",code:"141129"},{name:"交口县",code:"141130"},{name:"孝义市",code:"141181"},{name:"汾阳市",code:"141182"}]}]},{name:"内蒙古自治区",code:"150000",sub:[{name:"呼和浩特市",code:"150100",sub:[{name:"市辖区",code:"150101"},{name:"新城区",code:"150102"},{name:"回民区",code:"150103"},{name:"玉泉区",code:"150104"},{name:"赛罕区",code:"150105"},{name:"土默特左旗",code:"150121"},{name:"托克托县",code:"150122"},{name:"和林格尔县",code:"150123"},{name:"清水河县",code:"150124"},{name:"武川县",code:"150125"}]},{name:"包头市",code:"150200",sub:[{name:"市辖区",code:"150201"},{name:"东河区",code:"150202"},{name:"昆都仑区",code:"150203"},{name:"青山区",code:"150204"},{name:"石拐区",code:"150205"},{name:"白云鄂博矿区",code:"150206"},{name:"九原区",code:"150207"},{name:"土默特右旗",code:"150221"},{name:"固阳县",code:"150222"},{name:"达尔罕茂明安联合旗",code:"150223"}]},{name:"乌海市",code:"150300",sub:[{name:"市辖区",code:"150301"},{name:"海勃湾区",code:"150302"},{name:"海南区",code:"150303"},{name:"乌达区",code:"150304"}]},{name:"赤峰市",code:"150400",sub:[{name:"市辖区",code:"150401"},{name:"红山区",code:"150402"},{name:"元宝山区",code:"150403"},{name:"松山区",code:"150404"},{name:"阿鲁科尔沁旗",code:"150421"},{name:"巴林左旗",code:"150422"},{name:"巴林右旗",code:"150423"},{name:"林西县",code:"150424"},{name:"克什克腾旗",code:"150425"},{name:"翁牛特旗",code:"150426"},{name:"喀喇沁旗",code:"150428"},{name:"宁城县",code:"150429"},{name:"敖汉旗",code:"150430"}]},{name:"通辽市",code:"150500",sub:[{name:"市辖区",code:"150501"},{name:"科尔沁区",code:"150502"},{name:"科尔沁左翼中旗",code:"150521"},{name:"科尔沁左翼后旗",code:"150522"},{name:"开鲁县",code:"150523"},{name:"库伦旗",code:"150524"},{name:"奈曼旗",code:"150525"},{name:"扎鲁特旗",code:"150526"},{name:"霍林郭勒市",code:"150581"}]},{name:"鄂尔多斯市",code:"150600",sub:[{name:"市辖区",code:"150601"},{name:"东胜区",code:"150602"},{name:"达拉特旗",code:"150621"},{name:"准格尔旗",code:"150622"},{name:"鄂托克前旗",code:"150623"},{name:"鄂托克旗",code:"150624"},{name:"杭锦旗",code:"150625"},{name:"乌审旗",code:"150626"},{name:"伊金霍洛旗",code:"150627"}]},{name:"呼伦贝尔市",code:"150700",sub:[{name:"市辖区",code:"150701"},{name:"海拉尔区",code:"150702"},{name:"扎赉诺尔区",code:"150703"},{name:"阿荣旗",code:"150721"},{name:"莫力达瓦达斡尔族自治旗",code:"150722"},{name:"鄂伦春自治旗",code:"150723"},{name:"鄂温克族自治旗",code:"150724"},{name:"陈巴尔虎旗",code:"150725"},{name:"新巴尔虎左旗",code:"150726"},{name:"新巴尔虎右旗",code:"150727"},{name:"满洲里市",code:"150781"},{name:"牙克石市",code:"150782"},{name:"扎兰屯市",code:"150783"},{name:"额尔古纳市",code:"150784"},{name:"根河市",code:"150785"}]},{name:"巴彦淖尔市",code:"150800",sub:[{name:"市辖区",code:"150801"},{name:"临河区",code:"150802"},{name:"五原县",code:"150821"},{name:"磴口县",code:"150822"},{name:"乌拉特前旗",code:"150823"},{name:"乌拉特中旗",code:"150824"},{name:"乌拉特后旗",code:"150825"},{name:"杭锦后旗",code:"150826"}]},{name:"乌兰察布市",code:"150900",sub:[{name:"市辖区",code:"150901"},{name:"集宁区",code:"150902"},{name:"卓资县",code:"150921"},{name:"化德县",code:"150922"},{name:"商都县",code:"150923"},{name:"兴和县",code:"150924"},{name:"凉城县",code:"150925"},{name:"察哈尔右翼前旗",code:"150926"},{name:"察哈尔右翼中旗",code:"150927"},{name:"察哈尔右翼后旗",code:"150928"},{name:"四子王旗",code:"150929"},{name:"丰镇市",code:"150981"}]},{name:"兴安盟",code:"152200",sub:[{name:"乌兰浩特市",code:"152201"},{name:"阿尔山市",code:"152202"},{name:"科尔沁右翼前旗",code:"152221"},{name:"科尔沁右翼中旗",code:"152222"},{name:"扎赉特旗",code:"152223"},{name:"突泉县",code:"152224"}]},{name:"锡林郭勒盟",code:"152500",sub:[{name:"二连浩特市",code:"152501"},{name:"锡林浩特市",code:"152502"},{name:"阿巴嘎旗",code:"152522"},{name:"苏尼特左旗",code:"152523"},{name:"苏尼特右旗",code:"152524"},{name:"东乌珠穆沁旗",code:"152525"},{name:"西乌珠穆沁旗",code:"152526"},{name:"太仆寺旗",code:"152527"},{name:"镶黄旗",code:"152528"},{name:"正镶白旗",code:"152529"},{name:"正蓝旗",code:"152530"},{name:"多伦县",code:"152531"}]},{name:"阿拉善盟",code:"152900",sub:[{name:"阿拉善左旗",code:"152921"},{name:"阿拉善右旗",code:"152922"},{name:"额济纳旗",code:"152923"}]}]},{name:"辽宁省",code:"210000",sub:[{name:"沈阳市",code:"210100",sub:[{name:"市辖区",code:"210101"},{name:"和平区",code:"210102"},{name:"沈河区",code:"210103"},{name:"大东区",code:"210104"},{name:"皇姑区",code:"210105"},{name:"铁西区",code:"210106"},{name:"苏家屯区",code:"210111"},{name:"浑南区",code:"210112"},{name:"沈北新区",code:"210113"},{name:"于洪区",code:"210114"},{name:"辽中县",code:"210122"},{name:"康平县",code:"210123"},{name:"法库县",code:"210124"},{name:"新民市",code:"210181"}]},{name:"大连市",code:"210200",sub:[{name:"市辖区",code:"210201"},{name:"中山区",code:"210202"},{name:"西岗区",code:"210203"},{name:"沙河口区",code:"210204"},{name:"甘井子区",code:"210211"},{name:"旅顺口区",code:"210212"},{name:"金州区",code:"210213"},{name:"长海县",code:"210224"},{name:"瓦房店市",code:"210281"},{name:"普兰店市",code:"210282"},{name:"庄河市",code:"210283"}]},{name:"鞍山市",code:"210300",sub:[{name:"市辖区",code:"210301"},{name:"铁东区",code:"210302"},{name:"铁西区",code:"210303"},{name:"立山区",code:"210304"},{name:"千山区",code:"210311"},{name:"台安县",code:"210321"},{name:"岫岩满族自治县",code:"210323"},{name:"海城市",code:"210381"}]},{name:"抚顺市",code:"210400",sub:[{name:"市辖区",code:"210401"},{name:"新抚区",code:"210402"},{name:"东洲区",code:"210403"},{name:"望花区",code:"210404"},{name:"顺城区",code:"210411"},{name:"抚顺县",code:"210421"},{name:"新宾满族自治县",code:"210422"},{name:"清原满族自治县",code:"210423"}]},{name:"本溪市",code:"210500",sub:[{name:"市辖区",code:"210501"},{name:"平山区",code:"210502"},{name:"溪湖区",code:"210503"},{name:"明山区",code:"210504"},{name:"南芬区",code:"210505"},{name:"本溪满族自治县",code:"210521"},{name:"桓仁满族自治县",code:"210522"}]},{name:"丹东市",code:"210600",sub:[{name:"市辖区",code:"210601"},{name:"元宝区",code:"210602"},{name:"振兴区",code:"210603"},{name:"振安区",code:"210604"},{name:"宽甸满族自治县",code:"210624"},{name:"东港市",code:"210681"},{name:"凤城市",code:"210682"}]},{name:"锦州市",code:"210700",sub:[{name:"市辖区",code:"210701"},{name:"古塔区",code:"210702"},{name:"凌河区",code:"210703"},{name:"太和区",code:"210711"},{name:"黑山县",code:"210726"},{name:"义县",code:"210727"},{name:"凌海市",code:"210781"},{name:"北镇市",code:"210782"}]},{name:"营口市",code:"210800",sub:[{name:"市辖区",code:"210801"},{name:"站前区",code:"210802"},{name:"西市区",code:"210803"},{name:"鲅鱼圈区",code:"210804"},{name:"老边区",code:"210811"},{name:"盖州市",code:"210881"},{name:"大石桥市",code:"210882"}]},{name:"阜新市",code:"210900",sub:[{name:"市辖区",code:"210901"},{name:"海州区",code:"210902"},{name:"新邱区",code:"210903"},{name:"太平区",code:"210904"},{name:"清河门区",code:"210905"},{name:"细河区",code:"210911"},{name:"阜新蒙古族自治县",code:"210921"},{name:"彰武县",code:"210922"}]},{name:"辽阳市",code:"211000",sub:[{name:"市辖区",code:"211001"},{name:"白塔区",code:"211002"},{name:"文圣区",code:"211003"},{name:"宏伟区",code:"211004"},{name:"弓长岭区",code:"211005"},{name:"太子河区",code:"211011"},{name:"辽阳县",code:"211021"},{name:"灯塔市",code:"211081"}]},{name:"盘锦市",code:"211100",sub:[{name:"市辖区",code:"211101"},{name:"双台子区",code:"211102"},{name:"兴隆台区",code:"211103"},{name:"大洼县",code:"211121"},{name:"盘山县",code:"211122"}]},{name:"铁岭市",code:"211200",sub:[{name:"市辖区",code:"211201"},{name:"银州区",code:"211202"},{name:"清河区",code:"211204"},{name:"铁岭县",code:"211221"},{name:"西丰县",code:"211223"},{name:"昌图县",code:"211224"},{name:"调兵山市",code:"211281"},{name:"开原市",code:"211282"}]},{name:"朝阳市",code:"211300",sub:[{name:"市辖区",code:"211301"},{name:"双塔区",code:"211302"},{name:"龙城区",code:"211303"},{name:"朝阳县",code:"211321"},{name:"建平县",code:"211322"},{name:"喀喇沁左翼蒙古族自治县",code:"211324"},{name:"北票市",code:"211381"},{name:"凌源市",code:"211382"}]},{name:"葫芦岛市",code:"211400",sub:[{name:"市辖区",code:"211401"},{name:"连山区",code:"211402"},{name:"龙港区",code:"211403"},{name:"南票区",code:"211404"},{name:"绥中县",code:"211421"},{name:"建昌县",code:"211422"},{name:"兴城市",code:"211481"}]}]},{name:"吉林省",code:"220000",sub:[{name:"长春市",code:"220100",sub:[{name:"市辖区",code:"220101"},{name:"南关区",code:"220102"},{name:"宽城区",code:"220103"},{name:"朝阳区",code:"220104"},{name:"二道区",code:"220105"},{name:"绿园区",code:"220106"},{name:"双阳区",code:"220112"},{name:"九台区",code:"220113"},{name:"农安县",code:"220122"},{name:"榆树市",code:"220182"},{name:"德惠市",code:"220183"}]},{name:"吉林市",code:"220200",sub:[{name:"市辖区",code:"220201"},{name:"昌邑区",code:"220202"},{name:"龙潭区",code:"220203"},{name:"船营区",code:"220204"},{name:"丰满区",code:"220211"},{name:"永吉县",code:"220221"},{name:"蛟河市",code:"220281"},{name:"桦甸市",code:"220282"},{name:"舒兰市",code:"220283"},{name:"磐石市",code:"220284"}]},{name:"四平市",code:"220300",sub:[{name:"市辖区",code:"220301"},{name:"铁西区",code:"220302"},{name:"铁东区",code:"220303"},{name:"梨树县",code:"220322"},{name:"伊通满族自治县",code:"220323"},{name:"公主岭市",code:"220381"},{name:"双辽市",code:"220382"}]},{name:"辽源市",code:"220400",sub:[{name:"市辖区",code:"220401"},{name:"龙山区",code:"220402"},{name:"西安区",code:"220403"},{name:"东丰县",code:"220421"},{name:"东辽县",code:"220422"}]},{name:"通化市",code:"220500",sub:[{name:"市辖区",code:"220501"},{name:"东昌区",code:"220502"},{name:"二道江区",code:"220503"},{name:"通化县",code:"220521"},{name:"辉南县",code:"220523"},{name:"柳河县",code:"220524"},{name:"梅河口市",code:"220581"},{name:"集安市",code:"220582"}]},{name:"白山市",code:"220600",sub:[{name:"市辖区",code:"220601"},{name:"浑江区",code:"220602"},{name:"江源区",code:"220605"},{name:"抚松县",code:"220621"},{name:"靖宇县",code:"220622"},{name:"长白朝鲜族自治县",code:"220623"},{name:"临江市",code:"220681"}]},{name:"松原市",code:"220700",sub:[{name:"市辖区",code:"220701"},{name:"宁江区",code:"220702"},{name:"前郭尔罗斯蒙古族自治县",code:"220721"},{name:"长岭县",code:"220722"},{name:"乾安县",code:"220723"},{name:"扶余市",code:"220781"}]},{name:"白城市",code:"220800",sub:[{name:"市辖区",code:"220801"},{name:"洮北区",code:"220802"},{name:"镇赉县",code:"220821"},{name:"通榆县",code:"220822"},{name:"洮南市",code:"220881"},{name:"大安市",code:"220882"}]},{name:"延边朝鲜族自治州",code:"222400",sub:[{name:"延吉市",code:"222401"},{name:"图们市",code:"222402"},{name:"敦化市",code:"222403"},{name:"珲春市",code:"222404"},{name:"龙井市",code:"222405"},{name:"和龙市",code:"222406"},{name:"汪清县",code:"222424"},{name:"安图县",code:"222426"}]}]},{name:"黑龙江省",code:"230000",sub:[{name:"哈尔滨市",code:"230100",sub:[{name:"市辖区",code:"230101"},{name:"道里区",code:"230102"},{name:"南岗区",code:"230103"},{name:"道外区",code:"230104"},{name:"平房区",code:"230108"},{name:"松北区",code:"230109"},{name:"香坊区",code:"230110"},{name:"呼兰区",code:"230111"},{name:"阿城区",code:"230112"},{name:"双城区",code:"230113"},{name:"依兰县",code:"230123"},{name:"方正县",code:"230124"},{name:"宾县",code:"230125"},{name:"巴彦县",code:"230126"},{name:"木兰县",code:"230127"},{name:"通河县",code:"230128"},{name:"延寿县",code:"230129"},{name:"尚志市",code:"230183"},{name:"五常市",code:"230184"}]},{name:"齐齐哈尔市",code:"230200",sub:[{name:"市辖区",code:"230201"},{name:"龙沙区",code:"230202"},{name:"建华区",code:"230203"},{name:"铁锋区",code:"230204"},{name:"昂昂溪区",code:"230205"},{name:"富拉尔基区",code:"230206"},{name:"碾子山区",code:"230207"},{name:"梅里斯达斡尔族区",code:"230208"},{name:"龙江县",code:"230221"},{name:"依安县",code:"230223"},{name:"泰来县",code:"230224"},{name:"甘南县",code:"230225"},{name:"富裕县",code:"230227"},{name:"克山县",code:"230229"},{name:"克东县",code:"230230"},{name:"拜泉县",code:"230231"},{name:"讷河市",code:"230281"}]},{name:"鸡西市",code:"230300",sub:[{name:"市辖区",code:"230301"},{name:"鸡冠区",code:"230302"},{name:"恒山区",code:"230303"},{name:"滴道区",code:"230304"},{name:"梨树区",code:"230305"},{name:"城子河区",code:"230306"},{name:"麻山区",code:"230307"},{name:"鸡东县",code:"230321"},{name:"虎林市",code:"230381"},{name:"密山市",code:"230382"}]},{name:"鹤岗市",code:"230400",sub:[{name:"市辖区",code:"230401"},{name:"向阳区",code:"230402"},{name:"工农区",code:"230403"},{name:"南山区",code:"230404"},{name:"兴安区",code:"230405"},{name:"东山区",code:"230406"},{name:"兴山区",code:"230407"},{name:"萝北县",code:"230421"},{name:"绥滨县",code:"230422"}]},{name:"双鸭山市",code:"230500",sub:[{name:"市辖区",code:"230501"},{name:"尖山区",code:"230502"},{name:"岭东区",code:"230503"},{name:"四方台区",code:"230505"},{name:"宝山区",code:"230506"},{name:"集贤县",code:"230521"},{name:"友谊县",code:"230522"},{name:"宝清县",code:"230523"},{name:"饶河县",code:"230524"}]},{name:"大庆市",code:"230600",sub:[{name:"市辖区",code:"230601"},{name:"萨尔图区",code:"230602"},{name:"龙凤区",code:"230603"},{name:"让胡路区",code:"230604"},{name:"红岗区",code:"230605"},{name:"大同区",code:"230606"},{name:"肇州县",code:"230621"},{name:"肇源县",code:"230622"},{name:"林甸县",code:"230623"},{name:"杜尔伯特蒙古族自治县",code:"230624"}]},{name:"伊春市",code:"230700",sub:[{name:"市辖区",code:"230701"},{name:"伊春区",code:"230702"},{name:"南岔区",code:"230703"},{name:"友好区",code:"230704"},{name:"西林区",code:"230705"},{name:"翠峦区",code:"230706"},{name:"新青区",code:"230707"},{name:"美溪区",code:"230708"},{name:"金山屯区",code:"230709"},{name:"五营区",code:"230710"},{name:"乌马河区",code:"230711"},{name:"汤旺河区",code:"230712"},{name:"带岭区",code:"230713"},{name:"乌伊岭区",code:"230714"},{name:"红星区",code:"230715"},{name:"上甘岭区",code:"230716"},{name:"嘉荫县",code:"230722"},{name:"铁力市",code:"230781"}]},{name:"佳木斯市",code:"230800",sub:[{name:"市辖区",code:"230801"},{name:"向阳区",code:"230803"},{name:"前进区",code:"230804"},{name:"东风区",code:"230805"},{name:"郊区",code:"230811"},{name:"桦南县",code:"230822"},{name:"桦川县",code:"230826"},{name:"汤原县",code:"230828"},{name:"抚远县",code:"230833"},{name:"同江市",code:"230881"},{name:"富锦市",code:"230882"}]},{name:"七台河市",code:"230900",sub:[{name:"市辖区",code:"230901"},{name:"新兴区",code:"230902"},{name:"桃山区",code:"230903"},{name:"茄子河区",code:"230904"},{name:"勃利县",code:"230921"}]},{name:"牡丹江市",code:"231000",sub:[{name:"市辖区",code:"231001"},{name:"东安区",code:"231002"},{name:"阳明区",code:"231003"},{name:"爱民区",code:"231004"},{name:"西安区",code:"231005"},{name:"东宁县",code:"231024"},{name:"林口县",code:"231025"},{name:"绥芬河市",code:"231081"},{name:"海林市",code:"231083"},{name:"宁安市",code:"231084"},{name:"穆棱市",code:"231085"}]},{name:"黑河市",code:"231100",sub:[{name:"市辖区",code:"231101"},{name:"爱辉区",code:"231102"},{name:"嫩江县",code:"231121"},{name:"逊克县",code:"231123"},{name:"孙吴县",code:"231124"},{name:"北安市",code:"231181"},{name:"五大连池市",code:"231182"}]},{name:"绥化市",code:"231200",sub:[{name:"市辖区",code:"231201"},{name:"北林区",code:"231202"},{name:"望奎县",code:"231221"},{name:"兰西县",code:"231222"},{name:"青冈县",code:"231223"},{name:"庆安县",code:"231224"},{name:"明水县",code:"231225"},{name:"绥棱县",code:"231226"},{name:"安达市",code:"231281"},{name:"肇东市",code:"231282"},{name:"海伦市",code:"231283"}]},{name:"大兴安岭地区",code:"232700",sub:[{name:"呼玛县",code:"232721"},{name:"塔河县",code:"232722"},{name:"漠河县",code:"232723"}]}]},{name:"上海",code:"310000",sub:[{name:"上海市",code:"310000",sub:[{name:"黄浦区",code:"310101"},{name:"徐汇区",code:"310104"},{name:"长宁区",code:"310105"},{name:"静安区",code:"310106"},{name:"普陀区",code:"310107"},{name:"闸北区",code:"310108"},{name:"虹口区",code:"310109"},{name:"杨浦区",code:"310110"},{name:"闵行区",code:"310112"},{name:"宝山区",code:"310113"},{name:"嘉定区",code:"310114"},{name:"浦东新区",code:"310115"},{name:"金山区",code:"310116"},{name:"松江区",code:"310117"},{name:"青浦区",code:"310118"},{name:"奉贤区",code:"310120"},{name:"崇明县",code:"310230"}]}]},{name:"江苏省",code:"320000",sub:[{name:"南京市",code:"320100",sub:[{name:"市辖区",code:"320101"},{name:"玄武区",code:"320102"},{name:"秦淮区",code:"320104"},{name:"建邺区",code:"320105"},{name:"鼓楼区",code:"320106"},{name:"浦口区",code:"320111"},{name:"栖霞区",code:"320113"},{name:"雨花台区",code:"320114"},{name:"江宁区",code:"320115"},{name:"六合区",code:"320116"},{name:"溧水区",code:"320117"},{name:"高淳区",code:"320118"}]},{name:"无锡市",code:"320200",sub:[{name:"市辖区",code:"320201"},{name:"崇安区",code:"320202"},{name:"南长区",code:"320203"},{name:"北塘区",code:"320204"},{name:"锡山区",code:"320205"},{name:"惠山区",code:"320206"},{name:"滨湖区",code:"320211"},{name:"江阴市",code:"320281"},{name:"宜兴市",code:"320282"}]},{name:"徐州市",code:"320300",sub:[{name:"市辖区",code:"320301"},{name:"鼓楼区",code:"320302"},{name:"云龙区",code:"320303"},{name:"贾汪区",code:"320305"},{name:"泉山区",code:"320311"},{name:"铜山区",code:"320312"},{name:"丰县",code:"320321"},{name:"沛县",code:"320322"},{name:"睢宁县",code:"320324"},{name:"新沂市",code:"320381"},{name:"邳州市",code:"320382"}]},{name:"常州市",code:"320400",sub:[{name:"市辖区",code:"320401"},{name:"天宁区",code:"320402"},{name:"钟楼区",code:"320404"},{name:"戚墅堰区",code:"320405"},{name:"新北区",code:"320411"},{name:"武进区",code:"320412"},{name:"溧阳市",code:"320481"},{name:"金坛市",code:"320482"}]},{name:"苏州市",code:"320500",sub:[{name:"市辖区",code:"320501"},{name:"虎丘区",code:"320505"},{name:"吴中区",code:"320506"},{name:"相城区",code:"320507"},{name:"姑苏区",code:"320508"},{name:"吴江区",code:"320509"},{name:"常熟市",code:"320581"},{name:"张家港市",code:"320582"},{name:"昆山市",code:"320583"},{name:"太仓市",code:"320585"}]},{name:"南通市",code:"320600",sub:[{name:"市辖区",code:"320601"},{name:"崇川区",code:"320602"},{name:"港闸区",code:"320611"},{name:"通州区",code:"320612"},{name:"海安县",code:"320621"},{name:"如东县",code:"320623"},{name:"启东市",code:"320681"},{name:"如皋市",code:"320682"},{name:"海门市",code:"320684"}]},{name:"连云港市",code:"320700",sub:[{name:"市辖区",code:"320701"},{name:"连云区",code:"320703"},{name:"海州区",code:"320706"},{name:"赣榆区",code:"320707"},{name:"东海县",code:"320722"},{name:"灌云县",code:"320723"},{name:"灌南县",code:"320724"}]},{name:"淮安市",code:"320800",sub:[{name:"市辖区",code:"320801"},{name:"清河区",code:"320802"},{name:"淮安区",code:"320803"},{name:"淮阴区",code:"320804"},{name:"清浦区",code:"320811"},{name:"涟水县",code:"320826"},{name:"洪泽县",code:"320829"},{name:"盱眙县",code:"320830"},{name:"金湖县",code:"320831"}]},{name:"盐城市",code:"320900",sub:[{name:"市辖区",code:"320901"},{name:"亭湖区",code:"320902"},{name:"盐都区",code:"320903"},{name:"响水县",code:"320921"},{name:"滨海县",code:"320922"},{name:"阜宁县",code:"320923"},{name:"射阳县",code:"320924"},{name:"建湖县",code:"320925"},{name:"东台市",code:"320981"},{name:"大丰市",code:"320982"}]},{name:"扬州市",code:"321000",sub:[{name:"市辖区",code:"321001"},{name:"广陵区",code:"321002"},{name:"邗江区",code:"321003"},{name:"江都区",code:"321012"},{name:"宝应县",code:"321023"},{name:"仪征市",code:"321081"},{name:"高邮市",code:"321084"}]},{name:"镇江市",code:"321100",sub:[{name:"市辖区",code:"321101"},{name:"京口区",code:"321102"},{name:"润州区",code:"321111"},{name:"丹徒区",code:"321112"},{name:"丹阳市",code:"321181"},{name:"扬中市",code:"321182"},{name:"句容市",code:"321183"}]},{name:"泰州市",code:"321200",sub:[{name:"市辖区",code:"321201"},{name:"海陵区",code:"321202"},{name:"高港区",code:"321203"},{name:"姜堰区",code:"321204"},{name:"兴化市",code:"321281"},{name:"靖江市",code:"321282"},{name:"泰兴市",code:"321283"}]},{name:"宿迁市",code:"321300",sub:[{name:"市辖区",code:"321301"},{name:"宿城区",code:"321302"},{name:"宿豫区",code:"321311"},{name:"沭阳县",code:"321322"},{name:"泗阳县",code:"321323"},{name:"泗洪县",code:"321324"}]}]},{name:"浙江省",code:"330000",sub:[{name:"杭州市",code:"330100",sub:[{name:"市辖区",code:"330101"},{name:"上城区",code:"330102"},{name:"下城区",code:"330103"},{name:"江干区",code:"330104"},{name:"拱墅区",code:"330105"},{name:"西湖区",code:"330106"},{name:"滨江区",code:"330108"},{name:"萧山区",code:"330109"},{name:"余杭区",code:"330110"},{name:"富阳区",code:"330111"},{name:"桐庐县",code:"330122"},{name:"淳安县",code:"330127"},{name:"建德市",code:"330182"},{name:"临安市",code:"330185"}]},{name:"宁波市",code:"330200",sub:[{name:"市辖区",code:"330201"},{name:"海曙区",code:"330203"},{name:"江东区",code:"330204"},{name:"江北区",code:"330205"},{name:"北仑区",code:"330206"},{name:"镇海区",code:"330211"},{name:"鄞州区",code:"330212"},{name:"象山县",code:"330225"},{name:"宁海县",code:"330226"},{name:"余姚市",code:"330281"},{name:"慈溪市",code:"330282"},{name:"奉化市",code:"330283"}]},{name:"温州市",code:"330300",sub:[{name:"市辖区",code:"330301"},{name:"鹿城区",code:"330302"},{name:"龙湾区",code:"330303"},{name:"瓯海区",code:"330304"},{name:"洞头县",code:"330322"},{name:"永嘉县",code:"330324"},{name:"平阳县",code:"330326"},{name:"苍南县",code:"330327"},{name:"文成县",code:"330328"},{name:"泰顺县",code:"330329"},{name:"瑞安市",code:"330381"},{name:"乐清市",code:"330382"}]},{name:"嘉兴市",code:"330400",sub:[{name:"市辖区",code:"330401"},{name:"南湖区",code:"330402"},{name:"秀洲区",code:"330411"},{name:"嘉善县",code:"330421"},{name:"海盐县",code:"330424"},{name:"海宁市",code:"330481"},{name:"平湖市",code:"330482"},{name:"桐乡市",code:"330483"}]},{name:"湖州市",code:"330500",sub:[{name:"市辖区",code:"330501"},{name:"吴兴区",code:"330502"},{name:"南浔区",code:"330503"},{name:"德清县",code:"330521"},{name:"长兴县",code:"330522"},{name:"安吉县",code:"330523"}]},{name:"绍兴市",code:"330600",sub:[{name:"市辖区",code:"330601"},{name:"越城区",code:"330602"},{name:"柯桥区",code:"330603"},{name:"上虞区",code:"330604"},{name:"新昌县",code:"330624"},{name:"诸暨市",code:"330681"},{name:"嵊州市",code:"330683"}]},{name:"金华市",code:"330700",sub:[{name:"市辖区",code:"330701"},{name:"婺城区",code:"330702"},{name:"金东区",code:"330703"},{name:"武义县",code:"330723"},{name:"浦江县",code:"330726"},{name:"磐安县",code:"330727"},{name:"兰溪市",code:"330781"},{name:"义乌市",code:"330782"},{name:"东阳市",code:"330783"},{name:"永康市",code:"330784"}]},{name:"衢州市",code:"330800",sub:[{name:"市辖区",code:"330801"},{name:"柯城区",code:"330802"},{name:"衢江区",code:"330803"},{name:"常山县",code:"330822"},{name:"开化县",code:"330824"},{name:"龙游县",code:"330825"},{name:"江山市",code:"330881"}]},{name:"舟山市",code:"330900",sub:[{name:"市辖区",code:"330901"},{name:"定海区",code:"330902"},{name:"普陀区",code:"330903"},{name:"岱山县",code:"330921"},{name:"嵊泗县",code:"330922"}]},{name:"台州市",code:"331000",sub:[{name:"市辖区",code:"331001"},{name:"椒江区",code:"331002"},{name:"黄岩区",code:"331003"},{name:"路桥区",code:"331004"},{name:"玉环县",code:"331021"},{name:"三门县",code:"331022"},{name:"天台县",code:"331023"},{name:"仙居县",code:"331024"},{name:"温岭市",code:"331081"},{name:"临海市",code:"331082"}]},{name:"丽水市",code:"331100",sub:[{name:"市辖区",code:"331101"},{name:"莲都区",code:"331102"},{name:"青田县",code:"331121"},{name:"缙云县",code:"331122"},{name:"遂昌县",code:"331123"},{name:"松阳县",code:"331124"},{name:"云和县",code:"331125"},{name:"庆元县",code:"331126"},{name:"景宁畲族自治县",code:"331127"},{name:"龙泉市",code:"331181"}]}]},{name:"安徽省",code:"340000",sub:[{name:"合肥市",code:"340100",sub:[{name:"市辖区",code:"340101"},{name:"瑶海区",code:"340102"},{name:"庐阳区",code:"340103"},{name:"蜀山区",code:"340104"},{name:"包河区",code:"340111"},{name:"长丰县",code:"340121"},{name:"肥东县",code:"340122"},{name:"肥西县",code:"340123"},{name:"庐江县",code:"340124"},{name:"巢湖市",code:"340181"}]},{name:"芜湖市",code:"340200",sub:[{name:"市辖区",code:"340201"},{name:"镜湖区",code:"340202"},{name:"弋江区",code:"340203"},{name:"鸠江区",code:"340207"},{name:"三山区",code:"340208"},{name:"芜湖县",code:"340221"},{name:"繁昌县",code:"340222"},{name:"南陵县",code:"340223"},{name:"无为县",code:"340225"}]},{name:"蚌埠市",code:"340300",sub:[{name:"市辖区",code:"340301"},{name:"龙子湖区",code:"340302"},{name:"蚌山区",code:"340303"},{name:"禹会区",code:"340304"},{name:"淮上区",code:"340311"},{name:"怀远县",code:"340321"},{name:"五河县",code:"340322"},{name:"固镇县",code:"340323"}]},{name:"淮南市",code:"340400",sub:[{name:"市辖区",code:"340401"},{name:"大通区",code:"340402"},{
+name:"田家庵区",code:"340403"},{name:"谢家集区",code:"340404"},{name:"八公山区",code:"340405"},{name:"潘集区",code:"340406"},{name:"凤台县",code:"340421"}]},{name:"马鞍山市",code:"340500",sub:[{name:"市辖区",code:"340501"},{name:"花山区",code:"340503"},{name:"雨山区",code:"340504"},{name:"博望区",code:"340506"},{name:"当涂县",code:"340521"},{name:"含山县",code:"340522"},{name:"和县",code:"340523"}]},{name:"淮北市",code:"340600",sub:[{name:"市辖区",code:"340601"},{name:"杜集区",code:"340602"},{name:"相山区",code:"340603"},{name:"烈山区",code:"340604"},{name:"濉溪县",code:"340621"}]},{name:"铜陵市",code:"340700",sub:[{name:"市辖区",code:"340701"},{name:"铜官山区",code:"340702"},{name:"狮子山区",code:"340703"},{name:"郊区",code:"340711"},{name:"铜陵县",code:"340721"}]},{name:"安庆市",code:"340800",sub:[{name:"市辖区",code:"340801"},{name:"迎江区",code:"340802"},{name:"大观区",code:"340803"},{name:"宜秀区",code:"340811"},{name:"怀宁县",code:"340822"},{name:"枞阳县",code:"340823"},{name:"潜山县",code:"340824"},{name:"太湖县",code:"340825"},{name:"宿松县",code:"340826"},{name:"望江县",code:"340827"},{name:"岳西县",code:"340828"},{name:"桐城市",code:"340881"}]},{name:"黄山市",code:"341000",sub:[{name:"市辖区",code:"341001"},{name:"屯溪区",code:"341002"},{name:"黄山区",code:"341003"},{name:"徽州区",code:"341004"},{name:"歙县",code:"341021"},{name:"休宁县",code:"341022"},{name:"黟县",code:"341023"},{name:"祁门县",code:"341024"}]},{name:"滁州市",code:"341100",sub:[{name:"市辖区",code:"341101"},{name:"琅琊区",code:"341102"},{name:"南谯区",code:"341103"},{name:"来安县",code:"341122"},{name:"全椒县",code:"341124"},{name:"定远县",code:"341125"},{name:"凤阳县",code:"341126"},{name:"天长市",code:"341181"},{name:"明光市",code:"341182"}]},{name:"阜阳市",code:"341200",sub:[{name:"市辖区",code:"341201"},{name:"颍州区",code:"341202"},{name:"颍东区",code:"341203"},{name:"颍泉区",code:"341204"},{name:"临泉县",code:"341221"},{name:"太和县",code:"341222"},{name:"阜南县",code:"341225"},{name:"颍上县",code:"341226"},{name:"界首市",code:"341282"}]},{name:"宿州市",code:"341300",sub:[{name:"市辖区",code:"341301"},{name:"埇桥区",code:"341302"},{name:"砀山县",code:"341321"},{name:"萧县",code:"341322"},{name:"灵璧县",code:"341323"},{name:"泗县",code:"341324"}]},{name:"六安市",code:"341500",sub:[{name:"市辖区",code:"341501"},{name:"金安区",code:"341502"},{name:"裕安区",code:"341503"},{name:"寿县",code:"341521"},{name:"霍邱县",code:"341522"},{name:"舒城县",code:"341523"},{name:"金寨县",code:"341524"},{name:"霍山县",code:"341525"}]},{name:"亳州市",code:"341600",sub:[{name:"市辖区",code:"341601"},{name:"谯城区",code:"341602"},{name:"涡阳县",code:"341621"},{name:"蒙城县",code:"341622"},{name:"利辛县",code:"341623"}]},{name:"池州市",code:"341700",sub:[{name:"市辖区",code:"341701"},{name:"贵池区",code:"341702"},{name:"东至县",code:"341721"},{name:"石台县",code:"341722"},{name:"青阳县",code:"341723"}]},{name:"宣城市",code:"341800",sub:[{name:"市辖区",code:"341801"},{name:"宣州区",code:"341802"},{name:"郎溪县",code:"341821"},{name:"广德县",code:"341822"},{name:"泾县",code:"341823"},{name:"绩溪县",code:"341824"},{name:"旌德县",code:"341825"},{name:"宁国市",code:"341881"}]}]},{name:"福建省",code:"350000",sub:[{name:"福州市",code:"350100",sub:[{name:"市辖区",code:"350101"},{name:"鼓楼区",code:"350102"},{name:"台江区",code:"350103"},{name:"仓山区",code:"350104"},{name:"马尾区",code:"350105"},{name:"晋安区",code:"350111"},{name:"闽侯县",code:"350121"},{name:"连江县",code:"350122"},{name:"罗源县",code:"350123"},{name:"闽清县",code:"350124"},{name:"永泰县",code:"350125"},{name:"平潭县",code:"350128"},{name:"福清市",code:"350181"},{name:"长乐市",code:"350182"}]},{name:"厦门市",code:"350200",sub:[{name:"市辖区",code:"350201"},{name:"思明区",code:"350203"},{name:"海沧区",code:"350205"},{name:"湖里区",code:"350206"},{name:"集美区",code:"350211"},{name:"同安区",code:"350212"},{name:"翔安区",code:"350213"}]},{name:"莆田市",code:"350300",sub:[{name:"市辖区",code:"350301"},{name:"城厢区",code:"350302"},{name:"涵江区",code:"350303"},{name:"荔城区",code:"350304"},{name:"秀屿区",code:"350305"},{name:"仙游县",code:"350322"}]},{name:"三明市",code:"350400",sub:[{name:"市辖区",code:"350401"},{name:"梅列区",code:"350402"},{name:"三元区",code:"350403"},{name:"明溪县",code:"350421"},{name:"清流县",code:"350423"},{name:"宁化县",code:"350424"},{name:"大田县",code:"350425"},{name:"尤溪县",code:"350426"},{name:"沙县",code:"350427"},{name:"将乐县",code:"350428"},{name:"泰宁县",code:"350429"},{name:"建宁县",code:"350430"},{name:"永安市",code:"350481"}]},{name:"泉州市",code:"350500",sub:[{name:"市辖区",code:"350501"},{name:"鲤城区",code:"350502"},{name:"丰泽区",code:"350503"},{name:"洛江区",code:"350504"},{name:"泉港区",code:"350505"},{name:"惠安县",code:"350521"},{name:"安溪县",code:"350524"},{name:"永春县",code:"350525"},{name:"德化县",code:"350526"},{name:"金门县",code:"350527"},{name:"石狮市",code:"350581"},{name:"晋江市",code:"350582"},{name:"南安市",code:"350583"}]},{name:"漳州市",code:"350600",sub:[{name:"市辖区",code:"350601"},{name:"芗城区",code:"350602"},{name:"龙文区",code:"350603"},{name:"云霄县",code:"350622"},{name:"漳浦县",code:"350623"},{name:"诏安县",code:"350624"},{name:"长泰县",code:"350625"},{name:"东山县",code:"350626"},{name:"南靖县",code:"350627"},{name:"平和县",code:"350628"},{name:"华安县",code:"350629"},{name:"龙海市",code:"350681"}]},{name:"南平市",code:"350700",sub:[{name:"市辖区",code:"350701"},{name:"延平区",code:"350702"},{name:"建阳区",code:"350703"},{name:"顺昌县",code:"350721"},{name:"浦城县",code:"350722"},{name:"光泽县",code:"350723"},{name:"松溪县",code:"350724"},{name:"政和县",code:"350725"},{name:"邵武市",code:"350781"},{name:"武夷山市",code:"350782"},{name:"建瓯市",code:"350783"}]},{name:"龙岩市",code:"350800",sub:[{name:"市辖区",code:"350801"},{name:"新罗区",code:"350802"},{name:"永定区",code:"350803"},{name:"长汀县",code:"350821"},{name:"上杭县",code:"350823"},{name:"武平县",code:"350824"},{name:"连城县",code:"350825"},{name:"漳平市",code:"350881"}]},{name:"宁德市",code:"350900",sub:[{name:"市辖区",code:"350901"},{name:"蕉城区",code:"350902"},{name:"霞浦县",code:"350921"},{name:"古田县",code:"350922"},{name:"屏南县",code:"350923"},{name:"寿宁县",code:"350924"},{name:"周宁县",code:"350925"},{name:"柘荣县",code:"350926"},{name:"福安市",code:"350981"},{name:"福鼎市",code:"350982"}]}]},{name:"江西省",code:"360000",sub:[{name:"南昌市",code:"360100",sub:[{name:"市辖区",code:"360101"},{name:"东湖区",code:"360102"},{name:"西湖区",code:"360103"},{name:"青云谱区",code:"360104"},{name:"湾里区",code:"360105"},{name:"青山湖区",code:"360111"},{name:"南昌县",code:"360121"},{name:"新建县",code:"360122"},{name:"安义县",code:"360123"},{name:"进贤县",code:"360124"}]},{name:"景德镇市",code:"360200",sub:[{name:"市辖区",code:"360201"},{name:"昌江区",code:"360202"},{name:"珠山区",code:"360203"},{name:"浮梁县",code:"360222"},{name:"乐平市",code:"360281"}]},{name:"萍乡市",code:"360300",sub:[{name:"市辖区",code:"360301"},{name:"安源区",code:"360302"},{name:"湘东区",code:"360313"},{name:"莲花县",code:"360321"},{name:"上栗县",code:"360322"},{name:"芦溪县",code:"360323"}]},{name:"九江市",code:"360400",sub:[{name:"市辖区",code:"360401"},{name:"庐山区",code:"360402"},{name:"浔阳区",code:"360403"},{name:"九江县",code:"360421"},{name:"武宁县",code:"360423"},{name:"修水县",code:"360424"},{name:"永修县",code:"360425"},{name:"德安县",code:"360426"},{name:"星子县",code:"360427"},{name:"都昌县",code:"360428"},{name:"湖口县",code:"360429"},{name:"彭泽县",code:"360430"},{name:"瑞昌市",code:"360481"},{name:"共青城市",code:"360482"}]},{name:"新余市",code:"360500",sub:[{name:"市辖区",code:"360501"},{name:"渝水区",code:"360502"},{name:"分宜县",code:"360521"}]},{name:"鹰潭市",code:"360600",sub:[{name:"市辖区",code:"360601"},{name:"月湖区",code:"360602"},{name:"余江县",code:"360622"},{name:"贵溪市",code:"360681"}]},{name:"赣州市",code:"360700",sub:[{name:"市辖区",code:"360701"},{name:"章贡区",code:"360702"},{name:"南康区",code:"360703"},{name:"赣县",code:"360721"},{name:"信丰县",code:"360722"},{name:"大余县",code:"360723"},{name:"上犹县",code:"360724"},{name:"崇义县",code:"360725"},{name:"安远县",code:"360726"},{name:"龙南县",code:"360727"},{name:"定南县",code:"360728"},{name:"全南县",code:"360729"},{name:"宁都县",code:"360730"},{name:"于都县",code:"360731"},{name:"兴国县",code:"360732"},{name:"会昌县",code:"360733"},{name:"寻乌县",code:"360734"},{name:"石城县",code:"360735"},{name:"瑞金市",code:"360781"}]},{name:"吉安市",code:"360800",sub:[{name:"市辖区",code:"360801"},{name:"吉州区",code:"360802"},{name:"青原区",code:"360803"},{name:"吉安县",code:"360821"},{name:"吉水县",code:"360822"},{name:"峡江县",code:"360823"},{name:"新干县",code:"360824"},{name:"永丰县",code:"360825"},{name:"泰和县",code:"360826"},{name:"遂川县",code:"360827"},{name:"万安县",code:"360828"},{name:"安福县",code:"360829"},{name:"永新县",code:"360830"},{name:"井冈山市",code:"360881"}]},{name:"宜春市",code:"360900",sub:[{name:"市辖区",code:"360901"},{name:"袁州区",code:"360902"},{name:"奉新县",code:"360921"},{name:"万载县",code:"360922"},{name:"上高县",code:"360923"},{name:"宜丰县",code:"360924"},{name:"靖安县",code:"360925"},{name:"铜鼓县",code:"360926"},{name:"丰城市",code:"360981"},{name:"樟树市",code:"360982"},{name:"高安市",code:"360983"}]},{name:"抚州市",code:"361000",sub:[{name:"市辖区",code:"361001"},{name:"临川区",code:"361002"},{name:"南城县",code:"361021"},{name:"黎川县",code:"361022"},{name:"南丰县",code:"361023"},{name:"崇仁县",code:"361024"},{name:"乐安县",code:"361025"},{name:"宜黄县",code:"361026"},{name:"金溪县",code:"361027"},{name:"资溪县",code:"361028"},{name:"东乡县",code:"361029"},{name:"广昌县",code:"361030"}]},{name:"上饶市",code:"361100",sub:[{name:"市辖区",code:"361101"},{name:"信州区",code:"361102"},{name:"上饶县",code:"361121"},{name:"广丰县",code:"361122"},{name:"玉山县",code:"361123"},{name:"铅山县",code:"361124"},{name:"横峰县",code:"361125"},{name:"弋阳县",code:"361126"},{name:"余干县",code:"361127"},{name:"鄱阳县",code:"361128"},{name:"万年县",code:"361129"},{name:"婺源县",code:"361130"},{name:"德兴市",code:"361181"}]}]},{name:"山东省",code:"370000",sub:[{name:"济南市",code:"370100",sub:[{name:"市辖区",code:"370101"},{name:"历下区",code:"370102"},{name:"市中区",code:"370103"},{name:"槐荫区",code:"370104"},{name:"天桥区",code:"370105"},{name:"历城区",code:"370112"},{name:"长清区",code:"370113"},{name:"平阴县",code:"370124"},{name:"济阳县",code:"370125"},{name:"商河县",code:"370126"},{name:"章丘市",code:"370181"}]},{name:"青岛市",code:"370200",sub:[{name:"市辖区",code:"370201"},{name:"市南区",code:"370202"},{name:"市北区",code:"370203"},{name:"黄岛区",code:"370211"},{name:"崂山区",code:"370212"},{name:"李沧区",code:"370213"},{name:"城阳区",code:"370214"},{name:"胶州市",code:"370281"},{name:"即墨市",code:"370282"},{name:"平度市",code:"370283"},{name:"莱西市",code:"370285"}]},{name:"淄博市",code:"370300",sub:[{name:"市辖区",code:"370301"},{name:"淄川区",code:"370302"},{name:"张店区",code:"370303"},{name:"博山区",code:"370304"},{name:"临淄区",code:"370305"},{name:"周村区",code:"370306"},{name:"桓台县",code:"370321"},{name:"高青县",code:"370322"},{name:"沂源县",code:"370323"}]},{name:"枣庄市",code:"370400",sub:[{name:"市辖区",code:"370401"},{name:"市中区",code:"370402"},{name:"薛城区",code:"370403"},{name:"峄城区",code:"370404"},{name:"台儿庄区",code:"370405"},{name:"山亭区",code:"370406"},{name:"滕州市",code:"370481"}]},{name:"东营市",code:"370500",sub:[{name:"市辖区",code:"370501"},{name:"东营区",code:"370502"},{name:"河口区",code:"370503"},{name:"垦利县",code:"370521"},{name:"利津县",code:"370522"},{name:"广饶县",code:"370523"}]},{name:"烟台市",code:"370600",sub:[{name:"市辖区",code:"370601"},{name:"芝罘区",code:"370602"},{name:"福山区",code:"370611"},{name:"牟平区",code:"370612"},{name:"莱山区",code:"370613"},{name:"长岛县",code:"370634"},{name:"龙口市",code:"370681"},{name:"莱阳市",code:"370682"},{name:"莱州市",code:"370683"},{name:"蓬莱市",code:"370684"},{name:"招远市",code:"370685"},{name:"栖霞市",code:"370686"},{name:"海阳市",code:"370687"}]},{name:"潍坊市",code:"370700",sub:[{name:"市辖区",code:"370701"},{name:"潍城区",code:"370702"},{name:"寒亭区",code:"370703"},{name:"坊子区",code:"370704"},{name:"奎文区",code:"370705"},{name:"临朐县",code:"370724"},{name:"昌乐县",code:"370725"},{name:"青州市",code:"370781"},{name:"诸城市",code:"370782"},{name:"寿光市",code:"370783"},{name:"安丘市",code:"370784"},{name:"高密市",code:"370785"},{name:"昌邑市",code:"370786"}]},{name:"济宁市",code:"370800",sub:[{name:"市辖区",code:"370801"},{name:"任城区",code:"370811"},{name:"兖州区",code:"370812"},{name:"微山县",code:"370826"},{name:"鱼台县",code:"370827"},{name:"金乡县",code:"370828"},{name:"嘉祥县",code:"370829"},{name:"汶上县",code:"370830"},{name:"泗水县",code:"370831"},{name:"梁山县",code:"370832"},{name:"曲阜市",code:"370881"},{name:"邹城市",code:"370883"}]},{name:"泰安市",code:"370900",sub:[{name:"市辖区",code:"370901"},{name:"泰山区",code:"370902"},{name:"岱岳区",code:"370911"},{name:"宁阳县",code:"370921"},{name:"东平县",code:"370923"},{name:"新泰市",code:"370982"},{name:"肥城市",code:"370983"}]},{name:"威海市",code:"371000",sub:[{name:"市辖区",code:"371001"},{name:"环翠区",code:"371002"},{name:"文登市",code:"371081"},{name:"荣成市",code:"371082"},{name:"乳山市",code:"371083"}]},{name:"日照市",code:"371100",sub:[{name:"市辖区",code:"371101"},{name:"东港区",code:"371102"},{name:"岚山区",code:"371103"},{name:"五莲县",code:"371121"},{name:"莒县",code:"371122"}]},{name:"莱芜市",code:"371200",sub:[{name:"市辖区",code:"371201"},{name:"莱城区",code:"371202"},{name:"钢城区",code:"371203"}]},{name:"临沂市",code:"371300",sub:[{name:"市辖区",code:"371301"},{name:"兰山区",code:"371302"},{name:"罗庄区",code:"371311"},{name:"河东区",code:"371312"},{name:"沂南县",code:"371321"},{name:"郯城县",code:"371322"},{name:"沂水县",code:"371323"},{name:"兰陵县",code:"371324"},{name:"费县",code:"371325"},{name:"平邑县",code:"371326"},{name:"莒南县",code:"371327"},{name:"蒙阴县",code:"371328"},{name:"临沭县",code:"371329"}]},{name:"德州市",code:"371400",sub:[{name:"市辖区",code:"371401"},{name:"德城区",code:"371402"},{name:"陵城区",code:"371403"},{name:"宁津县",code:"371422"},{name:"庆云县",code:"371423"},{name:"临邑县",code:"371424"},{name:"齐河县",code:"371425"},{name:"平原县",code:"371426"},{name:"夏津县",code:"371427"},{name:"武城县",code:"371428"},{name:"乐陵市",code:"371481"},{name:"禹城市",code:"371482"}]},{name:"聊城市",code:"371500",sub:[{name:"市辖区",code:"371501"},{name:"东昌府区",code:"371502"},{name:"阳谷县",code:"371521"},{name:"莘县",code:"371522"},{name:"茌平县",code:"371523"},{name:"东阿县",code:"371524"},{name:"冠县",code:"371525"},{name:"高唐县",code:"371526"},{name:"临清市",code:"371581"}]},{name:"滨州市",code:"371600",sub:[{name:"市辖区",code:"371601"},{name:"滨城区",code:"371602"},{name:"沾化区",code:"371603"},{name:"惠民县",code:"371621"},{name:"阳信县",code:"371622"},{name:"无棣县",code:"371623"},{name:"博兴县",code:"371625"},{name:"邹平县",code:"371626"}]},{name:"菏泽市",code:"371700",sub:[{name:"市辖区",code:"371701"},{name:"牡丹区",code:"371702"},{name:"曹县",code:"371721"},{name:"单县",code:"371722"},{name:"成武县",code:"371723"},{name:"巨野县",code:"371724"},{name:"郓城县",code:"371725"},{name:"鄄城县",code:"371726"},{name:"定陶县",code:"371727"},{name:"东明县",code:"371728"}]}]},{name:"河南省",code:"410000",sub:[{name:"郑州市",code:"410100",sub:[{name:"市辖区",code:"410101"},{name:"中原区",code:"410102"},{name:"二七区",code:"410103"},{name:"管城回族区",code:"410104"},{name:"金水区",code:"410105"},{name:"上街区",code:"410106"},{name:"惠济区",code:"410108"},{name:"中牟县",code:"410122"},{name:"巩义市",code:"410181"},{name:"荥阳市",code:"410182"},{name:"新密市",code:"410183"},{name:"新郑市",code:"410184"},{name:"登封市",code:"410185"}]},{name:"开封市",code:"410200",sub:[{name:"市辖区",code:"410201"},{name:"龙亭区",code:"410202"},{name:"顺河回族区",code:"410203"},{name:"鼓楼区",code:"410204"},{name:"禹王台区",code:"410205"},{name:"祥符区",code:"410212"},{name:"杞县",code:"410221"},{name:"通许县",code:"410222"},{name:"尉氏县",code:"410223"},{name:"兰考县",code:"410225"}]},{name:"洛阳市",code:"410300",sub:[{name:"市辖区",code:"410301"},{name:"老城区",code:"410302"},{name:"西工区",code:"410303"},{name:"瀍河回族区",code:"410304"},{name:"涧西区",code:"410305"},{name:"吉利区",code:"410306"},{name:"洛龙区",code:"410311"},{name:"孟津县",code:"410322"},{name:"新安县",code:"410323"},{name:"栾川县",code:"410324"},{name:"嵩县",code:"410325"},{name:"汝阳县",code:"410326"},{name:"宜阳县",code:"410327"},{name:"洛宁县",code:"410328"},{name:"伊川县",code:"410329"},{name:"偃师市",code:"410381"}]},{name:"平顶山市",code:"410400",sub:[{name:"市辖区",code:"410401"},{name:"新华区",code:"410402"},{name:"卫东区",code:"410403"},{name:"石龙区",code:"410404"},{name:"湛河区",code:"410411"},{name:"宝丰县",code:"410421"},{name:"叶县",code:"410422"},{name:"鲁山县",code:"410423"},{name:"郏县",code:"410425"},{name:"舞钢市",code:"410481"},{name:"汝州市",code:"410482"}]},{name:"安阳市",code:"410500",sub:[{name:"市辖区",code:"410501"},{name:"文峰区",code:"410502"},{name:"北关区",code:"410503"},{name:"殷都区",code:"410505"},{name:"龙安区",code:"410506"},{name:"安阳县",code:"410522"},{name:"汤阴县",code:"410523"},{name:"滑县",code:"410526"},{name:"内黄县",code:"410527"},{name:"林州市",code:"410581"}]},{name:"鹤壁市",code:"410600",sub:[{name:"市辖区",code:"410601"},{name:"鹤山区",code:"410602"},{name:"山城区",code:"410603"},{name:"淇滨区",code:"410611"},{name:"浚县",code:"410621"},{name:"淇县",code:"410622"}]},{name:"新乡市",code:"410700",sub:[{name:"市辖区",code:"410701"},{name:"红旗区",code:"410702"},{name:"卫滨区",code:"410703"},{name:"凤泉区",code:"410704"},{name:"牧野区",code:"410711"},{name:"新乡县",code:"410721"},{name:"获嘉县",code:"410724"},{name:"原阳县",code:"410725"},{name:"延津县",code:"410726"},{name:"封丘县",code:"410727"},{name:"长垣县",code:"410728"},{name:"卫辉市",code:"410781"},{name:"辉县市",code:"410782"}]},{name:"焦作市",code:"410800",sub:[{name:"市辖区",code:"410801"},{name:"解放区",code:"410802"},{name:"中站区",code:"410803"},{name:"马村区",code:"410804"},{name:"山阳区",code:"410811"},{name:"修武县",code:"410821"},{name:"博爱县",code:"410822"},{name:"武陟县",code:"410823"},{name:"温县",code:"410825"},{name:"沁阳市",code:"410882"},{name:"孟州市",code:"410883"}]},{name:"濮阳市",code:"410900",sub:[{name:"市辖区",code:"410901"},{name:"华龙区",code:"410902"},{name:"清丰县",code:"410922"},{name:"南乐县",code:"410923"},{name:"范县",code:"410926"},{name:"台前县",code:"410927"},{name:"濮阳县",code:"410928"}]},{name:"许昌市",code:"411000",sub:[{name:"市辖区",code:"411001"},{name:"魏都区",code:"411002"},{name:"许昌县",code:"411023"},{name:"鄢陵县",code:"411024"},{name:"襄城县",code:"411025"},{name:"禹州市",code:"411081"},{name:"长葛市",code:"411082"}]},{name:"漯河市",code:"411100",sub:[{name:"市辖区",code:"411101"},{name:"源汇区",code:"411102"},{name:"郾城区",code:"411103"},{name:"召陵区",code:"411104"},{name:"舞阳县",code:"411121"},{name:"临颍县",code:"411122"}]},{name:"三门峡市",code:"411200",sub:[{name:"市辖区",code:"411201"},{name:"湖滨区",code:"411202"},{name:"渑池县",code:"411221"},{name:"陕县",code:"411222"},{name:"卢氏县",code:"411224"},{name:"义马市",code:"411281"},{name:"灵宝市",code:"411282"}]},{name:"南阳市",code:"411300",sub:[{name:"市辖区",code:"411301"},{name:"宛城区",code:"411302"},{name:"卧龙区",code:"411303"},{name:"南召县",code:"411321"},{name:"方城县",code:"411322"},{name:"西峡县",code:"411323"},{name:"镇平县",code:"411324"},{name:"内乡县",code:"411325"},{name:"淅川县",code:"411326"},{name:"社旗县",code:"411327"},{name:"唐河县",code:"411328"},{name:"新野县",code:"411329"},{name:"桐柏县",code:"411330"},{name:"邓州市",code:"411381"}]},{name:"商丘市",code:"411400",sub:[{name:"市辖区",code:"411401"},{name:"梁园区",code:"411402"},{name:"睢阳区",code:"411403"},{name:"民权县",code:"411421"},{name:"睢县",code:"411422"},{name:"宁陵县",code:"411423"},{name:"柘城县",code:"411424"},{name:"虞城县",code:"411425"},{name:"夏邑县",code:"411426"},{name:"永城市",code:"411481"}]},{name:"信阳市",code:"411500",sub:[{name:"市辖区",code:"411501"},{name:"浉河区",code:"411502"},{name:"平桥区",code:"411503"},{name:"罗山县",code:"411521"},{name:"光山县",code:"411522"},{name:"新县",code:"411523"},{name:"商城县",code:"411524"},{name:"固始县",code:"411525"},{name:"潢川县",code:"411526"},{name:"淮滨县",code:"411527"},{name:"息县",code:"411528"}]},{name:"周口市",code:"411600",sub:[{name:"市辖区",code:"411601"},{name:"川汇区",code:"411602"},{name:"扶沟县",code:"411621"},{name:"西华县",code:"411622"},{name:"商水县",code:"411623"},{name:"沈丘县",code:"411624"},{name:"郸城县",code:"411625"},{name:"淮阳县",code:"411626"},{name:"太康县",code:"411627"},{name:"鹿邑县",code:"411628"},{name:"项城市",code:"411681"}]},{name:"驻马店市",code:"411700",sub:[{name:"市辖区",code:"411701"},{name:"驿城区",code:"411702"},{name:"西平县",code:"411721"},{name:"上蔡县",code:"411722"},{name:"平舆县",code:"411723"},{name:"正阳县",code:"411724"},{name:"确山县",code:"411725"},{name:"泌阳县",code:"411726"},{name:"汝南县",code:"411727"},{name:"遂平县",code:"411728"},{name:"新蔡县",code:"411729"}]},{name:"济源市",code:"419001"}]},{name:"湖北省",code:"420000",sub:[{name:"武汉市",code:"420100",sub:[{name:"市辖区",code:"420101"},{name:"江岸区",code:"420102"},{name:"江汉区",code:"420103"},{name:"硚口区",code:"420104"},{name:"汉阳区",code:"420105"},{name:"武昌区",code:"420106"},{name:"青山区",code:"420107"},{name:"洪山区",code:"420111"},{name:"东西湖区",code:"420112"},{name:"汉南区",code:"420113"},{name:"蔡甸区",code:"420114"},{name:"江夏区",code:"420115"},{name:"黄陂区",code:"420116"},{name:"新洲区",code:"420117"}]},{name:"黄石市",code:"420200",sub:[{name:"市辖区",code:"420201"},{name:"黄石港区",code:"420202"},{name:"西塞山区",code:"420203"},{name:"下陆区",code:"420204"},{name:"铁山区",code:"420205"},{name:"阳新县",code:"420222"},{name:"大冶市",code:"420281"}]},{name:"十堰市",code:"420300",sub:[{name:"市辖区",code:"420301"},{name:"茅箭区",code:"420302"},{name:"张湾区",code:"420303"},{name:"郧阳区",code:"420304"},{name:"郧西县",code:"420322"},{name:"竹山县",code:"420323"},{name:"竹溪县",code:"420324"},{name:"房县",code:"420325"},{name:"丹江口市",code:"420381"}]},{name:"宜昌市",code:"420500",sub:[{name:"市辖区",code:"420501"},{name:"西陵区",code:"420502"},{name:"伍家岗区",code:"420503"},{name:"点军区",code:"420504"},{name:"猇亭区",code:"420505"},{name:"夷陵区",code:"420506"},{name:"远安县",code:"420525"},{name:"兴山县",code:"420526"},{name:"秭归县",code:"420527"},{name:"长阳土家族自治县",code:"420528"},{name:"五峰土家族自治县",code:"420529"},{name:"宜都市",code:"420581"},{name:"当阳市",code:"420582"},{name:"枝江市",code:"420583"}]},{name:"襄阳市",code:"420600",sub:[{name:"市辖区",code:"420601"},{name:"襄城区",code:"420602"},{name:"樊城区",code:"420606"},{name:"襄州区",code:"420607"},{name:"南漳县",code:"420624"},{name:"谷城县",code:"420625"},{name:"保康县",code:"420626"},{name:"老河口市",code:"420682"},{name:"枣阳市",code:"420683"},{name:"宜城市",code:"420684"}]},{name:"鄂州市",code:"420700",sub:[{name:"市辖区",code:"420701"},{name:"梁子湖区",code:"420702"},{name:"华容区",code:"420703"},{name:"鄂城区",code:"420704"}]},{name:"荆门市",code:"420800",sub:[{name:"市辖区",code:"420801"},{name:"东宝区",code:"420802"},{name:"掇刀区",code:"420804"},{name:"京山县",code:"420821"},{name:"沙洋县",code:"420822"},{name:"钟祥市",code:"420881"}]},{name:"孝感市",code:"420900",sub:[{name:"市辖区",code:"420901"},{name:"孝南区",code:"420902"},{name:"孝昌县",code:"420921"},{name:"大悟县",code:"420922"},{name:"云梦县",code:"420923"},{name:"应城市",code:"420981"},{name:"安陆市",code:"420982"},{name:"汉川市",code:"420984"}]},{name:"荆州市",code:"421000",sub:[{name:"市辖区",code:"421001"},{name:"沙市区",code:"421002"},{name:"荆州区",code:"421003"},{name:"公安县",code:"421022"},{name:"监利县",code:"421023"},{name:"江陵县",code:"421024"},{name:"石首市",code:"421081"},{name:"洪湖市",code:"421083"},{name:"松滋市",code:"421087"}]},{name:"黄冈市",code:"421100",sub:[{name:"市辖区",code:"421101"},{name:"黄州区",code:"421102"},{name:"团风县",code:"421121"},{name:"红安县",code:"421122"},{name:"罗田县",code:"421123"},{name:"英山县",code:"421124"},{name:"浠水县",code:"421125"},{name:"蕲春县",code:"421126"},{name:"黄梅县",code:"421127"},{name:"麻城市",code:"421181"},{name:"武穴市",code:"421182"}]},{name:"咸宁市",code:"421200",sub:[{name:"市辖区",code:"421201"},{name:"咸安区",code:"421202"},{name:"嘉鱼县",code:"421221"},{name:"通城县",code:"421222"},{name:"崇阳县",code:"421223"},{name:"通山县",code:"421224"},{name:"赤壁市",code:"421281"}]},{name:"随州市",code:"421300",sub:[{name:"市辖区",code:"421301"},{name:"曾都区",code:"421303"},{name:"随县",code:"421321"},{name:"广水市",code:"421381"}]},{name:"恩施土家族苗族自治州",code:"422800",sub:[{name:"恩施市",code:"422801"},{name:"利川市",code:"422802"},{name:"建始县",code:"422822"},{name:"巴东县",code:"422823"},{name:"宣恩县",code:"422825"},{name:"咸丰县",code:"422826"},{name:"来凤县",code:"422827"},{name:"鹤峰县",code:"422828"}]},{name:"仙桃市",code:"429004"},{name:"潜江市",code:"429005"},{name:"天门市",code:"429006"},{name:"神农架林区",code:"429021"}]},{name:"湖南省",code:"430000",sub:[{name:"长沙市",code:"430100",sub:[{name:"市辖区",code:"430101"},{name:"芙蓉区",code:"430102"},{name:"天心区",code:"430103"},{name:"岳麓区",code:"430104"},{name:"开福区",code:"430105"},{name:"雨花区",code:"430111"},{name:"望城区",code:"430112"},{name:"长沙县",code:"430121"},{name:"宁乡县",code:"430124"},{name:"浏阳市",code:"430181"}]},{name:"株洲市",code:"430200",sub:[{name:"市辖区",code:"430201"},{name:"荷塘区",code:"430202"},{name:"芦淞区",code:"430203"},{name:"石峰区",code:"430204"},{name:"天元区",code:"430211"},{name:"株洲县",code:"430221"},{name:"攸县",code:"430223"},{name:"茶陵县",code:"430224"},{name:"炎陵县",code:"430225"},{name:"醴陵市",code:"430281"}]},{name:"湘潭市",code:"430300",sub:[{name:"市辖区",code:"430301"},{name:"雨湖区",code:"430302"},{name:"岳塘区",code:"430304"},{name:"湘潭县",code:"430321"},{name:"湘乡市",code:"430381"},{name:"韶山市",code:"430382"}]},{name:"衡阳市",code:"430400",sub:[{name:"市辖区",code:"430401"},{name:"珠晖区",code:"430405"},{name:"雁峰区",code:"430406"},{name:"石鼓区",code:"430407"},{name:"蒸湘区",code:"430408"},{name:"南岳区",code:"430412"},{name:"衡阳县",code:"430421"},{name:"衡南县",code:"430422"},{name:"衡山县",code:"430423"},{name:"衡东县",code:"430424"},{name:"祁东县",code:"430426"},{name:"耒阳市",code:"430481"},{name:"常宁市",code:"430482"}]},{name:"邵阳市",code:"430500",sub:[{name:"市辖区",code:"430501"},{name:"双清区",code:"430502"},{name:"大祥区",code:"430503"},{name:"北塔区",code:"430511"},{name:"邵东县",code:"430521"},{name:"新邵县",code:"430522"},{name:"邵阳县",code:"430523"},{name:"隆回县",code:"430524"},{name:"洞口县",code:"430525"},{name:"绥宁县",code:"430527"},{name:"新宁县",code:"430528"},{name:"城步苗族自治县",code:"430529"},{name:"武冈市",code:"430581"}]},{name:"岳阳市",code:"430600",sub:[{name:"市辖区",code:"430601"},{name:"岳阳楼区",code:"430602"},{name:"云溪区",code:"430603"},{name:"君山区",code:"430611"},{name:"岳阳县",code:"430621"},{name:"华容县",code:"430623"},{name:"湘阴县",code:"430624"},{name:"平江县",code:"430626"},{name:"汨罗市",code:"430681"},{name:"临湘市",code:"430682"}]},{name:"常德市",code:"430700",sub:[{name:"市辖区",code:"430701"},{name:"武陵区",code:"430702"},{name:"鼎城区",code:"430703"},{name:"安乡县",code:"430721"},{name:"汉寿县",code:"430722"},{name:"澧县",code:"430723"},{name:"临澧县",code:"430724"},{name:"桃源县",code:"430725"},{name:"石门县",code:"430726"},{name:"津市市",code:"430781"}]},{name:"张家界市",code:"430800",sub:[{name:"市辖区",code:"430801"},{name:"永定区",code:"430802"},{name:"武陵源区",code:"430811"},{name:"慈利县",code:"430821"},{name:"桑植县",code:"430822"}]},{name:"益阳市",code:"430900",sub:[{name:"市辖区",code:"430901"},{name:"资阳区",code:"430902"},{name:"赫山区",code:"430903"},{name:"南县",code:"430921"},{name:"桃江县",code:"430922"},{name:"安化县",code:"430923"},{name:"沅江市",code:"430981"}]},{name:"郴州市",code:"431000",sub:[{name:"市辖区",code:"431001"},{name:"北湖区",code:"431002"},{name:"苏仙区",code:"431003"},{name:"桂阳县",code:"431021"},{name:"宜章县",code:"431022"},{name:"永兴县",code:"431023"},{name:"嘉禾县",code:"431024"},{name:"临武县",code:"431025"},{name:"汝城县",code:"431026"},{name:"桂东县",code:"431027"},{name:"安仁县",code:"431028"},{name:"资兴市",code:"431081"}]},{name:"永州市",code:"431100",sub:[{name:"市辖区",code:"431101"},{name:"零陵区",code:"431102"},{name:"冷水滩区",code:"431103"},{name:"祁阳县",code:"431121"},{name:"东安县",code:"431122"},{name:"双牌县",code:"431123"},{name:"道县",code:"431124"},{name:"江永县",code:"431125"},{name:"宁远县",code:"431126"},{name:"蓝山县",code:"431127"},{name:"新田县",code:"431128"},{name:"江华瑶族自治县",code:"431129"}]},{name:"怀化市",code:"431200",sub:[{name:"市辖区",code:"431201"},{name:"鹤城区",code:"431202"},{name:"中方县",code:"431221"},{name:"沅陵县",code:"431222"},{name:"辰溪县",code:"431223"},{name:"溆浦县",code:"431224"},{name:"会同县",code:"431225"},{name:"麻阳苗族自治县",code:"431226"},{name:"新晃侗族自治县",code:"431227"},{name:"芷江侗族自治县",code:"431228"},{name:"靖州苗族侗族自治县",code:"431229"},{name:"通道侗族自治县",code:"431230"},{name:"洪江市",code:"431281"}]},{name:"娄底市",code:"431300",sub:[{name:"市辖区",code:"431301"},{name:"娄星区",code:"431302"},{name:"双峰县",code:"431321"},{name:"新化县",code:"431322"},{name:"冷水江市",code:"431381"},{name:"涟源市",code:"431382"}]},{name:"湘西土家族苗族自治州",code:"433100",sub:[{name:"吉首市",code:"433101"},{name:"泸溪县",code:"433122"},{name:"凤凰县",code:"433123"},{name:"花垣县",code:"433124"},{name:"保靖县",code:"433125"},{name:"古丈县",code:"433126"},{name:"永顺县",code:"433127"},{name:"龙山县",code:"433130"}]}]},{name:"广东省",code:"440000",sub:[{name:"广州市",code:"440100",sub:[{name:"市辖区",code:"440101"},{name:"荔湾区",code:"440103"},{name:"越秀区",code:"440104"},{name:"海珠区",code:"440105"},{name:"天河区",code:"440106"},{name:"白云区",code:"440111"},{name:"黄埔区",code:"440112"},{name:"番禺区",code:"440113"},{name:"花都区",code:"440114"},{name:"南沙区",code:"440115"},{name:"从化区",code:"440117"},{name:"增城区",code:"440118"}]},{name:"韶关市",code:"440200",sub:[{name:"市辖区",code:"440201"},{name:"武江区",code:"440203"},{name:"浈江区",code:"440204"},{name:"曲江区",code:"440205"},{name:"始兴县",code:"440222"},{name:"仁化县",code:"440224"},{name:"翁源县",code:"440229"},{name:"乳源瑶族自治县",code:"440232"},{name:"新丰县",code:"440233"},{name:"乐昌市",code:"440281"},{name:"南雄市",code:"440282"}]},{name:"深圳市",code:"440300",sub:[{name:"市辖区",code:"440301"},{name:"罗湖区",code:"440303"},{name:"福田区",code:"440304"},{name:"南山区",code:"440305"},{name:"宝安区",code:"440306"},{name:"龙岗区",code:"440307"},{name:"盐田区",code:"440308"}]},{name:"珠海市",code:"440400",sub:[{name:"市辖区",code:"440401"},{name:"香洲区",code:"440402"},{name:"斗门区",code:"440403"},{name:"金湾区",code:"440404"}]},{name:"汕头市",code:"440500",sub:[{name:"市辖区",code:"440501"},{name:"龙湖区",code:"440507"},{name:"金平区",code:"440511"},{name:"濠江区",code:"440512"},{name:"潮阳区",code:"440513"},{name:"潮南区",code:"440514"},{name:"澄海区",code:"440515"},{name:"南澳县",code:"440523"}]},{name:"佛山市",code:"440600",sub:[{name:"市辖区",code:"440601"},{name:"禅城区",code:"440604"},{name:"南海区",code:"440605"},{name:"顺德区",code:"440606"},{name:"三水区",code:"440607"},{name:"高明区",code:"440608"}]},{name:"江门市",code:"440700",sub:[{name:"市辖区",code:"440701"},{name:"蓬江区",code:"440703"},{name:"江海区",code:"440704"},{name:"新会区",code:"440705"},{name:"台山市",code:"440781"},{name:"开平市",code:"440783"},{name:"鹤山市",code:"440784"},{name:"恩平市",code:"440785"}]},{name:"湛江市",code:"440800",sub:[{name:"市辖区",code:"440801"},{name:"赤坎区",code:"440802"},{name:"霞山区",code:"440803"},{name:"坡头区",code:"440804"},{name:"麻章区",code:"440811"},{name:"遂溪县",code:"440823"},{name:"徐闻县",code:"440825"},{name:"廉江市",code:"440881"},{name:"雷州市",code:"440882"},{name:"吴川市",code:"440883"}]},{name:"茂名市",code:"440900",sub:[{name:"市辖区",code:"440901"},{name:"茂南区",code:"440902"},{name:"电白区",code:"440904"},{name:"高州市",code:"440981"},{name:"化州市",code:"440982"},{name:"信宜市",code:"440983"}]},{name:"肇庆市",code:"441200",sub:[{name:"市辖区",code:"441201"},{name:"端州区",code:"441202"},{name:"鼎湖区",code:"441203"},{name:"广宁县",code:"441223"},{name:"怀集县",code:"441224"},{name:"封开县",code:"441225"},{name:"德庆县",code:"441226"},{name:"高要市",code:"441283"},{name:"四会市",code:"441284"}]},{name:"惠州市",code:"441300",sub:[{name:"市辖区",code:"441301"},{name:"惠城区",code:"441302"},{name:"惠阳区",code:"441303"},{name:"博罗县",code:"441322"},{name:"惠东县",code:"441323"},{name:"龙门县",code:"441324"}]},{name:"梅州市",code:"441400",sub:[{name:"市辖区",code:"441401"},{name:"梅江区",code:"441402"},{name:"梅县区",code:"441403"},{name:"大埔县",code:"441422"},{name:"丰顺县",code:"441423"},{name:"五华县",code:"441424"},{name:"平远县",code:"441426"},{name:"蕉岭县",code:"441427"},{name:"兴宁市",code:"441481"}]},{name:"汕尾市",code:"441500",sub:[{name:"市辖区",code:"441501"},{name:"城区",code:"441502"},{name:"海丰县",code:"441521"},{name:"陆河县",code:"441523"},{name:"陆丰市",code:"441581"}]},{name:"河源市",code:"441600",sub:[{name:"市辖区",code:"441601"},{name:"源城区",code:"441602"},{name:"紫金县",code:"441621"},{name:"龙川县",code:"441622"},{name:"连平县",code:"441623"},{name:"和平县",code:"441624"},{name:"东源县",code:"441625"}]},{name:"阳江市",code:"441700",sub:[{name:"市辖区",code:"441701"},{name:"江城区",code:"441702"},{name:"阳东区",code:"441704"},{name:"阳西县",code:"441721"},{name:"阳春市",code:"441781"}]},{name:"清远市",code:"441800",sub:[{name:"市辖区",code:"441801"},{name:"清城区",code:"441802"},{name:"清新区",code:"441803"},{name:"佛冈县",code:"441821"},{name:"阳山县",code:"441823"},{name:"连山壮族瑶族自治县",code:"441825"},{name:"连南瑶族自治县",code:"441826"},{name:"英德市",code:"441881"},{name:"连州市",code:"441882"}]},{name:"东莞市",code:"441900",sub:[]},{name:"中山市",code:"442000",sub:[]},{name:"潮州市",code:"445100",sub:[{name:"市辖区",code:"445101"},{name:"湘桥区",code:"445102"},{name:"潮安区",code:"445103"},{name:"饶平县",code:"445122"}]},{name:"揭阳市",code:"445200",sub:[{name:"市辖区",code:"445201"},{name:"榕城区",code:"445202"},{name:"揭东区",code:"445203"},{name:"揭西县",code:"445222"},{name:"惠来县",code:"445224"},{name:"普宁市",code:"445281"}]},{name:"云浮市",code:"445300",sub:[{name:"市辖区",code:"445301"},{name:"云城区",code:"445302"},{name:"云安区",code:"445303"},{name:"新兴县",code:"445321"},{name:"郁南县",code:"445322"},{name:"罗定市",code:"445381"}]}]},{name:"广西壮族自治区",code:"450000",sub:[{name:"南宁市",code:"450100",sub:[{name:"市辖区",code:"450101"},{name:"兴宁区",code:"450102"},{name:"青秀区",code:"450103"},{name:"江南区",code:"450105"},{name:"西乡塘区",code:"450107"},{name:"良庆区",code:"450108"},{name:"邕宁区",code:"450109"},{name:"武鸣县",code:"450122"},{name:"隆安县",code:"450123"},{name:"马山县",code:"450124"},{name:"上林县",code:"450125"},{name:"宾阳县",code:"450126"},{name:"横县",code:"450127"}]},{name:"柳州市",code:"450200",sub:[{name:"市辖区",code:"450201"},{name:"城中区",code:"450202"},{name:"鱼峰区",code:"450203"},{name:"柳南区",code:"450204"
+},{name:"柳北区",code:"450205"},{name:"柳江县",code:"450221"},{name:"柳城县",code:"450222"},{name:"鹿寨县",code:"450223"},{name:"融安县",code:"450224"},{name:"融水苗族自治县",code:"450225"},{name:"三江侗族自治县",code:"450226"}]},{name:"桂林市",code:"450300",sub:[{name:"市辖区",code:"450301"},{name:"秀峰区",code:"450302"},{name:"叠彩区",code:"450303"},{name:"象山区",code:"450304"},{name:"七星区",code:"450305"},{name:"雁山区",code:"450311"},{name:"临桂区",code:"450312"},{name:"阳朔县",code:"450321"},{name:"灵川县",code:"450323"},{name:"全州县",code:"450324"},{name:"兴安县",code:"450325"},{name:"永福县",code:"450326"},{name:"灌阳县",code:"450327"},{name:"龙胜各族自治县",code:"450328"},{name:"资源县",code:"450329"},{name:"平乐县",code:"450330"},{name:"荔浦县",code:"450331"},{name:"恭城瑶族自治县",code:"450332"}]},{name:"梧州市",code:"450400",sub:[{name:"市辖区",code:"450401"},{name:"万秀区",code:"450403"},{name:"长洲区",code:"450405"},{name:"龙圩区",code:"450406"},{name:"苍梧县",code:"450421"},{name:"藤县",code:"450422"},{name:"蒙山县",code:"450423"},{name:"岑溪市",code:"450481"}]},{name:"北海市",code:"450500",sub:[{name:"市辖区",code:"450501"},{name:"海城区",code:"450502"},{name:"银海区",code:"450503"},{name:"铁山港区",code:"450512"},{name:"合浦县",code:"450521"}]},{name:"防城港市",code:"450600",sub:[{name:"市辖区",code:"450601"},{name:"港口区",code:"450602"},{name:"防城区",code:"450603"},{name:"上思县",code:"450621"},{name:"东兴市",code:"450681"}]},{name:"钦州市",code:"450700",sub:[{name:"市辖区",code:"450701"},{name:"钦南区",code:"450702"},{name:"钦北区",code:"450703"},{name:"灵山县",code:"450721"},{name:"浦北县",code:"450722"}]},{name:"贵港市",code:"450800",sub:[{name:"市辖区",code:"450801"},{name:"港北区",code:"450802"},{name:"港南区",code:"450803"},{name:"覃塘区",code:"450804"},{name:"平南县",code:"450821"},{name:"桂平市",code:"450881"}]},{name:"玉林市",code:"450900",sub:[{name:"市辖区",code:"450901"},{name:"玉州区",code:"450902"},{name:"福绵区",code:"450903"},{name:"容县",code:"450921"},{name:"陆川县",code:"450922"},{name:"博白县",code:"450923"},{name:"兴业县",code:"450924"},{name:"北流市",code:"450981"}]},{name:"百色市",code:"451000",sub:[{name:"市辖区",code:"451001"},{name:"右江区",code:"451002"},{name:"田阳县",code:"451021"},{name:"田东县",code:"451022"},{name:"平果县",code:"451023"},{name:"德保县",code:"451024"},{name:"靖西县",code:"451025"},{name:"那坡县",code:"451026"},{name:"凌云县",code:"451027"},{name:"乐业县",code:"451028"},{name:"田林县",code:"451029"},{name:"西林县",code:"451030"},{name:"隆林各族自治县",code:"451031"}]},{name:"贺州市",code:"451100",sub:[{name:"市辖区",code:"451101"},{name:"八步区",code:"451102"},{name:"平桂管理区",code:"451119"},{name:"昭平县",code:"451121"},{name:"钟山县",code:"451122"},{name:"富川瑶族自治县",code:"451123"}]},{name:"河池市",code:"451200",sub:[{name:"市辖区",code:"451201"},{name:"金城江区",code:"451202"},{name:"南丹县",code:"451221"},{name:"天峨县",code:"451222"},{name:"凤山县",code:"451223"},{name:"东兰县",code:"451224"},{name:"罗城仫佬族自治县",code:"451225"},{name:"环江毛南族自治县",code:"451226"},{name:"巴马瑶族自治县",code:"451227"},{name:"都安瑶族自治县",code:"451228"},{name:"大化瑶族自治县",code:"451229"},{name:"宜州市",code:"451281"}]},{name:"来宾市",code:"451300",sub:[{name:"市辖区",code:"451301"},{name:"兴宾区",code:"451302"},{name:"忻城县",code:"451321"},{name:"象州县",code:"451322"},{name:"武宣县",code:"451323"},{name:"金秀瑶族自治县",code:"451324"},{name:"合山市",code:"451381"}]},{name:"崇左市",code:"451400",sub:[{name:"市辖区",code:"451401"},{name:"江州区",code:"451402"},{name:"扶绥县",code:"451421"},{name:"宁明县",code:"451422"},{name:"龙州县",code:"451423"},{name:"大新县",code:"451424"},{name:"天等县",code:"451425"},{name:"凭祥市",code:"451481"}]}]},{name:"海南省",code:"460000",sub:[{name:"海口市",code:"460100",sub:[{name:"市辖区",code:"460101"},{name:"秀英区",code:"460105"},{name:"龙华区",code:"460106"},{name:"琼山区",code:"460107"},{name:"美兰区",code:"460108"}]},{name:"三亚市",code:"460200",sub:[{name:"市辖区",code:"460201"},{name:"海棠区",code:"460202"},{name:"吉阳区",code:"460203"},{name:"天涯区",code:"460204"},{name:"崖州区",code:"460205"}]},{name:"三沙市",code:"460300",sub:[{name:"西沙群岛",code:"460321"},{name:"南沙群岛",code:"460322"},{name:"中沙群岛的岛礁及其海域",code:"460323"}]},{name:"五指山市",code:"469001"},{name:"琼海市",code:"469002"},{name:"儋州市",code:"469003"},{name:"文昌市",code:"469005"},{name:"万宁市",code:"469006"},{name:"东方市",code:"469007"},{name:"定安县",code:"469021"},{name:"屯昌县",code:"469022"},{name:"澄迈县",code:"469023"},{name:"临高县",code:"469024"},{name:"白沙黎族自治县",code:"469025"},{name:"昌江黎族自治县",code:"469026"},{name:"乐东黎族自治县",code:"469027"},{name:"陵水黎族自治县",code:"469028"},{name:"保亭黎族苗族自治县",code:"469029"},{name:"琼中黎族苗族自治县",code:"469030"}]},{name:"重庆",code:"500000",sub:[{name:"重庆市",code:"500000",sub:[{name:"万州区",code:"500101"},{name:"涪陵区",code:"500102"},{name:"渝中区",code:"500103"},{name:"大渡口区",code:"500104"},{name:"江北区",code:"500105"},{name:"沙坪坝区",code:"500106"},{name:"九龙坡区",code:"500107"},{name:"南岸区",code:"500108"},{name:"北碚区",code:"500109"},{name:"綦江区",code:"500110"},{name:"大足区",code:"500111"},{name:"渝北区",code:"500112"},{name:"巴南区",code:"500113"},{name:"黔江区",code:"500114"},{name:"长寿区",code:"500115"},{name:"江津区",code:"500116"},{name:"合川区",code:"500117"},{name:"永川区",code:"500118"},{name:"南川区",code:"500119"},{name:"璧山区",code:"500120"},{name:"铜梁区",code:"500151"},{name:"潼南县",code:"500223"},{name:"荣昌县",code:"500226"},{name:"梁平县",code:"500228"},{name:"城口县",code:"500229"},{name:"丰都县",code:"500230"},{name:"垫江县",code:"500231"},{name:"武隆县",code:"500232"},{name:"忠县",code:"500233"},{name:"开县",code:"500234"},{name:"云阳县",code:"500235"},{name:"奉节县",code:"500236"},{name:"巫山县",code:"500237"},{name:"巫溪县",code:"500238"},{name:"石柱土家族自治县",code:"500240"},{name:"秀山土家族苗族自治县",code:"500241"},{name:"酉阳土家族苗族自治县",code:"500242"},{name:"彭水苗族土家族自治县",code:"500243"}]}]},{name:"四川省",code:"510000",sub:[{name:"成都市",code:"510100",sub:[{name:"市辖区",code:"510101"},{name:"锦江区",code:"510104"},{name:"青羊区",code:"510105"},{name:"金牛区",code:"510106"},{name:"武侯区",code:"510107"},{name:"成华区",code:"510108"},{name:"龙泉驿区",code:"510112"},{name:"青白江区",code:"510113"},{name:"新都区",code:"510114"},{name:"温江区",code:"510115"},{name:"金堂县",code:"510121"},{name:"双流县",code:"510122"},{name:"郫县",code:"510124"},{name:"大邑县",code:"510129"},{name:"蒲江县",code:"510131"},{name:"新津县",code:"510132"},{name:"都江堰市",code:"510181"},{name:"彭州市",code:"510182"},{name:"邛崃市",code:"510183"},{name:"崇州市",code:"510184"}]},{name:"自贡市",code:"510300",sub:[{name:"市辖区",code:"510301"},{name:"自流井区",code:"510302"},{name:"贡井区",code:"510303"},{name:"大安区",code:"510304"},{name:"沿滩区",code:"510311"},{name:"荣县",code:"510321"},{name:"富顺县",code:"510322"}]},{name:"攀枝花市",code:"510400",sub:[{name:"市辖区",code:"510401"},{name:"东区",code:"510402"},{name:"西区",code:"510403"},{name:"仁和区",code:"510411"},{name:"米易县",code:"510421"},{name:"盐边县",code:"510422"}]},{name:"泸州市",code:"510500",sub:[{name:"市辖区",code:"510501"},{name:"江阳区",code:"510502"},{name:"纳溪区",code:"510503"},{name:"龙马潭区",code:"510504"},{name:"泸县",code:"510521"},{name:"合江县",code:"510522"},{name:"叙永县",code:"510524"},{name:"古蔺县",code:"510525"}]},{name:"德阳市",code:"510600",sub:[{name:"市辖区",code:"510601"},{name:"旌阳区",code:"510603"},{name:"中江县",code:"510623"},{name:"罗江县",code:"510626"},{name:"广汉市",code:"510681"},{name:"什邡市",code:"510682"},{name:"绵竹市",code:"510683"}]},{name:"绵阳市",code:"510700",sub:[{name:"市辖区",code:"510701"},{name:"涪城区",code:"510703"},{name:"游仙区",code:"510704"},{name:"三台县",code:"510722"},{name:"盐亭县",code:"510723"},{name:"安县",code:"510724"},{name:"梓潼县",code:"510725"},{name:"北川羌族自治县",code:"510726"},{name:"平武县",code:"510727"},{name:"江油市",code:"510781"}]},{name:"广元市",code:"510800",sub:[{name:"市辖区",code:"510801"},{name:"利州区",code:"510802"},{name:"昭化区",code:"510811"},{name:"朝天区",code:"510812"},{name:"旺苍县",code:"510821"},{name:"青川县",code:"510822"},{name:"剑阁县",code:"510823"},{name:"苍溪县",code:"510824"}]},{name:"遂宁市",code:"510900",sub:[{name:"市辖区",code:"510901"},{name:"船山区",code:"510903"},{name:"安居区",code:"510904"},{name:"蓬溪县",code:"510921"},{name:"射洪县",code:"510922"},{name:"大英县",code:"510923"}]},{name:"内江市",code:"511000",sub:[{name:"市辖区",code:"511001"},{name:"市中区",code:"511002"},{name:"东兴区",code:"511011"},{name:"威远县",code:"511024"},{name:"资中县",code:"511025"},{name:"隆昌县",code:"511028"}]},{name:"乐山市",code:"511100",sub:[{name:"市辖区",code:"511101"},{name:"市中区",code:"511102"},{name:"沙湾区",code:"511111"},{name:"五通桥区",code:"511112"},{name:"金口河区",code:"511113"},{name:"犍为县",code:"511123"},{name:"井研县",code:"511124"},{name:"夹江县",code:"511126"},{name:"沐川县",code:"511129"},{name:"峨边彝族自治县",code:"511132"},{name:"马边彝族自治县",code:"511133"},{name:"峨眉山市",code:"511181"}]},{name:"南充市",code:"511300",sub:[{name:"市辖区",code:"511301"},{name:"顺庆区",code:"511302"},{name:"高坪区",code:"511303"},{name:"嘉陵区",code:"511304"},{name:"南部县",code:"511321"},{name:"营山县",code:"511322"},{name:"蓬安县",code:"511323"},{name:"仪陇县",code:"511324"},{name:"西充县",code:"511325"},{name:"阆中市",code:"511381"}]},{name:"眉山市",code:"511400",sub:[{name:"市辖区",code:"511401"},{name:"东坡区",code:"511402"},{name:"彭山区",code:"511403"},{name:"仁寿县",code:"511421"},{name:"洪雅县",code:"511423"},{name:"丹棱县",code:"511424"},{name:"青神县",code:"511425"}]},{name:"宜宾市",code:"511500",sub:[{name:"市辖区",code:"511501"},{name:"翠屏区",code:"511502"},{name:"南溪区",code:"511503"},{name:"宜宾县",code:"511521"},{name:"江安县",code:"511523"},{name:"长宁县",code:"511524"},{name:"高县",code:"511525"},{name:"珙县",code:"511526"},{name:"筠连县",code:"511527"},{name:"兴文县",code:"511528"},{name:"屏山县",code:"511529"}]},{name:"广安市",code:"511600",sub:[{name:"市辖区",code:"511601"},{name:"广安区",code:"511602"},{name:"前锋区",code:"511603"},{name:"岳池县",code:"511621"},{name:"武胜县",code:"511622"},{name:"邻水县",code:"511623"},{name:"华蓥市",code:"511681"}]},{name:"达州市",code:"511700",sub:[{name:"市辖区",code:"511701"},{name:"通川区",code:"511702"},{name:"达川区",code:"511703"},{name:"宣汉县",code:"511722"},{name:"开江县",code:"511723"},{name:"大竹县",code:"511724"},{name:"渠县",code:"511725"},{name:"万源市",code:"511781"}]},{name:"雅安市",code:"511800",sub:[{name:"市辖区",code:"511801"},{name:"雨城区",code:"511802"},{name:"名山区",code:"511803"},{name:"荥经县",code:"511822"},{name:"汉源县",code:"511823"},{name:"石棉县",code:"511824"},{name:"天全县",code:"511825"},{name:"芦山县",code:"511826"},{name:"宝兴县",code:"511827"}]},{name:"巴中市",code:"511900",sub:[{name:"市辖区",code:"511901"},{name:"巴州区",code:"511902"},{name:"恩阳区",code:"511903"},{name:"通江县",code:"511921"},{name:"南江县",code:"511922"},{name:"平昌县",code:"511923"}]},{name:"资阳市",code:"512000",sub:[{name:"市辖区",code:"512001"},{name:"雁江区",code:"512002"},{name:"安岳县",code:"512021"},{name:"乐至县",code:"512022"},{name:"简阳市",code:"512081"}]},{name:"阿坝藏族羌族自治州",code:"513200",sub:[{name:"汶川县",code:"513221"},{name:"理县",code:"513222"},{name:"茂县",code:"513223"},{name:"松潘县",code:"513224"},{name:"九寨沟县",code:"513225"},{name:"金川县",code:"513226"},{name:"小金县",code:"513227"},{name:"黑水县",code:"513228"},{name:"马尔康县",code:"513229"},{name:"壤塘县",code:"513230"},{name:"阿坝县",code:"513231"},{name:"若尔盖县",code:"513232"},{name:"红原县",code:"513233"}]},{name:"甘孜藏族自治州",code:"513300",sub:[{name:"康定县",code:"513321"},{name:"泸定县",code:"513322"},{name:"丹巴县",code:"513323"},{name:"九龙县",code:"513324"},{name:"雅江县",code:"513325"},{name:"道孚县",code:"513326"},{name:"炉霍县",code:"513327"},{name:"甘孜县",code:"513328"},{name:"新龙县",code:"513329"},{name:"德格县",code:"513330"},{name:"白玉县",code:"513331"},{name:"石渠县",code:"513332"},{name:"色达县",code:"513333"},{name:"理塘县",code:"513334"},{name:"巴塘县",code:"513335"},{name:"乡城县",code:"513336"},{name:"稻城县",code:"513337"},{name:"得荣县",code:"513338"}]},{name:"凉山彝族自治州",code:"513400",sub:[{name:"西昌市",code:"513401"},{name:"木里藏族自治县",code:"513422"},{name:"盐源县",code:"513423"},{name:"德昌县",code:"513424"},{name:"会理县",code:"513425"},{name:"会东县",code:"513426"},{name:"宁南县",code:"513427"},{name:"普格县",code:"513428"},{name:"布拖县",code:"513429"},{name:"金阳县",code:"513430"},{name:"昭觉县",code:"513431"},{name:"喜德县",code:"513432"},{name:"冕宁县",code:"513433"},{name:"越西县",code:"513434"},{name:"甘洛县",code:"513435"},{name:"美姑县",code:"513436"},{name:"雷波县",code:"513437"}]}]},{name:"贵州省",code:"520000",sub:[{name:"贵阳市",code:"520100",sub:[{name:"市辖区",code:"520101"},{name:"南明区",code:"520102"},{name:"云岩区",code:"520103"},{name:"花溪区",code:"520111"},{name:"乌当区",code:"520112"},{name:"白云区",code:"520113"},{name:"观山湖区",code:"520115"},{name:"开阳县",code:"520121"},{name:"息烽县",code:"520122"},{name:"修文县",code:"520123"},{name:"清镇市",code:"520181"}]},{name:"六盘水市",code:"520200",sub:[{name:"钟山区",code:"520201"},{name:"六枝特区",code:"520203"},{name:"水城县",code:"520221"},{name:"盘县",code:"520222"}]},{name:"遵义市",code:"520300",sub:[{name:"市辖区",code:"520301"},{name:"红花岗区",code:"520302"},{name:"汇川区",code:"520303"},{name:"遵义县",code:"520321"},{name:"桐梓县",code:"520322"},{name:"绥阳县",code:"520323"},{name:"正安县",code:"520324"},{name:"道真仡佬族苗族自治县",code:"520325"},{name:"务川仡佬族苗族自治县",code:"520326"},{name:"凤冈县",code:"520327"},{name:"湄潭县",code:"520328"},{name:"余庆县",code:"520329"},{name:"习水县",code:"520330"},{name:"赤水市",code:"520381"},{name:"仁怀市",code:"520382"}]},{name:"安顺市",code:"520400",sub:[{name:"市辖区",code:"520401"},{name:"西秀区",code:"520402"},{name:"平坝区",code:"520403"},{name:"普定县",code:"520422"},{name:"镇宁布依族苗族自治县",code:"520423"},{name:"关岭布依族苗族自治县",code:"520424"},{name:"紫云苗族布依族自治县",code:"520425"}]},{name:"毕节市",code:"520500",sub:[{name:"市辖区",code:"520501"},{name:"七星关区",code:"520502"},{name:"大方县",code:"520521"},{name:"黔西县",code:"520522"},{name:"金沙县",code:"520523"},{name:"织金县",code:"520524"},{name:"纳雍县",code:"520525"},{name:"威宁彝族回族苗族自治县",code:"520526"},{name:"赫章县",code:"520527"}]},{name:"铜仁市",code:"520600",sub:[{name:"市辖区",code:"520601"},{name:"碧江区",code:"520602"},{name:"万山区",code:"520603"},{name:"江口县",code:"520621"},{name:"玉屏侗族自治县",code:"520622"},{name:"石阡县",code:"520623"},{name:"思南县",code:"520624"},{name:"印江土家族苗族自治县",code:"520625"},{name:"德江县",code:"520626"},{name:"沿河土家族自治县",code:"520627"},{name:"松桃苗族自治县",code:"520628"}]},{name:"黔西南布依族苗族自治州",code:"522300",sub:[{name:"兴义市",code:"522301"},{name:"兴仁县",code:"522322"},{name:"普安县",code:"522323"},{name:"晴隆县",code:"522324"},{name:"贞丰县",code:"522325"},{name:"望谟县",code:"522326"},{name:"册亨县",code:"522327"},{name:"安龙县",code:"522328"}]},{name:"黔东南苗族侗族自治州",code:"522600",sub:[{name:"凯里市",code:"522601"},{name:"黄平县",code:"522622"},{name:"施秉县",code:"522623"},{name:"三穗县",code:"522624"},{name:"镇远县",code:"522625"},{name:"岑巩县",code:"522626"},{name:"天柱县",code:"522627"},{name:"锦屏县",code:"522628"},{name:"剑河县",code:"522629"},{name:"台江县",code:"522630"},{name:"黎平县",code:"522631"},{name:"榕江县",code:"522632"},{name:"从江县",code:"522633"},{name:"雷山县",code:"522634"},{name:"麻江县",code:"522635"},{name:"丹寨县",code:"522636"}]},{name:"黔南布依族苗族自治州",code:"522700",sub:[{name:"都匀市",code:"522701"},{name:"福泉市",code:"522702"},{name:"荔波县",code:"522722"},{name:"贵定县",code:"522723"},{name:"瓮安县",code:"522725"},{name:"独山县",code:"522726"},{name:"平塘县",code:"522727"},{name:"罗甸县",code:"522728"},{name:"长顺县",code:"522729"},{name:"龙里县",code:"522730"},{name:"惠水县",code:"522731"},{name:"三都水族自治县",code:"522732"}]}]},{name:"云南省",code:"530000",sub:[{name:"昆明市",code:"530100",sub:[{name:"市辖区",code:"530101"},{name:"五华区",code:"530102"},{name:"盘龙区",code:"530103"},{name:"官渡区",code:"530111"},{name:"西山区",code:"530112"},{name:"东川区",code:"530113"},{name:"呈贡区",code:"530114"},{name:"晋宁县",code:"530122"},{name:"富民县",code:"530124"},{name:"宜良县",code:"530125"},{name:"石林彝族自治县",code:"530126"},{name:"嵩明县",code:"530127"},{name:"禄劝彝族苗族自治县",code:"530128"},{name:"寻甸回族彝族自治县",code:"530129"},{name:"安宁市",code:"530181"}]},{name:"曲靖市",code:"530300",sub:[{name:"市辖区",code:"530301"},{name:"麒麟区",code:"530302"},{name:"马龙县",code:"530321"},{name:"陆良县",code:"530322"},{name:"师宗县",code:"530323"},{name:"罗平县",code:"530324"},{name:"富源县",code:"530325"},{name:"会泽县",code:"530326"},{name:"沾益县",code:"530328"},{name:"宣威市",code:"530381"}]},{name:"玉溪市",code:"530400",sub:[{name:"市辖区",code:"530401"},{name:"红塔区",code:"530402"},{name:"江川县",code:"530421"},{name:"澄江县",code:"530422"},{name:"通海县",code:"530423"},{name:"华宁县",code:"530424"},{name:"易门县",code:"530425"},{name:"峨山彝族自治县",code:"530426"},{name:"新平彝族傣族自治县",code:"530427"},{name:"元江哈尼族彝族傣族自治县",code:"530428"}]},{name:"保山市",code:"530500",sub:[{name:"市辖区",code:"530501"},{name:"隆阳区",code:"530502"},{name:"施甸县",code:"530521"},{name:"腾冲县",code:"530522"},{name:"龙陵县",code:"530523"},{name:"昌宁县",code:"530524"}]},{name:"昭通市",code:"530600",sub:[{name:"市辖区",code:"530601"},{name:"昭阳区",code:"530602"},{name:"鲁甸县",code:"530621"},{name:"巧家县",code:"530622"},{name:"盐津县",code:"530623"},{name:"大关县",code:"530624"},{name:"永善县",code:"530625"},{name:"绥江县",code:"530626"},{name:"镇雄县",code:"530627"},{name:"彝良县",code:"530628"},{name:"威信县",code:"530629"},{name:"水富县",code:"530630"}]},{name:"丽江市",code:"530700",sub:[{name:"市辖区",code:"530701"},{name:"古城区",code:"530702"},{name:"玉龙纳西族自治县",code:"530721"},{name:"永胜县",code:"530722"},{name:"华坪县",code:"530723"},{name:"宁蒗彝族自治县",code:"530724"}]},{name:"普洱市",code:"530800",sub:[{name:"市辖区",code:"530801"},{name:"思茅区",code:"530802"},{name:"宁洱哈尼族彝族自治县",code:"530821"},{name:"墨江哈尼族自治县",code:"530822"},{name:"景东彝族自治县",code:"530823"},{name:"景谷傣族彝族自治县",code:"530824"},{name:"镇沅彝族哈尼族拉祜族自治县",code:"530825"},{name:"江城哈尼族彝族自治县",code:"530826"},{name:"孟连傣族拉祜族佤族自治县",code:"530827"},{name:"澜沧拉祜族自治县",code:"530828"},{name:"西盟佤族自治县",code:"530829"}]},{name:"临沧市",code:"530900",sub:[{name:"市辖区",code:"530901"},{name:"临翔区",code:"530902"},{name:"凤庆县",code:"530921"},{name:"云县",code:"530922"},{name:"永德县",code:"530923"},{name:"镇康县",code:"530924"},{name:"双江拉祜族佤族布朗族傣族自治县",code:"530925"},{name:"耿马傣族佤族自治县",code:"530926"},{name:"沧源佤族自治县",code:"530927"}]},{name:"楚雄彝族自治州",code:"532300",sub:[{name:"楚雄市",code:"532301"},{name:"双柏县",code:"532322"},{name:"牟定县",code:"532323"},{name:"南华县",code:"532324"},{name:"姚安县",code:"532325"},{name:"大姚县",code:"532326"},{name:"永仁县",code:"532327"},{name:"元谋县",code:"532328"},{name:"武定县",code:"532329"},{name:"禄丰县",code:"532331"}]},{name:"红河哈尼族彝族自治州",code:"532500",sub:[{name:"个旧市",code:"532501"},{name:"开远市",code:"532502"},{name:"蒙自市",code:"532503"},{name:"弥勒市",code:"532504"},{name:"屏边苗族自治县",code:"532523"},{name:"建水县",code:"532524"},{name:"石屏县",code:"532525"},{name:"泸西县",code:"532527"},{name:"元阳县",code:"532528"},{name:"红河县",code:"532529"},{name:"金平苗族瑶族傣族自治县",code:"532530"},{name:"绿春县",code:"532531"},{name:"河口瑶族自治县",code:"532532"}]},{name:"文山壮族苗族自治州",code:"532600",sub:[{name:"文山市",code:"532601"},{name:"砚山县",code:"532622"},{name:"西畴县",code:"532623"},{name:"麻栗坡县",code:"532624"},{name:"马关县",code:"532625"},{name:"丘北县",code:"532626"},{name:"广南县",code:"532627"},{name:"富宁县",code:"532628"}]},{name:"西双版纳傣族自治州",code:"532800",sub:[{name:"景洪市",code:"532801"},{name:"勐海县",code:"532822"},{name:"勐腊县",code:"532823"}]},{name:"大理白族自治州",code:"532900",sub:[{name:"大理市",code:"532901"},{name:"漾濞彝族自治县",code:"532922"},{name:"祥云县",code:"532923"},{name:"宾川县",code:"532924"},{name:"弥渡县",code:"532925"},{name:"南涧彝族自治县",code:"532926"},{name:"巍山彝族回族自治县",code:"532927"},{name:"永平县",code:"532928"},{name:"云龙县",code:"532929"},{name:"洱源县",code:"532930"},{name:"剑川县",code:"532931"},{name:"鹤庆县",code:"532932"}]},{name:"德宏傣族景颇族自治州",code:"533100",sub:[{name:"瑞丽市",code:"533102"},{name:"芒市",code:"533103"},{name:"梁河县",code:"533122"},{name:"盈江县",code:"533123"},{name:"陇川县",code:"533124"}]},{name:"怒江傈僳族自治州",code:"533300",sub:[{name:"泸水县",code:"533321"},{name:"福贡县",code:"533323"},{name:"贡山独龙族怒族自治县",code:"533324"},{name:"兰坪白族普米族自治县",code:"533325"}]},{name:"迪庆藏族自治州",code:"533400",sub:[{name:"香格里拉市",code:"533401"},{name:"德钦县",code:"533422"},{name:"维西傈僳族自治县",code:"533423"}]}]},{name:"西藏自治区",code:"540000",sub:[{name:"拉萨市",code:"540100",sub:[{name:"市辖区",code:"540101"},{name:"城关区",code:"540102"},{name:"林周县",code:"540121"},{name:"当雄县",code:"540122"},{name:"尼木县",code:"540123"},{name:"曲水县",code:"540124"},{name:"堆龙德庆县",code:"540125"},{name:"达孜县",code:"540126"},{name:"墨竹工卡县",code:"540127"}]},{name:"日喀则市",code:"540200",sub:[{name:"市辖区",code:"540201"},{name:"桑珠孜区",code:"540202"},{name:"南木林县",code:"540221"},{name:"江孜县",code:"540222"},{name:"定日县",code:"540223"},{name:"萨迦县",code:"540224"},{name:"拉孜县",code:"540225"},{name:"昂仁县",code:"540226"},{name:"谢通门县",code:"540227"},{name:"白朗县",code:"540228"},{name:"仁布县",code:"540229"},{name:"康马县",code:"540230"},{name:"定结县",code:"540231"},{name:"仲巴县",code:"540232"},{name:"亚东县",code:"540233"},{name:"吉隆县",code:"540234"},{name:"聂拉木县",code:"540235"},{name:"萨嘎县",code:"540236"},{name:"岗巴县",code:"540237"}]},{name:"昌都市",code:"540300",sub:[{name:"市辖区",code:"540301"},{name:"卡若区",code:"540302"},{name:"江达县",code:"540321"},{name:"贡觉县",code:"540322"},{name:"类乌齐县",code:"540323"},{name:"丁青县",code:"540324"},{name:"察雅县",code:"540325"},{name:"八宿县",code:"540326"},{name:"左贡县",code:"540327"},{name:"芒康县",code:"540328"},{name:"洛隆县",code:"540329"},{name:"边坝县",code:"540330"}]},{name:"山南地区",code:"542200",sub:[{name:"乃东县",code:"542221"},{name:"扎囊县",code:"542222"},{name:"贡嘎县",code:"542223"},{name:"桑日县",code:"542224"},{name:"琼结县",code:"542225"},{name:"曲松县",code:"542226"},{name:"措美县",code:"542227"},{name:"洛扎县",code:"542228"},{name:"加查县",code:"542229"},{name:"隆子县",code:"542231"},{name:"错那县",code:"542232"},{name:"浪卡子县",code:"542233"}]},{name:"那曲地区",code:"542400",sub:[{name:"那曲县",code:"542421"},{name:"嘉黎县",code:"542422"},{name:"比如县",code:"542423"},{name:"聂荣县",code:"542424"},{name:"安多县",code:"542425"},{name:"申扎县",code:"542426"},{name:"索县",code:"542427"},{name:"班戈县",code:"542428"},{name:"巴青县",code:"542429"},{name:"尼玛县",code:"542430"},{name:"双湖县",code:"542431"}]},{name:"阿里地区",code:"542500",sub:[{name:"普兰县",code:"542521"},{name:"札达县",code:"542522"},{name:"噶尔县",code:"542523"},{name:"日土县",code:"542524"},{name:"革吉县",code:"542525"},{name:"改则县",code:"542526"},{name:"措勤县",code:"542527"}]},{name:"林芝地区",code:"542600",sub:[{name:"林芝县",code:"542621"},{name:"工布江达县",code:"542622"},{name:"米林县",code:"542623"},{name:"墨脱县",code:"542624"},{name:"波密县",code:"542625"},{name:"察隅县",code:"542626"},{name:"朗县",code:"542627"}]}]},{name:"陕西省",code:"610000",sub:[{name:"西安市",code:"610100",sub:[{name:"市辖区",code:"610101"},{name:"新城区",code:"610102"},{name:"碑林区",code:"610103"},{name:"莲湖区",code:"610104"},{name:"灞桥区",code:"610111"},{name:"未央区",code:"610112"},{name:"雁塔区",code:"610113"},{name:"阎良区",code:"610114"},{name:"临潼区",code:"610115"},{name:"长安区",code:"610116"},{name:"高陵区",code:"610117"},{name:"蓝田县",code:"610122"},{name:"周至县",code:"610124"},{name:"户县",code:"610125"}]},{name:"铜川市",code:"610200",sub:[{name:"市辖区",code:"610201"},{name:"王益区",code:"610202"},{name:"印台区",code:"610203"},{name:"耀州区",code:"610204"},{name:"宜君县",code:"610222"}]},{name:"宝鸡市",code:"610300",sub:[{name:"市辖区",code:"610301"},{name:"渭滨区",code:"610302"},{name:"金台区",code:"610303"},{name:"陈仓区",code:"610304"},{name:"凤翔县",code:"610322"},{name:"岐山县",code:"610323"},{name:"扶风县",code:"610324"},{name:"眉县",code:"610326"},{name:"陇县",code:"610327"},{name:"千阳县",code:"610328"},{name:"麟游县",code:"610329"},{name:"凤县",code:"610330"},{name:"太白县",code:"610331"}]},{name:"咸阳市",code:"610400",sub:[{name:"市辖区",code:"610401"},{name:"秦都区",code:"610402"},{name:"杨陵区",code:"610403"},{name:"渭城区",code:"610404"},{name:"三原县",code:"610422"},{name:"泾阳县",code:"610423"},{name:"乾县",code:"610424"},{name:"礼泉县",code:"610425"},{name:"永寿县",code:"610426"},{name:"彬县",code:"610427"},{name:"长武县",code:"610428"},{name:"旬邑县",code:"610429"},{name:"淳化县",code:"610430"},{name:"武功县",code:"610431"},{name:"兴平市",code:"610481"}]},{name:"渭南市",code:"610500",sub:[{name:"市辖区",code:"610501"},{name:"临渭区",code:"610502"},{name:"华县",code:"610521"},{name:"潼关县",code:"610522"},{name:"大荔县",code:"610523"},{name:"合阳县",code:"610524"},{name:"澄城县",code:"610525"},{name:"蒲城县",code:"610526"},{name:"白水县",code:"610527"},{name:"富平县",code:"610528"},{name:"韩城市",code:"610581"},{name:"华阴市",code:"610582"}]},{name:"延安市",code:"610600",sub:[{name:"市辖区",code:"610601"},{name:"宝塔区",code:"610602"},{name:"延长县",code:"610621"},{name:"延川县",code:"610622"},{name:"子长县",code:"610623"},{name:"安塞县",code:"610624"},{name:"志丹县",code:"610625"},{name:"吴起县",code:"610626"},{name:"甘泉县",code:"610627"},{name:"富县",code:"610628"},{name:"洛川县",code:"610629"},{name:"宜川县",code:"610630"},{name:"黄龙县",code:"610631"},{name:"黄陵县",code:"610632"}]},{name:"汉中市",code:"610700",sub:[{name:"市辖区",code:"610701"},{name:"汉台区",code:"610702"},{name:"南郑县",code:"610721"},{name:"城固县",code:"610722"},{name:"洋县",code:"610723"},{name:"西乡县",code:"610724"},{name:"勉县",code:"610725"},{name:"宁强县",code:"610726"},{name:"略阳县",code:"610727"},{name:"镇巴县",code:"610728"},{name:"留坝县",code:"610729"},{name:"佛坪县",code:"610730"}]},{name:"榆林市",code:"610800",sub:[{name:"市辖区",code:"610801"},{name:"榆阳区",code:"610802"},{name:"神木县",code:"610821"},{name:"府谷县",code:"610822"},{name:"横山县",code:"610823"},{name:"靖边县",code:"610824"},{name:"定边县",code:"610825"},{name:"绥德县",code:"610826"},{name:"米脂县",code:"610827"},{name:"佳县",code:"610828"},{name:"吴堡县",code:"610829"},{name:"清涧县",code:"610830"},{name:"子洲县",code:"610831"}]},{name:"安康市",code:"610900",sub:[{name:"市辖区",code:"610901"},{name:"汉阴县",code:"610921"},{name:"石泉县",code:"610922"},{name:"宁陕县",code:"610923"},{name:"紫阳县",code:"610924"},{name:"岚皋县",code:"610925"},{name:"平利县",code:"610926"},{name:"镇坪县",code:"610927"},{name:"旬阳县",code:"610928"},{name:"白河县",code:"610929"}]},{name:"商洛市",code:"611000",sub:[{name:"市辖区",code:"611001"},{name:"商州区",code:"611002"},{name:"洛南县",code:"611021"},{name:"丹凤县",code:"611022"},{name:"商南县",code:"611023"},{name:"山阳县",code:"611024"},{name:"镇安县",code:"611025"},{name:"柞水县",code:"611026"}]}]},{name:"甘肃省",code:"620000",sub:[{name:"兰州市",code:"620100",sub:[{name:"市辖区",code:"620101"},{name:"城关区",code:"620102"},{name:"七里河区",code:"620103"},{name:"西固区",code:"620104"},{name:"安宁区",code:"620105"},{name:"红古区",code:"620111"},{name:"永登县",code:"620121"},{name:"皋兰县",code:"620122"},{name:"榆中县",code:"620123"}]},{name:"嘉峪关市",code:"620200",sub:[{name:"市辖区",code:"620201"}]},{name:"金昌市",code:"620300",sub:[{name:"市辖区",code:"620301"},{name:"金川区",code:"620302"},{name:"永昌县",code:"620321"}]},{name:"白银市",code:"620400",sub:[{name:"市辖区",code:"620401"},{name:"白银区",code:"620402"},{name:"平川区",code:"620403"},{name:"靖远县",code:"620421"},{name:"会宁县",code:"620422"},{name:"景泰县",code:"620423"}]},{name:"天水市",code:"620500",sub:[{name:"市辖区",code:"620501"},{name:"秦州区",code:"620502"},{name:"麦积区",code:"620503"},{name:"清水县",code:"620521"},{name:"秦安县",code:"620522"},{name:"甘谷县",code:"620523"},{name:"武山县",code:"620524"},{name:"张家川回族自治县",code:"620525"}]},{name:"武威市",code:"620600",sub:[{name:"市辖区",code:"620601"},{name:"凉州区",code:"620602"},{name:"民勤县",code:"620621"},{name:"古浪县",code:"620622"},{name:"天祝藏族自治县",code:"620623"}]},{name:"张掖市",code:"620700",sub:[{name:"市辖区",code:"620701"},{name:"甘州区",code:"620702"},{name:"肃南裕固族自治县",code:"620721"},{name:"民乐县",code:"620722"},{name:"临泽县",code:"620723"},{name:"高台县",code:"620724"},{name:"山丹县",code:"620725"}]},{name:"平凉市",code:"620800",sub:[{name:"市辖区",code:"620801"},{name:"崆峒区",code:"620802"},{name:"泾川县",code:"620821"},{name:"灵台县",code:"620822"},{name:"崇信县",code:"620823"},{name:"华亭县",code:"620824"},{name:"庄浪县",code:"620825"},{name:"静宁县",code:"620826"}]},{name:"酒泉市",code:"620900",sub:[{name:"市辖区",code:"620901"},{name:"肃州区",code:"620902"},{name:"金塔县",code:"620921"},{name:"瓜州县",code:"620922"},{name:"肃北蒙古族自治县",code:"620923"},{name:"阿克塞哈萨克族自治县",code:"620924"},{name:"玉门市",code:"620981"},{name:"敦煌市",code:"620982"}]},{name:"庆阳市",code:"621000",sub:[{name:"市辖区",code:"621001"},{name:"西峰区",code:"621002"},{name:"庆城县",code:"621021"},{name:"环县",code:"621022"},{name:"华池县",code:"621023"},{name:"合水县",code:"621024"},{name:"正宁县",code:"621025"},{name:"宁县",code:"621026"},{name:"镇原县",code:"621027"}]},{name:"定西市",code:"621100",sub:[{name:"市辖区",code:"621101"},{name:"安定区",code:"621102"},{name:"通渭县",code:"621121"},{name:"陇西县",code:"621122"},{name:"渭源县",code:"621123"},{name:"临洮县",code:"621124"},{name:"漳县",code:"621125"},{name:"岷县",code:"621126"}]},{name:"陇南市",code:"621200",sub:[{name:"市辖区",code:"621201"},{name:"武都区",code:"621202"},{name:"成县",code:"621221"},{name:"文县",code:"621222"},{name:"宕昌县",code:"621223"},{name:"康县",code:"621224"},{name:"西和县",code:"621225"},{name:"礼县",code:"621226"},{name:"徽县",code:"621227"},{name:"两当县",code:"621228"}]},{name:"临夏回族自治州",code:"622900",sub:[{name:"临夏市",code:"622901"},{name:"临夏县",code:"622921"},{name:"康乐县",code:"622922"},{name:"永靖县",code:"622923"},{name:"广河县",code:"622924"},{name:"和政县",code:"622925"},{name:"东乡族自治县",code:"622926"},{name:"积石山保安族东乡族撒拉族自治县",code:"622927"}]},{name:"甘南藏族自治州",code:"623000",sub:[{name:"合作市",code:"623001"},{name:"临潭县",code:"623021"},{name:"卓尼县",code:"623022"},{name:"舟曲县",code:"623023"},{name:"迭部县",code:"623024"},{name:"玛曲县",code:"623025"},{name:"碌曲县",code:"623026"},{name:"夏河县",code:"623027"}]}]},{name:"青海省",code:"630000",sub:[{name:"西宁市",code:"630100",sub:[{name:"市辖区",code:"630101"},{name:"城东区",code:"630102"},{name:"城中区",code:"630103"},{name:"城西区",code:"630104"},{name:"城北区",code:"630105"},{name:"大通回族土族自治县",code:"630121"},{name:"湟中县",code:"630122"},{name:"湟源县",code:"630123"}]},{name:"海东市",code:"630200",sub:[{name:"市辖区",code:"630201"},{name:"乐都区",code:"630202"},{name:"平安县",code:"630221"},{name:"民和回族土族自治县",code:"630222"},{name:"互助土族自治县",code:"630223"},{name:"化隆回族自治县",code:"630224"},{name:"循化撒拉族自治县",code:"630225"}]},{name:"海北藏族自治州",code:"632200",sub:[{name:"门源回族自治县",code:"632221"},{name:"祁连县",code:"632222"},{name:"海晏县",code:"632223"},{name:"刚察县",code:"632224"}]},{name:"黄南藏族自治州",code:"632300",sub:[{name:"同仁县",code:"632321"},{name:"尖扎县",code:"632322"},{name:"泽库县",code:"632323"},{name:"河南蒙古族自治县",code:"632324"}]},{name:"海南藏族自治州",code:"632500",sub:[{name:"共和县",code:"632521"},{name:"同德县",code:"632522"},{name:"贵德县",code:"632523"},{name:"兴海县",code:"632524"},{name:"贵南县",code:"632525"}]},{name:"果洛藏族自治州",code:"632600",sub:[{name:"玛沁县",code:"632621"},{name:"班玛县",code:"632622"},{name:"甘德县",code:"632623"},{name:"达日县",code:"632624"},{name:"久治县",code:"632625"},{name:"玛多县",code:"632626"}]},{name:"玉树藏族自治州",code:"632700",sub:[{name:"玉树市",code:"632701"},{name:"杂多县",code:"632722"},{name:"称多县",code:"632723"},{name:"治多县",code:"632724"},{name:"囊谦县",code:"632725"},{name:"曲麻莱县",code:"632726"}]},{name:"海西蒙古族藏族自治州",code:"632800",sub:[{name:"格尔木市",code:"632801"},{name:"德令哈市",code:"632802"},{name:"乌兰县",code:"632821"},{name:"都兰县",code:"632822"},{name:"天峻县",code:"632823"}]}]},{name:"宁夏回族自治区",code:"640000",sub:[{name:"银川市",code:"640100",sub:[{name:"市辖区",code:"640101"},{name:"兴庆区",code:"640104"},{name:"西夏区",code:"640105"},{name:"金凤区",code:"640106"},{name:"永宁县",code:"640121"},{name:"贺兰县",code:"640122"},{name:"灵武市",code:"640181"}]},{name:"石嘴山市",code:"640200",sub:[{name:"市辖区",code:"640201"},{name:"大武口区",code:"640202"},{name:"惠农区",code:"640205"},{name:"平罗县",code:"640221"}]},{name:"吴忠市",code:"640300",sub:[{name:"市辖区",code:"640301"},{name:"利通区",code:"640302"},{name:"红寺堡区",code:"640303"},{name:"盐池县",code:"640323"},{name:"同心县",code:"640324"},{name:"青铜峡市",code:"640381"}]},{name:"固原市",code:"640400",sub:[{name:"市辖区",code:"640401"},{name:"原州区",code:"640402"},{name:"西吉县",code:"640422"},{name:"隆德县",code:"640423"},{name:"泾源县",code:"640424"},{name:"彭阳县",code:"640425"}]},{name:"中卫市",code:"640500",sub:[{name:"市辖区",code:"640501"},{name:"沙坡头区",code:"640502"},{name:"中宁县",code:"640521"},{name:"海原县",code:"640522"}]}]},{name:"新疆维吾尔自治区",code:"650000",sub:[{name:"乌鲁木齐市",code:"650100",sub:[{name:"市辖区",code:"650101"},{name:"天山区",code:"650102"},{name:"沙依巴克区",code:"650103"},{name:"新市区",code:"650104"},{name:"水磨沟区",code:"650105"},{name:"头屯河区",code:"650106"},{name:"达坂城区",code:"650107"},{name:"米东区",code:"650109"},{name:"乌鲁木齐县",code:"650121"}]},{name:"克拉玛依市",code:"650200",sub:[{name:"市辖区",code:"650201"},{name:"独山子区",code:"650202"},{name:"克拉玛依区",code:"650203"},{name:"白碱滩区",code:"650204"},{name:"乌尔禾区",code:"650205"}]},{name:"吐鲁番地区",code:"652100",sub:[{name:"吐鲁番市",code:"652101"},{name:"鄯善县",code:"652122"},{name:"托克逊县",code:"652123"}]},{name:"哈密地区",code:"652200",sub:[{name:"哈密市",code:"652201"},{name:"巴里坤哈萨克自治县",code:"652222"},{name:"伊吾县",code:"652223"}]},{name:"昌吉回族自治州",code:"652300",sub:[{name:"昌吉市",code:"652301"},{name:"阜康市",code:"652302"},{name:"呼图壁县",code:"652323"},{name:"玛纳斯县",code:"652324"},{name:"奇台县",code:"652325"},{name:"吉木萨尔县",code:"652327"},{name:"木垒哈萨克自治县",code:"652328"}]},{name:"博尔塔拉蒙古自治州",code:"652700",sub:[{name:"博乐市",code:"652701"},{name:"阿拉山口市",code:"652702"},{name:"精河县",code:"652722"},{name:"温泉县",code:"652723"}]},{name:"巴音郭楞蒙古自治州",code:"652800",sub:[{name:"库尔勒市",code:"652801"},{name:"轮台县",code:"652822"},{name:"尉犁县",code:"652823"},{name:"若羌县",code:"652824"},{name:"且末县",code:"652825"},{name:"焉耆回族自治县",code:"652826"},{name:"和静县",code:"652827"},{name:"和硕县",code:"652828"},{name:"博湖县",code:"652829"}]},{name:"阿克苏地区",code:"652900",
+sub:[{name:"阿克苏市",code:"652901"},{name:"温宿县",code:"652922"},{name:"库车县",code:"652923"},{name:"沙雅县",code:"652924"},{name:"新和县",code:"652925"},{name:"拜城县",code:"652926"},{name:"乌什县",code:"652927"},{name:"阿瓦提县",code:"652928"},{name:"柯坪县",code:"652929"}]},{name:"克孜勒苏柯尔克孜自治州",code:"653000",sub:[{name:"阿图什市",code:"653001"},{name:"阿克陶县",code:"653022"},{name:"阿合奇县",code:"653023"},{name:"乌恰县",code:"653024"}]},{name:"喀什地区",code:"653100",sub:[{name:"喀什市",code:"653101"},{name:"疏附县",code:"653121"},{name:"疏勒县",code:"653122"},{name:"英吉沙县",code:"653123"},{name:"泽普县",code:"653124"},{name:"莎车县",code:"653125"},{name:"叶城县",code:"653126"},{name:"麦盖提县",code:"653127"},{name:"岳普湖县",code:"653128"},{name:"伽师县",code:"653129"},{name:"巴楚县",code:"653130"},{name:"塔什库尔干塔吉克自治县",code:"653131"}]},{name:"和田地区",code:"653200",sub:[{name:"和田市",code:"653201"},{name:"和田县",code:"653221"},{name:"墨玉县",code:"653222"},{name:"皮山县",code:"653223"},{name:"洛浦县",code:"653224"},{name:"策勒县",code:"653225"},{name:"于田县",code:"653226"},{name:"民丰县",code:"653227"}]},{name:"伊犁哈萨克自治州",code:"654000",sub:[{name:"伊宁市",code:"654002"},{name:"奎屯市",code:"654003"},{name:"霍尔果斯市",code:"654004"},{name:"伊宁县",code:"654021"},{name:"察布查尔锡伯自治县",code:"654022"},{name:"霍城县",code:"654023"},{name:"巩留县",code:"654024"},{name:"新源县",code:"654025"},{name:"昭苏县",code:"654026"},{name:"特克斯县",code:"654027"},{name:"尼勒克县",code:"654028"},{name:"塔城地区",code:"654200"},{name:"塔城市",code:"654201"},{name:"乌苏市",code:"654202"},{name:"额敏县",code:"654221"},{name:"沙湾县",code:"654223"},{name:"托里县",code:"654224"},{name:"裕民县",code:"654225"},{name:"和布克赛尔蒙古自治县",code:"654226"},{name:"阿勒泰地区",code:"654300"},{name:"阿勒泰市",code:"654301"},{name:"布尔津县",code:"654321"},{name:"富蕴县",code:"654322"},{name:"福海县",code:"654323"},{name:"哈巴河县",code:"654324"},{name:"青河县",code:"654325"},{name:"吉木乃县",code:"654326"}]},{name:"自治区直辖县级行政区划",code:"659000",sub:[{name:"石河子市",code:"659001"},{name:"阿拉尔市",code:"659002"},{name:"图木舒克市",code:"659003"},{name:"五家渠市",code:"659004"},{name:"北屯市",code:"659005"},{name:"铁门关市",code:"659006"},{name:"双河市",code:"659007"}]}]},{name:"台湾省",code:"710000",sub:[{name:"台北市",code:"710100",sub:[{name:"松山区",code:"710101"},{name:"信义区",code:"710102"},{name:"大安区",code:"710103"},{name:"中山区",code:"710104"},{name:"中正区",code:"710105"},{name:"大同区",code:"710106"},{name:"万华区",code:"710107"},{name:"文山区",code:"710108"},{name:"南港区",code:"710109"},{name:"内湖区",code:"710110"},{name:"士林区",code:"710111"},{name:"北投区",code:"710112"}]},{name:"高雄市",code:"710200",sub:[{name:"盐埕区",code:"710201"},{name:"鼓山区",code:"710202"},{name:"左营区",code:"710203"},{name:"楠梓区",code:"710204"},{name:"三民区",code:"710205"},{name:"新兴区",code:"710206"},{name:"前金区",code:"710207"},{name:"苓雅区",code:"710208"},{name:"前镇区",code:"710209"},{name:"旗津区",code:"710210"},{name:"小港区",code:"710211"},{name:"凤山区",code:"710212"},{name:"林园区",code:"710213"},{name:"大寮区",code:"710214"},{name:"大树区",code:"710215"},{name:"大社区",code:"710216"},{name:"仁武区",code:"710217"},{name:"鸟松区",code:"710218"},{name:"冈山区",code:"710219"},{name:"桥头区",code:"710220"},{name:"燕巢区",code:"710221"},{name:"田寮区",code:"710222"},{name:"阿莲区",code:"710223"},{name:"路竹区",code:"710224"},{name:"湖内区",code:"710225"},{name:"茄萣区",code:"710226"},{name:"永安区",code:"710227"},{name:"弥陀区",code:"710228"},{name:"梓官区",code:"710229"},{name:"旗山区",code:"710230"},{name:"美浓区",code:"710231"},{name:"六龟区",code:"710232"},{name:"甲仙区",code:"710233"},{name:"杉林区",code:"710234"},{name:"内门区",code:"710235"},{name:"茂林区",code:"710236"},{name:"桃源区",code:"710237"},{name:"那玛夏区",code:"710238"}]},{name:"基隆市",code:"710300",sub:[{name:"中正区",code:"710301"},{name:"七堵区",code:"710302"},{name:"暖暖区",code:"710303"},{name:"仁爱区",code:"710304"},{name:"中山区",code:"710305"},{name:"安乐区",code:"710306"},{name:"信义区",code:"710307"}]},{name:"台中市",code:"710400",sub:[{name:"中区",code:"710401"},{name:"东区",code:"710402"},{name:"南区",code:"710403"},{name:"西区",code:"710404"},{name:"北区",code:"710405"},{name:"西屯区",code:"710406"},{name:"南屯区",code:"710407"},{name:"北屯区",code:"710408"},{name:"丰原区",code:"710409"},{name:"东势区",code:"710410"},{name:"大甲区",code:"710411"},{name:"清水区",code:"710412"},{name:"沙鹿区",code:"710413"},{name:"梧栖区",code:"710414"},{name:"后里区",code:"710415"},{name:"神冈区",code:"710416"},{name:"潭子区",code:"710417"},{name:"大雅区",code:"710418"},{name:"新社区",code:"710419"},{name:"石冈区",code:"710420"},{name:"外埔区",code:"710421"},{name:"大安区",code:"710422"},{name:"乌日区",code:"710423"},{name:"大肚区",code:"710424"},{name:"龙井区",code:"710425"},{name:"雾峰区",code:"710426"},{name:"太平区",code:"710427"},{name:"大里区",code:"710428"},{name:"和平区",code:"710429"}]},{name:"台南市",code:"710500",sub:[{name:"东区",code:"710501"},{name:"南区",code:"710502"},{name:"北区",code:"710504"},{name:"安南区",code:"710506"},{name:"安平区",code:"710507"},{name:"中西区",code:"710508"},{name:"新营区",code:"710509"},{name:"盐水区",code:"710510"},{name:"白河区",code:"710511"},{name:"柳营区",code:"710512"},{name:"后壁区",code:"710513"},{name:"东山区",code:"710514"},{name:"麻豆区",code:"710515"},{name:"下营区",code:"710516"},{name:"六甲区",code:"710517"},{name:"官田区",code:"710518"},{name:"大内区",code:"710519"},{name:"佳里区",code:"710520"},{name:"学甲区",code:"710521"},{name:"西港区",code:"710522"},{name:"七股区",code:"710523"},{name:"将军区",code:"710524"},{name:"北门区",code:"710525"},{name:"新化区",code:"710526"},{name:"善化区",code:"710527"},{name:"新市区",code:"710528"},{name:"安定区",code:"710529"},{name:"山上区",code:"710530"},{name:"玉井区",code:"710531"},{name:"楠西区",code:"710532"},{name:"南化区",code:"710533"},{name:"左镇区",code:"710534"},{name:"仁德区",code:"710535"},{name:"归仁区",code:"710536"},{name:"关庙区",code:"710537"},{name:"龙崎区",code:"710538"},{name:"永康区",code:"710539"}]},{name:"新竹市",code:"710600",sub:[{name:"东区",code:"710601"},{name:"北区",code:"710602"},{name:"香山区",code:"710603"}]},{name:"嘉义市",code:"710700",sub:[{name:"东区",code:"710701"},{name:"西区",code:"710702"}]},{name:"新北市",code:"710800",sub:[{name:"板桥区",code:"710801"},{name:"三重区",code:"710802"},{name:"中和区",code:"710803"},{name:"永和区",code:"710804"},{name:"新庄区",code:"710805"},{name:"新店区",code:"710806"},{name:"树林区",code:"710807"},{name:"莺歌区",code:"710808"},{name:"三峡区",code:"710809"},{name:"淡水区",code:"710810"},{name:"汐止区",code:"710811"},{name:"瑞芳区",code:"710812"},{name:"土城区",code:"710813"},{name:"芦洲区",code:"710814"},{name:"五股区",code:"710815"},{name:"泰山区",code:"710816"},{name:"林口区",code:"710817"},{name:"深坑区",code:"710818"},{name:"石碇区",code:"710819"},{name:"坪林区",code:"710820"},{name:"三芝区",code:"710821"},{name:"石门区",code:"710822"},{name:"八里区",code:"710823"},{name:"平溪区",code:"710824"},{name:"双溪区",code:"710825"},{name:"贡寮区",code:"710826"},{name:"金山区",code:"710827"},{name:"万里区",code:"710828"},{name:"乌来区",code:"710829"}]},{name:"宜兰县",code:"712200",sub:[{name:"宜兰市",code:"712201"},{name:"罗东镇",code:"712221"},{name:"苏澳镇",code:"712222"},{name:"头城镇",code:"712223"},{name:"礁溪乡",code:"712224"},{name:"壮围乡",code:"712225"},{name:"员山乡",code:"712226"},{name:"冬山乡",code:"712227"},{name:"五结乡",code:"712228"},{name:"三星乡",code:"712229"},{name:"大同乡",code:"712230"},{name:"南澳乡",code:"712231"}]},{name:"桃园县",code:"712300",sub:[{name:"桃园市",code:"712301"},{name:"中坜市",code:"712302"},{name:"平镇市",code:"712303"},{name:"八德市",code:"712304"},{name:"杨梅市",code:"712305"},{name:"大溪镇",code:"712321"},{name:"芦竹乡",code:"712323"},{name:"大园乡",code:"712324"},{name:"龟山乡",code:"712325"},{name:"龙潭乡",code:"712327"},{name:"新屋乡",code:"712329"},{name:"观音乡",code:"712330"},{name:"复兴乡",code:"712331"}]},{name:"新竹县",code:"712400",sub:[{name:"竹北市",code:"712401"},{name:"竹东镇",code:"712421"},{name:"新埔镇",code:"712422"},{name:"关西镇",code:"712423"},{name:"湖口乡",code:"712424"},{name:"新丰乡",code:"712425"},{name:"芎林乡",code:"712426"},{name:"橫山乡",code:"712427"},{name:"北埔乡",code:"712428"},{name:"宝山乡",code:"712429"},{name:"峨眉乡",code:"712430"},{name:"尖石乡",code:"712431"},{name:"五峰乡",code:"712432"}]},{name:"苗栗县",code:"712500",sub:[{name:"苗栗市",code:"712501"},{name:"苑里镇",code:"712521"},{name:"通霄镇",code:"712522"},{name:"竹南镇",code:"712523"},{name:"头份镇",code:"712524"},{name:"后龙镇",code:"712525"},{name:"卓兰镇",code:"712526"},{name:"大湖乡",code:"712527"},{name:"公馆乡",code:"712528"},{name:"铜锣乡",code:"712529"},{name:"南庄乡",code:"712530"},{name:"头屋乡",code:"712531"},{name:"三义乡",code:"712532"},{name:"西湖乡",code:"712533"},{name:"造桥乡",code:"712534"},{name:"三湾乡",code:"712535"},{name:"狮潭乡",code:"712536"},{name:"泰安乡",code:"712537"}]},{name:"彰化县",code:"712700",sub:[{name:"彰化市",code:"712701"},{name:"鹿港镇",code:"712721"},{name:"和美镇",code:"712722"},{name:"线西乡",code:"712723"},{name:"伸港乡",code:"712724"},{name:"福兴乡",code:"712725"},{name:"秀水乡",code:"712726"},{name:"花坛乡",code:"712727"},{name:"芬园乡",code:"712728"},{name:"员林镇",code:"712729"},{name:"溪湖镇",code:"712730"},{name:"田中镇",code:"712731"},{name:"大村乡",code:"712732"},{name:"埔盐乡",code:"712733"},{name:"埔心乡",code:"712734"},{name:"永靖乡",code:"712735"},{name:"社头乡",code:"712736"},{name:"二水乡",code:"712737"},{name:"北斗镇",code:"712738"},{name:"二林镇",code:"712739"},{name:"田尾乡",code:"712740"},{name:"埤头乡",code:"712741"},{name:"芳苑乡",code:"712742"},{name:"大城乡",code:"712743"},{name:"竹塘乡",code:"712744"},{name:"溪州乡",code:"712745"}]},{name:"南投县",code:"712800",sub:[{name:"南投市",code:"712801"},{name:"埔里镇",code:"712821"},{name:"草屯镇",code:"712822"},{name:"竹山镇",code:"712823"},{name:"集集镇",code:"712824"},{name:"名间乡",code:"712825"},{name:"鹿谷乡",code:"712826"},{name:"中寮乡",code:"712827"},{name:"鱼池乡",code:"712828"},{name:"国姓乡",code:"712829"},{name:"水里乡",code:"712830"},{name:"信义乡",code:"712831"},{name:"仁爱乡",code:"712832"}]},{name:"云林县",code:"712900",sub:[{name:"斗六市",code:"712901"},{name:"斗南镇",code:"712921"},{name:"虎尾镇",code:"712922"},{name:"西螺镇",code:"712923"},{name:"土库镇",code:"712924"},{name:"北港镇",code:"712925"},{name:"古坑乡",code:"712926"},{name:"大埤乡",code:"712927"},{name:"莿桐乡",code:"712928"},{name:"林内乡",code:"712929"},{name:"二仑乡",code:"712930"},{name:"仑背乡",code:"712931"},{name:"麦寮乡",code:"712932"},{name:"东势乡",code:"712933"},{name:"褒忠乡",code:"712934"},{name:"台西乡",code:"712935"},{name:"元长乡",code:"712936"},{name:"四湖乡",code:"712937"},{name:"口湖乡",code:"712938"},{name:"水林乡",code:"712939"}]},{name:"嘉义县",code:"713000",sub:[{name:"太保市",code:"713001"},{name:"朴子市",code:"713002"},{name:"布袋镇",code:"713023"},{name:"大林镇",code:"713024"},{name:"民雄乡",code:"713025"},{name:"溪口乡",code:"713026"},{name:"新港乡",code:"713027"},{name:"六脚乡",code:"713028"},{name:"东石乡",code:"713029"},{name:"义竹乡",code:"713030"},{name:"鹿草乡",code:"713031"},{name:"水上乡",code:"713032"},{name:"中埔乡",code:"713033"},{name:"竹崎乡",code:"713034"},{name:"梅山乡",code:"713035"},{name:"番路乡",code:"713036"},{name:"大埔乡",code:"713037"},{name:"阿里山乡",code:"713038"}]},{name:"屏东县",code:"713300",sub:[{name:"屏东市",code:"713301"},{name:"潮州镇",code:"713321"},{name:"东港镇",code:"713322"},{name:"恒春镇",code:"713323"},{name:"万丹乡",code:"713324"},{name:"长治乡",code:"713325"},{name:"麟洛乡",code:"713326"},{name:"九如乡",code:"713327"},{name:"里港乡",code:"713328"},{name:"盐埔乡",code:"713329"},{name:"高树乡",code:"713330"},{name:"万峦乡",code:"713331"},{name:"内埔乡",code:"713332"},{name:"竹田乡",code:"713333"},{name:"新埤乡",code:"713334"},{name:"枋寮乡",code:"713335"},{name:"新园乡",code:"713336"},{name:"崁顶乡",code:"713337"},{name:"林边乡",code:"713338"},{name:"南州乡",code:"713339"},{name:"佳冬乡",code:"713340"},{name:"琉球乡",code:"713341"},{name:"车城乡",code:"713342"},{name:"满州乡",code:"713343"},{name:"枋山乡",code:"713344"},{name:"三地门乡",code:"713345"},{name:"雾台乡",code:"713346"},{name:"玛家乡",code:"713347"},{name:"泰武乡",code:"713348"},{name:"来义乡",code:"713349"},{name:"春日乡",code:"713350"},{name:"狮子乡",code:"713351"},{name:"牡丹乡",code:"713352"}]},{name:"台东县",code:"713400",sub:[{name:"台东市",code:"713401"},{name:"成功镇",code:"713421"},{name:"关山镇",code:"713422"},{name:"卑南乡",code:"713423"},{name:"鹿野乡",code:"713424"},{name:"池上乡",code:"713425"},{name:"东河乡",code:"713426"},{name:"长滨乡",code:"713427"},{name:"太麻里乡",code:"713428"},{name:"大武乡",code:"713429"},{name:"绿岛乡",code:"713430"},{name:"海端乡",code:"713431"},{name:"延平乡",code:"713432"},{name:"金峰乡",code:"713433"},{name:"达仁乡",code:"713434"},{name:"兰屿乡",code:"713435"}]},{name:"花莲县",code:"713500",sub:[{name:"花莲市",code:"713501"},{name:"凤林镇",code:"713521"},{name:"玉里镇",code:"713522"},{name:"新城乡",code:"713523"},{name:"吉安乡",code:"713524"},{name:"寿丰乡",code:"713525"},{name:"光复乡",code:"713526"},{name:"丰滨乡",code:"713527"},{name:"瑞穗乡",code:"713528"},{name:"富里乡",code:"713529"},{name:"秀林乡",code:"713530"},{name:"万荣乡",code:"713531"},{name:"卓溪乡",code:"713532"}]},{name:"澎湖县",code:"713600",sub:[{name:"马公市",code:"713601"},{name:"湖西乡",code:"713621"},{name:"白沙乡",code:"713622"},{name:"西屿乡",code:"713623"},{name:"望安乡",code:"713624"},{name:"七美乡",code:"713625"}]}]},{name:"香港特别行政区",code:"810000",sub:[{name:"香港岛",code:"810100",sub:[{name:"中西区",code:"810101"},{name:"湾仔区",code:"810102"},{name:"东区",code:"810103"},{name:"南区",code:"810104"}]},{name:"九龙",code:"810200",sub:[{name:"油尖旺区",code:"810201"},{name:"深水埗区",code:"810202"},{name:"九龙城区",code:"810203"},{name:"黄大仙区",code:"810204"},{name:"观塘区",code:"810205"}]},{name:"新界",code:"810300",sub:[{name:"荃湾区",code:"810301"},{name:"屯门区",code:"810302"},{name:"元朗区",code:"810303"},{name:"北区",code:"810304"},{name:"大埔区",code:"810305"},{name:"西贡区",code:"810306"},{name:"沙田区",code:"810307"},{name:"葵青区",code:"810308"},{name:"离岛区",code:"810309"}]}]},{name:"澳门特别行政区",code:"820000",sub:[{name:"澳门半岛",code:"820100",sub:[{name:"花地玛堂区",code:"820101"},{name:"圣安多尼堂区",code:"820102"},{name:"大堂区",code:"820103"},{name:"望德堂区",code:"820104"},{name:"风顺堂区",code:"820105"}]},{name:"氹仔岛",code:"820200",sub:[{name:"嘉模堂区",code:"820201"}]},{name:"路环岛",code:"820300",sub:[{name:"圣方济各堂区",code:"820301"}]}]}]}($),+function(e){"use strict";var n,a=e.rawCitiesData,c=function(e){for(var n=[],a=0;a<e.length;a++){var c=e[a];/^请选择|市辖区/.test(c.name)||n.push(c)}return n.length?n:[]},o=function(e){return e.sub?c(e.sub):[{name:"",code:e.code}]},m=function(e){for(var n=0;n<a.length;n++)if(a[n].code===e||a[n].name===e)return o(a[n]);return[]},d=function(e,n){for(var c=0;c<a.length;c++)if(a[c].code===e||a[c].name===e)for(var m=0;m<a[c].sub.length;m++)if(a[c].sub[m].code===n||a[c].sub[m].name===n)return o(a[c].sub[m])},u=function(e){var n,c,o=a[0],m=e.split(" ");return a.map(function(e){e.name===m[0]&&(o=e)}),o.sub.map(function(e){e.name===m[1]&&(n=e)}),m[2]&&n.sub.map(function(e){e.name===m[2]&&(c=e)}),c?[o.code,n.code,c.code]:[o.code,n.code]};e.fn.cityPicker=function(c){return c=e.extend({},n,c),this.each(function(){var n=this,s=a.map(function(e){return e.name}),b=a.map(function(e){return e.code}),t=o(a[0]),r=t.map(function(e){return e.name}),i=t.map(function(e){return e.code}),l=o(a[0].sub[0]),f=l.map(function(e){return e.name}),p=l.map(function(e){return e.code}),v=s[0],h=r[0],V=f[0],y=[{displayValues:s,values:b,cssClass:"col-province"},{displayValues:r,values:i,cssClass:"col-city"}];c.showDistrict&&y.push({values:p,displayValues:f,cssClass:"col-district"});var g={cssClass:"city-picker",rotateEffect:!1,formatValue:function(e,n,a){return a.join(" ")},onChange:function(a,o,u){var s,b=a.cols[0].displayValue;if(b!==v){var t=m(b);s=t[0].name;var r=d(b,s);return a.cols[1].replaceValues(t.map(function(e){return e.code}),t.map(function(e){return e.name})),c.showDistrict&&a.cols[2].replaceValues(r.map(function(e){return e.code}),r.map(function(e){return e.name})),v=b,h=s,a.updateValue(),!1}if(c.showDistrict&&(s=a.cols[1].displayValue,s!==h)){var i=d(b,s);return a.cols[2].replaceValues(i.map(function(e){return e.code}),i.map(function(e){return e.name})),h=s,a.updateValue(),!1}var l=o[o.length-1]?o.length-1:o.length-2;e(n).attr("data-code",o[l]),e(n).attr("data-codes",o.join(",")),c.onChange&&c.onChange.call(n,a,o,u)},cols:y};if(this){var C=e.extend({},c,g),w=e(this).val();if(w||(w="北京 北京市 东城区"),v=w.split(" ")[0],h=w.split(" ")[1],V=w.split(" ")[2],w){if(C.value=u(w),C.value[0]){var D=m(C.value[0]);C.cols[1].values=D.map(function(e){return e.code}),C.cols[1].displayValues=D.map(function(e){return e.name})}if(C.value[1]){if(c.showDistrict){var k=d(C.value[0],C.value[1]);C.cols[2].values=k.map(function(e){return e.code}),C.cols[2].displayValues=k.map(function(e){return e.name})}}else if(c.showDistrict){var k=d(C.value[0],C.cols[1].values[0]);C.cols[2].values=k.map(function(e){return e.code}),C.cols[2].displayValues=k.map(function(e){return e.name})}}e(this).picker(C)}})},n=e.fn.cityPicker.prototype.defaults={showDistrict:!0}}($);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-2.1.4.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-2.1.4.js
new file mode 100644
index 0000000..eed1777
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-2.1.4.js
@@ -0,0 +1,9210 @@
+/*!
+ * jQuery JavaScript Library v2.1.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:01Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper `window`
+		// is present, execute the factory and get jQuery.
+		// For environments that do not have a `window` with a `document`
+		// (such as Node.js), expose a factory as module.exports.
+		// This accentuates the need for the creation of a real `window`.
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info.
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//
+
+var arr = [];
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	version = "2.1.4",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android<4.1
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return just the one element from the set
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return all the elements in a clean array
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ) );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	eq: function( i ) {
+		var len = this.length,
+			j = +i + ( i < 0 ? len : 0 );
+		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: arr.sort,
+	splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+
+		// Skip the boolean and the target
+		target = arguments[ i ] || {};
+		i++;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// Extend jQuery itself if only one argument is passed
+	if ( i === length ) {
+		target = this;
+		i--;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	// Unique for each copy of jQuery on the page
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+	// Assume jQuery is ready without the ready module
+	isReady: true,
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	noop: function() {},
+
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray,
+
+	isWindow: function( obj ) {
+		return obj != null && obj === obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		// adding 1 corrects loss of precision from parseFloat (#15100)
+		return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
+	},
+
+	isPlainObject: function( obj ) {
+		// Not plain objects:
+		// - Any object or value whose internal [[Class]] property is not "[object Object]"
+		// - DOM nodes
+		// - window
+		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		if ( obj.constructor &&
+				!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
+			return false;
+		}
+
+		// If the function hasn't returned already, we're confident that
+		// |obj| is a plain object, created by {} or constructed with new Object
+		return true;
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+		// Support: Android<4.0, iOS<6 (functionish RegExp)
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	globalEval: function( code ) {
+		var script,
+			indirect = eval;
+
+		code = jQuery.trim( code );
+
+		if ( code ) {
+			// If the code includes a valid, prologue position
+			// strict mode pragma, execute code by injecting a
+			// script tag into the document.
+			if ( code.indexOf("use strict") === 1 ) {
+				script = document.createElement("script");
+				script.text = code;
+				document.head.appendChild( script ).parentNode.removeChild( script );
+			} else {
+			// Otherwise, avoid the DOM node creation, insertion
+			// and removal by using an indirect global eval
+				indirect( code );
+			}
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Support: IE9-11+
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
+
+		if ( args ) {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android<4.1
+	trim: function( text ) {
+		return text == null ?
+			"" :
+			( text + "" ).replace( rtrim, "" );
+	},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var ret = results || [];
+
+		if ( arr != null ) {
+			if ( isArraylike( Object(arr) ) ) {
+				jQuery.merge( ret,
+					typeof arr === "string" ?
+					[ arr ] : arr
+				);
+			} else {
+				push.call( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		return arr == null ? -1 : indexOf.call( arr, elem, i );
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		for ( ; j < len; j++ ) {
+			first[ i++ ] = second[ j ];
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
+			i = 0,
+			length = elems.length,
+			callbackExpect = !invert;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
+			}
+		}
+
+		return matches;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value,
+			i = 0,
+			length = elems.length,
+			isArray = isArraylike( elems ),
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( i in elems ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var tmp, args, proxy;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	now: Date.now,
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+
+	// Support: iOS 8.2 (not reproducible in simulator)
+	// `in` check used to prevent JIT error (gh-2145)
+	// hasOwn isn't used here due to false negatives
+	// regarding Nodelist length in IE
+	var length = "length" in obj && obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	if ( obj.nodeType === 1 && length ) {
+		return true;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+	support,
+	Expr,
+	getText,
+	isXML,
+	tokenize,
+	compile,
+	select,
+	outermostContext,
+	sortInput,
+	hasDuplicate,
+
+	// Local document vars
+	setDocument,
+	document,
+	docElem,
+	documentIsHTML,
+	rbuggyQSA,
+	rbuggyMatches,
+	matches,
+	contains,
+
+	// Instance-specific data
+	expando = "sizzle" + 1 * new Date(),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf as it's faster than native
+	// http://jsperf.com/thor-indexof-vs-for/5
+	indexOf = function( list, elem ) {
+		var i = 0,
+			len = list.length;
+		for ( ; i < len; i++ ) {
+			if ( list[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+	// Regular expressions
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + characterEncoding + ")(?:\\((" +
+		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+		// 1. quoted (capture 3; capture 4 or capture 5)
+		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+		// 2. simple (capture 6)
+		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+		// 3. anything else (capture 2)
+		".*" +
+		")\\)|)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rwhitespace = new RegExp( whitespace + "+", "g" ),
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+	rpseudo = new RegExp( pseudos ),
+	ridentifier = new RegExp( "^" + identifier + "$" ),
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	},
+
+	// Used for iframes
+	// See setDocument()
+	// Removing the function wrapper causes a "Permission Denied"
+	// error in IE
+	unloadHandler = function() {
+		setDocument();
+	};
+
+// Optimize for push.apply( _, NodeList )
+try {
+	push.apply(
+		(arr = slice.call( preferredDoc.childNodes )),
+		preferredDoc.childNodes
+	);
+	// Support: Android<4.0
+	// Detect silently failing push.apply
+	arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+	push = { apply: arr.length ?
+
+		// Leverage slice if possible
+		function( target, els ) {
+			push_native.apply( target, slice.call(els) );
+		} :
+
+		// Support: IE<9
+		// Otherwise append directly
+		function( target, els ) {
+			var j = target.length,
+				i = 0;
+			// Can't trust NodeList.length
+			while ( (target[j++] = els[i++]) ) {}
+			target.length = j - 1;
+		}
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	var match, elem, m, nodeType,
+		// QSA vars
+		i, groups, old, nid, newContext, newSelector;
+
+	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+		setDocument( context );
+	}
+
+	context = context || document;
+	results = results || [];
+	nodeType = context.nodeType;
+
+	if ( typeof selector !== "string" || !selector ||
+		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+		return results;
+	}
+
+	if ( !seed && documentIsHTML ) {
+
+		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document (jQuery #6963)
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, context.getElementsByTagName( selector ) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && support.getElementsByClassName ) {
+				push.apply( results, context.getElementsByClassName( m ) );
+				return results;
+			}
+		}
+
+		// QSA path
+		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+			nid = old = expando;
+			newContext = context;
+			newSelector = nodeType !== 1 && selector;
+
+			// qSA works strangely on Element-rooted queries
+			// We can work around this by specifying an extra ID on the root
+			// and working up from there (Thanks to Andrew Dupont for the technique)
+			// IE 8 doesn't work on object elements
+			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+				groups = tokenize( selector );
+
+				if ( (old = context.getAttribute("id")) ) {
+					nid = old.replace( rescape, "\\$&" );
+				} else {
+					context.setAttribute( "id", nid );
+				}
+				nid = "[id='" + nid + "'] ";
+
+				i = groups.length;
+				while ( i-- ) {
+					groups[i] = nid + toSelector( groups[i] );
+				}
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+				newSelector = groups.join(",");
+			}
+
+			if ( newSelector ) {
+				try {
+					push.apply( results,
+						newContext.querySelectorAll( newSelector )
+					);
+					return results;
+				} catch(qsaError) {
+				} finally {
+					if ( !old ) {
+						context.removeAttribute("id");
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = attrs.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare, parent,
+		doc = node ? node.ownerDocument || node : preferredDoc;
+
+	// If no document and documentElement is available, return
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Set our document
+	document = doc;
+	docElem = doc.documentElement;
+	parent = doc.defaultView;
+
+	// Support: IE>8
+	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
+	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+	// IE6-8 do not support the defaultView property so parent will be undefined
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", unloadHandler, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", unloadHandler );
+		}
+	}
+
+	/* Support tests
+	---------------------------------------------------------------------- */
+	documentIsHTML = !isXML( doc );
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties
+	// (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( doc.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Support: IE<9
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+				var m = context.getElementById( id );
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [ m ] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
+				return context.getElementsByTagName( tag );
+
+			// DocumentFragment nodes don't have gEBTN
+			} else if ( support.qsa ) {
+				return context.querySelectorAll( tag );
+			}
+		} :
+
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+				"<select id='" + expando + "-\f]' msallowcapture=''>" +
+				"<option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+				rbuggyQSA.push("~=");
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+
+			// Support: Safari 8+, iOS 8+
+			// https://bugs.webkit.org/show_bug.cgi?id=136851
+			// In-page `selector#id sibing-combinator selector` fails
+			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+				rbuggyQSA.push(".#.+[+~]");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = doc.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully does not implement inclusive descendent
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === doc ? -1 :
+				b === doc ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch (e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, outerCache, node, diff, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+							// Seek `elem` from a previously-cached index
+							outerCache = parent[ expando ] || (parent[ expando ] = {});
+							cache = outerCache[ type ] || [];
+							nodeIndex = cache[0] === dirruns && cache[1];
+							diff = cache[0] === dirruns && cache[2];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						// Use previously-cached element index if available
+						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+							diff = cache[1];
+
+						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+						} else {
+							// Use the same loop as above to seek `elem` from the start
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+									// Cache the index of each encountered element
+									if ( useCache ) {
+										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+									}
+
+									if ( node === elem ) {
+										break;
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					// Don't keep the element (issue #299)
+					input[0] = null;
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			text = text.replace( runescape, funescape );
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+			// Avoid hanging onto element (issue #299)
+			checkContext = null;
+			return ret;
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !match ) {
+			match = tokenize( selector );
+		}
+		i = match.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( match[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+		// Save selector and tokenization
+		cached.selector = selector;
+	}
+	return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		compiled = typeof selector === "function" && selector,
+		match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+	results = results || [];
+
+	// Try to minimize operations if there is no seed and only one group
+	if ( match.length === 1 ) {
+
+		// Take a shortcut and set the context if the root selector is an ID
+		tokens = match[0] = match[0].slice( 0 );
+		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+				support.getById && context.nodeType === 9 && documentIsHTML &&
+				Expr.relative[ tokens[1].type ] ) {
+
+			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+			if ( !context ) {
+				return results;
+
+			// Precompiled matchers will still verify ancestry, so step up a level
+			} else if ( compiled ) {
+				context = context.parentNode;
+			}
+
+			selector = selector.slice( tokens.shift().value.length );
+		}
+
+		// Fetch a seed set for right-to-left matching
+		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+		while ( i-- ) {
+			token = tokens[i];
+
+			// Abort if we hit a combinator
+			if ( Expr.relative[ (type = token.type) ] ) {
+				break;
+			}
+			if ( (find = Expr.find[ type ]) ) {
+				// Search, expanding context for leading sibling combinators
+				if ( (seed = find(
+					token.matches[0].replace( runescape, funescape ),
+					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+				)) ) {
+
+					// If seed is empty or no tokens remain, we can return early
+					tokens.splice( i, 1 );
+					selector = seed.length && toSelector( tokens );
+					if ( !selector ) {
+						push.apply( results, seed );
+						return results;
+					}
+
+					break;
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function if one is not provided
+	// Provide `match` to avoid retokenization if we modified the selector above
+	( compiled || compile( selector, match ) )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			len = this.length,
+			ret = [],
+			self = this;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// Option to run scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Support: Blackberry 4.6
+					// gEBID returns nodes no longer in the document (#6963)
+					if ( elem && elem.parentNode ) {
+						// Inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// Methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			truncate = until !== undefined;
+
+		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
+			if ( elem.nodeType === 1 ) {
+				if ( truncate && jQuery( elem ).is( until ) ) {
+					break;
+				}
+				matched.push( elem );
+			}
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var matched = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				matched.push( n );
+			}
+		}
+
+		return matched;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var targets = jQuery( target, this ),
+			l = targets.length;
+
+		return this.filter(function() {
+			var i = 0;
+			for ( ; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within the set
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// Index in selector
+		if ( typeof elem === "string" ) {
+			return indexOf.call( jQuery( elem ), this[ 0 ] );
+		}
+
+		// Locate the position of the desired element
+		return indexOf.call( this,
+
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[ 0 ] : elem
+		);
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var matched = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			matched = jQuery.filter( selector, matched );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				jQuery.unique( matched );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				matched.reverse();
+			}
+		}
+
+		return this.pushStack( matched );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// Flag to know if list is currently firing
+		firing,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( list && ( !fired || stack ) ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+					} else if ( !( --remaining ) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// Add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// If we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.triggerHandler ) {
+			jQuery( document ).triggerHandler( "ready" );
+			jQuery( document ).off( "ready" );
+		}
+	}
+});
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	document.removeEventListener( "DOMContentLoaded", completed, false );
+	window.removeEventListener( "load", completed, false );
+	jQuery.ready();
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// We once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		} else {
+
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+		}
+	}
+	return readyList.promise( obj );
+};
+
+// Kick off the DOM ready check even if the user does not
+jQuery.ready.promise();
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		len = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < len; i++ ) {
+				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			len ? fn( elems[0], key ) : emptyGet;
+};
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( owner ) {
+	// Accepts only:
+	//  - Node
+	//    - Node.ELEMENT_NODE
+	//    - Node.DOCUMENT_NODE
+	//  - Object
+	//    - Any
+	/* jshint -W018 */
+	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+function Data() {
+	// Support: Android<4,
+	// Old WebKit does not have Object.preventExtensions/freeze method,
+	// return new empty object instead with no [[set]] accessor
+	Object.defineProperty( this.cache = {}, 0, {
+		get: function() {
+			return {};
+		}
+	});
+
+	this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+Data.accepts = jQuery.acceptData;
+
+Data.prototype = {
+	key: function( owner ) {
+		// We can accept data for non-element nodes in modern browsers,
+		// but we should not, see #8335.
+		// Always return the key for a frozen object.
+		if ( !Data.accepts( owner ) ) {
+			return 0;
+		}
+
+		var descriptor = {},
+			// Check if the owner object already has a cache key
+			unlock = owner[ this.expando ];
+
+		// If not, create one
+		if ( !unlock ) {
+			unlock = Data.uid++;
+
+			// Secure it in a non-enumerable, non-writable property
+			try {
+				descriptor[ this.expando ] = { value: unlock };
+				Object.defineProperties( owner, descriptor );
+
+			// Support: Android<4
+			// Fallback to a less secure definition
+			} catch ( e ) {
+				descriptor[ this.expando ] = unlock;
+				jQuery.extend( owner, descriptor );
+			}
+		}
+
+		// Ensure the cache object
+		if ( !this.cache[ unlock ] ) {
+			this.cache[ unlock ] = {};
+		}
+
+		return unlock;
+	},
+	set: function( owner, data, value ) {
+		var prop,
+			// There may be an unlock assigned to this node,
+			// if there is no entry for this "owner", create one inline
+			// and set the unlock as though an owner entry had always existed
+			unlock = this.key( owner ),
+			cache = this.cache[ unlock ];
+
+		// Handle: [ owner, key, value ] args
+		if ( typeof data === "string" ) {
+			cache[ data ] = value;
+
+		// Handle: [ owner, { properties } ] args
+		} else {
+			// Fresh assignments by object are shallow copied
+			if ( jQuery.isEmptyObject( cache ) ) {
+				jQuery.extend( this.cache[ unlock ], data );
+			// Otherwise, copy the properties one-by-one to the cache object
+			} else {
+				for ( prop in data ) {
+					cache[ prop ] = data[ prop ];
+				}
+			}
+		}
+		return cache;
+	},
+	get: function( owner, key ) {
+		// Either a valid cache is found, or will be created.
+		// New caches will be created and the unlock returned,
+		// allowing direct access to the newly created
+		// empty data object. A valid owner object must be provided.
+		var cache = this.cache[ this.key( owner ) ];
+
+		return key === undefined ?
+			cache : cache[ key ];
+	},
+	access: function( owner, key, value ) {
+		var stored;
+		// In cases where either:
+		//
+		//   1. No key was specified
+		//   2. A string key was specified, but no value provided
+		//
+		// Take the "read" path and allow the get method to determine
+		// which value to return, respectively either:
+		//
+		//   1. The entire cache object
+		//   2. The data stored at the key
+		//
+		if ( key === undefined ||
+				((key && typeof key === "string") && value === undefined) ) {
+
+			stored = this.get( owner, key );
+
+			return stored !== undefined ?
+				stored : this.get( owner, jQuery.camelCase(key) );
+		}
+
+		// [*]When the key is not a string, or both a key and value
+		// are specified, set or extend (existing objects) with either:
+		//
+		//   1. An object of properties
+		//   2. A key and value
+		//
+		this.set( owner, key, value );
+
+		// Since the "set" path can have two possible entry points
+		// return the expected data based on which path was taken[*]
+		return value !== undefined ? value : key;
+	},
+	remove: function( owner, key ) {
+		var i, name, camel,
+			unlock = this.key( owner ),
+			cache = this.cache[ unlock ];
+
+		if ( key === undefined ) {
+			this.cache[ unlock ] = {};
+
+		} else {
+			// Support array or space separated string of keys
+			if ( jQuery.isArray( key ) ) {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = key.concat( key.map( jQuery.camelCase ) );
+			} else {
+				camel = jQuery.camelCase( key );
+				// Try the string as a key before any manipulation
+				if ( key in cache ) {
+					name = [ key, camel ];
+				} else {
+					// If a key with the spaces exists, use it.
+					// Otherwise, create an array by matching non-whitespace
+					name = camel;
+					name = name in cache ?
+						[ name ] : ( name.match( rnotwhite ) || [] );
+				}
+			}
+
+			i = name.length;
+			while ( i-- ) {
+				delete cache[ name[ i ] ];
+			}
+		}
+	},
+	hasData: function( owner ) {
+		return !jQuery.isEmptyObject(
+			this.cache[ owner[ this.expando ] ] || {}
+		);
+	},
+	discard: function( owner ) {
+		if ( owner[ this.expando ] ) {
+			delete this.cache[ owner[ this.expando ] ];
+		}
+	}
+};
+var data_priv = new Data();
+
+var data_user = new Data();
+
+
+
+//	Implementation Summary
+//
+//	1. Enforce API surface and semantic compatibility with 1.9.x branch
+//	2. Improve the module's maintainability by reducing the storage
+//		paths to a single mechanism.
+//	3. Use the same single mechanism to support "private" and "user" data.
+//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+//	5. Avoid exposing implementation details on user objects (eg. expando properties)
+//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+	var name;
+
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			data_user.set( elem, key, data );
+		} else {
+			data = undefined;
+		}
+	}
+	return data;
+}
+
+jQuery.extend({
+	hasData: function( elem ) {
+		return data_user.hasData( elem ) || data_priv.hasData( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return data_user.access( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		data_user.remove( elem, name );
+	},
+
+	// TODO: Now that all calls to _data and _removeData have been replaced
+	// with direct calls to data_priv methods, these can be deprecated.
+	_data: function( elem, name, data ) {
+		return data_priv.access( elem, name, data );
+	},
+
+	_removeData: function( elem, name ) {
+		data_priv.remove( elem, name );
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[ 0 ],
+			attrs = elem && elem.attributes;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = data_user.get( elem );
+
+				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+
+						// Support: IE11+
+						// The attrs elements can be null (#14894)
+						if ( attrs[ i ] ) {
+							name = attrs[ i ].name;
+							if ( name.indexOf( "data-" ) === 0 ) {
+								name = jQuery.camelCase( name.slice(5) );
+								dataAttr( elem, name, data[ name ] );
+							}
+						}
+					}
+					data_priv.set( elem, "hasDataAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				data_user.set( this, key );
+			});
+		}
+
+		return access( this, function( value ) {
+			var data,
+				camelKey = jQuery.camelCase( key );
+
+			// The calling jQuery object (element matches) is not empty
+			// (and therefore has an element appears at this[ 0 ]) and the
+			// `value` parameter was not undefined. An empty jQuery object
+			// will result in `undefined` for elem = this[ 0 ] which will
+			// throw an exception if an attempt to read a data cache is made.
+			if ( elem && value === undefined ) {
+				// Attempt to get data from the cache
+				// with the key as-is
+				data = data_user.get( elem, key );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// Attempt to get data from the cache
+				// with the key camelized
+				data = data_user.get( elem, camelKey );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// Attempt to "discover" the data in
+				// HTML5 custom data-* attrs
+				data = dataAttr( elem, camelKey, undefined );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// We tried really hard, but the data doesn't exist.
+				return;
+			}
+
+			// Set the data...
+			this.each(function() {
+				// First, attempt to store a copy or reference of any
+				// data that might've been store with a camelCased key.
+				var data = data_user.get( this, camelKey );
+
+				// For HTML5 data-* attribute interop, we have to
+				// store property names with dashes in a camelCase form.
+				// This might not apply to all properties...*
+				data_user.set( this, camelKey, value );
+
+				// *... In the case of properties that might _actually_
+				// have dashes, we need to also store a copy of that
+				// unchanged property.
+				if ( key.indexOf("-") !== -1 && data !== undefined ) {
+					data_user.set( this, key, value );
+				}
+			});
+		}, null, value, arguments.length > 1, null, true );
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			data_user.remove( this, key );
+		});
+	}
+});
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = data_priv.get( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray( data ) ) {
+					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// Clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// Not public - generate a queueHooks object, or return the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				data_priv.remove( elem, [ type + "queue", key ] );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// Ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+	};
+
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+	var fragment = document.createDocumentFragment(),
+		div = fragment.appendChild( document.createElement( "div" ) ),
+		input = document.createElement( "input" );
+
+	// Support: Safari<=5.1
+	// Check state lost if the name is set (#11217)
+	// Support: Windows Web Apps (WWA)
+	// `name` and `type` must use .setAttribute for WWA (#14901)
+	input.setAttribute( "type", "radio" );
+	input.setAttribute( "checked", "checked" );
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+
+	// Support: Safari<=5.1, Android<4.2
+	// Older WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<=11+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+})();
+var strundefined = typeof undefined;
+
+
+
+support.focusinBubbles = "onfocusin" in window;
+
+
+var
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var handleObjIn, eventHandle, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = data_priv.get( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !(events = elemData.events) ) {
+			events = elemData.events = {};
+		}
+		if ( !(eventHandle = elemData.handle) ) {
+			eventHandle = elemData.handle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
+					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+			};
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !(handlers = events[ type ]) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var j, origCount, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = data_priv.hasData( elem ) && data_priv.get( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+			data_priv.remove( elem, "events" );
+		}
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+
+		var i, cur, tmp, bubbleType, ontype, handle, special,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf(":") < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === (elem.ownerDocument || document) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+				jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					elem[ type ]();
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, j, ret, matched, handleObj,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
+				// a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( (event.result = ret) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var i, matches, sel, handleObj,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+			for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.disabled !== true || event.type !== "click" ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, handlers: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+		}
+
+		return handlerQueue;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var eventDoc, doc, body,
+				button = original.button;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: Cordova 2.5 (WebKit) (#13255)
+		// All events should have a target; Cordova deviceready doesn't
+		if ( !event.target ) {
+			event.target = document;
+		}
+
+		// Support: Safari 6.0+, Chrome<28
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					this.focus();
+					return false;
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Support: Firefox 20+
+				// Firefox doesn't alert if the returnValue field is not set.
+				if ( event.result !== undefined && event.originalEvent ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+	if ( elem.removeEventListener ) {
+		elem.removeEventListener( type, handle, false );
+	}
+};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined &&
+				// Support: Android<4.0
+				src.returnValue === false ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+
+		if ( e && e.preventDefault ) {
+			e.preventDefault();
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+
+		if ( e && e.stopPropagation ) {
+			e.stopPropagation();
+		}
+	},
+	stopImmediatePropagation: function() {
+		var e = this.originalEvent;
+
+		this.isImmediatePropagationStopped = returnTrue;
+
+		if ( e && e.stopImmediatePropagation ) {
+			e.stopImmediatePropagation();
+		}
+
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// Support: Chrome 15+
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout",
+	pointerenter: "pointerover",
+	pointerleave: "pointerout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// Support: Firefox, Chrome, Safari
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = data_priv.access( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = data_priv.access( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					data_priv.remove( doc, fix );
+
+				} else {
+					data_priv.access( doc, fix, attaches );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var origFn, type;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) {
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[0];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+});
+
+
+var
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /^$|\/(?:java|ecma)script/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+	// We have to close these tags to support XHTML (#13200)
+	wrapMap = {
+
+		// Support: IE9
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+		thead: [ 1, "<table>", "</table>" ],
+		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+		_default: [ 0, "", "" ]
+	};
+
+// Support: IE9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// Support: 1.x compatibility
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName("tbody")[0] ||
+			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+
+	if ( match ) {
+		elem.type = match[ 1 ];
+	} else {
+		elem.removeAttribute("type");
+	}
+
+	return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var i = 0,
+		l = elems.length;
+
+	for ( ; i < l; i++ ) {
+		data_priv.set(
+			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
+		);
+	}
+}
+
+function cloneCopyEvent( src, dest ) {
+	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	// 1. Copy private data: events, handlers, etc.
+	if ( data_priv.hasData( src ) ) {
+		pdataOld = data_priv.access( src );
+		pdataCur = data_priv.set( dest, pdataOld );
+		events = pdataOld.events;
+
+		if ( events ) {
+			delete pdataCur.handle;
+			pdataCur.events = {};
+
+			for ( type in events ) {
+				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+					jQuery.event.add( dest, type, events[ type ][ i ] );
+				}
+			}
+		}
+	}
+
+	// 2. Copy user data
+	if ( data_user.hasData( src ) ) {
+		udataOld = data_user.access( src );
+		udataCur = jQuery.extend( {}, udataOld );
+
+		data_user.set( dest, udataCur );
+	}
+}
+
+function getAll( context, tag ) {
+	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
+			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
+			[];
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], ret ) :
+		ret;
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+	var nodeName = dest.nodeName.toLowerCase();
+
+	// Fails to persist the checked state of a cloned checkbox or radio button.
+	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		dest.checked = src.checked;
+
+	// Fails to return the selected option to the default selected state when cloning options
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var i, l, srcElements, destElements,
+			clone = elem.cloneNode( true ),
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		// Fix IE cloning issues
+		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+				!jQuery.isXMLDoc( elem ) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			for ( i = 0, l = srcElements.length; i < l; i++ ) {
+				fixInput( srcElements[ i ], destElements[ i ] );
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0, l = srcElements.length; i < l; i++ ) {
+					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		// Return the cloned set
+		return clone;
+	},
+
+	buildFragment: function( elems, context, scripts, selection ) {
+		var elem, tmp, tag, wrap, contains, j,
+			fragment = context.createDocumentFragment(),
+			nodes = [],
+			i = 0,
+			l = elems.length;
+
+		for ( ; i < l; i++ ) {
+			elem = elems[ i ];
+
+			if ( elem || elem === 0 ) {
+
+				// Add nodes directly
+				if ( jQuery.type( elem ) === "object" ) {
+					// Support: QtWebKit, PhantomJS
+					// push.apply(_, arraylike) throws on ancient WebKit
+					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+				// Convert non-html into a text node
+				} else if ( !rhtml.test( elem ) ) {
+					nodes.push( context.createTextNode( elem ) );
+
+				// Convert html into DOM nodes
+				} else {
+					tmp = tmp || fragment.appendChild( context.createElement("div") );
+
+					// Deserialize a standard representation
+					tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
+
+					// Descend through wrappers to the right content
+					j = wrap[ 0 ];
+					while ( j-- ) {
+						tmp = tmp.lastChild;
+					}
+
+					// Support: QtWebKit, PhantomJS
+					// push.apply(_, arraylike) throws on ancient WebKit
+					jQuery.merge( nodes, tmp.childNodes );
+
+					// Remember the top-level container
+					tmp = fragment.firstChild;
+
+					// Ensure the created nodes are orphaned (#12392)
+					tmp.textContent = "";
+				}
+			}
+		}
+
+		// Remove wrapper from fragment
+		fragment.textContent = "";
+
+		i = 0;
+		while ( (elem = nodes[ i++ ]) ) {
+
+			// #4087 - If origin and destination elements are the same, and this is
+			// that element, do not do anything
+			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+				continue;
+			}
+
+			contains = jQuery.contains( elem.ownerDocument, elem );
+
+			// Append to fragment
+			tmp = getAll( fragment.appendChild( elem ), "script" );
+
+			// Preserve script evaluation history
+			if ( contains ) {
+				setGlobalEval( tmp );
+			}
+
+			// Capture executables
+			if ( scripts ) {
+				j = 0;
+				while ( (elem = tmp[ j++ ]) ) {
+					if ( rscriptType.test( elem.type || "" ) ) {
+						scripts.push( elem );
+					}
+				}
+			}
+		}
+
+		return fragment;
+	},
+
+	cleanData: function( elems ) {
+		var data, elem, type, key,
+			special = jQuery.event.special,
+			i = 0;
+
+		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
+			if ( jQuery.acceptData( elem ) ) {
+				key = elem[ data_priv.expando ];
+
+				if ( key && (data = data_priv.cache[ key ]) ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+					if ( data_priv.cache[ key ] ) {
+						// Discard any remaining `private` data
+						delete data_priv.cache[ key ];
+					}
+				}
+			}
+			// Discard any remaining `user` data
+			delete data_user.cache[ elem[ data_user.expando ] ];
+		}
+	}
+});
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().each(function() {
+					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+						this.textContent = value;
+					}
+				});
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		});
+	},
+
+	after: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		});
+	},
+
+	remove: function( selector, keepData /* Internal Use Only */ ) {
+		var elem,
+			elems = selector ? jQuery.filter( selector, this ) : this,
+			i = 0;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+			if ( !keepData && elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem ) );
+			}
+
+			if ( elem.parentNode ) {
+				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+					setGlobalEval( getAll( elem, "script" ) );
+				}
+				elem.parentNode.removeChild( elem );
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			if ( elem.nodeType === 1 ) {
+
+				// Prevent memory leaks
+				jQuery.cleanData( getAll( elem, false ) );
+
+				// Remove any remaining nodes
+				elem.textContent = "";
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map(function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined && elem.nodeType === 1 ) {
+				return elem.innerHTML;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for ( ; i < l; i++ ) {
+						elem = this[ i ] || {};
+
+						// Remove element nodes and prevent memory leaks
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch( e ) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var arg = arguments[ 0 ];
+
+		// Make the changes, replacing each context element with the new content
+		this.domManip( arguments, function( elem ) {
+			arg = this.parentNode;
+
+			jQuery.cleanData( getAll( this ) );
+
+			if ( arg ) {
+				arg.replaceChild( elem, this );
+			}
+		});
+
+		// Force removal if there was no new content (e.g., from empty arguments)
+		return arg && (arg.length || arg.nodeType) ? this : this.remove();
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, callback ) {
+
+		// Flatten any nested arrays
+		args = concat.apply( [], args );
+
+		var fragment, first, scripts, hasScripts, node, doc,
+			i = 0,
+			l = this.length,
+			set = this,
+			iNoClone = l - 1,
+			value = args[ 0 ],
+			isFunction = jQuery.isFunction( value );
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( isFunction ||
+				( l > 1 && typeof value === "string" &&
+					!support.checkClone && rchecked.test( value ) ) ) {
+			return this.each(function( index ) {
+				var self = set.eq( index );
+				if ( isFunction ) {
+					args[ 0 ] = value.call( this, index, self.html() );
+				}
+				self.domManip( args, callback );
+			});
+		}
+
+		if ( l ) {
+			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+				hasScripts = scripts.length;
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				for ( ; i < l; i++ ) {
+					node = fragment;
+
+					if ( i !== iNoClone ) {
+						node = jQuery.clone( node, true, true );
+
+						// Keep references to cloned scripts for later restoration
+						if ( hasScripts ) {
+							// Support: QtWebKit
+							// jQuery.merge because push.apply(_, arraylike) throws
+							jQuery.merge( scripts, getAll( node, "script" ) );
+						}
+					}
+
+					callback.call( this[ i ], node, i );
+				}
+
+				if ( hasScripts ) {
+					doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+					// Reenable scripts
+					jQuery.map( scripts, restoreScript );
+
+					// Evaluate executable scripts on first document insertion
+					for ( i = 0; i < hasScripts; i++ ) {
+						node = scripts[ i ];
+						if ( rscriptType.test( node.type || "" ) &&
+							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+							if ( node.src ) {
+								// Optional AJAX dependency, but won't run scripts if not present
+								if ( jQuery._evalUrl ) {
+									jQuery._evalUrl( node.src );
+								}
+							} else {
+								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+							}
+						}
+					}
+				}
+			}
+		}
+
+		return this;
+	}
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1,
+			i = 0;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone( true );
+			jQuery( insert[ i ] )[ original ]( elems );
+
+			// Support: QtWebKit
+			// .get() because push.apply(_, arraylike) throws
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+});
+
+
+var iframe,
+	elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var style,
+		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		// getDefaultComputedStyle might be reliably used only on attached element
+		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+			// Use of this method is a temporary fix (more like optimization) until something better comes along,
+			// since it was removed from specification and supported only in FF
+			style.display : jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = iframe[ 0 ].contentDocument;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+		// IE throws on elements created in popups
+		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+		if ( elem.ownerDocument.defaultView.opener ) {
+			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+		}
+
+		return window.getComputedStyle( elem, null );
+	};
+
+
+
+function curCSS( elem, name, computed ) {
+	var width, minWidth, maxWidth, ret,
+		style = elem.style;
+
+	computed = computed || getStyles( elem );
+
+	// Support: IE9
+	// getPropertyValue is only needed for .css('filter') (#12537)
+	if ( computed ) {
+		ret = computed.getPropertyValue( name ) || computed[ name ];
+	}
+
+	if ( computed ) {
+
+		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+			ret = jQuery.style( elem, name );
+		}
+
+		// Support: iOS < 6
+		// A tribute to the "awesome hack by Dean Edwards"
+		// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+			// Remember the original values
+			width = style.width;
+			minWidth = style.minWidth;
+			maxWidth = style.maxWidth;
+
+			// Put in the new values to get a computed value out
+			style.minWidth = style.maxWidth = style.width = ret;
+			ret = computed.width;
+
+			// Revert the changed values
+			style.width = width;
+			style.minWidth = minWidth;
+			style.maxWidth = maxWidth;
+		}
+	}
+
+	return ret !== undefined ?
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		ret + "" :
+		ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			if ( conditionFn() ) {
+				// Hook not needed (or it's not possible to use it due
+				// to missing dependency), remove it.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+			return (this.get = hookFn).apply( this, arguments );
+		}
+	};
+}
+
+
+(function() {
+	var pixelPositionVal, boxSizingReliableVal,
+		docElem = document.documentElement,
+		container = document.createElement( "div" ),
+		div = document.createElement( "div" );
+
+	if ( !div.style ) {
+		return;
+	}
+
+	// Support: IE9-11+
+	// Style of cloned element affects source element cloned (#8908)
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
+		"position:absolute";
+	container.appendChild( div );
+
+	// Executing both pixelPosition & boxSizingReliable tests require only one layout
+	// so they're executed at the same time to save the second computation.
+	function computePixelPositionAndBoxSizingReliable() {
+		div.style.cssText =
+			// Support: Firefox<29, Android 2.3
+			// Vendor-prefix box-sizing
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+			"border:1px;padding:1px;width:4px;position:absolute";
+		div.innerHTML = "";
+		docElem.appendChild( container );
+
+		var divStyle = window.getComputedStyle( div, null );
+		pixelPositionVal = divStyle.top !== "1%";
+		boxSizingReliableVal = divStyle.width === "4px";
+
+		docElem.removeChild( container );
+	}
+
+	// Support: node.js jsdom
+	// Don't assume that getComputedStyle is a property of the global object
+	if ( window.getComputedStyle ) {
+		jQuery.extend( support, {
+			pixelPosition: function() {
+
+				// This test is executed only once but we still do memoizing
+				// since we can use the boxSizingReliable pre-computing.
+				// No need to check if the test was already performed, though.
+				computePixelPositionAndBoxSizingReliable();
+				return pixelPositionVal;
+			},
+			boxSizingReliable: function() {
+				if ( boxSizingReliableVal == null ) {
+					computePixelPositionAndBoxSizingReliable();
+				}
+				return boxSizingReliableVal;
+			},
+			reliableMarginRight: function() {
+
+				// Support: Android 2.3
+				// Check if div with explicit width and no margin-right incorrectly
+				// gets computed margin-right based on width of container. (#3333)
+				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+				// This support function is only executed once so no memoizing is needed.
+				var ret,
+					marginDiv = div.appendChild( document.createElement( "div" ) );
+
+				// Reset CSS: box-sizing; display; margin; border; padding
+				marginDiv.style.cssText = div.style.cssText =
+					// Support: Firefox<29, Android 2.3
+					// Vendor-prefix box-sizing
+					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+					"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+				marginDiv.style.marginRight = marginDiv.style.width = "0";
+				div.style.width = "1px";
+				docElem.appendChild( container );
+
+				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
+
+				docElem.removeChild( container );
+				div.removeChild( marginDiv );
+
+				return ret;
+			}
+		});
+	}
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var
+	// Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: "0",
+		fontWeight: "400"
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// Shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// Check for vendor prefixed names
+	var capName = name[0].toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// Both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// At this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+			// At this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// At this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// Check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox &&
+			( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// Use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = data_priv.get( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+			}
+		} else {
+			hidden = isHidden( elem );
+
+			if ( display !== "none" || !hidden ) {
+				data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+jQuery.extend({
+
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"columnCount": true,
+		"fillOpacity": true,
+		"flexGrow": true,
+		"flexShrink": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		"float": "cssFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// Gets hook for the prefixed version, then unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// Convert "+=" or "-=" to relative numbers (#7345)
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set (#7116)
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// Support: IE9-11+
+			// background-* props affect original clone's values
+			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+				style[ name ] = value;
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var val, num, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// Try prefixed name followed by the unprefixed name
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		// Convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Make numeric if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+
+				// Certain elements can have dimension info if we invisibly show them
+				// but it must have a current display style that would benefit
+				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+					jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					}) :
+					getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var styles = extra && getStyles( elem );
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				) : 0
+			);
+		}
+	};
+});
+
+// Support: Android 2.3
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			return jQuery.swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// Assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each(function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// Passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails.
+			// Simple values such as "10px" are parsed to Float;
+			// complex values such as "rotate(1rad)" are returned as-is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// Use step hook for back compat.
+			// Use cssHook if its there.
+			// Use .style if available and use plain properties where available.
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE9
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	}
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value ),
+				target = tween.cur(),
+				parts = rfxnum.exec( value ),
+				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+				// Starting value computation is required for potential unit mismatches
+				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+				scale = 1,
+				maxIterations = 20;
+
+			if ( start && start[ 3 ] !== unit ) {
+				// Trust units reported by jQuery.css
+				unit = unit || start[ 3 ];
+
+				// Make sure we update the tween properties later on
+				parts = parts || [];
+
+				// Iteratively approximate from a nonzero starting point
+				start = +target || 1;
+
+				do {
+					// If previous iteration zeroed out, double until we get *something*.
+					// Use string for doubling so we don't accidentally see scale as unchanged below
+					scale = scale || ".5";
+
+					// Adjust and apply
+					start = start / scale;
+					jQuery.style( tween.elem, prop, start + unit );
+
+				// Update scale, tolerating zero or NaN from tween.cur(),
+				// break the loop if scale is unchanged or perfect, or if we've just had enough
+				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+			}
+
+			// Update tween properties
+			if ( parts ) {
+				start = tween.start = +start || +target || 0;
+				tween.unit = unit;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[ 1 ] ?
+					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+					+parts[ 2 ];
+			}
+
+			return tween;
+		} ]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	});
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		i = 0,
+		attrs = { height: type };
+
+	// If we include width, step value is 1 to do all cssExpand values,
+	// otherwise step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+			// We're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = data_priv.get( elem, "fxshow" );
+
+	// Handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// Ensure the complete handler is called before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// Height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE9-10 do not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+
+		// Test default display if display is currently "none"
+		checkDisplay = display === "none" ?
+			data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+			style.display = "inline-block";
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		anim.always(function() {
+			style.overflow = opts.overflow[ 0 ];
+			style.overflowX = opts.overflow[ 1 ];
+			style.overflowY = opts.overflow[ 2 ];
+		});
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+		// Any non-fx value stops us from restoring the original display value
+		} else {
+			display = undefined;
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = data_priv.access( elem, "fxshow", {} );
+		}
+
+		// Store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+
+			data_priv.remove( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+
+	// If this is a noop like .hide().hide(), restore an overwritten display value
+	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+		style.display = display;
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// Not quite $.extend, this won't overwrite existing keys.
+			// Reusing 'index' because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// Don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				// Support: Android 2.3
+				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// If we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// Resolve when we played the last frame; otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// Normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// Show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// Animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || data_priv.get( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = data_priv.get( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Start the next in the queue if the last step wasn't forced.
+			// Timers currently will call their complete callbacks, which
+			// will dequeue but only if they were gotoEnd.
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each(function() {
+			var index,
+				data = data_priv.get( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// Enable finishing flag on private data
+			data.finish = true;
+
+			// Empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// Look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// Turn off finishing flag
+			delete data.finish;
+		});
+	}
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		i = 0,
+		timers = jQuery.timers;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = setTimeout( next, time );
+		hooks.stop = function() {
+			clearTimeout( timeout );
+		};
+	});
+};
+
+
+(function() {
+	var input = document.createElement( "input" ),
+		select = document.createElement( "select" ),
+		opt = select.appendChild( document.createElement( "option" ) );
+
+	input.type = "checkbox";
+
+	// Support: iOS<=5.1, Android<=4.2+
+	// Default value for a checkbox should be "on"
+	support.checkOn = input.value !== "";
+
+	// Support: IE<=11+
+	// Must access selectedIndex to make default options select
+	support.optSelected = opt.selected;
+
+	// Support: Android<=2.3
+	// Options inside disabled selects are incorrectly marked as disabled
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE<=11+
+	// An input loses its value after becoming a radio
+	input = document.createElement( "input" );
+	input.value = "t";
+	input.type = "radio";
+	support.radioValue = input.value === "t";
+})();
+
+
+var nodeHook, boolHook,
+	attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	}
+});
+
+jQuery.extend({
+	attr: function( elem, name, value ) {
+		var hooks, ret,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === strundefined ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+
+			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+			ret = jQuery.find.attr( elem, name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret == null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( (name = attrNames[i++]) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+					// Set corresponding property to false
+					elem[ propName ] = false;
+				}
+
+				elem.removeAttribute( name );
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" &&
+					jQuery.nodeName( elem, "input" ) ) {
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	}
+});
+
+// Hooks for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			elem.setAttribute( name, name );
+		}
+		return name;
+	}
+};
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = function( elem, name, isXML ) {
+		var ret, handle;
+		if ( !isXML ) {
+			// Avoid an infinite loop by temporarily removing this function from the getter
+			handle = attrHandle[ name ];
+			attrHandle[ name ] = ret;
+			ret = getter( elem, name, isXML ) != null ?
+				name.toLowerCase() :
+				null;
+			attrHandle[ name ] = handle;
+		}
+		return ret;
+	};
+});
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i;
+
+jQuery.fn.extend({
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		return this.each(function() {
+			delete this[ jQuery.propFix[ name ] || name ];
+		});
+	}
+});
+
+jQuery.extend({
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// Don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+				ret :
+				( elem[ name ] = value );
+
+		} else {
+			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+				ret :
+				elem[ name ];
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
+					elem.tabIndex :
+					-1;
+			}
+		}
+	}
+});
+
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+			if ( parent && parent.parentNode ) {
+				parent.parentNode.selectedIndex;
+			}
+			return null;
+		}
+	};
+}
+
+jQuery.each([
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+	addClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			proceed = typeof value === "string" && value,
+			i = 0,
+			len = this.length;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call( this, j, this.className ) );
+			});
+		}
+
+		if ( proceed ) {
+			// The disjunction here is for better compressibility (see removeClass)
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					" "
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			proceed = arguments.length === 0 || typeof value === "string" && value,
+			i = 0,
+			len = this.length;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, this.className ) );
+			});
+		}
+		if ( proceed ) {
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					""
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// Only assign if different to avoid unneeded rendering.
+					finalValue = value ? jQuery.trim( cur ) : "";
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// Toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					classNames = value.match( rnotwhite ) || [];
+
+				while ( (className = classNames[ i++ ]) ) {
+					// Check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( type === strundefined || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					data_priv.set( this, "__className__", this.className );
+				}
+
+				// If the element has a class name or if we're passed `false`,
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+});
+
+
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// Handle most common string cases
+					ret.replace(rreturn, "") :
+					// Handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+
+			} else if ( typeof val === "number" ) {
+				val += "";
+
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+					// Support: IE10-11+
+					// option.text throws exceptions (#14686, #14858)
+					jQuery.trim( jQuery.text( elem ) );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// IE6-9 doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
+							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
+						optionSet = true;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	}
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			return elem.getAttribute("value") === null ? "on" : elem.value;
+		};
+	}
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+});
+
+jQuery.fn.extend({
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	}
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+// Support: Android 2.3
+// Workaround failure to string-cast null input
+jQuery.parseJSON = function( data ) {
+	return JSON.parse( data + "" );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml, tmp;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+
+	// Support: IE9
+	try {
+		tmp = new DOMParser();
+		xml = tmp.parseFromString( data, "text/xml" );
+	} catch ( e ) {
+		xml = undefined;
+	}
+
+	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat( "*" ),
+
+	// Document location
+	ajaxLocation = window.location.href,
+
+	// Segment location into parts
+	ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			while ( (dataType = dataTypes[i++]) ) {
+				// Prepend if requested
+				if ( dataType[0] === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+				// Otherwise append
+				} else {
+					(structure[ dataType ] = structure[ dataType ] || []).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		});
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var key, deep,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+	var ct, type, finalDataType, firstDataType,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+		// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s[ "throws" ] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		type: "GET",
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var transport,
+			// URL without anti-cache param
+			cacheURL,
+			// Response headers
+			responseHeadersString,
+			responseHeaders,
+			// timeout handle
+			timeoutTimer,
+			// Cross-domain detection vars
+			parts,
+			// To know if global events are to be dispatched
+			fireGlobals,
+			// Loop variable
+			i,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+				jQuery( callbackContext ) :
+				jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks("once memory"),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( (match = rheaders.exec( responseHeadersString )) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (prefilters might expect it)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
+			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+		fireGlobals = jQuery.event && s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger("ajaxStart");
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// Aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout(function() {
+					jqXHR.abort("timeout");
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("etag");
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+				// Extract error from statusText and normalize for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger("ajaxStop");
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// Shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		});
+	};
+});
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax({
+		url: url,
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	});
+};
+
+
+jQuery.fn.extend({
+	wrapAll: function( html ) {
+		var wrap;
+
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[ 0 ] ) {
+
+			// The elements to wrap the target around
+			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+			if ( this[ 0 ].parentNode ) {
+				wrap.insertBefore( this[ 0 ] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstElementChild ) {
+					elem = elem.firstElementChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function( i ) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	}
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
+};
+jQuery.expr.filters.visible = function( elem ) {
+	return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function() {
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		})
+		.filter(function() {
+			var type = this.type;
+
+			// Use .is( ":disabled" ) so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		})
+		.map(function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+
+jQuery.ajaxSettings.xhr = function() {
+	try {
+		return new XMLHttpRequest();
+	} catch( e ) {}
+};
+
+var xhrId = 0,
+	xhrCallbacks = {},
+	xhrSuccessStatus = {
+		// file protocol always yields status code 0, assume 200
+		0: 200,
+		// Support: IE9
+		// #1450: sometimes IE returns 1223 when it should be 204
+		1223: 204
+	},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE9
+// Open requests must be manually aborted on unload (#5280)
+// See https://support.microsoft.com/kb/2856746 for more info
+if ( window.attachEvent ) {
+	window.attachEvent( "onunload", function() {
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]();
+		}
+	});
+}
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport(function( options ) {
+	var callback;
+
+	// Cross domain only allowed if supported through XMLHttpRequest
+	if ( support.cors || xhrSupported && !options.crossDomain ) {
+		return {
+			send: function( headers, complete ) {
+				var i,
+					xhr = options.xhr(),
+					id = ++xhrId;
+
+				xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+				// Apply custom fields if provided
+				if ( options.xhrFields ) {
+					for ( i in options.xhrFields ) {
+						xhr[ i ] = options.xhrFields[ i ];
+					}
+				}
+
+				// Override mime type if needed
+				if ( options.mimeType && xhr.overrideMimeType ) {
+					xhr.overrideMimeType( options.mimeType );
+				}
+
+				// X-Requested-With header
+				// For cross-domain requests, seeing as conditions for a preflight are
+				// akin to a jigsaw puzzle, we simply never set it to be sure.
+				// (it can always be set on a per-request basis or even using ajaxSetup)
+				// For same-domain requests, won't change header if already provided.
+				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+					headers["X-Requested-With"] = "XMLHttpRequest";
+				}
+
+				// Set headers
+				for ( i in headers ) {
+					xhr.setRequestHeader( i, headers[ i ] );
+				}
+
+				// Callback
+				callback = function( type ) {
+					return function() {
+						if ( callback ) {
+							delete xhrCallbacks[ id ];
+							callback = xhr.onload = xhr.onerror = null;
+
+							if ( type === "abort" ) {
+								xhr.abort();
+							} else if ( type === "error" ) {
+								complete(
+									// file: protocol always yields status 0; see #8605, #14207
+									xhr.status,
+									xhr.statusText
+								);
+							} else {
+								complete(
+									xhrSuccessStatus[ xhr.status ] || xhr.status,
+									xhr.statusText,
+									// Support: IE9
+									// Accessing binary-data responseText throws an exception
+									// (#11426)
+									typeof xhr.responseText === "string" ? {
+										text: xhr.responseText
+									} : undefined,
+									xhr.getAllResponseHeaders()
+								);
+							}
+						}
+					};
+				};
+
+				// Listen to events
+				xhr.onload = callback();
+				xhr.onerror = callback("error");
+
+				// Create the abort callback
+				callback = xhrCallbacks[ id ] = callback("abort");
+
+				try {
+					// Do send the request (this may raise an exception)
+					xhr.send( options.hasContent && options.data || null );
+				} catch ( e ) {
+					// #14683: Only rethrow if this hasn't been notified as an error yet
+					if ( callback ) {
+						throw e;
+					}
+				}
+			},
+
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /(?:java|ecma)script/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+		var script, callback;
+		return {
+			send: function( _, complete ) {
+				script = jQuery("<script>").prop({
+					async: true,
+					charset: s.scriptCharset,
+					src: s.url
+				}).on(
+					"load error",
+					callback = function( evt ) {
+						script.remove();
+						callback = null;
+						if ( evt ) {
+							complete( evt.type === "error" ? 404 : 200, evt.type );
+						}
+					}
+				);
+				document.head.appendChild( script[ 0 ] );
+			},
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[1] ) ];
+	}
+
+	parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, type, response,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = jQuery.trim( url.slice( off ) );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax({
+			url: url,
+
+			// if "type" variable is undefined, then "GET" method will be used
+			type: type,
+			dataType: "html",
+			data: params
+		}).done(function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		}).complete( callback && function( jqXHR, status ) {
+			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+		});
+	}
+
+	return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+});
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep(jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	}).length;
+};
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// Set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
+
+		// Need to be able to calculate position if either
+		// top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend({
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each(function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				});
+		}
+
+		var docElem, win,
+			elem = this[ 0 ],
+			box = { top: 0, left: 0 },
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		// Support: BlackBerry 5, iOS 3 (original iPhone)
+		// If we don't have gBCR, just use 0,0 rather than error
+		if ( typeof elem.getBoundingClientRect !== strundefined ) {
+			box = elem.getBoundingClientRect();
+		}
+		win = getWindow( doc );
+		return {
+			top: box.top + win.pageYOffset - docElem.clientTop,
+			left: box.left + win.pageXOffset - docElem.clientLeft
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			elem = this[ 0 ],
+			parentOffset = { top: 0, left: 0 };
+
+		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+			// Assume getBoundingClientRect is there when computed position is fixed
+			offset = elem.getBoundingClientRect();
+
+		} else {
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		return {
+			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || docElem;
+
+			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+
+			return offsetParent || docElem;
+		});
+	}
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = "pageYOffset" === prop;
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? win[ prop ] : elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : window.pageXOffset,
+					top ? val : window.pageYOffset
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+// Support: Safari<7+, Chrome<37+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+				// If curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// Margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+					// whichever is greatest
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+	return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	});
+}
+
+
+
+
+var
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.js
new file mode 100755
index 0000000..c4c1d98
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.js
@@ -0,0 +1,6450 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+/* global $:true */
+/* global WebKitCSSMatrix:true */
+
+(function($) {
+  "use strict";
+
+  $.fn.transitionEnd = function(callback) {
+    var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
+      i, dom = this;
+
+    function fireCallBack(e) {
+      /*jshint validthis:true */
+      if (e.target !== this) return;
+      callback.call(this, e);
+      for (i = 0; i < events.length; i++) {
+        dom.off(events[i], fireCallBack);
+      }
+    }
+    if (callback) {
+      for (i = 0; i < events.length; i++) {
+        dom.on(events[i], fireCallBack);
+      }
+    }
+    return this;
+  };
+
+  $.support = (function() {
+    var support = {
+      touch: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch)
+    };
+    return support;
+  })();
+
+  $.touchEvents = {
+    start: $.support.touch ? 'touchstart' : 'mousedown',
+    move: $.support.touch ? 'touchmove' : 'mousemove',
+    end: $.support.touch ? 'touchend' : 'mouseup'
+  };
+
+  $.getTouchPosition = function(e) {
+    e = e.originalEvent || e; //jquery wrap the originevent
+    if(e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend') {
+      return {
+        x: e.targetTouches[0].pageX,
+        y: e.targetTouches[0].pageY
+      };
+    } else {
+      return {
+        x: e.pageX,
+        y: e.pageY
+      };
+    }
+  };
+
+  $.fn.scrollHeight = function() {
+    return this[0].scrollHeight;
+  };
+
+  $.fn.transform = function(transform) {
+    for (var i = 0; i < this.length; i++) {
+      var elStyle = this[i].style;
+      elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
+    }
+    return this;
+  };
+  $.fn.transition = function(duration) {
+    if (typeof duration !== 'string') {
+      duration = duration + 'ms';
+    }
+    for (var i = 0; i < this.length; i++) {
+      var elStyle = this[i].style;
+      elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
+    }
+    return this;
+  };
+
+  $.getTranslate = function (el, axis) {
+    var matrix, curTransform, curStyle, transformMatrix;
+
+    // automatic axis detection
+    if (typeof axis === 'undefined') {
+      axis = 'x';
+    }
+
+    curStyle = window.getComputedStyle(el, null);
+    if (window.WebKitCSSMatrix) {
+      // Some old versions of Webkit choke when 'none' is passed; pass
+      // empty string instead in this case
+      transformMatrix = new WebKitCSSMatrix(curStyle.webkitTransform === 'none' ? '' : curStyle.webkitTransform);
+    }
+    else {
+      transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
+      matrix = transformMatrix.toString().split(',');
+    }
+
+    if (axis === 'x') {
+      //Latest Chrome and webkits Fix
+      if (window.WebKitCSSMatrix)
+        curTransform = transformMatrix.m41;
+      //Crazy IE10 Matrix
+      else if (matrix.length === 16)
+        curTransform = parseFloat(matrix[12]);
+      //Normal Browsers
+      else
+        curTransform = parseFloat(matrix[4]);
+    }
+    if (axis === 'y') {
+      //Latest Chrome and webkits Fix
+      if (window.WebKitCSSMatrix)
+        curTransform = transformMatrix.m42;
+      //Crazy IE10 Matrix
+      else if (matrix.length === 16)
+        curTransform = parseFloat(matrix[13]);
+      //Normal Browsers
+      else
+        curTransform = parseFloat(matrix[5]);
+    }
+
+    return curTransform || 0;
+  };
+  $.requestAnimationFrame = function (callback) {
+    if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
+    else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
+    else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
+    else {
+      return window.setTimeout(callback, 1000 / 60);
+    }
+  };
+
+  $.cancelAnimationFrame = function (id) {
+    if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
+    else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
+    else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
+    else {
+      return window.clearTimeout(id);
+    }  
+  };
+
+  $.fn.join = function(arg) {
+    return this.toArray().join(arg);
+  }
+})($);
+
+/*===========================
+  Template7 Template engine
+  ===========================*/
+/* global $:true */
+/* jshint unused:false */
+/* jshint forin:false */
++function ($) {
+  "use strict";
+  $.Template7 = $.t7 = (function () {
+    function isArray(arr) {
+      return Object.prototype.toString.apply(arr) === '[object Array]';
+    }
+    function isObject(obj) {
+      return obj instanceof Object;
+    }
+    function isFunction(func) {
+      return typeof func === 'function';
+    }
+    var cache = {};
+    function helperToSlices(string) {
+      var helperParts = string.replace(/[{}#}]/g, '').split(' ');
+      var slices = [];
+      var shiftIndex, i, j;
+      for (i = 0; i < helperParts.length; i++) {
+        var part = helperParts[i];
+        if (i === 0) slices.push(part);
+        else {
+          if (part.indexOf('"') === 0) {
+            // Plain String
+            if (part.match(/"/g).length === 2) {
+              // One word string
+              slices.push(part);
+            }
+            else {
+              // Find closed Index
+              shiftIndex = 0;
+              for (j = i + 1; j < helperParts.length; j++) {
+                part += ' ' + helperParts[j];
+                if (helperParts[j].indexOf('"') >= 0) {
+                  shiftIndex = j;
+                  slices.push(part);
+                  break;
+                }
+              }
+              if (shiftIndex) i = shiftIndex;
+            }
+          }
+          else {
+            if (part.indexOf('=') > 0) {
+              // Hash
+              var hashParts = part.split('=');
+              var hashName = hashParts[0];
+              var hashContent = hashParts[1];
+              if (hashContent.match(/"/g).length !== 2) {
+                shiftIndex = 0;
+                for (j = i + 1; j < helperParts.length; j++) {
+                  hashContent += ' ' + helperParts[j];
+                  if (helperParts[j].indexOf('"') >= 0) {
+                    shiftIndex = j;
+                    break;
+                  }
+                }
+                if (shiftIndex) i = shiftIndex;
+              }
+              var hash = [hashName, hashContent.replace(/"/g,'')];
+              slices.push(hash);
+            }
+            else {
+              // Plain variable
+              slices.push(part);
+            }
+          }
+        }
+      }
+      return slices;
+    }
+    function stringToBlocks(string) {
+      var blocks = [], i, j, k;
+      if (!string) return [];
+      var _blocks = string.split(/({{[^{^}]*}})/);
+      for (i = 0; i < _blocks.length; i++) {
+        var block = _blocks[i];
+        if (block === '') continue;
+        if (block.indexOf('{{') < 0) {
+          blocks.push({
+            type: 'plain',
+            content: block
+          });
+        }
+        else {
+          if (block.indexOf('{/') >= 0) {
+            continue;
+          }
+          if (block.indexOf('{#') < 0 && block.indexOf(' ') < 0 && block.indexOf('else') < 0) {
+            // Simple variable
+            blocks.push({
+              type: 'variable',
+              contextName: block.replace(/[{}]/g, '')
+            });
+            continue;
+          }
+          // Helpers
+          var helperSlices = helperToSlices(block);
+          var helperName = helperSlices[0];
+          var helperContext = [];
+          var helperHash = {};
+          for (j = 1; j < helperSlices.length; j++) {
+            var slice = helperSlices[j];
+            if (isArray(slice)) {
+              // Hash
+              helperHash[slice[0]] = slice[1] === 'false' ? false : slice[1];
+            }
+            else {
+              helperContext.push(slice);
+            }
+          }
+
+          if (block.indexOf('{#') >= 0) {
+            // Condition/Helper
+            var helperStartIndex = i;
+            var helperContent = '';
+            var elseContent = '';
+            var toSkip = 0;
+            var shiftIndex;
+            var foundClosed = false, foundElse = false, foundClosedElse = false, depth = 0;
+            for (j = i + 1; j < _blocks.length; j++) {
+              if (_blocks[j].indexOf('{{#') >= 0) {
+                depth ++;
+              }
+              if (_blocks[j].indexOf('{{/') >= 0) {
+                depth --;
+              }
+              if (_blocks[j].indexOf('{{#' + helperName) >= 0) {
+                helperContent += _blocks[j];
+                if (foundElse) elseContent += _blocks[j];
+                toSkip ++;
+              }
+              else if (_blocks[j].indexOf('{{/' + helperName) >= 0) {
+                if (toSkip > 0) {
+                  toSkip--;
+                  helperContent += _blocks[j];
+                  if (foundElse) elseContent += _blocks[j];
+                }
+                else {
+                  shiftIndex = j;
+                  foundClosed = true;
+                  break;
+                }
+              }
+              else if (_blocks[j].indexOf('else') >= 0 && depth === 0) {
+                foundElse = true;
+              }
+              else {
+                if (!foundElse) helperContent += _blocks[j];
+                if (foundElse) elseContent += _blocks[j];
+              }
+
+            }
+            if (foundClosed) {
+              if (shiftIndex) i = shiftIndex;
+              blocks.push({
+                type: 'helper',
+                helperName: helperName,
+                contextName: helperContext,
+                content: helperContent,
+                inverseContent: elseContent,
+                hash: helperHash
+              });
+            }
+          }
+          else if (block.indexOf(' ') > 0) {
+            blocks.push({
+              type: 'helper',
+              helperName: helperName,
+              contextName: helperContext,
+              hash: helperHash
+            });
+          }
+        }
+      }
+      return blocks;
+    }
+    var Template7 = function (template) {
+      var t = this;
+      t.template = template;
+
+      function getCompileFn(block, depth) {
+        if (block.content) return compile(block.content, depth);
+        else return function () {return ''; };
+      }
+      function getCompileInverse(block, depth) {
+        if (block.inverseContent) return compile(block.inverseContent, depth);
+        else return function () {return ''; };
+      }
+      function getCompileVar(name, ctx) {
+        var variable, parts, levelsUp = 0, initialCtx = ctx;
+        if (name.indexOf('../') === 0) {
+          levelsUp = name.split('../').length - 1;
+          var newDepth = ctx.split('_')[1] - levelsUp;
+          ctx = 'ctx_' + (newDepth >= 1 ? newDepth : 1);
+          parts = name.split('../')[levelsUp].split('.');
+        }
+        else if (name.indexOf('@global') === 0) {
+          ctx = '$.Template7.global';
+          parts = name.split('@global.')[1].split('.');
+        }
+        else if (name.indexOf('@root') === 0) {
+          ctx = 'ctx_1';
+          parts = name.split('@root.')[1].split('.');
+        }
+        else {
+          parts = name.split('.');
+        }
+        variable = ctx;
+        for (var i = 0; i < parts.length; i++) {
+          var part = parts[i];
+          if (part.indexOf('@') === 0) {
+            if (i > 0) {
+              variable += '[(data && data.' + part.replace('@', '') + ')]';
+            }
+            else {
+              variable = '(data && data.' + name.replace('@', '') + ')';
+            }
+          }
+          else {
+            if (isFinite(part)) {
+              variable += '[' + part + ']';
+            }
+            else {
+              if (part.indexOf('this') === 0) {
+                variable = part.replace('this', ctx);
+              }
+              else {
+                variable += '.' + part;       
+              }
+            }
+          }
+        }
+
+        return variable;
+      }
+      function getCompiledArguments(contextArray, ctx) {
+        var arr = [];
+        for (var i = 0; i < contextArray.length; i++) {
+          if (contextArray[i].indexOf('"') === 0) arr.push(contextArray[i]);
+          else {
+            arr.push(getCompileVar(contextArray[i], ctx));
+          }
+        }
+        return arr.join(', ');
+      }
+      function compile(template, depth) {
+        depth = depth || 1;
+        template = template || t.template;
+        if (typeof template !== 'string') {
+          throw new Error('Template7: Template must be a string');
+        }
+        var blocks = stringToBlocks(template);
+        if (blocks.length === 0) {
+          return function () { return ''; };
+        }
+        var ctx = 'ctx_' + depth;
+        var resultString = '(function (' + ctx + ', data) {\n';
+        if (depth === 1) {
+          resultString += 'function isArray(arr){return Object.prototype.toString.apply(arr) === \'[object Array]\';}\n';
+          resultString += 'function isFunction(func){return (typeof func === \'function\');}\n';
+          resultString += 'function c(val, ctx) {if (typeof val !== "undefined") {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n';
+        }
+        resultString += 'var r = \'\';\n';
+        var i, j, context;
+        for (i = 0; i < blocks.length; i++) {
+          var block = blocks[i];
+          // Plain block
+          if (block.type === 'plain') {
+            resultString += 'r +=\'' + (block.content).replace(/\r/g, '\\r').replace(/\n/g, '\\n').replace(/'/g, '\\' + '\'') + '\';';
+            continue;
+          }
+          var variable, compiledArguments;
+          // Variable block
+          if (block.type === 'variable') {
+            variable = getCompileVar(block.contextName, ctx);
+            resultString += 'r += c(' + variable + ', ' + ctx + ');';
+          }
+          // Helpers block
+          if (block.type === 'helper') {
+            if (block.helperName in t.helpers) {
+              compiledArguments = getCompiledArguments(block.contextName, ctx);
+              resultString += 'r += ($.Template7.helpers.' + block.helperName + ').call(' + ctx + ', ' + (compiledArguments && (compiledArguments + ', ')) +'{hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+            }
+            else {
+              if (block.contextName.length > 0) {
+                throw new Error('Template7: Missing helper: "' + block.helperName + '"');
+              }
+              else {
+                variable = getCompileVar(block.helperName, ctx);
+                resultString += 'if (' + variable + ') {';
+                resultString += 'if (isArray(' + variable + ')) {';
+                resultString += 'r += ($.Template7.helpers.each).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+                resultString += '}else {';
+                resultString += 'r += ($.Template7.helpers.with).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: ctx_1});';
+                resultString += '}}';
+              }
+            }
+          }
+        }
+        resultString += '\nreturn r;})';
+        return eval.call(window, resultString);
+      }
+      t.compile = function (template) {
+        if (!t.compiled) {
+          t.compiled = compile(template);
+        }
+        return t.compiled;
+      };
+    };
+    Template7.prototype = {
+      options: {},
+      helpers: {
+        'if': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          if (context) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);
+          }
+        },
+        'unless': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          if (!context) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);
+          }
+        },
+        'each': function (context, options) {
+          var ret = '', i = 0;
+          if (isFunction(context)) { context = context.call(this); }
+          if (isArray(context)) {
+            if (options.hash.reverse) {
+              context = context.reverse();
+            }
+            for (i = 0; i < context.length; i++) {
+              ret += options.fn(context[i], {first: i === 0, last: i === context.length - 1, index: i});
+            }
+            if (options.hash.reverse) {
+              context = context.reverse();
+            }
+          }
+          else {
+            for (var key in context) {
+              i++;
+              ret += options.fn(context[key], {key: key});
+            }
+          }
+          if (i > 0) return ret;
+          else return options.inverse(this);
+        },
+        'with': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          return options.fn(context);
+        },
+        'join': function (context, options) {
+          if (isFunction(context)) { context = context.call(this); }
+          return context.join(options.hash.delimiter || options.hash.delimeter);
+        },
+        'js': function (expression, options) {
+          var func;
+          if (expression.indexOf('return')>=0) {
+            func = '(function(){'+expression+'})';
+          }
+          else {
+            func = '(function(){return ('+expression+')})';
+          }
+          return eval.call(this, func).call(this);
+        },
+        'js_compare': function (expression, options) {
+          var func;
+          if (expression.indexOf('return')>=0) {
+            func = '(function(){'+expression+'})';
+          }
+          else {
+            func = '(function(){return ('+expression+')})';
+          }
+          var condition = eval.call(this, func).call(this);
+          if (condition) {
+            return options.fn(this, options.data);
+          }
+          else {
+            return options.inverse(this, options.data);   
+          }
+        }
+      }
+    };
+    var t7 = function (template, data) {
+      if (arguments.length === 2) {
+        var instance = new Template7(template);
+        var rendered = instance.compile()(data);
+        instance = null;
+        return (rendered);
+      }
+      else return new Template7(template);
+    };
+    t7.registerHelper = function (name, fn) {
+      Template7.prototype.helpers[name] = fn;
+    };
+    t7.unregisterHelper = function (name) {
+      Template7.prototype.helpers[name] = undefined;  
+      delete Template7.prototype.helpers[name];
+    };
+
+    t7.compile = function (template, options) {
+      var instance = new Template7(template, options);
+      return instance.compile();
+    };
+
+    t7.options = Template7.prototype.options;
+    t7.helpers = Template7.prototype.helpers;
+    return t7;
+  })();
+}($);
+
+/*! Hammer.JS - v2.0.8 - 2016-04-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the MIT license */
+(function(window, document, exportName, undefined) {
+  'use strict';
+
+var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
+var TEST_ELEMENT = document.createElement('div');
+
+var TYPE_FUNCTION = 'function';
+
+var round = Math.round;
+var abs = Math.abs;
+var now = Date.now;
+
+/**
+ * set a timeout with a given scope
+ * @param {Function} fn
+ * @param {Number} timeout
+ * @param {Object} context
+ * @returns {number}
+ */
+function setTimeoutContext(fn, timeout, context) {
+    return setTimeout(bindFn(fn, context), timeout);
+}
+
+/**
+ * if the argument is an array, we want to execute the fn on each entry
+ * if it aint an array we don't want to do a thing.
+ * this is used by all the methods that accept a single and array argument.
+ * @param {*|Array} arg
+ * @param {String} fn
+ * @param {Object} [context]
+ * @returns {Boolean}
+ */
+function invokeArrayArg(arg, fn, context) {
+    if (Array.isArray(arg)) {
+        each(arg, context[fn], context);
+        return true;
+    }
+    return false;
+}
+
+/**
+ * walk objects and arrays
+ * @param {Object} obj
+ * @param {Function} iterator
+ * @param {Object} context
+ */
+function each(obj, iterator, context) {
+    var i;
+
+    if (!obj) {
+        return;
+    }
+
+    if (obj.forEach) {
+        obj.forEach(iterator, context);
+    } else if (obj.length !== undefined) {
+        i = 0;
+        while (i < obj.length) {
+            iterator.call(context, obj[i], i, obj);
+            i++;
+        }
+    } else {
+        for (i in obj) {
+            obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
+        }
+    }
+}
+
+/**
+ * wrap a method with a deprecation warning and stack trace
+ * @param {Function} method
+ * @param {String} name
+ * @param {String} message
+ * @returns {Function} A new function wrapping the supplied method.
+ */
+function deprecate(method, name, message) {
+    var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
+    return function() {
+        var e = new Error('get-stack-trace');
+        var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
+            .replace(/^\s+at\s+/gm, '')
+            .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
+
+        var log = window.console && (window.console.warn || window.console.log);
+        if (log) {
+            log.call(window.console, deprecationMessage, stack);
+        }
+        return method.apply(this, arguments);
+    };
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} target
+ * @param {...Object} objects_to_assign
+ * @returns {Object} target
+ */
+var assign;
+if (typeof Object.assign !== 'function') {
+    assign = function assign(target) {
+        if (target === undefined || target === null) {
+            throw new TypeError('Cannot convert undefined or null to object');
+        }
+
+        var output = Object(target);
+        for (var index = 1; index < arguments.length; index++) {
+            var source = arguments[index];
+            if (source !== undefined && source !== null) {
+                for (var nextKey in source) {
+                    if (source.hasOwnProperty(nextKey)) {
+                        output[nextKey] = source[nextKey];
+                    }
+                }
+            }
+        }
+        return output;
+    };
+} else {
+    assign = Object.assign;
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} dest
+ * @param {Object} src
+ * @param {Boolean} [merge=false]
+ * @returns {Object} dest
+ */
+var extend = deprecate(function extend(dest, src, merge) {
+    var keys = Object.keys(src);
+    var i = 0;
+    while (i < keys.length) {
+        if (!merge || (merge && dest[keys[i]] === undefined)) {
+            dest[keys[i]] = src[keys[i]];
+        }
+        i++;
+    }
+    return dest;
+}, 'extend', 'Use `assign`.');
+
+/**
+ * merge the values from src in the dest.
+ * means that properties that exist in dest will not be overwritten by src
+ * @param {Object} dest
+ * @param {Object} src
+ * @returns {Object} dest
+ */
+var merge = deprecate(function merge(dest, src) {
+    return extend(dest, src, true);
+}, 'merge', 'Use `assign`.');
+
+/**
+ * simple class inheritance
+ * @param {Function} child
+ * @param {Function} base
+ * @param {Object} [properties]
+ */
+function inherit(child, base, properties) {
+    var baseP = base.prototype,
+        childP;
+
+    childP = child.prototype = Object.create(baseP);
+    childP.constructor = child;
+    childP._super = baseP;
+
+    if (properties) {
+        assign(childP, properties);
+    }
+}
+
+/**
+ * simple function bind
+ * @param {Function} fn
+ * @param {Object} context
+ * @returns {Function}
+ */
+function bindFn(fn, context) {
+    return function boundFn() {
+        return fn.apply(context, arguments);
+    };
+}
+
+/**
+ * let a boolean value also be a function that must return a boolean
+ * this first item in args will be used as the context
+ * @param {Boolean|Function} val
+ * @param {Array} [args]
+ * @returns {Boolean}
+ */
+function boolOrFn(val, args) {
+    if (typeof val == TYPE_FUNCTION) {
+        return val.apply(args ? args[0] || undefined : undefined, args);
+    }
+    return val;
+}
+
+/**
+ * use the val2 when val1 is undefined
+ * @param {*} val1
+ * @param {*} val2
+ * @returns {*}
+ */
+function ifUndefined(val1, val2) {
+    return (val1 === undefined) ? val2 : val1;
+}
+
+/**
+ * addEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function addEventListeners(target, types, handler) {
+    each(splitStr(types), function(type) {
+        target.addEventListener(type, handler, false);
+    });
+}
+
+/**
+ * removeEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function removeEventListeners(target, types, handler) {
+    each(splitStr(types), function(type) {
+        target.removeEventListener(type, handler, false);
+    });
+}
+
+/**
+ * find if a node is in the given parent
+ * @method hasParent
+ * @param {HTMLElement} node
+ * @param {HTMLElement} parent
+ * @return {Boolean} found
+ */
+function hasParent(node, parent) {
+    while (node) {
+        if (node == parent) {
+            return true;
+        }
+        node = node.parentNode;
+    }
+    return false;
+}
+
+/**
+ * small indexOf wrapper
+ * @param {String} str
+ * @param {String} find
+ * @returns {Boolean} found
+ */
+function inStr(str, find) {
+    return str.indexOf(find) > -1;
+}
+
+/**
+ * split string on whitespace
+ * @param {String} str
+ * @returns {Array} words
+ */
+function splitStr(str) {
+    return str.trim().split(/\s+/g);
+}
+
+/**
+ * find if a array contains the object using indexOf or a simple polyFill
+ * @param {Array} src
+ * @param {String} find
+ * @param {String} [findByKey]
+ * @return {Boolean|Number} false when not found, or the index
+ */
+function inArray(src, find, findByKey) {
+    if (src.indexOf && !findByKey) {
+        return src.indexOf(find);
+    } else {
+        var i = 0;
+        while (i < src.length) {
+            if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
+                return i;
+            }
+            i++;
+        }
+        return -1;
+    }
+}
+
+/**
+ * convert array-like objects to real arrays
+ * @param {Object} obj
+ * @returns {Array}
+ */
+function toArray(obj) {
+    return Array.prototype.slice.call(obj, 0);
+}
+
+/**
+ * unique array with objects based on a key (like 'id') or just by the array's value
+ * @param {Array} src [{id:1},{id:2},{id:1}]
+ * @param {String} [key]
+ * @param {Boolean} [sort=False]
+ * @returns {Array} [{id:1},{id:2}]
+ */
+function uniqueArray(src, key, sort) {
+    var results = [];
+    var values = [];
+    var i = 0;
+
+    while (i < src.length) {
+        var val = key ? src[i][key] : src[i];
+        if (inArray(values, val) < 0) {
+            results.push(src[i]);
+        }
+        values[i] = val;
+        i++;
+    }
+
+    if (sort) {
+        if (!key) {
+            results = results.sort();
+        } else {
+            results = results.sort(function sortUniqueArray(a, b) {
+                return a[key] > b[key];
+            });
+        }
+    }
+
+    return results;
+}
+
+/**
+ * get the prefixed property
+ * @param {Object} obj
+ * @param {String} property
+ * @returns {String|Undefined} prefixed
+ */
+function prefixed(obj, property) {
+    var prefix, prop;
+    var camelProp = property[0].toUpperCase() + property.slice(1);
+
+    var i = 0;
+    while (i < VENDOR_PREFIXES.length) {
+        prefix = VENDOR_PREFIXES[i];
+        prop = (prefix) ? prefix + camelProp : property;
+
+        if (prop in obj) {
+            return prop;
+        }
+        i++;
+    }
+    return undefined;
+}
+
+/**
+ * get a unique id
+ * @returns {number} uniqueId
+ */
+var _uniqueId = 1;
+function uniqueId() {
+    return _uniqueId++;
+}
+
+/**
+ * get the window object of an element
+ * @param {HTMLElement} element
+ * @returns {DocumentView|Window}
+ */
+function getWindowForElement(element) {
+    var doc = element.ownerDocument || element;
+    return (doc.defaultView || doc.parentWindow || window);
+}
+
+var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
+
+var SUPPORT_TOUCH = ('ontouchstart' in window);
+var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
+var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
+
+var INPUT_TYPE_TOUCH = 'touch';
+var INPUT_TYPE_PEN = 'pen';
+var INPUT_TYPE_MOUSE = 'mouse';
+var INPUT_TYPE_KINECT = 'kinect';
+
+var COMPUTE_INTERVAL = 25;
+
+var INPUT_START = 1;
+var INPUT_MOVE = 2;
+var INPUT_END = 4;
+var INPUT_CANCEL = 8;
+
+var DIRECTION_NONE = 1;
+var DIRECTION_LEFT = 2;
+var DIRECTION_RIGHT = 4;
+var DIRECTION_UP = 8;
+var DIRECTION_DOWN = 16;
+
+var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
+var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
+var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
+
+var PROPS_XY = ['x', 'y'];
+var PROPS_CLIENT_XY = ['clientX', 'clientY'];
+
+/**
+ * create new input type manager
+ * @param {Manager} manager
+ * @param {Function} callback
+ * @returns {Input}
+ * @constructor
+ */
+function Input(manager, callback) {
+    var self = this;
+    this.manager = manager;
+    this.callback = callback;
+    this.element = manager.element;
+    this.target = manager.options.inputTarget;
+
+    // smaller wrapper around the handler, for the scope and the enabled state of the manager,
+    // so when disabled the input events are completely bypassed.
+    this.domHandler = function(ev) {
+        if (boolOrFn(manager.options.enable, [manager])) {
+            self.handler(ev);
+        }
+    };
+
+    this.init();
+
+}
+
+Input.prototype = {
+    /**
+     * should handle the inputEvent data and trigger the callback
+     * @virtual
+     */
+    handler: function() { },
+
+    /**
+     * bind the events
+     */
+    init: function() {
+        this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
+        this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
+        this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+    },
+
+    /**
+     * unbind the events
+     */
+    destroy: function() {
+        this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
+        this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
+        this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+    }
+};
+
+/**
+ * create new input type manager
+ * called by the Manager constructor
+ * @param {Hammer} manager
+ * @returns {Input}
+ */
+function createInputInstance(manager) {
+    var Type;
+    var inputClass = manager.options.inputClass;
+
+    if (inputClass) {
+        Type = inputClass;
+    } else if (SUPPORT_POINTER_EVENTS) {
+        Type = PointerEventInput;
+    } else if (SUPPORT_ONLY_TOUCH) {
+        Type = TouchInput;
+    } else if (!SUPPORT_TOUCH) {
+        Type = MouseInput;
+    } else {
+        Type = TouchMouseInput;
+    }
+    return new (Type)(manager, inputHandler);
+}
+
+/**
+ * handle input events
+ * @param {Manager} manager
+ * @param {String} eventType
+ * @param {Object} input
+ */
+function inputHandler(manager, eventType, input) {
+    var pointersLen = input.pointers.length;
+    var changedPointersLen = input.changedPointers.length;
+    var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
+    var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
+
+    input.isFirst = !!isFirst;
+    input.isFinal = !!isFinal;
+
+    if (isFirst) {
+        manager.session = {};
+    }
+
+    // source event is the normalized value of the domEvents
+    // like 'touchstart, mouseup, pointerdown'
+    input.eventType = eventType;
+
+    // compute scale, rotation etc
+    computeInputData(manager, input);
+
+    // emit secret event
+    manager.emit('hammer.input', input);
+
+    manager.recognize(input);
+    manager.session.prevInput = input;
+}
+
+/**
+ * extend the data with some usable properties like scale, rotate, velocity etc
+ * @param {Object} manager
+ * @param {Object} input
+ */
+function computeInputData(manager, input) {
+    var session = manager.session;
+    var pointers = input.pointers;
+    var pointersLength = pointers.length;
+
+    // store the first input to calculate the distance and direction
+    if (!session.firstInput) {
+        session.firstInput = simpleCloneInputData(input);
+    }
+
+    // to compute scale and rotation we need to store the multiple touches
+    if (pointersLength > 1 && !session.firstMultiple) {
+        session.firstMultiple = simpleCloneInputData(input);
+    } else if (pointersLength === 1) {
+        session.firstMultiple = false;
+    }
+
+    var firstInput = session.firstInput;
+    var firstMultiple = session.firstMultiple;
+    var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
+
+    var center = input.center = getCenter(pointers);
+    input.timeStamp = now();
+    input.deltaTime = input.timeStamp - firstInput.timeStamp;
+
+    input.angle = getAngle(offsetCenter, center);
+    input.distance = getDistance(offsetCenter, center);
+
+    computeDeltaXY(session, input);
+    input.offsetDirection = getDirection(input.deltaX, input.deltaY);
+
+    var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
+    input.overallVelocityX = overallVelocity.x;
+    input.overallVelocityY = overallVelocity.y;
+    input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
+
+    input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
+    input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
+
+    input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
+        session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
+
+    computeIntervalInputData(session, input);
+
+    // find the correct target
+    var target = manager.element;
+    if (hasParent(input.srcEvent.target, target)) {
+        target = input.srcEvent.target;
+    }
+    input.target = target;
+}
+
+function computeDeltaXY(session, input) {
+    var center = input.center;
+    var offset = session.offsetDelta || {};
+    var prevDelta = session.prevDelta || {};
+    var prevInput = session.prevInput || {};
+
+    if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
+        prevDelta = session.prevDelta = {
+            x: prevInput.deltaX || 0,
+            y: prevInput.deltaY || 0
+        };
+
+        offset = session.offsetDelta = {
+            x: center.x,
+            y: center.y
+        };
+    }
+
+    input.deltaX = prevDelta.x + (center.x - offset.x);
+    input.deltaY = prevDelta.y + (center.y - offset.y);
+}
+
+/**
+ * velocity is calculated every x ms
+ * @param {Object} session
+ * @param {Object} input
+ */
+function computeIntervalInputData(session, input) {
+    var last = session.lastInterval || input,
+        deltaTime = input.timeStamp - last.timeStamp,
+        velocity, velocityX, velocityY, direction;
+
+    if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
+        var deltaX = input.deltaX - last.deltaX;
+        var deltaY = input.deltaY - last.deltaY;
+
+        var v = getVelocity(deltaTime, deltaX, deltaY);
+        velocityX = v.x;
+        velocityY = v.y;
+        velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
+        direction = getDirection(deltaX, deltaY);
+
+        session.lastInterval = input;
+    } else {
+        // use latest velocity info if it doesn't overtake a minimum period
+        velocity = last.velocity;
+        velocityX = last.velocityX;
+        velocityY = last.velocityY;
+        direction = last.direction;
+    }
+
+    input.velocity = velocity;
+    input.velocityX = velocityX;
+    input.velocityY = velocityY;
+    input.direction = direction;
+}
+
+/**
+ * create a simple clone from the input used for storage of firstInput and firstMultiple
+ * @param {Object} input
+ * @returns {Object} clonedInputData
+ */
+function simpleCloneInputData(input) {
+    // make a simple copy of the pointers because we will get a reference if we don't
+    // we only need clientXY for the calculations
+    var pointers = [];
+    var i = 0;
+    while (i < input.pointers.length) {
+        pointers[i] = {
+            clientX: round(input.pointers[i].clientX),
+            clientY: round(input.pointers[i].clientY)
+        };
+        i++;
+    }
+
+    return {
+        timeStamp: now(),
+        pointers: pointers,
+        center: getCenter(pointers),
+        deltaX: input.deltaX,
+        deltaY: input.deltaY
+    };
+}
+
+/**
+ * get the center of all the pointers
+ * @param {Array} pointers
+ * @return {Object} center contains `x` and `y` properties
+ */
+function getCenter(pointers) {
+    var pointersLength = pointers.length;
+
+    // no need to loop when only one touch
+    if (pointersLength === 1) {
+        return {
+            x: round(pointers[0].clientX),
+            y: round(pointers[0].clientY)
+        };
+    }
+
+    var x = 0, y = 0, i = 0;
+    while (i < pointersLength) {
+        x += pointers[i].clientX;
+        y += pointers[i].clientY;
+        i++;
+    }
+
+    return {
+        x: round(x / pointersLength),
+        y: round(y / pointersLength)
+    };
+}
+
+/**
+ * calculate the velocity between two points. unit is in px per ms.
+ * @param {Number} deltaTime
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Object} velocity `x` and `y`
+ */
+function getVelocity(deltaTime, x, y) {
+    return {
+        x: x / deltaTime || 0,
+        y: y / deltaTime || 0
+    };
+}
+
+/**
+ * get the direction between two points
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Number} direction
+ */
+function getDirection(x, y) {
+    if (x === y) {
+        return DIRECTION_NONE;
+    }
+
+    if (abs(x) >= abs(y)) {
+        return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
+    }
+    return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
+}
+
+/**
+ * calculate the absolute distance between two points
+ * @param {Object} p1 {x, y}
+ * @param {Object} p2 {x, y}
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} distance
+ */
+function getDistance(p1, p2, props) {
+    if (!props) {
+        props = PROPS_XY;
+    }
+    var x = p2[props[0]] - p1[props[0]],
+        y = p2[props[1]] - p1[props[1]];
+
+    return Math.sqrt((x * x) + (y * y));
+}
+
+/**
+ * calculate the angle between two coordinates
+ * @param {Object} p1
+ * @param {Object} p2
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} angle
+ */
+function getAngle(p1, p2, props) {
+    if (!props) {
+        props = PROPS_XY;
+    }
+    var x = p2[props[0]] - p1[props[0]],
+        y = p2[props[1]] - p1[props[1]];
+    return Math.atan2(y, x) * 180 / Math.PI;
+}
+
+/**
+ * calculate the rotation degrees between two pointersets
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} rotation
+ */
+function getRotation(start, end) {
+    return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
+}
+
+/**
+ * calculate the scale factor between two pointersets
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} scale
+ */
+function getScale(start, end) {
+    return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
+}
+
+var MOUSE_INPUT_MAP = {
+    mousedown: INPUT_START,
+    mousemove: INPUT_MOVE,
+    mouseup: INPUT_END
+};
+
+var MOUSE_ELEMENT_EVENTS = 'mousedown';
+var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
+
+/**
+ * Mouse events input
+ * @constructor
+ * @extends Input
+ */
+function MouseInput() {
+    this.evEl = MOUSE_ELEMENT_EVENTS;
+    this.evWin = MOUSE_WINDOW_EVENTS;
+
+    this.pressed = false; // mousedown state
+
+    Input.apply(this, arguments);
+}
+
+inherit(MouseInput, Input, {
+    /**
+     * handle mouse events
+     * @param {Object} ev
+     */
+    handler: function MEhandler(ev) {
+        var eventType = MOUSE_INPUT_MAP[ev.type];
+
+        // on start we want to have the left mouse button down
+        if (eventType & INPUT_START && ev.button === 0) {
+            this.pressed = true;
+        }
+
+        if (eventType & INPUT_MOVE && ev.which !== 1) {
+            eventType = INPUT_END;
+        }
+
+        // mouse must be down
+        if (!this.pressed) {
+            return;
+        }
+
+        if (eventType & INPUT_END) {
+            this.pressed = false;
+        }
+
+        this.callback(this.manager, eventType, {
+            pointers: [ev],
+            changedPointers: [ev],
+            pointerType: INPUT_TYPE_MOUSE,
+            srcEvent: ev
+        });
+    }
+});
+
+var POINTER_INPUT_MAP = {
+    pointerdown: INPUT_START,
+    pointermove: INPUT_MOVE,
+    pointerup: INPUT_END,
+    pointercancel: INPUT_CANCEL,
+    pointerout: INPUT_CANCEL
+};
+
+// in IE10 the pointer types is defined as an enum
+var IE10_POINTER_TYPE_ENUM = {
+    2: INPUT_TYPE_TOUCH,
+    3: INPUT_TYPE_PEN,
+    4: INPUT_TYPE_MOUSE,
+    5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
+};
+
+var POINTER_ELEMENT_EVENTS = 'pointerdown';
+var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
+
+// IE10 has prefixed support, and case-sensitive
+if (window.MSPointerEvent && !window.PointerEvent) {
+    POINTER_ELEMENT_EVENTS = 'MSPointerDown';
+    POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
+}
+
+/**
+ * Pointer events input
+ * @constructor
+ * @extends Input
+ */
+function PointerEventInput() {
+    this.evEl = POINTER_ELEMENT_EVENTS;
+    this.evWin = POINTER_WINDOW_EVENTS;
+
+    Input.apply(this, arguments);
+
+    this.store = (this.manager.session.pointerEvents = []);
+}
+
+inherit(PointerEventInput, Input, {
+    /**
+     * handle mouse events
+     * @param {Object} ev
+     */
+    handler: function PEhandler(ev) {
+        var store = this.store;
+        var removePointer = false;
+
+        var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
+        var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
+        var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
+
+        var isTouch = (pointerType == INPUT_TYPE_TOUCH);
+
+        // get index of the event in the store
+        var storeIndex = inArray(store, ev.pointerId, 'pointerId');
+
+        // start and mouse must be down
+        if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
+            if (storeIndex < 0) {
+                store.push(ev);
+                storeIndex = store.length - 1;
+            }
+        } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+            removePointer = true;
+        }
+
+        // it not found, so the pointer hasn't been down (so it's probably a hover)
+        if (storeIndex < 0) {
+            return;
+        }
+
+        // update the event in the store
+        store[storeIndex] = ev;
+
+        this.callback(this.manager, eventType, {
+            pointers: store,
+            changedPointers: [ev],
+            pointerType: pointerType,
+            srcEvent: ev
+        });
+
+        if (removePointer) {
+            // remove from the store
+            store.splice(storeIndex, 1);
+        }
+    }
+});
+
+var SINGLE_TOUCH_INPUT_MAP = {
+    touchstart: INPUT_START,
+    touchmove: INPUT_MOVE,
+    touchend: INPUT_END,
+    touchcancel: INPUT_CANCEL
+};
+
+var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
+var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Touch events input
+ * @constructor
+ * @extends Input
+ */
+function SingleTouchInput() {
+    this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
+    this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
+    this.started = false;
+
+    Input.apply(this, arguments);
+}
+
+inherit(SingleTouchInput, Input, {
+    handler: function TEhandler(ev) {
+        var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
+
+        // should we handle the touch events?
+        if (type === INPUT_START) {
+            this.started = true;
+        }
+
+        if (!this.started) {
+            return;
+        }
+
+        var touches = normalizeSingleTouches.call(this, ev, type);
+
+        // when done, reset the started state
+        if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
+            this.started = false;
+        }
+
+        this.callback(this.manager, type, {
+            pointers: touches[0],
+            changedPointers: touches[1],
+            pointerType: INPUT_TYPE_TOUCH,
+            srcEvent: ev
+        });
+    }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function normalizeSingleTouches(ev, type) {
+    var all = toArray(ev.touches);
+    var changed = toArray(ev.changedTouches);
+
+    if (type & (INPUT_END | INPUT_CANCEL)) {
+        all = uniqueArray(all.concat(changed), 'identifier', true);
+    }
+
+    return [all, changed];
+}
+
+var TOUCH_INPUT_MAP = {
+    touchstart: INPUT_START,
+    touchmove: INPUT_MOVE,
+    touchend: INPUT_END,
+    touchcancel: INPUT_CANCEL
+};
+
+var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Multi-user touch events input
+ * @constructor
+ * @extends Input
+ */
+function TouchInput() {
+    this.evTarget = TOUCH_TARGET_EVENTS;
+    this.targetIds = {};
+
+    Input.apply(this, arguments);
+}
+
+inherit(TouchInput, Input, {
+    handler: function MTEhandler(ev) {
+        var type = TOUCH_INPUT_MAP[ev.type];
+        var touches = getTouches.call(this, ev, type);
+        if (!touches) {
+            return;
+        }
+
+        this.callback(this.manager, type, {
+            pointers: touches[0],
+            changedPointers: touches[1],
+            pointerType: INPUT_TYPE_TOUCH,
+            srcEvent: ev
+        });
+    }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function getTouches(ev, type) {
+    var allTouches = toArray(ev.touches);
+    var targetIds = this.targetIds;
+
+    // when there is only one touch, the process can be simplified
+    if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
+        targetIds[allTouches[0].identifier] = true;
+        return [allTouches, allTouches];
+    }
+
+    var i,
+        targetTouches,
+        changedTouches = toArray(ev.changedTouches),
+        changedTargetTouches = [],
+        target = this.target;
+
+    // get target touches from touches
+    targetTouches = allTouches.filter(function(touch) {
+        return hasParent(touch.target, target);
+    });
+
+    // collect touches
+    if (type === INPUT_START) {
+        i = 0;
+        while (i < targetTouches.length) {
+            targetIds[targetTouches[i].identifier] = true;
+            i++;
+        }
+    }
+
+    // filter changed touches to only contain touches that exist in the collected target ids
+    i = 0;
+    while (i < changedTouches.length) {
+        if (targetIds[changedTouches[i].identifier]) {
+            changedTargetTouches.push(changedTouches[i]);
+        }
+
+        // cleanup removed touches
+        if (type & (INPUT_END | INPUT_CANCEL)) {
+            delete targetIds[changedTouches[i].identifier];
+        }
+        i++;
+    }
+
+    if (!changedTargetTouches.length) {
+        return;
+    }
+
+    return [
+        // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
+        uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
+        changedTargetTouches
+    ];
+}
+
+/**
+ * Combined touch and mouse input
+ *
+ * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
+ * This because touch devices also emit mouse events while doing a touch.
+ *
+ * @constructor
+ * @extends Input
+ */
+
+var DEDUP_TIMEOUT = 2500;
+var DEDUP_DISTANCE = 25;
+
+function TouchMouseInput() {
+    Input.apply(this, arguments);
+
+    var handler = bindFn(this.handler, this);
+    this.touch = new TouchInput(this.manager, handler);
+    this.mouse = new MouseInput(this.manager, handler);
+
+    this.primaryTouch = null;
+    this.lastTouches = [];
+}
+
+inherit(TouchMouseInput, Input, {
+    /**
+     * handle mouse and touch events
+     * @param {Hammer} manager
+     * @param {String} inputEvent
+     * @param {Object} inputData
+     */
+    handler: function TMEhandler(manager, inputEvent, inputData) {
+        var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
+            isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
+
+        if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
+            return;
+        }
+
+        // when we're in a touch event, record touches to  de-dupe synthetic mouse event
+        if (isTouch) {
+            recordTouches.call(this, inputEvent, inputData);
+        } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
+            return;
+        }
+
+        this.callback(manager, inputEvent, inputData);
+    },
+
+    /**
+     * remove the event listeners
+     */
+    destroy: function destroy() {
+        this.touch.destroy();
+        this.mouse.destroy();
+    }
+});
+
+function recordTouches(eventType, eventData) {
+    if (eventType & INPUT_START) {
+        this.primaryTouch = eventData.changedPointers[0].identifier;
+        setLastTouch.call(this, eventData);
+    } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+        setLastTouch.call(this, eventData);
+    }
+}
+
+function setLastTouch(eventData) {
+    var touch = eventData.changedPointers[0];
+
+    if (touch.identifier === this.primaryTouch) {
+        var lastTouch = {x: touch.clientX, y: touch.clientY};
+        this.lastTouches.push(lastTouch);
+        var lts = this.lastTouches;
+        var removeLastTouch = function() {
+            var i = lts.indexOf(lastTouch);
+            if (i > -1) {
+                lts.splice(i, 1);
+            }
+        };
+        setTimeout(removeLastTouch, DEDUP_TIMEOUT);
+    }
+}
+
+function isSyntheticEvent(eventData) {
+    var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
+    for (var i = 0; i < this.lastTouches.length; i++) {
+        var t = this.lastTouches[i];
+        var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
+        if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
+            return true;
+        }
+    }
+    return false;
+}
+
+var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
+var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
+
+// magical touchAction value
+var TOUCH_ACTION_COMPUTE = 'compute';
+var TOUCH_ACTION_AUTO = 'auto';
+var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
+var TOUCH_ACTION_NONE = 'none';
+var TOUCH_ACTION_PAN_X = 'pan-x';
+var TOUCH_ACTION_PAN_Y = 'pan-y';
+var TOUCH_ACTION_MAP = getTouchActionProps();
+
+/**
+ * Touch Action
+ * sets the touchAction property or uses the js alternative
+ * @param {Manager} manager
+ * @param {String} value
+ * @constructor
+ */
+function TouchAction(manager, value) {
+    this.manager = manager;
+    this.set(value);
+}
+
+TouchAction.prototype = {
+    /**
+     * set the touchAction value on the element or enable the polyfill
+     * @param {String} value
+     */
+    set: function(value) {
+        // find out the touch-action by the event handlers
+        if (value == TOUCH_ACTION_COMPUTE) {
+            value = this.compute();
+        }
+
+        if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
+            this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
+        }
+        this.actions = value.toLowerCase().trim();
+    },
+
+    /**
+     * just re-set the touchAction value
+     */
+    update: function() {
+        this.set(this.manager.options.touchAction);
+    },
+
+    /**
+     * compute the value for the touchAction property based on the recognizer's settings
+     * @returns {String} value
+     */
+    compute: function() {
+        var actions = [];
+        each(this.manager.recognizers, function(recognizer) {
+            if (boolOrFn(recognizer.options.enable, [recognizer])) {
+                actions = actions.concat(recognizer.getTouchAction());
+            }
+        });
+        return cleanTouchActions(actions.join(' '));
+    },
+
+    /**
+     * this method is called on each input cycle and provides the preventing of the browser behavior
+     * @param {Object} input
+     */
+    preventDefaults: function(input) {
+        var srcEvent = input.srcEvent;
+        var direction = input.offsetDirection;
+
+        // if the touch action did prevented once this session
+        if (this.manager.session.prevented) {
+            srcEvent.preventDefault();
+            return;
+        }
+
+        var actions = this.actions;
+        var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
+        var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
+        var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
+
+        if (hasNone) {
+            //do not prevent defaults if this is a tap gesture
+
+            var isTapPointer = input.pointers.length === 1;
+            var isTapMovement = input.distance < 2;
+            var isTapTouchTime = input.deltaTime < 250;
+
+            if (isTapPointer && isTapMovement && isTapTouchTime) {
+                return;
+            }
+        }
+
+        if (hasPanX && hasPanY) {
+            // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
+            return;
+        }
+
+        if (hasNone ||
+            (hasPanY && direction & DIRECTION_HORIZONTAL) ||
+            (hasPanX && direction & DIRECTION_VERTICAL)) {
+            return this.preventSrc(srcEvent);
+        }
+    },
+
+    /**
+     * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
+     * @param {Object} srcEvent
+     */
+    preventSrc: function(srcEvent) {
+        this.manager.session.prevented = true;
+        srcEvent.preventDefault();
+    }
+};
+
+/**
+ * when the touchActions are collected they are not a valid value, so we need to clean things up. *
+ * @param {String} actions
+ * @returns {*}
+ */
+function cleanTouchActions(actions) {
+    // none
+    if (inStr(actions, TOUCH_ACTION_NONE)) {
+        return TOUCH_ACTION_NONE;
+    }
+
+    var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
+    var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
+
+    // if both pan-x and pan-y are set (different recognizers
+    // for different directions, e.g. horizontal pan but vertical swipe?)
+    // we need none (as otherwise with pan-x pan-y combined none of these
+    // recognizers will work, since the browser would handle all panning
+    if (hasPanX && hasPanY) {
+        return TOUCH_ACTION_NONE;
+    }
+
+    // pan-x OR pan-y
+    if (hasPanX || hasPanY) {
+        return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
+    }
+
+    // manipulation
+    if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
+        return TOUCH_ACTION_MANIPULATION;
+    }
+
+    return TOUCH_ACTION_AUTO;
+}
+
+function getTouchActionProps() {
+    if (!NATIVE_TOUCH_ACTION) {
+        return false;
+    }
+    var touchMap = {};
+    var cssSupports = window.CSS && window.CSS.supports;
+    ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
+
+        // If css.supports is not supported but there is native touch-action assume it supports
+        // all values. This is the case for IE 10 and 11.
+        touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
+    });
+    return touchMap;
+}
+
+/**
+ * Recognizer flow explained; *
+ * All recognizers have the initial state of POSSIBLE when a input session starts.
+ * The definition of a input session is from the first input until the last input, with all it's movement in it. *
+ * Example session for mouse-input: mousedown -> mousemove -> mouseup
+ *
+ * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
+ * which determines with state it should be.
+ *
+ * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
+ * POSSIBLE to give it another change on the next cycle.
+ *
+ *               Possible
+ *                  |
+ *            +-----+---------------+
+ *            |                     |
+ *      +-----+-----+               |
+ *      |           |               |
+ *   Failed      Cancelled          |
+ *                          +-------+------+
+ *                          |              |
+ *                      Recognized       Began
+ *                                         |
+ *                                      Changed
+ *                                         |
+ *                                  Ended/Recognized
+ */
+var STATE_POSSIBLE = 1;
+var STATE_BEGAN = 2;
+var STATE_CHANGED = 4;
+var STATE_ENDED = 8;
+var STATE_RECOGNIZED = STATE_ENDED;
+var STATE_CANCELLED = 16;
+var STATE_FAILED = 32;
+
+/**
+ * Recognizer
+ * Every recognizer needs to extend from this class.
+ * @constructor
+ * @param {Object} options
+ */
+function Recognizer(options) {
+    this.options = assign({}, this.defaults, options || {});
+
+    this.id = uniqueId();
+
+    this.manager = null;
+
+    // default is enable true
+    this.options.enable = ifUndefined(this.options.enable, true);
+
+    this.state = STATE_POSSIBLE;
+
+    this.simultaneous = {};
+    this.requireFail = [];
+}
+
+Recognizer.prototype = {
+    /**
+     * @virtual
+     * @type {Object}
+     */
+    defaults: {},
+
+    /**
+     * set options
+     * @param {Object} options
+     * @return {Recognizer}
+     */
+    set: function(options) {
+        assign(this.options, options);
+
+        // also update the touchAction, in case something changed about the directions/enabled state
+        this.manager && this.manager.touchAction.update();
+        return this;
+    },
+
+    /**
+     * recognize simultaneous with an other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    recognizeWith: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
+            return this;
+        }
+
+        var simultaneous = this.simultaneous;
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        if (!simultaneous[otherRecognizer.id]) {
+            simultaneous[otherRecognizer.id] = otherRecognizer;
+            otherRecognizer.recognizeWith(this);
+        }
+        return this;
+    },
+
+    /**
+     * drop the simultaneous link. it doesnt remove the link on the other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    dropRecognizeWith: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
+            return this;
+        }
+
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        delete this.simultaneous[otherRecognizer.id];
+        return this;
+    },
+
+    /**
+     * recognizer can only run when an other is failing
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    requireFailure: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
+            return this;
+        }
+
+        var requireFail = this.requireFail;
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        if (inArray(requireFail, otherRecognizer) === -1) {
+            requireFail.push(otherRecognizer);
+            otherRecognizer.requireFailure(this);
+        }
+        return this;
+    },
+
+    /**
+     * drop the requireFailure link. it does not remove the link on the other recognizer.
+     * @param {Recognizer} otherRecognizer
+     * @returns {Recognizer} this
+     */
+    dropRequireFailure: function(otherRecognizer) {
+        if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
+            return this;
+        }
+
+        otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+        var index = inArray(this.requireFail, otherRecognizer);
+        if (index > -1) {
+            this.requireFail.splice(index, 1);
+        }
+        return this;
+    },
+
+    /**
+     * has require failures boolean
+     * @returns {boolean}
+     */
+    hasRequireFailures: function() {
+        return this.requireFail.length > 0;
+    },
+
+    /**
+     * if the recognizer can recognize simultaneous with an other recognizer
+     * @param {Recognizer} otherRecognizer
+     * @returns {Boolean}
+     */
+    canRecognizeWith: function(otherRecognizer) {
+        return !!this.simultaneous[otherRecognizer.id];
+    },
+
+    /**
+     * You should use `tryEmit` instead of `emit` directly to check
+     * that all the needed recognizers has failed before emitting.
+     * @param {Object} input
+     */
+    emit: function(input) {
+        var self = this;
+        var state = this.state;
+
+        function emit(event) {
+            self.manager.emit(event, input);
+        }
+
+        // 'panstart' and 'panmove'
+        if (state < STATE_ENDED) {
+            emit(self.options.event + stateStr(state));
+        }
+
+        emit(self.options.event); // simple 'eventName' events
+
+        if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
+            emit(input.additionalEvent);
+        }
+
+        // panend and pancancel
+        if (state >= STATE_ENDED) {
+            emit(self.options.event + stateStr(state));
+        }
+    },
+
+    /**
+     * Check that all the require failure recognizers has failed,
+     * if true, it emits a gesture event,
+     * otherwise, setup the state to FAILED.
+     * @param {Object} input
+     */
+    tryEmit: function(input) {
+        if (this.canEmit()) {
+            return this.emit(input);
+        }
+        // it's failing anyway
+        this.state = STATE_FAILED;
+    },
+
+    /**
+     * can we emit?
+     * @returns {boolean}
+     */
+    canEmit: function() {
+        var i = 0;
+        while (i < this.requireFail.length) {
+            if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
+                return false;
+            }
+            i++;
+        }
+        return true;
+    },
+
+    /**
+     * update the recognizer
+     * @param {Object} inputData
+     */
+    recognize: function(inputData) {
+        // make a new copy of the inputData
+        // so we can change the inputData without messing up the other recognizers
+        var inputDataClone = assign({}, inputData);
+
+        // is is enabled and allow recognizing?
+        if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
+            this.reset();
+            this.state = STATE_FAILED;
+            return;
+        }
+
+        // reset when we've reached the end
+        if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
+            this.state = STATE_POSSIBLE;
+        }
+
+        this.state = this.process(inputDataClone);
+
+        // the recognizer has recognized a gesture
+        // so trigger an event
+        if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
+            this.tryEmit(inputDataClone);
+        }
+    },
+
+    /**
+     * return the state of the recognizer
+     * the actual recognizing happens in this method
+     * @virtual
+     * @param {Object} inputData
+     * @returns {Const} STATE
+     */
+    process: function(inputData) { }, // jshint ignore:line
+
+    /**
+     * return the preferred touch-action
+     * @virtual
+     * @returns {Array}
+     */
+    getTouchAction: function() { },
+
+    /**
+     * called when the gesture isn't allowed to recognize
+     * like when another is being recognized or it is disabled
+     * @virtual
+     */
+    reset: function() { }
+};
+
+/**
+ * get a usable string, used as event postfix
+ * @param {Const} state
+ * @returns {String} state
+ */
+function stateStr(state) {
+    if (state & STATE_CANCELLED) {
+        return 'cancel';
+    } else if (state & STATE_ENDED) {
+        return 'end';
+    } else if (state & STATE_CHANGED) {
+        return 'move';
+    } else if (state & STATE_BEGAN) {
+        return 'start';
+    }
+    return '';
+}
+
+/**
+ * direction cons to string
+ * @param {Const} direction
+ * @returns {String}
+ */
+function directionStr(direction) {
+    if (direction == DIRECTION_DOWN) {
+        return 'down';
+    } else if (direction == DIRECTION_UP) {
+        return 'up';
+    } else if (direction == DIRECTION_LEFT) {
+        return 'left';
+    } else if (direction == DIRECTION_RIGHT) {
+        return 'right';
+    }
+    return '';
+}
+
+/**
+ * get a recognizer by name if it is bound to a manager
+ * @param {Recognizer|String} otherRecognizer
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer}
+ */
+function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
+    var manager = recognizer.manager;
+    if (manager) {
+        return manager.get(otherRecognizer);
+    }
+    return otherRecognizer;
+}
+
+/**
+ * This recognizer is just used as a base for the simple attribute recognizers.
+ * @constructor
+ * @extends Recognizer
+ */
+function AttrRecognizer() {
+    Recognizer.apply(this, arguments);
+}
+
+inherit(AttrRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof AttrRecognizer
+     */
+    defaults: {
+        /**
+         * @type {Number}
+         * @default 1
+         */
+        pointers: 1
+    },
+
+    /**
+     * Used to check if it the recognizer receives valid input, like input.distance > 10.
+     * @memberof AttrRecognizer
+     * @param {Object} input
+     * @returns {Boolean} recognized
+     */
+    attrTest: function(input) {
+        var optionPointers = this.options.pointers;
+        return optionPointers === 0 || input.pointers.length === optionPointers;
+    },
+
+    /**
+     * Process the input and return the state for the recognizer
+     * @memberof AttrRecognizer
+     * @param {Object} input
+     * @returns {*} State
+     */
+    process: function(input) {
+        var state = this.state;
+        var eventType = input.eventType;
+
+        var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
+        var isValid = this.attrTest(input);
+
+        // on cancel input and we've recognized before, return STATE_CANCELLED
+        if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
+            return state | STATE_CANCELLED;
+        } else if (isRecognized || isValid) {
+            if (eventType & INPUT_END) {
+                return state | STATE_ENDED;
+            } else if (!(state & STATE_BEGAN)) {
+                return STATE_BEGAN;
+            }
+            return state | STATE_CHANGED;
+        }
+        return STATE_FAILED;
+    }
+});
+
+/**
+ * Pan
+ * Recognized when the pointer is down and moved in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PanRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+
+    this.pX = null;
+    this.pY = null;
+}
+
+inherit(PanRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof PanRecognizer
+     */
+    defaults: {
+        event: 'pan',
+        threshold: 10,
+        pointers: 1,
+        direction: DIRECTION_ALL
+    },
+
+    getTouchAction: function() {
+        var direction = this.options.direction;
+        var actions = [];
+        if (direction & DIRECTION_HORIZONTAL) {
+            actions.push(TOUCH_ACTION_PAN_Y);
+        }
+        if (direction & DIRECTION_VERTICAL) {
+            actions.push(TOUCH_ACTION_PAN_X);
+        }
+        return actions;
+    },
+
+    directionTest: function(input) {
+        var options = this.options;
+        var hasMoved = true;
+        var distance = input.distance;
+        var direction = input.direction;
+        var x = input.deltaX;
+        var y = input.deltaY;
+
+        // lock to axis?
+        if (!(direction & options.direction)) {
+            if (options.direction & DIRECTION_HORIZONTAL) {
+                direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
+                hasMoved = x != this.pX;
+                distance = Math.abs(input.deltaX);
+            } else {
+                direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
+                hasMoved = y != this.pY;
+                distance = Math.abs(input.deltaY);
+            }
+        }
+        input.direction = direction;
+        return hasMoved && distance > options.threshold && direction & options.direction;
+    },
+
+    attrTest: function(input) {
+        return AttrRecognizer.prototype.attrTest.call(this, input) &&
+            (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
+    },
+
+    emit: function(input) {
+
+        this.pX = input.deltaX;
+        this.pY = input.deltaY;
+
+        var direction = directionStr(input.direction);
+
+        if (direction) {
+            input.additionalEvent = this.options.event + direction;
+        }
+        this._super.emit.call(this, input);
+    }
+});
+
+/**
+ * Pinch
+ * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PinchRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(PinchRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof PinchRecognizer
+     */
+    defaults: {
+        event: 'pinch',
+        threshold: 0,
+        pointers: 2
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_NONE];
+    },
+
+    attrTest: function(input) {
+        return this._super.attrTest.call(this, input) &&
+            (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
+    },
+
+    emit: function(input) {
+        if (input.scale !== 1) {
+            var inOut = input.scale < 1 ? 'in' : 'out';
+            input.additionalEvent = this.options.event + inOut;
+        }
+        this._super.emit.call(this, input);
+    }
+});
+
+/**
+ * Press
+ * Recognized when the pointer is down for x ms without any movement.
+ * @constructor
+ * @extends Recognizer
+ */
+function PressRecognizer() {
+    Recognizer.apply(this, arguments);
+
+    this._timer = null;
+    this._input = null;
+}
+
+inherit(PressRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof PressRecognizer
+     */
+    defaults: {
+        event: 'press',
+        pointers: 1,
+        time: 251, // minimal time of the pointer to be pressed
+        threshold: 9 // a minimal movement is ok, but keep it low
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_AUTO];
+    },
+
+    process: function(input) {
+        var options = this.options;
+        var validPointers = input.pointers.length === options.pointers;
+        var validMovement = input.distance < options.threshold;
+        var validTime = input.deltaTime > options.time;
+
+        this._input = input;
+
+        // we only allow little movement
+        // and we've reached an end event, so a tap is possible
+        if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
+            this.reset();
+        } else if (input.eventType & INPUT_START) {
+            this.reset();
+            this._timer = setTimeoutContext(function() {
+                this.state = STATE_RECOGNIZED;
+                this.tryEmit();
+            }, options.time, this);
+        } else if (input.eventType & INPUT_END) {
+            return STATE_RECOGNIZED;
+        }
+        return STATE_FAILED;
+    },
+
+    reset: function() {
+        clearTimeout(this._timer);
+    },
+
+    emit: function(input) {
+        if (this.state !== STATE_RECOGNIZED) {
+            return;
+        }
+
+        if (input && (input.eventType & INPUT_END)) {
+            this.manager.emit(this.options.event + 'up', input);
+        } else {
+            this._input.timeStamp = now();
+            this.manager.emit(this.options.event, this._input);
+        }
+    }
+});
+
+/**
+ * Rotate
+ * Recognized when two or more pointer are moving in a circular motion.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function RotateRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(RotateRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof RotateRecognizer
+     */
+    defaults: {
+        event: 'rotate',
+        threshold: 0,
+        pointers: 2
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_NONE];
+    },
+
+    attrTest: function(input) {
+        return this._super.attrTest.call(this, input) &&
+            (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
+    }
+});
+
+/**
+ * Swipe
+ * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function SwipeRecognizer() {
+    AttrRecognizer.apply(this, arguments);
+}
+
+inherit(SwipeRecognizer, AttrRecognizer, {
+    /**
+     * @namespace
+     * @memberof SwipeRecognizer
+     */
+    defaults: {
+        event: 'swipe',
+        threshold: 10,
+        velocity: 0.3,
+        direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
+        pointers: 1
+    },
+
+    getTouchAction: function() {
+        return PanRecognizer.prototype.getTouchAction.call(this);
+    },
+
+    attrTest: function(input) {
+        var direction = this.options.direction;
+        var velocity;
+
+        if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
+            velocity = input.overallVelocity;
+        } else if (direction & DIRECTION_HORIZONTAL) {
+            velocity = input.overallVelocityX;
+        } else if (direction & DIRECTION_VERTICAL) {
+            velocity = input.overallVelocityY;
+        }
+
+        return this._super.attrTest.call(this, input) &&
+            direction & input.offsetDirection &&
+            input.distance > this.options.threshold &&
+            input.maxPointers == this.options.pointers &&
+            abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
+    },
+
+    emit: function(input) {
+        var direction = directionStr(input.offsetDirection);
+        if (direction) {
+            this.manager.emit(this.options.event + direction, input);
+        }
+
+        this.manager.emit(this.options.event, input);
+    }
+});
+
+/**
+ * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
+ * between the given interval and position. The delay option can be used to recognize multi-taps without firing
+ * a single tap.
+ *
+ * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
+ * multi-taps being recognized.
+ * @constructor
+ * @extends Recognizer
+ */
+function TapRecognizer() {
+    Recognizer.apply(this, arguments);
+
+    // previous time and center,
+    // used for tap counting
+    this.pTime = false;
+    this.pCenter = false;
+
+    this._timer = null;
+    this._input = null;
+    this.count = 0;
+}
+
+inherit(TapRecognizer, Recognizer, {
+    /**
+     * @namespace
+     * @memberof PinchRecognizer
+     */
+    defaults: {
+        event: 'tap',
+        pointers: 1,
+        taps: 1,
+        interval: 300, // max time between the multi-tap taps
+        time: 250, // max time of the pointer to be down (like finger on the screen)
+        threshold: 9, // a minimal movement is ok, but keep it low
+        posThreshold: 10 // a multi-tap can be a bit off the initial position
+    },
+
+    getTouchAction: function() {
+        return [TOUCH_ACTION_MANIPULATION];
+    },
+
+    process: function(input) {
+        var options = this.options;
+
+        var validPointers = input.pointers.length === options.pointers;
+        var validMovement = input.distance < options.threshold;
+        var validTouchTime = input.deltaTime < options.time;
+
+        this.reset();
+
+        if ((input.eventType & INPUT_START) && (this.count === 0)) {
+            return this.failTimeout();
+        }
+
+        // we only allow little movement
+        // and we've reached an end event, so a tap is possible
+        if (validMovement && validTouchTime && validPointers) {
+            if (input.eventType != INPUT_END) {
+                return this.failTimeout();
+            }
+
+            var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
+            var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
+
+            this.pTime = input.timeStamp;
+            this.pCenter = input.center;
+
+            if (!validMultiTap || !validInterval) {
+                this.count = 1;
+            } else {
+                this.count += 1;
+            }
+
+            this._input = input;
+
+            // if tap count matches we have recognized it,
+            // else it has began recognizing...
+            var tapCount = this.count % options.taps;
+            if (tapCount === 0) {
+                // no failing requirements, immediately trigger the tap event
+                // or wait as long as the multitap interval to trigger
+                if (!this.hasRequireFailures()) {
+                    return STATE_RECOGNIZED;
+                } else {
+                    this._timer = setTimeoutContext(function() {
+                        this.state = STATE_RECOGNIZED;
+                        this.tryEmit();
+                    }, options.interval, this);
+                    return STATE_BEGAN;
+                }
+            }
+        }
+        return STATE_FAILED;
+    },
+
+    failTimeout: function() {
+        this._timer = setTimeoutContext(function() {
+            this.state = STATE_FAILED;
+        }, this.options.interval, this);
+        return STATE_FAILED;
+    },
+
+    reset: function() {
+        clearTimeout(this._timer);
+    },
+
+    emit: function() {
+        if (this.state == STATE_RECOGNIZED) {
+            this._input.tapCount = this.count;
+            this.manager.emit(this.options.event, this._input);
+        }
+    }
+});
+
+/**
+ * Simple way to create a manager with a default set of recognizers.
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Hammer(element, options) {
+    options = options || {};
+    options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
+    return new Manager(element, options);
+}
+
+/**
+ * @const {string}
+ */
+Hammer.VERSION = '2.0.8';
+
+/**
+ * default settings
+ * @namespace
+ */
+Hammer.defaults = {
+    /**
+     * set if DOM events are being triggered.
+     * But this is slower and unused by simple implementations, so disabled by default.
+     * @type {Boolean}
+     * @default false
+     */
+    domEvents: false,
+
+    /**
+     * The value for the touchAction property/fallback.
+     * When set to `compute` it will magically set the correct value based on the added recognizers.
+     * @type {String}
+     * @default compute
+     */
+    touchAction: TOUCH_ACTION_COMPUTE,
+
+    /**
+     * @type {Boolean}
+     * @default true
+     */
+    enable: true,
+
+    /**
+     * EXPERIMENTAL FEATURE -- can be removed/changed
+     * Change the parent input target element.
+     * If Null, then it is being set the to main element.
+     * @type {Null|EventTarget}
+     * @default null
+     */
+    inputTarget: null,
+
+    /**
+     * force an input class
+     * @type {Null|Function}
+     * @default null
+     */
+    inputClass: null,
+
+    /**
+     * Default recognizer setup when calling `Hammer()`
+     * When creating a new Manager these will be skipped.
+     * @type {Array}
+     */
+    preset: [
+        // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
+        [RotateRecognizer, {enable: false}],
+        [PinchRecognizer, {enable: false}, ['rotate']],
+        [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
+        [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
+        [TapRecognizer],
+        [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
+        [PressRecognizer]
+    ],
+
+    /**
+     * Some CSS properties can be used to improve the working of Hammer.
+     * Add them to this method and they will be set when creating a new Manager.
+     * @namespace
+     */
+    cssProps: {
+        /**
+         * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
+         * @type {String}
+         * @default 'none'
+         */
+        userSelect: 'none',
+
+        /**
+         * Disable the Windows Phone grippers when pressing an element.
+         * @type {String}
+         * @default 'none'
+         */
+        touchSelect: 'none',
+
+        /**
+         * Disables the default callout shown when you touch and hold a touch target.
+         * On iOS, when you touch and hold a touch target such as a link, Safari displays
+         * a callout containing information about the link. This property allows you to disable that callout.
+         * @type {String}
+         * @default 'none'
+         */
+        touchCallout: 'none',
+
+        /**
+         * Specifies whether zooming is enabled. Used by IE10>
+         * @type {String}
+         * @default 'none'
+         */
+        contentZooming: 'none',
+
+        /**
+         * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
+         * @type {String}
+         * @default 'none'
+         */
+        userDrag: 'none',
+
+        /**
+         * Overrides the highlight color shown when the user taps a link or a JavaScript
+         * clickable element in iOS. This property obeys the alpha value, if specified.
+         * @type {String}
+         * @default 'rgba(0,0,0,0)'
+         */
+        tapHighlightColor: 'rgba(0,0,0,0)'
+    }
+};
+
+var STOP = 1;
+var FORCED_STOP = 2;
+
+/**
+ * Manager
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Manager(element, options) {
+    this.options = assign({}, Hammer.defaults, options || {});
+
+    this.options.inputTarget = this.options.inputTarget || element;
+
+    this.handlers = {};
+    this.session = {};
+    this.recognizers = [];
+    this.oldCssProps = {};
+
+    this.element = element;
+    this.input = createInputInstance(this);
+    this.touchAction = new TouchAction(this, this.options.touchAction);
+
+    toggleCssProps(this, true);
+
+    each(this.options.recognizers, function(item) {
+        var recognizer = this.add(new (item[0])(item[1]));
+        item[2] && recognizer.recognizeWith(item[2]);
+        item[3] && recognizer.requireFailure(item[3]);
+    }, this);
+}
+
+Manager.prototype = {
+    /**
+     * set options
+     * @param {Object} options
+     * @returns {Manager}
+     */
+    set: function(options) {
+        assign(this.options, options);
+
+        // Options that need a little more setup
+        if (options.touchAction) {
+            this.touchAction.update();
+        }
+        if (options.inputTarget) {
+            // Clean up existing event listeners and reinitialize
+            this.input.destroy();
+            this.input.target = options.inputTarget;
+            this.input.init();
+        }
+        return this;
+    },
+
+    /**
+     * stop recognizing for this session.
+     * This session will be discarded, when a new [input]start event is fired.
+     * When forced, the recognizer cycle is stopped immediately.
+     * @param {Boolean} [force]
+     */
+    stop: function(force) {
+        this.session.stopped = force ? FORCED_STOP : STOP;
+    },
+
+    /**
+     * run the recognizers!
+     * called by the inputHandler function on every movement of the pointers (touches)
+     * it walks through all the recognizers and tries to detect the gesture that is being made
+     * @param {Object} inputData
+     */
+    recognize: function(inputData) {
+        var session = this.session;
+        if (session.stopped) {
+            return;
+        }
+
+        // run the touch-action polyfill
+        this.touchAction.preventDefaults(inputData);
+
+        var recognizer;
+        var recognizers = this.recognizers;
+
+        // this holds the recognizer that is being recognized.
+        // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
+        // if no recognizer is detecting a thing, it is set to `null`
+        var curRecognizer = session.curRecognizer;
+
+        // reset when the last recognizer is recognized
+        // or when we're in a new session
+        if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
+            curRecognizer = session.curRecognizer = null;
+        }
+
+        var i = 0;
+        while (i < recognizers.length) {
+            recognizer = recognizers[i];
+
+            // find out if we are allowed try to recognize the input for this one.
+            // 1.   allow if the session is NOT forced stopped (see the .stop() method)
+            // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
+            //      that is being recognized.
+            // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
+            //      this can be setup with the `recognizeWith()` method on the recognizer.
+            if (session.stopped !== FORCED_STOP && ( // 1
+                    !curRecognizer || recognizer == curRecognizer || // 2
+                    recognizer.canRecognizeWith(curRecognizer))) { // 3
+                recognizer.recognize(inputData);
+            } else {
+                recognizer.reset();
+            }
+
+            // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
+            // current active recognizer. but only if we don't already have an active recognizer
+            if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
+                curRecognizer = session.curRecognizer = recognizer;
+            }
+            i++;
+        }
+    },
+
+    /**
+     * get a recognizer by its event name.
+     * @param {Recognizer|String} recognizer
+     * @returns {Recognizer|Null}
+     */
+    get: function(recognizer) {
+        if (recognizer instanceof Recognizer) {
+            return recognizer;
+        }
+
+        var recognizers = this.recognizers;
+        for (var i = 0; i < recognizers.length; i++) {
+            if (recognizers[i].options.event == recognizer) {
+                return recognizers[i];
+            }
+        }
+        return null;
+    },
+
+    /**
+     * add a recognizer to the manager
+     * existing recognizers with the same event name will be removed
+     * @param {Recognizer} recognizer
+     * @returns {Recognizer|Manager}
+     */
+    add: function(recognizer) {
+        if (invokeArrayArg(recognizer, 'add', this)) {
+            return this;
+        }
+
+        // remove existing
+        var existing = this.get(recognizer.options.event);
+        if (existing) {
+            this.remove(existing);
+        }
+
+        this.recognizers.push(recognizer);
+        recognizer.manager = this;
+
+        this.touchAction.update();
+        return recognizer;
+    },
+
+    /**
+     * remove a recognizer by name or instance
+     * @param {Recognizer|String} recognizer
+     * @returns {Manager}
+     */
+    remove: function(recognizer) {
+        if (invokeArrayArg(recognizer, 'remove', this)) {
+            return this;
+        }
+
+        recognizer = this.get(recognizer);
+
+        // let's make sure this recognizer exists
+        if (recognizer) {
+            var recognizers = this.recognizers;
+            var index = inArray(recognizers, recognizer);
+
+            if (index !== -1) {
+                recognizers.splice(index, 1);
+                this.touchAction.update();
+            }
+        }
+
+        return this;
+    },
+
+    /**
+     * bind event
+     * @param {String} events
+     * @param {Function} handler
+     * @returns {EventEmitter} this
+     */
+    on: function(events, handler) {
+        if (events === undefined) {
+            return;
+        }
+        if (handler === undefined) {
+            return;
+        }
+
+        var handlers = this.handlers;
+        each(splitStr(events), function(event) {
+            handlers[event] = handlers[event] || [];
+            handlers[event].push(handler);
+        });
+        return this;
+    },
+
+    /**
+     * unbind event, leave emit blank to remove all handlers
+     * @param {String} events
+     * @param {Function} [handler]
+     * @returns {EventEmitter} this
+     */
+    off: function(events, handler) {
+        if (events === undefined) {
+            return;
+        }
+
+        var handlers = this.handlers;
+        each(splitStr(events), function(event) {
+            if (!handler) {
+                delete handlers[event];
+            } else {
+                handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
+            }
+        });
+        return this;
+    },
+
+    /**
+     * emit event to the listeners
+     * @param {String} event
+     * @param {Object} data
+     */
+    emit: function(event, data) {
+        // we also want to trigger dom events
+        if (this.options.domEvents) {
+            triggerDomEvent(event, data);
+        }
+
+        // no handlers, so skip it all
+        var handlers = this.handlers[event] && this.handlers[event].slice();
+        if (!handlers || !handlers.length) {
+            return;
+        }
+
+        data.type = event;
+        data.preventDefault = function() {
+            data.srcEvent.preventDefault();
+        };
+
+        var i = 0;
+        while (i < handlers.length) {
+            handlers[i](data);
+            i++;
+        }
+    },
+
+    /**
+     * destroy the manager and unbinds all events
+     * it doesn't unbind dom events, that is the user own responsibility
+     */
+    destroy: function() {
+        this.element && toggleCssProps(this, false);
+
+        this.handlers = {};
+        this.session = {};
+        this.input.destroy();
+        this.element = null;
+    }
+};
+
+/**
+ * add/remove the css properties as defined in manager.options.cssProps
+ * @param {Manager} manager
+ * @param {Boolean} add
+ */
+function toggleCssProps(manager, add) {
+    var element = manager.element;
+    if (!element.style) {
+        return;
+    }
+    var prop;
+    each(manager.options.cssProps, function(value, name) {
+        prop = prefixed(element.style, name);
+        if (add) {
+            manager.oldCssProps[prop] = element.style[prop];
+            element.style[prop] = value;
+        } else {
+            element.style[prop] = manager.oldCssProps[prop] || '';
+        }
+    });
+    if (!add) {
+        manager.oldCssProps = {};
+    }
+}
+
+/**
+ * trigger dom event
+ * @param {String} event
+ * @param {Object} data
+ */
+function triggerDomEvent(event, data) {
+    var gestureEvent = document.createEvent('Event');
+    gestureEvent.initEvent(event, true, true);
+    gestureEvent.gesture = data;
+    data.target.dispatchEvent(gestureEvent);
+}
+
+assign(Hammer, {
+    INPUT_START: INPUT_START,
+    INPUT_MOVE: INPUT_MOVE,
+    INPUT_END: INPUT_END,
+    INPUT_CANCEL: INPUT_CANCEL,
+
+    STATE_POSSIBLE: STATE_POSSIBLE,
+    STATE_BEGAN: STATE_BEGAN,
+    STATE_CHANGED: STATE_CHANGED,
+    STATE_ENDED: STATE_ENDED,
+    STATE_RECOGNIZED: STATE_RECOGNIZED,
+    STATE_CANCELLED: STATE_CANCELLED,
+    STATE_FAILED: STATE_FAILED,
+
+    DIRECTION_NONE: DIRECTION_NONE,
+    DIRECTION_LEFT: DIRECTION_LEFT,
+    DIRECTION_RIGHT: DIRECTION_RIGHT,
+    DIRECTION_UP: DIRECTION_UP,
+    DIRECTION_DOWN: DIRECTION_DOWN,
+    DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
+    DIRECTION_VERTICAL: DIRECTION_VERTICAL,
+    DIRECTION_ALL: DIRECTION_ALL,
+
+    Manager: Manager,
+    Input: Input,
+    TouchAction: TouchAction,
+
+    TouchInput: TouchInput,
+    MouseInput: MouseInput,
+    PointerEventInput: PointerEventInput,
+    TouchMouseInput: TouchMouseInput,
+    SingleTouchInput: SingleTouchInput,
+
+    Recognizer: Recognizer,
+    AttrRecognizer: AttrRecognizer,
+    Tap: TapRecognizer,
+    Pan: PanRecognizer,
+    Swipe: SwipeRecognizer,
+    Pinch: PinchRecognizer,
+    Rotate: RotateRecognizer,
+    Press: PressRecognizer,
+
+    on: addEventListeners,
+    off: removeEventListeners,
+    each: each,
+    merge: merge,
+    extend: extend,
+    assign: assign,
+    inherit: inherit,
+    bindFn: bindFn,
+    prefixed: prefixed
+});
+
+// this prevents errors when Hammer is loaded in the presence of an AMD
+//  style loader but by script tag, not by the loader.
+var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
+freeGlobal.Hammer = Hammer;
+
+if (typeof define === 'function' && define.amd) {
+    define(function() {
+        return Hammer;
+    });
+} else if (typeof module != 'undefined' && module.exports) {
+    module.exports = Hammer;
+} else {
+    window[exportName] = Hammer;
+}
+
+})(window, document, 'Hammer');
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  $.modal = function(params, onOpen) {
+    params = $.extend({}, defaults, params);
+
+
+    var buttons = params.buttons;
+
+    var buttonsHtml = buttons.map(function(d, i) {
+      return '<a href="javascript:;" class="weui-dialog__btn ' + (d.className || "") + '">' + d.text + '</a>';
+    }).join("");
+
+    var tpl = '<div class="weui-dialog">' +
+                '<div class="weui-dialog__hd"><strong class="weui-dialog__title">' + params.title + '</strong></div>' +
+                ( params.text ? '<div class="weui-dialog__bd">'+params.text+'</div>' : '')+
+                '<div class="weui-dialog__ft">' + buttonsHtml + '</div>' +
+              '</div>';
+    
+    var dialog = $.openModal(tpl, onOpen);
+
+    dialog.find(".weui-dialog__btn").each(function(i, e) {
+      var el = $(e);
+      el.click(function() {
+        //先关闭对话框,再调用回调函数
+        if(params.autoClose) $.closeModal();
+
+        if(buttons[i].onClick) {
+          buttons[i].onClick.call(dialog);
+        }
+      });
+    });
+
+    return dialog;
+  };
+
+  $.openModal = function(tpl, onOpen) {
+    var mask = $("<div class='weui-mask'></div>").appendTo(document.body);
+    mask.show();
+
+    var dialog = $(tpl).appendTo(document.body);
+ 
+    if (onOpen) {
+      dialog.transitionEnd(function () {
+        onOpen.call(dialog);
+      });
+    }   
+
+    dialog.show();
+    mask.addClass("weui-mask--visible");
+    dialog.addClass("weui-dialog--visible");
+
+
+    return dialog;
+  }
+
+  $.closeModal = function() {
+    $(".weui-mask--visible").removeClass("weui-mask--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+    $(".weui-dialog--visible").removeClass("weui-dialog--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+  };
+
+  $.alert = function(text, title, onOK) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        onOK = arguments[1];
+        title = undefined;
+      }
+
+      config = {
+        text: text,
+        title: title,
+        onOK: onOK
+      }
+    }
+    return $.modal({
+      text: config.text,
+      title: config.title,
+      buttons: [{
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: config.onOK
+      }]
+    });
+  }
+
+  $.confirm = function(text, title, onOK, onCancel) {
+    var config;
+    if (typeof text === 'object') {
+      config = text
+    } else {
+      if (typeof title === 'function') {
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+
+      config = {
+        text: text,
+        title: title,
+        onOK: onOK,
+        onCancel: onCancel
+      }
+    }
+    return $.modal({
+      text: config.text,
+      title: config.title,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: config.onCancel
+      },
+      {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: config.onOK
+      }]
+    });
+  };
+
+  //如果参数过多,建议通过 config 对象进行配置,而不是传入多个参数。
+  $.prompt = function(text, title, onOK, onCancel, input) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        input = arguments[3];
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+      config = {
+        text: text,
+        title: title,
+        input: input,
+        onOK: onOK,
+        onCancel: onCancel,
+        empty: false  //allow empty
+      }
+    }
+
+    var modal = $.modal({
+      text: '<p class="weui-prompt-text">'+(config.text || '')+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-input" value="' + (config.input || '') + '" />',
+      title: config.title,
+      autoClose: false,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: function () {
+          $.closeModal();
+          config.onCancel && config.onCancel.call(modal);
+        }
+      },
+      {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: function() {
+          var input = $("#weui-prompt-input").val();
+          if (!config.empty && (input === "" || input === null)) {
+            modal.find('.weui-prompt-input').focus()[0].select();
+            return false;
+          }
+          $.closeModal();
+          config.onOK && config.onOK.call(modal, input);
+        }
+      }]
+    }, function () {
+      this.find('.weui-prompt-input').focus()[0].select();
+    });
+
+    return modal;
+  };
+
+  //如果参数过多,建议通过 config 对象进行配置,而不是传入多个参数。
+  $.login = function(text, title, onOK, onCancel, username, password) {
+    var config;
+    if (typeof text === 'object') {
+      config = text;
+    } else {
+      if (typeof title === 'function') {
+        password = arguments[4];
+        username = arguments[3];
+        onCancel = arguments[2];
+        onOK = arguments[1];
+        title = undefined;
+      }
+      config = {
+        text: text,
+        title: title,
+        username: username,
+        password: password,
+        onOK: onOK,
+        onCancel: onCancel
+      }
+    }
+
+    var modal = $.modal({
+      text: '<p class="weui-prompt-text">'+(config.text || '')+'</p>' +
+            '<input type="text" class="weui-input weui-prompt-input" id="weui-prompt-username" value="' + (config.username || '') + '" placeholder="输入用户名" />' +
+            '<input type="password" class="weui-input weui-prompt-input" id="weui-prompt-password" value="' + (config.password || '') + '" placeholder="输入密码" />',
+      title: config.title,
+      autoClose: false,
+      buttons: [
+      {
+        text: defaults.buttonCancel,
+        className: "default",
+        onClick: function () {
+          $.closeModal();
+          config.onCancel && config.onCancel.call(modal);
+        }
+      }, {
+        text: defaults.buttonOK,
+        className: "primary",
+        onClick: function() {
+          var username = $("#weui-prompt-username").val();
+          var password = $("#weui-prompt-password").val();
+          if (!config.empty && (username === "" || username === null)) {
+            modal.find('#weui-prompt-username').focus()[0].select();
+            return false;
+          }
+          if (!config.empty && (password === "" || password === null)) {
+            modal.find('#weui-prompt-password').focus()[0].select();
+            return false;
+          }
+          $.closeModal();
+          config.onOK && config.onOK.call(modal, username, password);
+        }
+      }]
+    }, function () {
+      this.find('#weui-prompt-username').focus()[0].select();
+    });
+
+    return modal;
+  };
+
+  defaults = $.modal.prototype.defaults = {
+    title: "提示",
+    text: undefined,
+    buttonOK: "确定",
+    buttonCancel: "取消",
+    buttons: [{
+      text: "确定",
+      className: "primary"
+    }],
+    autoClose: true //点击按钮自动关闭对话框,如果你不希望点击按钮就关闭对话框,可以把这个设置为false
+  };
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  var show = function(html, className) {
+    className = className || "";
+    var mask = $("<div class='weui-mask_transparent'></div>").appendTo(document.body);
+
+    var tpl = '<div class="weui-toast ' + className + '">' + html + '</div>';
+    var dialog = $(tpl).appendTo(document.body);
+
+    dialog.addClass("weui-toast--visible");
+    dialog.show();
+  };
+
+  var hide = function(callback) {
+    $(".weui-mask_transparent").remove();
+    var done = false;
+    var $el = $(".weui-toast--visible").removeClass("weui-toast--visible").transitionEnd(function() {
+      var $this = $(this);
+      $this.remove();
+      callback && callback();
+      done = true
+    });
+
+    setTimeout(function () {
+      if (!done) {
+        $el.remove()
+        callback && callback();
+      }
+    }, 1000)
+  }
+
+  $.toast = function(text, style, callback) {
+    if(typeof style === "function") {
+      callback = style;
+    }
+    var className, iconClassName = 'weui-icon-success-no-circle';
+    var duration = toastDefaults.duration;
+    if(style == "cancel") {
+      className = "weui-toast_cancel";
+      iconClassName = 'weui-icon-cancel'
+    } else if(style == "forbidden") {
+      className = "weui-toast--forbidden";
+      iconClassName = 'weui-icon-warn'
+    } else if(style == "text") {
+      className = "weui-toast--text";
+    } else if(typeof style === typeof 1) {
+      duration = style
+    }
+    show('<i class="' + iconClassName + ' weui-icon_toast"></i><p class="weui-toast_content">' + (text || "已经完成") + '</p>', className);
+
+    setTimeout(function() {
+      hide(callback);
+    }, duration);
+  }
+
+  $.showLoading = function(text) {
+    var html = '<div class="weui_loading">';
+    html += '<i class="weui-loading weui-icon_toast"></i>';
+    html += '</div>';
+    html += '<p class="weui-toast_content">' + (text || "数据加载中") + '</p>';
+    show(html, 'weui_loading_toast');
+  }
+
+  $.hideLoading = function() {
+    hide();
+  }
+
+  var toastDefaults = $.toast.prototype.defaults = {
+    duration: 2500
+  }
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var defaults;
+  
+  var show = function(params) {
+
+    var mask = $("<div class='weui-mask weui-actions_mask'></div>").appendTo(document.body);
+
+    var actions = params.actions || [];
+
+    var actionsHtml = actions.map(function(d, i) {
+      return '<div class="weui-actionsheet__cell ' + (d.className || "") + '">' + d.text + '</div>';
+    }).join("");
+
+    var titleHtml = "";
+    
+    if (params.title) {
+      titleHtml = '<div class="weui-actionsheet__title"><p class="weui-actionsheet__title-text">' + params.title + '</p></div>';
+    }
+
+    var tpl = '<div class="weui-actionsheet " id="weui-actionsheet">'+
+                titleHtml +
+                '<div class="weui-actionsheet__menu">'+
+                actionsHtml +
+                '</div>'+
+                '<div class="weui-actionsheet__action">'+
+                  '<div class="weui-actionsheet__cell weui-actionsheet_cancel">取消</div>'+
+                  '</div>'+
+                '</div>';
+    var dialog = $(tpl).appendTo(document.body);
+
+    dialog.find(".weui-actionsheet__menu .weui-actionsheet__cell, .weui-actionsheet__action .weui-actionsheet__cell").each(function(i, e) {
+      $(e).click(function() {
+        $.closeActions();
+        params.onClose && params.onClose();
+        if(actions[i] && actions[i].onClick) {
+          actions[i].onClick();
+        }
+      })
+    });
+
+    mask.show();
+    dialog.show();
+    mask.addClass("weui-mask--visible");
+    dialog.addClass("weui-actionsheet_toggle");
+  };
+
+  var hide = function() {
+    $(".weui-mask").removeClass("weui-mask--visible").transitionEnd(function() {
+      $(this).remove();
+    });
+    $(".weui-actionsheet").removeClass("weui-actionsheet_toggle").transitionEnd(function() {
+      $(this).remove();
+    });
+  }
+
+  $.actions = function(params) {
+    params = $.extend({}, defaults, params);
+    show(params);
+  }
+
+  $.closeActions = function() {
+    hide();
+  }
+
+  $(document).on("click", ".weui-actions_mask", function() {
+    $.closeActions();
+  });
+
+  var defaults = $.actions.prototype.defaults = {
+    title: undefined,
+    onClose: undefined,
+    /*actions: [{
+      text: "菜单",
+      className: "color-danger",
+      onClick: function() {
+        console.log(1);
+      }
+    },{
+      text: "菜单2",
+      className: "color-success",
+      onClick: function() {
+        console.log(2);
+      }
+    }]*/
+  }
+
+}($);
+
+/* ===============================================================================
+************   Pull to refreh ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var PTR = function(el, opt) {
+    if (typeof opt === typeof function () {}) {
+      opt = {
+        onRefresh: opt
+      }
+    }
+    if (typeof opt === typeof 'a') {
+      opt = undefined
+    }
+    this.opt = $.extend(PTR.defaults, opt || {});
+    this.container = $(el);
+    this.attachEvents();
+  }
+
+  PTR.defaults = {
+    distance: 50,
+    onRefresh: undefined,
+    onPull: undefined
+  }
+
+  PTR.prototype.touchStart = function(e) {
+    if(this.container.hasClass("refreshing")) return;
+    var p = $.getTouchPosition(e);
+    this.start = p;
+    this.diffX = this.diffY = 0;
+  };
+
+  PTR.prototype.touchMove= function(e) {
+    if(this.container.hasClass("refreshing")) return;
+    if(!this.start) return false;
+    if(this.container.scrollTop() > 0) return;
+    var p = $.getTouchPosition(e);
+    this.diffX = p.x - this.start.x;
+    this.diffY = p.y - this.start.y;
+    if (Math.abs(this.diffX) > Math.abs(this.diffY)) return true; // 说明是左右方向的拖动
+    if(this.diffY < 0) return;
+    this.container.addClass("touching");
+    e.preventDefault();
+    e.stopPropagation();
+    this.diffY = Math.pow(this.diffY, 0.75);
+    this.container.css("transform", "translate3d(0, "+this.diffY+"px, 0)");
+    this.triggerPull(this.diffY)
+  };
+  PTR.prototype.touchEnd = function() {
+    this.start = false;
+    if(this.diffY <= 0 || this.container.hasClass("refreshing")) return;
+    this.container.removeClass("touching");
+    this.container.removeClass("pull-down pull-up");
+    this.container.css("transform", "");
+    if(Math.abs(this.diffY) <= this.opt.distance) {
+    } else {
+      this.triggerPullToRefresh();
+    }
+  };
+
+  PTR.prototype.triggerPullToRefresh = function() {
+    this.triggerPull(this.opt.distance)
+    this.container.removeClass('pull-up').addClass("refreshing");
+    if (this.opt.onRefresh) {
+      this.opt.onRefresh.call(this)
+    }
+    this.container.trigger("pull-to-refresh");
+  }
+
+  PTR.prototype.triggerPull = function(diffY) {
+
+    if(diffY < this.opt.distance) {
+      this.container.removeClass("pull-up").addClass("pull-down");
+    } else {
+      this.container.removeClass("pull-down").addClass("pull-up");
+    }
+
+    if (this.opt.onPull) {
+      this.opt.onPull.call(this, Math.floor(diffY / this.opt.distance * 100))
+    }
+    this.container.trigger("pull");
+  }
+
+  PTR.prototype.pullToRefreshDone = function() {
+    this.container.removeClass("refreshing");
+  }
+
+  PTR.prototype.attachEvents = function() {
+    var el = this.container;
+    el.addClass("weui-pull-to-refresh");
+    el.on($.touchEvents.start, $.proxy(this.touchStart, this));
+    el.on($.touchEvents.move, $.proxy(this.touchMove, this));
+    el.on($.touchEvents.end, $.proxy(this.touchEnd, this));
+  };
+
+  var pullToRefreshDone = function(el) {
+    $(el).removeClass("refreshing");
+  }
+
+  $.fn.pullToRefresh = function(opt) {
+    return this.each(function() {
+      var $this = $(this)
+      var ptr = $this.data('ptr')
+      if (!ptr) $this.data('ptr', ptr = new PTR(this, opt))
+      if (typeof opt === typeof 'a') {
+        ptr[opt].call(ptr)
+      }
+    });
+  }
+
+  $.fn.pullToRefreshDone = function() {
+    return this.each(function() {
+      pullToRefreshDone(this);
+    });
+  }
+
+}($);
+
+/* ===============================================================================
+************   Infinite ************
+=============================================================================== */
+/* global $:true */
++function ($) {
+  "use strict";
+
+  // fix https://github.com/lihongxun945/jquery-weui/issues/442
+  // chrome will always return 0, when use document.body.scrollTop
+  // https://stackoverflow.com/questions/43717316/google-chrome-document-body-scrolltop-always-returns-0
+  var getOffset = function (container) {
+    var tagName = container[0].tagName.toUpperCase()
+    var scrollTop 
+    if (tagName === 'BODY' || tagName === 'HTML') {
+      scrollTop = container.scrollTop() || $(window).scrollTop()
+    } else {
+      scrollTop = container.scrollTop()
+    }
+    var offset = container.scrollHeight() - ($(window).height() + scrollTop)
+    console.log(offset)
+    return offset
+  }
+
+  var Infinite = function(el, distance) {
+    this.container = $(el);
+    this.container.data("infinite", this);
+    this.distance = distance || 50;
+    this.attachEvents();
+  }
+
+  Infinite.prototype.scroll = function() {
+    var container = this.container;
+    this._check();
+  }
+
+  Infinite.prototype.attachEvents = function(off) {
+    var el = this.container;
+    var scrollContainer = (el[0].tagName.toUpperCase() === "BODY" ? $(document) : el);
+    scrollContainer[off ? "off" : "on"]("scroll", $.proxy(this.scroll, this));
+  };
+  Infinite.prototype.detachEvents = function(off) {
+    this.attachEvents(true);
+  }
+  Infinite.prototype._check = function() {
+    var offset = getOffset(this.container);
+    if(Math.abs(offset) <= this.distance) {
+      this.container.trigger("infinite");
+    }
+  }
+
+  var infinite = function(el) {
+    attachEvents(el);
+  }
+
+  $.fn.infinite = function(distance) {
+    return this.each(function() {
+      new Infinite(this, distance);
+    });
+  }
+  $.fn.destroyInfinite = function() {
+    return this.each(function() {
+      var infinite = $(this).data("infinite");
+      if(infinite && infinite.detachEvents) infinite.detachEvents();
+    });
+  }
+
+}($);
+
+/* global $:true */
++function ($) {
+  "use strict";
+
+  var ITEM_ON = "weui-bar__item--on";
+
+  var showTab = function(a) {
+    var $a = $(a);
+    if($a.hasClass(ITEM_ON)) return;
+    var href = $a.attr("href");
+
+    if(!/^#/.test(href)) return ;
+
+    $a.parent().find("."+ITEM_ON).removeClass(ITEM_ON);
+    $a.addClass(ITEM_ON);
+
+    var bd = $a.parents(".weui-tab").find(".weui-tab__bd");
+
+    bd.find(".weui-tab__bd-item--active").removeClass("weui-tab__bd-item--active");
+
+    $(href).addClass("weui-tab__bd-item--active");
+  }
+
+  $.showTab = showTab;
+
+  $(document).on("click", ".weui-navbar__item, .weui-tabbar__item", function(e) {
+    var $a = $(e.currentTarget);
+    var href = $a.attr("href");
+    if($a.hasClass(ITEM_ON)) return;
+    if(!/^#/.test(href)) return;
+
+    e.preventDefault();
+
+    showTab($a);
+  });
+
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+
+  $(document).on("click touchstart", ".weui-search-bar__label", function(e) {
+    $(e.target).parents(".weui-search-bar").addClass("weui-search-bar_focusing").find('input').focus();
+  }) 
+  /*
+  .on("blur", ".weui-search-bar__input", function(e) {
+    var $input = $(e.target);
+    if(!$input.val()) $input.parents(".weui-search-bar").removeClass("weui-search-bar_focusing");
+  })
+  */
+  .on("click", ".weui-search-bar__cancel-btn", function(e) {
+    var $input = $(e.target).parents(".weui-search-bar").removeClass("weui-search-bar_focusing").find(".weui-search-bar__input").val("").blur();
+  })
+  .on("click", ".weui-icon-clear", function(e) {
+    var $input = $(e.target).parents(".weui-search-bar").find(".weui-search-bar__input").val("").focus();
+  });
+
+}($);
+
+/*===========================
+Device/OS Detection
+===========================*/
+/* global $:true */
+;(function ($) {
+    "use strict";
+    var device = {};
+    var ua = navigator.userAgent;
+
+    var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
+    var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
+    var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
+    var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
+
+    device.ios = device.android = device.iphone = device.ipad = device.androidChrome = false;
+    
+    // Android
+    if (android) {
+        device.os = 'android';
+        device.osVersion = android[2];
+        device.android = true;
+        device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
+    }
+    if (ipad || iphone || ipod) {
+        device.os = 'ios';
+        device.ios = true;
+    }
+    // iOS
+    if (iphone && !ipod) {
+        device.osVersion = iphone[2].replace(/_/g, '.');
+        device.iphone = true;
+    }
+    if (ipad) {
+        device.osVersion = ipad[2].replace(/_/g, '.');
+        device.ipad = true;
+    }
+    if (ipod) {
+        device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
+        device.iphone = true;
+    }
+    // iOS 8+ changed UA
+    if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
+        if (device.osVersion.split('.')[0] === '10') {
+            device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
+        }
+    }
+
+    // Webview
+    device.webView = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);
+        
+    // Minimal UI
+    if (device.os && device.os === 'ios') {
+        var osVersionArr = device.osVersion.split('.');
+        device.minimalUi = !device.webView &&
+                            (ipod || iphone) &&
+                            (osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7) &&
+                            $('meta[name="viewport"]').length > 0 && $('meta[name="viewport"]').attr('content').indexOf('minimal-ui') >= 0;
+    }
+
+    // Check for status bar and fullscreen app mode
+    var windowWidth = $(window).width();
+    var windowHeight = $(window).height();
+    device.statusBar = false;
+    if (device.webView && (windowWidth * windowHeight === screen.width * screen.height)) {
+        device.statusBar = true;
+    }
+    else {
+        device.statusBar = false;
+    }
+
+    // Classes
+    var classNames = [];
+
+    // Pixel Ratio
+    device.pixelRatio = window.devicePixelRatio || 1;
+    classNames.push('pixel-ratio-' + Math.floor(device.pixelRatio));
+    if (device.pixelRatio >= 2) {
+        classNames.push('retina');
+    }
+
+    // OS classes
+    if (device.os) {
+        classNames.push(device.os, device.os + '-' + device.osVersion.split('.')[0], device.os + '-' + device.osVersion.replace(/\./g, '-'));
+        if (device.os === 'ios') {
+            var major = parseInt(device.osVersion.split('.')[0], 10);
+            for (var i = major - 1; i >= 6; i--) {
+                classNames.push('ios-gt-' + i);
+            }
+        }
+        
+    }
+    // Status bar classes
+    if (device.statusBar) {
+        classNames.push('with-statusbar-overlay');
+    }
+    else {
+        $('html').removeClass('with-statusbar-overlay');
+    }
+
+    // Add html classes
+    if (classNames.length > 0) $('html').addClass(classNames.join(' '));
+
+    $.device = device;
+})($);
+
+/*======================================================
+************   Picker   ************
+======================================================*/
+/* global $:true */
+/* jshint unused:false */
+/* jshint multistr:true */
++ function($) {
+  "use strict";
+  var Picker = function (params) {
+      var p = this;
+      var defaults = {
+          updateValuesOnMomentum: false,
+          updateValuesOnTouchmove: true,
+          rotateEffect: false,
+          momentumRatio: 7,
+          freeMode: false,
+          // Common settings
+          scrollToInput: true,
+          inputReadOnly: true,
+          toolbar: true,
+          toolbarCloseText: '完成',
+          title: '请选择',
+          toolbarTemplate: '<div class="toolbar">\
+          <div class="toolbar-inner">\
+          <a href="javascript:;" class="picker-button close-picker">{{closeText}}</a>\
+          <h1 class="title">{{title}}</h1>\
+          </div>\
+          </div>',
+      };
+      params = params || {};
+      for (var def in defaults) {
+          if (typeof params[def] === 'undefined') {
+              params[def] = defaults[def];
+          }
+      }
+      p.params = params;
+      p.cols = [];
+      p.initialized = false;
+      
+      // Inline flag
+      p.inline = p.params.container ? true : false;
+
+      // 3D Transforms origin bug, only on safari
+      var originBug = $.device.ios || (navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !$.device.android;
+
+      // Should be converted to popover
+      function isPopover() {
+          var toPopover = false;
+          if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
+          if (!p.inline && p.params.input) {
+              if (p.params.onlyInPopover) toPopover = true;
+              else {
+                  if ($.device.ios) {
+                      toPopover = $.device.ipad ? true : false;
+                  }
+                  else {
+                      if ($(window).width() >= 768) toPopover = true;
+                  }
+              }
+          } 
+          return toPopover; 
+      }
+      function inPopover() {
+          if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
+          else return false;
+      }
+
+      // Value
+      p.setValue = function (arrValues, transition) {
+          var valueIndex = 0;
+          for (var i = 0; i < p.cols.length; i++) {
+              if (p.cols[i] && !p.cols[i].divider) {
+                  p.cols[i].setValue(arrValues[valueIndex], transition);
+                  valueIndex++;
+              }
+          }
+      };
+      p.updateValue = function () {
+          var newValue = [];
+          var newDisplayValue = [];
+          for (var i = 0; i < p.cols.length; i++) {
+              if (!p.cols[i].divider) {
+                  newValue.push(p.cols[i].value);
+                  newDisplayValue.push(p.cols[i].displayValue);
+              }
+          }
+          if (newValue.indexOf(undefined) >= 0) {
+              return;
+          }
+          p.value = newValue;
+          p.displayValue = newDisplayValue;
+          if (p.params.onChange) {
+              p.params.onChange(p, p.value, p.displayValue);
+          }
+          if (p.input && p.input.length > 0) {
+              $(p.input).val(p.params.formatValue ? p.params.formatValue(p, p.value, p.displayValue) : p.value.join(' '));
+              $(p.input).trigger('change');
+          }
+      };
+
+      // Columns Handlers
+      p.initPickerCol = function (colElement, updateItems) {
+          var colContainer = $(colElement);
+          var colIndex = colContainer.index();
+          var col = p.cols[colIndex];
+          if (col.divider) return;
+          col.container = colContainer;
+          col.wrapper = col.container.find('.picker-items-col-wrapper');
+          col.items = col.wrapper.find('.picker-item');
+          
+          var i, j;
+          var wrapperHeight, itemHeight, itemsHeight, minTranslate, maxTranslate;
+          col.replaceValues = function (values, displayValues) {
+              col.destroyEvents();
+              col.values = values;
+              col.displayValues = displayValues;
+              var newItemsHTML = p.columnHTML(col, true);
+              col.wrapper.html(newItemsHTML);
+              col.items = col.wrapper.find('.picker-item');
+              col.calcSize();
+              col.setValue(col.values[0] || '', 0, true);
+              col.initEvents();
+          };
+          col.calcSize = function () {
+              if (!col.values.length) return;
+              if (p.params.rotateEffect) {
+                  col.container.removeClass('picker-items-col-absolute');
+                  if (!col.width) col.container.css({width:''});
+              }
+              var colWidth, colHeight;
+              colWidth = 0;
+              colHeight = col.container[0].offsetHeight;
+              wrapperHeight = col.wrapper[0].offsetHeight;
+              itemHeight = col.items[0].offsetHeight;
+              itemsHeight = itemHeight * col.items.length;
+              minTranslate = colHeight / 2 - itemsHeight + itemHeight / 2;
+              maxTranslate = colHeight / 2 - itemHeight / 2;    
+              if (col.width) {
+                  colWidth = col.width;
+                  if (parseInt(colWidth, 10) === colWidth) colWidth = colWidth + 'px';
+                  col.container.css({width: colWidth});
+              }
+              if (p.params.rotateEffect) {
+                  if (!col.width) {
+                      col.items.each(function () {
+                          var item = $(this);
+                          item.css({width:'auto'});
+                          colWidth = Math.max(colWidth, item[0].offsetWidth);
+                          item.css({width:''});
+                      });
+                      col.container.css({width: (colWidth + 2) + 'px'});
+                  }
+                  col.container.addClass('picker-items-col-absolute');
+              }
+          };
+          col.calcSize();
+          
+          col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)').transition(0);
+
+
+          var activeIndex = 0;
+          var animationFrameId;
+
+          // Set Value Function
+          col.setValue = function (newValue, transition, valueCallbacks) {
+              if (typeof transition === 'undefined') transition = '';
+              var newActiveIndex = col.wrapper.find('.picker-item[data-picker-value="' + newValue + '"]').index();
+              if(typeof newActiveIndex === 'undefined' || newActiveIndex === -1) {
+                  col.value = col.displayValue = newValue;
+                  return;
+              }
+              var newTranslate = -newActiveIndex * itemHeight + maxTranslate;
+              // Update wrapper
+              col.wrapper.transition(transition);
+              col.wrapper.transform('translate3d(0,' + (newTranslate) + 'px,0)');
+                  
+              // Watch items
+              if (p.params.updateValuesOnMomentum && col.activeIndex && col.activeIndex !== newActiveIndex ) {
+                  $.cancelAnimationFrame(animationFrameId);
+                  col.wrapper.transitionEnd(function(){
+                      $.cancelAnimationFrame(animationFrameId);
+                  });
+                  updateDuringScroll();
+              }
+
+              // Update items
+              col.updateItems(newActiveIndex, newTranslate, transition, valueCallbacks);
+          };
+
+          col.updateItems = function (activeIndex, translate, transition, valueCallbacks) {
+              if (typeof translate === 'undefined') {
+                  translate = $.getTranslate(col.wrapper[0], 'y');
+              }
+              if(typeof activeIndex === 'undefined') activeIndex = -Math.round((translate - maxTranslate)/itemHeight);
+              if (activeIndex < 0) activeIndex = 0;
+              if (activeIndex >= col.items.length) activeIndex = col.items.length - 1;
+              var previousActiveIndex = col.activeIndex;
+              col.activeIndex = activeIndex;
+              /*
+              col.wrapper.find('.picker-selected, .picker-after-selected, .picker-before-selected').removeClass('picker-selected picker-after-selected picker-before-selected');
+
+              col.items.transition(transition);
+              var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
+              var prevItems = selectedItem.prevAll().addClass('picker-before-selected');
+              var nextItems = selectedItem.nextAll().addClass('picker-after-selected');
+              */
+              //去掉 .picker-after-selected, .picker-before-selected 以提高性能
+              col.wrapper.find('.picker-selected').removeClass('picker-selected');
+              if (p.params.rotateEffect) {
+                col.items.transition(transition);
+              }
+              var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
+
+              if (valueCallbacks || typeof valueCallbacks === 'undefined') {
+                  // Update values
+                  col.value = selectedItem.attr('data-picker-value');
+                  col.displayValue = col.displayValues ? col.displayValues[activeIndex] : col.value;
+                  // On change callback
+                  if (previousActiveIndex !== activeIndex) {
+                      if (col.onChange) {
+                          col.onChange(p, col.value, col.displayValue);
+                      }
+                      p.updateValue();
+                  }
+              }
+                  
+              // Set 3D rotate effect
+              if (!p.params.rotateEffect) {
+                  return;
+              }
+              var percentage = (translate - (Math.floor((translate - maxTranslate)/itemHeight) * itemHeight + maxTranslate)) / itemHeight;
+              
+              col.items.each(function () {
+                  var item = $(this);
+                  var itemOffsetTop = item.index() * itemHeight;
+                  var translateOffset = maxTranslate - translate;
+                  var itemOffset = itemOffsetTop - translateOffset;
+                  var percentage = itemOffset / itemHeight;
+
+                  var itemsFit = Math.ceil(col.height / itemHeight / 2) + 1;
+                  
+                  var angle = (-18*percentage);
+                  if (angle > 180) angle = 180;
+                  if (angle < -180) angle = -180;
+                  // Far class
+                  if (Math.abs(percentage) > itemsFit) item.addClass('picker-item-far');
+                  else item.removeClass('picker-item-far');
+                  // Set transform
+                  item.transform('translate3d(0, ' + (-translate + maxTranslate) + 'px, ' + (originBug ? -110 : 0) + 'px) rotateX(' + angle + 'deg)');
+              });
+          };
+
+          function updateDuringScroll() {
+              animationFrameId = $.requestAnimationFrame(function () {
+                  col.updateItems(undefined, undefined, 0);
+                  updateDuringScroll();
+              });
+          }
+
+          // Update items on init
+          if (updateItems) col.updateItems(0, maxTranslate, 0);
+
+          var allowItemClick = true;
+          var isTouched, isMoved, touchStartY, touchCurrentY, touchStartTime, touchEndTime, startTranslate, returnTo, currentTranslate, prevTranslate, velocityTranslate, velocityTime;
+          function handleTouchStart (e) {
+              if (isMoved || isTouched) return;
+              e.preventDefault();
+              isTouched = true;
+              var position = $.getTouchPosition(e);
+              touchStartY = touchCurrentY = position.y;
+              touchStartTime = (new Date()).getTime();
+              
+              allowItemClick = true;
+              startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
+          }
+          function handleTouchMove (e) {
+              if (!isTouched) return;
+              e.preventDefault();
+              allowItemClick = false;
+              var position = $.getTouchPosition(e);
+              touchCurrentY = position.y;
+              if (!isMoved) {
+                  // First move
+                  $.cancelAnimationFrame(animationFrameId);
+                  isMoved = true;
+                  startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
+                  col.wrapper.transition(0);
+              }
+              e.preventDefault();
+
+              var diff = touchCurrentY - touchStartY;
+              currentTranslate = startTranslate + diff;
+              returnTo = undefined;
+
+              // Normalize translate
+              if (currentTranslate < minTranslate) {
+                  currentTranslate = minTranslate - Math.pow(minTranslate - currentTranslate, 0.8);
+                  returnTo = 'min';
+              }
+              if (currentTranslate > maxTranslate) {
+                  currentTranslate = maxTranslate + Math.pow(currentTranslate - maxTranslate, 0.8);
+                  returnTo = 'max';
+              }
+              // Transform wrapper
+              col.wrapper.transform('translate3d(0,' + currentTranslate + 'px,0)');
+
+              // Update items
+              col.updateItems(undefined, currentTranslate, 0, p.params.updateValuesOnTouchmove);
+              
+              // Calc velocity
+              velocityTranslate = currentTranslate - prevTranslate || currentTranslate;
+              velocityTime = (new Date()).getTime();
+              prevTranslate = currentTranslate;
+          }
+          function handleTouchEnd (e) {
+              if (!isTouched || !isMoved) {
+                  isTouched = isMoved = false;
+                  return;
+              }
+              isTouched = isMoved = false;
+              col.wrapper.transition('');
+              if (returnTo) {
+                  if (returnTo === 'min') {
+                      col.wrapper.transform('translate3d(0,' + minTranslate + 'px,0)');
+                  }
+                  else col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)');
+              }
+              touchEndTime = new Date().getTime();
+              var velocity, newTranslate;
+              if (touchEndTime - touchStartTime > 300) {
+                  newTranslate = currentTranslate;
+              }
+              else {
+                  velocity = Math.abs(velocityTranslate / (touchEndTime - velocityTime));
+                  newTranslate = currentTranslate + velocityTranslate * p.params.momentumRatio;
+              }
+
+              newTranslate = Math.max(Math.min(newTranslate, maxTranslate), minTranslate);
+
+              // Active Index
+              var activeIndex = -Math.floor((newTranslate - maxTranslate)/itemHeight);
+
+              // Normalize translate
+              if (!p.params.freeMode) newTranslate = -activeIndex * itemHeight + maxTranslate;
+
+              // Transform wrapper
+              col.wrapper.transform('translate3d(0,' + (parseInt(newTranslate,10)) + 'px,0)');
+
+              // Update items
+              col.updateItems(activeIndex, newTranslate, '', true);
+
+              // Watch items
+              if (p.params.updateValuesOnMomentum) {
+                  updateDuringScroll();
+                  col.wrapper.transitionEnd(function(){
+                      $.cancelAnimationFrame(animationFrameId);
+                  });
+              }
+
+              // Allow click
+              setTimeout(function () {
+                  allowItemClick = true;
+              }, 100);
+          }
+
+          function handleClick(e) {
+              if (!allowItemClick) return;
+              $.cancelAnimationFrame(animationFrameId);
+              /*jshint validthis:true */
+              var value = $(this).attr('data-picker-value');
+              col.setValue(value);
+          }
+
+          col.initEvents = function (detach) {
+              var method = detach ? 'off' : 'on';
+              col.container[method]($.touchEvents.start, handleTouchStart);
+              col.container[method]($.touchEvents.move, handleTouchMove);
+              col.container[method]($.touchEvents.end, handleTouchEnd);
+              col.items[method]('click', handleClick);
+          };
+          col.destroyEvents = function () {
+              col.initEvents(true);
+          };
+
+          col.container[0].f7DestroyPickerCol = function () {
+              col.destroyEvents();
+          };
+
+          col.initEvents();
+
+      };
+      p.destroyPickerCol = function (colContainer) {
+          colContainer = $(colContainer);
+          if ('f7DestroyPickerCol' in colContainer[0]) colContainer[0].f7DestroyPickerCol();
+      };
+      // Resize cols
+      function resizeCols() {
+          if (!p.opened) return;
+          for (var i = 0; i < p.cols.length; i++) {
+              if (!p.cols[i].divider) {
+                  p.cols[i].calcSize();
+                  p.cols[i].setValue(p.cols[i].value, 0, false);
+              }
+          }
+      }
+      $(window).on('resize', resizeCols);
+
+      // HTML Layout
+      p.columnHTML = function (col, onlyItems) {
+          var columnItemsHTML = '';
+          var columnHTML = '';
+          if (col.divider) {
+              columnHTML += '<div class="picker-items-col picker-items-col-divider ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '">' + col.content + '</div>';
+          }
+          else {
+              for (var j = 0; j < col.values.length; j++) {
+                  columnItemsHTML += '<div class="picker-item" data-picker-value="' + col.values[j] + '">' + (col.displayValues ? col.displayValues[j] : col.values[j]) + '</div>';
+              }
+              columnHTML += '<div class="picker-items-col ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '"><div class="picker-items-col-wrapper">' + columnItemsHTML + '</div></div>';
+          }
+          return onlyItems ? columnItemsHTML : columnHTML;
+      };
+      p.layout = function () {
+          var pickerHTML = '';
+          var pickerClass = '';
+          var i;
+          p.cols = [];
+          var colsHTML = '';
+          for (i = 0; i < p.params.cols.length; i++) {
+              var col = p.params.cols[i];
+              colsHTML += p.columnHTML(p.params.cols[i]);
+              p.cols.push(col);
+          }
+          pickerClass = 'weui-picker-modal picker-columns ' + (p.params.cssClass || '') + (p.params.rotateEffect ? ' picker-3d' : '') + (p.params.cols.length === 1 ? ' picker-columns-single' : '');
+          pickerHTML =
+              '<div class="' + (pickerClass) + '">' +
+                  (p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText).replace(/{{title}}/g, p.params.title) : '') +
+                  '<div class="picker-modal-inner picker-items">' +
+                      colsHTML +
+                      '<div class="picker-center-highlight"></div>' +
+                  '</div>' +
+              '</div>';
+              
+          p.pickerHTML = pickerHTML;    
+      };
+
+      // Input Events
+      function openOnInput(e) {
+          e.preventDefault();
+          if (p.opened) return;
+          p.open();
+          if (p.params.scrollToInput && !isPopover()) {
+              var pageContent = p.input.parents('.content');
+              if (pageContent.length === 0) return;
+
+              var paddingTop = parseInt(pageContent.css('padding-top'), 10),
+                  paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
+                  pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
+                  pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
+                  newPaddingBottom;
+              var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
+              if (inputTop > pageHeight) {
+                  var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
+                  if (scrollTop + pageHeight > pageScrollHeight) {
+                      newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
+                      if (pageHeight === pageScrollHeight) {
+                          newPaddingBottom = p.container.height();
+                      }
+                      pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
+                  }
+                  pageContent.scrollTop(scrollTop, 300);
+              }
+          }
+      }
+      function closeOnHTMLClick(e) {
+          if (inPopover()) return;
+          if (p.input && p.input.length > 0) {
+              if (e.target !== p.input[0] && $(e.target).parents('.weui-picker-modal').length === 0) p.close();
+          }
+          else {
+              if ($(e.target).parents('.weui-picker-modal').length === 0) p.close();   
+          }
+      }
+
+      if (p.params.input) {
+          p.input = $(p.params.input);
+          if (p.input.length > 0) {
+              if (p.params.inputReadOnly) p.input.prop('readOnly', true);
+              if (!p.inline) {
+                  p.input.on('click', openOnInput);    
+              }
+              if (p.params.inputReadOnly) {
+                  p.input.on('focus mousedown', function (e) {
+                      e.preventDefault();
+                  });
+              }
+          }
+              
+      }
+      
+      if (!p.inline) $('html').on('click', closeOnHTMLClick);
+
+      // Open
+      function onPickerClose() {
+          p.opened = false;
+          if (p.input && p.input.length > 0) p.input.parents('.page-content').css({'padding-bottom': ''});
+          if (p.params.onClose) p.params.onClose(p);
+
+          // Destroy events
+          p.container.find('.picker-items-col').each(function () {
+              p.destroyPickerCol(this);
+          });
+      }
+
+      p.opened = false;
+      p.open = function () {
+          var toPopover = isPopover();
+
+          if (!p.opened) {
+
+              // Layout
+              p.layout();
+
+              // Append
+              if (toPopover) {
+                  p.pickerHTML = '<div class="popover popover-picker-columns"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
+                  p.popover = $.popover(p.pickerHTML, p.params.input, true);
+                  p.container = $(p.popover).find('.weui-picker-modal');
+                  $(p.popover).on('close', function () {
+                      onPickerClose();
+                  });
+              }
+              else if (p.inline) {
+                  p.container = $(p.pickerHTML);
+                  p.container.addClass('picker-modal-inline');
+                  $(p.params.container).append(p.container);
+              }
+              else {
+                  p.container = $($.openPicker(p.pickerHTML));
+                  $(p.container)
+                  .on('close', function () {
+                      onPickerClose();
+                  });
+              }
+
+              // Store picker instance
+              p.container[0].f7Picker = p;
+
+              // Init Events
+              p.container.find('.picker-items-col').each(function () {
+                  var updateItems = true;
+                  if ((!p.initialized && p.params.value) || (p.initialized && p.value)) updateItems = false;
+                  p.initPickerCol(this, updateItems);
+              });
+              
+              // Set value
+              if (!p.initialized) {
+                  if (p.params.value) {
+                      p.setValue(p.params.value, 0);
+                  }
+              }
+              else {
+                  if (p.value) p.setValue(p.value, 0);
+              }
+          }
+
+          // Set flag
+          p.opened = true;
+          p.initialized = true;
+
+          if (p.params.onOpen) p.params.onOpen(p);
+      };
+
+      // Close
+      p.close = function (force) {
+          if (!p.opened || p.inline) return;
+          if (inPopover()) {
+              $.closePicker(p.popover);
+              return;
+          }
+          else {
+              $.closePicker(p.container);
+              return;
+          }
+      };
+
+      // Destroy
+      p.destroy = function () {
+          p.close();
+          if (p.params.input && p.input.length > 0) {
+              p.input.off('click focus', openOnInput);
+              $(p.input).data('picker', null);
+          }
+          $('html').off('click', closeOnHTMLClick);
+          $(window).off('resize', resizeCols);
+      };
+
+      if (p.inline) {
+          p.open();
+      }
+
+      return p;
+  };
+
+  $(document).on("click", ".close-picker", function() {
+    var pickerToClose = $('.weui-picker-modal.weui-picker-modal-visible');
+    if (pickerToClose.length > 0) {
+      $.closePicker(pickerToClose);
+    }
+  });
+
+  //修复picker会滚动页面的bug
+  $(document).on($.touchEvents.move, ".picker-modal-inner", function(e) {
+    e.preventDefault();
+  });
+
+
+  $.openPicker = function(tpl, className, callback) {
+
+    if(typeof className === "function") {
+      callback = className;
+      className = undefined;
+    }
+
+    $.closePicker();
+
+    var container = $("<div class='weui-picker-container "+ (className || "") + "'></div>").appendTo(document.body);
+    container.show();
+
+    container.addClass("weui-picker-container-visible");
+
+    //关于布局的问题,如果直接放在body上,则做动画的时候会撑开body高度而导致滚动条变化。
+    var dialog = $(tpl).appendTo(container);
+    
+    dialog.width(); //通过取一次CSS值,强制浏览器不能把上下两行代码合并执行,因为合并之后会导致无法出现动画。
+
+    dialog.addClass("weui-picker-modal-visible");
+
+    callback && container.on("close", callback);
+
+    return dialog;
+  }
+
+  $.updatePicker = function(tpl) {
+    var container = $(".weui-picker-container-visible");
+    if(!container[0]) return false;
+
+    container.html("");
+
+    var dialog = $(tpl).appendTo(container);
+
+    dialog.addClass("weui-picker-modal-visible");
+
+    return dialog;
+  }
+
+  $.closePicker = function(container, callback) {
+    if(typeof container === "function") callback = container;
+    $(".weui-picker-modal-visible").removeClass("weui-picker-modal-visible").transitionEnd(function() {
+      $(this).parent().remove();
+      callback && callback();
+    }).trigger("close");
+  };
+
+  $.fn.picker = function(params) {
+    var args = arguments;
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      
+      var picker = $this.data("picker");
+      if(!picker) {
+        params = $.extend({ input: this }, params || {}) // https://github.com/lihongxun945/jquery-weui/issues/432
+        var inputValue = $this.val();
+        if(params.value === undefined && inputValue !== "") {
+          params.value = (params.cols && params.cols.length > 1) ? inputValue.split(" ") : [inputValue];
+        }
+        var p = $.extend({input: this}, params);
+        picker = new Picker(p);
+        $this.data("picker", picker);
+      }
+      if(typeof params === typeof "a") {
+        picker[params].apply(picker, Array.prototype.slice.call(args, 1));
+      }
+    });
+  };
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+
+  var defaults;
+
+  var selects = [];
+
+  var Select = function(input, config) {
+
+    var self = this;
+    this.config = config;
+
+    //init empty data
+    this.data = {
+      values: '',
+      titles: '',
+      origins: [],
+      length: 0
+    };
+
+    this.$input = $(input);
+    this.$input.prop("readOnly", true);
+
+    this.initConfig();
+
+    config = this.config;
+
+    this.$input.click($.proxy(this.open, this));
+    selects.push(this)
+  }
+
+  Select.prototype.initConfig = function() {
+    this.config = $.extend({}, defaults, this.config);
+
+    var config = this.config;
+
+    if(!config.items || !config.items.length) return;
+
+    config.items = config.items.map(function(d, i) {
+      if(typeof d == typeof "a") {
+        return {
+          title: d,
+          value: d
+        };
+      }
+
+      return d;
+    });
+
+
+    this.tpl = $.t7.compile("<div class='weui-picker-modal weui-select-modal'>" + config.toolbarTemplate + (config.multi ? config.checkboxTemplate : config.radioTemplate) + "</div>");
+
+    if(config.input !== undefined) this.$input.val(config.input);
+
+    this.parseInitValue();
+
+    this._init = true;
+  }
+
+  Select.prototype.updateInputValue = function(values, titles) {
+    var v, t;
+    if(this.config.multi) {
+      v = values.join(this.config.split);
+      t = titles.join(this.config.split);
+    } else {
+      v = values[0];
+      t = titles[0];
+    }
+
+    //caculate origin data
+    var origins = [];
+
+    this.config.items.forEach(function(d) {
+      values.each(function(i, dd) {
+        if(d.value == dd) origins.push(d);
+      });
+    });
+
+    this.$input.val(t).data("values", v);
+    this.$input.attr("value", t).attr("data-values", v);
+
+    var data = {
+      values: v,
+      titles: t,
+      valuesArray: values,
+      titlesArray: titles,
+      origins: origins,
+      length: origins.length
+    };
+    this.data = data;
+    this.$input.trigger("change", data);
+    this.config.onChange && this.config.onChange.call(this, data);
+  }
+
+  Select.prototype.parseInitValue = function() {
+    var value = this.$input.val();
+    var items = this.config.items;
+
+    //如果input为空,只有在第一次初始化的时候才保留默认选择。因为后来就是用户自己取消了全部选择,不能再为他选中默认值。
+    if( !this._init && (value === undefined || value == null || value === "")) return;
+
+    var titles = this.config.multi ? value.split(this.config.split) : [value];
+    for(var i=0;i<items.length;i++) {
+      items[i].checked = false;
+      for(var j=0;j<titles.length;j++) {
+        if(items[i].title === titles[j]) {
+          items[i].checked = true;
+        }
+      }
+    }
+  }
+
+  Select.prototype._bind = function(dialog) {
+    var self = this,
+        config = this.config;
+    dialog.on("change", function(e) {
+      var checked = dialog.find("input:checked");
+      var values = checked.map(function() {
+        return $(this).val();
+      });
+      var titles = checked.map(function() {
+        return $(this).data("title");
+      });
+      self.updateInputValue(values, titles);
+
+      if(config.autoClose && !config.multi) self.close();
+    })
+    .trigger('change')
+    .on("click", ".close-select", function() {
+      self.close();
+    });
+  }
+
+  //更新数据
+  Select.prototype.update = function(config) {
+    this.config = $.extend({}, this.config, config);
+    this.initConfig();
+    if(this._open) {
+      this._bind($.updatePicker(this.getHTML()));
+    }
+  }
+  
+  Select.prototype.open = function(values, titles) {
+
+    if(this._open) return;
+
+    // open picker 会默认关掉其他的,但是 onClose 不会被调用,所以这里先关掉其他select
+    for (var i = 0; i < selects.length; i++ ) {
+      var s = selects[i];
+      if (s === this) continue;
+      if (s._open) {
+        if(!s.close()) return false; // 其他的select由于某些条件限制关闭失败。
+      }
+    }
+
+    this.parseInitValue();
+
+    var config = this.config;
+
+    var dialog = this.dialog = $.openPicker(this.getHTML());
+    
+    this._bind(dialog);
+
+    this._open = true;
+    if(config.onOpen) config.onOpen(this);
+  }
+
+  Select.prototype.close = function(callback, force) {
+    if (!this._open) return false;
+    var self = this,
+        beforeClose = this.config.beforeClose;
+
+    if(typeof callback === typeof true) {
+      force === callback;
+    }
+    if(!force) {
+      if(beforeClose && typeof beforeClose === 'function' && beforeClose.call(this, this.data.values, this.data.titles) === false) {
+        return false
+      }
+      if(this.config.multi) {
+        if(this.config.min !== undefined && this.data.length < this.config.min) {
+          $.toast("请至少选择"+this.config.min+"个", "text");
+          return false
+        }
+        if(this.config.max !== undefined && this.data.length > this.config.max) {
+          $.toast("最多只能选择"+this.config.max+"个", "text");
+          return false
+        }
+      }
+    }
+    $.closePicker(function() {
+      self.onClose();
+      callback && callback();
+    });
+
+    return true
+  }
+
+  Select.prototype.onClose = function() {
+    this._open = false;
+    if(this.config.onClose) this.config.onClose(this);
+  }
+
+  Select.prototype.getHTML = function(callback) {
+    var config = this.config;
+    return this.tpl({
+      items: config.items,
+      title: config.title,
+      closeText: config.closeText
+    })
+  }
+
+
+  $.fn.select = function(params, args) {
+
+    return this.each(function() {
+      var $this = $(this);
+      if(!$this.data("weui-select")) $this.data("weui-select", new Select(this, params));
+
+      var select = $this.data("weui-select");
+
+      if(typeof params === typeof "a") select[params].call(select, args);
+
+      return select;
+    });
+  }
+
+  defaults = $.fn.select.prototype.defaults = {
+    items: [],
+    input: undefined, //输入框的初始值
+    title: "请选择",
+    multi: false,
+    closeText: "确定",
+    autoClose: true, //是否选择完成后自动关闭,只有单选模式下才有效
+    onChange: undefined, //function
+    beforeClose: undefined, // function 关闭之前,如果返回false则阻止关闭
+    onClose: undefined, //function
+    onOpen: undefined, //function
+    split: ",",  //多选模式下的分隔符
+    min: undefined, //多选模式下可用,最少选择数
+    max: undefined, //单选模式下可用,最多选择数
+    toolbarTemplate: '<div class="toolbar">\
+      <div class="toolbar-inner">\
+      <a href="javascript:;" class="picker-button close-select">{{closeText}}</a>\
+      <h1 class="title">{{title}}</h1>\
+      </div>\
+      </div>',
+    radioTemplate:
+      '<div class="weui-cells weui-cells_radio">\
+        {{#items}}\
+        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
+          <div class="weui-cell__bd weui-cell_primary">\
+            <p>{{this.title}}</p>\
+          </div>\
+          <div class="weui-cell__ft">\
+            <input type="radio" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}">\
+            <span class="weui-icon-checked"></span>\
+          </div>\
+        </label>\
+        {{/items}}\
+      </div>',
+    checkboxTemplate:
+      '<div class="weui-cells weui-cells_checkbox">\
+        {{#items}}\
+        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">\
+          <div class="weui-cell__bd weui-cell_primary">\
+            <p>{{this.title}}</p>\
+          </div>\
+          <div class="weui-cell__ft">\
+            <input type="checkbox" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}" >\
+            <span class="weui-icon-checked"></span>\
+          </div>\
+        </label>\
+        {{/items}}\
+      </div>',
+  }
+
+}($);
+
+/*======================================================
+************   Calendar   ************
+======================================================*/
+/* global $:true */
+/*jshint unused: false*/
++function ($) {
+  "use strict";
+  var rtl = false;
+  var defaults;
+  var isSameDate = function (a, b) {
+    var a = new Date(a),
+      b = new Date(b);
+    return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()
+  }
+  var Calendar = function (params) {
+      var p = this;
+      params = params || {};
+      for (var def in defaults) {
+          if (typeof params[def] === 'undefined') {
+              params[def] = defaults[def];
+          }
+      }
+      p.params = params;
+      p.initialized = false;
+
+      // Inline flag
+      p.inline = p.params.container ? true : false;
+
+      // Is horizontal
+      p.isH = p.params.direction === 'horizontal';
+
+      // RTL inverter
+      var inverter = p.isH ? (rtl ? -1 : 1) : 1;
+
+      // Animating flag
+      p.animating = false;
+
+      // Should be converted to popover
+      function isPopover() {
+          var toPopover = false;
+          if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
+          if (!p.inline && p.params.input) {
+              if (p.params.onlyInPopover) toPopover = true;
+              else {
+                  if ($.device.ios) {
+                      toPopover = $.device.ipad ? true : false;
+                  }
+                  else {
+                      if ($(window).width() >= 768) toPopover = true;
+                  }
+              }
+          } 
+          return toPopover; 
+      }
+      function inPopover() {
+          if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
+          else return false;
+      }
+
+      // Format date
+      function formatDate(date) {
+          date = new Date(date);
+          var year = date.getFullYear();
+          var month = date.getMonth();
+          var month1 = month + 1;
+          var day = date.getDate();
+          var weekDay = date.getDay();
+          return p.params.dateFormat
+              .replace(/yyyy/g, year)
+              .replace(/yy/g, (year + '').substring(2))
+              .replace(/mm/g, month1 < 10 ? '0' + month1 : month1)
+              .replace(/m/g, month1)
+              .replace(/MM/g, p.params.monthNames[month])
+              .replace(/M/g, p.params.monthNamesShort[month])
+              .replace(/dd/g, day < 10 ? '0' + day : day)
+              .replace(/d/g, day)
+              .replace(/DD/g, p.params.dayNames[weekDay])
+              .replace(/D/g, p.params.dayNamesShort[weekDay]);
+      }
+
+
+      // Value
+      p.addValue = function (value) {
+          if (p.params.multiple) {
+              if (!p.value) p.value = [];
+              var inValuesIndex;
+              for (var i = 0; i < p.value.length; i++) {
+                  if (isSameDate(value, p.value[i])) {
+                      inValuesIndex = i;
+                  }
+              }
+              if (typeof inValuesIndex === 'undefined') {
+                  p.value.push(value);
+              }
+              else {
+                  p.value.splice(inValuesIndex, 1);
+              }
+              p.updateValue();
+          }
+          else {
+              p.value = [value];
+              p.updateValue();
+          }
+      };
+      p.setValue = function (arrValues) {
+        var date = new Date(arrValues[0]);
+        p.setYearMonth(date.getFullYear(), date.getMonth());
+        p.addValue(+ date);
+      };
+      p.updateValue = function () {
+          p.wrapper.find('.picker-calendar-day-selected').removeClass('picker-calendar-day-selected');
+          var i, inputValue;
+          for (i = 0; i < p.value.length; i++) {
+              var valueDate = new Date(p.value[i]);
+              p.wrapper.find('.picker-calendar-day[data-date="' + valueDate.getFullYear() + '-' + valueDate.getMonth() + '-' + valueDate.getDate() + '"]').addClass('picker-calendar-day-selected');
+          }
+          if (p.params.onChange) {
+            p.params.onChange(p, p.value.map(formatDate), p.value.map(function (d) {
+              return + new Date(typeof d === typeof 'a' ? d.split(/\D/).filter(function (a) { return !!a; }).join("-") : d);
+            }));
+          }
+          if (p.input && p.input.length > 0) {
+              if (p.params.formatValue) inputValue = p.params.formatValue(p, p.value);
+              else {
+                  inputValue = [];
+                  for (i = 0; i < p.value.length; i++) {
+                      inputValue.push(formatDate(p.value[i]));
+                  }
+                  inputValue = inputValue.join(', ');
+              } 
+              $(p.input).val(inputValue);
+              $(p.input).trigger('change');
+          }
+      };
+
+      // Columns Handlers
+      p.initCalendarEvents = function () {
+          var col;
+          var allowItemClick = true;
+          var isTouched, isMoved, touchStartX, touchStartY, touchCurrentX, touchCurrentY, touchStartTime, touchEndTime, startTranslate, currentTranslate, wrapperWidth, wrapperHeight, percentage, touchesDiff, isScrolling;
+          function handleTouchStart (e) {
+              if (isMoved || isTouched) return;
+              // e.preventDefault();
+              isTouched = true;
+              var position = $.getTouchPosition(e);
+              touchStartX = touchCurrentY = position.x;
+              touchStartY = touchCurrentY = position.y;
+              touchStartTime = (new Date()).getTime();
+              percentage = 0;
+              allowItemClick = true;
+              isScrolling = undefined;
+              startTranslate = currentTranslate = p.monthsTranslate;
+          }
+          function handleTouchMove (e) {
+              if (!isTouched) return;
+              var position = $.getTouchPosition(e);
+              touchCurrentX = position.x;
+              touchCurrentY = position.y;
+              if (typeof isScrolling === 'undefined') {
+                  isScrolling = !!(isScrolling || Math.abs(touchCurrentY - touchStartY) > Math.abs(touchCurrentX - touchStartX));
+              }
+              if (p.isH && isScrolling) {
+                  isTouched = false;
+                  return;
+              }
+              e.preventDefault();
+              if (p.animating) {
+                  isTouched = false;
+                  return;   
+              }
+              allowItemClick = false;
+              if (!isMoved) {
+                  // First move
+                  isMoved = true;
+                  wrapperWidth = p.wrapper[0].offsetWidth;
+                  wrapperHeight = p.wrapper[0].offsetHeight;
+                  p.wrapper.transition(0);
+              }
+              e.preventDefault();
+
+              touchesDiff = p.isH ? touchCurrentX - touchStartX : touchCurrentY - touchStartY;
+              percentage = touchesDiff/(p.isH ? wrapperWidth : wrapperHeight);
+              currentTranslate = (p.monthsTranslate * inverter + percentage) * 100;
+
+              // Transform wrapper
+              p.wrapper.transform('translate3d(' + (p.isH ? currentTranslate : 0) + '%, ' + (p.isH ? 0 : currentTranslate) + '%, 0)');
+
+          }
+          function handleTouchEnd (e) {
+              if (!isTouched || !isMoved) {
+                  isTouched = isMoved = false;
+                  return;
+              }
+              isTouched = isMoved = false;
+              
+              touchEndTime = new Date().getTime();
+              if (touchEndTime - touchStartTime < 300) {
+                  if (Math.abs(touchesDiff) < 10) {
+                      p.resetMonth();
+                  }
+                  else if (touchesDiff >= 10) {
+                      if (rtl) p.nextMonth();
+                      else p.prevMonth();
+                  }
+                  else {
+                      if (rtl) p.prevMonth();
+                      else p.nextMonth();   
+                  }
+              }
+              else {
+                  if (percentage <= -0.5) {
+                      if (rtl) p.prevMonth();
+                      else p.nextMonth();
+                  }
+                  else if (percentage >= 0.5) {
+                      if (rtl) p.nextMonth();
+                      else p.prevMonth();
+                  }
+                  else {
+                      p.resetMonth();
+                  }
+              }
+
+              // Allow click
+              setTimeout(function () {
+                  allowItemClick = true;
+              }, 100);
+          }
+
+          function handleDayClick(e) {
+              if (!allowItemClick) return;
+              var day = $(e.target).parents('.picker-calendar-day');
+              if (day.length === 0 && $(e.target).hasClass('picker-calendar-day')) {
+                  day = $(e.target);
+              }
+              if (day.length === 0) return;
+              // if (day.hasClass('picker-calendar-day-selected') && !p.params.multiple) return;
+              if (day.hasClass('picker-calendar-day-disabled')) return;
+              if (day.hasClass('picker-calendar-day-next')) p.nextMonth();
+              if (day.hasClass('picker-calendar-day-prev')) p.prevMonth();
+              var dateYear = day.attr('data-year');
+              var dateMonth = day.attr('data-month');
+              var dateDay = day.attr('data-day');
+              if (p.params.onDayClick) {
+                  p.params.onDayClick(p, day[0], dateYear, dateMonth, dateDay);
+              }
+              p.addValue(new Date(dateYear, dateMonth, dateDay).getTime());
+              if (p.params.closeOnSelect && !p.params.multiple) p.close();
+          }
+
+          p.container.find('.picker-calendar-prev-month').on('click', p.prevMonth);
+          p.container.find('.picker-calendar-next-month').on('click', p.nextMonth);
+          p.container.find('.picker-calendar-prev-year').on('click', p.prevYear);
+          p.container.find('.picker-calendar-next-year').on('click', p.nextYear);
+          p.wrapper.on('click', handleDayClick);
+          if (p.params.touchMove) {
+              p.wrapper.on($.touchEvents.start, handleTouchStart);
+              p.wrapper.on($.touchEvents.move, handleTouchMove);
+              p.wrapper.on($.touchEvents.end, handleTouchEnd);
+          }
+              
+          p.container[0].f7DestroyCalendarEvents = function () {
+              p.container.find('.picker-calendar-prev-month').off('click', p.prevMonth);
+              p.container.find('.picker-calendar-next-month').off('click', p.nextMonth);
+              p.container.find('.picker-calendar-prev-year').off('click', p.prevYear);
+              p.container.find('.picker-calendar-next-year').off('click', p.nextYear);
+              p.wrapper.off('click', handleDayClick);
+              if (p.params.touchMove) {
+                  p.wrapper.off($.touchEvents.start, handleTouchStart);
+                  p.wrapper.off($.touchEvents.move, handleTouchMove);
+                  p.wrapper.off($.touchEvents.end, handleTouchEnd);
+              }
+          };
+          
+
+      };
+      p.destroyCalendarEvents = function (colContainer) {
+          if ('f7DestroyCalendarEvents' in p.container[0]) p.container[0].f7DestroyCalendarEvents();
+      };
+
+      // Calendar Methods
+      p.daysInMonth = function (date) {
+          var d = new Date(date);
+          return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
+      };
+      p.monthHTML = function (date, offset) {
+          date = new Date(date);
+          var year = date.getFullYear(),
+              month = date.getMonth(),
+              day = date.getDate();
+          if (offset === 'next') {
+              if (month === 11) date = new Date(year + 1, 0);
+              else date = new Date(year, month + 1, 1);
+          }
+          if (offset === 'prev') {
+              if (month === 0) date = new Date(year - 1, 11);
+              else date = new Date(year, month - 1, 1);
+          }
+          if (offset === 'next' || offset === 'prev') {
+              month = date.getMonth();
+              year = date.getFullYear();
+          }
+          var daysInPrevMonth = p.daysInMonth(new Date(date.getFullYear(), date.getMonth()).getTime() - 10 * 24 * 60 * 60 * 1000),
+              daysInMonth = p.daysInMonth(date),
+              firstDayOfMonthIndex = new Date(date.getFullYear(), date.getMonth()).getDay();
+          if (firstDayOfMonthIndex === 0) firstDayOfMonthIndex = 7;
+          
+          var dayDate, currentValues = [], i, j,
+              rows = 6, cols = 7,
+              monthHTML = '',
+              dayIndex = 0 + (p.params.firstDay - 1),    
+              today = new Date().setHours(0,0,0,0),
+              minDate = p.params.minDate ? new Date(p.params.minDate).getTime() : null,
+              maxDate = p.params.maxDate ? new Date(p.params.maxDate).getTime() : null;
+
+          if (p.value && p.value.length) {
+              for (i = 0; i < p.value.length; i++) {
+                  currentValues.push(new Date(p.value[i]).setHours(0,0,0,0));
+              }
+          }
+              
+          for (i = 1; i <= rows; i++) {
+              var rowHTML = '';
+              var row = i;
+              for (j = 1; j <= cols; j++) {
+                  var col = j;
+                  dayIndex ++;
+                  var dayNumber = dayIndex - firstDayOfMonthIndex;
+                  var addClass = '';
+                  if (dayNumber < 0) {
+                      dayNumber = daysInPrevMonth + dayNumber + 1;
+                      addClass += ' picker-calendar-day-prev';
+                      dayDate = new Date(month - 1 < 0 ? year - 1 : year, month - 1 < 0 ? 11 : month - 1, dayNumber).getTime();
+                  }
+                  else {
+                      dayNumber = dayNumber + 1;
+                      if (dayNumber > daysInMonth) {
+                          dayNumber = dayNumber - daysInMonth;
+                          addClass += ' picker-calendar-day-next';
+                          dayDate = new Date(month + 1 > 11 ? year + 1 : year, month + 1 > 11 ? 0 : month + 1, dayNumber).getTime();
+                      }
+                      else {
+                          dayDate = new Date(year, month, dayNumber).getTime();    
+                      }
+                  }
+                  // Today
+                  if (dayDate === today) addClass += ' picker-calendar-day-today';
+                  // Selected
+                  if (currentValues.indexOf(dayDate) >= 0) addClass += ' picker-calendar-day-selected';
+                  // Weekend
+                  if (p.params.weekendDays.indexOf(col - 1) >= 0) {
+                      addClass += ' picker-calendar-day-weekend';
+                  }
+                  // Disabled
+                  if ((minDate && dayDate < minDate) || (maxDate && dayDate > maxDate)) {
+                      addClass += ' picker-calendar-day-disabled';   
+                  }
+
+                  dayDate = new Date(dayDate);
+                  var dayYear = dayDate.getFullYear();
+                  var dayMonth = dayDate.getMonth();
+                  rowHTML += '<div data-year="' + dayYear + '" data-month="' + dayMonth + '" data-day="' + dayNumber + '" class="picker-calendar-day' + (addClass) + '" data-date="' + (dayYear + '-' + dayMonth + '-' + dayNumber) + '"><span>'+dayNumber+'</span></div>';
+              }
+              monthHTML += '<div class="picker-calendar-row">' + rowHTML + '</div>';
+          }
+          monthHTML = '<div class="picker-calendar-month" data-year="' + year + '" data-month="' + month + '">' + monthHTML + '</div>';
+          return monthHTML;
+      };
+      p.animating = false;
+      p.updateCurrentMonthYear = function (dir) {
+          if (typeof dir === 'undefined') {
+              p.currentMonth = parseInt(p.months.eq(1).attr('data-month'), 10);
+              p.currentYear = parseInt(p.months.eq(1).attr('data-year'), 10);   
+          }
+          else {
+              p.currentMonth = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-month'), 10);
+              p.currentYear = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-year'), 10);
+          }
+          p.container.find('.current-month-value').text(p.params.monthNames[p.currentMonth]);
+          p.container.find('.current-year-value').text(p.currentYear);
+              
+      };
+      p.onMonthChangeStart = function (dir) {
+          p.updateCurrentMonthYear(dir);
+          p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
+          var currentIndex = dir === 'next' ? p.months.length - 1 : 0;
+
+          p.months.eq(currentIndex).addClass('picker-calendar-month-current');
+          p.months.eq(dir === 'next' ? currentIndex - 1 : currentIndex + 1).addClass(dir === 'next' ? 'picker-calendar-month-prev' : 'picker-calendar-month-next');
+
+          if (p.params.onMonthYearChangeStart) {
+              p.params.onMonthYearChangeStart(p, p.currentYear, p.currentMonth);
+          }
+      };
+      p.onMonthChangeEnd = function (dir, rebuildBoth) {
+          p.animating = false;
+          var nextMonthHTML, prevMonthHTML, newMonthHTML;
+          p.wrapper.find('.picker-calendar-month:not(.picker-calendar-month-prev):not(.picker-calendar-month-current):not(.picker-calendar-month-next)').remove();
+          
+          if (typeof dir === 'undefined') {
+              dir = 'next';
+              rebuildBoth = true;
+          }
+          if (!rebuildBoth) {
+              newMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), dir);
+          }
+          else {
+              p.wrapper.find('.picker-calendar-month-next, .picker-calendar-month-prev').remove();
+              prevMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'prev');
+              nextMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'next');
+          }
+          if (dir === 'next' || rebuildBoth) {
+              p.wrapper.append(newMonthHTML || nextMonthHTML);
+          }
+          if (dir === 'prev' || rebuildBoth) {
+              p.wrapper.prepend(newMonthHTML || prevMonthHTML);
+          }
+          p.months = p.wrapper.find('.picker-calendar-month');
+          p.setMonthsTranslate(p.monthsTranslate);
+          if (p.params.onMonthAdd) {
+              p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
+          }
+          if (p.params.onMonthYearChangeEnd) {
+              p.params.onMonthYearChangeEnd(p, p.currentYear, p.currentMonth);
+          }
+      };
+      p.setMonthsTranslate = function (translate) {
+          translate = translate || p.monthsTranslate || 0;
+          if (typeof p.monthsTranslate === 'undefined') p.monthsTranslate = translate;
+          p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
+          var prevMonthTranslate = -(translate + 1) * 100 * inverter;
+          var currentMonthTranslate = -translate * 100 * inverter;
+          var nextMonthTranslate = -(translate - 1) * 100 * inverter;
+          p.months.eq(0).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+          p.months.eq(1).transform('translate3d(' + (p.isH ? currentMonthTranslate : 0) + '%, ' + (p.isH ? 0 : currentMonthTranslate) + '%, 0)').addClass('picker-calendar-month-current');
+          p.months.eq(2).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+      };
+      p.nextMonth = function (transition) {
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var nextMonth = parseInt(p.months.eq(p.months.length - 1).attr('data-month'), 10);
+          var nextYear = parseInt(p.months.eq(p.months.length - 1).attr('data-year'), 10);
+          var nextDate = new Date(nextYear, nextMonth);
+          var nextDateTime = nextDate.getTime();
+          var transitionEndCallback = p.animating ? false : true;
+          if (p.params.maxDate) {
+              if (nextDateTime > new Date(p.params.maxDate).getTime()) {
+                  return p.resetMonth();
+              }
+          }
+          p.monthsTranslate --;
+          if (nextMonth === p.currentMonth) {
+              var nextMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
+              var nextMonthHTML = $(p.monthHTML(nextDateTime, 'next')).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+              p.wrapper.append(nextMonthHTML[0]);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              if (p.params.onMonthAdd) {
+                  p.params.onMonthAdd(p, p.months.eq(p.months.length - 1)[0]);
+              }
+          }
+          p.animating = true;
+          p.onMonthChangeStart('next');
+          var translate = (p.monthsTranslate * 100) * inverter;
+
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+          if (transitionEndCallback) {
+              p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd('next');
+              });
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd('next');
+          }
+      };
+      p.prevMonth = function (transition) {
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var prevMonth = parseInt(p.months.eq(0).attr('data-month'), 10);
+          var prevYear = parseInt(p.months.eq(0).attr('data-year'), 10);
+          var prevDate = new Date(prevYear, prevMonth + 1, -1);
+          var prevDateTime = prevDate.getTime();
+          var transitionEndCallback = p.animating ? false : true;
+          if (p.params.minDate) {
+              if (prevDateTime < new Date(p.params.minDate).getTime()) {
+                  return p.resetMonth();
+              }
+          }
+          p.monthsTranslate ++;
+          if (prevMonth === p.currentMonth) {
+              var prevMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
+              var prevMonthHTML = $(p.monthHTML(prevDateTime, 'prev')).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+              p.wrapper.prepend(prevMonthHTML[0]);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              if (p.params.onMonthAdd) {
+                  p.params.onMonthAdd(p, p.months.eq(0)[0]);
+              }
+          }
+          p.animating = true;
+          p.onMonthChangeStart('prev');
+          var translate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+          if (transitionEndCallback) {
+              p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd('prev');
+              });
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd('prev');
+          }
+      };
+      p.resetMonth = function (transition) {
+          if (typeof transition === 'undefined') transition = '';
+          var translate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
+      };
+      p.setYearMonth = function (year, month, transition) {
+          if (typeof year === 'undefined') year = p.currentYear;
+          if (typeof month === 'undefined') month = p.currentMonth;
+          if (typeof transition === 'undefined' || typeof transition === 'object') {
+              transition = '';
+              if (!p.params.animate) transition = 0;
+          }
+          var targetDate;
+          if (year < p.currentYear) {
+              targetDate = new Date(year, month + 1, -1).getTime();
+          }
+          else {
+              targetDate = new Date(year, month).getTime();
+          }
+          if (p.params.maxDate && targetDate > new Date(p.params.maxDate).getTime()) {
+              return false;
+          }
+          if (p.params.minDate && targetDate < new Date(p.params.minDate).getTime()) {
+              return false;
+          }
+          var currentDate = new Date(p.currentYear, p.currentMonth).getTime();
+          var dir = targetDate > currentDate ? 'next' : 'prev';
+          var newMonthHTML = p.monthHTML(new Date(year, month));
+          p.monthsTranslate = p.monthsTranslate || 0;
+          var prevTranslate = p.monthsTranslate;
+          var monthTranslate, wrapperTranslate;
+          var transitionEndCallback = p.animating ? false : true;
+          if (targetDate > currentDate) {
+              // To next
+              p.monthsTranslate --;
+              if (!p.animating) p.months.eq(p.months.length - 1).remove();
+              p.wrapper.append(newMonthHTML);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              monthTranslate = -(prevTranslate - 1) * 100 * inverter;
+              p.months.eq(p.months.length - 1).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
+          }
+          else {
+              // To prev
+              p.monthsTranslate ++;
+              if (!p.animating) p.months.eq(0).remove();
+              p.wrapper.prepend(newMonthHTML);
+              p.months = p.wrapper.find('.picker-calendar-month');
+              monthTranslate = -(prevTranslate + 1) * 100 * inverter;
+              p.months.eq(0).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
+          }
+          if (p.params.onMonthAdd) {
+              p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
+          }
+          p.animating = true;
+          p.onMonthChangeStart(dir);
+          wrapperTranslate = (p.monthsTranslate * 100) * inverter;
+          p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? wrapperTranslate : 0) + '%, ' + (p.isH ? 0 : wrapperTranslate) + '%, 0)');
+          if (transitionEndCallback) {
+             p.wrapper.transitionEnd(function () {
+                  p.onMonthChangeEnd(dir, true);
+              }); 
+          }
+          if (!p.params.animate) {
+              p.onMonthChangeEnd(dir);
+          }
+      };
+      p.nextYear = function () {
+          p.setYearMonth(p.currentYear + 1);
+      };
+      p.prevYear = function () {
+          p.setYearMonth(p.currentYear - 1);
+      };
+      
+
+      // HTML Layout
+      p.layout = function () {
+          var pickerHTML = '';
+          var pickerClass = '';
+          var i;
+          
+          var layoutDate = p.value && p.value.length ? p.value[0] : new Date().setHours(0,0,0,0);
+          var prevMonthHTML = p.monthHTML(layoutDate, 'prev');
+          var currentMonthHTML = p.monthHTML(layoutDate);
+          var nextMonthHTML = p.monthHTML(layoutDate, 'next');
+          var monthsHTML = '<div class="picker-calendar-months"><div class="picker-calendar-months-wrapper">' + (prevMonthHTML + currentMonthHTML + nextMonthHTML) + '</div></div>';
+          // Week days header
+          var weekHeaderHTML = '';
+          if (p.params.weekHeader) {
+              for (i = 0; i < 7; i++) {
+                  var weekDayIndex = (i + p.params.firstDay > 6) ? (i - 7 + p.params.firstDay) : (i + p.params.firstDay);
+                  var dayName = p.params.dayNamesShort[weekDayIndex];
+                  weekHeaderHTML += '<div class="picker-calendar-week-day ' + ((p.params.weekendDays.indexOf(weekDayIndex) >= 0) ? 'picker-calendar-week-day-weekend' : '') + '"> ' + dayName + '</div>';
+                  
+              }
+              weekHeaderHTML = '<div class="picker-calendar-week-days">' + weekHeaderHTML + '</div>';
+          }
+          pickerClass = 'weui-picker-calendar ' + (p.params.cssClass || '');
+          if(!p.inline) pickerClass = 'weui-picker-modal ' + pickerClass;
+          var toolbarHTML = p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '';
+          if (p.params.toolbar) {
+              toolbarHTML = p.params.toolbarTemplate
+                  .replace(/{{closeText}}/g, p.params.toolbarCloseText)
+                  .replace(/{{monthPicker}}/g, (p.params.monthPicker ? p.params.monthPickerTemplate : ''))
+                  .replace(/{{yearPicker}}/g, (p.params.yearPicker ? p.params.yearPickerTemplate : ''));
+          }
+
+          pickerHTML =
+              '<div class="' + (pickerClass) + '">' +
+                  toolbarHTML +
+                  '<div class="picker-modal-inner">' +
+                      weekHeaderHTML +
+                      monthsHTML +
+                  '</div>' +
+              '</div>';
+              
+              
+          p.pickerHTML = pickerHTML;    
+      };
+
+      // Input Events
+      function openOnInput(e) {
+          e.preventDefault();
+          if (p.opened) return;
+          p.open();
+          if (p.params.scrollToInput && !isPopover()) {
+              var pageContent = p.input.parents('.page-content');
+              if (pageContent.length === 0) return;
+
+              var paddingTop = parseInt(pageContent.css('padding-top'), 10),
+                  paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
+                  pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
+                  pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
+                  newPaddingBottom;
+
+              var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
+              if (inputTop > pageHeight) {
+                  var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
+                  if (scrollTop + pageHeight > pageScrollHeight) {
+                      newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
+                      if (pageHeight === pageScrollHeight) {
+                          newPaddingBottom = p.container.height();
+                      }
+                      pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
+                  }
+                  pageContent.scrollTop(scrollTop, 300);
+              }
+          }
+      }
+      function closeOnHTMLClick(e) {
+          if (inPopover()) return;
+          if (p.input && p.input.length > 0) {
+              if (e.target !== p.input[0] && $(e.target).parents('.weui-picker-modal').length === 0) p.close();
+          }
+          else {
+              if ($(e.target).parents('.weui-picker-modal').length === 0) p.close();   
+          }
+      }
+
+      if (p.params.input) {
+          p.input = $(p.params.input);
+          if (p.input.length > 0) {
+              if (p.params.inputReadOnly) p.input.prop('readOnly', true);
+              if (!p.inline) {
+                  p.input.on('click', openOnInput);    
+              }
+              if (p.params.inputReadOnly) {
+                  p.input.on('focus mousedown', function (e) {
+                      e.preventDefault();
+                  });
+              }
+          }
+              
+      }
+      
+      //iphone 上无法正确触发 click,会导致点击外面无法关闭
+      if (!p.inline) $(document).on('click touchend', closeOnHTMLClick);
+
+      // Open
+      function onPickerClose() {
+          p.opened = false;
+          if (p.input && p.input.length > 0) p.input.parents('.page-content').css({'padding-bottom': ''});
+          if (p.params.onClose) p.params.onClose(p);
+
+          // Destroy events
+          p.destroyCalendarEvents();
+      }
+
+      p.opened = false;
+      p.open = function () {
+          var toPopover = isPopover() && false;
+          var updateValue = false;
+          if (!p.opened) {
+              // Set date value
+              if (!p.value) {
+                  if (p.params.value) {
+                      p.value = p.params.value;
+                      updateValue = true;
+                  }
+              }
+
+              // Layout
+              p.layout();
+
+              // Append
+              if (toPopover) {
+                  p.pickerHTML = '<div class="popover popover-picker-calendar"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
+                  p.popover = $.popover(p.pickerHTML, p.params.input, true);
+                  p.container = $(p.popover).find('.weui-picker-modal');
+                  $(p.popover).on('close', function () {
+                      onPickerClose();
+                  });
+              }
+              else if (p.inline) {
+                  p.container = $(p.pickerHTML);
+                  p.container.addClass('picker-modal-inline');
+                  $(p.params.container).append(p.container);
+              }
+              else {
+                  p.container = $($.openPicker(p.pickerHTML));
+                  $(p.container)
+                  .on('close', function () {
+                      onPickerClose();
+                  });
+              }
+
+              // Store calendar instance
+              p.container[0].f7Calendar = p;
+              p.wrapper = p.container.find('.picker-calendar-months-wrapper');
+
+              // Months
+              p.months = p.wrapper.find('.picker-calendar-month');
+
+              // Update current month and year
+              p.updateCurrentMonthYear();
+
+              // Set initial translate
+              p.monthsTranslate = 0;
+              p.setMonthsTranslate();
+
+              // Init events
+              p.initCalendarEvents();
+
+              // Update input value
+              if (updateValue) p.updateValue();
+              
+          }
+
+          // Set flag
+          p.opened = true;
+          p.initialized = true;
+          if (p.params.onMonthAdd) {
+              p.months.each(function () {
+                  p.params.onMonthAdd(p, this);
+              });
+          }
+          if (p.params.onOpen) p.params.onOpen(p);
+      };
+
+      // Close
+      p.close = function () {
+          if (!p.opened || p.inline) return;
+          p.animating = false;  //有可能还有动画没做完,因此animating设置还没改。
+          if (inPopover()) {
+              $.closePicker(p.popover);
+              return;
+          }
+          else {
+              $.closePicker(p.container);
+              return;
+          }
+      };
+
+      // Destroy
+      p.destroy = function () {
+          p.close();
+          if (p.params.input && p.input.length > 0) {
+              p.input.off('click focus', openOnInput);
+              p.input.data("calendar", null);
+          }
+          $('html').off('click', closeOnHTMLClick);
+      };
+
+      if (p.inline) {
+          p.open();
+      }
+
+      return p;
+  };
+
+  var format = function(d) {
+    return d < 10 ? "0"+d : d;
+  }
+
+
+  $.fn.calendar = function (params, args) {
+      params = params || {};
+      return this.each(function() {
+        var $this = $(this);
+        if(!$this[0]) return;
+        var p = {};
+        if($this[0].tagName.toUpperCase() === "INPUT") {
+          p.input = $this;
+        } else {
+          p.container = $this;
+        }
+
+        var calendar = $this.data("calendar");
+
+        if(!calendar) {
+          if(typeof params === typeof "a") {
+          } else {
+            if(!params.value && $this.val()) params.value = [$this.val()];
+            //默认显示今天
+            if(!params.value) {
+              var today = new Date();
+              params.value = [today.getFullYear() + "/" + format(today.getMonth() + 1) + "/" + format(today.getDate())];
+            }
+            calendar = $this.data("calendar", new Calendar($.extend(p, params)));
+          }
+        }
+
+        if(typeof params === typeof "a") {
+          calendar[params].call(calendar, args);
+        }
+      });
+  };
+
+  defaults = $.fn.calendar.prototype.defaults = {
+    value: undefined, // 通过JS赋值,注意是数组
+    monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    dayNames: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    dayNamesShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    firstDay: 1, // First day of the week, Monday
+    weekendDays: [0, 6], // Sunday and Saturday
+    multiple: false,
+    dateFormat: 'yyyy/mm/dd',
+    direction: 'horizontal', // or 'vertical'
+    minDate: null,
+    maxDate: null,
+    touchMove: true,
+    animate: true,
+    closeOnSelect: true,
+    monthPicker: true,
+    monthPickerTemplate: 
+        '<div class="picker-calendar-month-picker">' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-prev-month"><i class="icon icon-prev"></i></a>' +
+            '<div class="current-month-value"></div>' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-next-month"><i class="icon icon-next"></i></a>' +
+        '</div>',
+    yearPicker: true,
+    yearPickerTemplate: 
+        '<div class="picker-calendar-year-picker">' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-prev-year"><i class="icon icon-prev"></i></a>' +
+            '<span class="current-year-value"></span>' +
+            '<a href="javascript:;" class="link icon-only picker-calendar-next-year"><i class="icon icon-next"></i></a>' +
+        '</div>',
+    weekHeader: true,
+    // Common settings
+    scrollToInput: true,
+    inputReadOnly: true,
+    convertToPopover: true,
+    onlyInPopover: false,
+    toolbar: true,
+    toolbarCloseText: 'Done',
+    toolbarTemplate: 
+        '<div class="toolbar">' +
+            '<div class="toolbar-inner">' +
+                '{{yearPicker}}' +
+                '{{monthPicker}}' +
+                // '<a href="#" class="link close-picker">{{closeText}}</a>' +
+            '</div>' +
+        '</div>',
+    /* Callbacks
+    onMonthAdd
+    onChange
+    onOpen
+    onClose
+    onDayClick
+    onMonthYearChangeStart
+    onMonthYearChangeEnd
+    */
+  };
+
+}($);
+
+/* global $:true */
+/* jshint unused:false*/
+
++ function($) {
+  "use strict";
+
+
+  var defaults;
+
+  var formatNumber = function (n) {
+    return n < 10 ? "0" + n : n;
+  }
+
+  var Datetime = function(input, params) {
+    this.input = $(input);
+    this.params = params || {};
+
+    this.initMonthes = params.monthes
+
+    this.initYears = params.years
+
+    var p = $.extend({}, params, this.getConfig());
+    $(this.input).picker(p);
+  }
+
+  Datetime.prototype = {
+    getDays : function(max) {
+      var days = [];
+      for(var i=1; i<= (max||31);i++) {
+        days.push(i < 10 ? "0"+i : i);
+      }
+      return days;
+    },
+
+    getDaysByMonthAndYear : function(month, year) {
+      var int_d = new Date(year, parseInt(month)+1-1, 1);
+      var d = new Date(int_d - 1);
+      return this.getDays(d.getDate());
+    },
+    getConfig: function() {
+      var today = new Date(),
+          params = this.params,
+          self = this,
+          lastValidValues;
+
+      var config = {
+        rotateEffect: false,  //为了性能
+        cssClass: 'datetime-picker',
+
+        value: [today.getFullYear(), formatNumber(today.getMonth()+1), formatNumber(today.getDate()), formatNumber(today.getHours()), (formatNumber(today.getMinutes()))],
+
+        onChange: function (picker, values, displayValues) {
+          var cols = picker.cols;
+          var days = self.getDaysByMonthAndYear(values[1], values[0]);
+          var currentValue = values[2];
+          if(currentValue > days.length) currentValue = days.length;
+          picker.cols[4].setValue(currentValue);
+
+          //check min and max
+          var current = new Date(values[0]+'-'+values[1]+'-'+values[2]);
+          var valid = true;
+          if(params.min) {
+            var min = new Date(typeof params.min === "function" ? params.min() : params.min);
+
+            if(current < +min) {
+              picker.setValue(lastValidValues);
+              valid = false;
+            } 
+          }
+          if(params.max) {
+            var max = new Date(typeof params.max === "function" ? params.max() : params.max);
+            if(current > +max) {
+              picker.setValue(lastValidValues);
+              valid = false;
+            }
+          }
+
+          valid && (lastValidValues = values);
+
+          if (self.params.onChange) {
+            self.params.onChange.apply(this, arguments);
+          }
+        },
+
+        formatValue: function (p, values, displayValues) {
+          return self.params.format(p, values, displayValues);
+        },
+
+        cols: [
+          {
+            values: this.initYears
+          },
+          {
+            divider: true,  // 这是一个分隔符
+            content: params.yearSplit
+          },
+          {
+            values: this.initMonthes
+          },
+          {
+            divider: true,  // 这是一个分隔符
+            content: params.monthSplit
+          },
+          {
+            values: (function () {
+              var dates = [];
+              for (var i=1; i<=31; i++) dates.push(formatNumber(i));
+              return dates;
+            })()
+          },
+          
+        ]
+      }
+
+      if (params.dateSplit) {
+        config.cols.push({
+          divider: true,
+          content: params.dateSplit
+        })
+      }
+
+      config.cols.push({
+        divider: true,
+        content: params.datetimeSplit
+      })
+
+      var times = self.params.times();
+      if (times && times.length) {
+        config.cols = config.cols.concat(times);
+      }
+
+      var inputValue = this.input.val();
+      if(inputValue) config.value = params.parse(inputValue);
+      if(this.params.value) {
+        this.input.val(this.params.value);
+        config.value = params.parse(this.params.value);
+      }
+
+      return config;
+    }
+  }
+
+  $.fn.datetimePicker = function(params) {
+    params = $.extend({}, defaults, params);
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      var datetime = $this.data("datetime");
+      if(!datetime) $this.data("datetime", new Datetime(this, params));
+      return datetime;
+    });
+  };
+
+  defaults = $.fn.datetimePicker.prototype.defaults = {
+    input: undefined, // 默认值
+    min: undefined, // YYYY-MM-DD 最大最小值只比较年月日,不比较时分秒
+    max: undefined,  // YYYY-MM-DD
+    yearSplit: '-',
+    monthSplit: '-',
+    dateSplit: '',  // 默认为空
+    datetimeSplit: ' ',  // 日期和时间之间的分隔符,不可为空
+    monthes: ('01 02 03 04 05 06 07 08 09 10 11 12').split(' '),
+    years: (function () {
+      var arr = [];
+      for (var i = 1950; i <= 2030; i++) { arr.push(i); }
+      return arr;
+    })(),
+    times: function () {
+      return [  // 自定义的时间
+        {
+          values: (function () {
+            var hours = [];
+            for (var i=0; i<24; i++) hours.push(formatNumber(i));
+            return hours;
+          })()
+        },
+        {
+          divider: true,  // 这是一个分隔符
+          content: ':'
+        },
+        {
+          values: (function () {
+            var minutes = [];
+            for (var i=0; i<60; i++) minutes.push(formatNumber(i));
+            return minutes;
+          })()
+        }
+      ];
+    },
+    format: function (p, values) { // 数组转换成字符串
+      return p.cols.map(function (col) {
+        return col.value || col.content;
+      }).join('');
+    },
+    parse: function (str) {
+      // 把字符串转换成数组,用来解析初始值
+      // 如果你的定制的初始值格式无法被这个默认函数解析,请自定义这个函数。比如你的时间是 '子时' 那么默认情况这个'时'会被当做分隔符而导致错误,所以你需要自己定义parse函数
+      // 默认兼容的分隔符
+      var t = str.split(this.datetimeSplit);
+      return t[0].split(/\D/).concat(t[1].split(/:|时|分|秒/)).filter(function (d) {
+        return !!d;
+      })
+    }
+  }
+
+}($);
+
+/*======================================================
+************   Picker   ************
+======================================================*/
+/* global $:true */
+
++ function($) {
+  "use strict";
+
+
+  //Popup 和 picker 之类的不要共用一个弹出方法,因为这样会导致 在 popup 中再弹出 picker 的时候会有问题。
+
+  $.openPopup = function(popup, className) {
+
+    $.closePopup();
+
+    popup = $(popup);
+    popup.show();
+    popup.width();
+    popup.addClass("weui-popup__container--visible");
+    var modal = popup.find(".weui-popup__modal");
+    modal.width();
+    modal.transitionEnd(function() {
+      modal.trigger("open");
+    });
+  }
+
+
+  $.closePopup = function(container, remove) {
+    container = $(container || ".weui-popup__container--visible");
+    container.find('.weui-popup__modal').transitionEnd(function() {
+      var $this = $(this);
+      $this.trigger("close");
+      container.hide();
+      remove && container.remove();
+    })
+    container.removeClass("weui-popup__container--visible")
+  };
+
+
+  $(document).on("click", ".close-popup, .weui-popup__overlay", function() {
+    $.closePopup();
+  })
+  .on("click", ".open-popup", function() {
+    $($(this).data("target")).popup();
+  })
+  .on("click", ".weui-popup__container", function(e) {
+    if($(e.target).hasClass("weui-popup__container")) $.closePopup();
+  })
+
+  $.fn.popup = function() {
+    return this.each(function() {
+      $.openPopup(this);
+    });
+  };
+
+}($);
+
+/* ===============================================================================
+************   Notification ************
+=============================================================================== */
+/* global $:true */
++function ($) {
+  "use strict";
+
+  var noti, defaults, timeout, start, diffX, diffY;
+
+  var touchStart = function(e) {
+    var p = $.getTouchPosition(e);
+    start = p;
+    diffX = diffY = 0;
+    noti.addClass("touching");
+  };
+  var touchMove = function(e) {
+    if(!start) return false;
+    e.preventDefault();
+    e.stopPropagation();
+    var p = $.getTouchPosition(e);
+    diffX = p.x - start.x;
+    diffY = p.y - start.y;
+    if(diffY > 0) {
+      diffY = Math.sqrt(diffY);
+    }
+
+    noti.css("transform", "translate3d(0, "+diffY+"px, 0)");
+  };
+  var touchEnd = function() {
+    noti.removeClass("touching");
+    noti.attr("style", "");
+    if(diffY < 0 && (Math.abs(diffY) > noti.height()*0.38)) {
+      $.closeNotification();
+    }
+
+    if(Math.abs(diffX) <= 1 && Math.abs(diffY) <= 1) {
+      noti.trigger("noti-click");
+    }
+
+    start = false;
+  };
+
+  var attachEvents = function(el) {
+    el.on($.touchEvents.start, touchStart);
+    el.on($.touchEvents.move, touchMove);
+    el.on($.touchEvents.end, touchEnd);
+  };
+
+  $.notification = $.noti = function(params) {
+    params = $.extend({}, defaults, params);
+    noti = $(".weui-notification");
+    if(!noti[0]) { // create a new notification
+      noti = $('<div class="weui-notification"></div>').appendTo(document.body);
+      attachEvents(noti);
+    }
+
+    noti.off("noti-click"); //the click event is not correct sometime: it will trigger when user is draging.
+    if(params.onClick) noti.on("noti-click", function() {
+      params.onClick(params.data);
+    });
+
+    noti.html($.t7.compile(params.tpl)(params));
+
+    noti.show();
+
+    noti.addClass("weui-notification--in");
+    noti.data("params", params);
+
+    var startTimeout = function() {
+      if(timeout) {
+        clearTimeout(timeout);
+        timeout = null;
+      }
+
+      timeout = setTimeout(function() {
+        if(noti.hasClass("weui-notification--touching")) {
+          startTimeout();
+        } else {
+          $.closeNotification();
+        }
+      }, params.time);
+    };
+
+    startTimeout();
+
+  };
+
+  $.closeNotification = function() {
+    timeout && clearTimeout(timeout);
+    timeout = null;
+    var noti = $(".weui-notification").removeClass("weui-notification--in").transitionEnd(function() {
+      $(this).remove();
+    });
+
+    if(noti[0]) {
+      var params = $(".weui-notification").data("params");
+      if(params && params.onClose) {
+        params.onClose(params.data);
+      }
+    }
+  };
+
+  defaults = $.noti.prototype.defaults = {
+    title: undefined,
+    text: undefined,
+    media: undefined,
+    time: 4000,
+    onClick: undefined,
+    onClose: undefined,
+    data: undefined,
+    tpl:  '<div class="weui-notification__inner">' +
+            '{{#if media}}<div class="weui-notification__media">{{media}}</div>{{/if}}' +
+            '<div class="weui-notification__content">' +
+            '{{#if title}}<div class="weui-notification__title">{{title}}</div>{{/if}}' +
+            '{{#if text}}<div class="weui-notification__text">{{text}}</div>{{/if}}' +
+            '</div>' +
+            '<div class="weui-notification__handle-bar"></div>' +
+          '</div>'
+  };
+
+}($);
+
++ function($) {
+  "use strict";
+
+  var timeout;
+
+  $.toptip = function(text, duration, type) {
+    if(!text) return;
+    if(typeof duration === typeof "a") {
+      type = duration;
+      duration = undefined;
+    }
+    duration = duration || 3000;
+    var className = type ? 'bg-' + type : 'bg-danger';
+    var $t = $('.weui-toptips').remove();
+    $t = $('<div class="weui-toptips"></div>').appendTo(document.body);
+    $t.html(text);
+    $t[0].className = 'weui-toptips ' + className
+
+    clearTimeout(timeout);
+
+    if(!$t.hasClass('weui-toptips_visible')) {
+      $t.show().width();
+      $t.addClass('weui-toptips_visible');
+    }
+
+    timeout = setTimeout(function() {
+      $t.removeClass('weui-toptips_visible').transitionEnd(function() {
+        $t.remove();
+      });
+    }, duration);
+  }
+}($);
+
+/* global $:true */
++ function($) {
+  "use strict";
+  var Slider = function (container, arg) {
+    this.container = $(container);
+    this.handler = this.container.find('.weui-slider__handler')
+    this.track = this.container.find('.weui-slider__track')
+    this.value = this.container.find('.weui-slider-box__value')
+    this.bind()
+    if (typeof arg === 'function') {
+      this.callback = arg
+    }
+  }
+
+  Slider.prototype.bind = function () {
+    this.container
+      .on($.touchEvents.start, $.proxy(this.touchStart, this))
+      .on($.touchEvents.end, $.proxy(this.touchEnd, this));
+    $(document.body).on($.touchEvents.move, $.proxy(this.touchMove, this)) // move even outside container
+  }
+
+  Slider.prototype.touchStart = function (e) {
+    e.preventDefault()
+    this.start = $.getTouchPosition(e)
+    this.width = this.container.find('.weui-slider__inner').width()
+    this.left = parseInt(this.container.find('.weui-slider__handler').css('left'))
+    this.touching = true
+  }
+
+  Slider.prototype.touchMove = function (e) {
+    if (!this.touching) return true
+    var p = $.getTouchPosition(e)
+    var distance = p.x - this.start.x
+    var left = distance + this.left
+    var per = parseInt(left / this.width * 100)
+    if (per < 0) per = 0
+    if (per > 100) per = 100
+    this.handler.css('left', per + '%')
+    this.track.css('width', per + '%')
+    this.value.text(per)
+    this.callback && this.callback.call(this, per)
+    this.container.trigger('change', per)
+  }
+
+  Slider.prototype.touchEnd = function (e) {
+    this.touching = false
+  }
+
+  $.fn.slider = function (arg) {
+    this.each(function () {
+      var $this = $(this)
+      var slider = $this.data('slider')
+      if (slider) return slider;
+      else $this.data('slider', new Slider(this, arg))
+    })
+  }
+}($);
+
+/* ===============================================================================
+************   Swipeout ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var cache = [];
+  var TOUCHING = 'swipeout-touching'
+
+  var Swipeout = function(el) {
+    this.container = $(el);
+    this.mover = this.container.find('>.weui-cell__bd')
+    this.attachEvents();
+    cache.push(this)
+  }
+
+  Swipeout.prototype.touchStart = function(e) {
+    var p = $.getTouchPosition(e);
+    this.container.addClass(TOUCHING);
+    this.start = p;
+    this.startX = 0;
+    this.startTime = + new Date;
+    var transform =  this.mover.css('transform').match(/-?[\d\.]+/g)
+    if (transform && transform.length) this.startX = parseInt(transform[4])
+    this.diffX = this.diffY = 0;
+    this._closeOthers()
+    this.limit = this.container.find('>.weui-cell__ft').width() || 68; // 因为有的时候初始化的时候元素是隐藏的(比如在对话框内),所以在touchstart的时候计算宽度而不是初始化的时候
+  };
+
+  Swipeout.prototype.touchMove= function(e) {
+    if(!this.start) return true;
+    var p = $.getTouchPosition(e);
+    this.diffX = p.x - this.start.x;
+    this.diffY = p.y - this.start.y;
+    if (Math.abs(this.diffX) < Math.abs(this.diffY)) { // 说明是上下方向在拖动
+      this.close()
+      this.start = false
+      return true;
+    }
+    e.preventDefault();
+    e.stopPropagation();
+    var x = this.diffX + this.startX
+    if (x > 0) x = 0;
+    if (Math.abs(x) > this.limit) x = - (Math.pow(-(x+this.limit), .7) + this.limit)
+    this.mover.css("transform", "translate3d("+x+"px, 0, 0)");
+  };
+  Swipeout.prototype.touchEnd = function() {
+    if (!this.start) return true;
+    this.start = false;
+    var x = this.diffX + this.startX
+    var t = new Date - this.startTime;
+    if (this.diffX < -5 && t < 200) { // 向左快速滑动,则打开
+      this.open()
+    } else if (this.diffX >= 0 && t < 200) { // 向右快速滑动,或者单击,则关闭
+      this.close()
+    } else if (x > 0 || -x <= this.limit / 2) {
+      this.close()
+    } else {
+      this.open()
+    }
+  };
+
+
+  Swipeout.prototype.close = function() {
+    this.container.removeClass(TOUCHING);
+    this.mover.css("transform", "translate3d(0, 0, 0)");
+    this.container.trigger('swipeout-close');
+  }
+
+  Swipeout.prototype.open = function() {
+    this.container.removeClass(TOUCHING);
+    this._closeOthers()
+    this.mover.css("transform", "translate3d(" + (-this.limit) + "px, 0, 0)");
+    this.container.trigger('swipeout-open');
+  }
+
+  Swipeout.prototype.attachEvents = function() {
+    var el = this.mover;
+    el.on($.touchEvents.start, $.proxy(this.touchStart, this));
+    el.on($.touchEvents.move, $.proxy(this.touchMove, this));
+    el.on($.touchEvents.end, $.proxy(this.touchEnd, this));
+  }
+  Swipeout.prototype._closeOthers = function() {
+    //close others
+    var self = this
+    cache.forEach(function (s) {
+      if (s !== self) s.close()
+    })
+  }
+
+  var swipeout = function(el) {
+    return new Swipeout(el);
+  };
+
+  $.fn.swipeout = function (arg) {
+    return this.each(function() {
+      var $this = $(this)
+      var s = $this.data('swipeout') || swipeout(this);
+      $this.data('swipeout', s);
+
+      if (typeof arg === typeof 'a') {
+        s[arg]()
+      }
+    });
+  }
+
+  $('.weui-cell_swiped').swipeout() // auto init
+}($);
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.min.js
new file mode 100755
index 0000000..28951e8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery-weui.min.js
@@ -0,0 +1,13 @@
+/** 
+* jQuery WeUI V1.2.1 
+* By 言川
+* http://lihongxun945.github.io/jquery-weui/
+ */
+!function(t){"use strict";t.fn.transitionEnd=function(t){function e(r){if(r.target===this)for(t.call(this,r),n=0;n<i.length;n++)a.off(i[n],e)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],a=this;if(t)for(n=0;n<i.length;n++)a.on(i[n],e);return this},t.support=function(){var t={touch:!!("ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch)};return t}(),t.touchEvents={start:t.support.touch?"touchstart":"mousedown",move:t.support.touch?"touchmove":"mousemove",end:t.support.touch?"touchend":"mouseup"},t.getTouchPosition=function(t){return t=t.originalEvent||t,"touchstart"===t.type||"touchmove"===t.type||"touchend"===t.type?{x:t.targetTouches[0].pageX,y:t.targetTouches[0].pageY}:{x:t.pageX,y:t.pageY}},t.fn.scrollHeight=function(){return this[0].scrollHeight},t.fn.transform=function(t){for(var e=0;e<this.length;e++){var n=this[e].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=t}return this},t.fn.transition=function(t){"string"!=typeof t&&(t+="ms");for(var e=0;e<this.length;e++){var n=this[e].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=t}return this},t.getTranslate=function(t,e){var n,i,a,r;return"undefined"==typeof e&&(e="x"),a=window.getComputedStyle(t,null),window.WebKitCSSMatrix?r=new WebKitCSSMatrix("none"===a.webkitTransform?"":a.webkitTransform):(r=a.MozTransform||a.OTransform||a.MsTransform||a.msTransform||a.transform||a.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),n=r.toString().split(",")),"x"===e&&(i=window.WebKitCSSMatrix?r.m41:16===n.length?parseFloat(n[12]):parseFloat(n[4])),"y"===e&&(i=window.WebKitCSSMatrix?r.m42:16===n.length?parseFloat(n[13]):parseFloat(n[5])),i||0},t.requestAnimationFrame=function(t){return window.requestAnimationFrame?window.requestAnimationFrame(t):window.webkitRequestAnimationFrame?window.webkitRequestAnimationFrame(t):window.mozRequestAnimationFrame?window.mozRequestAnimationFrame(t):window.setTimeout(t,1e3/60)},t.cancelAnimationFrame=function(t){return window.cancelAnimationFrame?window.cancelAnimationFrame(t):window.webkitCancelAnimationFrame?window.webkitCancelAnimationFrame(t):window.mozCancelAnimationFrame?window.mozCancelAnimationFrame(t):window.clearTimeout(t)},t.fn.join=function(t){return this.toArray().join(t)}}($),+function(t){"use strict";t.Template7=t.t7=function(){function t(t){return"[object Array]"===Object.prototype.toString.apply(t)}function e(t){return"function"==typeof t}function n(t){var e,n,i,a=t.replace(/[{}#}]/g,"").split(" "),r=[];for(n=0;n<a.length;n++){var o=a[n];if(0===n)r.push(o);else if(0===o.indexOf('"'))if(2===o.match(/"/g).length)r.push(o);else{for(e=0,i=n+1;i<a.length;i++)if(o+=" "+a[i],a[i].indexOf('"')>=0){e=i,r.push(o);break}e&&(n=e)}else if(o.indexOf("=")>0){var s=o.split("="),c=s[0],l=s[1];if(2!==l.match(/"/g).length){for(e=0,i=n+1;i<a.length;i++)if(l+=" "+a[i],a[i].indexOf('"')>=0){e=i;break}e&&(n=e)}var u=[c,l.replace(/"/g,"")];r.push(u)}else r.push(o)}return r}function i(e){var i,a,r=[];if(!e)return[];var o=e.split(/({{[^{^}]*}})/);for(i=0;i<o.length;i++){var s=o[i];if(""!==s)if(s.indexOf("{{")<0)r.push({type:"plain",content:s});else{if(s.indexOf("{/")>=0)continue;if(s.indexOf("{#")<0&&s.indexOf(" ")<0&&s.indexOf("else")<0){r.push({type:"variable",contextName:s.replace(/[{}]/g,"")});continue}var c=n(s),l=c[0],u=[],p={};for(a=1;a<c.length;a++){var h=c[a];t(h)?p[h[0]]="false"!==h[1]&&h[1]:u.push(h)}if(s.indexOf("{#")>=0){var d,f="",m="",v=0,g=!1,w=!1,y=0;for(a=i+1;a<o.length;a++)if(o[a].indexOf("{{#")>=0&&y++,o[a].indexOf("{{/")>=0&&y--,o[a].indexOf("{{#"+l)>=0)f+=o[a],w&&(m+=o[a]),v++;else if(o[a].indexOf("{{/"+l)>=0){if(!(v>0)){d=a,g=!0;break}v--,f+=o[a],w&&(m+=o[a])}else o[a].indexOf("else")>=0&&0===y?w=!0:(w||(f+=o[a]),w&&(m+=o[a]));g&&(d&&(i=d),r.push({type:"helper",helperName:l,contextName:u,content:f,inverseContent:m,hash:p}))}else s.indexOf(" ")>0&&r.push({type:"helper",helperName:l,contextName:u,hash:p})}}return r}var a=function(t){function e(t,e){return t.content?o(t.content,e):function(){return""}}function n(t,e){return t.inverseContent?o(t.inverseContent,e):function(){return""}}function a(t,e){var n,i,a=0;if(0===t.indexOf("../")){a=t.split("../").length-1;var r=e.split("_")[1]-a;e="ctx_"+(r>=1?r:1),i=t.split("../")[a].split(".")}else 0===t.indexOf("@global")?(e="$.Template7.global",i=t.split("@global.")[1].split(".")):0===t.indexOf("@root")?(e="ctx_1",i=t.split("@root.")[1].split(".")):i=t.split(".");n=e;for(var o=0;o<i.length;o++){var s=i[o];0===s.indexOf("@")?o>0?n+="[(data && data."+s.replace("@","")+")]":n="(data && data."+t.replace("@","")+")":isFinite(s)?n+="["+s+"]":0===s.indexOf("this")?n=s.replace("this",e):n+="."+s}return n}function r(t,e){for(var n=[],i=0;i<t.length;i++)0===t[i].indexOf('"')?n.push(t[i]):n.push(a(t[i],e));return n.join(", ")}function o(t,o){if(o=o||1,t=t||s.template,"string"!=typeof t)throw new Error("Template7: Template must be a string");var c=i(t);if(0===c.length)return function(){return""};var l="ctx_"+o,u="(function ("+l+", data) {\n";1===o&&(u+="function isArray(arr){return Object.prototype.toString.apply(arr) === '[object Array]';}\n",u+="function isFunction(func){return (typeof func === 'function');}\n",u+='function c(val, ctx) {if (typeof val !== "undefined") {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n'),u+="var r = '';\n";var p;for(p=0;p<c.length;p++){var h=c[p];if("plain"!==h.type){var d,f;if("variable"===h.type&&(d=a(h.contextName,l),u+="r += c("+d+", "+l+");"),"helper"===h.type)if(h.helperName in s.helpers)f=r(h.contextName,l),u+="r += ($.Template7.helpers."+h.helperName+").call("+l+", "+(f&&f+", ")+"{hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});";else{if(h.contextName.length>0)throw new Error('Template7: Missing helper: "'+h.helperName+'"');d=a(h.helperName,l),u+="if ("+d+") {",u+="if (isArray("+d+")) {",u+="r += ($.Template7.helpers.each).call("+l+", "+d+", {hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});",u+="}else {",u+="r += ($.Template7.helpers.with).call("+l+", "+d+", {hash:"+JSON.stringify(h.hash)+", data: data || {}, fn: "+e(h,o+1)+", inverse: "+n(h,o+1)+", root: ctx_1});",u+="}}"}}else u+="r +='"+h.content.replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/'/g,"\\'")+"';"}return u+="\nreturn r;})",eval.call(window,u)}var s=this;s.template=t,s.compile=function(t){return s.compiled||(s.compiled=o(t)),s.compiled}};a.prototype={options:{},helpers:{"if":function(t,n){return e(t)&&(t=t.call(this)),t?n.fn(this,n.data):n.inverse(this,n.data)},unless:function(t,n){return e(t)&&(t=t.call(this)),t?n.inverse(this,n.data):n.fn(this,n.data)},each:function(n,i){var a="",r=0;if(e(n)&&(n=n.call(this)),t(n)){for(i.hash.reverse&&(n=n.reverse()),r=0;r<n.length;r++)a+=i.fn(n[r],{first:0===r,last:r===n.length-1,index:r});i.hash.reverse&&(n=n.reverse())}else for(var o in n)r++,a+=i.fn(n[o],{key:o});return r>0?a:i.inverse(this)},"with":function(t,n){return e(t)&&(t=t.call(this)),n.fn(t)},join:function(t,n){return e(t)&&(t=t.call(this)),t.join(n.hash.delimiter||n.hash.delimeter)},js:function(t,e){var n;return n=t.indexOf("return")>=0?"(function(){"+t+"})":"(function(){return ("+t+")})",eval.call(this,n).call(this)},js_compare:function(t,e){var n;n=t.indexOf("return")>=0?"(function(){"+t+"})":"(function(){return ("+t+")})";var i=eval.call(this,n).call(this);return i?e.fn(this,e.data):e.inverse(this,e.data)}}};var r=function(t,e){if(2===arguments.length){var n=new a(t),i=n.compile()(e);return n=null,i}return new a(t)};return r.registerHelper=function(t,e){a.prototype.helpers[t]=e},r.unregisterHelper=function(t){a.prototype.helpers[t]=void 0,delete a.prototype.helpers[t]},r.compile=function(t,e){var n=new a(t,e);return n.compile()},r.options=a.prototype.options,r.helpers=a.prototype.helpers,r}()}($),/*! Hammer.JS - v2.0.8 - 2016-04-23
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the MIT license */
+function(t,e,n,i){"use strict";function a(t,e,n){return setTimeout(l(t,n),e)}function r(t,e,n){return!!Array.isArray(t)&&(o(t,n[e],n),!0)}function o(t,e,n){var a;if(t)if(t.forEach)t.forEach(e,n);else if(t.length!==i)for(a=0;a<t.length;)e.call(n,t[a],a,t),a++;else for(a in t)t.hasOwnProperty(a)&&e.call(n,t[a],a,t)}function s(e,n,i){var a="DEPRECATED METHOD: "+n+"\n"+i+" AT \n";return function(){var n=new Error("get-stack-trace"),i=n&&n.stack?n.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",r=t.console&&(t.console.warn||t.console.log);return r&&r.call(t.console,a,i),e.apply(this,arguments)}}function c(t,e,n){var i,a=e.prototype;i=t.prototype=Object.create(a),i.constructor=t,i._super=a,n&&pt(i,n)}function l(t,e){return function(){return t.apply(e,arguments)}}function u(t,e){return typeof t==ft?t.apply(e?e[0]||i:i,e):t}function p(t,e){return t===i?e:t}function h(t,e,n){o(v(e),function(e){t.addEventListener(e,n,!1)})}function d(t,e,n){o(v(e),function(e){t.removeEventListener(e,n,!1)})}function f(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1}function m(t,e){return t.indexOf(e)>-1}function v(t){return t.trim().split(/\s+/g)}function g(t,e,n){if(t.indexOf&&!n)return t.indexOf(e);for(var i=0;i<t.length;){if(n&&t[i][n]==e||!n&&t[i]===e)return i;i++}return-1}function w(t){return Array.prototype.slice.call(t,0)}function y(t,e,n){for(var i=[],a=[],r=0;r<t.length;){var o=e?t[r][e]:t[r];g(a,o)<0&&i.push(t[r]),a[r]=o,r++}return n&&(i=e?i.sort(function(t,n){return t[e]>n[e]}):i.sort()),i}function T(t,e){for(var n,a,r=e[0].toUpperCase()+e.slice(1),o=0;o<ht.length;){if(n=ht[o],a=n?n+r:e,a in t)return a;o++}return i}function k(){return Tt++}function x(e){var n=e.ownerDocument||e;return n.defaultView||n.parentWindow||t}function C(t,e){var n=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){u(t.options.enable,[t])&&n.handler(e)},this.init()}function b(t){var e,n=t.options.inputClass;return new(e=n?n:Ct?F:bt?z:xt?j:N)(t,M)}function M(t,e,n){var i=n.pointers.length,a=n.changedPointers.length,r=e&Ot&&i-a===0,o=e&(It|Ht)&&i-a===0;n.isFirst=!!r,n.isFinal=!!o,r&&(t.session={}),n.eventType=e,_(t,n),t.emit("hammer.input",n),t.recognize(n),t.session.prevInput=n}function _(t,e){var n=t.session,i=e.pointers,a=i.length;n.firstInput||(n.firstInput=P(e)),a>1&&!n.firstMultiple?n.firstMultiple=P(e):1===a&&(n.firstMultiple=!1);var r=n.firstInput,o=n.firstMultiple,s=o?o.center:r.center,c=e.center=O(i);e.timeStamp=gt(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=S(s,c),e.distance=H(s,c),E(n,e),e.offsetDirection=I(e.deltaX,e.deltaY);var l=A(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=l.x,e.overallVelocityY=l.y,e.overallVelocity=vt(l.x)>vt(l.y)?l.x:l.y,e.scale=o?V(o.pointers,i):1,e.rotation=o?Y(o.pointers,i):0,e.maxPointers=n.prevInput?e.pointers.length>n.prevInput.maxPointers?e.pointers.length:n.prevInput.maxPointers:e.pointers.length,D(n,e);var u=t.element;f(e.srcEvent.target,u)&&(u=e.srcEvent.target),e.target=u}function E(t,e){var n=e.center,i=t.offsetDelta||{},a=t.prevDelta||{},r=t.prevInput||{};e.eventType!==Ot&&r.eventType!==It||(a=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},i=t.offsetDelta={x:n.x,y:n.y}),e.deltaX=a.x+(n.x-i.x),e.deltaY=a.y+(n.y-i.y)}function D(t,e){var n,a,r,o,s=t.lastInterval||e,c=e.timeStamp-s.timeStamp;if(e.eventType!=Ht&&(c>Pt||s.velocity===i)){var l=e.deltaX-s.deltaX,u=e.deltaY-s.deltaY,p=A(c,l,u);a=p.x,r=p.y,n=vt(p.x)>vt(p.y)?p.x:p.y,o=I(l,u),t.lastInterval=e}else n=s.velocity,a=s.velocityX,r=s.velocityY,o=s.direction;e.velocity=n,e.velocityX=a,e.velocityY=r,e.direction=o}function P(t){for(var e=[],n=0;n<t.pointers.length;)e[n]={clientX:mt(t.pointers[n].clientX),clientY:mt(t.pointers[n].clientY)},n++;return{timeStamp:gt(),pointers:e,center:O(e),deltaX:t.deltaX,deltaY:t.deltaY}}function O(t){var e=t.length;if(1===e)return{x:mt(t[0].clientX),y:mt(t[0].clientY)};for(var n=0,i=0,a=0;a<e;)n+=t[a].clientX,i+=t[a].clientY,a++;return{x:mt(n/e),y:mt(i/e)}}function A(t,e,n){return{x:e/t||0,y:n/t||0}}function I(t,e){return t===e?St:vt(t)>=vt(e)?t<0?Yt:Vt:e<0?Nt:Ft}function H(t,e,n){n||(n=Lt);var i=e[n[0]]-t[n[0]],a=e[n[1]]-t[n[1]];return Math.sqrt(i*i+a*a)}function S(t,e,n){n||(n=Lt);var i=e[n[0]]-t[n[0]],a=e[n[1]]-t[n[1]];return 180*Math.atan2(a,i)/Math.PI}function Y(t,e){return S(e[1],e[0],jt)+S(t[1],t[0],jt)}function V(t,e){return H(e[0],e[1],jt)/H(t[0],t[1],jt)}function N(){this.evEl=$t,this.evWin=Wt,this.pressed=!1,C.apply(this,arguments)}function F(){this.evEl=Bt,this.evWin=Gt,C.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function R(){this.evTarget=Zt,this.evWin=Qt,this.started=!1,C.apply(this,arguments)}function q(t,e){var n=w(t.touches),i=w(t.changedTouches);return e&(It|Ht)&&(n=y(n.concat(i),"identifier",!0)),[n,i]}function z(){this.evTarget=ee,this.targetIds={},C.apply(this,arguments)}function L(t,e){var n=w(t.touches),i=this.targetIds;if(e&(Ot|At)&&1===n.length)return i[n[0].identifier]=!0,[n,n];var a,r,o=w(t.changedTouches),s=[],c=this.target;if(r=n.filter(function(t){return f(t.target,c)}),e===Ot)for(a=0;a<r.length;)i[r[a].identifier]=!0,a++;for(a=0;a<o.length;)i[o[a].identifier]&&s.push(o[a]),e&(It|Ht)&&delete i[o[a].identifier],a++;return s.length?[y(r.concat(s),"identifier",!0),s]:void 0}function j(){C.apply(this,arguments);var t=l(this.handler,this);this.touch=new z(this.manager,t),this.mouse=new N(this.manager,t),this.primaryTouch=null,this.lastTouches=[]}function X(t,e){t&Ot?(this.primaryTouch=e.changedPointers[0].identifier,$.call(this,e)):t&(It|Ht)&&$.call(this,e)}function $(t){var e=t.changedPointers[0];if(e.identifier===this.primaryTouch){var n={x:e.clientX,y:e.clientY};this.lastTouches.push(n);var i=this.lastTouches,a=function(){var t=i.indexOf(n);t>-1&&i.splice(t,1)};setTimeout(a,ne)}}function W(t){for(var e=t.srcEvent.clientX,n=t.srcEvent.clientY,i=0;i<this.lastTouches.length;i++){var a=this.lastTouches[i],r=Math.abs(e-a.x),o=Math.abs(n-a.y);if(r<=ie&&o<=ie)return!0}return!1}function K(t,e){this.manager=t,this.set(e)}function U(t){if(m(t,le))return le;var e=m(t,ue),n=m(t,pe);return e&&n?le:e||n?e?ue:pe:m(t,ce)?ce:se}function B(){if(!re)return!1;var e={},n=t.CSS&&t.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(i){e[i]=!n||t.CSS.supports("touch-action",i)}),e}function G(t){this.options=pt({},this.defaults,t||{}),this.id=k(),this.manager=null,this.options.enable=p(this.options.enable,!0),this.state=de,this.simultaneous={},this.requireFail=[]}function J(t){return t&we?"cancel":t&ve?"end":t&me?"move":t&fe?"start":""}function Z(t){return t==Ft?"down":t==Nt?"up":t==Yt?"left":t==Vt?"right":""}function Q(t,e){var n=e.manager;return n?n.get(t):t}function tt(){G.apply(this,arguments)}function et(){tt.apply(this,arguments),this.pX=null,this.pY=null}function nt(){tt.apply(this,arguments)}function it(){G.apply(this,arguments),this._timer=null,this._input=null}function at(){tt.apply(this,arguments)}function rt(){tt.apply(this,arguments)}function ot(){G.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function st(t,e){return e=e||{},e.recognizers=p(e.recognizers,st.defaults.preset),new ct(t,e)}function ct(t,e){this.options=pt({},st.defaults,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=b(this),this.touchAction=new K(this,this.options.touchAction),lt(this,!0),o(this.options.recognizers,function(t){var e=this.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])},this)}function lt(t,e){var n=t.element;if(n.style){var i;o(t.options.cssProps,function(a,r){i=T(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=a):n.style[i]=t.oldCssProps[i]||""}),e||(t.oldCssProps={})}}function ut(t,n){var i=e.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n,n.target.dispatchEvent(i)}var pt,ht=["","webkit","Moz","MS","ms","o"],dt=e.createElement("div"),ft="function",mt=Math.round,vt=Math.abs,gt=Date.now;pt="function"!=typeof Object.assign?function(t){if(t===i||null===t)throw new TypeError("Cannot convert undefined or null to object");for(var e=Object(t),n=1;n<arguments.length;n++){var a=arguments[n];if(a!==i&&null!==a)for(var r in a)a.hasOwnProperty(r)&&(e[r]=a[r])}return e}:Object.assign;var wt=s(function(t,e,n){for(var a=Object.keys(e),r=0;r<a.length;)(!n||n&&t[a[r]]===i)&&(t[a[r]]=e[a[r]]),r++;return t},"extend","Use `assign`."),yt=s(function(t,e){return wt(t,e,!0)},"merge","Use `assign`."),Tt=1,kt=/mobile|tablet|ip(ad|hone|od)|android/i,xt="ontouchstart"in t,Ct=T(t,"PointerEvent")!==i,bt=xt&&kt.test(navigator.userAgent),Mt="touch",_t="pen",Et="mouse",Dt="kinect",Pt=25,Ot=1,At=2,It=4,Ht=8,St=1,Yt=2,Vt=4,Nt=8,Ft=16,Rt=Yt|Vt,qt=Nt|Ft,zt=Rt|qt,Lt=["x","y"],jt=["clientX","clientY"];C.prototype={handler:function(){},init:function(){this.evEl&&h(this.element,this.evEl,this.domHandler),this.evTarget&&h(this.target,this.evTarget,this.domHandler),this.evWin&&h(x(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&d(this.element,this.evEl,this.domHandler),this.evTarget&&d(this.target,this.evTarget,this.domHandler),this.evWin&&d(x(this.element),this.evWin,this.domHandler)}};var Xt={mousedown:Ot,mousemove:At,mouseup:It},$t="mousedown",Wt="mousemove mouseup";c(N,C,{handler:function(t){var e=Xt[t.type];e&Ot&&0===t.button&&(this.pressed=!0),e&At&&1!==t.which&&(e=It),this.pressed&&(e&It&&(this.pressed=!1),this.callback(this.manager,e,{pointers:[t],changedPointers:[t],pointerType:Et,srcEvent:t}))}});var Kt={pointerdown:Ot,pointermove:At,pointerup:It,pointercancel:Ht,pointerout:Ht},Ut={2:Mt,3:_t,4:Et,5:Dt},Bt="pointerdown",Gt="pointermove pointerup pointercancel";t.MSPointerEvent&&!t.PointerEvent&&(Bt="MSPointerDown",Gt="MSPointerMove MSPointerUp MSPointerCancel"),c(F,C,{handler:function(t){var e=this.store,n=!1,i=t.type.toLowerCase().replace("ms",""),a=Kt[i],r=Ut[t.pointerType]||t.pointerType,o=r==Mt,s=g(e,t.pointerId,"pointerId");a&Ot&&(0===t.button||o)?s<0&&(e.push(t),s=e.length-1):a&(It|Ht)&&(n=!0),s<0||(e[s]=t,this.callback(this.manager,a,{pointers:e,changedPointers:[t],pointerType:r,srcEvent:t}),n&&e.splice(s,1))}});var Jt={touchstart:Ot,touchmove:At,touchend:It,touchcancel:Ht},Zt="touchstart",Qt="touchstart touchmove touchend touchcancel";c(R,C,{handler:function(t){var e=Jt[t.type];if(e===Ot&&(this.started=!0),this.started){var n=q.call(this,t,e);e&(It|Ht)&&n[0].length-n[1].length===0&&(this.started=!1),this.callback(this.manager,e,{pointers:n[0],changedPointers:n[1],pointerType:Mt,srcEvent:t})}}});var te={touchstart:Ot,touchmove:At,touchend:It,touchcancel:Ht},ee="touchstart touchmove touchend touchcancel";c(z,C,{handler:function(t){var e=te[t.type],n=L.call(this,t,e);n&&this.callback(this.manager,e,{pointers:n[0],changedPointers:n[1],pointerType:Mt,srcEvent:t})}});var ne=2500,ie=25;c(j,C,{handler:function(t,e,n){var i=n.pointerType==Mt,a=n.pointerType==Et;if(!(a&&n.sourceCapabilities&&n.sourceCapabilities.firesTouchEvents)){if(i)X.call(this,e,n);else if(a&&W.call(this,n))return;this.callback(t,e,n)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var ae=T(dt.style,"touchAction"),re=ae!==i,oe="compute",se="auto",ce="manipulation",le="none",ue="pan-x",pe="pan-y",he=B();K.prototype={set:function(t){t==oe&&(t=this.compute()),re&&this.manager.element.style&&he[t]&&(this.manager.element.style[ae]=t),this.actions=t.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var t=[];return o(this.manager.recognizers,function(e){u(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))}),U(t.join(" "))},preventDefaults:function(t){var e=t.srcEvent,n=t.offsetDirection;if(this.manager.session.prevented)return void e.preventDefault();var i=this.actions,a=m(i,le)&&!he[le],r=m(i,pe)&&!he[pe],o=m(i,ue)&&!he[ue];if(a){var s=1===t.pointers.length,c=t.distance<2,l=t.deltaTime<250;if(s&&c&&l)return}return o&&r?void 0:a||r&&n&Rt||o&&n&qt?this.preventSrc(e):void 0},preventSrc:function(t){this.manager.session.prevented=!0,t.preventDefault()}};var de=1,fe=2,me=4,ve=8,ge=ve,we=16,ye=32;G.prototype={defaults:{},set:function(t){return pt(this.options,t),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(t){if(r(t,"recognizeWith",this))return this;var e=this.simultaneous;return t=Q(t,this),e[t.id]||(e[t.id]=t,t.recognizeWith(this)),this},dropRecognizeWith:function(t){return r(t,"dropRecognizeWith",this)?this:(t=Q(t,this),delete this.simultaneous[t.id],this)},requireFailure:function(t){if(r(t,"requireFailure",this))return this;var e=this.requireFail;return t=Q(t,this),g(e,t)===-1&&(e.push(t),t.requireFailure(this)),this},dropRequireFailure:function(t){if(r(t,"dropRequireFailure",this))return this;t=Q(t,this);var e=g(this.requireFail,t);return e>-1&&this.requireFail.splice(e,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(t){return!!this.simultaneous[t.id]},emit:function(t){function e(e){n.manager.emit(e,t)}var n=this,i=this.state;i<ve&&e(n.options.event+J(i)),e(n.options.event),t.additionalEvent&&e(t.additionalEvent),i>=ve&&e(n.options.event+J(i))},tryEmit:function(t){return this.canEmit()?this.emit(t):void(this.state=ye)},canEmit:function(){for(var t=0;t<this.requireFail.length;){if(!(this.requireFail[t].state&(ye|de)))return!1;t++}return!0},recognize:function(t){var e=pt({},t);return u(this.options.enable,[this,e])?(this.state&(ge|we|ye)&&(this.state=de),this.state=this.process(e),void(this.state&(fe|me|ve|we)&&this.tryEmit(e))):(this.reset(),void(this.state=ye))},process:function(t){},getTouchAction:function(){},reset:function(){}},c(tt,G,{defaults:{pointers:1},attrTest:function(t){var e=this.options.pointers;return 0===e||t.pointers.length===e},process:function(t){var e=this.state,n=t.eventType,i=e&(fe|me),a=this.attrTest(t);return i&&(n&Ht||!a)?e|we:i||a?n&It?e|ve:e&fe?e|me:fe:ye}}),c(et,tt,{defaults:{event:"pan",threshold:10,pointers:1,direction:zt},getTouchAction:function(){var t=this.options.direction,e=[];return t&Rt&&e.push(pe),t&qt&&e.push(ue),e},directionTest:function(t){var e=this.options,n=!0,i=t.distance,a=t.direction,r=t.deltaX,o=t.deltaY;return a&e.direction||(e.direction&Rt?(a=0===r?St:r<0?Yt:Vt,n=r!=this.pX,i=Math.abs(t.deltaX)):(a=0===o?St:o<0?Nt:Ft,n=o!=this.pY,i=Math.abs(t.deltaY))),t.direction=a,n&&i>e.threshold&&a&e.direction},attrTest:function(t){return tt.prototype.attrTest.call(this,t)&&(this.state&fe||!(this.state&fe)&&this.directionTest(t))},emit:function(t){this.pX=t.deltaX,this.pY=t.deltaY;var e=Z(t.direction);e&&(t.additionalEvent=this.options.event+e),this._super.emit.call(this,t)}}),c(nt,tt,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[le]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.scale-1)>this.options.threshold||this.state&fe)},emit:function(t){if(1!==t.scale){var e=t.scale<1?"in":"out";t.additionalEvent=this.options.event+e}this._super.emit.call(this,t)}}),c(it,G,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[se]},process:function(t){var e=this.options,n=t.pointers.length===e.pointers,i=t.distance<e.threshold,r=t.deltaTime>e.time;if(this._input=t,!i||!n||t.eventType&(It|Ht)&&!r)this.reset();else if(t.eventType&Ot)this.reset(),this._timer=a(function(){this.state=ge,this.tryEmit()},e.time,this);else if(t.eventType&It)return ge;return ye},reset:function(){clearTimeout(this._timer)},emit:function(t){this.state===ge&&(t&&t.eventType&It?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=gt(),this.manager.emit(this.options.event,this._input)))}}),c(at,tt,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[le]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.rotation)>this.options.threshold||this.state&fe)}}),c(rt,tt,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Rt|qt,pointers:1},getTouchAction:function(){return et.prototype.getTouchAction.call(this)},attrTest:function(t){var e,n=this.options.direction;return n&(Rt|qt)?e=t.overallVelocity:n&Rt?e=t.overallVelocityX:n&qt&&(e=t.overallVelocityY),this._super.attrTest.call(this,t)&&n&t.offsetDirection&&t.distance>this.options.threshold&&t.maxPointers==this.options.pointers&&vt(e)>this.options.velocity&&t.eventType&It},emit:function(t){var e=Z(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)}}),c(ot,G,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ce]},process:function(t){var e=this.options,n=t.pointers.length===e.pointers,i=t.distance<e.threshold,r=t.deltaTime<e.time;if(this.reset(),t.eventType&Ot&&0===this.count)return this.failTimeout();if(i&&r&&n){if(t.eventType!=It)return this.failTimeout();var o=!this.pTime||t.timeStamp-this.pTime<e.interval,s=!this.pCenter||H(this.pCenter,t.center)<e.posThreshold;this.pTime=t.timeStamp,this.pCenter=t.center,s&&o?this.count+=1:this.count=1,this._input=t;var c=this.count%e.taps;if(0===c)return this.hasRequireFailures()?(this._timer=a(function(){this.state=ge,this.tryEmit()},e.interval,this),fe):ge}return ye},failTimeout:function(){return this._timer=a(function(){this.state=ye},this.options.interval,this),ye},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==ge&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),st.VERSION="2.0.8",st.defaults={domEvents:!1,touchAction:oe,enable:!0,inputTarget:null,inputClass:null,preset:[[at,{enable:!1}],[nt,{enable:!1},["rotate"]],[rt,{direction:Rt}],[et,{direction:Rt},["swipe"]],[ot],[ot,{event:"doubletap",taps:2},["tap"]],[it]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var Te=1,ke=2;ct.prototype={set:function(t){return pt(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},stop:function(t){this.session.stopped=t?ke:Te},recognize:function(t){var e=this.session;if(!e.stopped){this.touchAction.preventDefaults(t);var n,i=this.recognizers,a=e.curRecognizer;(!a||a&&a.state&ge)&&(a=e.curRecognizer=null);for(var r=0;r<i.length;)n=i[r],e.stopped===ke||a&&n!=a&&!n.canRecognizeWith(a)?n.reset():n.recognize(t),!a&&n.state&(fe|me|ve)&&(a=e.curRecognizer=n),r++}},get:function(t){if(t instanceof G)return t;for(var e=this.recognizers,n=0;n<e.length;n++)if(e[n].options.event==t)return e[n];return null},add:function(t){if(r(t,"add",this))return this;var e=this.get(t.options.event);return e&&this.remove(e),this.recognizers.push(t),t.manager=this,this.touchAction.update(),t},remove:function(t){if(r(t,"remove",this))return this;if(t=this.get(t)){var e=this.recognizers,n=g(e,t);n!==-1&&(e.splice(n,1),this.touchAction.update())}return this},on:function(t,e){if(t!==i&&e!==i){var n=this.handlers;return o(v(t),function(t){n[t]=n[t]||[],n[t].push(e)}),this}},off:function(t,e){if(t!==i){var n=this.handlers;return o(v(t),function(t){e?n[t]&&n[t].splice(g(n[t],e),1):delete n[t]}),this}},emit:function(t,e){this.options.domEvents&&ut(t,e);var n=this.handlers[t]&&this.handlers[t].slice();if(n&&n.length){e.type=t,e.preventDefault=function(){e.srcEvent.preventDefault()};for(var i=0;i<n.length;)n[i](e),i++}},destroy:function(){this.element&&lt(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},pt(st,{INPUT_START:Ot,INPUT_MOVE:At,INPUT_END:It,INPUT_CANCEL:Ht,STATE_POSSIBLE:de,STATE_BEGAN:fe,STATE_CHANGED:me,STATE_ENDED:ve,STATE_RECOGNIZED:ge,STATE_CANCELLED:we,STATE_FAILED:ye,DIRECTION_NONE:St,DIRECTION_LEFT:Yt,DIRECTION_RIGHT:Vt,DIRECTION_UP:Nt,DIRECTION_DOWN:Ft,DIRECTION_HORIZONTAL:Rt,DIRECTION_VERTICAL:qt,DIRECTION_ALL:zt,Manager:ct,Input:C,TouchAction:K,TouchInput:z,MouseInput:N,PointerEventInput:F,TouchMouseInput:j,SingleTouchInput:R,Recognizer:G,AttrRecognizer:tt,Tap:ot,Pan:et,Swipe:rt,Pinch:nt,Rotate:at,Press:it,on:h,off:d,each:o,merge:yt,extend:wt,assign:pt,inherit:c,bindFn:l,prefixed:T});var xe="undefined"!=typeof t?t:"undefined"!=typeof self?self:{};xe.Hammer=st,"function"==typeof define&&define.amd?define(function(){return st}):"undefined"!=typeof module&&module.exports?module.exports=st:t[n]=st}(window,document,"Hammer"),+function(t){"use strict";var e;t.modal=function(n,i){n=t.extend({},e,n);var a=n.buttons,r=a.map(function(t,e){return'<a href="javascript:;" class="weui-dialog__btn '+(t.className||"")+'">'+t.text+"</a>"}).join(""),o='<div class="weui-dialog"><div class="weui-dialog__hd"><strong class="weui-dialog__title">'+n.title+"</strong></div>"+(n.text?'<div class="weui-dialog__bd">'+n.text+"</div>":"")+'<div class="weui-dialog__ft">'+r+"</div></div>",s=t.openModal(o,i);return s.find(".weui-dialog__btn").each(function(e,i){var r=t(i);r.click(function(){n.autoClose&&t.closeModal(),a[e].onClick&&a[e].onClick.call(s)})}),s},t.openModal=function(e,n){var i=t("<div class='weui-mask'></div>").appendTo(document.body);i.show();var a=t(e).appendTo(document.body);return n&&a.transitionEnd(function(){n.call(a)}),a.show(),i.addClass("weui-mask--visible"),a.addClass("weui-dialog--visible"),a},t.closeModal=function(){t(".weui-mask--visible").removeClass("weui-mask--visible").transitionEnd(function(){t(this).remove()}),t(".weui-dialog--visible").removeClass("weui-dialog--visible").transitionEnd(function(){t(this).remove()})},t.alert=function(n,i,a){var r;return"object"==typeof n?r=n:("function"==typeof i&&(a=arguments[1],i=void 0),r={text:n,title:i,onOK:a}),t.modal({text:r.text,title:r.title,buttons:[{text:e.buttonOK,className:"primary",onClick:r.onOK}]})},t.confirm=function(n,i,a,r){var o;return"object"==typeof n?o=n:("function"==typeof i&&(r=arguments[2],a=arguments[1],i=void 0),o={text:n,title:i,onOK:a,onCancel:r}),t.modal({text:o.text,title:o.title,buttons:[{text:e.buttonCancel,className:"default",onClick:o.onCancel},{text:e.buttonOK,className:"primary",onClick:o.onOK}]})},t.prompt=function(n,i,a,r,o){var s;"object"==typeof n?s=n:("function"==typeof i&&(o=arguments[3],r=arguments[2],a=arguments[1],i=void 0),s={text:n,title:i,input:o,onOK:a,onCancel:r,empty:!1});var c=t.modal({text:'<p class="weui-prompt-text">'+(s.text||"")+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-input" value="'+(s.input||"")+'" />',title:s.title,autoClose:!1,buttons:[{text:e.buttonCancel,className:"default",onClick:function(){t.closeModal(),s.onCancel&&s.onCancel.call(c)}},{text:e.buttonOK,className:"primary",onClick:function(){var e=t("#weui-prompt-input").val();return s.empty||""!==e&&null!==e?(t.closeModal(),void(s.onOK&&s.onOK.call(c,e))):(c.find(".weui-prompt-input").focus()[0].select(),!1)}}]},function(){this.find(".weui-prompt-input").focus()[0].select()});return c},t.login=function(n,i,a,r,o,s){var c;"object"==typeof n?c=n:("function"==typeof i&&(s=arguments[4],o=arguments[3],r=arguments[2],a=arguments[1],i=void 0),c={text:n,title:i,username:o,password:s,onOK:a,onCancel:r});var l=t.modal({text:'<p class="weui-prompt-text">'+(c.text||"")+'</p><input type="text" class="weui-input weui-prompt-input" id="weui-prompt-username" value="'+(c.username||"")+'" placeholder="输入用户名" /><input type="password" class="weui-input weui-prompt-input" id="weui-prompt-password" value="'+(c.password||"")+'" placeholder="输入密码" />',title:c.title,autoClose:!1,buttons:[{text:e.buttonCancel,className:"default",onClick:function(){t.closeModal(),c.onCancel&&c.onCancel.call(l)}},{text:e.buttonOK,className:"primary",onClick:function(){var e=t("#weui-prompt-username").val(),n=t("#weui-prompt-password").val();return c.empty||""!==e&&null!==e?c.empty||""!==n&&null!==n?(t.closeModal(),void(c.onOK&&c.onOK.call(l,e,n))):(l.find("#weui-prompt-password").focus()[0].select(),!1):(l.find("#weui-prompt-username").focus()[0].select(),!1)}}]},function(){this.find("#weui-prompt-username").focus()[0].select()});return l},e=t.modal.prototype.defaults={title:"提示",text:void 0,buttonOK:"确定",buttonCancel:"取消",buttons:[{text:"确定",className:"primary"}],autoClose:!0}}($),+function(t){"use strict";var e=function(e,n){n=n||"";var i=(t("<div class='weui-mask_transparent'></div>").appendTo(document.body),'<div class="weui-toast '+n+'">'+e+"</div>"),a=t(i).appendTo(document.body);a.addClass("weui-toast--visible"),a.show()},n=function(e){t(".weui-mask_transparent").remove();var n=!1,i=t(".weui-toast--visible").removeClass("weui-toast--visible").transitionEnd(function(){var i=t(this);i.remove(),e&&e(),n=!0});setTimeout(function(){n||(i.remove(),e&&e())},1e3)};t.toast=function(t,a,r){"function"==typeof a&&(r=a);var o,s="weui-icon-success-no-circle",c=i.duration;"cancel"==a?(o="weui-toast_cancel",s="weui-icon-cancel"):"forbidden"==a?(o="weui-toast--forbidden",s="weui-icon-warn"):"text"==a?o="weui-toast--text":"number"==typeof a&&(c=a),e('<i class="'+s+' weui-icon_toast"></i><p class="weui-toast_content">'+(t||"已经完成")+"</p>",o),setTimeout(function(){n(r)},c)},t.showLoading=function(t){var n='<div class="weui_loading">';n+='<i class="weui-loading weui-icon_toast"></i>',n+="</div>",n+='<p class="weui-toast_content">'+(t||"数据加载中")+"</p>",e(n,"weui_loading_toast")},t.hideLoading=function(){n()};var i=t.toast.prototype.defaults={duration:2500}}($),+function(t){"use strict";var e,n=function(e){var n=t("<div class='weui-mask weui-actions_mask'></div>").appendTo(document.body),i=e.actions||[],a=i.map(function(t,e){return'<div class="weui-actionsheet__cell '+(t.className||"")+'">'+t.text+"</div>"}).join(""),r="";e.title&&(r='<div class="weui-actionsheet__title"><p class="weui-actionsheet__title-text">'+e.title+"</p></div>");var o='<div class="weui-actionsheet " id="weui-actionsheet">'+r+'<div class="weui-actionsheet__menu">'+a+'</div><div class="weui-actionsheet__action"><div class="weui-actionsheet__cell weui-actionsheet_cancel">取消</div></div></div>',s=t(o).appendTo(document.body);s.find(".weui-actionsheet__menu .weui-actionsheet__cell, .weui-actionsheet__action .weui-actionsheet__cell").each(function(n,a){t(a).click(function(){t.closeActions(),e.onClose&&e.onClose(),i[n]&&i[n].onClick&&i[n].onClick()})}),n.show(),s.show(),n.addClass("weui-mask--visible"),s.addClass("weui-actionsheet_toggle")},i=function(){t(".weui-mask").removeClass("weui-mask--visible").transitionEnd(function(){t(this).remove()}),t(".weui-actionsheet").removeClass("weui-actionsheet_toggle").transitionEnd(function(){t(this).remove()})};t.actions=function(i){i=t.extend({},e,i),n(i)},t.closeActions=function(){i()},t(document).on("click",".weui-actions_mask",function(){t.closeActions()});var e=t.actions.prototype.defaults={title:void 0,onClose:void 0}}($),+function(t){"use strict";var e=function(n,i){"function"==typeof i&&(i={onRefresh:i}),"string"==typeof i&&(i=void 0),this.opt=t.extend(e.defaults,i||{}),this.container=t(n),this.attachEvents()};e.defaults={distance:50,onRefresh:void 0,onPull:void 0},e.prototype.touchStart=function(e){if(!this.container.hasClass("refreshing")){var n=t.getTouchPosition(e);this.start=n,this.diffX=this.diffY=0}},e.prototype.touchMove=function(e){if(!this.container.hasClass("refreshing")){if(!this.start)return!1;if(!(this.container.scrollTop()>0)){var n=t.getTouchPosition(e);return this.diffX=n.x-this.start.x,this.diffY=n.y-this.start.y,Math.abs(this.diffX)>Math.abs(this.diffY)||void(this.diffY<0||(this.container.addClass("touching"),e.preventDefault(),e.stopPropagation(),this.diffY=Math.pow(this.diffY,.75),this.container.css("transform","translate3d(0, "+this.diffY+"px, 0)"),this.triggerPull(this.diffY)))}}},e.prototype.touchEnd=function(){this.start=!1,this.diffY<=0||this.container.hasClass("refreshing")||(this.container.removeClass("touching"),this.container.removeClass("pull-down pull-up"),this.container.css("transform",""),Math.abs(this.diffY)<=this.opt.distance||this.triggerPullToRefresh())},e.prototype.triggerPullToRefresh=function(){this.triggerPull(this.opt.distance),this.container.removeClass("pull-up").addClass("refreshing"),this.opt.onRefresh&&this.opt.onRefresh.call(this),this.container.trigger("pull-to-refresh")},e.prototype.triggerPull=function(t){t<this.opt.distance?this.container.removeClass("pull-up").addClass("pull-down"):this.container.removeClass("pull-down").addClass("pull-up"),this.opt.onPull&&this.opt.onPull.call(this,Math.floor(t/this.opt.distance*100)),this.container.trigger("pull")},e.prototype.pullToRefreshDone=function(){this.container.removeClass("refreshing")},e.prototype.attachEvents=function(){var e=this.container;e.addClass("weui-pull-to-refresh"),e.on(t.touchEvents.start,t.proxy(this.touchStart,this)),e.on(t.touchEvents.move,t.proxy(this.touchMove,this)),e.on(t.touchEvents.end,t.proxy(this.touchEnd,this))};var n=function(e){t(e).removeClass("refreshing")};t.fn.pullToRefresh=function(n){return this.each(function(){var i=t(this),a=i.data("ptr");a||i.data("ptr",a=new e(this,n)),"string"==typeof n&&a[n].call(a)})},t.fn.pullToRefreshDone=function(){return this.each(function(){n(this)})}}($),+function(t){"use strict";var e=function(e){var n,i=e[0].tagName.toUpperCase();n="BODY"===i||"HTML"===i?e.scrollTop()||t(window).scrollTop():e.scrollTop();var a=e.scrollHeight()-(t(window).height()+n);return console.log(a),a},n=function(e,n){this.container=t(e),this.container.data("infinite",this),this.distance=n||50,this.attachEvents()};n.prototype.scroll=function(){this.container;this._check()},n.prototype.attachEvents=function(e){var n=this.container,i="BODY"===n[0].tagName.toUpperCase()?t(document):n;i[e?"off":"on"]("scroll",t.proxy(this.scroll,this))},n.prototype.detachEvents=function(t){this.attachEvents(!0)},n.prototype._check=function(){var t=e(this.container);Math.abs(t)<=this.distance&&this.container.trigger("infinite")};t.fn.infinite=function(t){return this.each(function(){new n(this,t)})},t.fn.destroyInfinite=function(){return this.each(function(){var e=t(this).data("infinite");e&&e.detachEvents&&e.detachEvents()})}}($),+function(t){"use strict";var e="weui-bar__item--on",n=function(n){var i=t(n);if(!i.hasClass(e)){var a=i.attr("href");if(/^#/.test(a)){i.parent().find("."+e).removeClass(e),i.addClass(e);var r=i.parents(".weui-tab").find(".weui-tab__bd");r.find(".weui-tab__bd-item--active").removeClass("weui-tab__bd-item--active"),t(a).addClass("weui-tab__bd-item--active")}}};t.showTab=n,t(document).on("click",".weui-navbar__item, .weui-tabbar__item",function(i){var a=t(i.currentTarget),r=a.attr("href");a.hasClass(e)||/^#/.test(r)&&(i.preventDefault(),n(a))})}($),+function(t){"use strict";t(document).on("click touchstart",".weui-search-bar__label",function(e){t(e.target).parents(".weui-search-bar").addClass("weui-search-bar_focusing").find("input").focus()}).on("click",".weui-search-bar__cancel-btn",function(e){t(e.target).parents(".weui-search-bar").removeClass("weui-search-bar_focusing").find(".weui-search-bar__input").val("").blur()}).on("click",".weui-icon-clear",function(e){t(e.target).parents(".weui-search-bar").find(".weui-search-bar__input").val("").focus()})}($),function(t){"use strict";var e={},n=navigator.userAgent,i=n.match(/(Android);?[\s\/]+([\d.]+)?/),a=n.match(/(iPad).*OS\s([\d_]+)/),r=n.match(/(iPod)(.*OS\s([\d_]+))?/),o=!a&&n.match(/(iPhone\sOS)\s([\d_]+)/);if(e.ios=e.android=e.iphone=e.ipad=e.androidChrome=!1,i&&(e.os="android",e.osVersion=i[2],e.android=!0,e.androidChrome=n.toLowerCase().indexOf("chrome")>=0),(a||o||r)&&(e.os="ios",e.ios=!0),o&&!r&&(e.osVersion=o[2].replace(/_/g,"."),e.iphone=!0),a&&(e.osVersion=a[2].replace(/_/g,"."),e.ipad=!0),r&&(e.osVersion=r[3]?r[3].replace(/_/g,"."):null,e.iphone=!0),e.ios&&e.osVersion&&n.indexOf("Version/")>=0&&"10"===e.osVersion.split(".")[0]&&(e.osVersion=n.toLowerCase().split("version/")[1].split(" ")[0]),
+e.webView=(o||a||r)&&n.match(/.*AppleWebKit(?!.*Safari)/i),e.os&&"ios"===e.os){var s=e.osVersion.split(".");e.minimalUi=!e.webView&&(r||o)&&(1*s[0]===7?1*s[1]>=1:1*s[0]>7)&&t('meta[name="viewport"]').length>0&&t('meta[name="viewport"]').attr("content").indexOf("minimal-ui")>=0}var c=t(window).width(),l=t(window).height();e.statusBar=!1,e.webView&&c*l===screen.width*screen.height?e.statusBar=!0:e.statusBar=!1;var u=[];if(e.pixelRatio=window.devicePixelRatio||1,u.push("pixel-ratio-"+Math.floor(e.pixelRatio)),e.pixelRatio>=2&&u.push("retina"),e.os&&(u.push(e.os,e.os+"-"+e.osVersion.split(".")[0],e.os+"-"+e.osVersion.replace(/\./g,"-")),"ios"===e.os))for(var p=parseInt(e.osVersion.split(".")[0],10),h=p-1;h>=6;h--)u.push("ios-gt-"+h);e.statusBar?u.push("with-statusbar-overlay"):t("html").removeClass("with-statusbar-overlay"),u.length>0&&t("html").addClass(u.join(" ")),t.device=e}($),+function(t){"use strict";var e=function(e){function n(){var e=!1;return c.params.convertToPopover||c.params.onlyInPopover?(!c.inline&&c.params.input&&(c.params.onlyInPopover?e=!0:t.device.ios?e=!!t.device.ipad:t(window).width()>=768&&(e=!0)),e):e}function i(){return!!(c.opened&&c.container&&c.container.length>0&&c.container.parents(".popover").length>0)}function a(){if(c.opened)for(var t=0;t<c.cols.length;t++)c.cols[t].divider||(c.cols[t].calcSize(),c.cols[t].setValue(c.cols[t].value,0,!1))}function r(t){if(t.preventDefault(),!c.opened&&(c.open(),c.params.scrollToInput&&!n())){var e=c.input.parents(".content");if(0===e.length)return;var i,a=parseInt(e.css("padding-top"),10),r=parseInt(e.css("padding-bottom"),10),o=e[0].offsetHeight-a-c.container.height(),s=e[0].scrollHeight-a-c.container.height(),l=c.input.offset().top-a+c.input[0].offsetHeight;if(l>o){var u=e.scrollTop()+l-o;u+o>s&&(i=u+o-s+r,o===s&&(i=c.container.height()),e.css({"padding-bottom":i+"px"})),e.scrollTop(u,300)}}}function o(e){i()||(c.input&&c.input.length>0?e.target!==c.input[0]&&0===t(e.target).parents(".weui-picker-modal").length&&c.close():0===t(e.target).parents(".weui-picker-modal").length&&c.close())}function s(){c.opened=!1,c.input&&c.input.length>0&&c.input.parents(".page-content").css({"padding-bottom":""}),c.params.onClose&&c.params.onClose(c),c.container.find(".picker-items-col").each(function(){c.destroyPickerCol(this)})}var c=this,l={updateValuesOnMomentum:!1,updateValuesOnTouchmove:!0,rotateEffect:!1,momentumRatio:7,freeMode:!1,scrollToInput:!0,inputReadOnly:!0,toolbar:!0,toolbarCloseText:"完成",title:"请选择",toolbarTemplate:'<div class="toolbar">          <div class="toolbar-inner">          <a href="javascript:;" class="picker-button close-picker">{{closeText}}</a>          <h1 class="title">{{title}}</h1>          </div>          </div>'};e=e||{};for(var u in l)"undefined"==typeof e[u]&&(e[u]=l[u]);c.params=e,c.cols=[],c.initialized=!1,c.inline=!!c.params.container;var p=t.device.ios||navigator.userAgent.toLowerCase().indexOf("safari")>=0&&navigator.userAgent.toLowerCase().indexOf("chrome")<0&&!t.device.android;return c.setValue=function(t,e){for(var n=0,i=0;i<c.cols.length;i++)c.cols[i]&&!c.cols[i].divider&&(c.cols[i].setValue(t[n],e),n++)},c.updateValue=function(){for(var e=[],n=[],i=0;i<c.cols.length;i++)c.cols[i].divider||(e.push(c.cols[i].value),n.push(c.cols[i].displayValue));e.indexOf(void 0)>=0||(c.value=e,c.displayValue=n,c.params.onChange&&c.params.onChange(c,c.value,c.displayValue),c.input&&c.input.length>0&&(t(c.input).val(c.params.formatValue?c.params.formatValue(c,c.value,c.displayValue):c.value.join(" ")),t(c.input).trigger("change")))},c.initPickerCol=function(e,n){function i(){w=t.requestAnimationFrame(function(){h.updateItems(void 0,void 0,0),i()})}function a(e){if(!T&&!y){e.preventDefault(),y=!0;var n=t.getTouchPosition(e);k=x=n.y,C=(new Date).getTime(),A=!0,M=E=t.getTranslate(h.wrapper[0],"y")}}function r(e){if(y){e.preventDefault(),A=!1;var n=t.getTouchPosition(e);x=n.y,T||(t.cancelAnimationFrame(w),T=!0,M=E=t.getTranslate(h.wrapper[0],"y"),h.wrapper.transition(0)),e.preventDefault();var i=x-k;E=M+i,_=void 0,E<v&&(E=v-Math.pow(v-E,.8),_="min"),E>g&&(E=g+Math.pow(E-g,.8),_="max"),h.wrapper.transform("translate3d(0,"+E+"px,0)"),h.updateItems(void 0,E,0,c.params.updateValuesOnTouchmove),P=E-D||E,O=(new Date).getTime(),D=E}}function o(e){if(!y||!T)return void(y=T=!1);y=T=!1,h.wrapper.transition(""),_&&("min"===_?h.wrapper.transform("translate3d(0,"+v+"px,0)"):h.wrapper.transform("translate3d(0,"+g+"px,0)")),b=(new Date).getTime();var n,a;b-C>300?a=E:(n=Math.abs(P/(b-O)),a=E+P*c.params.momentumRatio),a=Math.max(Math.min(a,g),v);var r=-Math.floor((a-g)/f);c.params.freeMode||(a=-r*f+g),h.wrapper.transform("translate3d(0,"+parseInt(a,10)+"px,0)"),h.updateItems(r,a,"",!0),c.params.updateValuesOnMomentum&&(i(),h.wrapper.transitionEnd(function(){t.cancelAnimationFrame(w)})),setTimeout(function(){A=!0},100)}function s(e){if(A){t.cancelAnimationFrame(w);var n=t(this).attr("data-picker-value");h.setValue(n)}}var l=t(e),u=l.index(),h=c.cols[u];if(!h.divider){h.container=l,h.wrapper=h.container.find(".picker-items-col-wrapper"),h.items=h.wrapper.find(".picker-item");var d,f,m,v,g;h.replaceValues=function(t,e){h.destroyEvents(),h.values=t,h.displayValues=e;var n=c.columnHTML(h,!0);h.wrapper.html(n),h.items=h.wrapper.find(".picker-item"),h.calcSize(),h.setValue(h.values[0]||"",0,!0),h.initEvents()},h.calcSize=function(){if(h.values.length){c.params.rotateEffect&&(h.container.removeClass("picker-items-col-absolute"),h.width||h.container.css({width:""}));var e,n;e=0,n=h.container[0].offsetHeight,d=h.wrapper[0].offsetHeight,f=h.items[0].offsetHeight,m=f*h.items.length,v=n/2-m+f/2,g=n/2-f/2,h.width&&(e=h.width,parseInt(e,10)===e&&(e+="px"),h.container.css({width:e})),c.params.rotateEffect&&(h.width||(h.items.each(function(){var n=t(this);n.css({width:"auto"}),e=Math.max(e,n[0].offsetWidth),n.css({width:""})}),h.container.css({width:e+2+"px"})),h.container.addClass("picker-items-col-absolute"))}},h.calcSize(),h.wrapper.transform("translate3d(0,"+g+"px,0)").transition(0);var w;h.setValue=function(e,n,a){"undefined"==typeof n&&(n="");var r=h.wrapper.find('.picker-item[data-picker-value="'+e+'"]').index();if("undefined"==typeof r||r===-1)return void(h.value=h.displayValue=e);var o=-r*f+g;h.wrapper.transition(n),h.wrapper.transform("translate3d(0,"+o+"px,0)"),c.params.updateValuesOnMomentum&&h.activeIndex&&h.activeIndex!==r&&(t.cancelAnimationFrame(w),h.wrapper.transitionEnd(function(){t.cancelAnimationFrame(w)}),i()),h.updateItems(r,o,n,a)},h.updateItems=function(e,n,i,a){"undefined"==typeof n&&(n=t.getTranslate(h.wrapper[0],"y")),"undefined"==typeof e&&(e=-Math.round((n-g)/f)),e<0&&(e=0),e>=h.items.length&&(e=h.items.length-1);var r=h.activeIndex;h.activeIndex=e,h.wrapper.find(".picker-selected").removeClass("picker-selected"),c.params.rotateEffect&&h.items.transition(i);var o=h.items.eq(e).addClass("picker-selected").transform("");if((a||"undefined"==typeof a)&&(h.value=o.attr("data-picker-value"),h.displayValue=h.displayValues?h.displayValues[e]:h.value,r!==e&&(h.onChange&&h.onChange(c,h.value,h.displayValue),c.updateValue())),c.params.rotateEffect){(n-(Math.floor((n-g)/f)*f+g))/f;h.items.each(function(){var e=t(this),i=e.index()*f,a=g-n,r=i-a,o=r/f,s=Math.ceil(h.height/f/2)+1,c=-18*o;c>180&&(c=180),c<-180&&(c=-180),Math.abs(o)>s?e.addClass("picker-item-far"):e.removeClass("picker-item-far"),e.transform("translate3d(0, "+(-n+g)+"px, "+(p?-110:0)+"px) rotateX("+c+"deg)")})}},n&&h.updateItems(0,g,0);var y,T,k,x,C,b,M,_,E,D,P,O,A=!0;h.initEvents=function(e){var n=e?"off":"on";h.container[n](t.touchEvents.start,a),h.container[n](t.touchEvents.move,r),h.container[n](t.touchEvents.end,o),h.items[n]("click",s)},h.destroyEvents=function(){h.initEvents(!0)},h.container[0].f7DestroyPickerCol=function(){h.destroyEvents()},h.initEvents()}},c.destroyPickerCol=function(e){e=t(e),"f7DestroyPickerCol"in e[0]&&e[0].f7DestroyPickerCol()},t(window).on("resize",a),c.columnHTML=function(t,e){var n="",i="";if(t.divider)i+='<div class="picker-items-col picker-items-col-divider '+(t.textAlign?"picker-items-col-"+t.textAlign:"")+" "+(t.cssClass||"")+'">'+t.content+"</div>";else{for(var a=0;a<t.values.length;a++)n+='<div class="picker-item" data-picker-value="'+t.values[a]+'">'+(t.displayValues?t.displayValues[a]:t.values[a])+"</div>";i+='<div class="picker-items-col '+(t.textAlign?"picker-items-col-"+t.textAlign:"")+" "+(t.cssClass||"")+'"><div class="picker-items-col-wrapper">'+n+"</div></div>"}return e?n:i},c.layout=function(){var t,e="",n="";c.cols=[];var i="";for(t=0;t<c.params.cols.length;t++){var a=c.params.cols[t];i+=c.columnHTML(c.params.cols[t]),c.cols.push(a)}n="weui-picker-modal picker-columns "+(c.params.cssClass||"")+(c.params.rotateEffect?" picker-3d":"")+(1===c.params.cols.length?" picker-columns-single":""),e='<div class="'+n+'">'+(c.params.toolbar?c.params.toolbarTemplate.replace(/{{closeText}}/g,c.params.toolbarCloseText).replace(/{{title}}/g,c.params.title):"")+'<div class="picker-modal-inner picker-items">'+i+'<div class="picker-center-highlight"></div></div></div>',c.pickerHTML=e},c.params.input&&(c.input=t(c.params.input),c.input.length>0&&(c.params.inputReadOnly&&c.input.prop("readOnly",!0),c.inline||c.input.on("click",r),c.params.inputReadOnly&&c.input.on("focus mousedown",function(t){t.preventDefault()}))),c.inline||t("html").on("click",o),c.opened=!1,c.open=function(){var e=n();c.opened||(c.layout(),e?(c.pickerHTML='<div class="popover popover-picker-columns"><div class="popover-inner">'+c.pickerHTML+"</div></div>",c.popover=t.popover(c.pickerHTML,c.params.input,!0),c.container=t(c.popover).find(".weui-picker-modal"),t(c.popover).on("close",function(){s()})):c.inline?(c.container=t(c.pickerHTML),c.container.addClass("picker-modal-inline"),t(c.params.container).append(c.container)):(c.container=t(t.openPicker(c.pickerHTML)),t(c.container).on("close",function(){s()})),c.container[0].f7Picker=c,c.container.find(".picker-items-col").each(function(){var t=!0;(!c.initialized&&c.params.value||c.initialized&&c.value)&&(t=!1),c.initPickerCol(this,t)}),c.initialized?c.value&&c.setValue(c.value,0):c.params.value&&c.setValue(c.params.value,0)),c.opened=!0,c.initialized=!0,c.params.onOpen&&c.params.onOpen(c)},c.close=function(e){if(c.opened&&!c.inline)return i()?void t.closePicker(c.popover):void t.closePicker(c.container)},c.destroy=function(){c.close(),c.params.input&&c.input.length>0&&(c.input.off("click focus",r),t(c.input).data("picker",null)),t("html").off("click",o),t(window).off("resize",a)},c.inline&&c.open(),c};t(document).on("click",".close-picker",function(){var e=t(".weui-picker-modal.weui-picker-modal-visible");e.length>0&&t.closePicker(e)}),t(document).on(t.touchEvents.move,".picker-modal-inner",function(t){t.preventDefault()}),t.openPicker=function(e,n,i){"function"==typeof n&&(i=n,n=void 0),t.closePicker();var a=t("<div class='weui-picker-container "+(n||"")+"'></div>").appendTo(document.body);a.show(),a.addClass("weui-picker-container-visible");var r=t(e).appendTo(a);return r.width(),r.addClass("weui-picker-modal-visible"),i&&a.on("close",i),r},t.updatePicker=function(e){var n=t(".weui-picker-container-visible");if(!n[0])return!1;n.html("");var i=t(e).appendTo(n);return i.addClass("weui-picker-modal-visible"),i},t.closePicker=function(e,n){"function"==typeof e&&(n=e),t(".weui-picker-modal-visible").removeClass("weui-picker-modal-visible").transitionEnd(function(){t(this).parent().remove(),n&&n()}).trigger("close")},t.fn.picker=function(n){var i=arguments;return this.each(function(){if(this){var a=t(this),r=a.data("picker");if(!r){n=t.extend({input:this},n||{});var o=a.val();void 0===n.value&&""!==o&&(n.value=n.cols&&n.cols.length>1?o.split(" "):[o]);var s=t.extend({input:this},n);r=new e(s),a.data("picker",r)}"string"==typeof n&&r[n].apply(r,Array.prototype.slice.call(i,1))}})}}($),+function(t){"use strict";var e,n=[],i=function(e,i){this.config=i,this.data={values:"",titles:"",origins:[],length:0},this.$input=t(e),this.$input.prop("readOnly",!0),this.initConfig(),i=this.config,this.$input.click(t.proxy(this.open,this)),n.push(this)};i.prototype.initConfig=function(){this.config=t.extend({},e,this.config);var n=this.config;n.items&&n.items.length&&(n.items=n.items.map(function(t,e){return"string"==typeof t?{title:t,value:t}:t}),this.tpl=t.t7.compile("<div class='weui-picker-modal weui-select-modal'>"+n.toolbarTemplate+(n.multi?n.checkboxTemplate:n.radioTemplate)+"</div>"),void 0!==n.input&&this.$input.val(n.input),this.parseInitValue(),this._init=!0)},i.prototype.updateInputValue=function(t,e){var n,i;this.config.multi?(n=t.join(this.config.split),i=e.join(this.config.split)):(n=t[0],i=e[0]);var a=[];this.config.items.forEach(function(e){t.each(function(t,n){e.value==n&&a.push(e)})}),this.$input.val(i).data("values",n),this.$input.attr("value",i).attr("data-values",n);var r={values:n,titles:i,valuesArray:t,titlesArray:e,origins:a,length:a.length};this.data=r,this.$input.trigger("change",r),this.config.onChange&&this.config.onChange.call(this,r)},i.prototype.parseInitValue=function(){var t=this.$input.val(),e=this.config.items;if(this._init||void 0!==t&&null!=t&&""!==t)for(var n=this.config.multi?t.split(this.config.split):[t],i=0;i<e.length;i++){e[i].checked=!1;for(var a=0;a<n.length;a++)e[i].title===n[a]&&(e[i].checked=!0)}},i.prototype._bind=function(e){var n=this,i=this.config;e.on("change",function(a){var r=e.find("input:checked"),o=r.map(function(){return t(this).val()}),s=r.map(function(){return t(this).data("title")});n.updateInputValue(o,s),i.autoClose&&!i.multi&&n.close()}).trigger("change").on("click",".close-select",function(){n.close()})},i.prototype.update=function(e){this.config=t.extend({},this.config,e),this.initConfig(),this._open&&this._bind(t.updatePicker(this.getHTML()))},i.prototype.open=function(e,i){if(!this._open){for(var a=0;a<n.length;a++){var r=n[a];if(r!==this&&r._open&&!r.close())return!1}this.parseInitValue();var o=this.config,s=this.dialog=t.openPicker(this.getHTML());this._bind(s),this._open=!0,o.onOpen&&o.onOpen(this)}},i.prototype.close=function(e,n){if(!this._open)return!1;var i=this,a=this.config.beforeClose;if(!n){if(a&&"function"==typeof a&&a.call(this,this.data.values,this.data.titles)===!1)return!1;if(this.config.multi){if(void 0!==this.config.min&&this.data.length<this.config.min)return t.toast("请至少选择"+this.config.min+"个","text"),!1;if(void 0!==this.config.max&&this.data.length>this.config.max)return t.toast("最多只能选择"+this.config.max+"个","text"),!1}}return t.closePicker(function(){i.onClose(),e&&e()}),!0},i.prototype.onClose=function(){this._open=!1,this.config.onClose&&this.config.onClose(this)},i.prototype.getHTML=function(t){var e=this.config;return this.tpl({items:e.items,title:e.title,closeText:e.closeText})},t.fn.select=function(e,n){return this.each(function(){var a=t(this);a.data("weui-select")||a.data("weui-select",new i(this,e));var r=a.data("weui-select");return"string"==typeof e&&r[e].call(r,n),r})},e=t.fn.select.prototype.defaults={items:[],input:void 0,title:"请选择",multi:!1,closeText:"确定",autoClose:!0,onChange:void 0,beforeClose:void 0,onClose:void 0,onOpen:void 0,split:",",min:void 0,max:void 0,toolbarTemplate:'<div class="toolbar">      <div class="toolbar-inner">      <a href="javascript:;" class="picker-button close-select">{{closeText}}</a>      <h1 class="title">{{title}}</h1>      </div>      </div>',radioTemplate:'<div class="weui-cells weui-cells_radio">        {{#items}}        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">          <div class="weui-cell__bd weui-cell_primary">            <p>{{this.title}}</p>          </div>          <div class="weui-cell__ft">            <input type="radio" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}">            <span class="weui-icon-checked"></span>          </div>        </label>        {{/items}}      </div>',checkboxTemplate:'<div class="weui-cells weui-cells_checkbox">        {{#items}}        <label class="weui-cell weui-check_label" for="weui-select-id-{{this.title}}">          <div class="weui-cell__bd weui-cell_primary">            <p>{{this.title}}</p>          </div>          <div class="weui-cell__ft">            <input type="checkbox" class="weui-check" name="weui-select" id="weui-select-id-{{this.title}}" value="{{this.value}}" {{#if this.checked}}checked="checked"{{/if}} data-title="{{this.title}}" >            <span class="weui-icon-checked"></span>          </div>        </label>        {{/items}}      </div>'}}($),+function(t){"use strict";var e,n=!1,i=function(t,e){var t=new Date(t),e=new Date(e);return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()},a=function(a){function r(){var e=!1;return p.params.convertToPopover||p.params.onlyInPopover?(!p.inline&&p.params.input&&(p.params.onlyInPopover?e=!0:t.device.ios?e=!!t.device.ipad:t(window).width()>=768&&(e=!0)),e):e}function o(){return!!(p.opened&&p.container&&p.container.length>0&&p.container.parents(".popover").length>0)}function s(t){t=new Date(t);var e=t.getFullYear(),n=t.getMonth(),i=n+1,a=t.getDate(),r=t.getDay();return p.params.dateFormat.replace(/yyyy/g,e).replace(/yy/g,(e+"").substring(2)).replace(/mm/g,i<10?"0"+i:i).replace(/m/g,i).replace(/MM/g,p.params.monthNames[n]).replace(/M/g,p.params.monthNamesShort[n]).replace(/dd/g,a<10?"0"+a:a).replace(/d/g,a).replace(/DD/g,p.params.dayNames[r]).replace(/D/g,p.params.dayNamesShort[r])}function c(t){if(t.preventDefault(),!p.opened&&(p.open(),p.params.scrollToInput&&!r())){var e=p.input.parents(".page-content");if(0===e.length)return;var n,i=parseInt(e.css("padding-top"),10),a=parseInt(e.css("padding-bottom"),10),o=e[0].offsetHeight-i-p.container.height(),s=e[0].scrollHeight-i-p.container.height(),c=p.input.offset().top-i+p.input[0].offsetHeight;if(c>o){var l=e.scrollTop()+c-o;l+o>s&&(n=l+o-s+a,o===s&&(n=p.container.height()),e.css({"padding-bottom":n+"px"})),e.scrollTop(l,300)}}}function l(e){o()||(p.input&&p.input.length>0?e.target!==p.input[0]&&0===t(e.target).parents(".weui-picker-modal").length&&p.close():0===t(e.target).parents(".weui-picker-modal").length&&p.close())}function u(){p.opened=!1,p.input&&p.input.length>0&&p.input.parents(".page-content").css({"padding-bottom":""}),p.params.onClose&&p.params.onClose(p),p.destroyCalendarEvents()}var p=this;a=a||{};for(var h in e)"undefined"==typeof a[h]&&(a[h]=e[h]);p.params=a,p.initialized=!1,p.inline=!!p.params.container,p.isH="horizontal"===p.params.direction;var d=p.isH&&n?-1:1;return p.animating=!1,p.addValue=function(t){if(p.params.multiple){p.value||(p.value=[]);for(var e,n=0;n<p.value.length;n++)i(t,p.value[n])&&(e=n);"undefined"==typeof e?p.value.push(t):p.value.splice(e,1),p.updateValue()}else p.value=[t],p.updateValue()},p.setValue=function(t){var e=new Date(t[0]);p.setYearMonth(e.getFullYear(),e.getMonth()),p.addValue(+e)},p.updateValue=function(){p.wrapper.find(".picker-calendar-day-selected").removeClass("picker-calendar-day-selected");var e,n;for(e=0;e<p.value.length;e++){var i=new Date(p.value[e]);p.wrapper.find('.picker-calendar-day[data-date="'+i.getFullYear()+"-"+i.getMonth()+"-"+i.getDate()+'"]').addClass("picker-calendar-day-selected")}if(p.params.onChange&&p.params.onChange(p,p.value.map(s),p.value.map(function(t){return+new Date("string"==typeof t?t.split(/\D/).filter(function(t){return!!t}).join("-"):t)})),p.input&&p.input.length>0){if(p.params.formatValue)n=p.params.formatValue(p,p.value);else{for(n=[],e=0;e<p.value.length;e++)n.push(s(p.value[e]));n=n.join(", ")}t(p.input).val(n),t(p.input).trigger("change")}},p.initCalendarEvents=function(){function e(e){if(!s&&!o){o=!0;var n=t.getTouchPosition(e);c=h=n.x,l=h=n.y,f=(new Date).getTime(),T=0,C=!0,x=void 0,v=g=p.monthsTranslate}}function i(e){if(o){var n=t.getTouchPosition(e);if(u=n.x,h=n.y,"undefined"==typeof x&&(x=!!(x||Math.abs(h-l)>Math.abs(u-c))),p.isH&&x)return void(o=!1);if(e.preventDefault(),p.animating)return void(o=!1);C=!1,s||(s=!0,w=p.wrapper[0].offsetWidth,y=p.wrapper[0].offsetHeight,p.wrapper.transition(0)),e.preventDefault(),k=p.isH?u-c:h-l,T=k/(p.isH?w:y),g=100*(p.monthsTranslate*d+T),p.wrapper.transform("translate3d("+(p.isH?g:0)+"%, "+(p.isH?0:g)+"%, 0)")}}function a(t){return o&&s?(o=s=!1,m=(new Date).getTime(),m-f<300?Math.abs(k)<10?p.resetMonth():k>=10?n?p.nextMonth():p.prevMonth():n?p.prevMonth():p.nextMonth():T<=-.5?n?p.prevMonth():p.nextMonth():T>=.5?n?p.nextMonth():p.prevMonth():p.resetMonth(),void setTimeout(function(){C=!0},100)):void(o=s=!1)}function r(e){if(C){var n=t(e.target).parents(".picker-calendar-day");if(0===n.length&&t(e.target).hasClass("picker-calendar-day")&&(n=t(e.target)),0!==n.length&&!n.hasClass("picker-calendar-day-disabled")){n.hasClass("picker-calendar-day-next")&&p.nextMonth(),n.hasClass("picker-calendar-day-prev")&&p.prevMonth();var i=n.attr("data-year"),a=n.attr("data-month"),r=n.attr("data-day");p.params.onDayClick&&p.params.onDayClick(p,n[0],i,a,r),p.addValue(new Date(i,a,r).getTime()),p.params.closeOnSelect&&!p.params.multiple&&p.close()}}}var o,s,c,l,u,h,f,m,v,g,w,y,T,k,x,C=!0;p.container.find(".picker-calendar-prev-month").on("click",p.prevMonth),p.container.find(".picker-calendar-next-month").on("click",p.nextMonth),p.container.find(".picker-calendar-prev-year").on("click",p.prevYear),p.container.find(".picker-calendar-next-year").on("click",p.nextYear),p.wrapper.on("click",r),p.params.touchMove&&(p.wrapper.on(t.touchEvents.start,e),p.wrapper.on(t.touchEvents.move,i),p.wrapper.on(t.touchEvents.end,a)),p.container[0].f7DestroyCalendarEvents=function(){p.container.find(".picker-calendar-prev-month").off("click",p.prevMonth),p.container.find(".picker-calendar-next-month").off("click",p.nextMonth),p.container.find(".picker-calendar-prev-year").off("click",p.prevYear),p.container.find(".picker-calendar-next-year").off("click",p.nextYear),p.wrapper.off("click",r),p.params.touchMove&&(p.wrapper.off(t.touchEvents.start,e),p.wrapper.off(t.touchEvents.move,i),p.wrapper.off(t.touchEvents.end,a))}},p.destroyCalendarEvents=function(t){"f7DestroyCalendarEvents"in p.container[0]&&p.container[0].f7DestroyCalendarEvents()},p.daysInMonth=function(t){var e=new Date(t);return new Date(e.getFullYear(),e.getMonth()+1,0).getDate()},p.monthHTML=function(t,e){t=new Date(t);var n=t.getFullYear(),i=t.getMonth();t.getDate();"next"===e&&(t=11===i?new Date(n+1,0):new Date(n,i+1,1)),"prev"===e&&(t=0===i?new Date(n-1,11):new Date(n,i-1,1)),"next"!==e&&"prev"!==e||(i=t.getMonth(),n=t.getFullYear());var a=p.daysInMonth(new Date(t.getFullYear(),t.getMonth()).getTime()-864e6),r=p.daysInMonth(t),o=new Date(t.getFullYear(),t.getMonth()).getDay();0===o&&(o=7);var s,c,l,u=[],h=6,d=7,f="",m=0+(p.params.firstDay-1),v=(new Date).setHours(0,0,0,0),g=p.params.minDate?new Date(p.params.minDate).getTime():null,w=p.params.maxDate?new Date(p.params.maxDate).getTime():null;if(p.value&&p.value.length)for(c=0;c<p.value.length;c++)u.push(new Date(p.value[c]).setHours(0,0,0,0));for(c=1;c<=h;c++){var y="";for(l=1;l<=d;l++){var T=l;m++;var k=m-o,x="";k<0?(k=a+k+1,x+=" picker-calendar-day-prev",s=new Date(i-1<0?n-1:n,i-1<0?11:i-1,k).getTime()):(k+=1,k>r?(k-=r,x+=" picker-calendar-day-next",s=new Date(i+1>11?n+1:n,i+1>11?0:i+1,k).getTime()):s=new Date(n,i,k).getTime()),s===v&&(x+=" picker-calendar-day-today"),u.indexOf(s)>=0&&(x+=" picker-calendar-day-selected"),p.params.weekendDays.indexOf(T-1)>=0&&(x+=" picker-calendar-day-weekend"),(g&&s<g||w&&s>w)&&(x+=" picker-calendar-day-disabled"),s=new Date(s);var C=s.getFullYear(),b=s.getMonth();y+='<div data-year="'+C+'" data-month="'+b+'" data-day="'+k+'" class="picker-calendar-day'+x+'" data-date="'+(C+"-"+b+"-"+k)+'"><span>'+k+"</span></div>"}f+='<div class="picker-calendar-row">'+y+"</div>"}return f='<div class="picker-calendar-month" data-year="'+n+'" data-month="'+i+'">'+f+"</div>"},p.animating=!1,p.updateCurrentMonthYear=function(t){"undefined"==typeof t?(p.currentMonth=parseInt(p.months.eq(1).attr("data-month"),10),p.currentYear=parseInt(p.months.eq(1).attr("data-year"),10)):(p.currentMonth=parseInt(p.months.eq("next"===t?p.months.length-1:0).attr("data-month"),10),p.currentYear=parseInt(p.months.eq("next"===t?p.months.length-1:0).attr("data-year"),10)),p.container.find(".current-month-value").text(p.params.monthNames[p.currentMonth]),p.container.find(".current-year-value").text(p.currentYear)},p.onMonthChangeStart=function(t){p.updateCurrentMonthYear(t),p.months.removeClass("picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next");var e="next"===t?p.months.length-1:0;p.months.eq(e).addClass("picker-calendar-month-current"),p.months.eq("next"===t?e-1:e+1).addClass("next"===t?"picker-calendar-month-prev":"picker-calendar-month-next"),p.params.onMonthYearChangeStart&&p.params.onMonthYearChangeStart(p,p.currentYear,p.currentMonth)},p.onMonthChangeEnd=function(t,e){p.animating=!1;var n,i,a;p.wrapper.find(".picker-calendar-month:not(.picker-calendar-month-prev):not(.picker-calendar-month-current):not(.picker-calendar-month-next)").remove(),"undefined"==typeof t&&(t="next",e=!0),e?(p.wrapper.find(".picker-calendar-month-next, .picker-calendar-month-prev").remove(),i=p.monthHTML(new Date(p.currentYear,p.currentMonth),"prev"),n=p.monthHTML(new Date(p.currentYear,p.currentMonth),"next")):a=p.monthHTML(new Date(p.currentYear,p.currentMonth),t),("next"===t||e)&&p.wrapper.append(a||n),("prev"===t||e)&&p.wrapper.prepend(a||i),p.months=p.wrapper.find(".picker-calendar-month"),p.setMonthsTranslate(p.monthsTranslate),p.params.onMonthAdd&&p.params.onMonthAdd(p,"next"===t?p.months.eq(p.months.length-1)[0]:p.months.eq(0)[0]),p.params.onMonthYearChangeEnd&&p.params.onMonthYearChangeEnd(p,p.currentYear,p.currentMonth)},p.setMonthsTranslate=function(t){t=t||p.monthsTranslate||0,"undefined"==typeof p.monthsTranslate&&(p.monthsTranslate=t),p.months.removeClass("picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next");var e=100*-(t+1)*d,n=100*-t*d,i=100*-(t-1)*d;p.months.eq(0).transform("translate3d("+(p.isH?e:0)+"%, "+(p.isH?0:e)+"%, 0)").addClass("picker-calendar-month-prev"),p.months.eq(1).transform("translate3d("+(p.isH?n:0)+"%, "+(p.isH?0:n)+"%, 0)").addClass("picker-calendar-month-current"),p.months.eq(2).transform("translate3d("+(p.isH?i:0)+"%, "+(p.isH?0:i)+"%, 0)").addClass("picker-calendar-month-next")},p.nextMonth=function(e){"undefined"!=typeof e&&"object"!=typeof e||(e="",p.params.animate||(e=0));var n=parseInt(p.months.eq(p.months.length-1).attr("data-month"),10),i=parseInt(p.months.eq(p.months.length-1).attr("data-year"),10),a=new Date(i,n),r=a.getTime(),o=!p.animating;if(p.params.maxDate&&r>new Date(p.params.maxDate).getTime())return p.resetMonth();if(p.monthsTranslate--,n===p.currentMonth){var s=100*-p.monthsTranslate*d,c=t(p.monthHTML(r,"next")).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-next");p.wrapper.append(c[0]),p.months=p.wrapper.find(".picker-calendar-month"),p.params.onMonthAdd&&p.params.onMonthAdd(p,p.months.eq(p.months.length-1)[0])}p.animating=!0,p.onMonthChangeStart("next");var l=100*p.monthsTranslate*d;p.wrapper.transition(e).transform("translate3d("+(p.isH?l:0)+"%, "+(p.isH?0:l)+"%, 0)"),o&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd("next")}),p.params.animate||p.onMonthChangeEnd("next")},p.prevMonth=function(e){"undefined"!=typeof e&&"object"!=typeof e||(e="",p.params.animate||(e=0));var n=parseInt(p.months.eq(0).attr("data-month"),10),i=parseInt(p.months.eq(0).attr("data-year"),10),a=new Date(i,n+1,(-1)),r=a.getTime(),o=!p.animating;if(p.params.minDate&&r<new Date(p.params.minDate).getTime())return p.resetMonth();if(p.monthsTranslate++,n===p.currentMonth){var s=100*-p.monthsTranslate*d,c=t(p.monthHTML(r,"prev")).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-prev");p.wrapper.prepend(c[0]),p.months=p.wrapper.find(".picker-calendar-month"),p.params.onMonthAdd&&p.params.onMonthAdd(p,p.months.eq(0)[0])}p.animating=!0,p.onMonthChangeStart("prev");var l=100*p.monthsTranslate*d;p.wrapper.transition(e).transform("translate3d("+(p.isH?l:0)+"%, "+(p.isH?0:l)+"%, 0)"),o&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd("prev")}),p.params.animate||p.onMonthChangeEnd("prev")},p.resetMonth=function(t){"undefined"==typeof t&&(t="");var e=100*p.monthsTranslate*d;p.wrapper.transition(t).transform("translate3d("+(p.isH?e:0)+"%, "+(p.isH?0:e)+"%, 0)")},p.setYearMonth=function(t,e,n){"undefined"==typeof t&&(t=p.currentYear),"undefined"==typeof e&&(e=p.currentMonth),"undefined"!=typeof n&&"object"!=typeof n||(n="",p.params.animate||(n=0));var i;if(i=t<p.currentYear?new Date(t,e+1,(-1)).getTime():new Date(t,e).getTime(),p.params.maxDate&&i>new Date(p.params.maxDate).getTime())return!1;if(p.params.minDate&&i<new Date(p.params.minDate).getTime())return!1;var a=new Date(p.currentYear,p.currentMonth).getTime(),r=i>a?"next":"prev",o=p.monthHTML(new Date(t,e));p.monthsTranslate=p.monthsTranslate||0;var s,c,l=p.monthsTranslate,u=!p.animating;i>a?(p.monthsTranslate--,p.animating||p.months.eq(p.months.length-1).remove(),p.wrapper.append(o),p.months=p.wrapper.find(".picker-calendar-month"),s=100*-(l-1)*d,p.months.eq(p.months.length-1).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-next")):(p.monthsTranslate++,p.animating||p.months.eq(0).remove(),p.wrapper.prepend(o),p.months=p.wrapper.find(".picker-calendar-month"),s=100*-(l+1)*d,p.months.eq(0).transform("translate3d("+(p.isH?s:0)+"%, "+(p.isH?0:s)+"%, 0)").addClass("picker-calendar-month-prev")),p.params.onMonthAdd&&p.params.onMonthAdd(p,"next"===r?p.months.eq(p.months.length-1)[0]:p.months.eq(0)[0]),p.animating=!0,p.onMonthChangeStart(r),c=100*p.monthsTranslate*d,p.wrapper.transition(n).transform("translate3d("+(p.isH?c:0)+"%, "+(p.isH?0:c)+"%, 0)"),u&&p.wrapper.transitionEnd(function(){p.onMonthChangeEnd(r,!0)}),p.params.animate||p.onMonthChangeEnd(r)},p.nextYear=function(){p.setYearMonth(p.currentYear+1)},p.prevYear=function(){p.setYearMonth(p.currentYear-1)},p.layout=function(){var t,e="",n="",i=p.value&&p.value.length?p.value[0]:(new Date).setHours(0,0,0,0),a=p.monthHTML(i,"prev"),r=p.monthHTML(i),o=p.monthHTML(i,"next"),s='<div class="picker-calendar-months"><div class="picker-calendar-months-wrapper">'+(a+r+o)+"</div></div>",c="";if(p.params.weekHeader){for(t=0;t<7;t++){var l=t+p.params.firstDay>6?t-7+p.params.firstDay:t+p.params.firstDay,u=p.params.dayNamesShort[l];c+='<div class="picker-calendar-week-day '+(p.params.weekendDays.indexOf(l)>=0?"picker-calendar-week-day-weekend":"")+'"> '+u+"</div>"}c='<div class="picker-calendar-week-days">'+c+"</div>"}n="weui-picker-calendar "+(p.params.cssClass||""),p.inline||(n="weui-picker-modal "+n);var h=p.params.toolbar?p.params.toolbarTemplate.replace(/{{closeText}}/g,p.params.toolbarCloseText):"";p.params.toolbar&&(h=p.params.toolbarTemplate.replace(/{{closeText}}/g,p.params.toolbarCloseText).replace(/{{monthPicker}}/g,p.params.monthPicker?p.params.monthPickerTemplate:"").replace(/{{yearPicker}}/g,p.params.yearPicker?p.params.yearPickerTemplate:"")),e='<div class="'+n+'">'+h+'<div class="picker-modal-inner">'+c+s+"</div></div>",p.pickerHTML=e},p.params.input&&(p.input=t(p.params.input),p.input.length>0&&(p.params.inputReadOnly&&p.input.prop("readOnly",!0),p.inline||p.input.on("click",c),p.params.inputReadOnly&&p.input.on("focus mousedown",function(t){t.preventDefault()}))),p.inline||t(document).on("click touchend",l),p.opened=!1,p.open=function(){var e=r()&&!1,n=!1;p.opened||(p.value||p.params.value&&(p.value=p.params.value,n=!0),p.layout(),e?(p.pickerHTML='<div class="popover popover-picker-calendar"><div class="popover-inner">'+p.pickerHTML+"</div></div>",p.popover=t.popover(p.pickerHTML,p.params.input,!0),p.container=t(p.popover).find(".weui-picker-modal"),
+t(p.popover).on("close",function(){u()})):p.inline?(p.container=t(p.pickerHTML),p.container.addClass("picker-modal-inline"),t(p.params.container).append(p.container)):(p.container=t(t.openPicker(p.pickerHTML)),t(p.container).on("close",function(){u()})),p.container[0].f7Calendar=p,p.wrapper=p.container.find(".picker-calendar-months-wrapper"),p.months=p.wrapper.find(".picker-calendar-month"),p.updateCurrentMonthYear(),p.monthsTranslate=0,p.setMonthsTranslate(),p.initCalendarEvents(),n&&p.updateValue()),p.opened=!0,p.initialized=!0,p.params.onMonthAdd&&p.months.each(function(){p.params.onMonthAdd(p,this)}),p.params.onOpen&&p.params.onOpen(p)},p.close=function(){if(p.opened&&!p.inline)return p.animating=!1,o()?void t.closePicker(p.popover):void t.closePicker(p.container)},p.destroy=function(){p.close(),p.params.input&&p.input.length>0&&(p.input.off("click focus",c),p.input.data("calendar",null)),t("html").off("click",l)},p.inline&&p.open(),p},r=function(t){return t<10?"0"+t:t};t.fn.calendar=function(e,n){return e=e||{},this.each(function(){var i=t(this);if(i[0]){var o={};"INPUT"===i[0].tagName.toUpperCase()?o.input=i:o.container=i;var s=i.data("calendar");if(!s)if("string"==typeof e);else{if(!e.value&&i.val()&&(e.value=[i.val()]),!e.value){var c=new Date;e.value=[c.getFullYear()+"/"+r(c.getMonth()+1)+"/"+r(c.getDate())]}s=i.data("calendar",new a(t.extend(o,e)))}"string"==typeof e&&s[e].call(s,n)}})},e=t.fn.calendar.prototype.defaults={value:void 0,monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["周日","周一","周二","周三","周四","周五","周六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],firstDay:1,weekendDays:[0,6],multiple:!1,dateFormat:"yyyy/mm/dd",direction:"horizontal",minDate:null,maxDate:null,touchMove:!0,animate:!0,closeOnSelect:!0,monthPicker:!0,monthPickerTemplate:'<div class="picker-calendar-month-picker"><a href="javascript:;" class="link icon-only picker-calendar-prev-month"><i class="icon icon-prev"></i></a><div class="current-month-value"></div><a href="javascript:;" class="link icon-only picker-calendar-next-month"><i class="icon icon-next"></i></a></div>',yearPicker:!0,yearPickerTemplate:'<div class="picker-calendar-year-picker"><a href="javascript:;" class="link icon-only picker-calendar-prev-year"><i class="icon icon-prev"></i></a><span class="current-year-value"></span><a href="javascript:;" class="link icon-only picker-calendar-next-year"><i class="icon icon-next"></i></a></div>',weekHeader:!0,scrollToInput:!0,inputReadOnly:!0,convertToPopover:!0,onlyInPopover:!1,toolbar:!0,toolbarCloseText:"Done",toolbarTemplate:'<div class="toolbar"><div class="toolbar-inner">{{yearPicker}}{{monthPicker}}</div></div>'}}($),+function(t){"use strict";var e,n=function(t){return t<10?"0"+t:t},i=function(e,n){this.input=t(e),this.params=n||{},this.initMonthes=n.monthes,this.initYears=n.years;var i=t.extend({},n,this.getConfig());t(this.input).picker(i)};i.prototype={getDays:function(t){for(var e=[],n=1;n<=(t||31);n++)e.push(n<10?"0"+n:n);return e},getDaysByMonthAndYear:function(t,e){var n=new Date(e,parseInt(t)+1-1,1),i=new Date(n-1);return this.getDays(i.getDate())},getConfig:function(){var t,e=new Date,i=this.params,a=this,r={rotateEffect:!1,cssClass:"datetime-picker",value:[e.getFullYear(),n(e.getMonth()+1),n(e.getDate()),n(e.getHours()),n(e.getMinutes())],onChange:function(e,n,r){var o=(e.cols,a.getDaysByMonthAndYear(n[1],n[0])),s=n[2];s>o.length&&(s=o.length),e.cols[4].setValue(s);var c=new Date(n[0]+"-"+n[1]+"-"+n[2]),l=!0;if(i.min){var u=new Date("function"==typeof i.min?i.min():i.min);c<+u&&(e.setValue(t),l=!1)}if(i.max){var p=new Date("function"==typeof i.max?i.max():i.max);c>+p&&(e.setValue(t),l=!1)}l&&(t=n),a.params.onChange&&a.params.onChange.apply(this,arguments)},formatValue:function(t,e,n){return a.params.format(t,e,n)},cols:[{values:this.initYears},{divider:!0,content:i.yearSplit},{values:this.initMonthes},{divider:!0,content:i.monthSplit},{values:function(){for(var t=[],e=1;e<=31;e++)t.push(n(e));return t}()}]};i.dateSplit&&r.cols.push({divider:!0,content:i.dateSplit}),r.cols.push({divider:!0,content:i.datetimeSplit});var o=a.params.times();o&&o.length&&(r.cols=r.cols.concat(o));var s=this.input.val();return s&&(r.value=i.parse(s)),this.params.value&&(this.input.val(this.params.value),r.value=i.parse(this.params.value)),r}},t.fn.datetimePicker=function(n){return n=t.extend({},e,n),this.each(function(){if(this){var e=t(this),a=e.data("datetime");return a||e.data("datetime",new i(this,n)),a}})},e=t.fn.datetimePicker.prototype.defaults={input:void 0,min:void 0,max:void 0,yearSplit:"-",monthSplit:"-",dateSplit:"",datetimeSplit:" ",monthes:"01 02 03 04 05 06 07 08 09 10 11 12".split(" "),years:function(){for(var t=[],e=1950;e<=2030;e++)t.push(e);return t}(),times:function(){return[{values:function(){for(var t=[],e=0;e<24;e++)t.push(n(e));return t}()},{divider:!0,content:":"},{values:function(){for(var t=[],e=0;e<60;e++)t.push(n(e));return t}()}]},format:function(t,e){return t.cols.map(function(t){return t.value||t.content}).join("")},parse:function(t){var e=t.split(this.datetimeSplit);return e[0].split(/\D/).concat(e[1].split(/:|时|分|秒/)).filter(function(t){return!!t})}}}($),+function(t){"use strict";t.openPopup=function(e,n){t.closePopup(),e=t(e),e.show(),e.width(),e.addClass("weui-popup__container--visible");var i=e.find(".weui-popup__modal");i.width(),i.transitionEnd(function(){i.trigger("open")})},t.closePopup=function(e,n){e=t(e||".weui-popup__container--visible"),e.find(".weui-popup__modal").transitionEnd(function(){var i=t(this);i.trigger("close"),e.hide(),n&&e.remove()}),e.removeClass("weui-popup__container--visible")},t(document).on("click",".close-popup, .weui-popup__overlay",function(){t.closePopup()}).on("click",".open-popup",function(){t(t(this).data("target")).popup()}).on("click",".weui-popup__container",function(e){t(e.target).hasClass("weui-popup__container")&&t.closePopup()}),t.fn.popup=function(){return this.each(function(){t.openPopup(this)})}}($),+function(t){"use strict";var e,n,i,a,r,o,s=function(n){var i=t.getTouchPosition(n);a=i,r=o=0,e.addClass("touching")},c=function(n){if(!a)return!1;n.preventDefault(),n.stopPropagation();var i=t.getTouchPosition(n);r=i.x-a.x,o=i.y-a.y,o>0&&(o=Math.sqrt(o)),e.css("transform","translate3d(0, "+o+"px, 0)")},l=function(){e.removeClass("touching"),e.attr("style",""),o<0&&Math.abs(o)>.38*e.height()&&t.closeNotification(),Math.abs(r)<=1&&Math.abs(o)<=1&&e.trigger("noti-click"),a=!1},u=function(e){e.on(t.touchEvents.start,s),e.on(t.touchEvents.move,c),e.on(t.touchEvents.end,l)};t.notification=t.noti=function(a){a=t.extend({},n,a),e=t(".weui-notification"),e[0]||(e=t('<div class="weui-notification"></div>').appendTo(document.body),u(e)),e.off("noti-click"),a.onClick&&e.on("noti-click",function(){a.onClick(a.data)}),e.html(t.t7.compile(a.tpl)(a)),e.show(),e.addClass("weui-notification--in"),e.data("params",a);var r=function(){i&&(clearTimeout(i),i=null),i=setTimeout(function(){e.hasClass("weui-notification--touching")?r():t.closeNotification()},a.time)};r()},t.closeNotification=function(){i&&clearTimeout(i),i=null;var e=t(".weui-notification").removeClass("weui-notification--in").transitionEnd(function(){t(this).remove()});if(e[0]){var n=t(".weui-notification").data("params");n&&n.onClose&&n.onClose(n.data)}},n=t.noti.prototype.defaults={title:void 0,text:void 0,media:void 0,time:4e3,onClick:void 0,onClose:void 0,data:void 0,tpl:'<div class="weui-notification__inner">{{#if media}}<div class="weui-notification__media">{{media}}</div>{{/if}}<div class="weui-notification__content">{{#if title}}<div class="weui-notification__title">{{title}}</div>{{/if}}{{#if text}}<div class="weui-notification__text">{{text}}</div>{{/if}}</div><div class="weui-notification__handle-bar"></div></div>'}}($),+function(t){"use strict";var e;t.toptip=function(n,i,a){if(n){"string"==typeof i&&(a=i,i=void 0),i=i||3e3;var r=a?"bg-"+a:"bg-danger",o=t(".weui-toptips").remove();o=t('<div class="weui-toptips"></div>').appendTo(document.body),o.html(n),o[0].className="weui-toptips "+r,clearTimeout(e),o.hasClass("weui-toptips_visible")||(o.show().width(),o.addClass("weui-toptips_visible")),e=setTimeout(function(){o.removeClass("weui-toptips_visible").transitionEnd(function(){o.remove()})},i)}}}($),+function(t){"use strict";var e=function(e,n){this.container=t(e),this.handler=this.container.find(".weui-slider__handler"),this.track=this.container.find(".weui-slider__track"),this.value=this.container.find(".weui-slider-box__value"),this.bind(),"function"==typeof n&&(this.callback=n)};e.prototype.bind=function(){this.container.on(t.touchEvents.start,t.proxy(this.touchStart,this)).on(t.touchEvents.end,t.proxy(this.touchEnd,this)),t(document.body).on(t.touchEvents.move,t.proxy(this.touchMove,this))},e.prototype.touchStart=function(e){e.preventDefault(),this.start=t.getTouchPosition(e),this.width=this.container.find(".weui-slider__inner").width(),this.left=parseInt(this.container.find(".weui-slider__handler").css("left")),this.touching=!0},e.prototype.touchMove=function(e){if(!this.touching)return!0;var n=t.getTouchPosition(e),i=n.x-this.start.x,a=i+this.left,r=parseInt(a/this.width*100);r<0&&(r=0),r>100&&(r=100),this.handler.css("left",r+"%"),this.track.css("width",r+"%"),this.value.text(r),this.callback&&this.callback.call(this,r),this.container.trigger("change",r)},e.prototype.touchEnd=function(t){this.touching=!1},t.fn.slider=function(n){this.each(function(){var i=t(this),a=i.data("slider");return a?a:void i.data("slider",new e(this,n))})}}($),+function(t){"use strict";var e=[],n="swipeout-touching",i=function(n){this.container=t(n),this.mover=this.container.find(">.weui-cell__bd"),this.attachEvents(),e.push(this)};i.prototype.touchStart=function(e){var i=t.getTouchPosition(e);this.container.addClass(n),this.start=i,this.startX=0,this.startTime=+new Date;var a=this.mover.css("transform").match(/-?[\d\.]+/g);a&&a.length&&(this.startX=parseInt(a[4])),this.diffX=this.diffY=0,this._closeOthers(),this.limit=this.container.find(">.weui-cell__ft").width()||68},i.prototype.touchMove=function(e){if(!this.start)return!0;var n=t.getTouchPosition(e);if(this.diffX=n.x-this.start.x,this.diffY=n.y-this.start.y,Math.abs(this.diffX)<Math.abs(this.diffY))return this.close(),this.start=!1,!0;e.preventDefault(),e.stopPropagation();var i=this.diffX+this.startX;i>0&&(i=0),Math.abs(i)>this.limit&&(i=-(Math.pow(-(i+this.limit),.7)+this.limit)),this.mover.css("transform","translate3d("+i+"px, 0, 0)")},i.prototype.touchEnd=function(){if(!this.start)return!0;this.start=!1;var t=this.diffX+this.startX,e=new Date-this.startTime;this.diffX<-5&&e<200?this.open():this.diffX>=0&&e<200?this.close():t>0||-t<=this.limit/2?this.close():this.open()},i.prototype.close=function(){this.container.removeClass(n),this.mover.css("transform","translate3d(0, 0, 0)"),this.container.trigger("swipeout-close")},i.prototype.open=function(){this.container.removeClass(n),this._closeOthers(),this.mover.css("transform","translate3d("+-this.limit+"px, 0, 0)"),this.container.trigger("swipeout-open")},i.prototype.attachEvents=function(){var e=this.mover;e.on(t.touchEvents.start,t.proxy(this.touchStart,this)),e.on(t.touchEvents.move,t.proxy(this.touchMove,this)),e.on(t.touchEvents.end,t.proxy(this.touchEnd,this))},i.prototype._closeOthers=function(){var t=this;e.forEach(function(e){e!==t&&e.close()})};var a=function(t){return new i(t)};t.fn.swipeout=function(e){return this.each(function(){var n=t(this),i=n.data("swipeout")||a(this);n.data("swipeout",i),"string"==typeof e&&i[e]()})},t(".weui-cell_swiped").swipeout()}($);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery.mobile-1.4.5.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery.mobile-1.4.5.min.js
new file mode 100755
index 0000000..5b1a9a1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/jquery.mobile-1.4.5.min.js
@@ -0,0 +1,10 @@
+/*! jQuery Mobile 1.4.5 | Git HEADhash: 68e55e7 <> 2014-10-31T17:33:30Z | (c) 2010, 2014 jQuery Foundation, Inc. | jquery.org/license */
+
+!function(a,b,c){"function"==typeof define&&define.amd?define(["jquery"],function(d){return c(d,a,b),d.mobile}):c(a.jQuery,a,b)}(this,document,function(a,b,c){!function(a){a.mobile={}}(a),function(a,b){function d(b,c){var d,f,g,h=b.nodeName.toLowerCase();return"area"===h?(d=b.parentNode,f=d.name,b.href&&f&&"map"===d.nodeName.toLowerCase()?(g=a("img[usemap=#"+f+"]")[0],!!g&&e(g)):!1):(/input|select|textarea|button|object/.test(h)?!b.disabled:"a"===h?b.href||c:c)&&e(b)}function e(b){return a.expr.filters.visible(b)&&!a(b).parents().addBack().filter(function(){return"hidden"===a.css(this,"visibility")}).length}var f=0,g=/^ui-id-\d+$/;a.ui=a.ui||{},a.extend(a.ui,{version:"c0ab71056b936627e8a7821f03c044aec6280a40",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),a.fn.extend({focus:function(b){return function(c,d){return"number"==typeof c?this.each(function(){var b=this;setTimeout(function(){a(b).focus(),d&&d.call(b)},c)}):b.apply(this,arguments)}}(a.fn.focus),scrollParent:function(){var b;return b=a.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.css(this,"position"))&&/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(this[0].ownerDocument||c):b},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++f)})},removeUniqueId:function(){return this.each(function(){g.test(this.id)&&a(this).removeAttr("id")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return d(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var c=a.attr(b,"tabindex"),e=isNaN(c);return(e||c>=0)&&d(b,!e)}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function e(b,c,d,e){return a.each(f,function(){c-=parseFloat(a.css(b,"padding"+this))||0,d&&(c-=parseFloat(a.css(b,"border"+this+"Width"))||0),e&&(c-=parseFloat(a.css(b,"margin"+this))||0)}),c}var f="Width"===d?["Left","Right"]:["Top","Bottom"],g=d.toLowerCase(),h={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?h["inner"+d].call(this):this.each(function(){a(this).css(g,e(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return"number"!=typeof b?h["outer"+d].call(this,b):this.each(function(){a(this).css(g,e(this,b,!0,c)+"px")})}}),a.fn.addBack||(a.fn.addBack=function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}),a("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(a.fn.removeData=function(b){return function(c){return arguments.length?b.call(this,a.camelCase(c)):b.call(this)}}(a.fn.removeData)),a.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),a.support.selectstart="onselectstart"in c.createElement("div"),a.fn.extend({disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(d){if(d!==b)return this.css("zIndex",d);if(this.length)for(var e,f,g=a(this[0]);g.length&&g[0]!==c;){if(e=g.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(f=parseInt(g.css("zIndex"),10),!isNaN(f)&&0!==f))return f;g=g.parent()}return 0}}),a.ui.plugin={add:function(b,c,d){var e,f=a.ui[b].prototype;for(e in d)f.plugins[e]=f.plugins[e]||[],f.plugins[e].push([c,d[e]])},call:function(a,b,c,d){var e,f=a.plugins[b];if(f&&(d||a.element[0].parentNode&&11!==a.element[0].parentNode.nodeType))for(e=0;e<f.length;e++)a.options[f[e][0]]&&f[e][1].apply(a.element,c)}}}(a),function(a,b){var d=function(b,c){var d=b.parent(),e=[],f=function(){var b=a(this),c=a.mobile.toolbar&&b.data("mobile-toolbar")?b.toolbar("option"):{position:b.attr("data-"+a.mobile.ns+"position"),updatePagePadding:b.attr("data-"+a.mobile.ns+"update-page-padding")!==!1};return!("fixed"===c.position&&c.updatePagePadding===!0)},g=d.children(":jqmData(role='header')").filter(f),h=b.children(":jqmData(role='header')"),i=d.children(":jqmData(role='footer')").filter(f),j=b.children(":jqmData(role='footer')");return 0===h.length&&g.length>0&&(e=e.concat(g.toArray())),0===j.length&&i.length>0&&(e=e.concat(i.toArray())),a.each(e,function(b,d){c-=a(d).outerHeight()}),Math.max(0,c)};a.extend(a.mobile,{window:a(b),document:a(c),keyCode:a.ui.keyCode,behaviors:{},silentScroll:function(c){"number"!==a.type(c)&&(c=a.mobile.defaultHomeScroll),a.event.special.scrollstart.enabled=!1,setTimeout(function(){b.scrollTo(0,c),a.mobile.document.trigger("silentscroll",{x:0,y:c})},20),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},getClosestBaseUrl:function(b){var c=a(b).closest(".ui-page").jqmData("url"),d=a.mobile.path.documentBase.hrefNoHash;return a.mobile.dynamicBaseEnabled&&c&&a.mobile.path.isPath(c)||(c=d),a.mobile.path.makeUrlAbsolute(c,d)},removeActiveLinkClass:function(b){!a.mobile.activeClickedLink||a.mobile.activeClickedLink.closest("."+a.mobile.activePageClass).length&&!b||a.mobile.activeClickedLink.removeClass(a.mobile.activeBtnClass),a.mobile.activeClickedLink=null},getInheritedTheme:function(a,b){for(var c,d,e=a[0],f="",g=/ui-(bar|body|overlay)-([a-z])\b/;e&&(c=e.className||"",!(c&&(d=g.exec(c))&&(f=d[2])));)e=e.parentNode;return f||b||"a"},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;var d,e,f,g,h,i=b.length,j=a();for(g=0;i>g;g++){for(e=b.eq(g),f=!1,d=b[g];d;){if(h=d.getAttribute?d.getAttribute("data-"+a.mobile.ns+c):"","false"===h){f=!0;break}d=d.parentNode}f||(j=j.add(e))}return j},getScreenHeight:function(){return b.innerHeight||a.mobile.window.height()},resetActivePageHeight:function(b){var c=a("."+a.mobile.activePageClass),e=c.height(),f=c.outerHeight(!0);b=d(c,"number"==typeof b?b:a.mobile.getScreenHeight()),c.css("min-height",""),c.height()<b&&c.css("min-height",b-(f-e))},loading:function(){var b=this.loading._widget||a(a.mobile.loader.prototype.defaultHtml).loader(),c=b.loader.apply(b,arguments);return this.loading._widget=b,c}}),a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.fn.extend({removeWithDependents:function(){a.removeWithDependents(this)},enhanceWithin:function(){var b,c={},d=a.mobile.page.prototype.keepNativeSelector(),e=this;a.mobile.nojs&&a.mobile.nojs(this),a.mobile.links&&a.mobile.links(this),a.mobile.degradeInputsWithin&&a.mobile.degradeInputsWithin(this),a.fn.buttonMarkup&&this.find(a.fn.buttonMarkup.initSelector).not(d).jqmEnhanceable().buttonMarkup(),a.fn.fieldcontain&&this.find(":jqmData(role='fieldcontain')").not(d).jqmEnhanceable().fieldcontain(),a.each(a.mobile.widgets,function(b,f){if(f.initSelector){var g=a.mobile.enhanceable(e.find(f.initSelector));g.length>0&&(g=g.not(d)),g.length>0&&(c[f.prototype.widgetName]=g)}});for(b in c)c[b][b]();return this},addDependents:function(b){a.addDependents(this,b)},getEncodedText:function(){return a("<a>").text(this.text()).html()},jqmEnhanceable:function(){return a.mobile.enhanceable(this)},jqmHijackable:function(){return a.mobile.hijackable(this)}}),a.removeWithDependents=function(b){var c=a(b);(c.jqmData("dependents")||a()).remove(),c.remove()},a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.find.matches=function(b,c){return a.find(b,null,null,c)},a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}}(a,this),function(a){a.extend(a.mobile,{version:"1.4.5",subPageUrlKey:"ui-page",hideUrlBar:!0,keepNative:":jqmData(role='none'), :jqmData(role='nojs')",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:!0,hashListeningEnabled:!0,linkBindingEnabled:!0,defaultPageTransition:"fade",maxTransitionWidth:!1,minScrollBack:0,defaultDialogTransition:"pop",pageLoadErrorMessage:"Error Loading Page",pageLoadErrorMessageTheme:"a",phonegapNavigationEnabled:!1,autoInitializePage:!0,pushStateEnabled:!0,ignoreContentEnabled:!1,buttonMarkup:{hoverDelay:200},dynamicBaseEnabled:!0,pageContainer:a(),allowCrossDomainPages:!1,dialogHashKey:"&ui-state=dialog"})}(a,this),function(a,b){var c=0,d=Array.prototype.slice,e=a.cleanData;a.cleanData=function(b){for(var c,d=0;null!=(c=b[d]);d++)try{a(c).triggerHandler("remove")}catch(f){}e(b)},a.widget=function(b,c,d){var e,f,g,h,i={},j=b.split(".")[0];return b=b.split(".")[1],e=j+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][e.toLowerCase()]=function(b){return!!a.data(b,e)},a[j]=a[j]||{},f=a[j][b],g=a[j][b]=function(a,b){return this._createWidget?void(arguments.length&&this._createWidget(a,b)):new g(a,b)},a.extend(g,f,{version:d.version,_proto:a.extend({},d),_childConstructors:[]}),h=new c,h.options=a.widget.extend({},h.options),a.each(d,function(b,d){return a.isFunction(d)?void(i[b]=function(){var a=function(){return c.prototype[b].apply(this,arguments)},e=function(a){return c.prototype[b].apply(this,a)};return function(){var b,c=this._super,f=this._superApply;return this._super=a,this._superApply=e,b=d.apply(this,arguments),this._super=c,this._superApply=f,b}}()):void(i[b]=d)}),g.prototype=a.widget.extend(h,{widgetEventPrefix:f?h.widgetEventPrefix||b:b},i,{constructor:g,namespace:j,widgetName:b,widgetFullName:e}),f?(a.each(f._childConstructors,function(b,c){var d=c.prototype;a.widget(d.namespace+"."+d.widgetName,g,c._proto)}),delete f._childConstructors):c._childConstructors.push(g),a.widget.bridge(b,g),g},a.widget.extend=function(c){for(var e,f,g=d.call(arguments,1),h=0,i=g.length;i>h;h++)for(e in g[h])f=g[h][e],g[h].hasOwnProperty(e)&&f!==b&&(c[e]=a.isPlainObject(f)?a.isPlainObject(c[e])?a.widget.extend({},c[e],f):a.widget.extend({},f):f);return c},a.widget.bridge=function(c,e){var f=e.prototype.widgetFullName||c;a.fn[c]=function(g){var h="string"==typeof g,i=d.call(arguments,1),j=this;return g=!h&&i.length?a.widget.extend.apply(null,[g].concat(i)):g,this.each(h?function(){var d,e=a.data(this,f);return"instance"===g?(j=e,!1):e?a.isFunction(e[g])&&"_"!==g.charAt(0)?(d=e[g].apply(e,i),d!==e&&d!==b?(j=d&&d.jquery?j.pushStack(d.get()):d,!1):void 0):a.error("no such method '"+g+"' for "+c+" widget instance"):a.error("cannot call methods on "+c+" prior to initialization; attempted to call method '"+g+"'")}:function(){var b=a.data(this,f);b?b.option(g||{})._init():a.data(this,f,new e(g,this))}),j}},a.Widget=function(){},a.Widget._childConstructors=[],a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(b,d){d=a(d||this.defaultElement||this)[0],this.element=a(d),this.uuid=c++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=a.widget.extend({},this.options,this._getCreateOptions(),b),this.bindings=a(),this.hoverable=a(),this.focusable=a(),d!==this&&(a.data(d,this.widgetFullName,this),this._on(!0,this.element,{remove:function(a){a.target===d&&this.destroy()}}),this.document=a(d.style?d.ownerDocument:d.document||d),this.window=a(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:a.noop,_getCreateEventData:a.noop,_create:a.noop,_init:a.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(a.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:a.noop,widget:function(){return this.element},option:function(c,d){var e,f,g,h=c;if(0===arguments.length)return a.widget.extend({},this.options);if("string"==typeof c)if(h={},e=c.split("."),c=e.shift(),e.length){for(f=h[c]=a.widget.extend({},this.options[c]),g=0;g<e.length-1;g++)f[e[g]]=f[e[g]]||{},f=f[e[g]];if(c=e.pop(),d===b)return f[c]===b?null:f[c];f[c]=d}else{if(d===b)return this.options[c]===b?null:this.options[c];h[c]=d}return this._setOptions(h),this},_setOptions:function(a){var b;for(b in a)this._setOption(b,a[b]);return this},_setOption:function(a,b){return this.options[a]=b,"disabled"===a&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!b),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(b,c,d){var e,f=this;"boolean"!=typeof b&&(d=c,c=b,b=!1),d?(c=e=a(c),this.bindings=this.bindings.add(c)):(d=c,c=this.element,e=this.widget()),a.each(d,function(d,g){function h(){return b||f.options.disabled!==!0&&!a(this).hasClass("ui-state-disabled")?("string"==typeof g?f[g]:g).apply(f,arguments):void 0}"string"!=typeof g&&(h.guid=g.guid=g.guid||h.guid||a.guid++);var i=d.match(/^(\w+)\s*(.*)$/),j=i[1]+f.eventNamespace,k=i[2];k?e.delegate(k,j,h):c.bind(j,h)})},_off:function(a,b){b=(b||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,a.unbind(b).undelegate(b)},_delay:function(a,b){function c(){return("string"==typeof a?d[a]:a).apply(d,arguments)}var d=this;return setTimeout(c,b||0)},_hoverable:function(b){this.hoverable=this.hoverable.add(b),this._on(b,{mouseenter:function(b){a(b.currentTarget).addClass("ui-state-hover")},mouseleave:function(b){a(b.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(b){this.focusable=this.focusable.add(b),this._on(b,{focusin:function(b){a(b.currentTarget).addClass("ui-state-focus")},focusout:function(b){a(b.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(b,c,d){var e,f,g=this.options[b];if(d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.apply(this.element[0],[c].concat(d))===!1||c.isDefaultPrevented())}},a.each({show:"fadeIn",hide:"fadeOut"},function(b,c){a.Widget.prototype["_"+b]=function(d,e,f){"string"==typeof e&&(e={effect:e});var g,h=e?e===!0||"number"==typeof e?c:e.effect||c:b;e=e||{},"number"==typeof e&&(e={duration:e}),g=!a.isEmptyObject(e),e.complete=f,e.delay&&d.delay(e.delay),g&&a.effects&&a.effects.effect[h]?d[b](e):h!==b&&d[h]?d[h](e.duration,e.easing,f):d.queue(function(c){a(this)[b](),f&&f.call(d[0]),c()})}})}(a),function(a,b,c){var d={},e=a.find,f=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,g=/:jqmData\(([^)]*)\)/g;a.extend(a.mobile,{ns:"",getAttribute:function(b,c){var d;b=b.jquery?b[0]:b,b&&b.getAttribute&&(d=b.getAttribute("data-"+a.mobile.ns+c));try{d="true"===d?!0:"false"===d?!1:"null"===d?null:+d+""===d?+d:f.test(d)?JSON.parse(d):d}catch(e){}return d},nsNormalizeDict:d,nsNormalize:function(b){return d[b]||(d[b]=a.camelCase(a.mobile.ns+b))},closestPageData:function(a){return a.closest(":jqmData(role='page'), :jqmData(role='dialog')").data("mobile-page")}}),a.fn.jqmData=function(b,d){var e;return"undefined"!=typeof b&&(b&&(b=a.mobile.nsNormalize(b)),e=arguments.length<2||d===c?this.data(b):this.data(b,d)),e},a.jqmData=function(b,c,d){var e;return"undefined"!=typeof c&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,d)),e},a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))},a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))},a.find=function(b,c,d,f){return b.indexOf(":jqmData")>-1&&(b=b.replace(g,"[data-"+(a.mobile.ns||"")+"$1]")),e.call(this,b,c,d,f)},a.extend(a.find,e)}(a,this),function(a){var b=/[A-Z]/g,c=function(a){return"-"+a.toLowerCase()};a.extend(a.Widget.prototype,{_getCreateOptions:function(){var d,e,f=this.element[0],g={};if(!a.mobile.getAttribute(f,"defaults"))for(d in this.options)e=a.mobile.getAttribute(f,d.replace(b,c)),null!=e&&(g[d]=e);return g}}),a.mobile.widget=a.Widget}(a),function(a){var b="ui-loader",c=a("html");a.widget("mobile.loader",{options:{theme:"a",textVisible:!1,html:"",text:"loading"},defaultHtml:"<div class='"+b+"'><span class='ui-icon-loading'></span><h1></h1></div>",fakeFixLoader:function(){var b=a("."+a.mobile.activeBtnClass).first();this.element.css({top:a.support.scrollTop&&this.window.scrollTop()+this.window.height()/2||b.length&&b.offset().top||100})},checkLoaderPosition:function(){var b=this.element.offset(),c=this.window.scrollTop(),d=a.mobile.getScreenHeight();(b.top<c||b.top-c>d)&&(this.element.addClass("ui-loader-fakefix"),this.fakeFixLoader(),this.window.unbind("scroll",this.checkLoaderPosition).bind("scroll",a.proxy(this.fakeFixLoader,this)))},resetHtml:function(){this.element.html(a(this.defaultHtml).html())},show:function(d,e,f){var g,h,i;this.resetHtml(),"object"===a.type(d)?(i=a.extend({},this.options,d),d=i.theme):(i=this.options,d=d||i.theme),h=e||(i.text===!1?"":i.text),c.addClass("ui-loading"),g=i.textVisible,this.element.attr("class",b+" ui-corner-all ui-body-"+d+" ui-loader-"+(g||e||d.text?"verbose":"default")+(i.textonly||f?" ui-loader-textonly":"")),i.html?this.element.html(i.html):this.element.find("h1").text(h),this.element.appendTo(a(a.mobile.pagecontainer?":mobile-pagecontainer":"body")),this.checkLoaderPosition(),this.window.bind("scroll",a.proxy(this.checkLoaderPosition,this))},hide:function(){c.removeClass("ui-loading"),this.options.text&&this.element.removeClass("ui-loader-fakefix"),this.window.unbind("scroll",this.fakeFixLoader),this.window.unbind("scroll",this.checkLoaderPosition)}})}(a,this),function(a,b,d){"$:nomunge";function e(a){return a=a||location.href,"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var f,g="hashchange",h=c,i=a.event.special,j=h.documentMode,k="on"+g in b&&(j===d||j>7);a.fn[g]=function(a){return a?this.bind(g,a):this.trigger(g)},a.fn[g].delay=50,i[g]=a.extend(i[g],{setup:function(){return k?!1:void a(f.start)},teardown:function(){return k?!1:void a(f.stop)}}),f=function(){function c(){var d=e(),h=n(j);d!==j?(m(j=d,h),a(b).trigger(g)):h!==j&&(location.href=location.href.replace(/#.*/,"")+h),f=setTimeout(c,a.fn[g].delay)}var f,i={},j=e(),l=function(a){return a},m=l,n=l;return i.start=function(){f||c()},i.stop=function(){f&&clearTimeout(f),f=d},b.attachEvent&&!b.addEventListener&&!k&&function(){var b,d;i.start=function(){b||(d=a.fn[g].src,d=d&&d+e(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||m(e()),c()}).attr("src",d||"javascript:0").insertAfter("body")[0].contentWindow,h.onpropertychange=function(){try{"title"===event.propertyName&&(b.document.title=h.title)}catch(a){}})},i.stop=l,n=function(){return e(b.location.href)},m=function(c,d){var e=b.document,f=a.fn[g].domain;c!==d&&(e.title=h.title,e.open(),f&&e.write('<script>document.domain="'+f+'"</script>'),e.close(),b.location.hash=c)}}(),i}()}(a,this),function(a){b.matchMedia=b.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(c),a.mobile.media=function(a){return b.matchMedia(a).matches}}(a),function(a){var b={touch:"ontouchend"in c};a.mobile.support=a.mobile.support||{},a.extend(a.support,b),a.extend(a.mobile.support,b)}(a),function(a){a.extend(a.support,{orientation:"orientation"in b&&"onorientationchange"in b})}(a),function(a,d){function e(a){var b,c=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(c+" ")+c).split(" ");for(b in e)if(n[e[b]]!==d)return!0}function f(){var c=b,d=!(!c.document.createElementNS||!c.document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||c.opera&&-1===navigator.userAgent.indexOf("Chrome")),e=function(b){b&&d||a("html").addClass("ui-nosvg")},f=new c.Image;f.onerror=function(){e(!1)},f.onload=function(){e(1===f.width&&1===f.height)},f.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="}function g(){var e,f,g,h="transform-3d",i=a.mobile.media("(-"+o.join("-"+h+"),(-")+"-"+h+"),("+h+")");if(i)return!!i;e=c.createElement("div"),f={MozTransform:"-moz-transform",transform:"transform"},m.append(e);for(g in f)e.style[g]!==d&&(e.style[g]="translate3d( 100px, 1px, 1px )",i=b.getComputedStyle(e).getPropertyValue(f[g]));return!!i&&"none"!==i}function h(){var b,c,d=location.protocol+"//"+location.host+location.pathname+"ui-dir/",e=a("head base"),f=null,g="";return e.length?g=e.attr("href"):e=f=a("<base>",{href:d}).appendTo("head"),b=a("<a href='testurl' />").prependTo(m),c=b[0].href,e[0].href=g||location.pathname,f&&f.remove(),0===c.indexOf(d)}function i(){var a,d=c.createElement("x"),e=c.documentElement,f=b.getComputedStyle;return"pointerEvents"in d.style?(d.style.pointerEvents="auto",d.style.pointerEvents="x",e.appendChild(d),a=f&&"auto"===f(d,"").pointerEvents,e.removeChild(d),!!a):!1}function j(){var a=c.createElement("div");return"undefined"!=typeof a.getBoundingClientRect}function k(){var a=b,c=navigator.userAgent,d=navigator.platform,e=c.match(/AppleWebKit\/([0-9]+)/),f=!!e&&e[1],g=c.match(/Fennec\/([0-9]+)/),h=!!g&&g[1],i=c.match(/Opera Mobi\/([0-9]+)/),j=!!i&&i[1];return(d.indexOf("iPhone")>-1||d.indexOf("iPad")>-1||d.indexOf("iPod")>-1)&&f&&534>f||a.operamini&&"[object OperaMini]"==={}.toString.call(a.operamini)||i&&7458>j||c.indexOf("Android")>-1&&f&&533>f||h&&6>h||"palmGetResource"in b&&f&&534>f||c.indexOf("MeeGo")>-1&&c.indexOf("NokiaBrowser/8.5.0")>-1?!1:!0}var l,m=a("<body>").prependTo("html"),n=m[0].style,o=["Webkit","Moz","O"],p="palmGetResource"in b,q=b.operamini&&"[object OperaMini]"==={}.toString.call(b.operamini),r=b.blackberry&&!e("-webkit-transform");a.extend(a.mobile,{browser:{}}),a.mobile.browser.oldIE=function(){var a=3,b=c.createElement("div"),d=b.all||[];do b.innerHTML="<!--[if gt IE "+ ++a+"]><br><![endif]-->";while(d[0]);return a>4?a:!a}(),a.extend(a.support,{pushState:"pushState"in history&&"replaceState"in history&&!(b.navigator.userAgent.indexOf("Firefox")>=0&&b.top!==b)&&-1===b.navigator.userAgent.search(/CriOS/),mediaquery:a.mobile.media("only all"),cssPseudoElement:!!e("content"),touchOverflow:!!e("overflowScrolling"),cssTransform3d:g(),boxShadow:!!e("boxShadow")&&!r,fixedPosition:k(),scrollTop:("pageXOffset"in b||"scrollTop"in c.documentElement||"scrollTop"in m[0])&&!p&&!q,dynamicBaseTag:h(),cssPointerEvents:i(),boundingRect:j(),inlineSVG:f}),m.remove(),l=function(){var a=b.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")>-1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}(),a.mobile.gradeA=function(){return(a.support.mediaquery&&a.support.cssPseudoElement||a.mobile.browser.oldIE&&a.mobile.browser.oldIE>=8)&&(a.support.boundingRect||null!==a.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/))},a.mobile.ajaxBlacklist=b.blackberry&&!b.WebKitPoint||q||l,l&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")}),a.support.boxShadow||a("html").addClass("ui-noboxshadow")}(a),function(a,b){var c,d=a.mobile.window,e=function(){};a.event.special.beforenavigate={setup:function(){d.on("navigate",e)},teardown:function(){d.off("navigate",e)}},a.event.special.navigate=c={bound:!1,pushStateEnabled:!0,originalEventName:b,isPushStateEnabled:function(){return a.support.pushState&&a.mobile.pushStateEnabled===!0&&this.isHashChangeEnabled()},isHashChangeEnabled:function(){return a.mobile.hashListeningEnabled===!0},popstate:function(b){var c=new a.Event("navigate"),e=new a.Event("beforenavigate"),f=b.originalEvent.state||{};e.originalEvent=b,d.trigger(e),e.isDefaultPrevented()||(b.historyState&&a.extend(f,b.historyState),c.originalEvent=b,setTimeout(function(){d.trigger(c,{state:f})},0))},hashchange:function(b){var c=new a.Event("navigate"),e=new a.Event("beforenavigate");e.originalEvent=b,d.trigger(e),e.isDefaultPrevented()||(c.originalEvent=b,d.trigger(c,{state:b.hashchangeState||{}}))},setup:function(){c.bound||(c.bound=!0,c.isPushStateEnabled()?(c.originalEventName="popstate",d.bind("popstate.navigate",c.popstate)):c.isHashChangeEnabled()&&(c.originalEventName="hashchange",d.bind("hashchange.navigate",c.hashchange)))}}}(a),function(a,c){var d,e,f="&ui-state=dialog";a.mobile.path=d={uiStateKey:"&ui-state",urlParseRE:/^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,getLocation:function(a){var b=this.parseUrl(a||location.href),c=a?b:location,d=b.hash;return d="#"===d?"":d,c.protocol+b.doubleSlash+c.host+(""!==c.protocol&&"/"!==c.pathname.substring(0,1)?"/":"")+c.pathname+c.search+d},getDocumentUrl:function(b){return b?a.extend({},d.documentUrl):d.documentUrl.href},parseLocation:function(){return this.parseUrl(this.getLocation())},parseUrl:function(b){if("object"===a.type(b))return b;var c=d.urlParseRE.exec(b||"")||[];return{href:c[0]||"",hrefNoHash:c[1]||"",hrefNoSearch:c[2]||"",domain:c[3]||"",protocol:c[4]||"",doubleSlash:c[5]||"",authority:c[6]||"",username:c[8]||"",password:c[9]||"",host:c[10]||"",hostname:c[11]||"",port:c[12]||"",pathname:c[13]||"",directory:c[14]||"",filename:c[15]||"",search:c[16]||"",hash:c[17]||""}},makePathAbsolute:function(a,b){var c,d,e,f;if(a&&"/"===a.charAt(0))return a;for(a=a||"",b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"",c=b?b.split("/"):[],d=a.split("/"),e=0;e<d.length;e++)switch(f=d[e]){case".":break;case"..":c.length&&c.pop();break;default:c.push(f)}return"/"+c.join("/")},isSameDomain:function(a,b){return d.parseUrl(a).domain.toLowerCase()===d.parseUrl(b).domain.toLowerCase()},isRelativeUrl:function(a){return""===d.parseUrl(a).protocol},isAbsoluteUrl:function(a){return""!==d.parseUrl(a).protocol},makeUrlAbsolute:function(a,b){if(!d.isRelativeUrl(a))return a;b===c&&(b=this.documentBase);var e=d.parseUrl(a),f=d.parseUrl(b),g=e.protocol||f.protocol,h=e.protocol?e.doubleSlash:e.doubleSlash||f.doubleSlash,i=e.authority||f.authority,j=""!==e.pathname,k=d.makePathAbsolute(e.pathname||f.filename,f.pathname),l=e.search||!j&&f.search||"",m=e.hash;return g+h+i+k+l+m},addSearchParams:function(b,c){var e=d.parseUrl(b),f="object"==typeof c?a.param(c):c,g=e.search||"?";return e.hrefNoSearch+g+("?"!==g.charAt(g.length-1)?"&":"")+f+(e.hash||"")},convertUrlToDataUrl:function(a){var c=a,e=d.parseUrl(a);return d.isEmbeddedPage(e)?c=e.hash.split(f)[0].replace(/^#/,"").replace(/\?.*$/,""):d.isSameDomain(e,this.documentBase)&&(c=e.hrefNoHash.replace(this.documentBase.domain,"").split(f)[0]),b.decodeURIComponent(c)},get:function(a){return a===c&&(a=d.parseLocation().hash),d.stripHash(a).replace(/[^\/]*\.[^\/*]+$/,"")},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(this.documentBase.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},stripQueryParams:function(a){return a.replace(/\?.*$/,"")},cleanHash:function(a){return d.stripHash(a.replace(/\?.*$/,"").replace(f,""))},isHashValid:function(a){return/^#[^#]+$/.test(a)},isExternal:function(a){var b=d.parseUrl(a);return!(!b.protocol||b.domain.toLowerCase()===this.documentUrl.domain.toLowerCase())},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isEmbeddedPage:function(a){var b=d.parseUrl(a);return""!==b.protocol?!this.isPath(b.hash)&&b.hash&&(b.hrefNoHash===this.documentUrl.hrefNoHash||this.documentBaseDiffers&&b.hrefNoHash===this.documentBase.hrefNoHash):/^#/.test(b.href)},squash:function(a,b){var c,e,f,g,h,i=this.isPath(a),j=this.parseUrl(a),k=j.hash,l="";return b||(i?b=d.getLocation():(h=d.getDocumentUrl(!0),b=d.isPath(h.hash)?d.squash(h.href):h.href)),e=i?d.stripHash(a):a,e=d.isPath(j.hash)?d.stripHash(j.hash):e,g=e.indexOf(this.uiStateKey),g>-1&&(l=e.slice(g),e=e.slice(0,g)),c=d.makeUrlAbsolute(e,b),f=this.parseUrl(c).search,i?((d.isPath(k)||0===k.replace("#","").indexOf(this.uiStateKey))&&(k=""),l&&-1===k.indexOf(this.uiStateKey)&&(k+=l),-1===k.indexOf("#")&&""!==k&&(k="#"+k),c=d.parseUrl(c),c=c.protocol+c.doubleSlash+c.host+c.pathname+f+k):c+=c.indexOf("#")>-1?l:"#"+l,c},isPreservableHash:function(a){return 0===a.replace("#","").indexOf(this.uiStateKey)},hashToSelector:function(a){var b="#"===a.substring(0,1);return b&&(a=a.substring(1)),(b?"#":"")+a.replace(/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,"\\$1")},getFilePath:function(a){return a&&a.split(f)[0]},isFirstPageUrl:function(b){var e=d.parseUrl(d.makeUrlAbsolute(b,this.documentBase)),f=e.hrefNoHash===this.documentUrl.hrefNoHash||this.documentBaseDiffers&&e.hrefNoHash===this.documentBase.hrefNoHash,g=a.mobile.firstPage,h=g&&g[0]?g[0].id:c;return f&&(!e.hash||"#"===e.hash||h&&e.hash.replace(/^#/,"")===h)},isPermittedCrossDomainRequest:function(b,c){return a.mobile.allowCrossDomainPages&&("file:"===b.protocol||"content:"===b.protocol)&&-1!==c.search(/^https?:/)}},d.documentUrl=d.parseLocation(),e=a("head").find("base"),d.documentBase=e.length?d.parseUrl(d.makeUrlAbsolute(e.attr("href"),d.documentUrl.href)):d.documentUrl,d.documentBaseDiffers=d.documentUrl.hrefNoHash!==d.documentBase.hrefNoHash,d.getDocumentBase=function(b){return b?a.extend({},d.documentBase):d.documentBase.href},a.extend(a.mobile,{getDocumentUrl:d.getDocumentUrl,getDocumentBase:d.getDocumentBase})}(a),function(a,b){a.mobile.History=function(a,b){this.stack=a||[],this.activeIndex=b||0},a.extend(a.mobile.History.prototype,{getActive:function(){return this.stack[this.activeIndex]},getLast:function(){return this.stack[this.previousIndex]},getNext:function(){return this.stack[this.activeIndex+1]},getPrev:function(){return this.stack[this.activeIndex-1]},add:function(a,b){b=b||{},this.getNext()&&this.clearForward(),b.hash&&-1===b.hash.indexOf("#")&&(b.hash="#"+b.hash),b.url=a,this.stack.push(b),this.activeIndex=this.stack.length-1},clearForward:function(){this.stack=this.stack.slice(0,this.activeIndex+1)},find:function(a,b,c){b=b||this.stack;var d,e,f,g=b.length;for(e=0;g>e;e++)if(d=b[e],(decodeURIComponent(a)===decodeURIComponent(d.url)||decodeURIComponent(a)===decodeURIComponent(d.hash))&&(f=e,c))return f;return f},closest:function(a){var c,d=this.activeIndex;return c=this.find(a,this.stack.slice(0,d)),c===b&&(c=this.find(a,this.stack.slice(d),!0),c=c===b?c:c+d),c},direct:function(c){var d=this.closest(c.url),e=this.activeIndex;d!==b&&(this.activeIndex=d,this.previousIndex=e),e>d?(c.present||c.back||a.noop)(this.getActive(),"back"):d>e?(c.present||c.forward||a.noop)(this.getActive(),"forward"):d===b&&c.missing&&c.missing(this.getActive())}})}(a),function(a){var d=a.mobile.path,e=location.href;a.mobile.Navigator=function(b){this.history=b,this.ignoreInitialHashChange=!0,a.mobile.window.bind({"popstate.history":a.proxy(this.popstate,this),"hashchange.history":a.proxy(this.hashchange,this)})},a.extend(a.mobile.Navigator.prototype,{squash:function(e,f){var g,h,i=d.isPath(e)?d.stripHash(e):e;return h=d.squash(e),g=a.extend({hash:i,url:h},f),b.history.replaceState(g,g.title||c.title,h),g},hash:function(a,b){var c,e,f,g;return c=d.parseUrl(a),e=d.parseLocation(),e.pathname+e.search===c.pathname+c.search?f=c.hash?c.hash:c.pathname+c.search:d.isPath(a)?(g=d.parseUrl(b),f=g.pathname+g.search+(d.isPreservableHash(g.hash)?g.hash.replace("#",""):"")):f=a,f},go:function(e,f,g){var h,i,j,k,l=a.event.special.navigate.isPushStateEnabled();
+i=d.squash(e),j=this.hash(e,i),g&&j!==d.stripHash(d.parseLocation().hash)&&(this.preventNextHashChange=g),this.preventHashAssignPopState=!0,b.location.hash=j,this.preventHashAssignPopState=!1,h=a.extend({url:i,hash:j,title:c.title},f),l&&(k=new a.Event("popstate"),k.originalEvent={type:"popstate",state:null},this.squash(e,h),g||(this.ignorePopState=!0,a.mobile.window.trigger(k))),this.history.add(h.url,h)},popstate:function(b){var c,f;if(a.event.special.navigate.isPushStateEnabled())return this.preventHashAssignPopState?(this.preventHashAssignPopState=!1,void b.stopImmediatePropagation()):this.ignorePopState?void(this.ignorePopState=!1):!b.originalEvent.state&&1===this.history.stack.length&&this.ignoreInitialHashChange&&(this.ignoreInitialHashChange=!1,location.href===e)?void b.preventDefault():(c=d.parseLocation().hash,!b.originalEvent.state&&c?(f=this.squash(c),this.history.add(f.url,f),void(b.historyState=f)):void this.history.direct({url:(b.originalEvent.state||{}).url||c,present:function(c,d){b.historyState=a.extend({},c),b.historyState.direction=d}}))},hashchange:function(b){var e,f;if(a.event.special.navigate.isHashChangeEnabled()&&!a.event.special.navigate.isPushStateEnabled()){if(this.preventNextHashChange)return this.preventNextHashChange=!1,void b.stopImmediatePropagation();e=this.history,f=d.parseLocation().hash,this.history.direct({url:f,present:function(c,d){b.hashchangeState=a.extend({},c),b.hashchangeState.direction=d},missing:function(){e.add(f,{hash:f,title:c.title})}})}}})}(a),function(a){a.mobile.navigate=function(b,c,d){a.mobile.navigate.navigator.go(b,c,d)},a.mobile.navigate.history=new a.mobile.History,a.mobile.navigate.navigator=new a.mobile.Navigator(a.mobile.navigate.history);var b=a.mobile.path.parseLocation();a.mobile.navigate.history.add(b.href,{hash:b.hash})}(a),function(a,b){var d={animation:{},transition:{}},e=c.createElement("a"),f=["","webkit-","moz-","o-"];a.each(["animation","transition"],function(c,g){var h=0===c?g+"-name":g;a.each(f,function(c,f){return e.style[a.camelCase(f+h)]!==b?(d[g].prefix=f,!1):void 0}),d[g].duration=a.camelCase(d[g].prefix+g+"-duration"),d[g].event=a.camelCase(d[g].prefix+g+"-end"),""===d[g].prefix&&(d[g].event=d[g].event.toLowerCase())}),a.support.cssTransitions=d.transition.prefix!==b,a.support.cssAnimations=d.animation.prefix!==b,a(e).remove(),a.fn.animationComplete=function(e,f,g){var h,i,j=this,k=function(){clearTimeout(h),e.apply(this,arguments)},l=f&&"animation"!==f?"transition":"animation";return a.support.cssTransitions&&"transition"===l||a.support.cssAnimations&&"animation"===l?(g===b&&(a(this).context!==c&&(i=3e3*parseFloat(a(this).css(d[l].duration))),(0===i||i===b||isNaN(i))&&(i=a.fn.animationComplete.defaultDuration)),h=setTimeout(function(){a(j).off(d[l].event,k),e.apply(j)},i),a(this).one(d[l].event,k)):(setTimeout(a.proxy(e,this),0),a(this))},a.fn.animationComplete.defaultDuration=1e3}(a),function(a,b,c,d){function e(a){for(;a&&"undefined"!=typeof a.originalEvent;)a=a.originalEvent;return a}function f(b,c){var f,g,h,i,j,k,l,m,n,o=b.type;if(b=a.Event(b),b.type=c,f=b.originalEvent,g=a.event.props,o.search(/^(mouse|click)/)>-1&&(g=E),f)for(l=g.length,i;l;)i=g[--l],b[i]=f[i];if(o.search(/mouse(down|up)|click/)>-1&&!b.which&&(b.which=1),-1!==o.search(/^touch/)&&(h=e(f),o=h.touches,j=h.changedTouches,k=o&&o.length?o[0]:j&&j.length?j[0]:d))for(m=0,n=C.length;n>m;m++)i=C[m],b[i]=k[i];return b}function g(b){for(var c,d,e={};b;){c=a.data(b,z);for(d in c)c[d]&&(e[d]=e.hasVirtualBinding=!0);b=b.parentNode}return e}function h(b,c){for(var d;b;){if(d=a.data(b,z),d&&(!c||d[c]))return b;b=b.parentNode}return null}function i(){M=!1}function j(){M=!0}function k(){Q=0,K.length=0,L=!1,j()}function l(){i()}function m(){n(),G=setTimeout(function(){G=0,k()},a.vmouse.resetTimerDuration)}function n(){G&&(clearTimeout(G),G=0)}function o(b,c,d){var e;return(d&&d[b]||!d&&h(c.target,b))&&(e=f(c,b),a(c.target).trigger(e)),e}function p(b){var c,d=a.data(b.target,A);L||Q&&Q===d||(c=o("v"+b.type,b),c&&(c.isDefaultPrevented()&&b.preventDefault(),c.isPropagationStopped()&&b.stopPropagation(),c.isImmediatePropagationStopped()&&b.stopImmediatePropagation()))}function q(b){var c,d,f,h=e(b).touches;h&&1===h.length&&(c=b.target,d=g(c),d.hasVirtualBinding&&(Q=P++,a.data(c,A,Q),n(),l(),J=!1,f=e(b).touches[0],H=f.pageX,I=f.pageY,o("vmouseover",b,d),o("vmousedown",b,d)))}function r(a){M||(J||o("vmousecancel",a,g(a.target)),J=!0,m())}function s(b){if(!M){var c=e(b).touches[0],d=J,f=a.vmouse.moveDistanceThreshold,h=g(b.target);J=J||Math.abs(c.pageX-H)>f||Math.abs(c.pageY-I)>f,J&&!d&&o("vmousecancel",b,h),o("vmousemove",b,h),m()}}function t(a){if(!M){j();var b,c,d=g(a.target);o("vmouseup",a,d),J||(b=o("vclick",a,d),b&&b.isDefaultPrevented()&&(c=e(a).changedTouches[0],K.push({touchID:Q,x:c.clientX,y:c.clientY}),L=!0)),o("vmouseout",a,d),J=!1,m()}}function u(b){var c,d=a.data(b,z);if(d)for(c in d)if(d[c])return!0;return!1}function v(){}function w(b){var c=b.substr(1);return{setup:function(){u(this)||a.data(this,z,{});var d=a.data(this,z);d[b]=!0,F[b]=(F[b]||0)+1,1===F[b]&&O.bind(c,p),a(this).bind(c,v),N&&(F.touchstart=(F.touchstart||0)+1,1===F.touchstart&&O.bind("touchstart",q).bind("touchend",t).bind("touchmove",s).bind("scroll",r))},teardown:function(){--F[b],F[b]||O.unbind(c,p),N&&(--F.touchstart,F.touchstart||O.unbind("touchstart",q).unbind("touchmove",s).unbind("touchend",t).unbind("scroll",r));var d=a(this),e=a.data(this,z);e&&(e[b]=!1),d.unbind(c,v),u(this)||d.removeData(z)}}}var x,y,z="virtualMouseBindings",A="virtualTouchID",B="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),C="clientX clientY pageX pageY screenX screenY".split(" "),D=a.event.mouseHooks?a.event.mouseHooks.props:[],E=a.event.props.concat(D),F={},G=0,H=0,I=0,J=!1,K=[],L=!1,M=!1,N="addEventListener"in c,O=a(c),P=1,Q=0;for(a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500},y=0;y<B.length;y++)a.event.special[B[y]]=w(B[y]);N&&c.addEventListener("click",function(b){var c,d,e,f,g,h,i=K.length,j=b.target;if(i)for(c=b.clientX,d=b.clientY,x=a.vmouse.clickDistanceThreshold,e=j;e;){for(f=0;i>f;f++)if(g=K[f],h=0,e===j&&Math.abs(g.x-c)<x&&Math.abs(g.y-d)<x||a.data(e,A)===g.touchID)return b.preventDefault(),void b.stopPropagation();e=e.parentNode}},!0)}(a,b,c),function(a,b,d){function e(b,c,e,f){var g=e.type;e.type=c,f?a.event.trigger(e,d,b):a.event.dispatch.call(b,e),e.type=g}var f=a(c),g=a.mobile.support.touch,h="touchmove scroll",i=g?"touchstart":"mousedown",j=g?"touchend":"mouseup",k=g?"touchmove":"mousemove";a.each("touchstart touchmove touchend tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(b,c){a.fn[c]=function(a){return a?this.bind(c,a):this.trigger(c)},a.attrFn&&(a.attrFn[c]=!0)}),a.event.special.scrollstart={enabled:!0,setup:function(){function b(a,b){c=b,e(f,c?"scrollstart":"scrollstop",a)}var c,d,f=this,g=a(f);g.bind(h,function(e){a.event.special.scrollstart.enabled&&(c||b(e,!0),clearTimeout(d),d=setTimeout(function(){b(e,!1)},50))})},teardown:function(){a(this).unbind(h)}},a.event.special.tap={tapholdThreshold:750,emitTapOnTaphold:!0,setup:function(){var b=this,c=a(b),d=!1;c.bind("vmousedown",function(g){function h(){clearTimeout(k)}function i(){h(),c.unbind("vclick",j).unbind("vmouseup",h),f.unbind("vmousecancel",i)}function j(a){i(),d||l!==a.target?d&&a.preventDefault():e(b,"tap",a)}if(d=!1,g.which&&1!==g.which)return!1;var k,l=g.target;c.bind("vmouseup",h).bind("vclick",j),f.bind("vmousecancel",i),k=setTimeout(function(){a.event.special.tap.emitTapOnTaphold||(d=!0),e(b,"taphold",a.Event("taphold",{target:l}))},a.event.special.tap.tapholdThreshold)})},teardown:function(){a(this).unbind("vmousedown").unbind("vclick").unbind("vmouseup"),f.unbind("vmousecancel")}},a.event.special.swipe={scrollSupressionThreshold:30,durationThreshold:1e3,horizontalDistanceThreshold:30,verticalDistanceThreshold:30,getLocation:function(a){var c=b.pageXOffset,d=b.pageYOffset,e=a.clientX,f=a.clientY;return 0===a.pageY&&Math.floor(f)>Math.floor(a.pageY)||0===a.pageX&&Math.floor(e)>Math.floor(a.pageX)?(e-=c,f-=d):(f<a.pageY-d||e<a.pageX-c)&&(e=a.pageX-c,f=a.pageY-d),{x:e,y:f}},start:function(b){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b,d=a.event.special.swipe.getLocation(c);return{time:(new Date).getTime(),coords:[d.x,d.y],origin:a(b.target)}},stop:function(b){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b,d=a.event.special.swipe.getLocation(c);return{time:(new Date).getTime(),coords:[d.x,d.y]}},handleSwipe:function(b,c,d,f){if(c.time-b.time<a.event.special.swipe.durationThreshold&&Math.abs(b.coords[0]-c.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(b.coords[1]-c.coords[1])<a.event.special.swipe.verticalDistanceThreshold){var g=b.coords[0]>c.coords[0]?"swipeleft":"swiperight";return e(d,"swipe",a.Event("swipe",{target:f,swipestart:b,swipestop:c}),!0),e(d,g,a.Event(g,{target:f,swipestart:b,swipestop:c}),!0),!0}return!1},eventInProgress:!1,setup:function(){var b,c=this,d=a(c),e={};b=a.data(this,"mobile-events"),b||(b={length:0},a.data(this,"mobile-events",b)),b.length++,b.swipe=e,e.start=function(b){if(!a.event.special.swipe.eventInProgress){a.event.special.swipe.eventInProgress=!0;var d,g=a.event.special.swipe.start(b),h=b.target,i=!1;e.move=function(b){g&&!b.isDefaultPrevented()&&(d=a.event.special.swipe.stop(b),i||(i=a.event.special.swipe.handleSwipe(g,d,c,h),i&&(a.event.special.swipe.eventInProgress=!1)),Math.abs(g.coords[0]-d.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault())},e.stop=function(){i=!0,a.event.special.swipe.eventInProgress=!1,f.off(k,e.move),e.move=null},f.on(k,e.move).one(j,e.stop)}},d.on(i,e.start)},teardown:function(){var b,c;b=a.data(this,"mobile-events"),b&&(c=b.swipe,delete b.swipe,b.length--,0===b.length&&a.removeData(this,"mobile-events")),c&&(c.start&&a(this).off(i,c.start),c.move&&f.off(k,c.move),c.stop&&f.off(j,c.stop))}},a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe.left",swiperight:"swipe.right"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)},teardown:function(){a(this).unbind(c)}}})}(a,this),function(a){a.event.special.throttledresize={setup:function(){a(this).bind("resize",f)},teardown:function(){a(this).unbind("resize",f)}};var b,c,d,e=250,f=function(){c=(new Date).getTime(),d=c-g,d>=e?(g=c,a(this).trigger("throttledresize")):(b&&clearTimeout(b),b=setTimeout(f,e-d))},g=0}(a),function(a,b){function d(){var a=e();a!==f&&(f=a,l.trigger(m))}var e,f,g,h,i,j,k,l=a(b),m="orientationchange",n={0:!0,180:!0};a.support.orientation&&(i=b.innerWidth||l.width(),j=b.innerHeight||l.height(),k=50,g=i>j&&i-j>k,h=n[b.orientation],(g&&h||!g&&!h)&&(n={"-90":!0,90:!0})),a.event.special.orientationchange=a.extend({},a.event.special.orientationchange,{setup:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:(f=e(),void l.bind("throttledresize",d))},teardown:function(){return a.support.orientation&&!a.event.special.orientationchange.disabled?!1:void l.unbind("throttledresize",d)},add:function(a){var b=a.handler;a.handler=function(a){return a.orientation=e(),b.apply(this,arguments)}}}),a.event.special.orientationchange.orientation=e=function(){var d=!0,e=c.documentElement;return d=a.support.orientation?n[b.orientation]:e&&e.clientWidth/e.clientHeight<1.1,d?"portrait":"landscape"},a.fn[m]=function(a){return a?this.bind(m,a):this.trigger(m)},a.attrFn&&(a.attrFn[m]=!0)}(a,this),function(a){var b=a("head").children("base"),c={element:b.length?b:a("<base>",{href:a.mobile.path.documentBase.hrefNoHash}).prependTo(a("head")),linkSelector:"[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]",set:function(b){a.mobile.dynamicBaseEnabled&&a.support.dynamicBaseTag&&c.element.attr("href",a.mobile.path.makeUrlAbsolute(b,a.mobile.path.documentBase))},rewrite:function(b,d){var e=a.mobile.path.get(b);d.find(c.linkSelector).each(function(b,c){var d=a(c).is("[href]")?"href":a(c).is("[src]")?"src":"action",f=a.mobile.path.parseLocation(),g=a(c).attr(d);g=g.replace(f.protocol+f.doubleSlash+f.host+f.pathname,""),/^(\w+:|#|\/)/.test(g)||a(c).attr(d,e+g)})},reset:function(){c.element.attr("href",a.mobile.path.documentBase.hrefNoSearch)}};a.mobile.base=c}(a),function(a,b){a.mobile.widgets={};var c=a.widget,d=a.mobile.keepNative;a.widget=function(c){return function(){var d=c.apply(this,arguments),e=d.prototype.widgetName;return d.initSelector=d.prototype.initSelector!==b?d.prototype.initSelector:":jqmData(role='"+e+"')",a.mobile.widgets[e]=d,d}}(a.widget),a.extend(a.widget,c),a.mobile.document.on("create",function(b){a(b.target).enhanceWithin()}),a.widget("mobile.page",{options:{theme:"a",domCache:!1,keepNativeDefault:a.mobile.keepNative,contentTheme:null,enhanced:!1},_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments),this._trigger("init")},_create:function(){return this._trigger("beforecreate")===!1?!1:(this.options.enhanced||this._enhance(),this._on(this.element,{pagebeforehide:"removeContainerBackground",pagebeforeshow:"_handlePageBeforeShow"}),this.element.enhanceWithin(),void("dialog"===a.mobile.getAttribute(this.element[0],"role")&&a.mobile.dialog&&this.element.dialog()))},_enhance:function(){var c="data-"+a.mobile.ns,d=this;this.options.role&&this.element.attr("data-"+a.mobile.ns+"role",this.options.role),this.element.attr("tabindex","0").addClass("ui-page ui-page-theme-"+this.options.theme),this.element.find("["+c+"role='content']").each(function(){var e=a(this),f=this.getAttribute(c+"theme")||b;d.options.contentTheme=f||d.options.contentTheme||d.options.dialog&&d.options.theme||"dialog"===d.element.jqmData("role")&&d.options.theme,e.addClass("ui-content"),d.options.contentTheme&&e.addClass("ui-body-"+d.options.contentTheme),e.attr("role","main").addClass("ui-content")})},bindRemove:function(b){var c=this.element;!c.data("mobile-page").options.domCache&&c.is(":jqmData(external-page='true')")&&c.bind("pagehide.remove",b||function(b,c){if(!c.samePage){var d=a(this),e=new a.Event("pageremove");d.trigger(e),e.isDefaultPrevented()||d.removeWithDependents()}})},_setOptions:function(c){c.theme!==b&&this.element.removeClass("ui-page-theme-"+this.options.theme).addClass("ui-page-theme-"+c.theme),c.contentTheme!==b&&this.element.find("[data-"+a.mobile.ns+"='content']").removeClass("ui-body-"+this.options.contentTheme).addClass("ui-body-"+c.contentTheme)},_handlePageBeforeShow:function(){this.setContainerBackground()},removeContainerBackground:function(){this.element.closest(":mobile-pagecontainer").pagecontainer({theme:"none"})},setContainerBackground:function(a){this.element.parent().pagecontainer({theme:a||this.options.theme})},keepNativeSelector:function(){var b=this.options,c=a.trim(b.keepNative||""),e=a.trim(a.mobile.keepNative),f=a.trim(b.keepNativeDefault),g=d===e?"":e,h=""===g?f:"";return(c?[c]:[]).concat(g?[g]:[]).concat(h?[h]:[]).join(", ")}})}(a),function(a,d){a.widget("mobile.pagecontainer",{options:{theme:"a"},initSelector:!1,_create:function(){this._trigger("beforecreate"),this.setLastScrollEnabled=!0,this._on(this.window,{navigate:"_disableRecordScroll",scrollstop:"_delayedRecordScroll"}),this._on(this.window,{navigate:"_filterNavigateEvents"}),this._on({pagechange:"_afterContentChange"}),this.window.one("navigate",a.proxy(function(){this.setLastScrollEnabled=!0},this))},_setOptions:function(a){a.theme!==d&&"none"!==a.theme?this.element.removeClass("ui-overlay-"+this.options.theme).addClass("ui-overlay-"+a.theme):a.theme!==d&&this.element.removeClass("ui-overlay-"+this.options.theme),this._super(a)},_disableRecordScroll:function(){this.setLastScrollEnabled=!1},_enableRecordScroll:function(){this.setLastScrollEnabled=!0},_afterContentChange:function(){this.setLastScrollEnabled=!0,this._off(this.window,"scrollstop"),this._on(this.window,{scrollstop:"_delayedRecordScroll"})},_recordScroll:function(){if(this.setLastScrollEnabled){var a,b,c,d=this._getActiveHistory();d&&(a=this._getScroll(),b=this._getMinScroll(),c=this._getDefaultScroll(),d.lastScroll=b>a?c:a)}},_delayedRecordScroll:function(){setTimeout(a.proxy(this,"_recordScroll"),100)},_getScroll:function(){return this.window.scrollTop()},_getMinScroll:function(){return a.mobile.minScrollBack},_getDefaultScroll:function(){return a.mobile.defaultHomeScroll},_filterNavigateEvents:function(b,c){var d;b.originalEvent&&b.originalEvent.isDefaultPrevented()||(d=b.originalEvent.type.indexOf("hashchange")>-1?c.state.hash:c.state.url,d||(d=this._getHash()),d&&"#"!==d&&0!==d.indexOf("#"+a.mobile.path.uiStateKey)||(d=location.href),this._handleNavigate(d,c.state))},_getHash:function(){return a.mobile.path.parseLocation().hash},getActivePage:function(){return this.activePage},_getInitialContent:function(){return a.mobile.firstPage},_getHistory:function(){return a.mobile.navigate.history},_getActiveHistory:function(){return this._getHistory().getActive()},_getDocumentBase:function(){return a.mobile.path.documentBase},back:function(){this.go(-1)},forward:function(){this.go(1)},go:function(c){if(a.mobile.hashListeningEnabled)b.history.go(c);else{var d=a.mobile.navigate.history.activeIndex,e=d+parseInt(c,10),f=a.mobile.navigate.history.stack[e].url,g=c>=1?"forward":"back";a.mobile.navigate.history.activeIndex=e,a.mobile.navigate.history.previousIndex=d,this.change(f,{direction:g,changeHash:!1,fromHashChange:!0})}},_handleDestination:function(b){var c;return"string"===a.type(b)&&(b=a.mobile.path.stripHash(b)),b&&(c=this._getHistory(),b=a.mobile.path.isPath(b)?b:a.mobile.path.makeUrlAbsolute("#"+b,this._getDocumentBase())),b||this._getInitialContent()},_transitionFromHistory:function(a,b){var c=this._getHistory(),d="back"===a?c.getLast():c.getActive();return d&&d.transition||b},_handleDialog:function(b,c){var d,e,f=this.getActivePage();return f&&!f.data("mobile-dialog")?("back"===c.direction?this.back():this.forward(),!1):(d=c.pageUrl,e=this._getActiveHistory(),a.extend(b,{role:e.role,transition:this._transitionFromHistory(c.direction,b.transition),reverse:"back"===c.direction}),d)},_handleNavigate:function(b,c){var d=a.mobile.path.stripHash(b),e=this._getHistory(),f=0===e.stack.length?"none":this._transitionFromHistory(c.direction),g={changeHash:!1,fromHashChange:!0,reverse:"back"===c.direction};a.extend(g,c,{transition:f}),e.activeIndex>0&&d.indexOf(a.mobile.dialogHashKey)>-1&&(d=this._handleDialog(g,c),d===!1)||this._changeContent(this._handleDestination(d),g)},_changeContent:function(b,c){a.mobile.changePage(b,c)},_getBase:function(){return a.mobile.base},_getNs:function(){return a.mobile.ns},_enhance:function(a,b){return a.page({role:b})},_include:function(a,b){a.appendTo(this.element),this._enhance(a,b.role),a.page("bindRemove")},_find:function(b){var c,d=this._createFileUrl(b),e=this._createDataUrl(b),f=this._getInitialContent();return c=this.element.children("[data-"+this._getNs()+"url='"+a.mobile.path.hashToSelector(e)+"']"),0===c.length&&e&&!a.mobile.path.isPath(e)&&(c=this.element.children(a.mobile.path.hashToSelector("#"+e)).attr("data-"+this._getNs()+"url",e).jqmData("url",e)),0===c.length&&a.mobile.path.isFirstPageUrl(d)&&f&&f.parent().length&&(c=a(f)),c},_getLoader:function(){return a.mobile.loading()},_showLoading:function(b,c,d,e){this._loadMsg||(this._loadMsg=setTimeout(a.proxy(function(){this._getLoader().loader("show",c,d,e),this._loadMsg=0},this),b))},_hideLoading:function(){clearTimeout(this._loadMsg),this._loadMsg=0,this._getLoader().loader("hide")},_showError:function(){this._hideLoading(),this._showLoading(0,a.mobile.pageLoadErrorMessageTheme,a.mobile.pageLoadErrorMessage,!0),setTimeout(a.proxy(this,"_hideLoading"),1500)},_parse:function(b,c){var d,e=a("<div></div>");return e.get(0).innerHTML=b,d=e.find(":jqmData(role='page'), :jqmData(role='dialog')").first(),d.length||(d=a("<div data-"+this._getNs()+"role='page'>"+(b.split(/<\/?body[^>]*>/gim)[1]||"")+"</div>")),d.attr("data-"+this._getNs()+"url",this._createDataUrl(c)).attr("data-"+this._getNs()+"external-page",!0),d},_setLoadedTitle:function(b,c){var d=c.match(/<title[^>]*>([^<]*)/)&&RegExp.$1;d&&!b.jqmData("title")&&(d=a("<div>"+d+"</div>").text(),b.jqmData("title",d))},_isRewritableBaseTag:function(){return a.mobile.dynamicBaseEnabled&&!a.support.dynamicBaseTag},_createDataUrl:function(b){return a.mobile.path.convertUrlToDataUrl(b)},_createFileUrl:function(b){return a.mobile.path.getFilePath(b)},_triggerWithDeprecated:function(b,c,d){var e=a.Event("page"+b),f=a.Event(this.widgetName+b);return(d||this.element).trigger(e,c),this._trigger(b,f,c),{deprecatedEvent:e,event:f}},_loadSuccess:function(b,c,e,f){var g=this._createFileUrl(b);return a.proxy(function(h,i,j){var k,l=new RegExp("(<[^>]+\\bdata-"+this._getNs()+"role=[\"']?page[\"']?[^>]*>)"),m=new RegExp("\\bdata-"+this._getNs()+"url=[\"']?([^\"'>]*)[\"']?");l.test(h)&&RegExp.$1&&m.test(RegExp.$1)&&RegExp.$1&&(g=a.mobile.path.getFilePath(a("<div>"+RegExp.$1+"</div>").text()),g=this.window[0].encodeURIComponent(g)),e.prefetch===d&&this._getBase().set(g),k=this._parse(h,g),this._setLoadedTitle(k,h),c.xhr=j,c.textStatus=i,c.page=k,c.content=k,c.toPage=k,this._triggerWithDeprecated("load",c).event.isDefaultPrevented()||(this._isRewritableBaseTag()&&k&&this._getBase().rewrite(g,k),this._include(k,e),e.showLoadMsg&&this._hideLoading(),f.resolve(b,e,k))},this)},_loadDefaults:{type:"get",data:d,reloadPage:!1,reload:!1,role:d,showLoadMsg:!1,loadMsgDelay:50},load:function(b,c){var e,f,g,h,i=c&&c.deferred||a.Deferred(),j=c&&c.reload===d&&c.reloadPage!==d?{reload:c.reloadPage}:{},k=a.extend({},this._loadDefaults,c,j),l=null,m=a.mobile.path.makeUrlAbsolute(b,this._findBaseWithDefault());return k.data&&"get"===k.type&&(m=a.mobile.path.addSearchParams(m,k.data),k.data=d),k.data&&"post"===k.type&&(k.reload=!0),e=this._createFileUrl(m),f=this._createDataUrl(m),l=this._find(m),0===l.length&&a.mobile.path.isEmbeddedPage(e)&&!a.mobile.path.isFirstPageUrl(e)?(i.reject(m,k),i.promise()):(this._getBase().reset(),l.length&&!k.reload?(this._enhance(l,k.role),i.resolve(m,k,l),k.prefetch||this._getBase().set(b),i.promise()):(h={url:b,absUrl:m,toPage:b,prevPage:c?c.fromPage:d,dataUrl:f,deferred:i,options:k},g=this._triggerWithDeprecated("beforeload",h),g.deprecatedEvent.isDefaultPrevented()||g.event.isDefaultPrevented()?i.promise():(k.showLoadMsg&&this._showLoading(k.loadMsgDelay),k.prefetch===d&&this._getBase().reset(),a.mobile.allowCrossDomainPages||a.mobile.path.isSameDomain(a.mobile.path.documentUrl,m)?(a.ajax({url:e,type:k.type,data:k.data,contentType:k.contentType,dataType:"html",success:this._loadSuccess(m,h,k,i),error:this._loadError(m,h,k,i)}),i.promise()):(i.reject(m,k),i.promise()))))},_loadError:function(b,c,d,e){return a.proxy(function(f,g,h){this._getBase().set(a.mobile.path.get()),c.xhr=f,c.textStatus=g,c.errorThrown=h;var i=this._triggerWithDeprecated("loadfailed",c);i.deprecatedEvent.isDefaultPrevented()||i.event.isDefaultPrevented()||(d.showLoadMsg&&this._showError(),e.reject(b,d))},this)},_getTransitionHandler:function(b){return b=a.mobile._maybeDegradeTransition(b),a.mobile.transitionHandlers[b]||a.mobile.defaultTransitionHandler},_triggerCssTransitionEvents:function(b,c,d){var e=!1;d=d||"",c&&(b[0]===c[0]&&(e=!0),this._triggerWithDeprecated(d+"hide",{nextPage:b,toPage:b,prevPage:c,samePage:e},c)),this._triggerWithDeprecated(d+"show",{prevPage:c||a(""),toPage:b},b)},_cssTransition:function(b,c,d){var e,f,g=d.transition,h=d.reverse,i=d.deferred;this._triggerCssTransitionEvents(b,c,"before"),this._hideLoading(),e=this._getTransitionHandler(g),f=new e(g,h,b,c).transition(),f.done(a.proxy(function(){this._triggerCssTransitionEvents(b,c)},this)),f.done(function(){i.resolve.apply(i,arguments)})},_releaseTransitionLock:function(){f=!1,e.length>0&&a.mobile.changePage.apply(null,e.pop())},_removeActiveLinkClass:function(b){a.mobile.removeActiveLinkClass(b)},_loadUrl:function(b,c,d){d.target=b,d.deferred=a.Deferred(),this.load(b,d),d.deferred.done(a.proxy(function(a,b,d){f=!1,b.absUrl=c.absUrl,this.transition(d,c,b)},this)),d.deferred.fail(a.proxy(function(){this._removeActiveLinkClass(!0),this._releaseTransitionLock(),this._triggerWithDeprecated("changefailed",c)},this))},_triggerPageBeforeChange:function(b,c,d){var e;return c.prevPage=this.activePage,a.extend(c,{toPage:b,options:d}),c.absUrl="string"===a.type(b)?a.mobile.path.makeUrlAbsolute(b,this._findBaseWithDefault()):d.absUrl,e=this._triggerWithDeprecated("beforechange",c),e.event.isDefaultPrevented()||e.deprecatedEvent.isDefaultPrevented()?!1:!0},change:function(b,c){if(f)return void e.unshift(arguments);var d=a.extend({},a.mobile.changePage.defaults,c),g={};d.fromPage=d.fromPage||this.activePage,this._triggerPageBeforeChange(b,g,d)&&(b=g.toPage,"string"===a.type(b)?(f=!0,this._loadUrl(b,g,d)):this.transition(b,g,d))},transition:function(b,g,h){var i,j,k,l,m,n,o,p,q,r,s,t,u,v;if(f)return void e.unshift([b,h]);if(this._triggerPageBeforeChange(b,g,h)&&(g.prevPage=h.fromPage,v=this._triggerWithDeprecated("beforetransition",g),!v.deprecatedEvent.isDefaultPrevented()&&!v.event.isDefaultPrevented())){if(f=!0,b[0]!==a.mobile.firstPage[0]||h.dataUrl||(h.dataUrl=a.mobile.path.documentUrl.hrefNoHash),i=h.fromPage,j=h.dataUrl&&a.mobile.path.convertUrlToDataUrl(h.dataUrl)||b.jqmData("url"),k=j,l=a.mobile.path.getFilePath(j),m=a.mobile.navigate.history.getActive(),n=0===a.mobile.navigate.history.activeIndex,o=0,p=c.title,q=("dialog"===h.role||"dialog"===b.jqmData("role"))&&b.jqmData("dialog")!==!0,i&&i[0]===b[0]&&!h.allowSamePageTransition)return f=!1,this._triggerWithDeprecated("transition",g),this._triggerWithDeprecated("change",g),void(h.fromHashChange&&a.mobile.navigate.history.direct({url:j}));b.page({role:h.role}),h.fromHashChange&&(o="back"===h.direction?-1:1);try{c.activeElement&&"body"!==c.activeElement.nodeName.toLowerCase()?a(c.activeElement).blur():a("input:focus, textarea:focus, select:focus").blur()}catch(w){}r=!1,q&&m&&(m.url&&m.url.indexOf(a.mobile.dialogHashKey)>-1&&this.activePage&&!this.activePage.hasClass("ui-dialog")&&a.mobile.navigate.history.activeIndex>0&&(h.changeHash=!1,r=!0),j=m.url||"",j+=!r&&j.indexOf("#")>-1?a.mobile.dialogHashKey:"#"+a.mobile.dialogHashKey),s=m?b.jqmData("title")||b.children(":jqmData(role='header')").find(".ui-title").text():p,s&&p===c.title&&(p=s),b.jqmData("title")||b.jqmData("title",p),h.transition=h.transition||(o&&!n?m.transition:d)||(q?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition),!o&&r&&(a.mobile.navigate.history.getActive().pageUrl=k),j&&!h.fromHashChange&&(!a.mobile.path.isPath(j)&&j.indexOf("#")<0&&(j="#"+j),t={transition:h.transition,title:p,pageUrl:k,role:h.role},h.changeHash!==!1&&a.mobile.hashListeningEnabled?a.mobile.navigate(this.window[0].encodeURI(j),t,!0):b[0]!==a.mobile.firstPage[0]&&a.mobile.navigate.history.add(j,t)),c.title=p,a.mobile.activePage=b,this.activePage=b,h.reverse=h.reverse||0>o,u=a.Deferred(),this._cssTransition(b,i,{transition:h.transition,reverse:h.reverse,deferred:u}),u.done(a.proxy(function(c,d,e,f,i){a.mobile.removeActiveLinkClass(),h.duplicateCachedPage&&h.duplicateCachedPage.remove(),i||a.mobile.focusPage(b),this._releaseTransitionLock(),this._triggerWithDeprecated("transition",g),this._triggerWithDeprecated("change",g)},this))}},_findBaseWithDefault:function(){var b=this.activePage&&a.mobile.getClosestBaseUrl(this.activePage);return b||a.mobile.path.documentBase.hrefNoHash}}),a.mobile.navreadyDeferred=a.Deferred();var e=[],f=!1}(a),function(a,d){function e(a){for(;a&&("string"!=typeof a.nodeName||"a"!==a.nodeName.toLowerCase());)a=a.parentNode;return a}var f=a.Deferred(),g=a.Deferred(),h=function(){g.resolve(),g=null},i=a.mobile.path.documentUrl,j=null;a.mobile.loadPage=function(b,c){var d;return c=c||{},d=c.pageContainer||a.mobile.pageContainer,c.deferred=a.Deferred(),d.pagecontainer("load",b,c),c.deferred.promise()},a.mobile.back=function(){var c=b.navigator;this.phonegapNavigationEnabled&&c&&c.app&&c.app.backHistory?c.app.backHistory():a.mobile.pageContainer.pagecontainer("back")},a.mobile.focusPage=function(a){var b=a.find("[autofocus]"),c=a.find(".ui-title:eq(0)");return b.length?void b.focus():void(c.length?c.focus():a.focus())},a.mobile._maybeDegradeTransition=a.mobile._maybeDegradeTransition||function(a){return a},a.mobile.changePage=function(b,c){a.mobile.pageContainer.pagecontainer("change",b,c)},a.mobile.changePage.defaults={transition:d,reverse:!1,changeHash:!0,fromHashChange:!1,role:d,duplicateCachedPage:d,pageContainer:d,showLoadMsg:!0,dataUrl:d,fromPage:d,allowSamePageTransition:!1},a.mobile._registerInternalEvents=function(){var c=function(b,c){var d,e,f,g,h=!0;return!a.mobile.ajaxEnabled||b.is(":jqmData(ajax='false')")||!b.jqmHijackable().length||b.attr("target")?!1:(d=j&&j.attr("formaction")||b.attr("action"),g=(b.attr("method")||"get").toLowerCase(),d||(d=a.mobile.getClosestBaseUrl(b),"get"===g&&(d=a.mobile.path.parseUrl(d).hrefNoSearch),d===a.mobile.path.documentBase.hrefNoHash&&(d=i.hrefNoSearch)),d=a.mobile.path.makeUrlAbsolute(d,a.mobile.getClosestBaseUrl(b)),a.mobile.path.isExternal(d)&&!a.mobile.path.isPermittedCrossDomainRequest(i,d)?!1:(c||(e=b.serializeArray(),j&&j[0].form===b[0]&&(f=j.attr("name"),f&&(a.each(e,function(a,b){return b.name===f?(f="",!1):void 0}),f&&e.push({name:f,value:j.attr("value")}))),h={url:d,options:{type:g,data:a.param(e),transition:b.jqmData("transition"),reverse:"reverse"===b.jqmData("direction"),reloadPage:!0}}),h))};a.mobile.document.delegate("form","submit",function(b){var d;b.isDefaultPrevented()||(d=c(a(this)),d&&(a.mobile.changePage(d.url,d.options),b.preventDefault()))}),a.mobile.document.bind("vclick",function(b){var d,f,g=b.target,h=!1;if(!(b.which>1)&&a.mobile.linkBindingEnabled){if(j=a(g),a.data(g,"mobile-button")){if(!c(a(g).closest("form"),!0))return;g.parentNode&&(g=g.parentNode)}else{if(g=e(g),!g||"#"===a.mobile.path.parseUrl(g.getAttribute("href")||"#").hash)return;if(!a(g).jqmHijackable().length)return}~g.className.indexOf("ui-link-inherit")?g.parentNode&&(f=a.data(g.parentNode,"buttonElements")):f=a.data(g,"buttonElements"),f?g=f.outer:h=!0,d=a(g),h&&(d=d.closest(".ui-btn")),d.length>0&&!d.hasClass("ui-state-disabled")&&(a.mobile.removeActiveLinkClass(!0),a.mobile.activeClickedLink=d,a.mobile.activeClickedLink.addClass(a.mobile.activeBtnClass))}}),a.mobile.document.bind("click",function(c){if(a.mobile.linkBindingEnabled&&!c.isDefaultPrevented()){var f,g,h,j,k,l,m,n=e(c.target),o=a(n),p=function(){b.setTimeout(function(){a.mobile.removeActiveLinkClass(!0)},200)};if(a.mobile.activeClickedLink&&a.mobile.activeClickedLink[0]===c.target.parentNode&&p(),n&&!(c.which>1)&&o.jqmHijackable().length){if(o.is(":jqmData(rel='back')"))return a.mobile.back(),!1;if(f=a.mobile.getClosestBaseUrl(o),g=a.mobile.path.makeUrlAbsolute(o.attr("href")||"#",f),!a.mobile.ajaxEnabled&&!a.mobile.path.isEmbeddedPage(g))return void p();if(!(-1===g.search("#")||a.mobile.path.isExternal(g)&&a.mobile.path.isAbsoluteUrl(g))){if(g=g.replace(/[^#]*#/,""),!g)return void c.preventDefault();g=a.mobile.path.isPath(g)?a.mobile.path.makeUrlAbsolute(g,f):a.mobile.path.makeUrlAbsolute("#"+g,i.hrefNoHash)}if(h=o.is("[rel='external']")||o.is(":jqmData(ajax='false')")||o.is("[target]"),j=h||a.mobile.path.isExternal(g)&&!a.mobile.path.isPermittedCrossDomainRequest(i,g))return void p();k=o.jqmData("transition"),l="reverse"===o.jqmData("direction")||o.jqmData("back"),m=o.attr("data-"+a.mobile.ns+"rel")||d,a.mobile.changePage(g,{transition:k,reverse:l,role:m,link:o}),c.preventDefault()}}}),a.mobile.document.delegate(".ui-page","pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),d=c.attr("href");d&&-1===a.inArray(d,b)&&(b.push(d),a.mobile.loadPage(d,{role:c.attr("data-"+a.mobile.ns+"rel"),prefetch:!0}))})}),a.mobile.pageContainer.pagecontainer(),a.mobile.document.bind("pageshow",function(){g?g.done(a.mobile.resetActivePageHeight):a.mobile.resetActivePageHeight()
+}),a.mobile.window.bind("throttledresize",a.mobile.resetActivePageHeight)},a(function(){f.resolve()}),"complete"===c.readyState?h():a.mobile.window.load(h),a.when(f,a.mobile.navreadyDeferred).done(function(){a.mobile._registerInternalEvents()})}(a),function(a,b){a.mobile.Transition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.Transition.prototype,{toPreClass:" ui-page-pre-in",init:function(b,c,d,e){a.extend(this,{name:b,reverse:c,$to:d,$from:e,deferred:new a.Deferred})},cleanFrom:function(){this.$from.removeClass(a.mobile.activePageClass+" out in reverse "+this.name).height("")},beforeDoneIn:function(){},beforeDoneOut:function(){},beforeStartOut:function(){},doneIn:function(){this.beforeDoneIn(),this.$to.removeClass("out in reverse "+this.name).height(""),this.toggleViewportClass(),a.mobile.window.scrollTop()!==this.toScroll&&this.scrollPage(),this.sequential||this.$to.addClass(a.mobile.activePageClass),this.deferred.resolve(this.name,this.reverse,this.$to,this.$from,!0)},doneOut:function(a,b,c,d){this.beforeDoneOut(),this.startIn(a,b,c,d)},hideIn:function(a){this.$to.css("z-index",-10),a.call(this),this.$to.css("z-index","")},scrollPage:function(){a.event.special.scrollstart.enabled=!1,(a.mobile.hideUrlBar||this.toScroll!==a.mobile.defaultHomeScroll)&&b.scrollTo(0,this.toScroll),setTimeout(function(){a.event.special.scrollstart.enabled=!0},150)},startIn:function(b,c,d,e){this.hideIn(function(){this.$to.addClass(a.mobile.activePageClass+this.toPreClass),e||a.mobile.focusPage(this.$to),this.$to.height(b+this.toScroll),d||this.scrollPage()}),this.$to.removeClass(this.toPreClass).addClass(this.name+" in "+c),d?this.doneIn():this.$to.animationComplete(a.proxy(function(){this.doneIn()},this))},startOut:function(b,c,d){this.beforeStartOut(b,c,d),this.$from.height(b+a.mobile.window.scrollTop()).addClass(this.name+" out"+c)},toggleViewportClass:function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+this.name)},transition:function(){var b,c=this.reverse?" reverse":"",d=a.mobile.getScreenHeight(),e=a.mobile.maxTransitionWidth!==!1&&a.mobile.window.width()>a.mobile.maxTransitionWidth;return this.toScroll=a.mobile.navigate.history.getActive().lastScroll||a.mobile.defaultHomeScroll,b=!a.support.cssTransitions||!a.support.cssAnimations||e||!this.name||"none"===this.name||Math.max(a.mobile.window.scrollTop(),this.toScroll)>a.mobile.getMaxScrollForTransition(),this.toggleViewportClass(),this.$from&&!b?this.startOut(d,c,b):this.doneOut(d,c,b,!0),this.deferred.promise()}})}(a,this),function(a){a.mobile.SerialTransition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.SerialTransition.prototype,a.mobile.Transition.prototype,{sequential:!0,beforeDoneOut:function(){this.$from&&this.cleanFrom()},beforeStartOut:function(b,c,d){this.$from.animationComplete(a.proxy(function(){this.doneOut(b,c,d)},this))}})}(a),function(a){a.mobile.ConcurrentTransition=function(){this.init.apply(this,arguments)},a.extend(a.mobile.ConcurrentTransition.prototype,a.mobile.Transition.prototype,{sequential:!1,beforeDoneIn:function(){this.$from&&this.cleanFrom()},beforeStartOut:function(a,b,c){this.doneOut(a,b,c)}})}(a),function(a){var b=function(){return 3*a.mobile.getScreenHeight()};a.mobile.transitionHandlers={sequential:a.mobile.SerialTransition,simultaneous:a.mobile.ConcurrentTransition},a.mobile.defaultTransitionHandler=a.mobile.transitionHandlers.sequential,a.mobile.transitionFallbacks={},a.mobile._maybeDegradeTransition=function(b){return b&&!a.support.cssTransform3d&&a.mobile.transitionFallbacks[b]&&(b=a.mobile.transitionFallbacks[b]),b},a.mobile.getMaxScrollForTransition=a.mobile.getMaxScrollForTransition||b}(a),function(a){a.mobile.transitionFallbacks.flip="fade"}(a,this),function(a){a.mobile.transitionFallbacks.flow="fade"}(a,this),function(a){a.mobile.transitionFallbacks.pop="fade"}(a,this),function(a){a.mobile.transitionHandlers.slide=a.mobile.transitionHandlers.simultaneous,a.mobile.transitionFallbacks.slide="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slidedown="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slidefade="fade"}(a,this),function(a){a.mobile.transitionFallbacks.slideup="fade"}(a,this),function(a){a.mobile.transitionFallbacks.turn="fade"}(a,this),function(a){a.mobile.degradeInputs={color:!1,date:!1,datetime:!1,"datetime-local":!1,email:!1,month:!1,number:!1,range:"number",search:"text",tel:!1,time:!1,url:!1,week:!1},a.mobile.page.prototype.options.degradeInputs=a.mobile.degradeInputs,a.mobile.degradeInputsWithin=function(b){b=a(b),b.find("input").not(a.mobile.page.prototype.keepNativeSelector()).each(function(){var b,c,d,e,f=a(this),g=this.getAttribute("type"),h=a.mobile.degradeInputs[g]||"text";a.mobile.degradeInputs[g]&&(b=a("<div>").html(f.clone()).html(),c=b.indexOf(" type=")>-1,d=c?/\s+type=["']?\w+['"]?/:/\/?>/,e=' type="'+h+'" data-'+a.mobile.ns+'type="'+g+'"'+(c?"":">"),f.replaceWith(b.replace(d,e)))})}}(a),function(a,b,c){a.widget("mobile.page",a.mobile.page,{options:{closeBtn:"left",closeBtnText:"Close",overlayTheme:"a",corners:!0,dialog:!1},_create:function(){this._super(),this.options.dialog&&(a.extend(this,{_inner:this.element.children(),_headerCloseButton:null}),this.options.enhanced||this._setCloseBtn(this.options.closeBtn))},_enhance:function(){this._super(),this.options.dialog&&this.element.addClass("ui-dialog").wrapInner(a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-overlay-shadow"+(this.options.corners?" ui-corner-all":"")}))},_setOptions:function(b){var d,e,f=this.options;b.corners!==c&&this._inner.toggleClass("ui-corner-all",!!b.corners),b.overlayTheme!==c&&a.mobile.activePage[0]===this.element[0]&&(f.overlayTheme=b.overlayTheme,this._handlePageBeforeShow()),b.closeBtnText!==c&&(d=f.closeBtn,e=b.closeBtnText),b.closeBtn!==c&&(d=b.closeBtn),d&&this._setCloseBtn(d,e),this._super(b)},_handlePageBeforeShow:function(){this.options.overlayTheme&&this.options.dialog?(this.removeContainerBackground(),this.setContainerBackground(this.options.overlayTheme)):this._super()},_setCloseBtn:function(b,c){var d,e=this._headerCloseButton;b="left"===b?"left":"right"===b?"right":"none","none"===b?e&&(e.remove(),e=null):e?(e.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-"+b),c&&e.text(c)):(d=this._inner.find(":jqmData(role='header')").first(),e=a("<a></a>",{href:"#","class":"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-"+b}).attr("data-"+a.mobile.ns+"rel","back").text(c||this.options.closeBtnText||"").prependTo(d)),this._headerCloseButton=e}})}(a,this),function(a,b,c){a.widget("mobile.dialog",{options:{closeBtn:"left",closeBtnText:"Close",overlayTheme:"a",corners:!0},_handlePageBeforeShow:function(){this._isCloseable=!0,this.options.overlayTheme&&this.element.page("removeContainerBackground").page("setContainerBackground",this.options.overlayTheme)},_handlePageBeforeHide:function(){this._isCloseable=!1},_handleVClickSubmit:function(b){var c,d=a(b.target).closest("vclick"===b.type?"a":"form");d.length&&!d.jqmData("transition")&&(c={},c["data-"+a.mobile.ns+"transition"]=(a.mobile.navigate.history.getActive()||{}).transition||a.mobile.defaultDialogTransition,c["data-"+a.mobile.ns+"direction"]="reverse",d.attr(c))},_create:function(){var b=this.element,c=this.options;b.addClass("ui-dialog").wrapInner(a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-overlay-shadow"+(c.corners?" ui-corner-all":"")})),a.extend(this,{_isCloseable:!1,_inner:b.children(),_headerCloseButton:null}),this._on(b,{vclick:"_handleVClickSubmit",submit:"_handleVClickSubmit",pagebeforeshow:"_handlePageBeforeShow",pagebeforehide:"_handlePageBeforeHide"}),this._setCloseBtn(c.closeBtn)},_setOptions:function(b){var d,e,f=this.options;b.corners!==c&&this._inner.toggleClass("ui-corner-all",!!b.corners),b.overlayTheme!==c&&a.mobile.activePage[0]===this.element[0]&&(f.overlayTheme=b.overlayTheme,this._handlePageBeforeShow()),b.closeBtnText!==c&&(d=f.closeBtn,e=b.closeBtnText),b.closeBtn!==c&&(d=b.closeBtn),d&&this._setCloseBtn(d,e),this._super(b)},_setCloseBtn:function(b,c){var d,e=this._headerCloseButton;b="left"===b?"left":"right"===b?"right":"none","none"===b?e&&(e.remove(),e=null):e?(e.removeClass("ui-btn-left ui-btn-right").addClass("ui-btn-"+b),c&&e.text(c)):(d=this._inner.find(":jqmData(role='header')").first(),e=a("<a></a>",{role:"button",href:"#","class":"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-"+b}).text(c||this.options.closeBtnText||"").prependTo(d),this._on(e,{click:"close"})),this._headerCloseButton=e},close:function(){var b=a.mobile.navigate.history;this._isCloseable&&(this._isCloseable=!1,a.mobile.hashListeningEnabled&&b.activeIndex>0?a.mobile.back():a.mobile.pageContainer.pagecontainer("back"))}})}(a,this),function(a,b){var c=/([A-Z])/g,d=function(a){return"ui-btn-icon-"+(null===a?"left":a)};a.widget("mobile.collapsible",{options:{enhanced:!1,expandCueText:null,collapseCueText:null,collapsed:!0,heading:"h1,h2,h3,h4,h5,h6,legend",collapsedIcon:null,expandedIcon:null,iconpos:null,theme:null,contentTheme:null,inset:null,corners:null,mini:null},_create:function(){var b=this.element,c={accordion:b.closest(":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')"+(a.mobile.collapsibleset?", :mobile-collapsibleset":"")).addClass("ui-collapsible-set")};this._ui=c,this._renderedOptions=this._getOptions(this.options),this.options.enhanced?(c.heading=this.element.children(".ui-collapsible-heading"),c.content=c.heading.next(),c.anchor=c.heading.children(),c.status=c.anchor.children(".ui-collapsible-heading-status")):this._enhance(b,c),this._on(c.heading,{tap:function(){c.heading.find("a").first().addClass(a.mobile.activeBtnClass)},click:function(a){this._handleExpandCollapse(!c.heading.hasClass("ui-collapsible-heading-collapsed")),a.preventDefault(),a.stopPropagation()}})},_getOptions:function(b){var d,e=this._ui.accordion,f=this._ui.accordionWidget;b=a.extend({},b),e.length&&!f&&(this._ui.accordionWidget=f=e.data("mobile-collapsibleset"));for(d in b)b[d]=null!=b[d]?b[d]:f?f.options[d]:e.length?a.mobile.getAttribute(e[0],d.replace(c,"-$1").toLowerCase()):null,null==b[d]&&(b[d]=a.mobile.collapsible.defaults[d]);return b},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:""},_enhance:function(b,c){var e,f=this._renderedOptions,g=this._themeClassFromOption("ui-body-",f.contentTheme);return b.addClass("ui-collapsible "+(f.inset?"ui-collapsible-inset ":"")+(f.inset&&f.corners?"ui-corner-all ":"")+(g?"ui-collapsible-themed-content ":"")),c.originalHeading=b.children(this.options.heading).first(),c.content=b.wrapInner("<div class='ui-collapsible-content "+g+"'></div>").children(".ui-collapsible-content"),c.heading=c.originalHeading,c.heading.is("legend")&&(c.heading=a("<div role='heading'>"+c.heading.html()+"</div>"),c.placeholder=a("<div><!-- placeholder for legend --></div>").insertBefore(c.originalHeading),c.originalHeading.remove()),e=f.collapsed?f.collapsedIcon?"ui-icon-"+f.collapsedIcon:"":f.expandedIcon?"ui-icon-"+f.expandedIcon:"",c.status=a("<span class='ui-collapsible-heading-status'></span>"),c.anchor=c.heading.detach().addClass("ui-collapsible-heading").append(c.status).wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().addClass("ui-btn "+(e?e+" ":"")+(e?d(f.iconpos)+" ":"")+this._themeClassFromOption("ui-btn-",f.theme)+" "+(f.mini?"ui-mini ":"")),c.heading.insertBefore(c.content),this._handleExpandCollapse(this.options.collapsed),c},refresh:function(){this._applyOptions(this.options),this._renderedOptions=this._getOptions(this.options)},_applyOptions:function(a){var c,e,f,g,h,i=this.element,j=this._renderedOptions,k=this._ui,l=k.anchor,m=k.status,n=this._getOptions(a);a.collapsed!==b&&this._handleExpandCollapse(a.collapsed),c=i.hasClass("ui-collapsible-collapsed"),c?n.expandCueText!==b&&m.text(n.expandCueText):n.collapseCueText!==b&&m.text(n.collapseCueText),h=n.collapsedIcon!==b?n.collapsedIcon!==!1:j.collapsedIcon!==!1,(n.iconpos!==b||n.collapsedIcon!==b||n.expandedIcon!==b)&&(l.removeClass([d(j.iconpos)].concat(j.expandedIcon?["ui-icon-"+j.expandedIcon]:[]).concat(j.collapsedIcon?["ui-icon-"+j.collapsedIcon]:[]).join(" ")),h&&l.addClass([d(n.iconpos!==b?n.iconpos:j.iconpos)].concat(c?["ui-icon-"+(n.collapsedIcon!==b?n.collapsedIcon:j.collapsedIcon)]:["ui-icon-"+(n.expandedIcon!==b?n.expandedIcon:j.expandedIcon)]).join(" "))),n.theme!==b&&(f=this._themeClassFromOption("ui-btn-",j.theme),e=this._themeClassFromOption("ui-btn-",n.theme),l.removeClass(f).addClass(e)),n.contentTheme!==b&&(f=this._themeClassFromOption("ui-body-",j.contentTheme),e=this._themeClassFromOption("ui-body-",n.contentTheme),k.content.removeClass(f).addClass(e)),n.inset!==b&&(i.toggleClass("ui-collapsible-inset",n.inset),g=!(!n.inset||!n.corners&&!j.corners)),n.corners!==b&&(g=!(!n.corners||!n.inset&&!j.inset)),g!==b&&i.toggleClass("ui-corner-all",g),n.mini!==b&&l.toggleClass("ui-mini",n.mini)},_setOptions:function(a){this._applyOptions(a),this._super(a),this._renderedOptions=this._getOptions(this.options)},_handleExpandCollapse:function(b){var c=this._renderedOptions,d=this._ui;d.status.text(b?c.expandCueText:c.collapseCueText),d.heading.toggleClass("ui-collapsible-heading-collapsed",b).find("a").first().toggleClass("ui-icon-"+c.expandedIcon,!b).toggleClass("ui-icon-"+c.collapsedIcon,b||c.expandedIcon===c.collapsedIcon).removeClass(a.mobile.activeBtnClass),this.element.toggleClass("ui-collapsible-collapsed",b),d.content.toggleClass("ui-collapsible-content-collapsed",b).attr("aria-hidden",b).trigger("updatelayout"),this.options.collapsed=b,this._trigger(b?"collapse":"expand")},expand:function(){this._handleExpandCollapse(!1)},collapse:function(){this._handleExpandCollapse(!0)},_destroy:function(){var a=this._ui,b=this.options;b.enhanced||(a.placeholder?(a.originalHeading.insertBefore(a.placeholder),a.placeholder.remove(),a.heading.remove()):(a.status.remove(),a.heading.removeClass("ui-collapsible-heading ui-collapsible-heading-collapsed").children().contents().unwrap()),a.anchor.contents().unwrap(),a.content.contents().unwrap(),this.element.removeClass("ui-collapsible ui-collapsible-collapsed ui-collapsible-themed-content ui-collapsible-inset ui-corner-all"))}}),a.mobile.collapsible.defaults={expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsedIcon:"plus",contentTheme:"inherit",expandedIcon:"minus",iconpos:"left",inset:!0,corners:!0,theme:"inherit",mini:!1}}(a),function(a){function b(b){var d,e=b.length,f=[];for(d=0;e>d;d++)b[d].className.match(c)||f.push(b[d]);return a(f)}var c=/\bui-screen-hidden\b/;a.mobile.behaviors.addFirstLastClasses={_getVisibles:function(a,c){var d;return c?d=b(a):(d=a.filter(":visible"),0===d.length&&(d=b(a))),d},_addFirstLastClasses:function(a,b,c){a.removeClass("ui-first-child ui-last-child"),b.eq(0).addClass("ui-first-child").end().last().addClass("ui-last-child"),c||this.element.trigger("updatelayout")},_removeFirstLastClasses:function(a){a.removeClass("ui-first-child ui-last-child")}}}(a),function(a,b){var c=":mobile-collapsible, "+a.mobile.collapsible.initSelector;a.widget("mobile.collapsibleset",a.extend({initSelector:":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')",options:a.extend({enhanced:!1},a.mobile.collapsible.defaults),_handleCollapsibleExpand:function(b){var c=a(b.target).closest(".ui-collapsible");c.parent().is(":mobile-collapsibleset, :jqmData(role='collapsible-set')")&&c.siblings(".ui-collapsible:not(.ui-collapsible-collapsed)").collapsible("collapse")},_create:function(){var b=this.element,c=this.options;a.extend(this,{_classes:""}),c.enhanced||(b.addClass("ui-collapsible-set "+this._themeClassFromOption("ui-group-theme-",c.theme)+" "+(c.corners&&c.inset?"ui-corner-all ":"")),this.element.find(a.mobile.collapsible.initSelector).collapsible()),this._on(b,{collapsibleexpand:"_handleCollapsibleExpand"})},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:""},_init:function(){this._refresh(!0),this.element.children(c).filter(":jqmData(collapsed='false')").collapsible("expand")},_setOptions:function(a){var c,d,e=this.element,f=this._themeClassFromOption("ui-group-theme-",a.theme);return f&&e.removeClass(this._themeClassFromOption("ui-group-theme-",this.options.theme)).addClass(f),a.inset!==b&&(d=!(!a.inset||!a.corners&&!this.options.corners)),a.corners!==b&&(d=!(!a.corners||!a.inset&&!this.options.inset)),d!==b&&e.toggleClass("ui-corner-all",d),c=this._super(a),this.element.children(":mobile-collapsible").collapsible("refresh"),c},_destroy:function(){var a=this.element;this._removeFirstLastClasses(a.children(c)),a.removeClass("ui-collapsible-set ui-corner-all "+this._themeClassFromOption("ui-group-theme-",this.options.theme)).children(":mobile-collapsible").collapsible("destroy")},_refresh:function(b){var d=this.element.children(c);this.element.find(a.mobile.collapsible.initSelector).not(".ui-collapsible").collapsible(),this._addFirstLastClasses(d,this._getVisibles(d,b),b)},refresh:function(){this._refresh(!1)}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain")}}(a),function(a){a.fn.grid=function(b){return this.each(function(){var c,d,e=a(this),f=a.extend({grid:null},b),g=e.children(),h={solo:1,a:2,b:3,c:4,d:5},i=f.grid;if(!i)if(g.length<=5)for(d in h)h[d]===g.length&&(i=d);else i="a",e.addClass("ui-grid-duo");c=h[i],e.addClass("ui-grid-"+i),g.filter(":nth-child("+c+"n+1)").addClass("ui-block-a"),c>1&&g.filter(":nth-child("+c+"n+2)").addClass("ui-block-b"),c>2&&g.filter(":nth-child("+c+"n+3)").addClass("ui-block-c"),c>3&&g.filter(":nth-child("+c+"n+4)").addClass("ui-block-d"),c>4&&g.filter(":nth-child("+c+"n+5)").addClass("ui-block-e")})}}(a),function(a,b){a.widget("mobile.navbar",{options:{iconpos:"top",grid:null},_create:function(){var d=this.element,e=d.find("a, button"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:b;d.addClass("ui-navbar").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid}),e.each(function(){var b=a.mobile.getAttribute(this,"icon"),c=a.mobile.getAttribute(this,"theme"),d="ui-btn";c&&(d+=" ui-btn-"+c),b&&(d+=" ui-icon-"+b+" ui-btn-icon-"+f),a(this).addClass(d)}),d.delegate("a","vclick",function(){var b=a(this);b.hasClass("ui-state-disabled")||b.hasClass("ui-disabled")||b.hasClass(a.mobile.activeBtnClass)||(e.removeClass(a.mobile.activeBtnClass),b.addClass(a.mobile.activeBtnClass),a(c).one("pagehide",function(){b.removeClass(a.mobile.activeBtnClass)}))}),d.closest(".ui-page").bind("pagebeforeshow",function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}})}(a),function(a){var b=a.mobile.getAttribute;a.widget("mobile.listview",a.extend({options:{theme:null,countTheme:null,dividerTheme:null,icon:"carat-r",splitIcon:"carat-r",splitTheme:null,corners:!0,shadow:!0,inset:!1},_create:function(){var a=this,b="";b+=a.options.inset?" ui-listview-inset":"",a.options.inset&&(b+=a.options.corners?" ui-corner-all":"",b+=a.options.shadow?" ui-shadow":""),a.element.addClass(" ui-listview"+b),a.refresh(!0)},_findFirstElementByTagName:function(a,b,c,d){var e={};for(e[c]=e[d]=!0;a;){if(e[a.nodeName])return a;a=a[b]}return null},_addThumbClasses:function(b){var c,d,e=b.length;for(c=0;e>c;c++)d=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),d.length&&a(this._findFirstElementByTagName(d[0].parentNode,"parentNode","li","LI")).addClass(d.hasClass("ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb")},_getChildrenByTagName:function(b,c,d){var e=[],f={};for(f[c]=f[d]=!0,b=b.firstChild;b;)f[b.nodeName]&&e.push(b),b=b.nextSibling;return a(e)},_beforeListviewRefresh:a.noop,_afterListviewRefresh:a.noop,refresh:function(c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=this.options,y=this.element,z=!!a.nodeName(y[0],"ol"),A=y.attr("start"),B={},C=y.find(".ui-li-count"),D=b(y[0],"counttheme")||this.options.countTheme,E=D?"ui-body-"+D:"ui-body-inherit";for(x.theme&&y.addClass("ui-group-theme-"+x.theme),z&&(A||0===A)&&(n=parseInt(A,10)-1,y.css("counter-reset","listnumbering "+n)),this._beforeListviewRefresh(),w=this._getChildrenByTagName(y[0],"li","LI"),e=0,f=w.length;f>e;e++)g=w.eq(e),h="",(c||g[0].className.search(/\bui-li-static\b|\bui-li-divider\b/)<0)&&(l=this._getChildrenByTagName(g[0],"a","A"),m="list-divider"===b(g[0],"role"),p=g.attr("value"),i=b(g[0],"theme"),l.length&&l[0].className.search(/\bui-btn\b/)<0&&!m?(j=b(g[0],"icon"),k=j===!1?!1:j||x.icon,l.removeClass("ui-link"),d="ui-btn",i&&(d+=" ui-btn-"+i),l.length>1?(h="ui-li-has-alt",q=l.last(),r=b(q[0],"theme")||x.splitTheme||b(g[0],"theme",!0),s=r?" ui-btn-"+r:"",t=b(q[0],"icon")||b(g[0],"icon")||x.splitIcon,u="ui-btn ui-btn-icon-notext ui-icon-"+t+s,q.attr("title",a.trim(q.getEncodedText())).addClass(u).empty(),l=l.first()):k&&(d+=" ui-btn-icon-right ui-icon-"+k),l.addClass(d)):m?(v=b(g[0],"theme")||x.dividerTheme||x.theme,h="ui-li-divider ui-bar-"+(v?v:"inherit"),g.attr("role","heading")):l.length<=0&&(h="ui-li-static ui-body-"+(i?i:"inherit")),z&&p&&(o=parseInt(p,10)-1,g.css("counter-reset","listnumbering "+o))),B[h]||(B[h]=[]),B[h].push(g[0]);for(h in B)a(B[h]).addClass(h);C.each(function(){a(this).closest("li").addClass("ui-li-has-count")}),E&&C.not("[class*='ui-body-']").addClass(E),this._addThumbClasses(w),this._addThumbClasses(w.find(".ui-btn")),this._afterListviewRefresh(),this._addFirstLastClasses(w,this._getVisibles(w,c),c)}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a){function b(b){var c=a.trim(b.text())||null;return c?c=c.slice(0,1).toUpperCase():null}a.widget("mobile.listview",a.mobile.listview,{options:{autodividers:!1,autodividersSelector:b},_beforeListviewRefresh:function(){this.options.autodividers&&(this._replaceDividers(),this._superApply(arguments))},_replaceDividers:function(){var b,d,e,f,g,h=null,i=this.element;for(i.children("li:jqmData(role='list-divider')").remove(),d=i.children("li"),b=0;b<d.length;b++)e=d[b],f=this.options.autodividersSelector(a(e)),f&&h!==f&&(g=c.createElement("li"),g.appendChild(c.createTextNode(f)),g.setAttribute("data-"+a.mobile.ns+"role","list-divider"),e.parentNode.insertBefore(g,e)),h=f}})}(a),function(a){var b=/(^|\s)ui-li-divider($|\s)/,c=/(^|\s)ui-screen-hidden($|\s)/;a.widget("mobile.listview",a.mobile.listview,{options:{hideDividers:!1},_afterListviewRefresh:function(){var a,d,e,f=!0;if(this._superApply(arguments),this.options.hideDividers)for(a=this._getChildrenByTagName(this.element[0],"li","LI"),d=a.length-1;d>-1;d--)e=a[d],e.className.match(b)?(f&&(e.className=e.className+" ui-screen-hidden"),f=!0):e.className.match(c)||(f=!1)}})}(a),function(a){a.mobile.nojs=function(b){a(":jqmData(role='nojs')",b).addClass("ui-nojs")}}(a),function(a){a.mobile.behaviors.formReset={_handleFormReset:function(){this._on(this.element.closest("form"),{reset:function(){this._delay("_reset")}})}}}(a),function(a,b){var c=a.mobile.path.hashToSelector;a.widget("mobile.checkboxradio",a.extend({initSelector:"input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",options:{theme:"inherit",mini:!1,wrapperClass:null,enhanced:!1,iconpos:"left"},_create:function(){var b=this.element,c=this.options,d=function(a,b){return a.jqmData(b)||a.closest("form, fieldset").jqmData(b)},e=this.options.enhanced?{element:this.element.siblings("label"),isParent:!1}:this._findLabel(),f=b[0].type,g="ui-"+f+"-on",h="ui-"+f+"-off";("checkbox"===f||"radio"===f)&&(this.element[0].disabled&&(this.options.disabled=!0),c.iconpos=d(b,"iconpos")||e.element.attr("data-"+a.mobile.ns+"iconpos")||c.iconpos,c.mini=d(b,"mini")||c.mini,a.extend(this,{input:b,label:e.element,labelIsParent:e.isParent,inputtype:f,checkedClass:g,uncheckedClass:h}),this.options.enhanced||this._enhance(),this._on(e.element,{vmouseover:"_handleLabelVMouseOver",vclick:"_handleLabelVClick"}),this._on(b,{vmousedown:"_cacheVals",vclick:"_handleInputVClick",focus:"_handleInputFocus",blur:"_handleInputBlur"}),this._handleFormReset(),this.refresh())},_findLabel:function(){var b,d,e,f=this.element,g=f[0].labels;return g&&g.length>0?(d=a(g[0]),e=a.contains(d[0],f[0])):(b=f.closest("label"),e=b.length>0,d=e?b:a(this.document[0].getElementsByTagName("label")).filter("[for='"+c(f[0].id)+"']").first()),{element:d,isParent:e}},_enhance:function(){this.label.addClass("ui-btn ui-corner-all"),this.labelIsParent?this.input.add(this.label).wrapAll(this._wrapper()):(this.element.wrap(this._wrapper()),this.element.parent().prepend(this.label)),this._setOptions({theme:this.options.theme,iconpos:this.options.iconpos,mini:this.options.mini})},_wrapper:function(){return a("<div class='"+(this.options.wrapperClass?this.options.wrapperClass:"")+" ui-"+this.inputtype+(this.options.disabled?" ui-state-disabled":"")+"' ></div>")},_handleInputFocus:function(){this.label.addClass(a.mobile.focusClass)},_handleInputBlur:function(){this.label.removeClass(a.mobile.focusClass)},_handleInputVClick:function(){this.element.prop("checked",this.element.is(":checked")),this._getInputSet().not(this.element).prop("checked",!1),this._updateAll(!0)},_handleLabelVMouseOver:function(a){this.label.parent().hasClass("ui-state-disabled")&&a.stopPropagation()},_handleLabelVClick:function(a){var b=this.element;return b.is(":disabled")?void a.preventDefault():(this._cacheVals(),b.prop("checked","radio"===this.inputtype&&!0||!b.prop("checked")),b.triggerHandler("click"),this._getInputSet().not(b).prop("checked",!1),this._updateAll(),!1)},_cacheVals:function(){this._getInputSet().each(function(){a(this).attr("data-"+a.mobile.ns+"cacheVal",this.checked)})},_getInputSet:function(){var b,d,e=this.element[0],f=e.name,g=e.form,h=this.element.parents().last().get(0),i=this.element;return f&&"radio"===this.inputtype&&h&&(b="input[type='radio'][name='"+c(f)+"']",g?(d=g.getAttribute("id"),d&&(i=a(b+"[form='"+c(d)+"']",h)),i=a(g).find(b).filter(function(){return this.form===g}).add(i)):i=a(b,h).filter(function(){return!this.form})),i},_updateAll:function(b){var c=this;this._getInputSet().each(function(){var d=a(this);!this.checked&&"checkbox"!==c.inputtype||b||d.trigger("change")}).checkboxradio("refresh")},_reset:function(){this.refresh()},_hasIcon:function(){var b,c,d=a.mobile.controlgroup;return d&&(b=this.element.closest(":mobile-controlgroup,"+d.prototype.initSelector),b.length>0)?(c=a.data(b[0],"mobile-controlgroup"),"horizontal"!==(c?c.options.type:b.attr("data-"+a.mobile.ns+"type"))):!0},refresh:function(){var b=this.element[0].checked,c=a.mobile.activeBtnClass,d="ui-btn-icon-"+this.options.iconpos,e=[],f=[];this._hasIcon()?(f.push(c),e.push(d)):(f.push(d),(b?e:f).push(c)),b?(e.push(this.checkedClass),f.push(this.uncheckedClass)):(e.push(this.uncheckedClass),f.push(this.checkedClass)),this.widget().toggleClass("ui-state-disabled",this.element.prop("disabled")),this.label.addClass(e.join(" ")).removeClass(f.join(" "))},widget:function(){return this.label.parent()},_setOptions:function(a){var c=this.label,d=this.options,e=this.widget(),f=this._hasIcon();a.disabled!==b&&(this.input.prop("disabled",!!a.disabled),e.toggleClass("ui-state-disabled",!!a.disabled)),a.mini!==b&&e.toggleClass("ui-mini",!!a.mini),a.theme!==b&&c.removeClass("ui-btn-"+d.theme).addClass("ui-btn-"+a.theme),a.wrapperClass!==b&&e.removeClass(d.wrapperClass).addClass(a.wrapperClass),a.iconpos!==b&&f?c.removeClass("ui-btn-icon-"+d.iconpos).addClass("ui-btn-icon-"+a.iconpos):f||c.removeClass("ui-btn-icon-"+d.iconpos),this._super(a)}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.button",{initSelector:"input[type='button'], input[type='submit'], input[type='reset']",options:{theme:null,icon:null,iconpos:"left",iconshadow:!1,corners:!0,shadow:!0,inline:null,mini:null,wrapperClass:null,enhanced:!1},_create:function(){this.element.is(":disabled")&&(this.options.disabled=!0),this.options.enhanced||this._enhance(),a.extend(this,{wrapper:this.element.parent()}),this._on({focus:function(){this.widget().addClass(a.mobile.focusClass)},blur:function(){this.widget().removeClass(a.mobile.focusClass)}}),this.refresh(!0)},_enhance:function(){this.element.wrap(this._button())},_button:function(){var b=this.options,c=this._getIconClasses(this.options);return a("<div class='ui-btn ui-input-btn"+(b.wrapperClass?" "+b.wrapperClass:"")+(b.theme?" ui-btn-"+b.theme:"")+(b.corners?" ui-corner-all":"")+(b.shadow?" ui-shadow":"")+(b.inline?" ui-btn-inline":"")+(b.mini?" ui-mini":"")+(b.disabled?" ui-state-disabled":"")+(c?" "+c:"")+"' >"+this.element.val()+"</div>")},widget:function(){return this.wrapper},_destroy:function(){this.element.insertBefore(this.wrapper),this.wrapper.remove()},_getIconClasses:function(a){return a.icon?"ui-icon-"+a.icon+(a.iconshadow?" ui-shadow-icon":"")+" ui-btn-icon-"+a.iconpos:""},_setOptions:function(c){var d=this.widget();c.theme!==b&&d.removeClass(this.options.theme).addClass("ui-btn-"+c.theme),c.corners!==b&&d.toggleClass("ui-corner-all",c.corners),c.shadow!==b&&d.toggleClass("ui-shadow",c.shadow),c.inline!==b&&d.toggleClass("ui-btn-inline",c.inline),c.mini!==b&&d.toggleClass("ui-mini",c.mini),c.disabled!==b&&(this.element.prop("disabled",c.disabled),d.toggleClass("ui-state-disabled",c.disabled)),(c.icon!==b||c.iconshadow!==b||c.iconpos!==b)&&d.removeClass(this._getIconClasses(this.options)).addClass(this._getIconClasses(a.extend({},this.options,c))),this._super(c)},refresh:function(b){var c,d=this.element.prop("disabled");this.options.icon&&"notext"===this.options.iconpos&&this.element.attr("title")&&this.element.attr("title",this.element.val()),b||(c=this.element.detach(),a(this.wrapper).text(this.element.val()).append(c)),this.options.disabled!==d&&this._setOptions({disabled:d})}})}(a),function(a){var b=a("meta[name=viewport]"),c=b.attr("content"),d=c+",maximum-scale=1, user-scalable=no",e=c+",maximum-scale=10, user-scalable=yes",f=/(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(c);a.mobile.zoom=a.extend({},{enabled:!f,locked:!1,disable:function(c){f||a.mobile.zoom.locked||(b.attr("content",d),a.mobile.zoom.enabled=!1,a.mobile.zoom.locked=c||!1)},enable:function(c){f||a.mobile.zoom.locked&&c!==!0||(b.attr("content",e),a.mobile.zoom.enabled=!0,a.mobile.zoom.locked=!1)},restore:function(){f||(b.attr("content",c),a.mobile.zoom.enabled=!0)}})}(a),function(a,b){a.widget("mobile.textinput",{initSelector:"input[type='text'],input[type='search'],:jqmData(type='search'),input[type='number'],:jqmData(type='number'),input[type='password'],input[type='email'],input[type='url'],input[type='tel'],textarea,input[type='time'],input[type='date'],input[type='month'],input[type='week'],input[type='datetime'],input[type='datetime-local'],input[type='color'],input:not([type]),input[type='file']",options:{theme:null,corners:!0,mini:!1,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,wrapperClass:"",enhanced:!1},_create:function(){var b=this.options,c=this.element.is("[type='search'], :jqmData(type='search')"),d="TEXTAREA"===this.element[0].tagName,e=this.element.is("[data-"+(a.mobile.ns||"")+"type='range']"),f=(this.element.is("input")||this.element.is("[data-"+(a.mobile.ns||"")+"type='search']"))&&!e;this.element.prop("disabled")&&(b.disabled=!0),a.extend(this,{classes:this._classesFromOptions(),isSearch:c,isTextarea:d,isRange:e,inputNeedsWrap:f}),this._autoCorrect(),b.enhanced||this._enhance(),this._on({focus:"_handleFocus",blur:"_handleBlur"})},refresh:function(){this.setOptions({disabled:this.element.is(":disabled")})},_enhance:function(){var a=[];this.isTextarea&&a.push("ui-input-text"),(this.isTextarea||this.isRange)&&a.push("ui-shadow-inset"),this.inputNeedsWrap?this.element.wrap(this._wrap()):a=a.concat(this.classes),this.element.addClass(a.join(" "))},widget:function(){return this.inputNeedsWrap?this.element.parent():this.element},_classesFromOptions:function(){var a=this.options,b=[];return b.push("ui-body-"+(null===a.theme?"inherit":a.theme)),a.corners&&b.push("ui-corner-all"),a.mini&&b.push("ui-mini"),a.disabled&&b.push("ui-state-disabled"),a.wrapperClass&&b.push(a.wrapperClass),b
+},_wrap:function(){return a("<div class='"+(this.isSearch?"ui-input-search ":"ui-input-text ")+this.classes.join(" ")+" ui-shadow-inset'></div>")},_autoCorrect:function(){"undefined"==typeof this.element[0].autocorrect||a.support.touchOverflow||(this.element[0].setAttribute("autocorrect","off"),this.element[0].setAttribute("autocomplete","off"))},_handleBlur:function(){this.widget().removeClass(a.mobile.focusClass),this.options.preventFocusZoom&&a.mobile.zoom.enable(!0)},_handleFocus:function(){this.options.preventFocusZoom&&a.mobile.zoom.disable(!0),this.widget().addClass(a.mobile.focusClass)},_setOptions:function(a){var c=this.widget();this._super(a),(a.disabled!==b||a.mini!==b||a.corners!==b||a.theme!==b||a.wrapperClass!==b)&&(c.removeClass(this.classes.join(" ")),this.classes=this._classesFromOptions(),c.addClass(this.classes.join(" "))),a.disabled!==b&&this.element.prop("disabled",!!a.disabled)},_destroy:function(){this.options.enhanced||(this.inputNeedsWrap&&this.element.unwrap(),this.element.removeClass("ui-input-text "+this.classes.join(" ")))}})}(a),function(a,d){a.widget("mobile.slider",a.extend({initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",widgetEventPrefix:"slide",options:{theme:null,trackTheme:null,corners:!0,mini:!1,highlight:!1},_create:function(){var e,f,g,h,i,j,k,l,m,n,o=this,p=this.element,q=this.options.trackTheme||a.mobile.getAttribute(p[0],"theme"),r=q?" ui-bar-"+q:" ui-bar-inherit",s=this.options.corners||p.jqmData("corners")?" ui-corner-all":"",t=this.options.mini||p.jqmData("mini")?" ui-mini":"",u=p[0].nodeName.toLowerCase(),v="select"===u,w=p.parent().is(":jqmData(role='rangeslider')"),x=v?"ui-slider-switch":"",y=p.attr("id"),z=a("[for='"+y+"']"),A=z.attr("id")||y+"-label",B=v?0:parseFloat(p.attr("min")),C=v?p.find("option").length-1:parseFloat(p.attr("max")),D=b.parseFloat(p.attr("step")||1),E=c.createElement("a"),F=a(E),G=c.createElement("div"),H=a(G),I=this.options.highlight&&!v?function(){var b=c.createElement("div");return b.className="ui-slider-bg "+a.mobile.activeBtnClass,a(b).prependTo(H)}():!1;if(z.attr("id",A),this.isToggleSwitch=v,E.setAttribute("href","#"),G.setAttribute("role","application"),G.className=[this.isToggleSwitch?"ui-slider ui-slider-track ui-shadow-inset ":"ui-slider-track ui-shadow-inset ",x,r,s,t].join(""),E.className="ui-slider-handle",G.appendChild(E),F.attr({role:"slider","aria-valuemin":B,"aria-valuemax":C,"aria-valuenow":this._value(),"aria-valuetext":this._value(),title:this._value(),"aria-labelledby":A}),a.extend(this,{slider:H,handle:F,control:p,type:u,step:D,max:C,min:B,valuebg:I,isRangeslider:w,dragging:!1,beforeStart:null,userModified:!1,mouseMoved:!1}),v){for(k=p.attr("tabindex"),k&&F.attr("tabindex",k),p.attr("tabindex","-1").focus(function(){a(this).blur(),F.focus()}),f=c.createElement("div"),f.className="ui-slider-inneroffset",g=0,h=G.childNodes.length;h>g;g++)f.appendChild(G.childNodes[g]);for(G.appendChild(f),F.addClass("ui-slider-handle-snapping"),e=p.find("option"),i=0,j=e.length;j>i;i++)l=i?"a":"b",m=i?" "+a.mobile.activeBtnClass:"",n=c.createElement("span"),n.className=["ui-slider-label ui-slider-label-",l,m].join(""),n.setAttribute("role","img"),n.appendChild(c.createTextNode(e[i].innerHTML)),a(n).prependTo(H);o._labels=a(".ui-slider-label",H)}p.addClass(v?"ui-slider-switch":"ui-slider-input"),this._on(p,{change:"_controlChange",keyup:"_controlKeyup",blur:"_controlBlur",vmouseup:"_controlVMouseUp"}),H.bind("vmousedown",a.proxy(this._sliderVMouseDown,this)).bind("vclick",!1),this._on(c,{vmousemove:"_preventDocumentDrag"}),this._on(H.add(c),{vmouseup:"_sliderVMouseUp"}),H.insertAfter(p),v||w||(f=this.options.mini?"<div class='ui-slider ui-mini'>":"<div class='ui-slider'>",p.add(H).wrapAll(f)),this._on(this.handle,{vmousedown:"_handleVMouseDown",keydown:"_handleKeydown",keyup:"_handleKeyup"}),this.handle.bind("vclick",!1),this._handleFormReset(),this.refresh(d,d,!0)},_setOptions:function(a){a.theme!==d&&this._setTheme(a.theme),a.trackTheme!==d&&this._setTrackTheme(a.trackTheme),a.corners!==d&&this._setCorners(a.corners),a.mini!==d&&this._setMini(a.mini),a.highlight!==d&&this._setHighlight(a.highlight),a.disabled!==d&&this._setDisabled(a.disabled),this._super(a)},_controlChange:function(a){return this._trigger("controlchange",a)===!1?!1:void(this.mouseMoved||this.refresh(this._value(),!0))},_controlKeyup:function(){this.refresh(this._value(),!0,!0)},_controlBlur:function(){this.refresh(this._value(),!0)},_controlVMouseUp:function(){this._checkedRefresh()},_handleVMouseDown:function(){this.handle.focus()},_handleKeydown:function(b){var c=this._value();if(!this.options.disabled){switch(b.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.preventDefault(),this._keySliding||(this._keySliding=!0,this.handle.addClass("ui-state-active"))}switch(b.keyCode){case a.mobile.keyCode.HOME:this.refresh(this.min);break;case a.mobile.keyCode.END:this.refresh(this.max);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:this.refresh(c+this.step);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:this.refresh(c-this.step)}}},_handleKeyup:function(){this._keySliding&&(this._keySliding=!1,this.handle.removeClass("ui-state-active"))},_sliderVMouseDown:function(a){return this.options.disabled||1!==a.which&&0!==a.which&&a.which!==d?!1:this._trigger("beforestart",a)===!1?!1:(this.dragging=!0,this.userModified=!1,this.mouseMoved=!1,this.isToggleSwitch&&(this.beforeStart=this.element[0].selectedIndex),this.refresh(a),this._trigger("start"),!1)},_sliderVMouseUp:function(){return this.dragging?(this.dragging=!1,this.isToggleSwitch&&(this.handle.addClass("ui-slider-handle-snapping"),this.refresh(this.mouseMoved?this.userModified?0===this.beforeStart?1:0:this.beforeStart:0===this.beforeStart?1:0)),this.mouseMoved=!1,this._trigger("stop"),!1):void 0},_preventDocumentDrag:function(a){return this._trigger("drag",a)===!1?!1:this.dragging&&!this.options.disabled?(this.mouseMoved=!0,this.isToggleSwitch&&this.handle.removeClass("ui-slider-handle-snapping"),this.refresh(a),this.userModified=this.beforeStart!==this.element[0].selectedIndex,!1):void 0},_checkedRefresh:function(){this.value!==this._value()&&this.refresh(this._value())},_value:function(){return this.isToggleSwitch?this.element[0].selectedIndex:parseFloat(this.element.val())},_reset:function(){this.refresh(d,!1,!0)},refresh:function(b,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z=this,A=a.mobile.getAttribute(this.element[0],"theme"),B=this.options.theme||A,C=B?" ui-btn-"+B:"",D=this.options.trackTheme||A,E=D?" ui-bar-"+D:" ui-bar-inherit",F=this.options.corners?" ui-corner-all":"",G=this.options.mini?" ui-mini":"";if(z.slider[0].className=[this.isToggleSwitch?"ui-slider ui-slider-switch ui-slider-track ui-shadow-inset":"ui-slider-track ui-shadow-inset",E,F,G].join(""),(this.options.disabled||this.element.prop("disabled"))&&this.disable(),this.value=this._value(),this.options.highlight&&!this.isToggleSwitch&&0===this.slider.find(".ui-slider-bg").length&&(this.valuebg=function(){var b=c.createElement("div");return b.className="ui-slider-bg "+a.mobile.activeBtnClass,a(b).prependTo(z.slider)}()),this.handle.addClass("ui-btn"+C+" ui-shadow"),l=this.element,m=!this.isToggleSwitch,n=m?[]:l.find("option"),o=m?parseFloat(l.attr("min")):0,p=m?parseFloat(l.attr("max")):n.length-1,q=m&&parseFloat(l.attr("step"))>0?parseFloat(l.attr("step")):1,"object"==typeof b){if(h=b,i=8,f=this.slider.offset().left,g=this.slider.width(),j=g/((p-o)/q),!this.dragging||h.pageX<f-i||h.pageX>f+g+i)return;k=j>1?(h.pageX-f)/g*100:Math.round((h.pageX-f)/g*100)}else null==b&&(b=m?parseFloat(l.val()||0):l[0].selectedIndex),k=(parseFloat(b)-o)/(p-o)*100;if(!isNaN(k)&&(r=k/100*(p-o)+o,s=(r-o)%q,t=r-s,2*Math.abs(s)>=q&&(t+=s>0?q:-q),u=100/((p-o)/q),r=parseFloat(t.toFixed(5)),"undefined"==typeof j&&(j=g/((p-o)/q)),j>1&&m&&(k=(r-o)*u*(1/q)),0>k&&(k=0),k>100&&(k=100),o>r&&(r=o),r>p&&(r=p),this.handle.css("left",k+"%"),this.handle[0].setAttribute("aria-valuenow",m?r:n.eq(r).attr("value")),this.handle[0].setAttribute("aria-valuetext",m?r:n.eq(r).getEncodedText()),this.handle[0].setAttribute("title",m?r:n.eq(r).getEncodedText()),this.valuebg&&this.valuebg.css("width",k+"%"),this._labels&&(v=this.handle.width()/this.slider.width()*100,w=k&&v+(100-v)*k/100,x=100===k?0:Math.min(v+100-w,100),this._labels.each(function(){var b=a(this).hasClass("ui-slider-label-a");a(this).width((b?w:x)+"%")})),!e)){if(y=!1,m?(y=parseFloat(l.val())!==r,l.val(r)):(y=l[0].selectedIndex!==r,l[0].selectedIndex=r),this._trigger("beforechange",b)===!1)return!1;!d&&y&&l.trigger("change")}},_setHighlight:function(a){a=!!a,a?(this.options.highlight=!!a,this.refresh()):this.valuebg&&(this.valuebg.remove(),this.valuebg=!1)},_setTheme:function(a){this.handle.removeClass("ui-btn-"+this.options.theme).addClass("ui-btn-"+a);var b=this.options.theme?this.options.theme:"inherit",c=a?a:"inherit";this.control.removeClass("ui-body-"+b).addClass("ui-body-"+c)},_setTrackTheme:function(a){var b=this.options.trackTheme?this.options.trackTheme:"inherit",c=a?a:"inherit";this.slider.removeClass("ui-body-"+b).addClass("ui-body-"+c)},_setMini:function(a){a=!!a,this.isToggleSwitch||this.isRangeslider||(this.slider.parent().toggleClass("ui-mini",a),this.element.toggleClass("ui-mini",a)),this.slider.toggleClass("ui-mini",a)},_setCorners:function(a){this.slider.toggleClass("ui-corner-all",a),this.isToggleSwitch||this.control.toggleClass("ui-corner-all",a)},_setDisabled:function(a){a=!!a,this.element.prop("disabled",a),this.slider.toggleClass("ui-state-disabled",a).attr("aria-disabled",a),this.element.toggleClass("ui-state-disabled",a)}},a.mobile.behaviors.formReset))}(a),function(a){function b(){return c||(c=a("<div></div>",{"class":"ui-slider-popup ui-shadow ui-corner-all"})),c.clone()}var c;a.widget("mobile.slider",a.mobile.slider,{options:{popupEnabled:!1,showValue:!1},_create:function(){this._super(),a.extend(this,{_currentValue:null,_popup:null,_popupVisible:!1}),this._setOption("popupEnabled",this.options.popupEnabled),this._on(this.handle,{vmousedown:"_showPopup"}),this._on(this.slider.add(this.document),{vmouseup:"_hidePopup"}),this._refresh()},_positionPopup:function(){var a=this.handle.offset();this._popup.offset({left:a.left+(this.handle.width()-this._popup.width())/2,top:a.top-this._popup.outerHeight()-5})},_setOption:function(a,c){this._super(a,c),"showValue"===a?this.handle.html(c&&!this.options.mini?this._value():""):"popupEnabled"===a&&c&&!this._popup&&(this._popup=b().addClass("ui-body-"+(this.options.theme||"a")).hide().insertBefore(this.element))},refresh:function(){this._super.apply(this,arguments),this._refresh()},_refresh:function(){var a,b=this.options;b.popupEnabled&&this.handle.removeAttr("title"),a=this._value(),a!==this._currentValue&&(this._currentValue=a,b.popupEnabled&&this._popup&&(this._positionPopup(),this._popup.html(a)),b.showValue&&!this.options.mini&&this.handle.html(a))},_showPopup:function(){this.options.popupEnabled&&!this._popupVisible&&(this.handle.html(""),this._popup.show(),this._positionPopup(),this._popupVisible=!0)},_hidePopup:function(){var a=this.options;a.popupEnabled&&this._popupVisible&&(a.showValue&&!a.mini&&this.handle.html(this._value()),this._popup.hide(),this._popupVisible=!1)}})}(a),function(a,b){a.widget("mobile.flipswitch",a.extend({options:{onText:"On",offText:"Off",theme:null,enhanced:!1,wrapperClass:null,corners:!0,mini:!1},_create:function(){this.options.enhanced?a.extend(this,{flipswitch:this.element.parent(),on:this.element.find(".ui-flipswitch-on").eq(0),off:this.element.find(".ui-flipswitch-off").eq(0),type:this.element.get(0).tagName}):this._enhance(),this._handleFormReset(),this._originalTabIndex=this.element.attr("tabindex"),null!=this._originalTabIndex&&this.on.attr("tabindex",this._originalTabIndex),this.element.attr("tabindex","-1"),this._on({focus:"_handleInputFocus"}),this.element.is(":disabled")&&this._setOptions({disabled:!0}),this._on(this.flipswitch,{click:"_toggle",swipeleft:"_left",swiperight:"_right"}),this._on(this.on,{keydown:"_keydown"}),this._on({change:"refresh"})},_handleInputFocus:function(){this.on.focus()},widget:function(){return this.flipswitch},_left:function(){this.flipswitch.removeClass("ui-flipswitch-active"),"SELECT"===this.type?this.element.get(0).selectedIndex=0:this.element.prop("checked",!1),this.element.trigger("change")},_right:function(){this.flipswitch.addClass("ui-flipswitch-active"),"SELECT"===this.type?this.element.get(0).selectedIndex=1:this.element.prop("checked",!0),this.element.trigger("change")},_enhance:function(){var b=a("<div>"),c=this.options,d=this.element,e=c.theme?c.theme:"inherit",f=a("<a></a>",{href:"#"}),g=a("<span></span>"),h=d.get(0).tagName,i="INPUT"===h?c.onText:d.find("option").eq(1).text(),j="INPUT"===h?c.offText:d.find("option").eq(0).text();f.addClass("ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit").text(i),g.addClass("ui-flipswitch-off").text(j),b.addClass("ui-flipswitch ui-shadow-inset ui-bar-"+e+" "+(c.wrapperClass?c.wrapperClass:"")+" "+(d.is(":checked")||d.find("option").eq(1).is(":selected")?"ui-flipswitch-active":"")+(d.is(":disabled")?" ui-state-disabled":"")+(c.corners?" ui-corner-all":"")+(c.mini?" ui-mini":"")).append(f,g),d.addClass("ui-flipswitch-input").after(b).appendTo(b),a.extend(this,{flipswitch:b,on:f,off:g,type:h})},_reset:function(){this.refresh()},refresh:function(){var a,b=this.flipswitch.hasClass("ui-flipswitch-active")?"_right":"_left";a="SELECT"===this.type?this.element.get(0).selectedIndex>0?"_right":"_left":this.element.prop("checked")?"_right":"_left",a!==b&&this[a]()},_toggle:function(){var a=this.flipswitch.hasClass("ui-flipswitch-active")?"_left":"_right";this[a]()},_keydown:function(b){b.which===a.mobile.keyCode.LEFT?this._left():b.which===a.mobile.keyCode.RIGHT?this._right():b.which===a.mobile.keyCode.SPACE&&(this._toggle(),b.preventDefault())},_setOptions:function(a){if(a.theme!==b){var c=a.theme?a.theme:"inherit",d=a.theme?a.theme:"inherit";this.widget().removeClass("ui-bar-"+c).addClass("ui-bar-"+d)}a.onText!==b&&this.on.text(a.onText),a.offText!==b&&this.off.text(a.offText),a.disabled!==b&&this.widget().toggleClass("ui-state-disabled",a.disabled),a.mini!==b&&this.widget().toggleClass("ui-mini",a.mini),a.corners!==b&&this.widget().toggleClass("ui-corner-all",a.corners),this._super(a)},_destroy:function(){this.options.enhanced||(null!=this._originalTabIndex?this.element.attr("tabindex",this._originalTabIndex):this.element.removeAttr("tabindex"),this.on.remove(),this.off.remove(),this.element.unwrap(),this.flipswitch.remove(),this.removeClass("ui-flipswitch-input"))}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.rangeslider",a.extend({options:{theme:null,trackTheme:null,corners:!0,mini:!1,highlight:!0},_create:function(){var b=this.element,c=this.options.mini?"ui-rangeslider ui-mini":"ui-rangeslider",d=b.find("input").first(),e=b.find("input").last(),f=b.find("label").first(),g=a.data(d.get(0),"mobile-slider")||a.data(d.slider().get(0),"mobile-slider"),h=a.data(e.get(0),"mobile-slider")||a.data(e.slider().get(0),"mobile-slider"),i=g.slider,j=h.slider,k=g.handle,l=a("<div class='ui-rangeslider-sliders' />").appendTo(b);d.addClass("ui-rangeslider-first"),e.addClass("ui-rangeslider-last"),b.addClass(c),i.appendTo(l),j.appendTo(l),f.insertBefore(b),k.prependTo(j),a.extend(this,{_inputFirst:d,_inputLast:e,_sliderFirst:i,_sliderLast:j,_label:f,_targetVal:null,_sliderTarget:!1,_sliders:l,_proxy:!1}),this.refresh(),this._on(this.element.find("input.ui-slider-input"),{slidebeforestart:"_slidebeforestart",slidestop:"_slidestop",slidedrag:"_slidedrag",slidebeforechange:"_change",blur:"_change",keyup:"_change"}),this._on({mousedown:"_change"}),this._on(this.element.closest("form"),{reset:"_handleReset"}),this._on(k,{vmousedown:"_dragFirstHandle"})},_handleReset:function(){var a=this;setTimeout(function(){a._updateHighlight()},0)},_dragFirstHandle:function(b){return a.data(this._inputFirst.get(0),"mobile-slider").dragging=!0,a.data(this._inputFirst.get(0),"mobile-slider").refresh(b),a.data(this._inputFirst.get(0),"mobile-slider")._trigger("start"),!1},_slidedrag:function(b){var c=a(b.target).is(this._inputFirst),d=c?this._inputLast:this._inputFirst;return this._sliderTarget=!1,"first"===this._proxy&&c||"last"===this._proxy&&!c?(a.data(d.get(0),"mobile-slider").dragging=!0,a.data(d.get(0),"mobile-slider").refresh(b),!1):void 0},_slidestop:function(b){var c=a(b.target).is(this._inputFirst);this._proxy=!1,this.element.find("input").trigger("vmouseup"),this._sliderFirst.css("z-index",c?1:"")},_slidebeforestart:function(b){this._sliderTarget=!1,a(b.originalEvent.target).hasClass("ui-slider-track")&&(this._sliderTarget=!0,this._targetVal=a(b.target).val())},_setOptions:function(a){a.theme!==b&&this._setTheme(a.theme),a.trackTheme!==b&&this._setTrackTheme(a.trackTheme),a.mini!==b&&this._setMini(a.mini),a.highlight!==b&&this._setHighlight(a.highlight),a.disabled!==b&&this._setDisabled(a.disabled),this._super(a),this.refresh()},refresh:function(){var a=this.element,b=this.options;(this._inputFirst.is(":disabled")||this._inputLast.is(":disabled"))&&(this.options.disabled=!0),a.find("input").slider({theme:b.theme,trackTheme:b.trackTheme,disabled:b.disabled,corners:b.corners,mini:b.mini,highlight:b.highlight}).slider("refresh"),this._updateHighlight()},_change:function(b){if("keyup"===b.type)return this._updateHighlight(),!1;var c=this,d=parseFloat(this._inputFirst.val(),10),e=parseFloat(this._inputLast.val(),10),f=a(b.target).hasClass("ui-rangeslider-first"),g=f?this._inputFirst:this._inputLast,h=f?this._inputLast:this._inputFirst;if(this._inputFirst.val()>this._inputLast.val()&&"mousedown"===b.type&&!a(b.target).hasClass("ui-slider-handle"))g.blur();else if("mousedown"===b.type)return;return d>e&&!this._sliderTarget?(g.val(f?e:d).slider("refresh"),this._trigger("normalize")):d>e&&(g.val(this._targetVal).slider("refresh"),setTimeout(function(){h.val(f?d:e).slider("refresh"),a.data(h.get(0),"mobile-slider").handle.focus(),c._sliderFirst.css("z-index",f?"":1),c._trigger("normalize")},0),this._proxy=f?"first":"last"),d===e?(a.data(g.get(0),"mobile-slider").handle.css("z-index",1),a.data(h.get(0),"mobile-slider").handle.css("z-index",0)):(a.data(h.get(0),"mobile-slider").handle.css("z-index",""),a.data(g.get(0),"mobile-slider").handle.css("z-index","")),this._updateHighlight(),d>=e?!1:void 0},_updateHighlight:function(){var b=parseInt(a.data(this._inputFirst.get(0),"mobile-slider").handle.get(0).style.left,10),c=parseInt(a.data(this._inputLast.get(0),"mobile-slider").handle.get(0).style.left,10),d=c-b;this.element.find(".ui-slider-bg").css({"margin-left":b+"%",width:d+"%"})},_setTheme:function(a){this._inputFirst.slider("option","theme",a),this._inputLast.slider("option","theme",a)},_setTrackTheme:function(a){this._inputFirst.slider("option","trackTheme",a),this._inputLast.slider("option","trackTheme",a)},_setMini:function(a){this._inputFirst.slider("option","mini",a),this._inputLast.slider("option","mini",a),this.element.toggleClass("ui-mini",!!a)},_setHighlight:function(a){this._inputFirst.slider("option","highlight",a),this._inputLast.slider("option","highlight",a)},_setDisabled:function(a){this._inputFirst.prop("disabled",a),this._inputLast.prop("disabled",a)},_destroy:function(){this._label.prependTo(this.element),this.element.removeClass("ui-rangeslider ui-mini"),this._inputFirst.after(this._sliderFirst),this._inputLast.after(this._sliderLast),this._sliders.remove(),this.element.find("input").removeClass("ui-rangeslider-first ui-rangeslider-last").slider("destroy")}},a.mobile.behaviors.formReset))}(a),function(a,b){a.widget("mobile.textinput",a.mobile.textinput,{options:{clearBtn:!1,clearBtnText:"Clear text"},_create:function(){this._super(),this.isSearch&&(this.options.clearBtn=!0),this.options.clearBtn&&this.inputNeedsWrap&&this._addClearBtn()},clearButton:function(){return a("<a href='#' tabindex='-1' aria-hidden='true' class='ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all'></a>").attr("title",this.options.clearBtnText).text(this.options.clearBtnText)},_clearBtnClick:function(a){this.element.val("").focus().trigger("change"),this._clearBtn.addClass("ui-input-clear-hidden"),a.preventDefault()},_addClearBtn:function(){this.options.enhanced||this._enhanceClear(),a.extend(this,{_clearBtn:this.widget().find("a.ui-input-clear")}),this._bindClearEvents(),this._toggleClear()},_enhanceClear:function(){this.clearButton().appendTo(this.widget()),this.widget().addClass("ui-input-has-clear")},_bindClearEvents:function(){this._on(this._clearBtn,{click:"_clearBtnClick"}),this._on({keyup:"_toggleClear",change:"_toggleClear",input:"_toggleClear",focus:"_toggleClear",blur:"_toggleClear",cut:"_toggleClear",paste:"_toggleClear"})},_unbindClear:function(){this._off(this._clearBtn,"click"),this._off(this.element,"keyup change input focus blur cut paste")},_setOptions:function(a){this._super(a),a.clearBtn===b||this.element.is("textarea, :jqmData(type='range')")||(a.clearBtn?this._addClearBtn():this._destroyClear()),a.clearBtnText!==b&&this._clearBtn!==b&&this._clearBtn.text(a.clearBtnText).attr("title",a.clearBtnText)},_toggleClear:function(){this._delay("_toggleClearClass",0)},_toggleClearClass:function(){this._clearBtn.toggleClass("ui-input-clear-hidden",!this.element.val())},_destroyClear:function(){this.widget().removeClass("ui-input-has-clear"),this._unbindClear(),this._clearBtn.remove()},_destroy:function(){this._super(),this.options.clearBtn&&this._destroyClear()}})}(a),function(a,b){a.widget("mobile.textinput",a.mobile.textinput,{options:{autogrow:!0,keyupTimeoutBuffer:100},_create:function(){this._super(),this.options.autogrow&&this.isTextarea&&this._autogrow()},_autogrow:function(){this.element.addClass("ui-textinput-autogrow"),this._on({keyup:"_timeout",change:"_timeout",input:"_timeout",paste:"_timeout"}),this._on(!0,this.document,{pageshow:"_handleShow",popupbeforeposition:"_handleShow",updatelayout:"_handleShow",panelopen:"_handleShow"})},_handleShow:function(b){a.contains(b.target,this.element[0])&&this.element.is(":visible")&&("popupbeforeposition"!==b.type&&this.element.addClass("ui-textinput-autogrow-resize").animationComplete(a.proxy(function(){this.element.removeClass("ui-textinput-autogrow-resize")},this),"transition"),this._prepareHeightUpdate())},_unbindAutogrow:function(){this.element.removeClass("ui-textinput-autogrow"),this._off(this.element,"keyup change input paste"),this._off(this.document,"pageshow popupbeforeposition updatelayout panelopen")},keyupTimeout:null,_prepareHeightUpdate:function(a){this.keyupTimeout&&clearTimeout(this.keyupTimeout),a===b?this._updateHeight():this.keyupTimeout=this._delay("_updateHeight",a)},_timeout:function(){this._prepareHeightUpdate(this.options.keyupTimeoutBuffer)},_updateHeight:function(){var a,b,c,d,e,f,g,h,i,j=this.window.scrollTop();this.keyupTimeout=0,"onpage"in this.element[0]||this.element.css({height:0,"min-height":0,"max-height":0}),d=this.element[0].scrollHeight,e=this.element[0].clientHeight,f=parseFloat(this.element.css("border-top-width")),g=parseFloat(this.element.css("border-bottom-width")),h=f+g,i=d+h+15,0===e&&(a=parseFloat(this.element.css("padding-top")),b=parseFloat(this.element.css("padding-bottom")),c=a+b,i+=c),this.element.css({height:i,"min-height":"","max-height":""}),this.window.scrollTop(j)},refresh:function(){this.options.autogrow&&this.isTextarea&&this._updateHeight()},_setOptions:function(a){this._super(a),a.autogrow!==b&&this.isTextarea&&(a.autogrow?this._autogrow():this._unbindAutogrow())}})}(a),function(a){a.widget("mobile.selectmenu",a.extend({initSelector:"select:not( :jqmData(role='slider')):not( :jqmData(role='flipswitch') )",options:{theme:null,icon:"carat-d",iconpos:"right",inline:!1,corners:!0,shadow:!0,iconshadow:!1,overlayTheme:null,dividerTheme:null,hidePlaceholderMenuItems:!0,closeText:"Close",nativeMenu:!0,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,mini:!1},_button:function(){return a("<div/>")},_setDisabled:function(a){return this.element.attr("disabled",a),this.button.attr("aria-disabled",a),this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var b=this.options.inline||this.element.jqmData("inline"),c=this.options.mini||this.element.jqmData("mini"),d="";~this.element[0].className.indexOf("ui-btn-left")&&(d=" ui-btn-left"),~this.element[0].className.indexOf("ui-btn-right")&&(d=" ui-btn-right"),b&&(d+=" ui-btn-inline"),c&&(d+=" ui-mini"),this.select=this.element.removeClass("ui-btn-left ui-btn-right").wrap("<div class='ui-select"+d+"'>"),this.selectId=this.select.attr("id")||"select-"+this.uuid,this.buttonId=this.selectId+"-button",this.label=a("label[for='"+this.selectId+"']"),this.isMultiple=this.select[0].multiple},_destroy:function(){var a=this.element.parents(".ui-select");a.length>0&&(a.is(".ui-btn-left, .ui-btn-right")&&this.element.addClass(a.hasClass("ui-btn-left")?"ui-btn-left":"ui-btn-right"),this.element.insertAfter(a),a.remove())},_create:function(){this._preExtension(),this.button=this._button();var c=this,d=this.options,e=d.icon?d.iconpos||this.select.jqmData("iconpos"):!1,f=this.button.insertBefore(this.select).attr("id",this.buttonId).addClass("ui-btn"+(d.icon?" ui-icon-"+d.icon+" ui-btn-icon-"+e+(d.iconshadow?" ui-shadow-icon":""):"")+(d.theme?" ui-btn-"+d.theme:"")+(d.corners?" ui-corner-all":"")+(d.shadow?" ui-shadow":""));this.setButtonText(),d.nativeMenu&&b.opera&&b.opera.version&&f.addClass("ui-select-nativeonly"),this.isMultiple&&(this.buttonCount=a("<span>").addClass("ui-li-count ui-body-inherit").hide().appendTo(f.addClass("ui-li-has-count"))),(d.disabled||this.element.attr("disabled"))&&this.disable(),this.select.change(function(){c.refresh(),d.nativeMenu&&c._delay(function(){c.select.blur()})}),this._handleFormReset(),this._on(this.button,{keydown:"_handleKeydown"}),this.build()},build:function(){var b=this;this.select.appendTo(b.button).bind("vmousedown",function(){b.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){b.button.addClass(a.mobile.focusClass)}).bind("blur",function(){b.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){b.button.trigger("vmouseover")}).bind("vmousemove",function(){b.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){b.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}),b.button.bind("vmousedown",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.label.bind("click focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.select.bind("focus",function(){b.options.preventFocusZoom&&a.mobile.zoom.disable(!0)}),b.button.bind("mouseup",function(){b.options.preventFocusZoom&&setTimeout(function(){a.mobile.zoom.enable(!0)},0)}),b.select.bind("blur",function(){b.options.preventFocusZoom&&a.mobile.zoom.enable(!0)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var b=this,d=this.selected(),e=this.placeholder,f=a(c.createElement("span"));this.button.children("span").not(".ui-li-count").remove().end().end().prepend(function(){return e=d.length?d.map(function(){return a(this).text()}).get().join(", "):b.placeholder,e?f.text(e):f.html("&#160;"),f.addClass(b.select.attr("class")).addClass(d.attr("class")).removeClass("ui-screen-hidden")}())},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},_handleKeydown:function(){this._delay("_refreshButton")},_reset:function(){this.refresh()},_refreshButton:function(){this.setButtonText(),this.setButtonCount()},refresh:function(){this._refreshButton()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(!0),this.button.addClass("ui-state-disabled")},enable:function(){this._setDisabled(!1),this.button.removeClass("ui-state-disabled")}},a.mobile.behaviors.formReset))}(a),function(a){a.mobile.links=function(b){a(b).find("a").jqmEnhanceable().filter(":jqmData(rel='popup')[href][href!='']").each(function(){var a=this,b=a.getAttribute("href").substring(1);b&&(a.setAttribute("aria-haspopup",!0),a.setAttribute("aria-owns",b),a.setAttribute("aria-expanded",!1))}).end().not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")}}(a),function(a,c){function d(a,b,c,d){var e=d;return e=b>a?c+(a-b)/2:Math.min(Math.max(c,d-b/2),c+a-b)}function e(a){return{x:a.scrollLeft(),y:a.scrollTop(),cx:a[0].innerWidth||a.width(),cy:a[0].innerHeight||a.height()}}a.widget("mobile.popup",{options:{wrapperClass:null,theme:null,overlayTheme:null,shadow:!0,corners:!0,transition:"none",positionTo:"origin",tolerance:null,closeLinkSelector:"a:jqmData(rel='back')",closeLinkEvents:"click.popup",navigateEvents:"navigate.popup",closeEvents:"navigate.popup pagebeforechange.popup",dismissible:!0,enhanced:!1,history:!a.mobile.browser.oldIE},_handleDocumentVmousedown:function(b){this._isOpen&&a.contains(this._ui.container[0],b.target)&&this._ignoreResizeEvents()},_create:function(){var b=this.element,c=b.attr("id"),d=this.options;d.history=d.history&&a.mobile.ajaxEnabled&&a.mobile.hashListeningEnabled,this._on(this.document,{vmousedown:"_handleDocumentVmousedown"}),a.extend(this,{_scrollTop:0,_page:b.closest(".ui-page"),_ui:null,_fallbackTransition:"",_currentTransition:!1,_prerequisites:null,_isOpen:!1,_tolerance:null,_resizeData:null,_ignoreResizeTo:0,_orientationchangeInProgress:!1}),0===this._page.length&&(this._page=a("body")),d.enhanced?this._ui={container:b.parent(),screen:b.parent().prev(),placeholder:a(this.document[0].getElementById(c+"-placeholder"))}:(this._ui=this._enhance(b,c),this._applyTransition(d.transition)),this._setTolerance(d.tolerance)._ui.focusElement=this._ui.container,this._on(this._ui.screen,{vclick:"_eatEventAndClose"}),this._on(this.window,{orientationchange:a.proxy(this,"_handleWindowOrientationchange"),resize:a.proxy(this,"_handleWindowResize"),keyup:a.proxy(this,"_handleWindowKeyUp")}),this._on(this.document,{focusin:"_handleDocumentFocusIn"})},_enhance:function(b,c){var d=this.options,e=d.wrapperClass,f={screen:a("<div class='ui-screen-hidden ui-popup-screen "+this._themeClassFromOption("ui-overlay-",d.overlayTheme)+"'></div>"),placeholder:a("<div style='display: none;'><!-- placeholder --></div>"),container:a("<div class='ui-popup-container ui-popup-hidden ui-popup-truncate"+(e?" "+e:"")+"'></div>")},g=this.document[0].createDocumentFragment();return g.appendChild(f.screen[0]),g.appendChild(f.container[0]),c&&(f.screen.attr("id",c+"-screen"),f.container.attr("id",c+"-popup"),f.placeholder.attr("id",c+"-placeholder").html("<!-- placeholder for "+c+" -->")),this._page[0].appendChild(g),f.placeholder.insertAfter(b),b.detach().addClass("ui-popup "+this._themeClassFromOption("ui-body-",d.theme)+" "+(d.shadow?"ui-overlay-shadow ":"")+(d.corners?"ui-corner-all ":"")).appendTo(f.container),f},_eatEventAndClose:function(a){return a.preventDefault(),a.stopImmediatePropagation(),this.options.dismissible&&this.close(),!1},_resizeScreen:function(){var a=this._ui.screen,b=this._ui.container.outerHeight(!0),c=a.removeAttr("style").height(),d=this.document.height()-1;d>c?a.height(d):b>c&&a.height(b)},_handleWindowKeyUp:function(b){return this._isOpen&&b.keyCode===a.mobile.keyCode.ESCAPE?this._eatEventAndClose(b):void 0},_expectResizeEvent:function(){var a=e(this.window);
+if(this._resizeData){if(a.x===this._resizeData.windowCoordinates.x&&a.y===this._resizeData.windowCoordinates.y&&a.cx===this._resizeData.windowCoordinates.cx&&a.cy===this._resizeData.windowCoordinates.cy)return!1;clearTimeout(this._resizeData.timeoutId)}return this._resizeData={timeoutId:this._delay("_resizeTimeout",200),windowCoordinates:a},!0},_resizeTimeout:function(){this._isOpen?this._expectResizeEvent()||(this._ui.container.hasClass("ui-popup-hidden")&&(this._ui.container.removeClass("ui-popup-hidden ui-popup-truncate"),this.reposition({positionTo:"window"}),this._ignoreResizeEvents()),this._resizeScreen(),this._resizeData=null,this._orientationchangeInProgress=!1):(this._resizeData=null,this._orientationchangeInProgress=!1)},_stopIgnoringResizeEvents:function(){this._ignoreResizeTo=0},_ignoreResizeEvents:function(){this._ignoreResizeTo&&clearTimeout(this._ignoreResizeTo),this._ignoreResizeTo=this._delay("_stopIgnoringResizeEvents",1e3)},_handleWindowResize:function(){this._isOpen&&0===this._ignoreResizeTo&&(!this._expectResizeEvent()&&!this._orientationchangeInProgress||this._ui.container.hasClass("ui-popup-hidden")||this._ui.container.addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style"))},_handleWindowOrientationchange:function(){!this._orientationchangeInProgress&&this._isOpen&&0===this._ignoreResizeTo&&(this._expectResizeEvent(),this._orientationchangeInProgress=!0)},_handleDocumentFocusIn:function(b){var c,d=b.target,e=this._ui;if(this._isOpen){if(d!==e.container[0]){if(c=a(d),!a.contains(e.container[0],d))return a(this.document[0].activeElement).one("focus",a.proxy(function(){this._safelyBlur(d)},this)),e.focusElement.focus(),b.preventDefault(),b.stopImmediatePropagation(),!1;e.focusElement[0]===e.container[0]&&(e.focusElement=c)}this._ignoreResizeEvents()}},_themeClassFromOption:function(a,b){return b?"none"===b?"":a+b:a+"inherit"},_applyTransition:function(b){return b&&(this._ui.container.removeClass(this._fallbackTransition),"none"!==b&&(this._fallbackTransition=a.mobile._maybeDegradeTransition(b),"none"===this._fallbackTransition&&(this._fallbackTransition=""),this._ui.container.addClass(this._fallbackTransition))),this},_setOptions:function(a){var b=this.options,d=this.element,e=this._ui.screen;return a.wrapperClass!==c&&this._ui.container.removeClass(b.wrapperClass).addClass(a.wrapperClass),a.theme!==c&&d.removeClass(this._themeClassFromOption("ui-body-",b.theme)).addClass(this._themeClassFromOption("ui-body-",a.theme)),a.overlayTheme!==c&&(e.removeClass(this._themeClassFromOption("ui-overlay-",b.overlayTheme)).addClass(this._themeClassFromOption("ui-overlay-",a.overlayTheme)),this._isOpen&&e.addClass("in")),a.shadow!==c&&d.toggleClass("ui-overlay-shadow",a.shadow),a.corners!==c&&d.toggleClass("ui-corner-all",a.corners),a.transition!==c&&(this._currentTransition||this._applyTransition(a.transition)),a.tolerance!==c&&this._setTolerance(a.tolerance),a.disabled!==c&&a.disabled&&this.close(),this._super(a)},_setTolerance:function(b){var d,e={t:30,r:15,b:30,l:15};if(b!==c)switch(d=String(b).split(","),a.each(d,function(a,b){d[a]=parseInt(b,10)}),d.length){case 1:isNaN(d[0])||(e.t=e.r=e.b=e.l=d[0]);break;case 2:isNaN(d[0])||(e.t=e.b=d[0]),isNaN(d[1])||(e.l=e.r=d[1]);break;case 4:isNaN(d[0])||(e.t=d[0]),isNaN(d[1])||(e.r=d[1]),isNaN(d[2])||(e.b=d[2]),isNaN(d[3])||(e.l=d[3])}return this._tolerance=e,this},_clampPopupWidth:function(a){var b,c=e(this.window),d={x:this._tolerance.l,y:c.y+this._tolerance.t,cx:c.cx-this._tolerance.l-this._tolerance.r,cy:c.cy-this._tolerance.t-this._tolerance.b};return a||this._ui.container.css("max-width",d.cx),b={cx:this._ui.container.outerWidth(!0),cy:this._ui.container.outerHeight(!0)},{rc:d,menuSize:b}},_calculateFinalLocation:function(a,b){var c,e=b.rc,f=b.menuSize;return c={left:d(e.cx,f.cx,e.x,a.x),top:d(e.cy,f.cy,e.y,a.y)},c.top=Math.max(0,c.top),c.top-=Math.min(c.top,Math.max(0,c.top+f.cy-this.document.height())),c},_placementCoords:function(a){return this._calculateFinalLocation(a,this._clampPopupWidth())},_createPrerequisites:function(b,c,d){var e,f=this;e={screen:a.Deferred(),container:a.Deferred()},e.screen.then(function(){e===f._prerequisites&&b()}),e.container.then(function(){e===f._prerequisites&&c()}),a.when(e.screen,e.container).done(function(){e===f._prerequisites&&(f._prerequisites=null,d())}),f._prerequisites=e},_animate:function(b){return this._ui.screen.removeClass(b.classToRemove).addClass(b.screenClassToAdd),b.prerequisites.screen.resolve(),b.transition&&"none"!==b.transition&&(b.applyTransition&&this._applyTransition(b.transition),this._fallbackTransition)?void this._ui.container.addClass(b.containerClassToAdd).removeClass(b.classToRemove).animationComplete(a.proxy(b.prerequisites.container,"resolve")):(this._ui.container.removeClass(b.classToRemove),void b.prerequisites.container.resolve())},_desiredCoords:function(b){var c,d=null,f=e(this.window),g=b.x,h=b.y,i=b.positionTo;if(i&&"origin"!==i)if("window"===i)g=f.cx/2+f.x,h=f.cy/2+f.y;else{try{d=a(i)}catch(j){d=null}d&&(d.filter(":visible"),0===d.length&&(d=null))}return d&&(c=d.offset(),g=c.left+d.outerWidth()/2,h=c.top+d.outerHeight()/2),("number"!==a.type(g)||isNaN(g))&&(g=f.cx/2+f.x),("number"!==a.type(h)||isNaN(h))&&(h=f.cy/2+f.y),{x:g,y:h}},_reposition:function(a){a={x:a.x,y:a.y,positionTo:a.positionTo},this._trigger("beforeposition",c,a),this._ui.container.offset(this._placementCoords(this._desiredCoords(a)))},reposition:function(a){this._isOpen&&this._reposition(a)},_safelyBlur:function(b){b!==this.window[0]&&"body"!==b.nodeName.toLowerCase()&&a(b).blur()},_openPrerequisitesComplete:function(){var b=this.element.attr("id"),c=this._ui.container.find(":focusable").first();this._ui.container.addClass("ui-popup-active"),this._isOpen=!0,this._resizeScreen(),a.contains(this._ui.container[0],this.document[0].activeElement)||this._safelyBlur(this.document[0].activeElement),c.length>0&&(this._ui.focusElement=c),this._ignoreResizeEvents(),b&&this.document.find("[aria-haspopup='true'][aria-owns='"+b+"']").attr("aria-expanded",!0),this._trigger("afteropen")},_open:function(b){var c=a.extend({},this.options,b),d=function(){var a=navigator.userAgent,b=a.match(/AppleWebKit\/([0-9\.]+)/),c=!!b&&b[1],d=a.match(/Android (\d+(?:\.\d+))/),e=!!d&&d[1],f=a.indexOf("Chrome")>-1;return null!==d&&"4.0"===e&&c&&c>534.13&&!f?!0:!1}();this._createPrerequisites(a.noop,a.noop,a.proxy(this,"_openPrerequisitesComplete")),this._currentTransition=c.transition,this._applyTransition(c.transition),this._ui.screen.removeClass("ui-screen-hidden"),this._ui.container.removeClass("ui-popup-truncate"),this._reposition(c),this._ui.container.removeClass("ui-popup-hidden"),this.options.overlayTheme&&d&&this.element.closest(".ui-page").addClass("ui-popup-open"),this._animate({additionalCondition:!0,transition:c.transition,classToRemove:"",screenClassToAdd:"in",containerClassToAdd:"in",applyTransition:!1,prerequisites:this._prerequisites})},_closePrerequisiteScreen:function(){this._ui.screen.removeClass("out").addClass("ui-screen-hidden")},_closePrerequisiteContainer:function(){this._ui.container.removeClass("reverse out").addClass("ui-popup-hidden ui-popup-truncate").removeAttr("style")},_closePrerequisitesDone:function(){var b=this._ui.container,d=this.element.attr("id");a.mobile.popup.active=c,a(":focus",b[0]).add(b[0]).blur(),d&&this.document.find("[aria-haspopup='true'][aria-owns='"+d+"']").attr("aria-expanded",!1),this._trigger("afterclose")},_close:function(b){this._ui.container.removeClass("ui-popup-active"),this._page.removeClass("ui-popup-open"),this._isOpen=!1,this._createPrerequisites(a.proxy(this,"_closePrerequisiteScreen"),a.proxy(this,"_closePrerequisiteContainer"),a.proxy(this,"_closePrerequisitesDone")),this._animate({additionalCondition:this._ui.screen.hasClass("in"),transition:b?"none":this._currentTransition,classToRemove:"in",screenClassToAdd:"out",containerClassToAdd:"reverse out",applyTransition:!0,prerequisites:this._prerequisites})},_unenhance:function(){this.options.enhanced||(this._setOptions({theme:a.mobile.popup.prototype.options.theme}),this.element.detach().insertAfter(this._ui.placeholder).removeClass("ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit"),this._ui.screen.remove(),this._ui.container.remove(),this._ui.placeholder.remove())},_destroy:function(){return a.mobile.popup.active===this?(this.element.one("popupafterclose",a.proxy(this,"_unenhance")),this.close()):this._unenhance(),this},_closePopup:function(c,d){var e,f,g=this.options,h=!1;c&&c.isDefaultPrevented()||a.mobile.popup.active!==this||(b.scrollTo(0,this._scrollTop),c&&"pagebeforechange"===c.type&&d&&(e="string"==typeof d.toPage?d.toPage:d.toPage.jqmData("url"),e=a.mobile.path.parseUrl(e),f=e.pathname+e.search+e.hash,this._myUrl!==a.mobile.path.makeUrlAbsolute(f)?h=!0:c.preventDefault()),this.window.off(g.closeEvents),this.element.undelegate(g.closeLinkSelector,g.closeLinkEvents),this._close(h))},_bindContainerClose:function(){this.window.on(this.options.closeEvents,a.proxy(this,"_closePopup"))},widget:function(){return this._ui.container},open:function(b){var c,d,e,f,g,h,i=this,j=this.options;return a.mobile.popup.active||j.disabled?this:(a.mobile.popup.active=this,this._scrollTop=this.window.scrollTop(),j.history?(h=a.mobile.navigate.history,d=a.mobile.dialogHashKey,e=a.mobile.activePage,f=e?e.hasClass("ui-dialog"):!1,this._myUrl=c=h.getActive().url,(g=c.indexOf(d)>-1&&!f&&h.activeIndex>0)?(i._open(b),i._bindContainerClose(),this):(-1!==c.indexOf(d)||f?c=a.mobile.path.parseLocation().hash+d:c+=c.indexOf("#")>-1?d:"#"+d,this.window.one("beforenavigate",function(a){a.preventDefault(),i._open(b),i._bindContainerClose()}),this.urlAltered=!0,a.mobile.navigate(c,{role:"dialog"}),this)):(i._open(b),i._bindContainerClose(),i.element.delegate(j.closeLinkSelector,j.closeLinkEvents,function(a){i.close(),a.preventDefault()}),this))},close:function(){return a.mobile.popup.active!==this?this:(this._scrollTop=this.window.scrollTop(),this.options.history&&this.urlAltered?(a.mobile.back(),this.urlAltered=!1):this._closePopup(),this)}}),a.mobile.popup.handleLink=function(b){var c,d=a.mobile.path,e=a(d.hashToSelector(d.parseUrl(b.attr("href")).hash)).first();e.length>0&&e.data("mobile-popup")&&(c=b.offset(),e.popup("open",{x:c.left+b.outerWidth()/2,y:c.top+b.outerHeight()/2,transition:b.jqmData("transition"),positionTo:b.jqmData("position-to")})),setTimeout(function(){b.removeClass(a.mobile.activeBtnClass)},300)},a.mobile.document.on("pagebeforechange",function(b,c){"popup"===c.options.role&&(a.mobile.popup.handleLink(c.options.link),b.preventDefault())})}(a),function(a,b){var d=".ui-disabled,.ui-state-disabled,.ui-li-divider,.ui-screen-hidden,:jqmData(role='placeholder')",e=function(a,b,c){var e=a[c+"All"]().not(d).first();e.length&&(b.blur().attr("tabindex","-1"),e.find("a").first().focus())};a.widget("mobile.selectmenu",a.mobile.selectmenu,{_create:function(){var a=this.options;return a.nativeMenu=a.nativeMenu||this.element.parents(":jqmData(role='popup'),:mobile-popup").length>0,this._super()},_handleSelectFocus:function(){this.element.blur(),this.button.focus()},_handleKeydown:function(a){this._super(a),this._handleButtonVclickKeydown(a)},_handleButtonVclickKeydown:function(b){this.options.disabled||this.isOpen||this.options.nativeMenu||("vclick"===b.type||b.keyCode&&(b.keyCode===a.mobile.keyCode.ENTER||b.keyCode===a.mobile.keyCode.SPACE))&&(this._decideFormat(),"overlay"===this.menuType?this.button.attr("href","#"+this.popupId).attr("data-"+(a.mobile.ns||"")+"rel","popup"):this.button.attr("href","#"+this.dialogId).attr("data-"+(a.mobile.ns||"")+"rel","dialog"),this.isOpen=!0)},_handleListFocus:function(b){var c="focusin"===b.type?{tabindex:"0",event:"vmouseover"}:{tabindex:"-1",event:"vmouseout"};a(b.target).attr("tabindex",c.tabindex).trigger(c.event)},_handleListKeydown:function(b){var c=a(b.target),d=c.closest("li");switch(b.keyCode){case 38:return e(d,c,"prev"),!1;case 40:return e(d,c,"next"),!1;case 13:case 32:return c.trigger("click"),!1}},_handleMenuPageHide:function(){this._delayedTrigger(),this.thisPage.page("bindRemove")},_handleHeaderCloseClick:function(){return"overlay"===this.menuType?(this.close(),!1):void 0},_handleListItemClick:function(b){var c=a(b.target).closest("li"),d=this.select[0].selectedIndex,e=a.mobile.getAttribute(c,"option-index"),f=this._selectOptions().eq(e)[0];f.selected=this.isMultiple?!f.selected:!0,this.isMultiple&&c.find("a").toggleClass("ui-checkbox-on",f.selected).toggleClass("ui-checkbox-off",!f.selected),this.isMultiple||d===e||(this._triggerChange=!0),this.isMultiple?(this.select.trigger("change"),this.list.find("li:not(.ui-li-divider)").eq(e).find("a").first().focus()):this.close(),b.preventDefault()},build:function(){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=this.options;return v.nativeMenu?this._super():(c=this.selectId,d=c+"-listbox",e=c+"-dialog",f=this.label,g=this.element.closest(".ui-page"),h=this.element[0].multiple,i=c+"-menu",j=v.theme?" data-"+a.mobile.ns+"theme='"+v.theme+"'":"",k=v.overlayTheme||v.theme||null,l=k?" data-"+a.mobile.ns+"overlay-theme='"+k+"'":"",m=v.dividerTheme&&h?" data-"+a.mobile.ns+"divider-theme='"+v.dividerTheme+"'":"",n=a("<div data-"+a.mobile.ns+"role='dialog' class='ui-selectmenu' id='"+e+"'"+j+l+"><div data-"+a.mobile.ns+"role='header'><div class='ui-title'></div></div><div data-"+a.mobile.ns+"role='content'></div></div>"),o=a("<div"+j+l+" id='"+d+"' class='ui-selectmenu'></div>").insertAfter(this.select).popup(),p=a("<ul class='ui-selectmenu-list' id='"+i+"' role='listbox' aria-labelledby='"+this.buttonId+"'"+j+m+"></ul>").appendTo(o),q=a("<div class='ui-header ui-bar-"+(v.theme?v.theme:"inherit")+"'></div>").prependTo(o),r=a("<h1 class='ui-title'></h1>").appendTo(q),this.isMultiple&&(u=a("<a>",{role:"button",text:v.closeText,href:"#","class":"ui-btn ui-corner-all ui-btn-left ui-btn-icon-notext ui-icon-delete"}).appendTo(q)),a.extend(this,{selectId:c,menuId:i,popupId:d,dialogId:e,thisPage:g,menuPage:n,label:f,isMultiple:h,theme:v.theme,listbox:o,list:p,header:q,headerTitle:r,headerClose:u,menuPageContent:s,menuPageClose:t,placeholder:""}),this.refresh(),this._origTabIndex===b&&(this._origTabIndex=null===this.select[0].getAttribute("tabindex")?!1:this.select.attr("tabindex")),this.select.attr("tabindex","-1"),this._on(this.select,{focus:"_handleSelectFocus"}),this._on(this.button,{vclick:"_handleButtonVclickKeydown"}),this.list.attr("role","listbox"),this._on(this.list,{focusin:"_handleListFocus",focusout:"_handleListFocus",keydown:"_handleListKeydown","click li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)":"_handleListItemClick"}),this._on(this.menuPage,{pagehide:"_handleMenuPageHide"}),this._on(this.listbox,{popupafterclose:"_popupClosed"}),this.isMultiple&&this._on(this.headerClose,{click:"_handleHeaderCloseClick"}),this)},_popupClosed:function(){this.close(),this._delayedTrigger()},_delayedTrigger:function(){this._triggerChange&&this.element.trigger("change"),this._triggerChange=!1},_isRebuildRequired:function(){var a=this.list.find("li"),b=this._selectOptions().not(".ui-screen-hidden");return b.text()!==a.text()},selected:function(){return this._selectOptions().filter(":selected:not( :jqmData(placeholder='true') )")},refresh:function(b){var c,d;return this.options.nativeMenu?this._super(b):(c=this,(b||this._isRebuildRequired())&&c._buildList(),d=this.selectedIndices(),c.setButtonText(),c.setButtonCount(),void c.list.find("li:not(.ui-li-divider)").find("a").removeClass(a.mobile.activeBtnClass).end().attr("aria-selected",!1).each(function(b){var e=a(this);a.inArray(b,d)>-1?(e.attr("aria-selected",!0),c.isMultiple?e.find("a").removeClass("ui-checkbox-off").addClass("ui-checkbox-on"):e.hasClass("ui-screen-hidden")?e.next().find("a").addClass(a.mobile.activeBtnClass):e.find("a").addClass(a.mobile.activeBtnClass)):c.isMultiple&&e.find("a").removeClass("ui-checkbox-on").addClass("ui-checkbox-off")}))},close:function(){if(!this.options.disabled&&this.isOpen){var a=this;"page"===a.menuType?(a.menuPage.dialog("close"),a.list.appendTo(a.listbox)):a.listbox.popup("close"),a._focusButton(),a.isOpen=!1}},open:function(){this.button.click()},_focusMenuItem:function(){var b=this.list.find("a."+a.mobile.activeBtnClass);0===b.length&&(b=this.list.find("li:not("+d+") a.ui-btn")),b.first().focus()},_decideFormat:function(){var b=this,c=this.window,d=b.list.parent(),e=d.outerHeight(),f=c.scrollTop(),g=b.button.offset().top,h=c.height();e>h-80||!a.support.scrollTop?(b.menuPage.appendTo(a.mobile.pageContainer).page(),b.menuPageContent=b.menuPage.find(".ui-content"),b.menuPageClose=b.menuPage.find(".ui-header a"),b.thisPage.unbind("pagehide.remove"),0===f&&g>h&&b.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",g)}),b.menuPage.one({pageshow:a.proxy(this,"_focusMenuItem"),pagehide:a.proxy(this,"close")}),b.menuType="page",b.menuPageContent.append(b.list),b.menuPage.find("div .ui-title").text(b.label.getEncodedText()||b.placeholder)):(b.menuType="overlay",b.listbox.one({popupafteropen:a.proxy(this,"_focusMenuItem")}))},_buildList:function(){var b,d,e,f,g,h,i,j,k,l,m,n,o,p,q=this,r=this.options,s=this.placeholder,t=!0,u="false",v="data-"+a.mobile.ns,w=v+"option-index",x=v+"icon",y=v+"role",z=v+"placeholder",A=c.createDocumentFragment(),B=!1;for(q.list.empty().filter(".ui-listview").listview("destroy"),b=this._selectOptions(),d=b.length,e=this.select[0],g=0;d>g;g++,B=!1)h=b[g],i=a(h),i.hasClass("ui-screen-hidden")||(j=h.parentNode,m=[],k=i.text(),l=c.createElement("a"),l.setAttribute("href","#"),l.appendChild(c.createTextNode(k)),j!==e&&"optgroup"===j.nodeName.toLowerCase()&&(n=j.getAttribute("label"),n!==f&&(o=c.createElement("li"),o.setAttribute(y,"list-divider"),o.setAttribute("role","option"),o.setAttribute("tabindex","-1"),o.appendChild(c.createTextNode(n)),A.appendChild(o),f=n)),!t||h.getAttribute("value")&&0!==k.length&&!i.jqmData("placeholder")||(t=!1,B=!0,null===h.getAttribute(z)&&(this._removePlaceholderAttr=!0),h.setAttribute(z,!0),r.hidePlaceholderMenuItems&&m.push("ui-screen-hidden"),s!==k&&(s=q.placeholder=k)),p=c.createElement("li"),h.disabled&&(m.push("ui-state-disabled"),p.setAttribute("aria-disabled",!0)),p.setAttribute(w,g),p.setAttribute(x,u),B&&p.setAttribute(z,!0),p.className=m.join(" "),p.setAttribute("role","option"),l.setAttribute("tabindex","-1"),this.isMultiple&&a(l).addClass("ui-btn ui-checkbox-off ui-btn-icon-right"),p.appendChild(l),A.appendChild(p));q.list[0].appendChild(A),this.isMultiple||s.length?this.headerTitle.text(this.placeholder):this.header.addClass("ui-screen-hidden"),q.list.listview()},_button:function(){return this.options.nativeMenu?this._super():a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})},_destroy:function(){this.options.nativeMenu||(this.close(),this._origTabIndex!==b&&(this._origTabIndex!==!1?this.select.attr("tabindex",this._origTabIndex):this.select.removeAttr("tabindex")),this._removePlaceholderAttr&&this._selectOptions().removeAttr("data-"+a.mobile.ns+"placeholder"),this.listbox.remove(),this.menuPage.remove()),this._super()}})}(a),function(a,b){function c(a,b){var c=b?b:[];return c.push("ui-btn"),a.theme&&c.push("ui-btn-"+a.theme),a.icon&&(c=c.concat(["ui-icon-"+a.icon,"ui-btn-icon-"+a.iconpos]),a.iconshadow&&c.push("ui-shadow-icon")),a.inline&&c.push("ui-btn-inline"),a.shadow&&c.push("ui-shadow"),a.corners&&c.push("ui-corner-all"),a.mini&&c.push("ui-mini"),c}function d(a){var c,d,e,g=!1,h=!0,i={icon:"",inline:!1,shadow:!1,corners:!1,iconshadow:!1,mini:!1},j=[];for(a=a.split(" "),c=0;c<a.length;c++)e=!0,d=f[a[c]],d!==b?(e=!1,i[d]=!0):0===a[c].indexOf("ui-btn-icon-")?(e=!1,h=!1,i.iconpos=a[c].substring(12)):0===a[c].indexOf("ui-icon-")?(e=!1,i.icon=a[c].substring(8)):0===a[c].indexOf("ui-btn-")&&8===a[c].length?(e=!1,i.theme=a[c].substring(7)):"ui-btn"===a[c]&&(e=!1,g=!0),e&&j.push(a[c]);return h&&(i.icon=""),{options:i,unknownClasses:j,alreadyEnhanced:g}}function e(a){return"-"+a.toLowerCase()}var f={"ui-shadow":"shadow","ui-corner-all":"corners","ui-btn-inline":"inline","ui-shadow-icon":"iconshadow","ui-mini":"mini"},g=function(){var c=a.mobile.getAttribute.apply(this,arguments);return null==c?b:c},h=/[A-Z]/g;a.fn.buttonMarkup=function(f,i){var j,k,l,m,n,o=a.fn.buttonMarkup.defaults;for(j=0;j<this.length;j++){if(l=this[j],k=i?{alreadyEnhanced:!1,unknownClasses:[]}:d(l.className),m=a.extend({},k.alreadyEnhanced?k.options:{},f),!k.alreadyEnhanced)for(n in o)m[n]===b&&(m[n]=g(l,n.replace(h,e)));l.className=c(a.extend({},o,m),k.unknownClasses).join(" "),"button"!==l.tagName.toLowerCase()&&l.setAttribute("role","button")}return this},a.fn.buttonMarkup.defaults={icon:"",iconpos:"left",theme:null,inline:!1,shadow:!0,corners:!0,iconshadow:!1,mini:!1},a.extend(a.fn.buttonMarkup,{initSelector:"a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button:not(:jqmData(role='navbar') button)"})}(a),function(a,b){a.widget("mobile.controlgroup",a.extend({options:{enhanced:!1,theme:null,shadow:!1,corners:!0,excludeInvisible:!0,type:"vertical",mini:!1},_create:function(){var b=this.element,c=this.options,d=a.mobile.page.prototype.keepNativeSelector();a.fn.buttonMarkup&&this.element.find(a.fn.buttonMarkup.initSelector).not(d).buttonMarkup(),a.each(this._childWidgets,a.proxy(function(b,c){a.mobile[c]&&this.element.find(a.mobile[c].initSelector).not(d)[c]()},this)),a.extend(this,{_ui:null,_initialRefresh:!0}),this._ui=c.enhanced?{groupLegend:b.children(".ui-controlgroup-label").children(),childWrapper:b.children(".ui-controlgroup-controls")}:this._enhance()},_childWidgets:["checkboxradio","selectmenu","button"],_themeClassFromOption:function(a){return a?"none"===a?"":"ui-group-theme-"+a:""},_enhance:function(){var b=this.element,c=this.options,d={groupLegend:b.children("legend"),childWrapper:b.addClass("ui-controlgroup ui-controlgroup-"+("horizontal"===c.type?"horizontal":"vertical")+" "+this._themeClassFromOption(c.theme)+" "+(c.corners?"ui-corner-all ":"")+(c.mini?"ui-mini ":"")).wrapInner("<div class='ui-controlgroup-controls "+(c.shadow===!0?"ui-shadow":"")+"'></div>").children()};return d.groupLegend.length>0&&a("<div role='heading' class='ui-controlgroup-label'></div>").append(d.groupLegend).prependTo(b),d},_init:function(){this.refresh()},_setOptions:function(a){var c,d,e=this.element;return a.type!==b&&(e.removeClass("ui-controlgroup-horizontal ui-controlgroup-vertical").addClass("ui-controlgroup-"+("horizontal"===a.type?"horizontal":"vertical")),c=!0),a.theme!==b&&e.removeClass(this._themeClassFromOption(this.options.theme)).addClass(this._themeClassFromOption(a.theme)),a.corners!==b&&e.toggleClass("ui-corner-all",a.corners),a.mini!==b&&e.toggleClass("ui-mini",a.mini),a.shadow!==b&&this._ui.childWrapper.toggleClass("ui-shadow",a.shadow),a.excludeInvisible!==b&&(this.options.excludeInvisible=a.excludeInvisible,c=!0),d=this._super(a),c&&this.refresh(),d},container:function(){return this._ui.childWrapper},refresh:function(){var b=this.container(),c=b.find(".ui-btn").not(".ui-slider-handle"),d=this._initialRefresh;a.mobile.checkboxradio&&b.find(":mobile-checkboxradio").checkboxradio("refresh"),this._addFirstLastClasses(c,this.options.excludeInvisible?this._getVisibles(c,d):c,d),this._initialRefresh=!1},_destroy:function(){var a,b,c=this.options;return c.enhanced?this:(a=this._ui,b=this.element.removeClass("ui-controlgroup ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini "+this._themeClassFromOption(c.theme)).find(".ui-btn").not(".ui-slider-handle"),this._removeFirstLastClasses(b),a.groupLegend.unwrap(),void a.childWrapper.children().unwrap())}},a.mobile.behaviors.addFirstLastClasses))}(a),function(a,b){a.widget("mobile.toolbar",{initSelector:":jqmData(role='footer'), :jqmData(role='header')",options:{theme:null,addBackBtn:!1,backBtnTheme:null,backBtnText:"Back"},_create:function(){var b,c,d=this.element.is(":jqmData(role='header')")?"header":"footer",e=this.element.closest(".ui-page");0===e.length&&(e=!1,this._on(this.document,{pageshow:"refresh"})),a.extend(this,{role:d,page:e,leftbtn:b,rightbtn:c}),this.element.attr("role","header"===d?"banner":"contentinfo").addClass("ui-"+d),this.refresh(),this._setOptions(this.options)},_setOptions:function(a){if(a.addBackBtn!==b&&this._updateBackButton(),null!=a.backBtnTheme&&this.element.find(".ui-toolbar-back-btn").addClass("ui-btn ui-btn-"+a.backBtnTheme),a.backBtnText!==b&&this.element.find(".ui-toolbar-back-btn .ui-btn-text").text(a.backBtnText),a.theme!==b){var c=this.options.theme?this.options.theme:"inherit",d=a.theme?a.theme:"inherit";this.element.removeClass("ui-bar-"+c).addClass("ui-bar-"+d)}this._super(a)},refresh:function(){"header"===this.role&&this._addHeaderButtonClasses(),this.page||(this._setRelative(),"footer"===this.role?this.element.appendTo("body"):"header"===this.role&&this._updateBackButton()),this._addHeadingClasses(),this._btnMarkup()},_setRelative:function(){a("[data-"+a.mobile.ns+"role='page']").css({position:"relative"})},_btnMarkup:function(){this.element.children("a").filter(":not([data-"+a.mobile.ns+"role='none'])").attr("data-"+a.mobile.ns+"role","button"),this.element.trigger("create")},_addHeaderButtonClasses:function(){var a=this.element.children("a, button");this.leftbtn=a.hasClass("ui-btn-left")&&!a.hasClass("ui-toolbar-back-btn"),this.rightbtn=a.hasClass("ui-btn-right"),this.leftbtn=this.leftbtn||a.eq(0).not(".ui-btn-right,.ui-toolbar-back-btn").addClass("ui-btn-left").length,this.rightbtn=this.rightbtn||a.eq(1).addClass("ui-btn-right").length},_updateBackButton:function(){var b,c=this.options,d=c.backBtnTheme||c.theme;b=this._backButton=this._backButton||{},this.options.addBackBtn&&"header"===this.role&&a(".ui-page").length>1&&(this.page?this.page[0].getAttribute("data-"+a.mobile.ns+"url")!==a.mobile.path.stripHash(location.hash):a.mobile.navigate&&a.mobile.navigate.history&&a.mobile.navigate.history.activeIndex>0)&&!this.leftbtn?b.attached||(this.backButton=b.element=(b.element||a("<a role='button' href='javascript:void(0);' class='ui-btn ui-corner-all ui-shadow ui-btn-left "+(d?"ui-btn-"+d+" ":"")+"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' data-"+a.mobile.ns+"rel='back'>"+c.backBtnText+"</a>")).prependTo(this.element),b.attached=!0):b.element&&(b.element.detach(),b.attached=!1)},_addHeadingClasses:function(){this.element.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({role:"heading","aria-level":"1"})},_destroy:function(){var a;this.element.children("h1, h2, h3, h4, h5, h6").removeClass("ui-title").removeAttr("role").removeAttr("aria-level"),"header"===this.role&&(this.element.children("a, button").removeClass("ui-btn-left ui-btn-right ui-btn ui-shadow ui-corner-all"),this.backButton&&this.backButton.remove()),a=this.options.theme?this.options.theme:"inherit",this.element.removeClass("ui-bar-"+a),this.element.removeClass("ui-"+this.role).removeAttr("role")}})}(a),function(a,b){a.widget("mobile.toolbar",a.mobile.toolbar,{options:{position:null,visibleOnPageShow:!0,disablePageZoom:!0,transition:"slide",fullscreen:!1,tapToggle:!0,tapToggleBlacklist:"a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open",hideDuringFocus:"input, textarea, select",updatePagePadding:!0,trackPersistentToolbars:!0,supportBlacklist:function(){return!a.support.fixedPosition}},_create:function(){this._super(),this.pagecontainer=a(":mobile-pagecontainer"),"fixed"!==this.options.position||this.options.supportBlacklist()||this._makeFixed()},_makeFixed:function(){this.element.addClass("ui-"+this.role+"-fixed"),this.updatePagePadding(),this._addTransitionClass(),this._bindPageEvents(),this._bindToggleHandlers()},_setOptions:function(c){if("fixed"===c.position&&"fixed"!==this.options.position&&this._makeFixed(),"fixed"===this.options.position&&!this.options.supportBlacklist()){var d=this.page?this.page:a(".ui-page-active").length>0?a(".ui-page-active"):a(".ui-page").eq(0);c.fullscreen!==b&&(c.fullscreen?(this.element.addClass("ui-"+this.role+"-fullscreen"),d.addClass("ui-page-"+this.role+"-fullscreen")):(this.element.removeClass("ui-"+this.role+"-fullscreen"),d.removeClass("ui-page-"+this.role+"-fullscreen").addClass("ui-page-"+this.role+"-fixed")))}this._super(c)},_addTransitionClass:function(){var a=this.options.transition;a&&"none"!==a&&("slide"===a&&(a=this.element.hasClass("ui-header")?"slidedown":"slideup"),this.element.addClass(a))},_bindPageEvents:function(){var a=this.page?this.element.closest(".ui-page"):this.document;this._on(a,{pagebeforeshow:"_handlePageBeforeShow",webkitAnimationStart:"_handleAnimationStart",animationstart:"_handleAnimationStart",updatelayout:"_handleAnimationStart",pageshow:"_handlePageShow",pagebeforehide:"_handlePageBeforeHide"})},_handlePageBeforeShow:function(){var b=this.options;b.disablePageZoom&&a.mobile.zoom.disable(!0),b.visibleOnPageShow||this.hide(!0)},_handleAnimationStart:function(){this.options.updatePagePadding&&this.updatePagePadding(this.page?this.page:".ui-page-active")},_handlePageShow:function(){this.updatePagePadding(this.page?this.page:".ui-page-active"),this.options.updatePagePadding&&this._on(this.window,{throttledresize:"updatePagePadding"})},_handlePageBeforeHide:function(b,c){var d,e,f,g,h=this.options;h.disablePageZoom&&a.mobile.zoom.enable(!0),h.updatePagePadding&&this._off(this.window,"throttledresize"),h.trackPersistentToolbars&&(d=a(".ui-footer-fixed:jqmData(id)",this.page),e=a(".ui-header-fixed:jqmData(id)",this.page),f=d.length&&c.nextPage&&a(".ui-footer-fixed:jqmData(id='"+d.jqmData("id")+"')",c.nextPage)||a(),g=e.length&&c.nextPage&&a(".ui-header-fixed:jqmData(id='"+e.jqmData("id")+"')",c.nextPage)||a(),(f.length||g.length)&&(f.add(g).appendTo(a.mobile.pageContainer),c.nextPage.one("pageshow",function(){g.prependTo(this),f.appendTo(this)})))},_visible:!0,updatePagePadding:function(c){var d=this.element,e="header"===this.role,f=parseFloat(d.css(e?"top":"bottom"));this.options.fullscreen||(c=c&&c.type===b&&c||this.page||d.closest(".ui-page"),c=this.page?this.page:".ui-page-active",a(c).css("padding-"+(e?"top":"bottom"),d.outerHeight()+f))},_useTransition:function(b){var c=this.window,d=this.element,e=c.scrollTop(),f=d.height(),g=this.page?d.closest(".ui-page").height():a(".ui-page-active").height(),h=a.mobile.getScreenHeight();return!b&&(this.options.transition&&"none"!==this.options.transition&&("header"===this.role&&!this.options.fullscreen&&e>f||"footer"===this.role&&!this.options.fullscreen&&g-f>e+h)||this.options.fullscreen)},show:function(a){var b="ui-fixed-hidden",c=this.element;this._useTransition(a)?c.removeClass("out "+b).addClass("in").animationComplete(function(){c.removeClass("in")}):c.removeClass(b),this._visible=!0},hide:function(a){var b="ui-fixed-hidden",c=this.element,d="out"+("slide"===this.options.transition?" reverse":"");this._useTransition(a)?c.addClass(d).removeClass("in").animationComplete(function(){c.addClass(b).removeClass(d)}):c.addClass(b).removeClass(d),this._visible=!1},toggle:function(){this[this._visible?"hide":"show"]()},_bindToggleHandlers:function(){var b,c,d=this,e=d.options,f=!0,g=this.page?this.page:a(".ui-page");g.bind("vclick",function(b){e.tapToggle&&!a(b.target).closest(e.tapToggleBlacklist).length&&d.toggle()}).bind("focusin focusout",function(g){screen.width<1025&&a(g.target).is(e.hideDuringFocus)&&!a(g.target).closest(".ui-header-fixed, .ui-footer-fixed").length&&("focusout"!==g.type||f?"focusin"===g.type&&f&&(clearTimeout(b),f=!1,c=setTimeout(function(){d.hide()},0)):(f=!0,clearTimeout(c),b=setTimeout(function(){d.show()},0)))})},_setRelative:function(){"fixed"!==this.options.position&&a("[data-"+a.mobile.ns+"role='page']").css({position:"relative"})},_destroy:function(){var b,c,d,e,f,g=this.pagecontainer.pagecontainer("getActivePage");this._super(),"fixed"===this.options.position&&(d=a("body>.ui-"+this.role+"-fixed").add(g.find(".ui-"+this.options.role+"-fixed")).not(this.element).length>0,f=a("body>.ui-"+this.role+"-fixed").add(g.find(".ui-"+this.options.role+"-fullscreen")).not(this.element).length>0,c="ui-header-fixed ui-footer-fixed ui-header-fullscreen in out ui-footer-fullscreen fade slidedown slideup ui-fixed-hidden",this.element.removeClass(c),f||(b="ui-page-"+this.role+"-fullscreen"),d||(e="header"===this.role,b+=" ui-page-"+this.role+"-fixed",g.css("padding-"+(e?"top":"bottom"),"")),g.removeClass(b))
+}})}(a),function(a){a.widget("mobile.toolbar",a.mobile.toolbar,{_makeFixed:function(){this._super(),this._workarounds()},_workarounds:function(){var a=navigator.userAgent,b=navigator.platform,c=a.match(/AppleWebKit\/([0-9]+)/),d=!!c&&c[1],e=null,f=this;if(b.indexOf("iPhone")>-1||b.indexOf("iPad")>-1||b.indexOf("iPod")>-1)e="ios";else{if(!(a.indexOf("Android")>-1))return;e="android"}if("ios"===e)f._bindScrollWorkaround();else{if(!("android"===e&&d&&534>d))return;f._bindScrollWorkaround(),f._bindListThumbWorkaround()}},_viewportOffset:function(){var a=this.element,b=a.hasClass("ui-header"),c=Math.abs(a.offset().top-this.window.scrollTop());return b||(c=Math.round(c-this.window.height()+a.outerHeight())-60),c},_bindScrollWorkaround:function(){var a=this;this._on(this.window,{scrollstop:function(){var b=a._viewportOffset();b>2&&a._visible&&a._triggerRedraw()}})},_bindListThumbWorkaround:function(){this.element.closest(".ui-page").addClass("ui-android-2x-fixed")},_triggerRedraw:function(){var b=parseFloat(a(".ui-page-active").css("padding-bottom"));a(".ui-page-active").css("padding-bottom",b+1+"px"),setTimeout(function(){a(".ui-page-active").css("padding-bottom",b+"px")},0)},destroy:function(){this._super(),this.element.closest(".ui-page-active").removeClass("ui-android-2x-fix")}})}(a),function(a,b){function c(){var a=e.clone(),b=a.eq(0),c=a.eq(1),d=c.children();return{arEls:c.add(b),gd:b,ct:c,ar:d}}var d=a.mobile.browser.oldIE&&a.mobile.browser.oldIE<=8,e=a("<div class='ui-popup-arrow-guide'></div><div class='ui-popup-arrow-container"+(d?" ie":"")+"'><div class='ui-popup-arrow'></div></div>");a.widget("mobile.popup",a.mobile.popup,{options:{arrow:""},_create:function(){var a,b=this._super();return this.options.arrow&&(this._ui.arrow=a=this._addArrow()),b},_addArrow:function(){var a,b=this.options,d=c();return a=this._themeClassFromOption("ui-body-",b.theme),d.ar.addClass(a+(b.shadow?" ui-overlay-shadow":"")),d.arEls.hide().appendTo(this.element),d},_unenhance:function(){var a=this._ui.arrow;return a&&a.arEls.remove(),this._super()},_tryAnArrow:function(a,b,c,d,e){var f,g,h,i={},j={};return d.arFull[a.dimKey]>d.guideDims[a.dimKey]?e:(i[a.fst]=c[a.fst]+(d.arHalf[a.oDimKey]+d.menuHalf[a.oDimKey])*a.offsetFactor-d.contentBox[a.fst]+(d.clampInfo.menuSize[a.oDimKey]-d.contentBox[a.oDimKey])*a.arrowOffsetFactor,i[a.snd]=c[a.snd],f=d.result||this._calculateFinalLocation(i,d.clampInfo),g={x:f.left,y:f.top},j[a.fst]=g[a.fst]+d.contentBox[a.fst]+a.tipOffset,j[a.snd]=Math.max(f[a.prop]+d.guideOffset[a.prop]+d.arHalf[a.dimKey],Math.min(f[a.prop]+d.guideOffset[a.prop]+d.guideDims[a.dimKey]-d.arHalf[a.dimKey],c[a.snd])),h=Math.abs(c.x-j.x)+Math.abs(c.y-j.y),(!e||h<e.diff)&&(j[a.snd]-=d.arHalf[a.dimKey]+f[a.prop]+d.contentBox[a.snd],e={dir:b,diff:h,result:f,posProp:a.prop,posVal:j[a.snd]}),e)},_getPlacementState:function(a){var b,c,d=this._ui.arrow,e={clampInfo:this._clampPopupWidth(!a),arFull:{cx:d.ct.width(),cy:d.ct.height()},guideDims:{cx:d.gd.width(),cy:d.gd.height()},guideOffset:d.gd.offset()};return b=this.element.offset(),d.gd.css({left:0,top:0,right:0,bottom:0}),c=d.gd.offset(),e.contentBox={x:c.left-b.left,y:c.top-b.top,cx:d.gd.width(),cy:d.gd.height()},d.gd.removeAttr("style"),e.guideOffset={left:e.guideOffset.left-b.left,top:e.guideOffset.top-b.top},e.arHalf={cx:e.arFull.cx/2,cy:e.arFull.cy/2},e.menuHalf={cx:e.clampInfo.menuSize.cx/2,cy:e.clampInfo.menuSize.cy/2},e},_placementCoords:function(b){var c,e,f,g,h,i=this.options.arrow,j=this._ui.arrow;return j?(j.arEls.show(),h={},c=this._getPlacementState(!0),f={l:{fst:"x",snd:"y",prop:"top",dimKey:"cy",oDimKey:"cx",offsetFactor:1,tipOffset:-c.arHalf.cx,arrowOffsetFactor:0},r:{fst:"x",snd:"y",prop:"top",dimKey:"cy",oDimKey:"cx",offsetFactor:-1,tipOffset:c.arHalf.cx+c.contentBox.cx,arrowOffsetFactor:1},b:{fst:"y",snd:"x",prop:"left",dimKey:"cx",oDimKey:"cy",offsetFactor:-1,tipOffset:c.arHalf.cy+c.contentBox.cy,arrowOffsetFactor:1},t:{fst:"y",snd:"x",prop:"left",dimKey:"cx",oDimKey:"cy",offsetFactor:1,tipOffset:-c.arHalf.cy,arrowOffsetFactor:0}},a.each((i===!0?"l,t,r,b":i).split(","),a.proxy(function(a,d){e=this._tryAnArrow(f[d],d,b,c,e)},this)),e?(j.ct.removeClass("ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b").addClass("ui-popup-arrow-"+e.dir).removeAttr("style").css(e.posProp,e.posVal).show(),d||(g=this.element.offset(),h[f[e.dir].fst]=j.ct.offset(),h[f[e.dir].snd]={left:g.left+c.contentBox.x,top:g.top+c.contentBox.y}),e.result):(j.arEls.hide(),this._super(b))):this._super(b)},_setOptions:function(a){var c,d=this.options.theme,e=this._ui.arrow,f=this._super(a);if(a.arrow!==b){if(!e&&a.arrow)return void(this._ui.arrow=this._addArrow());e&&!a.arrow&&(e.arEls.remove(),this._ui.arrow=null)}return e=this._ui.arrow,e&&(a.theme!==b&&(d=this._themeClassFromOption("ui-body-",d),c=this._themeClassFromOption("ui-body-",a.theme),e.ar.removeClass(d).addClass(c)),a.shadow!==b&&e.ar.toggleClass("ui-overlay-shadow",a.shadow)),f},_destroy:function(){var a=this._ui.arrow;return a&&a.arEls.remove(),this._super()}})}(a),function(a,c){a.widget("mobile.panel",{options:{classes:{panel:"ui-panel",panelOpen:"ui-panel-open",panelClosed:"ui-panel-closed",panelFixed:"ui-panel-fixed",panelInner:"ui-panel-inner",modal:"ui-panel-dismiss",modalOpen:"ui-panel-dismiss-open",pageContainer:"ui-panel-page-container",pageWrapper:"ui-panel-wrapper",pageFixedToolbar:"ui-panel-fixed-toolbar",pageContentPrefix:"ui-panel-page-content",animate:"ui-panel-animate"},animate:!0,theme:null,position:"left",dismissible:!0,display:"reveal",swipeClose:!0,positionFixed:!1},_closeLink:null,_parentPage:null,_page:null,_modal:null,_panelInner:null,_wrapper:null,_fixedToolbars:null,_create:function(){var b=this.element,c=b.closest(".ui-page, :jqmData(role='page')");a.extend(this,{_closeLink:b.find(":jqmData(rel='close')"),_parentPage:c.length>0?c:!1,_openedPage:null,_page:this._getPage,_panelInner:this._getPanelInner(),_fixedToolbars:this._getFixedToolbars}),"overlay"!==this.options.display&&this._getWrapper(),this._addPanelClasses(),a.support.cssTransform3d&&this.options.animate&&this.element.addClass(this.options.classes.animate),this._bindUpdateLayout(),this._bindCloseEvents(),this._bindLinkListeners(),this._bindPageEvents(),this.options.dismissible&&this._createModal(),this._bindSwipeEvents()},_getPanelInner:function(){var a=this.element.find("."+this.options.classes.panelInner);return 0===a.length&&(a=this.element.children().wrapAll("<div class='"+this.options.classes.panelInner+"' />").parent()),a},_createModal:function(){var b=this,c=b._parentPage?b._parentPage.parent():b.element.parent();b._modal=a("<div class='"+b.options.classes.modal+"'></div>").on("mousedown",function(){b.close()}).appendTo(c)},_getPage:function(){var b=this._openedPage||this._parentPage||a("."+a.mobile.activePageClass);return b},_getWrapper:function(){var a=this._page().find("."+this.options.classes.pageWrapper);0===a.length&&(a=this._page().children(".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)").wrapAll("<div class='"+this.options.classes.pageWrapper+"'></div>").parent()),this._wrapper=a},_getFixedToolbars:function(){var b=a("body").children(".ui-header-fixed, .ui-footer-fixed"),c=this._page().find(".ui-header-fixed, .ui-footer-fixed"),d=b.add(c).addClass(this.options.classes.pageFixedToolbar);return d},_getPosDisplayClasses:function(a){return a+"-position-"+this.options.position+" "+a+"-display-"+this.options.display},_getPanelClasses:function(){var a=this.options.classes.panel+" "+this._getPosDisplayClasses(this.options.classes.panel)+" "+this.options.classes.panelClosed+" ui-body-"+(this.options.theme?this.options.theme:"inherit");return this.options.positionFixed&&(a+=" "+this.options.classes.panelFixed),a},_addPanelClasses:function(){this.element.addClass(this._getPanelClasses())},_handleCloseClick:function(a){a.isDefaultPrevented()||this.close()},_bindCloseEvents:function(){this._on(this._closeLink,{click:"_handleCloseClick"}),this._on({"click a:jqmData(ajax='false')":"_handleCloseClick"})},_positionPanel:function(b){var c=this,d=c._panelInner.outerHeight(),e=d>a.mobile.getScreenHeight();e||!c.options.positionFixed?(e&&(c._unfixPanel(),a.mobile.resetActivePageHeight(d)),b&&this.window[0].scrollTo(0,a.mobile.defaultHomeScroll)):c._fixPanel()},_bindFixListener:function(){this._on(a(b),{throttledresize:"_positionPanel"})},_unbindFixListener:function(){this._off(a(b),"throttledresize")},_unfixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.removeClass(this.options.classes.panelFixed)},_fixPanel:function(){this.options.positionFixed&&a.support.fixedPosition&&this.element.addClass(this.options.classes.panelFixed)},_bindUpdateLayout:function(){var a=this;a.element.on("updatelayout",function(){a._open&&a._positionPanel()})},_bindLinkListeners:function(){this._on("body",{"click a":"_handleClick"})},_handleClick:function(b){var d,e=this.element.attr("id");b.currentTarget.href.split("#")[1]===e&&e!==c&&(b.preventDefault(),d=a(b.target),d.hasClass("ui-btn")&&(d.addClass(a.mobile.activeBtnClass),this.element.one("panelopen panelclose",function(){d.removeClass(a.mobile.activeBtnClass)})),this.toggle())},_bindSwipeEvents:function(){var a=this,b=a._modal?a.element.add(a._modal):a.element;a.options.swipeClose&&("left"===a.options.position?b.on("swipeleft.panel",function(){a.close()}):b.on("swiperight.panel",function(){a.close()}))},_bindPageEvents:function(){var a=this;this.document.on("panelbeforeopen",function(b){a._open&&b.target!==a.element[0]&&a.close()}).on("keyup.panel",function(b){27===b.keyCode&&a._open&&a.close()}),this._parentPage||"overlay"===this.options.display||this._on(this.document,{pageshow:function(){this._openedPage=null,this._getWrapper()}}),a._parentPage?this.document.on("pagehide",":jqmData(role='page')",function(){a._open&&a.close(!0)}):this.document.on("pagebeforehide",function(){a._open&&a.close(!0)})},_open:!1,_pageContentOpenClasses:null,_modalOpenClasses:null,open:function(b){if(!this._open){var c=this,d=c.options,e=function(){c._off(c.document,"panelclose"),c._page().jqmData("panel","open"),a.support.cssTransform3d&&d.animate&&"overlay"!==d.display&&(c._wrapper.addClass(d.classes.animate),c._fixedToolbars().addClass(d.classes.animate)),!b&&a.support.cssTransform3d&&d.animate?(c._wrapper||c.element).animationComplete(f,"transition"):setTimeout(f,0),d.theme&&"overlay"!==d.display&&c._page().parent().addClass(d.classes.pageContainer+"-themed "+d.classes.pageContainer+"-"+d.theme),c.element.removeClass(d.classes.panelClosed).addClass(d.classes.panelOpen),c._positionPanel(!0),c._pageContentOpenClasses=c._getPosDisplayClasses(d.classes.pageContentPrefix),"overlay"!==d.display&&(c._page().parent().addClass(d.classes.pageContainer),c._wrapper.addClass(c._pageContentOpenClasses),c._fixedToolbars().addClass(c._pageContentOpenClasses)),c._modalOpenClasses=c._getPosDisplayClasses(d.classes.modal)+" "+d.classes.modalOpen,c._modal&&c._modal.addClass(c._modalOpenClasses).height(Math.max(c._modal.height(),c.document.height()))},f=function(){c._open&&("overlay"!==d.display&&(c._wrapper.addClass(d.classes.pageContentPrefix+"-open"),c._fixedToolbars().addClass(d.classes.pageContentPrefix+"-open")),c._bindFixListener(),c._trigger("open"),c._openedPage=c._page())};c._trigger("beforeopen"),"open"===c._page().jqmData("panel")?c._on(c.document,{panelclose:e}):e(),c._open=!0}},close:function(b){if(this._open){var c=this,d=this.options,e=function(){c.element.removeClass(d.classes.panelOpen),"overlay"!==d.display&&(c._wrapper.removeClass(c._pageContentOpenClasses),c._fixedToolbars().removeClass(c._pageContentOpenClasses)),!b&&a.support.cssTransform3d&&d.animate?(c._wrapper||c.element).animationComplete(f,"transition"):setTimeout(f,0),c._modal&&c._modal.removeClass(c._modalOpenClasses).height("")},f=function(){d.theme&&"overlay"!==d.display&&c._page().parent().removeClass(d.classes.pageContainer+"-themed "+d.classes.pageContainer+"-"+d.theme),c.element.addClass(d.classes.panelClosed),"overlay"!==d.display&&(c._page().parent().removeClass(d.classes.pageContainer),c._wrapper.removeClass(d.classes.pageContentPrefix+"-open"),c._fixedToolbars().removeClass(d.classes.pageContentPrefix+"-open")),a.support.cssTransform3d&&d.animate&&"overlay"!==d.display&&(c._wrapper.removeClass(d.classes.animate),c._fixedToolbars().removeClass(d.classes.animate)),c._fixPanel(),c._unbindFixListener(),a.mobile.resetActivePageHeight(),c._page().jqmRemoveData("panel"),c._trigger("close"),c._openedPage=null};c._trigger("beforeclose"),e(),c._open=!1}},toggle:function(){this[this._open?"close":"open"]()},_destroy:function(){var b,c=this.options,d=a("body > :mobile-panel").length+a.mobile.activePage.find(":mobile-panel").length>1;"overlay"!==c.display&&(b=a("body > :mobile-panel").add(a.mobile.activePage.find(":mobile-panel")),0===b.not(".ui-panel-display-overlay").not(this.element).length&&this._wrapper.children().unwrap(),this._open&&(this._fixedToolbars().removeClass(c.classes.pageContentPrefix+"-open"),a.support.cssTransform3d&&c.animate&&this._fixedToolbars().removeClass(c.classes.animate),this._page().parent().removeClass(c.classes.pageContainer),c.theme&&this._page().parent().removeClass(c.classes.pageContainer+"-themed "+c.classes.pageContainer+"-"+c.theme))),d||this.document.off("panelopen panelclose"),this._open&&this._page().jqmRemoveData("panel"),this._panelInner.children().unwrap(),this.element.removeClass([this._getPanelClasses(),c.classes.panelOpen,c.classes.animate].join(" ")).off("swipeleft.panel swiperight.panel").off("panelbeforeopen").off("panelhide").off("keyup.panel").off("updatelayout"),this._modal&&this._modal.remove()}})}(a),function(a,b){a.widget("mobile.table",{options:{classes:{table:"ui-table"},enhanced:!1},_create:function(){this.options.enhanced||this.element.addClass(this.options.classes.table),a.extend(this,{headers:b,allHeaders:b}),this._refresh(!0)},_setHeaders:function(){var a=this.element.find("thead tr");this.headers=this.element.find("tr:eq(0)").children(),this.allHeaders=this.headers.add(a.children())},refresh:function(){this._refresh()},rebuild:a.noop,_refresh:function(){var b=this.element,c=b.find("thead tr");this._setHeaders(),c.each(function(){var d=0;a(this).children().each(function(){var e,f=parseInt(this.getAttribute("colspan"),10),g=":nth-child("+(d+1)+")";if(this.setAttribute("data-"+a.mobile.ns+"colstart",d+1),f)for(e=0;f-1>e;e++)d++,g+=", :nth-child("+(d+1)+")";a(this).jqmData("cells",b.find("tr").not(c.eq(0)).not(this).children(g)),d++})})}})}(a),function(a){a.widget("mobile.table",a.mobile.table,{options:{mode:"columntoggle",columnBtnTheme:null,columnPopupTheme:null,columnBtnText:"Columns...",classes:a.extend(a.mobile.table.prototype.options.classes,{popup:"ui-table-columntoggle-popup",columnBtn:"ui-table-columntoggle-btn",priorityPrefix:"ui-table-priority-",columnToggleTable:"ui-table-columntoggle"})},_create:function(){this._super(),"columntoggle"===this.options.mode&&(a.extend(this,{_menu:null}),this.options.enhanced?(this._menu=a(this.document[0].getElementById(this._id()+"-popup")).children().first(),this._addToggles(this._menu,!0)):(this._menu=this._enhanceColToggle(),this.element.addClass(this.options.classes.columnToggleTable)),this._setupEvents(),this._setToggleState())},_id:function(){return this.element.attr("id")||this.widgetName+this.uuid},_setupEvents:function(){this._on(this.window,{throttledresize:"_setToggleState"}),this._on(this._menu,{"change input":"_menuInputChange"})},_addToggles:function(b,c){var d,e=0,f=this.options,g=b.controlgroup("container");c?d=b.find("input"):g.empty(),this.headers.not("td").each(function(){var b,h,i=a(this),j=a.mobile.getAttribute(this,"priority");j&&(h=i.add(i.jqmData("cells")),h.addClass(f.classes.priorityPrefix+j),b=(c?d.eq(e++):a("<label><input type='checkbox' checked />"+(i.children("abbr").first().attr("title")||i.text())+"</label>").appendTo(g).children(0).checkboxradio({theme:f.columnPopupTheme})).jqmData("header",i).jqmData("cells",h),i.jqmData("input",b))}),c||b.controlgroup("refresh")},_menuInputChange:function(b){var c=a(b.target),d=c[0].checked;c.jqmData("cells").toggleClass("ui-table-cell-hidden",!d).toggleClass("ui-table-cell-visible",d)},_unlockCells:function(a){a.removeClass("ui-table-cell-hidden ui-table-cell-visible")},_enhanceColToggle:function(){var b,c,d,e,f=this.element,g=this.options,h=a.mobile.ns,i=this.document[0].createDocumentFragment();return b=this._id()+"-popup",c=a("<a href='#"+b+"' class='"+g.classes.columnBtn+" ui-btn ui-btn-"+(g.columnBtnTheme||"a")+" ui-corner-all ui-shadow ui-mini' data-"+h+"rel='popup'>"+g.columnBtnText+"</a>"),d=a("<div class='"+g.classes.popup+"' id='"+b+"'></div>"),e=a("<fieldset></fieldset>").controlgroup(),this._addToggles(e,!1),e.appendTo(d),i.appendChild(d[0]),i.appendChild(c[0]),f.before(i),d.popup(),e},rebuild:function(){this._super(),"columntoggle"===this.options.mode&&this._refresh(!1)},_refresh:function(b){var c,d,e;if(this._super(b),!b&&"columntoggle"===this.options.mode)for(c=this.headers,d=[],this._menu.find("input").each(function(){var b=a(this),e=b.jqmData("header"),f=c.index(e[0]);f>-1&&!b.prop("checked")&&d.push(f)}),this._unlockCells(this.element.find(".ui-table-cell-hidden, .ui-table-cell-visible")),this._addToggles(this._menu,b),e=d.length-1;e>-1;e--)c.eq(d[e]).jqmData("input").prop("checked",!1).checkboxradio("refresh").trigger("change")},_setToggleState:function(){this._menu.find("input").each(function(){var b=a(this);this.checked="table-cell"===b.jqmData("cells").eq(0).css("display"),b.checkboxradio("refresh")})},_destroy:function(){this._super()}})}(a),function(a){a.widget("mobile.table",a.mobile.table,{options:{mode:"reflow",classes:a.extend(a.mobile.table.prototype.options.classes,{reflowTable:"ui-table-reflow",cellLabels:"ui-table-cell-label"})},_create:function(){this._super(),"reflow"===this.options.mode&&(this.options.enhanced||(this.element.addClass(this.options.classes.reflowTable),this._updateReflow()))},rebuild:function(){this._super(),"reflow"===this.options.mode&&this._refresh(!1)},_refresh:function(a){this._super(a),a||"reflow"!==this.options.mode||this._updateReflow()},_updateReflow:function(){var b=this,c=this.options;a(b.allHeaders.get().reverse()).each(function(){var d,e,f=a(this).jqmData("cells"),g=a.mobile.getAttribute(this,"colstart"),h=f.not(this).filter("thead th").length&&" ui-table-cell-label-top",i=a(this).clone().contents();i.length>0&&(h?(d=parseInt(this.getAttribute("colspan"),10),e="",d&&(e="td:nth-child("+d+"n + "+g+")"),b._addLabels(f.filter(e),c.classes.cellLabels+h,i)):b._addLabels(f,c.classes.cellLabels,i))})},_addLabels:function(b,c,d){1===d.length&&"abbr"===d[0].nodeName.toLowerCase()&&(d=d.eq(0).attr("title")),b.not(":has(b."+c+")").prepend(a("<b class='"+c+"'></b>").append(d))}})}(a),function(a,c){var d=function(b,c){return-1===(""+(a.mobile.getAttribute(this,"filtertext")||a(this).text())).toLowerCase().indexOf(c)};a.widget("mobile.filterable",{initSelector:":jqmData(filter='true')",options:{filterReveal:!1,filterCallback:d,enhanced:!1,input:null,children:"> li, > option, > optgroup option, > tbody tr, > .ui-controlgroup-controls > .ui-btn, > .ui-controlgroup-controls > .ui-checkbox, > .ui-controlgroup-controls > .ui-radio"},_create:function(){var b=this.options;a.extend(this,{_search:null,_timer:0}),this._setInput(b.input),b.enhanced||this._filterItems((this._search&&this._search.val()||"").toLowerCase())},_onKeyUp:function(){var c,d,e=this._search;if(e){if(c=e.val().toLowerCase(),d=a.mobile.getAttribute(e[0],"lastval")+"",d&&d===c)return;this._timer&&(b.clearTimeout(this._timer),this._timer=0),this._timer=this._delay(function(){return this._trigger("beforefilter",null,{input:e})===!1?!1:(e[0].setAttribute("data-"+a.mobile.ns+"lastval",c),this._filterItems(c),void(this._timer=0))},250)}},_getFilterableItems:function(){var b=this.element,c=this.options.children,d=c?a.isFunction(c)?c():c.nodeName?a(c):c.jquery?c:this.element.find(c):{length:0};return 0===d.length&&(d=b.children()),d},_filterItems:function(b){var c,e,f,g,h=[],i=[],j=this.options,k=this._getFilterableItems();if(null!=b)for(e=j.filterCallback||d,f=k.length,c=0;f>c;c++)g=e.call(k[c],c,b)?i:h,g.push(k[c]);0===i.length?k[j.filterReveal&&0===b.length?"addClass":"removeClass"]("ui-screen-hidden"):(a(i).addClass("ui-screen-hidden"),a(h).removeClass("ui-screen-hidden")),this._refreshChildWidget(),this._trigger("filter",null,{items:k})},_refreshChildWidget:function(){var b,c,d=["collapsibleset","selectmenu","controlgroup","listview"];for(c=d.length-1;c>-1;c--)b=d[c],a.mobile[b]&&(b=this.element.data("mobile-"+b),b&&a.isFunction(b.refresh)&&b.refresh())},_setInput:function(c){var d=this._search;this._timer&&(b.clearTimeout(this._timer),this._timer=0),d&&(this._off(d,"keyup change input"),d=null),c&&(d=c.jquery?c:c.nodeName?a(c):this.document.find(c),this._on(d,{keydown:"_onKeyDown",keypress:"_onKeyPress",keyup:"_onKeyUp",change:"_onKeyUp",input:"_onKeyUp"})),this._search=d},_onKeyDown:function(b){b.keyCode===a.ui.keyCode.ENTER&&(b.preventDefault(),this._preventKeyPress=!0)},_onKeyPress:function(a){this._preventKeyPress&&(a.preventDefault(),this._preventKeyPress=!1)},_setOptions:function(a){var b=!(a.filterReveal===c&&a.filterCallback===c&&a.children===c);this._super(a),a.input!==c&&(this._setInput(a.input),b=!0),b&&this.refresh()},_destroy:function(){var a=this.options,b=this._getFilterableItems();a.enhanced?b.toggleClass("ui-screen-hidden",a.filterReveal):b.removeClass("ui-screen-hidden")},refresh:function(){this._timer&&(b.clearTimeout(this._timer),this._timer=0),this._filterItems((this._search&&this._search.val()||"").toLowerCase())}})}(a),function(a,b){var c=function(a,b){return function(c){b.call(this,c),a._syncTextInputOptions(c)}},d=/(^|\s)ui-li-divider(\s|$)/,e=a.mobile.filterable.prototype.options.filterCallback;a.mobile.filterable.prototype.options.filterCallback=function(a,b){return!this.className.match(d)&&e.call(this,a,b)},a.widget("mobile.filterable",a.mobile.filterable,{options:{filterPlaceholder:"Filter items...",filterTheme:null},_create:function(){var b,c,d=this.element,e=["collapsibleset","selectmenu","controlgroup","listview"],f={};for(this._super(),a.extend(this,{_widget:null}),b=e.length-1;b>-1;b--)if(c=e[b],a.mobile[c]){if(this._setWidget(d.data("mobile-"+c)))break;f[c+"create"]="_handleCreate"}this._widget||this._on(d,f)},_handleCreate:function(a){this._setWidget(this.element.data("mobile-"+a.type.substring(0,a.type.length-6)))},_trigger:function(a,b,c){return this._widget&&"mobile-listview"===this._widget.widgetFullName&&"beforefilter"===a&&this._widget._trigger("beforefilter",b,c),this._super(a,b,c)},_setWidget:function(a){return!this._widget&&a&&(this._widget=a,this._widget._setOptions=c(this,this._widget._setOptions)),this._widget&&(this._syncTextInputOptions(this._widget.options),"listview"===this._widget.widgetName&&(this._widget.options.hideDividers=!0,this._widget.element.listview("refresh"))),!!this._widget},_isSearchInternal:function(){return this._search&&this._search.jqmData("ui-filterable-"+this.uuid+"-internal")},_setInput:function(b){var c=this.options,d=!0,e={};if(!b){if(this._isSearchInternal())return;d=!1,b=a("<input data-"+a.mobile.ns+"type='search' placeholder='"+c.filterPlaceholder+"'></input>").jqmData("ui-filterable-"+this.uuid+"-internal",!0),a("<form class='ui-filterable'></form>").append(b).submit(function(a){a.preventDefault(),b.blur()}).insertBefore(this.element),a.mobile.textinput&&(null!=this.options.filterTheme&&(e.theme=c.filterTheme),b.textinput(e))}this._super(b),this._isSearchInternal()&&d&&this._search.attr("placeholder",this.options.filterPlaceholder)},_setOptions:function(c){var d=this._super(c);return c.filterPlaceholder!==b&&this._isSearchInternal()&&this._search.attr("placeholder",c.filterPlaceholder),c.filterTheme!==b&&this._search&&a.mobile.textinput&&this._search.textinput("option","theme",c.filterTheme),d},_refreshChildWidget:function(){this._refreshingChildWidget=!0,this._superApply(arguments),this._refreshingChildWidget=!1},refresh:function(){this._refreshingChildWidget||this._superApply(arguments)},_destroy:function(){this._isSearchInternal()&&this._search.remove(),this._super()},_syncTextInputOptions:function(c){var d,e={};if(this._isSearchInternal()&&a.mobile.textinput){for(d in a.mobile.textinput.prototype.options)c[d]!==b&&(e[d]="theme"===d&&null!=this.options.filterTheme?this.options.filterTheme:c[d]);this._search.textinput("option",e)}}}),a.widget("mobile.listview",a.mobile.listview,{options:{filter:!1},_create:function(){return this.options.filter!==!0||this.element.data("mobile-filterable")||this.element.filterable(),this._super()},refresh:function(){var a;this._superApply(arguments),this.options.filter===!0&&(a=this.element.data("mobile-filterable"),a&&a.refresh())}})}(a),function(a,b){function c(){return++e}function d(a){return a.hash.length>1&&decodeURIComponent(a.href.replace(f,""))===decodeURIComponent(location.href.replace(f,""))}var e=0,f=/#.*$/;a.widget("ui.tabs",{version:"fadf2b312a05040436451c64bbfaf4814bc62c56",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var b=this,c=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",c.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(b){a(this).is(".ui-state-disabled")&&b.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){a(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),c.active=this._initialActive(),a.isArray(c.disabled)&&(c.disabled=a.unique(c.disabled.concat(a.map(this.tabs.filter(".ui-state-disabled"),function(a){return b.tabs.index(a)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(c.active):a(),this._refresh(),this.active.length&&this.load(c.active)},_initialActive:function(){var b=this.options.active,c=this.options.collapsible,d=location.hash.substring(1);return null===b&&(d&&this.tabs.each(function(c,e){return a(e).attr("aria-controls")===d?(b=c,!1):void 0}),null===b&&(b=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===b||-1===b)&&(b=this.tabs.length?0:!1)),b!==!1&&(b=this.tabs.index(this.tabs.eq(b)),-1===b&&(b=c?!1:0)),!c&&b===!1&&this.anchors.length&&(b=0),b},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):a()}},_tabKeydown:function(b){var c=a(this.document[0].activeElement).closest("li"),d=this.tabs.index(c),e=!0;if(!this._handlePageNav(b)){switch(b.keyCode){case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:d++;break;case a.ui.keyCode.UP:case a.ui.keyCode.LEFT:e=!1,d--;break;case a.ui.keyCode.END:d=this.anchors.length-1;break;case a.ui.keyCode.HOME:d=0;break;case a.ui.keyCode.SPACE:return b.preventDefault(),clearTimeout(this.activating),void this._activate(d);case a.ui.keyCode.ENTER:return b.preventDefault(),clearTimeout(this.activating),void this._activate(d===this.options.active?!1:d);default:return}b.preventDefault(),clearTimeout(this.activating),d=this._focusNextTab(d,e),b.ctrlKey||(c.attr("aria-selected","false"),this.tabs.eq(d).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",d)},this.delay))}},_panelKeydown:function(b){this._handlePageNav(b)||b.ctrlKey&&b.keyCode===a.ui.keyCode.UP&&(b.preventDefault(),this.active.focus())},_handlePageNav:function(b){return b.altKey&&b.keyCode===a.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):b.altKey&&b.keyCode===a.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(b,c){function d(){return b>e&&(b=0),0>b&&(b=e),b}for(var e=this.tabs.length-1;-1!==a.inArray(d(),this.options.disabled);)b=c?b+1:b-1;return b},_focusNextTab:function(a,b){return a=this._findNextTab(a,b),this.tabs.eq(a).focus(),a},_setOption:function(a,b){return"active"===a?void this._activate(b):"disabled"===a?void this._setupDisabled(b):(this._super(a,b),"collapsible"===a&&(this.element.toggleClass("ui-tabs-collapsible",b),b||this.options.active!==!1||this._activate(0)),"event"===a&&this._setupEvents(b),void("heightStyle"===a&&this._setupHeightStyle(b)))},_tabId:function(a){return a.attr("aria-controls")||"ui-tabs-"+c()},_sanitizeSelector:function(a){return a?a.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var b=this.options,c=this.tablist.children(":has(a[href])");b.disabled=a.map(c.filter(".ui-state-disabled"),function(a){return c.index(a)}),this._processTabs(),b.active!==!1&&this.anchors.length?this.active.length&&!a.contains(this.tablist[0],this.active[0])?this.tabs.length===b.disabled.length?(b.active=!1,this.active=a()):this._activate(this._findNextTab(Math.max(0,b.active-1),!1)):b.active=this.tabs.index(this.active):(b.active=!1,this.active=a()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var b=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return a("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=a(),this.anchors.each(function(c,e){var f,g,h,i=a(e).uniqueId().attr("id"),j=a(e).closest("li"),k=j.attr("aria-controls");d(e)?(f=e.hash,g=b.element.find(b._sanitizeSelector(f))):(h=b._tabId(j),f="#"+h,g=b.element.find(f),g.length||(g=b._createPanel(h),g.insertAfter(b.panels[c-1]||b.tablist)),g.attr("aria-live","polite")),g.length&&(b.panels=b.panels.add(g)),k&&j.data("ui-tabs-aria-controls",k),j.attr({"aria-controls":f.substring(1),"aria-labelledby":i}),g.attr("aria-labelledby",i)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(b){return a("<div>").attr("id",b).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(b){a.isArray(b)&&(b.length?b.length===this.anchors.length&&(b=!0):b=!1);for(var c,d=0;c=this.tabs[d];d++)b===!0||-1!==a.inArray(d,b)?a(c).addClass("ui-state-disabled").attr("aria-disabled","true"):a(c).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=b},_setupEvents:function(b){var c={click:function(a){a.preventDefault()}};b&&a.each(b.split(" "),function(a,b){c[b]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,c),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(b){var c,d=this.element.parent();"fill"===b?(c=d.height(),c-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var b=a(this),d=b.css("position");"absolute"!==d&&"fixed"!==d&&(c-=b.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){c-=a(this).outerHeight(!0)
+}),this.panels.each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")):"auto"===b&&(c=0,this.panels.each(function(){c=Math.max(c,a(this).height("").height())}).height(c))},_eventHandler:function(b){var c=this.options,d=this.active,e=a(b.currentTarget),f=e.closest("li"),g=f[0]===d[0],h=g&&c.collapsible,i=h?a():this._getPanelForTab(f),j=d.length?this._getPanelForTab(d):a(),k={oldTab:d,oldPanel:j,newTab:h?a():f,newPanel:i};b.preventDefault(),f.hasClass("ui-state-disabled")||f.hasClass("ui-tabs-loading")||this.running||g&&!c.collapsible||this._trigger("beforeActivate",b,k)===!1||(c.active=h?!1:this.tabs.index(f),this.active=g?a():f,this.xhr&&this.xhr.abort(),j.length||i.length||a.error("jQuery UI Tabs: Mismatching fragment identifier."),i.length&&this.load(this.tabs.index(f),b),this._toggle(b,k))},_toggle:function(b,c){function d(){f.running=!1,f._trigger("activate",b,c)}function e(){c.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),g.length&&f.options.show?f._show(g,f.options.show,d):(g.show(),d())}var f=this,g=c.newPanel,h=c.oldPanel;this.running=!0,h.length&&this.options.hide?this._hide(h,this.options.hide,function(){c.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),e()}):(c.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),h.hide(),e()),h.attr({"aria-expanded":"false","aria-hidden":"true"}),c.oldTab.attr("aria-selected","false"),g.length&&h.length?c.oldTab.attr("tabIndex",-1):g.length&&this.tabs.filter(function(){return 0===a(this).attr("tabIndex")}).attr("tabIndex",-1),g.attr({"aria-expanded":"true","aria-hidden":"false"}),c.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(b){var c,d=this._findActive(b);d[0]!==this.active[0]&&(d.length||(d=this.active),c=d.find(".ui-tabs-anchor")[0],this._eventHandler({target:c,currentTarget:c,preventDefault:a.noop}))},_findActive:function(b){return b===!1?a():this.tabs.eq(b)},_getIndex:function(a){return"string"==typeof a&&(a=this.anchors.index(this.anchors.filter("[href$='"+a+"']"))),a},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){a.data(this,"ui-tabs-destroy")?a(this).remove():a(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var b=a(this),c=b.data("ui-tabs-aria-controls");c?b.attr("aria-controls",c).removeData("ui-tabs-aria-controls"):b.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(c){var d=this.options.disabled;d!==!1&&(c===b?d=!1:(c=this._getIndex(c),d=a.isArray(d)?a.map(d,function(a){return a!==c?a:null}):a.map(this.tabs,function(a,b){return b!==c?b:null})),this._setupDisabled(d))},disable:function(c){var d=this.options.disabled;if(d!==!0){if(c===b)d=!0;else{if(c=this._getIndex(c),-1!==a.inArray(c,d))return;d=a.isArray(d)?a.merge([c],d).sort():[c]}this._setupDisabled(d)}},load:function(b,c){b=this._getIndex(b);var e=this,f=this.tabs.eq(b),g=f.find(".ui-tabs-anchor"),h=this._getPanelForTab(f),i={tab:f,panel:h};d(g[0])||(this.xhr=a.ajax(this._ajaxSettings(g,c,i)),this.xhr&&"canceled"!==this.xhr.statusText&&(f.addClass("ui-tabs-loading"),h.attr("aria-busy","true"),this.xhr.success(function(a){setTimeout(function(){h.html(a),e._trigger("load",c,i)},1)}).complete(function(a,b){setTimeout(function(){"abort"===b&&e.panels.stop(!1,!0),f.removeClass("ui-tabs-loading"),h.removeAttr("aria-busy"),a===e.xhr&&delete e.xhr},1)})))},_ajaxSettings:function(b,c,d){var e=this;return{url:b.attr("href"),beforeSend:function(b,f){return e._trigger("beforeLoad",c,a.extend({jqXHR:b,ajaxSettings:f},d))}}},_getPanelForTab:function(b){var c=a(b).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+c))}})}(a),function(){}(a),function(a,b){function c(a){e=a.originalEvent,i=e.accelerationIncludingGravity,f=Math.abs(i.x),g=Math.abs(i.y),h=Math.abs(i.z),!b.orientation&&(f>7||(h>6&&8>g||8>h&&g>6)&&f>5)?d.enabled&&d.disable():d.enabled||d.enable()}a.mobile.iosorientationfixEnabled=!0;var d,e,f,g,h,i,j=navigator.userAgent;return/iPhone|iPad|iPod/.test(navigator.platform)&&/OS [1-5]_[0-9_]* like Mac OS X/i.test(j)&&j.indexOf("AppleWebKit")>-1?(d=a.mobile.zoom,void a.mobile.document.on("mobileinit",function(){a.mobile.iosorientationfixEnabled&&a.mobile.window.bind("orientationchange.iosorientationfix",d.enable).bind("devicemotion.iosorientationfix",c)})):void(a.mobile.iosorientationfixEnabled=!1)}(a,this),function(a,b,d){function e(){f.removeClass("ui-mobile-rendering")}var f=a("html"),g=a.mobile.window;a(b.document).trigger("mobileinit"),a.mobile.gradeA()&&(a.mobile.ajaxBlacklist&&(a.mobile.ajaxEnabled=!1),f.addClass("ui-mobile ui-mobile-rendering"),setTimeout(e,5e3),a.extend(a.mobile,{initializePage:function(){var b=a.mobile.path,f=a(":jqmData(role='page'), :jqmData(role='dialog')"),h=b.stripHash(b.stripQueryParams(b.parseLocation().hash)),i=a.mobile.path.parseLocation(),j=h?c.getElementById(h):d;f.length||(f=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0)),f.each(function(){var c=a(this);c[0].getAttribute("data-"+a.mobile.ns+"url")||c.attr("data-"+a.mobile.ns+"url",c.attr("id")||b.convertUrlToDataUrl(i.pathname+i.search))}),a.mobile.firstPage=f.first(),a.mobile.pageContainer=a.mobile.firstPage.parent().addClass("ui-mobile-viewport").pagecontainer(),a.mobile.navreadyDeferred.resolve(),g.trigger("pagecontainercreate"),a.mobile.loading("show"),e(),a.mobile.hashListeningEnabled&&a.mobile.path.isHashValid(location.hash)&&(a(j).is(":jqmData(role='page')")||a.mobile.path.isPath(h)||h===a.mobile.dialogHashKey)?a.event.special.navigate.isPushStateEnabled()?(a.mobile.navigate.history.stack=[],a.mobile.navigate(a.mobile.path.isPath(location.hash)?location.hash:location.href)):g.trigger("hashchange",[!0]):(a.event.special.navigate.isPushStateEnabled()&&a.mobile.navigate.navigator.squash(b.parseLocation().href),a.mobile.changePage(a.mobile.firstPage,{transition:"none",reverse:!0,changeHash:!1,fromHashChange:!0}))}}),a(function(){a.support.inlineSVG(),a.mobile.hideUrlBar&&b.scrollTo(0,1),a.mobile.defaultHomeScroll=a.support.scrollTop&&1!==a.mobile.window.scrollTop()?1:0,a.mobile.autoInitializePage&&a.mobile.initializePage(),a.mobile.hideUrlBar&&g.load(a.mobile.silentScroll),a.support.cssPointerEvents||a.mobile.document.delegate(".ui-state-disabled,.ui-disabled","vclick",function(a){a.preventDefault(),a.stopImmediatePropagation()})}))}(a,this)});
+//# sourceMappingURL=jquery.mobile-1.4.5.min.map
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/qrcode.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/qrcode.min.js
new file mode 100755
index 0000000..993e88f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/qrcode.min.js
@@ -0,0 +1 @@
+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/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.js
new file mode 100755
index 0000000..a83b981
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.js
@@ -0,0 +1,4161 @@
+/**
+ * Swiper 3.3.1
+ * Most modern mobile touch slider and framework with hardware accelerated transitions
+ * 
+ * http://www.idangero.us/swiper/
+ * 
+ * Copyright 2016, Vladimir Kharlampidi
+ * The iDangero.us
+ * http://www.idangero.us/
+ * 
+ * Licensed under MIT
+ * 
+ * Released on: February 7, 2016
+ */
+(function () {
+    'use strict';
+    var $;
+    /*===========================
+    Swiper
+    ===========================*/
+    var Swiper = function (container, params) {
+        if (!(this instanceof Swiper)) return new Swiper(container, params);
+
+        var defaults = {
+            direction: 'horizontal',
+            touchEventsTarget: 'container',
+            initialSlide: 0,
+            speed: 300,
+            // autoplay
+            autoplay: false,
+            autoplayDisableOnInteraction: true,
+            autoplayStopOnLast: false,
+            // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
+            iOSEdgeSwipeDetection: false,
+            iOSEdgeSwipeThreshold: 20,
+            // Free mode
+            freeMode: false,
+            freeModeMomentum: true,
+            freeModeMomentumRatio: 1,
+            freeModeMomentumBounce: true,
+            freeModeMomentumBounceRatio: 1,
+            freeModeSticky: false,
+            freeModeMinimumVelocity: 0.02,
+            // Autoheight
+            autoHeight: false,
+            // Set wrapper width
+            setWrapperSize: false,
+            // Virtual Translate
+            virtualTranslate: false,
+            // Effects
+            effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
+            coverflow: {
+                rotate: 50,
+                stretch: 0,
+                depth: 100,
+                modifier: 1,
+                slideShadows : true
+            },
+            flip: {
+                slideShadows : true,
+                limitRotation: true
+            },
+            cube: {
+                slideShadows: true,
+                shadow: true,
+                shadowOffset: 20,
+                shadowScale: 0.94
+            },
+            fade: {
+                crossFade: false
+            },
+            // Parallax
+            parallax: false,
+            // Scrollbar
+            scrollbar: null,
+            scrollbarHide: true,
+            scrollbarDraggable: false,
+            scrollbarSnapOnRelease: false,
+            // Keyboard Mousewheel
+            keyboardControl: false,
+            mousewheelControl: false,
+            mousewheelReleaseOnEdges: false,
+            mousewheelInvert: false,
+            mousewheelForceToAxis: false,
+            mousewheelSensitivity: 1,
+            // Hash Navigation
+            hashnav: false,
+            // Breakpoints
+            breakpoints: undefined,
+            // Slides grid
+            spaceBetween: 0,
+            slidesPerView: 1,
+            slidesPerColumn: 1,
+            slidesPerColumnFill: 'column',
+            slidesPerGroup: 1,
+            centeredSlides: false,
+            slidesOffsetBefore: 0, // in px
+            slidesOffsetAfter: 0, // in px
+            // Round length
+            roundLengths: false,
+            // Touches
+            touchRatio: 1,
+            touchAngle: 45,
+            simulateTouch: true,
+            shortSwipes: true,
+            longSwipes: true,
+            longSwipesRatio: 0.5,
+            longSwipesMs: 300,
+            followFinger: true,
+            onlyExternal: false,
+            threshold: 0,
+            touchMoveStopPropagation: true,
+            // Unique Navigation Elements
+            uniqueNavElements: true,
+            // Pagination
+            pagination: null,
+            paginationElement: 'span',
+            paginationClickable: false,
+            paginationHide: false,
+            paginationBulletRender: null,
+            paginationProgressRender: null,
+            paginationFractionRender: null,
+            paginationCustomRender: null,
+            paginationType: 'bullets', // 'bullets' or 'progress' or 'fraction' or 'custom'
+            // Resistance
+            resistance: true,
+            resistanceRatio: 0.85,
+            // Next/prev buttons
+            nextButton: null,
+            prevButton: null,
+            // Progress
+            watchSlidesProgress: false,
+            watchSlidesVisibility: false,
+            // Cursor
+            grabCursor: false,
+            // Clicks
+            preventClicks: true,
+            preventClicksPropagation: true,
+            slideToClickedSlide: false,
+            // Lazy Loading
+            lazyLoading: false,
+            lazyLoadingInPrevNext: false,
+            lazyLoadingInPrevNextAmount: 1,
+            lazyLoadingOnTransitionStart: false,
+            // Images
+            preloadImages: true,
+            updateOnImagesReady: true,
+            // loop
+            loop: false,
+            loopAdditionalSlides: 0,
+            loopedSlides: null,
+            // Control
+            control: undefined,
+            controlInverse: false,
+            controlBy: 'slide', //or 'container'
+            // Swiping/no swiping
+            allowSwipeToPrev: true,
+            allowSwipeToNext: true,
+            swipeHandler: null, //'.swipe-handler',
+            noSwiping: true,
+            noSwipingClass: 'swiper-no-swiping',
+            // NS
+            slideClass: 'swiper-slide',
+            slideActiveClass: 'swiper-slide-active',
+            slideVisibleClass: 'swiper-slide-visible',
+            slideDuplicateClass: 'swiper-slide-duplicate',
+            slideNextClass: 'swiper-slide-next',
+            slidePrevClass: 'swiper-slide-prev',
+            wrapperClass: 'swiper-wrapper',
+            bulletClass: 'swiper-pagination-bullet',
+            bulletActiveClass: 'swiper-pagination-bullet-active',
+            buttonDisabledClass: 'swiper-button-disabled',
+            paginationCurrentClass: 'swiper-pagination-current',
+            paginationTotalClass: 'swiper-pagination-total',
+            paginationHiddenClass: 'swiper-pagination-hidden',
+            paginationProgressbarClass: 'swiper-pagination-progressbar',
+            // Observer
+            observer: false,
+            observeParents: false,
+            // Accessibility
+            a11y: false,
+            prevSlideMessage: 'Previous slide',
+            nextSlideMessage: 'Next slide',
+            firstSlideMessage: 'This is the first slide',
+            lastSlideMessage: 'This is the last slide',
+            paginationBulletMessage: 'Go to slide {{index}}',
+            // Callbacks
+            runCallbacksOnInit: true
+            /*
+            Callbacks:
+            onInit: function (swiper)
+            onDestroy: function (swiper)
+            onClick: function (swiper, e)
+            onTap: function (swiper, e)
+            onDoubleTap: function (swiper, e)
+            onSliderMove: function (swiper, e)
+            onSlideChangeStart: function (swiper)
+            onSlideChangeEnd: function (swiper)
+            onTransitionStart: function (swiper)
+            onTransitionEnd: function (swiper)
+            onImagesReady: function (swiper)
+            onProgress: function (swiper, progress)
+            onTouchStart: function (swiper, e)
+            onTouchMove: function (swiper, e)
+            onTouchMoveOpposite: function (swiper, e)
+            onTouchEnd: function (swiper, e)
+            onReachBeginning: function (swiper)
+            onReachEnd: function (swiper)
+            onSetTransition: function (swiper, duration)
+            onSetTranslate: function (swiper, translate)
+            onAutoplayStart: function (swiper)
+            onAutoplayStop: function (swiper),
+            onLazyImageLoad: function (swiper, slide, image)
+            onLazyImageReady: function (swiper, slide, image)
+            */
+        
+        };
+        var initialVirtualTranslate = params && params.virtualTranslate;
+        
+        params = params || {};
+        var originalParams = {};
+        for (var param in params) {
+            if (typeof params[param] === 'object' && params[param] !== null && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) {
+                originalParams[param] = {};
+                for (var deepParam in params[param]) {
+                    originalParams[param][deepParam] = params[param][deepParam];
+                }
+            }
+            else {
+                originalParams[param] = params[param];
+            }
+        }
+        for (var def in defaults) {
+            if (typeof params[def] === 'undefined') {
+                params[def] = defaults[def];
+            }
+            else if (typeof params[def] === 'object') {
+                for (var deepDef in defaults[def]) {
+                    if (typeof params[def][deepDef] === 'undefined') {
+                        params[def][deepDef] = defaults[def][deepDef];
+                    }
+                }
+            }
+        }
+        
+        // Swiper
+        var s = this;
+        
+        // Params
+        s.params = params;
+        s.originalParams = originalParams;
+        
+        // Classname
+        s.classNames = [];
+        /*=========================
+          Dom Library and plugins
+          ===========================*/
+        if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){
+            $ = Dom7;
+        }
+        if (typeof $ === 'undefined') {
+            if (typeof Dom7 === 'undefined') {
+                $ = window.Dom7 || window.Zepto || window.jQuery;
+            }
+            else {
+                $ = Dom7;
+            }
+            if (!$) return;
+        }
+        // Export it to Swiper instance
+        s.$ = $;
+        
+        /*=========================
+          Breakpoints
+          ===========================*/
+        s.currentBreakpoint = undefined;
+        s.getActiveBreakpoint = function () {
+            //Get breakpoint for window width
+            if (!s.params.breakpoints) return false;
+            var breakpoint = false;
+            var points = [], point;
+            for ( point in s.params.breakpoints ) {
+                if (s.params.breakpoints.hasOwnProperty(point)) {
+                    points.push(point);
+                }
+            }
+            points.sort(function (a, b) {
+                return parseInt(a, 10) > parseInt(b, 10);
+            });
+            for (var i = 0; i < points.length; i++) {
+                point = points[i];
+                if (point >= window.innerWidth && !breakpoint) {
+                    breakpoint = point;
+                }
+            }
+            return breakpoint || 'max';
+        };
+        s.setBreakpoint = function () {
+            //Set breakpoint for window width and update parameters
+            var breakpoint = s.getActiveBreakpoint();
+            if (breakpoint && s.currentBreakpoint !== breakpoint) {
+                var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams;
+                var needsReLoop = s.params.loop && (breakPointsParams.slidesPerView !== s.params.slidesPerView);
+                for ( var param in breakPointsParams ) {
+                    s.params[param] = breakPointsParams[param];
+                }
+                s.currentBreakpoint = breakpoint;
+                if(needsReLoop && s.destroyLoop) {
+                    s.reLoop(true);
+                }
+            }
+        };
+        // Set breakpoint on load
+        if (s.params.breakpoints) {
+            s.setBreakpoint();
+        }
+        
+        /*=========================
+          Preparation - Define Container, Wrapper and Pagination
+          ===========================*/
+        s.container = $(container);
+        if (s.container.length === 0) return;
+        if (s.container.length > 1) {
+            var swipers = [];
+            s.container.each(function () {
+                var container = this;
+                swipers.push(new Swiper(this, params));
+            });
+            return swipers;
+        }
+        
+        // Save instance in container HTML Element and in data
+        s.container[0].swiper = s;
+        s.container.data('swiper', s);
+        
+        s.classNames.push('swiper-container-' + s.params.direction);
+        
+        if (s.params.freeMode) {
+            s.classNames.push('swiper-container-free-mode');
+        }
+        if (!s.support.flexbox) {
+            s.classNames.push('swiper-container-no-flexbox');
+            s.params.slidesPerColumn = 1;
+        }
+        if (s.params.autoHeight) {
+            s.classNames.push('swiper-container-autoheight');
+        }
+        // Enable slides progress when required
+        if (s.params.parallax || s.params.watchSlidesVisibility) {
+            s.params.watchSlidesProgress = true;
+        }
+        // Coverflow / 3D
+        if (['cube', 'coverflow', 'flip'].indexOf(s.params.effect) >= 0) {
+            if (s.support.transforms3d) {
+                s.params.watchSlidesProgress = true;
+                s.classNames.push('swiper-container-3d');
+            }
+            else {
+                s.params.effect = 'slide';
+            }
+        }
+        if (s.params.effect !== 'slide') {
+            s.classNames.push('swiper-container-' + s.params.effect);
+        }
+        if (s.params.effect === 'cube') {
+            s.params.resistanceRatio = 0;
+            s.params.slidesPerView = 1;
+            s.params.slidesPerColumn = 1;
+            s.params.slidesPerGroup = 1;
+            s.params.centeredSlides = false;
+            s.params.spaceBetween = 0;
+            s.params.virtualTranslate = true;
+            s.params.setWrapperSize = false;
+        }
+        if (s.params.effect === 'fade' || s.params.effect === 'flip') {
+            s.params.slidesPerView = 1;
+            s.params.slidesPerColumn = 1;
+            s.params.slidesPerGroup = 1;
+            s.params.watchSlidesProgress = true;
+            s.params.spaceBetween = 0;
+            s.params.setWrapperSize = false;
+            if (typeof initialVirtualTranslate === 'undefined') {
+                s.params.virtualTranslate = true;
+            }
+        }
+        
+        // Grab Cursor
+        if (s.params.grabCursor && s.support.touch) {
+            s.params.grabCursor = false;
+        }
+        
+        // Wrapper
+        s.wrapper = s.container.children('.' + s.params.wrapperClass);
+        
+        // Pagination
+        if (s.params.pagination) {
+            s.paginationContainer = $(s.params.pagination);
+            if (s.params.uniqueNavElements && typeof s.params.pagination === 'string' && s.paginationContainer.length > 1 && s.container.find(s.params.pagination).length === 1) {
+                s.paginationContainer = s.container.find(s.params.pagination);
+            }
+        
+            if (s.params.paginationType === 'bullets' && s.params.paginationClickable) {
+                s.paginationContainer.addClass('swiper-pagination-clickable');
+            }
+            else {
+                s.params.paginationClickable = false;
+            }
+            s.paginationContainer.addClass('swiper-pagination-' + s.params.paginationType);
+        }
+        // Next/Prev Buttons
+        if (s.params.nextButton || s.params.prevButton) {
+            if (s.params.nextButton) {
+                s.nextButton = $(s.params.nextButton);
+                if (s.params.uniqueNavElements && typeof s.params.nextButton === 'string' && s.nextButton.length > 1 && s.container.find(s.params.nextButton).length === 1) {
+                    s.nextButton = s.container.find(s.params.nextButton);
+                }
+            }
+            if (s.params.prevButton) {
+                s.prevButton = $(s.params.prevButton);
+                if (s.params.uniqueNavElements && typeof s.params.prevButton === 'string' && s.prevButton.length > 1 && s.container.find(s.params.prevButton).length === 1) {
+                    s.prevButton = s.container.find(s.params.prevButton);
+                }
+            }
+        }
+        
+        // Is Horizontal
+        s.isHorizontal = function () {
+            return s.params.direction === 'horizontal';
+        };
+        // s.isH = isH;
+        
+        // RTL
+        s.rtl = s.isHorizontal() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl');
+        if (s.rtl) {
+            s.classNames.push('swiper-container-rtl');
+        }
+        
+        // Wrong RTL support
+        if (s.rtl) {
+            s.wrongRTL = s.wrapper.css('display') === '-webkit-box';
+        }
+        
+        // Columns
+        if (s.params.slidesPerColumn > 1) {
+            s.classNames.push('swiper-container-multirow');
+        }
+        
+        // Check for Android
+        if (s.device.android) {
+            s.classNames.push('swiper-container-android');
+        }
+        
+        // Add classes
+        s.container.addClass(s.classNames.join(' '));
+        
+        // Translate
+        s.translate = 0;
+        
+        // Progress
+        s.progress = 0;
+        
+        // Velocity
+        s.velocity = 0;
+        
+        /*=========================
+          Locks, unlocks
+          ===========================*/
+        s.lockSwipeToNext = function () {
+            s.params.allowSwipeToNext = false;
+        };
+        s.lockSwipeToPrev = function () {
+            s.params.allowSwipeToPrev = false;
+        };
+        s.lockSwipes = function () {
+            s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false;
+        };
+        s.unlockSwipeToNext = function () {
+            s.params.allowSwipeToNext = true;
+        };
+        s.unlockSwipeToPrev = function () {
+            s.params.allowSwipeToPrev = true;
+        };
+        s.unlockSwipes = function () {
+            s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true;
+        };
+        
+        /*=========================
+          Round helper
+          ===========================*/
+        function round(a) {
+            return Math.floor(a);
+        }
+        /*=========================
+          Set grab cursor
+          ===========================*/
+        if (s.params.grabCursor) {
+            s.container[0].style.cursor = 'move';
+            s.container[0].style.cursor = '-webkit-grab';
+            s.container[0].style.cursor = '-moz-grab';
+            s.container[0].style.cursor = 'grab';
+        }
+        /*=========================
+          Update on Images Ready
+          ===========================*/
+        s.imagesToLoad = [];
+        s.imagesLoaded = 0;
+        
+        s.loadImage = function (imgElement, src, srcset, checkForComplete, callback) {
+            var image;
+            function onReady () {
+                if (callback) callback();
+            }
+            if (!imgElement.complete || !checkForComplete) {
+                if (src) {
+                    image = new window.Image();
+                    image.onload = onReady;
+                    image.onerror = onReady;
+                    if (srcset) {
+                        image.srcset = srcset;
+                    }
+                    if (src) {
+                        image.src = src;
+                    }
+                } else {
+                    onReady();
+                }
+        
+            } else {//image already loaded...
+                onReady();
+            }
+        };
+        s.preloadImages = function () {
+            s.imagesToLoad = s.container.find('img');
+            function _onReady() {
+                if (typeof s === 'undefined' || s === null) return;
+                if (s.imagesLoaded !== undefined) s.imagesLoaded++;
+                if (s.imagesLoaded === s.imagesToLoad.length) {
+                    if (s.params.updateOnImagesReady) s.update();
+                    s.emit('onImagesReady', s);
+                }
+            }
+            for (var i = 0; i < s.imagesToLoad.length; i++) {
+                s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), true, _onReady);
+            }
+        };
+        
+        /*=========================
+          Autoplay
+          ===========================*/
+        s.autoplayTimeoutId = undefined;
+        s.autoplaying = false;
+        s.autoplayPaused = false;
+        function autoplay() {
+            s.autoplayTimeoutId = setTimeout(function () {
+                if (s.params.loop) {
+                    s.fixLoop();
+                    s._slideNext();
+                    s.emit('onAutoplay', s);
+                }
+                else {
+                    if (!s.isEnd) {
+                        s._slideNext();
+                        s.emit('onAutoplay', s);
+                    }
+                    else {
+                        if (!params.autoplayStopOnLast) {
+                            s._slideTo(0);
+                            s.emit('onAutoplay', s);
+                        }
+                        else {
+                            s.stopAutoplay();
+                        }
+                    }
+                }
+            }, s.params.autoplay);
+        }
+        s.startAutoplay = function () {
+            if (typeof s.autoplayTimeoutId !== 'undefined') return false;
+            if (!s.params.autoplay) return false;
+            if (s.autoplaying) return false;
+            s.autoplaying = true;
+            s.emit('onAutoplayStart', s);
+            autoplay();
+        };
+        s.stopAutoplay = function (internal) {
+            if (!s.autoplayTimeoutId) return;
+            if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
+            s.autoplaying = false;
+            s.autoplayTimeoutId = undefined;
+            s.emit('onAutoplayStop', s);
+        };
+        s.pauseAutoplay = function (speed) {
+            if (s.autoplayPaused) return;
+            if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
+            s.autoplayPaused = true;
+            if (speed === 0) {
+                s.autoplayPaused = false;
+                autoplay();
+            }
+            else {
+                s.wrapper.transitionEnd(function () {
+                    if (!s) return;
+                    s.autoplayPaused = false;
+                    if (!s.autoplaying) {
+                        s.stopAutoplay();
+                    }
+                    else {
+                        autoplay();
+                    }
+                });
+            }
+        };
+        /*=========================
+          Min/Max Translate
+          ===========================*/
+        s.minTranslate = function () {
+            return (-s.snapGrid[0]);
+        };
+        s.maxTranslate = function () {
+            return (-s.snapGrid[s.snapGrid.length - 1]);
+        };
+        /*=========================
+          Slider/slides sizes
+          ===========================*/
+        s.updateAutoHeight = function () {
+            // Update Height
+            var slide = s.slides.eq(s.activeIndex)[0];
+            if (typeof slide !== 'undefined') {
+                var newHeight = slide.offsetHeight;
+                if (newHeight) s.wrapper.css('height', newHeight + 'px');
+            }
+        };
+        s.updateContainerSize = function () {
+            var width, height;
+            if (typeof s.params.width !== 'undefined') {
+                width = s.params.width;
+            }
+            else {
+                width = s.container[0].clientWidth;
+            }
+            if (typeof s.params.height !== 'undefined') {
+                height = s.params.height;
+            }
+            else {
+                height = s.container[0].clientHeight;
+            }
+            if (width === 0 && s.isHorizontal() || height === 0 && !s.isHorizontal()) {
+                return;
+            }
+        
+            //Subtract paddings
+            width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10);
+            height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10);
+        
+            // Store values
+            s.width = width;
+            s.height = height;
+            s.size = s.isHorizontal() ? s.width : s.height;
+        };
+        
+        s.updateSlidesSize = function () {
+            s.slides = s.wrapper.children('.' + s.params.slideClass);
+            s.snapGrid = [];
+            s.slidesGrid = [];
+            s.slidesSizesGrid = [];
+        
+            var spaceBetween = s.params.spaceBetween,
+                slidePosition = -s.params.slidesOffsetBefore,
+                i,
+                prevSlideSize = 0,
+                index = 0;
+            if (typeof s.size === 'undefined') return;
+            if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
+                spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size;
+            }
+        
+            s.virtualSize = -spaceBetween;
+            // reset margins
+            if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''});
+            else s.slides.css({marginRight: '', marginBottom: ''});
+        
+            var slidesNumberEvenToRows;
+            if (s.params.slidesPerColumn > 1) {
+                if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) {
+                    slidesNumberEvenToRows = s.slides.length;
+                }
+                else {
+                    slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn;
+                }
+                if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') {
+                    slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn);
+                }
+            }
+        
+            // Calc slides
+            var slideSize;
+            var slidesPerColumn = s.params.slidesPerColumn;
+            var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
+            var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length);
+            for (i = 0; i < s.slides.length; i++) {
+                slideSize = 0;
+                var slide = s.slides.eq(i);
+                if (s.params.slidesPerColumn > 1) {
+                    // Set slides order
+                    var newSlideOrderIndex;
+                    var column, row;
+                    if (s.params.slidesPerColumnFill === 'column') {
+                        column = Math.floor(i / slidesPerColumn);
+                        row = i - column * slidesPerColumn;
+                        if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) {
+                            if (++row >= slidesPerColumn) {
+                                row = 0;
+                                column++;
+                            }
+                        }
+                        newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn;
+                        slide
+                            .css({
+                                '-webkit-box-ordinal-group': newSlideOrderIndex,
+                                '-moz-box-ordinal-group': newSlideOrderIndex,
+                                '-ms-flex-order': newSlideOrderIndex,
+                                '-webkit-order': newSlideOrderIndex,
+                                'order': newSlideOrderIndex
+                            });
+                    }
+                    else {
+                        row = Math.floor(i / slidesPerRow);
+                        column = i - row * slidesPerRow;
+                    }
+                    slide
+                        .css({
+                            'margin-top': (row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px')
+                        })
+                        .attr('data-swiper-column', column)
+                        .attr('data-swiper-row', row);
+        
+                }
+                if (slide.css('display') === 'none') continue;
+                if (s.params.slidesPerView === 'auto') {
+                    slideSize = s.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);
+                    if (s.params.roundLengths) slideSize = round(slideSize);
+                }
+                else {
+                    slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView;
+                    if (s.params.roundLengths) slideSize = round(slideSize);
+        
+                    if (s.isHorizontal()) {
+                        s.slides[i].style.width = slideSize + 'px';
+                    }
+                    else {
+                        s.slides[i].style.height = slideSize + 'px';
+                    }
+                }
+                s.slides[i].swiperSlideSize = slideSize;
+                s.slidesSizesGrid.push(slideSize);
+        
+        
+                if (s.params.centeredSlides) {
+                    slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
+                    if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween;
+                    if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
+                    if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
+                    s.slidesGrid.push(slidePosition);
+                }
+                else {
+                    if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
+                    s.slidesGrid.push(slidePosition);
+                    slidePosition = slidePosition + slideSize + spaceBetween;
+                }
+        
+                s.virtualSize += slideSize + spaceBetween;
+        
+                prevSlideSize = slideSize;
+        
+                index ++;
+            }
+            s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter;
+            var newSlidesGrid;
+        
+            if (
+                s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) {
+                s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+            }
+            if (!s.support.flexbox || s.params.setWrapperSize) {
+                if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+                else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'});
+            }
+        
+            if (s.params.slidesPerColumn > 1) {
+                s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows;
+                s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween;
+                s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
+                if (s.params.centeredSlides) {
+                    newSlidesGrid = [];
+                    for (i = 0; i < s.snapGrid.length; i++) {
+                        if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]);
+                    }
+                    s.snapGrid = newSlidesGrid;
+                }
+            }
+        
+            // Remove last grid elements depending on width
+            if (!s.params.centeredSlides) {
+                newSlidesGrid = [];
+                for (i = 0; i < s.snapGrid.length; i++) {
+                    if (s.snapGrid[i] <= s.virtualSize - s.size) {
+                        newSlidesGrid.push(s.snapGrid[i]);
+                    }
+                }
+                s.snapGrid = newSlidesGrid;
+                if (Math.floor(s.virtualSize - s.size) - Math.floor(s.snapGrid[s.snapGrid.length - 1]) > 1) {
+                    s.snapGrid.push(s.virtualSize - s.size);
+                }
+            }
+            if (s.snapGrid.length === 0) s.snapGrid = [0];
+        
+            if (s.params.spaceBetween !== 0) {
+                if (s.isHorizontal()) {
+                    if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'});
+                    else s.slides.css({marginRight: spaceBetween + 'px'});
+                }
+                else s.slides.css({marginBottom: spaceBetween + 'px'});
+            }
+            if (s.params.watchSlidesProgress) {
+                s.updateSlidesOffset();
+            }
+        };
+        s.updateSlidesOffset = function () {
+            for (var i = 0; i < s.slides.length; i++) {
+                s.slides[i].swiperSlideOffset = s.isHorizontal() ? s.slides[i].offsetLeft : s.slides[i].offsetTop;
+            }
+        };
+        
+        /*=========================
+          Slider/slides progress
+          ===========================*/
+        s.updateSlidesProgress = function (translate) {
+            if (typeof translate === 'undefined') {
+                translate = s.translate || 0;
+            }
+            if (s.slides.length === 0) return;
+            if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset();
+        
+            var offsetCenter = -translate;
+            if (s.rtl) offsetCenter = translate;
+        
+            // Visible Slides
+            s.slides.removeClass(s.params.slideVisibleClass);
+            for (var i = 0; i < s.slides.length; i++) {
+                var slide = s.slides[i];
+                var slideProgress = (offsetCenter - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween);
+                if (s.params.watchSlidesVisibility) {
+                    var slideBefore = -(offsetCenter - slide.swiperSlideOffset);
+                    var slideAfter = slideBefore + s.slidesSizesGrid[i];
+                    var isVisible =
+                        (slideBefore >= 0 && slideBefore < s.size) ||
+                        (slideAfter > 0 && slideAfter <= s.size) ||
+                        (slideBefore <= 0 && slideAfter >= s.size);
+                    if (isVisible) {
+                        s.slides.eq(i).addClass(s.params.slideVisibleClass);
+                    }
+                }
+                slide.progress = s.rtl ? -slideProgress : slideProgress;
+            }
+        };
+        s.updateProgress = function (translate) {
+            if (typeof translate === 'undefined') {
+                translate = s.translate || 0;
+            }
+            var translatesDiff = s.maxTranslate() - s.minTranslate();
+            var wasBeginning = s.isBeginning;
+            var wasEnd = s.isEnd;
+            if (translatesDiff === 0) {
+                s.progress = 0;
+                s.isBeginning = s.isEnd = true;
+            }
+            else {
+                s.progress = (translate - s.minTranslate()) / (translatesDiff);
+                s.isBeginning = s.progress <= 0;
+                s.isEnd = s.progress >= 1;
+            }
+            if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s);
+            if (s.isEnd && !wasEnd) s.emit('onReachEnd', s);
+        
+            if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate);
+            s.emit('onProgress', s, s.progress);
+        };
+        s.updateActiveIndex = function () {
+            var translate = s.rtl ? s.translate : -s.translate;
+            var newActiveIndex, i, snapIndex;
+            for (i = 0; i < s.slidesGrid.length; i ++) {
+                if (typeof s.slidesGrid[i + 1] !== 'undefined') {
+                    if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) {
+                        newActiveIndex = i;
+                    }
+                    else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) {
+                        newActiveIndex = i + 1;
+                    }
+                }
+                else {
+                    if (translate >= s.slidesGrid[i]) {
+                        newActiveIndex = i;
+                    }
+                }
+            }
+            // Normalize slideIndex
+            if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0;
+            // for (i = 0; i < s.slidesGrid.length; i++) {
+                // if (- translate >= s.slidesGrid[i]) {
+                    // newActiveIndex = i;
+                // }
+            // }
+            snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup);
+            if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1;
+        
+            if (newActiveIndex === s.activeIndex) {
+                return;
+            }
+            s.snapIndex = snapIndex;
+            s.previousIndex = s.activeIndex;
+            s.activeIndex = newActiveIndex;
+            s.updateClasses();
+        };
+        
+        /*=========================
+          Classes
+          ===========================*/
+        s.updateClasses = function () {
+            s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass);
+            var activeSlide = s.slides.eq(s.activeIndex);
+            // Active classes
+            activeSlide.addClass(s.params.slideActiveClass);
+            // Next Slide
+            var nextSlide = activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass);
+            if (s.params.loop && nextSlide.length === 0) {
+                s.slides.eq(0).addClass(s.params.slideNextClass);
+            }
+            // Prev Slide
+            var prevSlide = activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass);
+            if (s.params.loop && prevSlide.length === 0) {
+                s.slides.eq(-1).addClass(s.params.slidePrevClass);
+            }
+        
+            // Pagination
+            if (s.paginationContainer && s.paginationContainer.length > 0) {
+                // Current/Total
+                var current,
+                    total = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
+                if (s.params.loop) {
+                    current = Math.ceil((s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup);
+                    if (current > s.slides.length - 1 - s.loopedSlides * 2) {
+                        current = current - (s.slides.length - s.loopedSlides * 2);
+                    }
+                    if (current > total - 1) current = current - total;
+                    if (current < 0 && s.params.paginationType !== 'bullets') current = total + current;
+                }
+                else {
+                    if (typeof s.snapIndex !== 'undefined') {
+                        current = s.snapIndex;
+                    }
+                    else {
+                        current = s.activeIndex || 0;
+                    }
+                }
+                // Types
+                if (s.params.paginationType === 'bullets' && s.bullets && s.bullets.length > 0) {
+                    s.bullets.removeClass(s.params.bulletActiveClass);
+                    if (s.paginationContainer.length > 1) {
+                        s.bullets.each(function () {
+                            if ($(this).index() === current) $(this).addClass(s.params.bulletActiveClass);
+                        });
+                    }
+                    else {
+                        s.bullets.eq(current).addClass(s.params.bulletActiveClass);
+                    }
+                }
+                if (s.params.paginationType === 'fraction') {
+                    s.paginationContainer.find('.' + s.params.paginationCurrentClass).text(current + 1);
+                    s.paginationContainer.find('.' + s.params.paginationTotalClass).text(total);
+                }
+                if (s.params.paginationType === 'progress') {
+                    var scale = (current + 1) / total,
+                        scaleX = scale,
+                        scaleY = 1;
+                    if (!s.isHorizontal()) {
+                        scaleY = scale;
+                        scaleX = 1;
+                    }
+                    s.paginationContainer.find('.' + s.params.paginationProgressbarClass).transform('translate3d(0,0,0) scaleX(' + scaleX + ') scaleY(' + scaleY + ')').transition(s.params.speed);
+                }
+                if (s.params.paginationType === 'custom' && s.params.paginationCustomRender) {
+                    s.paginationContainer.html(s.params.paginationCustomRender(s, current + 1, total));
+                    s.emit('onPaginationRendered', s, s.paginationContainer[0]);
+                }
+            }
+        
+            // Next/active buttons
+            if (!s.params.loop) {
+                if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                    if (s.isBeginning) {
+                        s.prevButton.addClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.disable(s.prevButton);
+                    }
+                    else {
+                        s.prevButton.removeClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.enable(s.prevButton);
+                    }
+                }
+                if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                    if (s.isEnd) {
+                        s.nextButton.addClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.disable(s.nextButton);
+                    }
+                    else {
+                        s.nextButton.removeClass(s.params.buttonDisabledClass);
+                        if (s.params.a11y && s.a11y) s.a11y.enable(s.nextButton);
+                    }
+                }
+            }
+        };
+        
+        /*=========================
+          Pagination
+          ===========================*/
+        s.updatePagination = function () {
+            if (!s.params.pagination) return;
+            if (s.paginationContainer && s.paginationContainer.length > 0) {
+                var paginationHTML = '';
+                if (s.params.paginationType === 'bullets') {
+                    var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
+                    for (var i = 0; i < numberOfBullets; i++) {
+                        if (s.params.paginationBulletRender) {
+                            paginationHTML += s.params.paginationBulletRender(i, s.params.bulletClass);
+                        }
+                        else {
+                            paginationHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>';
+                        }
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                    s.bullets = s.paginationContainer.find('.' + s.params.bulletClass);
+                    if (s.params.paginationClickable && s.params.a11y && s.a11y) {
+                        s.a11y.initPagination();
+                    }
+                }
+                if (s.params.paginationType === 'fraction') {
+                    if (s.params.paginationFractionRender) {
+                        paginationHTML = s.params.paginationFractionRender(s, s.params.paginationCurrentClass, s.params.paginationTotalClass);
+                    }
+                    else {
+                        paginationHTML =
+                            '<span class="' + s.params.paginationCurrentClass + '"></span>' +
+                            ' / ' +
+                            '<span class="' + s.params.paginationTotalClass+'"></span>';
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                }
+                if (s.params.paginationType === 'progress') {
+                    if (s.params.paginationProgressRender) {
+                        paginationHTML = s.params.paginationProgressRender(s, s.params.paginationProgressbarClass);
+                    }
+                    else {
+                        paginationHTML = '<span class="' + s.params.paginationProgressbarClass + '"></span>';
+                    }
+                    s.paginationContainer.html(paginationHTML);
+                }
+                if (s.params.paginationType !== 'custom') {
+                    s.emit('onPaginationRendered', s, s.paginationContainer[0]);
+                }
+            }
+        };
+        /*=========================
+          Common update method
+          ===========================*/
+        s.update = function (updateTranslate) {
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            s.updateProgress();
+            s.updatePagination();
+            s.updateClasses();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+            }
+            function forceSetTranslate() {
+                newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
+                s.setWrapperTranslate(newTranslate);
+                s.updateActiveIndex();
+                s.updateClasses();
+            }
+            if (updateTranslate) {
+                var translated, newTranslate;
+                if (s.controller && s.controller.spline) {
+                    s.controller.spline = undefined;
+                }
+                if (s.params.freeMode) {
+                    forceSetTranslate();
+                    if (s.params.autoHeight) {
+                        s.updateAutoHeight();
+                    }
+                }
+                else {
+                    if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
+                        translated = s.slideTo(s.slides.length - 1, 0, false, true);
+                    }
+                    else {
+                        translated = s.slideTo(s.activeIndex, 0, false, true);
+                    }
+                    if (!translated) {
+                        forceSetTranslate();
+                    }
+                }
+            }
+            else if (s.params.autoHeight) {
+                s.updateAutoHeight();
+            }
+        };
+        
+        /*=========================
+          Resize Handler
+          ===========================*/
+        s.onResize = function (forceUpdatePagination) {
+            //Breakpoints
+            if (s.params.breakpoints) {
+                s.setBreakpoint();
+            }
+        
+            // Disable locks on resize
+            var allowSwipeToPrev = s.params.allowSwipeToPrev;
+            var allowSwipeToNext = s.params.allowSwipeToNext;
+            s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true;
+        
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+            }
+            if (s.controller && s.controller.spline) {
+                s.controller.spline = undefined;
+            }
+            var slideChangedBySlideTo = false;
+            if (s.params.freeMode) {
+                var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
+                s.setWrapperTranslate(newTranslate);
+                s.updateActiveIndex();
+                s.updateClasses();
+        
+                if (s.params.autoHeight) {
+                    s.updateAutoHeight();
+                }
+            }
+            else {
+                s.updateClasses();
+                if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
+                    slideChangedBySlideTo = s.slideTo(s.slides.length - 1, 0, false, true);
+                }
+                else {
+                    slideChangedBySlideTo = s.slideTo(s.activeIndex, 0, false, true);
+                }
+            }
+            if (s.params.lazyLoading && !slideChangedBySlideTo && s.lazy) {
+                s.lazy.load();
+            }
+            // Return locks after resize
+            s.params.allowSwipeToPrev = allowSwipeToPrev;
+            s.params.allowSwipeToNext = allowSwipeToNext;
+        };
+        
+        /*=========================
+          Events
+          ===========================*/
+        
+        //Define Touch Events
+        var desktopEvents = ['mousedown', 'mousemove', 'mouseup'];
+        if (window.navigator.pointerEnabled) desktopEvents = ['pointerdown', 'pointermove', 'pointerup'];
+        else if (window.navigator.msPointerEnabled) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp'];
+        s.touchEvents = {
+            start : s.support.touch || !s.params.simulateTouch  ? 'touchstart' : desktopEvents[0],
+            move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : desktopEvents[1],
+            end : s.support.touch || !s.params.simulateTouch ? 'touchend' : desktopEvents[2]
+        };
+        
+        
+        // WP8 Touch Events Fix
+        if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) {
+            (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction);
+        }
+        
+        // Attach/detach events
+        s.initEvents = function (detach) {
+            var actionDom = detach ? 'off' : 'on';
+            var action = detach ? 'removeEventListener' : 'addEventListener';
+            var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0];
+            var target = s.support.touch ? touchEventsTarget : document;
+        
+            var moveCapture = s.params.nested ? true : false;
+        
+            //Touch Events
+            if (s.browser.ie) {
+                touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
+                target[action](s.touchEvents.move, s.onTouchMove, moveCapture);
+                target[action](s.touchEvents.end, s.onTouchEnd, false);
+            }
+            else {
+                if (s.support.touch) {
+                    touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
+                    touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture);
+                    touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, false);
+                }
+                if (params.simulateTouch && !s.device.ios && !s.device.android) {
+                    touchEventsTarget[action]('mousedown', s.onTouchStart, false);
+                    document[action]('mousemove', s.onTouchMove, moveCapture);
+                    document[action]('mouseup', s.onTouchEnd, false);
+                }
+            }
+            window[action]('resize', s.onResize);
+        
+            // Next, Prev, Index
+            if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                s.nextButton[actionDom]('click', s.onClickNext);
+                if (s.params.a11y && s.a11y) s.nextButton[actionDom]('keydown', s.a11y.onEnterKey);
+            }
+            if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                s.prevButton[actionDom]('click', s.onClickPrev);
+                if (s.params.a11y && s.a11y) s.prevButton[actionDom]('keydown', s.a11y.onEnterKey);
+            }
+            if (s.params.pagination && s.params.paginationClickable) {
+                s.paginationContainer[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex);
+                if (s.params.a11y && s.a11y) s.paginationContainer[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey);
+            }
+        
+            // Prevent Links Clicks
+            if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true);
+        };
+        s.attachEvents = function () {
+            s.initEvents();
+        };
+        s.detachEvents = function () {
+            s.initEvents(true);
+        };
+        
+        /*=========================
+          Handle Clicks
+          ===========================*/
+        // Prevent Clicks
+        s.allowClick = true;
+        s.preventClicks = function (e) {
+            if (!s.allowClick) {
+                if (s.params.preventClicks) e.preventDefault();
+                if (s.params.preventClicksPropagation && s.animating) {
+                    e.stopPropagation();
+                    e.stopImmediatePropagation();
+                }
+            }
+        };
+        // Clicks
+        s.onClickNext = function (e) {
+            e.preventDefault();
+            if (s.isEnd && !s.params.loop) return;
+            s.slideNext();
+        };
+        s.onClickPrev = function (e) {
+            e.preventDefault();
+            if (s.isBeginning && !s.params.loop) return;
+            s.slidePrev();
+        };
+        s.onClickIndex = function (e) {
+            e.preventDefault();
+            var index = $(this).index() * s.params.slidesPerGroup;
+            if (s.params.loop) index = index + s.loopedSlides;
+            s.slideTo(index);
+        };
+        
+        /*=========================
+          Handle Touches
+          ===========================*/
+        function findElementInEvent(e, selector) {
+            var el = $(e.target);
+            if (!el.is(selector)) {
+                if (typeof selector === 'string') {
+                    el = el.parents(selector);
+                }
+                else if (selector.nodeType) {
+                    var found;
+                    el.parents().each(function (index, _el) {
+                        if (_el === selector) found = selector;
+                    });
+                    if (!found) return undefined;
+                    else return selector;
+                }
+            }
+            if (el.length === 0) {
+                return undefined;
+            }
+            return el[0];
+        }
+        s.updateClickedSlide = function (e) {
+            var slide = findElementInEvent(e, '.' + s.params.slideClass);
+            var slideFound = false;
+            if (slide) {
+                for (var i = 0; i < s.slides.length; i++) {
+                    if (s.slides[i] === slide) slideFound = true;
+                }
+            }
+        
+            if (slide && slideFound) {
+                s.clickedSlide = slide;
+                s.clickedIndex = $(slide).index();
+            }
+            else {
+                s.clickedSlide = undefined;
+                s.clickedIndex = undefined;
+                return;
+            }
+            if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) {
+                var slideToIndex = s.clickedIndex,
+                    realIndex,
+                    duplicatedSlides;
+                if (s.params.loop) {
+                    if (s.animating) return;
+                    realIndex = $(s.clickedSlide).attr('data-swiper-slide-index');
+                    if (s.params.centeredSlides) {
+                        if ((slideToIndex < s.loopedSlides - s.params.slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + s.params.slidesPerView/2)) {
+                            s.fixLoop();
+                            slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index();
+                            setTimeout(function () {
+                                s.slideTo(slideToIndex);
+                            }, 0);
+                        }
+                        else {
+                            s.slideTo(slideToIndex);
+                        }
+                    }
+                    else {
+                        if (slideToIndex > s.slides.length - s.params.slidesPerView) {
+                            s.fixLoop();
+                            slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index();
+                            setTimeout(function () {
+                                s.slideTo(slideToIndex);
+                            }, 0);
+                        }
+                        else {
+                            s.slideTo(slideToIndex);
+                        }
+                    }
+                }
+                else {
+                    s.slideTo(slideToIndex);
+                }
+            }
+        };
+        
+        var isTouched,
+            isMoved,
+            allowTouchCallbacks,
+            touchStartTime,
+            isScrolling,
+            currentTranslate,
+            startTranslate,
+            allowThresholdMove,
+            // Form elements to match
+            formElements = 'input, select, textarea, button',
+            // Last click time
+            lastClickTime = Date.now(), clickTimeout,
+            //Velocities
+            velocities = [],
+            allowMomentumBounce;
+        
+        // Animating Flag
+        s.animating = false;
+        
+        // Touches information
+        s.touches = {
+            startX: 0,
+            startY: 0,
+            currentX: 0,
+            currentY: 0,
+            diff: 0
+        };
+        
+        // Touch handlers
+        var isTouchEvent, startMoving;
+        s.onTouchStart = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            isTouchEvent = e.type === 'touchstart';
+            if (!isTouchEvent && 'which' in e && e.which === 3) return;
+            if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) {
+                s.allowClick = true;
+                return;
+            }
+            if (s.params.swipeHandler) {
+                if (!findElementInEvent(e, s.params.swipeHandler)) return;
+            }
+        
+            var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
+            var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
+        
+            // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
+            if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) {
+                return;
+            }
+        
+            isTouched = true;
+            isMoved = false;
+            allowTouchCallbacks = true;
+            isScrolling = undefined;
+            startMoving = undefined;
+            s.touches.startX = startX;
+            s.touches.startY = startY;
+            touchStartTime = Date.now();
+            s.allowClick = true;
+            s.updateContainerSize();
+            s.swipeDirection = undefined;
+            if (s.params.threshold > 0) allowThresholdMove = false;
+            if (e.type !== 'touchstart') {
+                var preventDefault = true;
+                if ($(e.target).is(formElements)) preventDefault = false;
+                if (document.activeElement && $(document.activeElement).is(formElements)) {
+                    document.activeElement.blur();
+                }
+                if (preventDefault) {
+                    e.preventDefault();
+                }
+            }
+            s.emit('onTouchStart', s, e);
+        };
+        
+        s.onTouchMove = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            if (isTouchEvent && e.type === 'mousemove') return;
+            if (e.preventedByNestedSwiper) {
+                s.touches.startX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+                s.touches.startY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+                return;
+            }
+            if (s.params.onlyExternal) {
+                // isMoved = true;
+                s.allowClick = false;
+                if (isTouched) {
+                    s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+                    s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+                    touchStartTime = Date.now();
+                }
+                return;
+            }
+            if (isTouchEvent && document.activeElement) {
+                if (e.target === document.activeElement && $(e.target).is(formElements)) {
+                    isMoved = true;
+                    s.allowClick = false;
+                    return;
+                }
+            }
+            if (allowTouchCallbacks) {
+                s.emit('onTouchMove', s, e);
+            }
+            if (e.targetTouches && e.targetTouches.length > 1) return;
+        
+            s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
+            s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
+        
+            if (typeof isScrolling === 'undefined') {
+                var touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI;
+                isScrolling = s.isHorizontal() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle);
+            }
+            if (isScrolling) {
+                s.emit('onTouchMoveOpposite', s, e);
+            }
+            if (typeof startMoving === 'undefined' && s.browser.ieTouch) {
+                if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) {
+                    startMoving = true;
+                }
+            }
+            if (!isTouched) return;
+            if (isScrolling)  {
+                isTouched = false;
+                return;
+            }
+            if (!startMoving && s.browser.ieTouch) {
+                return;
+            }
+            s.allowClick = false;
+            s.emit('onSliderMove', s, e);
+            e.preventDefault();
+            if (s.params.touchMoveStopPropagation && !s.params.nested) {
+                e.stopPropagation();
+            }
+        
+            if (!isMoved) {
+                if (params.loop) {
+                    s.fixLoop();
+                }
+                startTranslate = s.getWrapperTranslate();
+                s.setWrapperTransition(0);
+                if (s.animating) {
+                    s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd');
+                }
+                if (s.params.autoplay && s.autoplaying) {
+                    if (s.params.autoplayDisableOnInteraction) {
+                        s.stopAutoplay();
+                    }
+                    else {
+                        s.pauseAutoplay();
+                    }
+                }
+                allowMomentumBounce = false;
+                //Grab Cursor
+                if (s.params.grabCursor) {
+                    s.container[0].style.cursor = 'move';
+                    s.container[0].style.cursor = '-webkit-grabbing';
+                    s.container[0].style.cursor = '-moz-grabbin';
+                    s.container[0].style.cursor = 'grabbing';
+                }
+            }
+            isMoved = true;
+        
+            var diff = s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
+        
+            diff = diff * s.params.touchRatio;
+            if (s.rtl) diff = -diff;
+        
+            s.swipeDirection = diff > 0 ? 'prev' : 'next';
+            currentTranslate = diff + startTranslate;
+        
+            var disableParentSwiper = true;
+            if ((diff > 0 && currentTranslate > s.minTranslate())) {
+                disableParentSwiper = false;
+                if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio);
+            }
+            else if (diff < 0 && currentTranslate < s.maxTranslate()) {
+                disableParentSwiper = false;
+                if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio);
+            }
+        
+            if (disableParentSwiper) {
+                e.preventedByNestedSwiper = true;
+            }
+        
+            // Directions locks
+            if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) {
+                currentTranslate = startTranslate;
+            }
+            if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) {
+                currentTranslate = startTranslate;
+            }
+        
+            if (!s.params.followFinger) return;
+        
+            // Threshold
+            if (s.params.threshold > 0) {
+                if (Math.abs(diff) > s.params.threshold || allowThresholdMove) {
+                    if (!allowThresholdMove) {
+                        allowThresholdMove = true;
+                        s.touches.startX = s.touches.currentX;
+                        s.touches.startY = s.touches.currentY;
+                        currentTranslate = startTranslate;
+                        s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
+                        return;
+                    }
+                }
+                else {
+                    currentTranslate = startTranslate;
+                    return;
+                }
+            }
+            // Update active index in free mode
+            if (s.params.freeMode || s.params.watchSlidesProgress) {
+                s.updateActiveIndex();
+            }
+            if (s.params.freeMode) {
+                //Velocity
+                if (velocities.length === 0) {
+                    velocities.push({
+                        position: s.touches[s.isHorizontal() ? 'startX' : 'startY'],
+                        time: touchStartTime
+                    });
+                }
+                velocities.push({
+                    position: s.touches[s.isHorizontal() ? 'currentX' : 'currentY'],
+                    time: (new window.Date()).getTime()
+                });
+            }
+            // Update progress
+            s.updateProgress(currentTranslate);
+            // Update translate
+            s.setWrapperTranslate(currentTranslate);
+        };
+        s.onTouchEnd = function (e) {
+            if (e.originalEvent) e = e.originalEvent;
+            if (allowTouchCallbacks) {
+                s.emit('onTouchEnd', s, e);
+            }
+            allowTouchCallbacks = false;
+            if (!isTouched) return;
+            //Return Grab Cursor
+            if (s.params.grabCursor && isMoved && isTouched) {
+                s.container[0].style.cursor = 'move';
+                s.container[0].style.cursor = '-webkit-grab';
+                s.container[0].style.cursor = '-moz-grab';
+                s.container[0].style.cursor = 'grab';
+            }
+        
+            // Time diff
+            var touchEndTime = Date.now();
+            var timeDiff = touchEndTime - touchStartTime;
+        
+            // Tap, doubleTap, Click
+            if (s.allowClick) {
+                s.updateClickedSlide(e);
+                s.emit('onTap', s, e);
+                if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) {
+                    if (clickTimeout) clearTimeout(clickTimeout);
+                    clickTimeout = setTimeout(function () {
+                        if (!s) return;
+                        if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) {
+                            s.paginationContainer.toggleClass(s.params.paginationHiddenClass);
+                        }
+                        s.emit('onClick', s, e);
+                    }, 300);
+        
+                }
+                if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) {
+                    if (clickTimeout) clearTimeout(clickTimeout);
+                    s.emit('onDoubleTap', s, e);
+                }
+            }
+        
+            lastClickTime = Date.now();
+            setTimeout(function () {
+                if (s) s.allowClick = true;
+            }, 0);
+        
+            if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) {
+                isTouched = isMoved = false;
+                return;
+            }
+            isTouched = isMoved = false;
+        
+            var currentPos;
+            if (s.params.followFinger) {
+                currentPos = s.rtl ? s.translate : -s.translate;
+            }
+            else {
+                currentPos = -currentTranslate;
+            }
+            if (s.params.freeMode) {
+                if (currentPos < -s.minTranslate()) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                else if (currentPos > -s.maxTranslate()) {
+                    if (s.slides.length < s.snapGrid.length) {
+                        s.slideTo(s.snapGrid.length - 1);
+                    }
+                    else {
+                        s.slideTo(s.slides.length - 1);
+                    }
+                    return;
+                }
+        
+                if (s.params.freeModeMomentum) {
+                    if (velocities.length > 1) {
+                        var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop();
+        
+                        var distance = lastMoveEvent.position - velocityEvent.position;
+                        var time = lastMoveEvent.time - velocityEvent.time;
+                        s.velocity = distance / time;
+                        s.velocity = s.velocity / 2;
+                        if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) {
+                            s.velocity = 0;
+                        }
+                        // this implies that the user stopped moving a finger then released.
+                        // There would be no events with distance zero, so the last event is stale.
+                        if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) {
+                            s.velocity = 0;
+                        }
+                    } else {
+                        s.velocity = 0;
+                    }
+        
+                    velocities.length = 0;
+                    var momentumDuration = 1000 * s.params.freeModeMomentumRatio;
+                    var momentumDistance = s.velocity * momentumDuration;
+        
+                    var newPosition = s.translate + momentumDistance;
+                    if (s.rtl) newPosition = - newPosition;
+                    var doBounce = false;
+                    var afterBouncePosition;
+                    var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio;
+                    if (newPosition < s.maxTranslate()) {
+                        if (s.params.freeModeMomentumBounce) {
+                            if (newPosition + s.maxTranslate() < -bounceAmount) {
+                                newPosition = s.maxTranslate() - bounceAmount;
+                            }
+                            afterBouncePosition = s.maxTranslate();
+                            doBounce = true;
+                            allowMomentumBounce = true;
+                        }
+                        else {
+                            newPosition = s.maxTranslate();
+                        }
+                    }
+                    else if (newPosition > s.minTranslate()) {
+                        if (s.params.freeModeMomentumBounce) {
+                            if (newPosition - s.minTranslate() > bounceAmount) {
+                                newPosition = s.minTranslate() + bounceAmount;
+                            }
+                            afterBouncePosition = s.minTranslate();
+                            doBounce = true;
+                            allowMomentumBounce = true;
+                        }
+                        else {
+                            newPosition = s.minTranslate();
+                        }
+                    }
+                    else if (s.params.freeModeSticky) {
+                        var j = 0,
+                            nextSlide;
+                        for (j = 0; j < s.snapGrid.length; j += 1) {
+                            if (s.snapGrid[j] > -newPosition) {
+                                nextSlide = j;
+                                break;
+                            }
+        
+                        }
+                        if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') {
+                            newPosition = s.snapGrid[nextSlide];
+                        } else {
+                            newPosition = s.snapGrid[nextSlide - 1];
+                        }
+                        if (!s.rtl) newPosition = - newPosition;
+                    }
+                    //Fix duration
+                    if (s.velocity !== 0) {
+                        if (s.rtl) {
+                            momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity);
+                        }
+                        else {
+                            momentumDuration = Math.abs((newPosition - s.translate) / s.velocity);
+                        }
+                    }
+                    else if (s.params.freeModeSticky) {
+                        s.slideReset();
+                        return;
+                    }
+        
+                    if (s.params.freeModeMomentumBounce && doBounce) {
+                        s.updateProgress(afterBouncePosition);
+                        s.setWrapperTransition(momentumDuration);
+                        s.setWrapperTranslate(newPosition);
+                        s.onTransitionStart();
+                        s.animating = true;
+                        s.wrapper.transitionEnd(function () {
+                            if (!s || !allowMomentumBounce) return;
+                            s.emit('onMomentumBounce', s);
+        
+                            s.setWrapperTransition(s.params.speed);
+                            s.setWrapperTranslate(afterBouncePosition);
+                            s.wrapper.transitionEnd(function () {
+                                if (!s) return;
+                                s.onTransitionEnd();
+                            });
+                        });
+                    } else if (s.velocity) {
+                        s.updateProgress(newPosition);
+                        s.setWrapperTransition(momentumDuration);
+                        s.setWrapperTranslate(newPosition);
+                        s.onTransitionStart();
+                        if (!s.animating) {
+                            s.animating = true;
+                            s.wrapper.transitionEnd(function () {
+                                if (!s) return;
+                                s.onTransitionEnd();
+                            });
+                        }
+        
+                    } else {
+                        s.updateProgress(newPosition);
+                    }
+        
+                    s.updateActiveIndex();
+                }
+                if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) {
+                    s.updateProgress();
+                    s.updateActiveIndex();
+                }
+                return;
+            }
+        
+            // Find current slide
+            var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0];
+            for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) {
+                if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') {
+                    if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) {
+                        stopIndex = i;
+                        groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i];
+                    }
+                }
+                else {
+                    if (currentPos >= s.slidesGrid[i]) {
+                        stopIndex = i;
+                        groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2];
+                    }
+                }
+            }
+        
+            // Find current slide size
+            var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize;
+        
+            if (timeDiff > s.params.longSwipesMs) {
+                // Long touches
+                if (!s.params.longSwipes) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                if (s.swipeDirection === 'next') {
+                    if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup);
+                    else s.slideTo(stopIndex);
+        
+                }
+                if (s.swipeDirection === 'prev') {
+                    if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup);
+                    else s.slideTo(stopIndex);
+                }
+            }
+            else {
+                // Short swipes
+                if (!s.params.shortSwipes) {
+                    s.slideTo(s.activeIndex);
+                    return;
+                }
+                if (s.swipeDirection === 'next') {
+                    s.slideTo(stopIndex + s.params.slidesPerGroup);
+        
+                }
+                if (s.swipeDirection === 'prev') {
+                    s.slideTo(stopIndex);
+                }
+            }
+        };
+        /*=========================
+          Transitions
+          ===========================*/
+        s._slideTo = function (slideIndex, speed) {
+            return s.slideTo(slideIndex, speed, true, true);
+        };
+        s.slideTo = function (slideIndex, speed, runCallbacks, internal) {
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (typeof slideIndex === 'undefined') slideIndex = 0;
+            if (slideIndex < 0) slideIndex = 0;
+            s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup);
+            if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1;
+        
+            var translate = - s.snapGrid[s.snapIndex];
+            // Stop autoplay
+            if (s.params.autoplay && s.autoplaying) {
+                if (internal || !s.params.autoplayDisableOnInteraction) {
+                    s.pauseAutoplay(speed);
+                }
+                else {
+                    s.stopAutoplay();
+                }
+            }
+            // Update progress
+            s.updateProgress(translate);
+        
+            // Normalize slideIndex
+            for (var i = 0; i < s.slidesGrid.length; i++) {
+                if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) {
+                    slideIndex = i;
+                }
+            }
+        
+            // Directions locks
+            if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) {
+                return false;
+            }
+            if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) {
+                if ((s.activeIndex || 0) !== slideIndex ) return false;
+            }
+        
+            // Update Index
+            if (typeof speed === 'undefined') speed = s.params.speed;
+            s.previousIndex = s.activeIndex || 0;
+            s.activeIndex = slideIndex;
+        
+            if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) {
+                // Update Height
+                if (s.params.autoHeight) {
+                    s.updateAutoHeight();
+                }
+                s.updateClasses();
+                if (s.params.effect !== 'slide') {
+                    s.setWrapperTranslate(translate);
+                }
+                return false;
+            }
+            s.updateClasses();
+            s.onTransitionStart(runCallbacks);
+        
+            if (speed === 0) {
+                s.setWrapperTranslate(translate);
+                s.setWrapperTransition(0);
+                s.onTransitionEnd(runCallbacks);
+            }
+            else {
+                s.setWrapperTranslate(translate);
+                s.setWrapperTransition(speed);
+                if (!s.animating) {
+                    s.animating = true;
+                    s.wrapper.transitionEnd(function () {
+                        if (!s) return;
+                        s.onTransitionEnd(runCallbacks);
+                    });
+                }
+        
+            }
+        
+            return true;
+        };
+        
+        s.onTransitionStart = function (runCallbacks) {
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (s.params.autoHeight) {
+                s.updateAutoHeight();
+            }
+            if (s.lazy) s.lazy.onTransitionStart();
+            if (runCallbacks) {
+                s.emit('onTransitionStart', s);
+                if (s.activeIndex !== s.previousIndex) {
+                    s.emit('onSlideChangeStart', s);
+                    if (s.activeIndex > s.previousIndex) {
+                        s.emit('onSlideNextStart', s);
+                    }
+                    else {
+                        s.emit('onSlidePrevStart', s);
+                    }
+                }
+        
+            }
+        };
+        s.onTransitionEnd = function (runCallbacks) {
+            s.animating = false;
+            s.setWrapperTransition(0);
+            if (typeof runCallbacks === 'undefined') runCallbacks = true;
+            if (s.lazy) s.lazy.onTransitionEnd();
+            if (runCallbacks) {
+                s.emit('onTransitionEnd', s);
+                if (s.activeIndex !== s.previousIndex) {
+                    s.emit('onSlideChangeEnd', s);
+                    if (s.activeIndex > s.previousIndex) {
+                        s.emit('onSlideNextEnd', s);
+                    }
+                    else {
+                        s.emit('onSlidePrevEnd', s);
+                    }
+                }
+            }
+            if (s.params.hashnav && s.hashnav) {
+                s.hashnav.setHash();
+            }
+        
+        };
+        s.slideNext = function (runCallbacks, speed, internal) {
+            if (s.params.loop) {
+                if (s.animating) return false;
+                s.fixLoop();
+                var clientLeft = s.container[0].clientLeft;
+                return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
+            }
+            else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
+        };
+        s._slideNext = function (speed) {
+            return s.slideNext(true, speed, true);
+        };
+        s.slidePrev = function (runCallbacks, speed, internal) {
+            if (s.params.loop) {
+                if (s.animating) return false;
+                s.fixLoop();
+                var clientLeft = s.container[0].clientLeft;
+                return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
+            }
+            else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
+        };
+        s._slidePrev = function (speed) {
+            return s.slidePrev(true, speed, true);
+        };
+        s.slideReset = function (runCallbacks, speed, internal) {
+            return s.slideTo(s.activeIndex, speed, runCallbacks);
+        };
+        
+        /*=========================
+          Translate/transition helpers
+          ===========================*/
+        s.setWrapperTransition = function (duration, byController) {
+            s.wrapper.transition(duration);
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                s.effects[s.params.effect].setTransition(duration);
+            }
+            if (s.params.parallax && s.parallax) {
+                s.parallax.setTransition(duration);
+            }
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.setTransition(duration);
+            }
+            if (s.params.control && s.controller) {
+                s.controller.setTransition(duration, byController);
+            }
+            s.emit('onSetTransition', s, duration);
+        };
+        s.setWrapperTranslate = function (translate, updateActiveIndex, byController) {
+            var x = 0, y = 0, z = 0;
+            if (s.isHorizontal()) {
+                x = s.rtl ? -translate : translate;
+            }
+            else {
+                y = translate;
+            }
+        
+            if (s.params.roundLengths) {
+                x = round(x);
+                y = round(y);
+            }
+        
+            if (!s.params.virtualTranslate) {
+                if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)');
+                else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)');
+            }
+        
+            s.translate = s.isHorizontal() ? x : y;
+        
+            // Check if we need to update progress
+            var progress;
+            var translatesDiff = s.maxTranslate() - s.minTranslate();
+            if (translatesDiff === 0) {
+                progress = 0;
+            }
+            else {
+                progress = (translate - s.minTranslate()) / (translatesDiff);
+            }
+            if (progress !== s.progress) {
+                s.updateProgress(translate);
+            }
+        
+            if (updateActiveIndex) s.updateActiveIndex();
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                s.effects[s.params.effect].setTranslate(s.translate);
+            }
+            if (s.params.parallax && s.parallax) {
+                s.parallax.setTranslate(s.translate);
+            }
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.setTranslate(s.translate);
+            }
+            if (s.params.control && s.controller) {
+                s.controller.setTranslate(s.translate, byController);
+            }
+            s.emit('onSetTranslate', s, s.translate);
+        };
+        
+        s.getTranslate = function (el, axis) {
+            var matrix, curTransform, curStyle, transformMatrix;
+        
+            // automatic axis detection
+            if (typeof axis === 'undefined') {
+                axis = 'x';
+            }
+        
+            if (s.params.virtualTranslate) {
+                return s.rtl ? -s.translate : s.translate;
+            }
+        
+            curStyle = window.getComputedStyle(el, null);
+            if (window.WebKitCSSMatrix) {
+                curTransform = curStyle.transform || curStyle.webkitTransform;
+                if (curTransform.split(',').length > 6) {
+                    curTransform = curTransform.split(', ').map(function(a){
+                        return a.replace(',','.');
+                    }).join(', ');
+                }
+                // Some old versions of Webkit choke when 'none' is passed; pass
+                // empty string instead in this case
+                transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
+            }
+            else {
+                transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
+                matrix = transformMatrix.toString().split(',');
+            }
+        
+            if (axis === 'x') {
+                //Latest Chrome and webkits Fix
+                if (window.WebKitCSSMatrix)
+                    curTransform = transformMatrix.m41;
+                //Crazy IE10 Matrix
+                else if (matrix.length === 16)
+                    curTransform = parseFloat(matrix[12]);
+                //Normal Browsers
+                else
+                    curTransform = parseFloat(matrix[4]);
+            }
+            if (axis === 'y') {
+                //Latest Chrome and webkits Fix
+                if (window.WebKitCSSMatrix)
+                    curTransform = transformMatrix.m42;
+                //Crazy IE10 Matrix
+                else if (matrix.length === 16)
+                    curTransform = parseFloat(matrix[13]);
+                //Normal Browsers
+                else
+                    curTransform = parseFloat(matrix[5]);
+            }
+            if (s.rtl && curTransform) curTransform = -curTransform;
+            return curTransform || 0;
+        };
+        s.getWrapperTranslate = function (axis) {
+            if (typeof axis === 'undefined') {
+                axis = s.isHorizontal() ? 'x' : 'y';
+            }
+            return s.getTranslate(s.wrapper[0], axis);
+        };
+        
+        /*=========================
+          Observer
+          ===========================*/
+        s.observers = [];
+        function initObserver(target, options) {
+            options = options || {};
+            // create an observer instance
+            var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
+            var observer = new ObserverFunc(function (mutations) {
+                mutations.forEach(function (mutation) {
+                    s.onResize(true);
+                    s.emit('onObserverUpdate', s, mutation);
+                });
+            });
+        
+            observer.observe(target, {
+                attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
+                childList: typeof options.childList === 'undefined' ? true : options.childList,
+                characterData: typeof options.characterData === 'undefined' ? true : options.characterData
+            });
+        
+            s.observers.push(observer);
+        }
+        s.initObservers = function () {
+            if (s.params.observeParents) {
+                var containerParents = s.container.parents();
+                for (var i = 0; i < containerParents.length; i++) {
+                    initObserver(containerParents[i]);
+                }
+            }
+        
+            // Observe container
+            initObserver(s.container[0], {childList: false});
+        
+            // Observe wrapper
+            initObserver(s.wrapper[0], {attributes: false});
+        };
+        s.disconnectObservers = function () {
+            for (var i = 0; i < s.observers.length; i++) {
+                s.observers[i].disconnect();
+            }
+            s.observers = [];
+        };
+        /*=========================
+          Loop
+          ===========================*/
+        // Create looped slides
+        s.createLoop = function () {
+            // Remove duplicated slides
+            s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
+        
+            var slides = s.wrapper.children('.' + s.params.slideClass);
+        
+            if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length;
+        
+            s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10);
+            s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides;
+            if (s.loopedSlides > slides.length) {
+                s.loopedSlides = slides.length;
+            }
+        
+            var prependSlides = [], appendSlides = [], i;
+            slides.each(function (index, el) {
+                var slide = $(this);
+                if (index < s.loopedSlides) appendSlides.push(el);
+                if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el);
+                slide.attr('data-swiper-slide-index', index);
+            });
+            for (i = 0; i < appendSlides.length; i++) {
+                s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
+            }
+            for (i = prependSlides.length - 1; i >= 0; i--) {
+                s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
+            }
+        };
+        s.destroyLoop = function () {
+            s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
+            s.slides.removeAttr('data-swiper-slide-index');
+        };
+        s.reLoop = function (updatePosition) {
+            var oldIndex = s.activeIndex - s.loopedSlides;
+            s.destroyLoop();
+            s.createLoop();
+            s.updateSlidesSize();
+            if (updatePosition) {
+                s.slideTo(oldIndex + s.loopedSlides, 0, false);
+            }
+        
+        };
+        s.fixLoop = function () {
+            var newIndex;
+            //Fix For Negative Oversliding
+            if (s.activeIndex < s.loopedSlides) {
+                newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex;
+                newIndex = newIndex + s.loopedSlides;
+                s.slideTo(newIndex, 0, false, true);
+            }
+            //Fix For Positive Oversliding
+            else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) {
+                newIndex = -s.slides.length + s.activeIndex + s.loopedSlides;
+                newIndex = newIndex + s.loopedSlides;
+                s.slideTo(newIndex, 0, false, true);
+            }
+        };
+        /*=========================
+          Append/Prepend/Remove Slides
+          ===========================*/
+        s.appendSlide = function (slides) {
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            if (typeof slides === 'object' && slides.length) {
+                for (var i = 0; i < slides.length; i++) {
+                    if (slides[i]) s.wrapper.append(slides[i]);
+                }
+            }
+            else {
+                s.wrapper.append(slides);
+            }
+            if (s.params.loop) {
+                s.createLoop();
+            }
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+        };
+        s.prependSlide = function (slides) {
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            var newActiveIndex = s.activeIndex + 1;
+            if (typeof slides === 'object' && slides.length) {
+                for (var i = 0; i < slides.length; i++) {
+                    if (slides[i]) s.wrapper.prepend(slides[i]);
+                }
+                newActiveIndex = s.activeIndex + slides.length;
+            }
+            else {
+                s.wrapper.prepend(slides);
+            }
+            if (s.params.loop) {
+                s.createLoop();
+            }
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+            s.slideTo(newActiveIndex, 0, false);
+        };
+        s.removeSlide = function (slidesIndexes) {
+            if (s.params.loop) {
+                s.destroyLoop();
+                s.slides = s.wrapper.children('.' + s.params.slideClass);
+            }
+            var newActiveIndex = s.activeIndex,
+                indexToRemove;
+            if (typeof slidesIndexes === 'object' && slidesIndexes.length) {
+                for (var i = 0; i < slidesIndexes.length; i++) {
+                    indexToRemove = slidesIndexes[i];
+                    if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
+                    if (indexToRemove < newActiveIndex) newActiveIndex--;
+                }
+                newActiveIndex = Math.max(newActiveIndex, 0);
+            }
+            else {
+                indexToRemove = slidesIndexes;
+                if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
+                if (indexToRemove < newActiveIndex) newActiveIndex--;
+                newActiveIndex = Math.max(newActiveIndex, 0);
+            }
+        
+            if (s.params.loop) {
+                s.createLoop();
+            }
+        
+            if (!(s.params.observer && s.support.observer)) {
+                s.update(true);
+            }
+            if (s.params.loop) {
+                s.slideTo(newActiveIndex + s.loopedSlides, 0, false);
+            }
+            else {
+                s.slideTo(newActiveIndex, 0, false);
+            }
+        
+        };
+        s.removeAllSlides = function () {
+            var slidesIndexes = [];
+            for (var i = 0; i < s.slides.length; i++) {
+                slidesIndexes.push(i);
+            }
+            s.removeSlide(slidesIndexes);
+        };
+        
+
+        /*=========================
+          Effects
+          ===========================*/
+        s.effects = {
+            fade: {
+                setTranslate: function () {
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var offset = slide[0].swiperSlideOffset;
+                        var tx = -offset;
+                        if (!s.params.virtualTranslate) tx = tx - s.translate;
+                        var ty = 0;
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                        }
+                        var slideOpacity = s.params.fade.crossFade ?
+                                Math.max(1 - Math.abs(slide[0].progress), 0) :
+                                1 + Math.min(Math.max(slide[0].progress, -1), 0);
+                        slide
+                            .css({
+                                opacity: slideOpacity
+                            })
+                            .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)');
+        
+                    }
+        
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration);
+                    if (s.params.virtualTranslate && duration !== 0) {
+                        var eventTriggered = false;
+                        s.slides.transitionEnd(function () {
+                            if (eventTriggered) return;
+                            if (!s) return;
+                            eventTriggered = true;
+                            s.animating = false;
+                            var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
+                            for (var i = 0; i < triggerEvents.length; i++) {
+                                s.wrapper.trigger(triggerEvents[i]);
+                            }
+                        });
+                    }
+                }
+            },
+            flip: {
+                setTranslate: function () {
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var progress = slide[0].progress;
+                        if (s.params.flip.limitRotation) {
+                            progress = Math.max(Math.min(slide[0].progress, 1), -1);
+                        }
+                        var offset = slide[0].swiperSlideOffset;
+                        var rotate = -180 * progress,
+                            rotateY = rotate,
+                            rotateX = 0,
+                            tx = -offset,
+                            ty = 0;
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                            rotateX = -rotateY;
+                            rotateY = 0;
+                        }
+                        else if (s.rtl) {
+                            rotateY = -rotateY;
+                        }
+        
+                        slide[0].style.zIndex = -Math.abs(Math.round(progress)) + s.slides.length;
+        
+                        if (s.params.flip.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
+                        }
+        
+                        slide
+                            .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)');
+                    }
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                    if (s.params.virtualTranslate && duration !== 0) {
+                        var eventTriggered = false;
+                        s.slides.eq(s.activeIndex).transitionEnd(function () {
+                            if (eventTriggered) return;
+                            if (!s) return;
+                            if (!$(this).hasClass(s.params.slideActiveClass)) return;
+                            eventTriggered = true;
+                            s.animating = false;
+                            var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
+                            for (var i = 0; i < triggerEvents.length; i++) {
+                                s.wrapper.trigger(triggerEvents[i]);
+                            }
+                        });
+                    }
+                }
+            },
+            cube: {
+                setTranslate: function () {
+                    var wrapperRotate = 0, cubeShadow;
+                    if (s.params.cube.shadow) {
+                        if (s.isHorizontal()) {
+                            cubeShadow = s.wrapper.find('.swiper-cube-shadow');
+                            if (cubeShadow.length === 0) {
+                                cubeShadow = $('<div class="swiper-cube-shadow"></div>');
+                                s.wrapper.append(cubeShadow);
+                            }
+                            cubeShadow.css({height: s.width + 'px'});
+                        }
+                        else {
+                            cubeShadow = s.container.find('.swiper-cube-shadow');
+                            if (cubeShadow.length === 0) {
+                                cubeShadow = $('<div class="swiper-cube-shadow"></div>');
+                                s.container.append(cubeShadow);
+                            }
+                        }
+                    }
+                    for (var i = 0; i < s.slides.length; i++) {
+                        var slide = s.slides.eq(i);
+                        var slideAngle = i * 90;
+                        var round = Math.floor(slideAngle / 360);
+                        if (s.rtl) {
+                            slideAngle = -slideAngle;
+                            round = Math.floor(-slideAngle / 360);
+                        }
+                        var progress = Math.max(Math.min(slide[0].progress, 1), -1);
+                        var tx = 0, ty = 0, tz = 0;
+                        if (i % 4 === 0) {
+                            tx = - round * 4 * s.size;
+                            tz = 0;
+                        }
+                        else if ((i - 1) % 4 === 0) {
+                            tx = 0;
+                            tz = - round * 4 * s.size;
+                        }
+                        else if ((i - 2) % 4 === 0) {
+                            tx = s.size + round * 4 * s.size;
+                            tz = s.size;
+                        }
+                        else if ((i - 3) % 4 === 0) {
+                            tx = - s.size;
+                            tz = 3 * s.size + s.size * 4 * round;
+                        }
+                        if (s.rtl) {
+                            tx = -tx;
+                        }
+        
+                        if (!s.isHorizontal()) {
+                            ty = tx;
+                            tx = 0;
+                        }
+        
+                        var transform = 'rotateX(' + (s.isHorizontal() ? 0 : -slideAngle) + 'deg) rotateY(' + (s.isHorizontal() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)';
+                        if (progress <= 1 && progress > -1) {
+                            wrapperRotate = i * 90 + progress * 90;
+                            if (s.rtl) wrapperRotate = -i * 90 - progress * 90;
+                        }
+                        slide.transform(transform);
+                        if (s.params.cube.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
+                        }
+                    }
+                    s.wrapper.css({
+                        '-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        '-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        '-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
+                        'transform-origin': '50% 50% -' + (s.size / 2) + 'px'
+                    });
+        
+                    if (s.params.cube.shadow) {
+                        if (s.isHorizontal()) {
+                            cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')');
+                        }
+                        else {
+                            var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
+                            var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
+                            var scale1 = s.params.cube.shadowScale,
+                                scale2 = s.params.cube.shadowScale / multiplier,
+                                offset = s.params.cube.shadowOffset;
+                            cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)');
+                        }
+                    }
+                    var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0;
+                    s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (s.isHorizontal() ? 0 : wrapperRotate) + 'deg) rotateY(' + (s.isHorizontal() ? -wrapperRotate : 0) + 'deg)');
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                    if (s.params.cube.shadow && !s.isHorizontal()) {
+                        s.container.find('.swiper-cube-shadow').transition(duration);
+                    }
+                }
+            },
+            coverflow: {
+                setTranslate: function () {
+                    var transform = s.translate;
+                    var center = s.isHorizontal() ? -transform + s.width / 2 : -transform + s.height / 2;
+                    var rotate = s.isHorizontal() ? s.params.coverflow.rotate: -s.params.coverflow.rotate;
+                    var translate = s.params.coverflow.depth;
+                    //Each slide offset from center
+                    for (var i = 0, length = s.slides.length; i < length; i++) {
+                        var slide = s.slides.eq(i);
+                        var slideSize = s.slidesSizesGrid[i];
+                        var slideOffset = slide[0].swiperSlideOffset;
+                        var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier;
+        
+                        var rotateY = s.isHorizontal() ? rotate * offsetMultiplier : 0;
+                        var rotateX = s.isHorizontal() ? 0 : rotate * offsetMultiplier;
+                        // var rotateZ = 0
+                        var translateZ = -translate * Math.abs(offsetMultiplier);
+        
+                        var translateY = s.isHorizontal() ? 0 : s.params.coverflow.stretch * (offsetMultiplier);
+                        var translateX = s.isHorizontal() ? s.params.coverflow.stretch * (offsetMultiplier) : 0;
+        
+                        //Fix for ultra small values
+                        if (Math.abs(translateX) < 0.001) translateX = 0;
+                        if (Math.abs(translateY) < 0.001) translateY = 0;
+                        if (Math.abs(translateZ) < 0.001) translateZ = 0;
+                        if (Math.abs(rotateY) < 0.001) rotateY = 0;
+                        if (Math.abs(rotateX) < 0.001) rotateX = 0;
+        
+                        var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px)  rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)';
+        
+                        slide.transform(slideTransform);
+                        slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
+                        if (s.params.coverflow.slideShadows) {
+                            //Set shadows
+                            var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
+                            var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
+                            if (shadowBefore.length === 0) {
+                                shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
+                                slide.append(shadowBefore);
+                            }
+                            if (shadowAfter.length === 0) {
+                                shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
+                                slide.append(shadowAfter);
+                            }
+                            if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
+                            if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0;
+                        }
+                    }
+        
+                    //Set correct perspective for IE10
+                    if (s.browser.ie) {
+                        var ws = s.wrapper[0].style;
+                        ws.perspectiveOrigin = center + 'px 50%';
+                    }
+                },
+                setTransition: function (duration) {
+                    s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
+                }
+            }
+        };
+
+        /*=========================
+          Images Lazy Loading
+          ===========================*/
+        s.lazy = {
+            initialImageLoaded: false,
+            loadImageInSlide: function (index, loadInDuplicate) {
+                if (typeof index === 'undefined') return;
+                if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true;
+                if (s.slides.length === 0) return;
+        
+                var slide = s.slides.eq(index);
+                var img = slide.find('.swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)');
+                if (slide.hasClass('swiper-lazy') && !slide.hasClass('swiper-lazy-loaded') && !slide.hasClass('swiper-lazy-loading')) {
+                    img = img.add(slide[0]);
+                }
+                if (img.length === 0) return;
+        
+                img.each(function () {
+                    var _img = $(this);
+                    _img.addClass('swiper-lazy-loading');
+                    var background = _img.attr('data-background');
+                    var src = _img.attr('data-src'),
+                        srcset = _img.attr('data-srcset');
+                    s.loadImage(_img[0], (src || background), srcset, false, function () {
+                        if (background) {
+                            _img.css('background-image', 'url("' + background + '")');
+                            _img.removeAttr('data-background');
+                        }
+                        else {
+                            if (srcset) {
+                                _img.attr('srcset', srcset);
+                                _img.removeAttr('data-srcset');
+                            }
+                            if (src) {
+                                _img.attr('src', src);
+                                _img.removeAttr('data-src');
+                            }
+        
+                        }
+        
+                        _img.addClass('swiper-lazy-loaded').removeClass('swiper-lazy-loading');
+                        slide.find('.swiper-lazy-preloader, .preloader').remove();
+                        if (s.params.loop && loadInDuplicate) {
+                            var slideOriginalIndex = slide.attr('data-swiper-slide-index');
+                            if (slide.hasClass(s.params.slideDuplicateClass)) {
+                                var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')');
+                                s.lazy.loadImageInSlide(originalSlide.index(), false);
+                            }
+                            else {
+                                var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]');
+                                s.lazy.loadImageInSlide(duplicatedSlide.index(), false);
+                            }
+                        }
+                        s.emit('onLazyImageReady', s, slide[0], _img[0]);
+                    });
+        
+                    s.emit('onLazyImageLoad', s, slide[0], _img[0]);
+                });
+        
+            },
+            load: function () {
+                var i;
+                if (s.params.watchSlidesVisibility) {
+                    s.wrapper.children('.' + s.params.slideVisibleClass).each(function () {
+                        s.lazy.loadImageInSlide($(this).index());
+                    });
+                }
+                else {
+                    if (s.params.slidesPerView > 1) {
+                        for (i = s.activeIndex; i < s.activeIndex + s.params.slidesPerView ; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                    }
+                    else {
+                        s.lazy.loadImageInSlide(s.activeIndex);
+                    }
+                }
+                if (s.params.lazyLoadingInPrevNext) {
+                    if (s.params.slidesPerView > 1 || (s.params.lazyLoadingInPrevNextAmount && s.params.lazyLoadingInPrevNextAmount > 1)) {
+                        var amount = s.params.lazyLoadingInPrevNextAmount;
+                        var spv = s.params.slidesPerView;
+                        var maxIndex = Math.min(s.activeIndex + spv + Math.max(amount, spv), s.slides.length);
+                        var minIndex = Math.max(s.activeIndex - Math.max(spv, amount), 0);
+                        // Next Slides
+                        for (i = s.activeIndex + s.params.slidesPerView; i < maxIndex; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                        // Prev Slides
+                        for (i = minIndex; i < s.activeIndex ; i++) {
+                            if (s.slides[i]) s.lazy.loadImageInSlide(i);
+                        }
+                    }
+                    else {
+                        var nextSlide = s.wrapper.children('.' + s.params.slideNextClass);
+                        if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index());
+        
+                        var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass);
+                        if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index());
+                    }
+                }
+            },
+            onTransitionStart: function () {
+                if (s.params.lazyLoading) {
+                    if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) {
+                        s.lazy.load();
+                    }
+                }
+            },
+            onTransitionEnd: function () {
+                if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) {
+                    s.lazy.load();
+                }
+            }
+        };
+        
+
+        /*=========================
+          Scrollbar
+          ===========================*/
+        s.scrollbar = {
+            isTouched: false,
+            setDragPosition: function (e) {
+                var sb = s.scrollbar;
+                var x = 0, y = 0;
+                var translate;
+                var pointerPosition = s.isHorizontal() ?
+                    ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) :
+                    ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ;
+                var position = (pointerPosition) - sb.track.offset()[s.isHorizontal() ? 'left' : 'top'] - sb.dragSize / 2;
+                var positionMin = -s.minTranslate() * sb.moveDivider;
+                var positionMax = -s.maxTranslate() * sb.moveDivider;
+                if (position < positionMin) {
+                    position = positionMin;
+                }
+                else if (position > positionMax) {
+                    position = positionMax;
+                }
+                position = -position / sb.moveDivider;
+                s.updateProgress(position);
+                s.setWrapperTranslate(position, true);
+            },
+            dragStart: function (e) {
+                var sb = s.scrollbar;
+                sb.isTouched = true;
+                e.preventDefault();
+                e.stopPropagation();
+        
+                sb.setDragPosition(e);
+                clearTimeout(sb.dragTimeout);
+        
+                sb.track.transition(0);
+                if (s.params.scrollbarHide) {
+                    sb.track.css('opacity', 1);
+                }
+                s.wrapper.transition(100);
+                sb.drag.transition(100);
+                s.emit('onScrollbarDragStart', s);
+            },
+            dragMove: function (e) {
+                var sb = s.scrollbar;
+                if (!sb.isTouched) return;
+                if (e.preventDefault) e.preventDefault();
+                else e.returnValue = false;
+                sb.setDragPosition(e);
+                s.wrapper.transition(0);
+                sb.track.transition(0);
+                sb.drag.transition(0);
+                s.emit('onScrollbarDragMove', s);
+            },
+            dragEnd: function (e) {
+                var sb = s.scrollbar;
+                if (!sb.isTouched) return;
+                sb.isTouched = false;
+                if (s.params.scrollbarHide) {
+                    clearTimeout(sb.dragTimeout);
+                    sb.dragTimeout = setTimeout(function () {
+                        sb.track.css('opacity', 0);
+                        sb.track.transition(400);
+                    }, 1000);
+        
+                }
+                s.emit('onScrollbarDragEnd', s);
+                if (s.params.scrollbarSnapOnRelease) {
+                    s.slideReset();
+                }
+            },
+            enableDraggable: function () {
+                var sb = s.scrollbar;
+                var target = s.support.touch ? sb.track : document;
+                $(sb.track).on(s.touchEvents.start, sb.dragStart);
+                $(target).on(s.touchEvents.move, sb.dragMove);
+                $(target).on(s.touchEvents.end, sb.dragEnd);
+            },
+            disableDraggable: function () {
+                var sb = s.scrollbar;
+                var target = s.support.touch ? sb.track : document;
+                $(sb.track).off(s.touchEvents.start, sb.dragStart);
+                $(target).off(s.touchEvents.move, sb.dragMove);
+                $(target).off(s.touchEvents.end, sb.dragEnd);
+            },
+            set: function () {
+                if (!s.params.scrollbar) return;
+                var sb = s.scrollbar;
+                sb.track = $(s.params.scrollbar);
+                if (s.params.uniqueNavElements && typeof s.params.scrollbar === 'string' && sb.track.length > 1 && s.container.find(s.params.scrollbar).length === 1) {
+                    sb.track = s.container.find(s.params.scrollbar);
+                }
+                sb.drag = sb.track.find('.swiper-scrollbar-drag');
+                if (sb.drag.length === 0) {
+                    sb.drag = $('<div class="swiper-scrollbar-drag"></div>');
+                    sb.track.append(sb.drag);
+                }
+                sb.drag[0].style.width = '';
+                sb.drag[0].style.height = '';
+                sb.trackSize = s.isHorizontal() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight;
+        
+                sb.divider = s.size / s.virtualSize;
+                sb.moveDivider = sb.divider * (sb.trackSize / s.size);
+                sb.dragSize = sb.trackSize * sb.divider;
+        
+                if (s.isHorizontal()) {
+                    sb.drag[0].style.width = sb.dragSize + 'px';
+                }
+                else {
+                    sb.drag[0].style.height = sb.dragSize + 'px';
+                }
+        
+                if (sb.divider >= 1) {
+                    sb.track[0].style.display = 'none';
+                }
+                else {
+                    sb.track[0].style.display = '';
+                }
+                if (s.params.scrollbarHide) {
+                    sb.track[0].style.opacity = 0;
+                }
+            },
+            setTranslate: function () {
+                if (!s.params.scrollbar) return;
+                var diff;
+                var sb = s.scrollbar;
+                var translate = s.translate || 0;
+                var newPos;
+        
+                var newSize = sb.dragSize;
+                newPos = (sb.trackSize - sb.dragSize) * s.progress;
+                if (s.rtl && s.isHorizontal()) {
+                    newPos = -newPos;
+                    if (newPos > 0) {
+                        newSize = sb.dragSize - newPos;
+                        newPos = 0;
+                    }
+                    else if (-newPos + sb.dragSize > sb.trackSize) {
+                        newSize = sb.trackSize + newPos;
+                    }
+                }
+                else {
+                    if (newPos < 0) {
+                        newSize = sb.dragSize + newPos;
+                        newPos = 0;
+                    }
+                    else if (newPos + sb.dragSize > sb.trackSize) {
+                        newSize = sb.trackSize - newPos;
+                    }
+                }
+                if (s.isHorizontal()) {
+                    if (s.support.transforms3d) {
+                        sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)');
+                    }
+                    else {
+                        sb.drag.transform('translateX(' + (newPos) + 'px)');
+                    }
+                    sb.drag[0].style.width = newSize + 'px';
+                }
+                else {
+                    if (s.support.transforms3d) {
+                        sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)');
+                    }
+                    else {
+                        sb.drag.transform('translateY(' + (newPos) + 'px)');
+                    }
+                    sb.drag[0].style.height = newSize + 'px';
+                }
+                if (s.params.scrollbarHide) {
+                    clearTimeout(sb.timeout);
+                    sb.track[0].style.opacity = 1;
+                    sb.timeout = setTimeout(function () {
+                        sb.track[0].style.opacity = 0;
+                        sb.track.transition(400);
+                    }, 1000);
+                }
+            },
+            setTransition: function (duration) {
+                if (!s.params.scrollbar) return;
+                s.scrollbar.drag.transition(duration);
+            }
+        };
+
+        /*=========================
+          Controller
+          ===========================*/
+        s.controller = {
+            LinearSpline: function (x, y) {
+                this.x = x;
+                this.y = y;
+                this.lastIndex = x.length - 1;
+                // Given an x value (x2), return the expected y2 value:
+                // (x1,y1) is the known point before given value,
+                // (x3,y3) is the known point after given value.
+                var i1, i3;
+                var l = this.x.length;
+        
+                this.interpolate = function (x2) {
+                    if (!x2) return 0;
+        
+                    // Get the indexes of x1 and x3 (the array indexes before and after given x2):
+                    i3 = binarySearch(this.x, x2);
+                    i1 = i3 - 1;
+        
+                    // We have our indexes i1 & i3, so we can calculate already:
+                    // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
+                    return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1];
+                };
+        
+                var binarySearch = (function() {
+                    var maxIndex, minIndex, guess;
+                    return function(array, val) {
+                        minIndex = -1;
+                        maxIndex = array.length;
+                        while (maxIndex - minIndex > 1)
+                            if (array[guess = maxIndex + minIndex >> 1] <= val) {
+                                minIndex = guess;
+                            } else {
+                                maxIndex = guess;
+                            }
+                        return maxIndex;
+                    };
+                })();
+            },
+            //xxx: for now i will just save one spline function to to
+            getInterpolateFunction: function(c){
+                if(!s.controller.spline) s.controller.spline = s.params.loop ?
+                    new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) :
+                    new s.controller.LinearSpline(s.snapGrid, c.snapGrid);
+            },
+            setTranslate: function (translate, byController) {
+               var controlled = s.params.control;
+               var multiplier, controlledTranslate;
+               function setControlledTranslate(c) {
+                    // this will create an Interpolate function based on the snapGrids
+                    // x is the Grid of the scrolled scroller and y will be the controlled scroller
+                    // it makes sense to create this only once and recall it for the interpolation
+                    // the function does a lot of value caching for performance
+                    translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate;
+                    if (s.params.controlBy === 'slide') {
+                        s.controller.getInterpolateFunction(c);
+                        // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
+                        // but it did not work out
+                        controlledTranslate = -s.controller.spline.interpolate(-translate);
+                    }
+        
+                    if(!controlledTranslate || s.params.controlBy === 'container'){
+                        multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate());
+                        controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate();
+                    }
+        
+                    if (s.params.controlInverse) {
+                        controlledTranslate = c.maxTranslate() - controlledTranslate;
+                    }
+                    c.updateProgress(controlledTranslate);
+                    c.setWrapperTranslate(controlledTranslate, false, s);
+                    c.updateActiveIndex();
+               }
+               if (s.isArray(controlled)) {
+                   for (var i = 0; i < controlled.length; i++) {
+                       if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
+                           setControlledTranslate(controlled[i]);
+                       }
+                   }
+               }
+               else if (controlled instanceof Swiper && byController !== controlled) {
+        
+                   setControlledTranslate(controlled);
+               }
+            },
+            setTransition: function (duration, byController) {
+                var controlled = s.params.control;
+                var i;
+                function setControlledTransition(c) {
+                    c.setWrapperTransition(duration, s);
+                    if (duration !== 0) {
+                        c.onTransitionStart();
+                        c.wrapper.transitionEnd(function(){
+                            if (!controlled) return;
+                            if (c.params.loop && s.params.controlBy === 'slide') {
+                                c.fixLoop();
+                            }
+                            c.onTransitionEnd();
+        
+                        });
+                    }
+                }
+                if (s.isArray(controlled)) {
+                    for (i = 0; i < controlled.length; i++) {
+                        if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
+                            setControlledTransition(controlled[i]);
+                        }
+                    }
+                }
+                else if (controlled instanceof Swiper && byController !== controlled) {
+                    setControlledTransition(controlled);
+                }
+            }
+        };
+
+        /*=========================
+          Hash Navigation
+          ===========================*/
+        s.hashnav = {
+            init: function () {
+                if (!s.params.hashnav) return;
+                s.hashnav.initialized = true;
+                var hash = document.location.hash.replace('#', '');
+                if (!hash) return;
+                var speed = 0;
+                for (var i = 0, length = s.slides.length; i < length; i++) {
+                    var slide = s.slides.eq(i);
+                    var slideHash = slide.attr('data-hash');
+                    if (slideHash === hash && !slide.hasClass(s.params.slideDuplicateClass)) {
+                        var index = slide.index();
+                        s.slideTo(index, speed, s.params.runCallbacksOnInit, true);
+                    }
+                }
+            },
+            setHash: function () {
+                if (!s.hashnav.initialized || !s.params.hashnav) return;
+                document.location.hash = s.slides.eq(s.activeIndex).attr('data-hash') || '';
+            }
+        };
+
+        /*=========================
+          Keyboard Control
+          ===========================*/
+        function handleKeyboard(e) {
+            if (e.originalEvent) e = e.originalEvent; //jquery fix
+            var kc = e.keyCode || e.charCode;
+            // Directions locks
+            if (!s.params.allowSwipeToNext && (s.isHorizontal() && kc === 39 || !s.isHorizontal() && kc === 40)) {
+                return false;
+            }
+            if (!s.params.allowSwipeToPrev && (s.isHorizontal() && kc === 37 || !s.isHorizontal() && kc === 38)) {
+                return false;
+            }
+            if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
+                return;
+            }
+            if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) {
+                return;
+            }
+            if (kc === 37 || kc === 39 || kc === 38 || kc === 40) {
+                var inView = false;
+                //Check that swiper should be inside of visible area of window
+                if (s.container.parents('.swiper-slide').length > 0 && s.container.parents('.swiper-slide-active').length === 0) {
+                    return;
+                }
+                var windowScroll = {
+                    left: window.pageXOffset,
+                    top: window.pageYOffset
+                };
+                var windowWidth = window.innerWidth;
+                var windowHeight = window.innerHeight;
+                var swiperOffset = s.container.offset();
+                if (s.rtl) swiperOffset.left = swiperOffset.left - s.container[0].scrollLeft;
+                var swiperCoord = [
+                    [swiperOffset.left, swiperOffset.top],
+                    [swiperOffset.left + s.width, swiperOffset.top],
+                    [swiperOffset.left, swiperOffset.top + s.height],
+                    [swiperOffset.left + s.width, swiperOffset.top + s.height]
+                ];
+                for (var i = 0; i < swiperCoord.length; i++) {
+                    var point = swiperCoord[i];
+                    if (
+                        point[0] >= windowScroll.left && point[0] <= windowScroll.left + windowWidth &&
+                        point[1] >= windowScroll.top && point[1] <= windowScroll.top + windowHeight
+                    ) {
+                        inView = true;
+                    }
+        
+                }
+                if (!inView) return;
+            }
+            if (s.isHorizontal()) {
+                if (kc === 37 || kc === 39) {
+                    if (e.preventDefault) e.preventDefault();
+                    else e.returnValue = false;
+                }
+                if ((kc === 39 && !s.rtl) || (kc === 37 && s.rtl)) s.slideNext();
+                if ((kc === 37 && !s.rtl) || (kc === 39 && s.rtl)) s.slidePrev();
+            }
+            else {
+                if (kc === 38 || kc === 40) {
+                    if (e.preventDefault) e.preventDefault();
+                    else e.returnValue = false;
+                }
+                if (kc === 40) s.slideNext();
+                if (kc === 38) s.slidePrev();
+            }
+        }
+        s.disableKeyboardControl = function () {
+            s.params.keyboardControl = false;
+            $(document).off('keydown', handleKeyboard);
+        };
+        s.enableKeyboardControl = function () {
+            s.params.keyboardControl = true;
+            $(document).on('keydown', handleKeyboard);
+        };
+        
+
+        /*=========================
+          Mousewheel Control
+          ===========================*/
+        s.mousewheel = {
+            event: false,
+            lastScrollTime: (new window.Date()).getTime()
+        };
+        if (s.params.mousewheelControl) {
+            try {
+                new window.WheelEvent('wheel');
+                s.mousewheel.event = 'wheel';
+            } catch (e) {
+                if (window.WheelEvent || (s.container[0] && 'wheel' in s.container[0])) {
+                    s.mousewheel.event = 'wheel';
+                }
+            }
+            if (!s.mousewheel.event && window.WheelEvent) {
+        
+            }
+            if (!s.mousewheel.event && document.onmousewheel !== undefined) {
+                s.mousewheel.event = 'mousewheel';
+            }
+            if (!s.mousewheel.event) {
+                s.mousewheel.event = 'DOMMouseScroll';
+            }
+        }
+        function handleMousewheel(e) {
+            if (e.originalEvent) e = e.originalEvent; //jquery fix
+            var we = s.mousewheel.event;
+            var delta = 0;
+            var rtlFactor = s.rtl ? -1 : 1;
+        
+            //WebKits
+            if (we === 'mousewheel') {
+                if (s.params.mousewheelForceToAxis) {
+                    if (s.isHorizontal()) {
+                        if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX * rtlFactor;
+                        else return;
+                    }
+                    else {
+                        if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY;
+                        else return;
+                    }
+                }
+                else {
+                    delta = Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY) ? - e.wheelDeltaX * rtlFactor : - e.wheelDeltaY;
+                }
+            }
+            //Old FireFox
+            else if (we === 'DOMMouseScroll') delta = -e.detail;
+            //New FireFox
+            else if (we === 'wheel') {
+                if (s.params.mousewheelForceToAxis) {
+                    if (s.isHorizontal()) {
+                        if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX * rtlFactor;
+                        else return;
+                    }
+                    else {
+                        if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY;
+                        else return;
+                    }
+                }
+                else {
+                    delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX * rtlFactor : - e.deltaY;
+                }
+            }
+            if (delta === 0) return;
+        
+            if (s.params.mousewheelInvert) delta = -delta;
+        
+            if (!s.params.freeMode) {
+                if ((new window.Date()).getTime() - s.mousewheel.lastScrollTime > 60) {
+                    if (delta < 0) {
+                        if ((!s.isEnd || s.params.loop) && !s.animating) s.slideNext();
+                        else if (s.params.mousewheelReleaseOnEdges) return true;
+                    }
+                    else {
+                        if ((!s.isBeginning || s.params.loop) && !s.animating) s.slidePrev();
+                        else if (s.params.mousewheelReleaseOnEdges) return true;
+                    }
+                }
+                s.mousewheel.lastScrollTime = (new window.Date()).getTime();
+        
+            }
+            else {
+                //Freemode or scrollContainer:
+                var position = s.getWrapperTranslate() + delta * s.params.mousewheelSensitivity;
+                var wasBeginning = s.isBeginning,
+                    wasEnd = s.isEnd;
+        
+                if (position >= s.minTranslate()) position = s.minTranslate();
+                if (position <= s.maxTranslate()) position = s.maxTranslate();
+        
+                s.setWrapperTransition(0);
+                s.setWrapperTranslate(position);
+                s.updateProgress();
+                s.updateActiveIndex();
+        
+                if (!wasBeginning && s.isBeginning || !wasEnd && s.isEnd) {
+                    s.updateClasses();
+                }
+        
+                if (s.params.freeModeSticky) {
+                    clearTimeout(s.mousewheel.timeout);
+                    s.mousewheel.timeout = setTimeout(function () {
+                        s.slideReset();
+                    }, 300);
+                }
+                else {
+                    if (s.params.lazyLoading && s.lazy) {
+                        s.lazy.load();
+                    }
+                }
+        
+                // Return page scroll on edge positions
+                if (position === 0 || position === s.maxTranslate()) return;
+            }
+            if (s.params.autoplay) s.stopAutoplay();
+        
+            if (e.preventDefault) e.preventDefault();
+            else e.returnValue = false;
+            return false;
+        }
+        s.disableMousewheelControl = function () {
+            if (!s.mousewheel.event) return false;
+            s.container.off(s.mousewheel.event, handleMousewheel);
+            return true;
+        };
+        
+        s.enableMousewheelControl = function () {
+            if (!s.mousewheel.event) return false;
+            s.container.on(s.mousewheel.event, handleMousewheel);
+            return true;
+        };
+        
+
+        /*=========================
+          Parallax
+          ===========================*/
+        function setParallaxTransform(el, progress) {
+            el = $(el);
+            var p, pX, pY;
+            var rtlFactor = s.rtl ? -1 : 1;
+        
+            p = el.attr('data-swiper-parallax') || '0';
+            pX = el.attr('data-swiper-parallax-x');
+            pY = el.attr('data-swiper-parallax-y');
+            if (pX || pY) {
+                pX = pX || '0';
+                pY = pY || '0';
+            }
+            else {
+                if (s.isHorizontal()) {
+                    pX = p;
+                    pY = '0';
+                }
+                else {
+                    pY = p;
+                    pX = '0';
+                }
+            }
+        
+            if ((pX).indexOf('%') >= 0) {
+                pX = parseInt(pX, 10) * progress * rtlFactor + '%';
+            }
+            else {
+                pX = pX * progress * rtlFactor + 'px' ;
+            }
+            if ((pY).indexOf('%') >= 0) {
+                pY = parseInt(pY, 10) * progress + '%';
+            }
+            else {
+                pY = pY * progress + 'px' ;
+            }
+        
+            el.transform('translate3d(' + pX + ', ' + pY + ',0px)');
+        }
+        s.parallax = {
+            setTranslate: function () {
+                s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
+                    setParallaxTransform(this, s.progress);
+        
+                });
+                s.slides.each(function () {
+                    var slide = $(this);
+                    slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () {
+                        var progress = Math.min(Math.max(slide[0].progress, -1), 1);
+                        setParallaxTransform(this, progress);
+                    });
+                });
+            },
+            setTransition: function (duration) {
+                if (typeof duration === 'undefined') duration = s.params.speed;
+                s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
+                    var el = $(this);
+                    var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration;
+                    if (duration === 0) parallaxDuration = 0;
+                    el.transition(parallaxDuration);
+                });
+            }
+        };
+        
+
+        /*=========================
+          Plugins API. Collect all and init all plugins
+          ===========================*/
+        s._plugins = [];
+        for (var plugin in s.plugins) {
+            var p = s.plugins[plugin](s, s.params[plugin]);
+            if (p) s._plugins.push(p);
+        }
+        // Method to call all plugins event/method
+        s.callPlugins = function (eventName) {
+            for (var i = 0; i < s._plugins.length; i++) {
+                if (eventName in s._plugins[i]) {
+                    s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+                }
+            }
+        };
+
+        /*=========================
+          Events/Callbacks/Plugins Emitter
+          ===========================*/
+        function normalizeEventName (eventName) {
+            if (eventName.indexOf('on') !== 0) {
+                if (eventName[0] !== eventName[0].toUpperCase()) {
+                    eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1);
+                }
+                else {
+                    eventName = 'on' + eventName;
+                }
+            }
+            return eventName;
+        }
+        s.emitterEventListeners = {
+        
+        };
+        s.emit = function (eventName) {
+            // Trigger callbacks
+            if (s.params[eventName]) {
+                s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+            }
+            var i;
+            // Trigger events
+            if (s.emitterEventListeners[eventName]) {
+                for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
+                    s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+                }
+            }
+            // Trigger plugins
+            if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
+        };
+        s.on = function (eventName, handler) {
+            eventName = normalizeEventName(eventName);
+            if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = [];
+            s.emitterEventListeners[eventName].push(handler);
+            return s;
+        };
+        s.off = function (eventName, handler) {
+            var i;
+            eventName = normalizeEventName(eventName);
+            if (typeof handler === 'undefined') {
+                // Remove all handlers for such event
+                s.emitterEventListeners[eventName] = [];
+                return s;
+            }
+            if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return;
+            for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
+                if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1);
+            }
+            return s;
+        };
+        s.once = function (eventName, handler) {
+            eventName = normalizeEventName(eventName);
+            var _handler = function () {
+                handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+                s.off(eventName, _handler);
+            };
+            s.on(eventName, _handler);
+            return s;
+        };
+
+        // Accessibility tools
+        s.a11y = {
+            makeFocusable: function ($el) {
+                $el.attr('tabIndex', '0');
+                return $el;
+            },
+            addRole: function ($el, role) {
+                $el.attr('role', role);
+                return $el;
+            },
+        
+            addLabel: function ($el, label) {
+                $el.attr('aria-label', label);
+                return $el;
+            },
+        
+            disable: function ($el) {
+                $el.attr('aria-disabled', true);
+                return $el;
+            },
+        
+            enable: function ($el) {
+                $el.attr('aria-disabled', false);
+                return $el;
+            },
+        
+            onEnterKey: function (event) {
+                if (event.keyCode !== 13) return;
+                if ($(event.target).is(s.params.nextButton)) {
+                    s.onClickNext(event);
+                    if (s.isEnd) {
+                        s.a11y.notify(s.params.lastSlideMessage);
+                    }
+                    else {
+                        s.a11y.notify(s.params.nextSlideMessage);
+                    }
+                }
+                else if ($(event.target).is(s.params.prevButton)) {
+                    s.onClickPrev(event);
+                    if (s.isBeginning) {
+                        s.a11y.notify(s.params.firstSlideMessage);
+                    }
+                    else {
+                        s.a11y.notify(s.params.prevSlideMessage);
+                    }
+                }
+                if ($(event.target).is('.' + s.params.bulletClass)) {
+                    $(event.target)[0].click();
+                }
+            },
+        
+            liveRegion: $('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),
+        
+            notify: function (message) {
+                var notification = s.a11y.liveRegion;
+                if (notification.length === 0) return;
+                notification.html('');
+                notification.html(message);
+            },
+            init: function () {
+                // Setup accessibility
+                if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
+                    s.a11y.makeFocusable(s.nextButton);
+                    s.a11y.addRole(s.nextButton, 'button');
+                    s.a11y.addLabel(s.nextButton, s.params.nextSlideMessage);
+                }
+                if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
+                    s.a11y.makeFocusable(s.prevButton);
+                    s.a11y.addRole(s.prevButton, 'button');
+                    s.a11y.addLabel(s.prevButton, s.params.prevSlideMessage);
+                }
+        
+                $(s.container).append(s.a11y.liveRegion);
+            },
+            initPagination: function () {
+                if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) {
+                    s.bullets.each(function () {
+                        var bullet = $(this);
+                        s.a11y.makeFocusable(bullet);
+                        s.a11y.addRole(bullet, 'button');
+                        s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1));
+                    });
+                }
+            },
+            destroy: function () {
+                if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove();
+            }
+        };
+        
+
+        /*=========================
+          Init/Destroy
+          ===========================*/
+        s.init = function () {
+            if (s.params.loop) s.createLoop();
+            s.updateContainerSize();
+            s.updateSlidesSize();
+            s.updatePagination();
+            if (s.params.scrollbar && s.scrollbar) {
+                s.scrollbar.set();
+                if (s.params.scrollbarDraggable) {
+                    s.scrollbar.enableDraggable();
+                }
+            }
+            if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
+                if (!s.params.loop) s.updateProgress();
+                s.effects[s.params.effect].setTranslate();
+            }
+            if (s.params.loop) {
+                s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit);
+            }
+            else {
+                s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit);
+                if (s.params.initialSlide === 0) {
+                    if (s.parallax && s.params.parallax) s.parallax.setTranslate();
+                    if (s.lazy && s.params.lazyLoading) {
+                        s.lazy.load();
+                        s.lazy.initialImageLoaded = true;
+                    }
+                }
+            }
+            s.attachEvents();
+            if (s.params.observer && s.support.observer) {
+                s.initObservers();
+            }
+            if (s.params.preloadImages && !s.params.lazyLoading) {
+                s.preloadImages();
+            }
+            if (s.params.autoplay) {
+                s.startAutoplay();
+            }
+            if (s.params.keyboardControl) {
+                if (s.enableKeyboardControl) s.enableKeyboardControl();
+            }
+            if (s.params.mousewheelControl) {
+                if (s.enableMousewheelControl) s.enableMousewheelControl();
+            }
+            if (s.params.hashnav) {
+                if (s.hashnav) s.hashnav.init();
+            }
+            if (s.params.a11y && s.a11y) s.a11y.init();
+            s.emit('onInit', s);
+        };
+        
+        // Cleanup dynamic styles
+        s.cleanupStyles = function () {
+            // Container
+            s.container.removeClass(s.classNames.join(' ')).removeAttr('style');
+        
+            // Wrapper
+            s.wrapper.removeAttr('style');
+        
+            // Slides
+            if (s.slides && s.slides.length) {
+                s.slides
+                    .removeClass([
+                      s.params.slideVisibleClass,
+                      s.params.slideActiveClass,
+                      s.params.slideNextClass,
+                      s.params.slidePrevClass
+                    ].join(' '))
+                    .removeAttr('style')
+                    .removeAttr('data-swiper-column')
+                    .removeAttr('data-swiper-row');
+            }
+        
+            // Pagination/Bullets
+            if (s.paginationContainer && s.paginationContainer.length) {
+                s.paginationContainer.removeClass(s.params.paginationHiddenClass);
+            }
+            if (s.bullets && s.bullets.length) {
+                s.bullets.removeClass(s.params.bulletActiveClass);
+            }
+        
+            // Buttons
+            if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
+            if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
+        
+            // Scrollbar
+            if (s.params.scrollbar && s.scrollbar) {
+                if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style');
+                if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style');
+            }
+        };
+        
+        // Destroy
+        s.destroy = function (deleteInstance, cleanupStyles) {
+            // Detach evebts
+            s.detachEvents();
+            // Stop autoplay
+            s.stopAutoplay();
+            // Disable draggable
+            if (s.params.scrollbar && s.scrollbar) {
+                if (s.params.scrollbarDraggable) {
+                    s.scrollbar.disableDraggable();
+                }
+            }
+            // Destroy loop
+            if (s.params.loop) {
+                s.destroyLoop();
+            }
+            // Cleanup styles
+            if (cleanupStyles) {
+                s.cleanupStyles();
+            }
+            // Disconnect observer
+            s.disconnectObservers();
+            // Disable keyboard/mousewheel
+            if (s.params.keyboardControl) {
+                if (s.disableKeyboardControl) s.disableKeyboardControl();
+            }
+            if (s.params.mousewheelControl) {
+                if (s.disableMousewheelControl) s.disableMousewheelControl();
+            }
+            // Disable a11y
+            if (s.params.a11y && s.a11y) s.a11y.destroy();
+            // Destroy callback
+            s.emit('onDestroy');
+            // Delete instance
+            if (deleteInstance !== false) s = null;
+        };
+        
+        s.init();
+        
+
+    
+        // Return swiper instance
+        return s;
+    };
+    
+
+    /*==================================================
+        Prototype
+    ====================================================*/
+    Swiper.prototype = {
+        isSafari: (function () {
+            var ua = navigator.userAgent.toLowerCase();
+            return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
+        })(),
+        isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),
+        isArray: function (arr) {
+            return Object.prototype.toString.apply(arr) === '[object Array]';
+        },
+        /*==================================================
+        Browser
+        ====================================================*/
+        browser: {
+            ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
+            ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1)
+        },
+        /*==================================================
+        Devices
+        ====================================================*/
+        device: (function () {
+            var ua = navigator.userAgent;
+            var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
+            var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
+            var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
+            var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
+            return {
+                ios: ipad || iphone || ipod,
+                android: android
+            };
+        })(),
+        /*==================================================
+        Feature Detection
+        ====================================================*/
+        support: {
+            touch : (window.Modernizr && Modernizr.touch === true) || (function () {
+                return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
+            })(),
+    
+            transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () {
+                var div = document.createElement('div').style;
+                return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div);
+            })(),
+    
+            flexbox: (function () {
+                var div = document.createElement('div').style;
+                var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' ');
+                for (var i = 0; i < styles.length; i++) {
+                    if (styles[i] in div) return true;
+                }
+            })(),
+    
+            observer: (function () {
+                return ('MutationObserver' in window || 'WebkitMutationObserver' in window);
+            })()
+        },
+        /*==================================================
+        Plugins
+        ====================================================*/
+        plugins: {}
+    };
+    
+
+    /*===========================
+     Get Dom libraries
+     ===========================*/
+    var swiperDomPlugins = ['jQuery', 'Zepto', 'Dom7'];
+    for (var i = 0; i < swiperDomPlugins.length; i++) {
+    	if (window[swiperDomPlugins[i]]) {
+    		addLibraryPlugin(window[swiperDomPlugins[i]]);
+    	}
+    }
+    // Required DOM Plugins
+    var domLib;
+    if (typeof Dom7 === 'undefined') {
+    	domLib = window.Dom7 || window.Zepto || window.jQuery;
+    }
+    else {
+    	domLib = Dom7;
+    }
+
+    /*===========================
+    Add .swiper plugin from Dom libraries
+    ===========================*/
+    function addLibraryPlugin(lib) {
+        lib.fn.swiper = function (params) {
+            var firstInstance;
+            lib(this).each(function () {
+                var s = new Swiper(this, params);
+                if (!firstInstance) firstInstance = s;
+            });
+            return firstInstance;
+        };
+    }
+    
+    if (domLib) {
+        if (!('transitionEnd' in domLib.fn)) {
+            domLib.fn.transitionEnd = function (callback) {
+                var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
+                    i, j, dom = this;
+                function fireCallBack(e) {
+                    /*jshint validthis:true */
+                    if (e.target !== this) return;
+                    callback.call(this, e);
+                    for (i = 0; i < events.length; i++) {
+                        dom.off(events[i], fireCallBack);
+                    }
+                }
+                if (callback) {
+                    for (i = 0; i < events.length; i++) {
+                        dom.on(events[i], fireCallBack);
+                    }
+                }
+                return this;
+            };
+        }
+        if (!('transform' in domLib.fn)) {
+            domLib.fn.transform = function (transform) {
+                for (var i = 0; i < this.length; i++) {
+                    var elStyle = this[i].style;
+                    elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
+                }
+                return this;
+            };
+        }
+        if (!('transition' in domLib.fn)) {
+            domLib.fn.transition = function (duration) {
+                if (typeof duration !== 'string') {
+                    duration = duration + 'ms';
+                }
+                for (var i = 0; i < this.length; i++) {
+                    var elStyle = this[i].style;
+                    elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
+                }
+                return this;
+            };
+        }
+    }
+
+    window.Swiper = Swiper;
+})();
+/*===========================
+Swiper AMD Export
+===========================*/
+if (typeof(module) !== 'undefined')
+{
+    module.exports = window.Swiper;
+}
+else if (typeof define === 'function' && define.amd) {
+    define([], function () {
+        'use strict';
+        return window.Swiper;
+    });
+}
+//# sourceMappingURL=maps/swiper.jquery.js.map
+
+/* ===============================================================================
+************ Swiper ************
+=============================================================================== */
+/* global $:true */
+
++function ($) {
+  "use strict";
+
+  var defaults;
+
+  $.fn.swiper = function(params) {
+    return this.each(function() {
+      if(!this) return;
+      var $this = $(this);
+      var swiper = $this.data("swiper");
+      if(!swiper) $this.data("swiper", new Swiper(this, $.extend({}, defaults, params))); 
+      return swiper;
+    });
+  }
+
+  defaults = $.fn.swiper.prototype.defaults = {
+    pagination: ".swiper-pagination"
+  };
+
+}($);
+
+/* global $:true */
++ function($) {
+
+  var defaults;
+
+  var Photos = function(config) {
+    this.initConfig(config);
+    this.index = 0;
+  }
+
+  Photos.prototype = {
+    initConfig: function (config) {
+      this.config = $.extend({}, defaults, config);
+      this.activeIndex = this.lastActiveIndex = this.config.initIndex;
+
+      this.config.items = this.config.items.map(function(d, i) {
+        if(typeof d === typeof 'a') {
+          return {
+            image: d,
+            caption: ''
+          }
+        }
+        return d;
+      });
+
+      this.tpl = $.t7.compile(this.config.tpl);
+      if(this.config.autoOpen) this.open();
+    },
+
+    open: function (index) {
+      if (this._open) return false;
+      if (!this.modal) {
+        this.modal = $(this.tpl(this.config)).appendTo(document.body);
+        this.container = this.modal.find('.swiper-container');
+        this.wrapper = this.modal.find('.swiper-wrapper');
+
+        var hammer = new Hammer(this.container[0]);
+        hammer.get('pinch').set({ enable: true });
+        hammer.on('pinchstart', $.proxy(this.onGestureStart, this));
+        hammer.on('pinchmove', $.proxy(this.onGestureChange, this));
+        hammer.on('pinchend', $.proxy(this.onGestureEnd, this));
+        this.modal.on($.touchEvents.start, $.proxy(this.onTouchStart, this));
+        this.modal.on($.touchEvents.move, $.proxy(this.onTouchMove, this));
+        this.modal.on($.touchEvents.end, $.proxy(this.onTouchEnd, this));
+
+        //init index
+        this.wrapper.transition(0);
+        this.wrapper.transform('translate3d(-' + $(window).width()*this.config.initIndex + 'px,0,0)');
+        this.container.find('.caption-item').eq(this.config.initIndex).addClass('active');
+        this.container.find('.swiper-pagination-bullet').eq(this.config.initIndex).addClass('swiper-pagination-bullet-active');
+      }
+
+      var self = this;
+      this.modal.show().height();
+      this.modal.addClass('weui-photo-browser-modal-visible');
+      this.container.addClass('swiper-container-visible').transitionEnd(function() {
+        self.initParams();
+        if(index !== undefined) {
+          self.slideTo(index);
+        }
+        if(self.config.onOpen) {
+          self.config.onOpen.call(self);
+        }
+      });
+
+      this._open = true;
+    },
+
+    close: function() {
+      this.container.transitionEnd($.proxy(function() {
+        this.modal.hide();
+        this._open = false;
+        if(this.config.onClose) this.config.onClose.call(this);
+      }, this));
+      this.container.removeClass('swiper-container-visible');
+      this.modal.removeClass('weui-photo-browser-modal-visible');
+    },
+
+    initParams: function () {
+      if(this.containerHeight) return false;
+
+      this.windowWidth = $(window).width();
+      this.containerHeight = this.container.height();
+      this.containerWidth = this.container.width();
+
+      this.touchStart = {};
+
+      this.wrapperTransform = 0;
+      this.wrapperLastTransform = - $(window).width()*this.config.initIndex;
+      this.wrapperDiff = 0;
+
+      this.lastScale = 1;
+      this.currentScale = 1;
+
+      this.imageLastTransform = { x: 0, y: 0 };
+      this.imageTransform = { x: 0, y: 0 };
+      this.imageDiff = { x: 0, y: 0 };
+      this.imageLastDiff = { x: 0, y: 0 };
+    },
+
+    onTouchStart: function (e) {
+      if(this.scaling) return false;
+      this.touching = true;
+      this.touchStart = $.getTouchPosition(e);
+      this.touchMove = null;
+      this.touchStartTime = + new Date;
+      this.wrapperDiff = 0;
+      this.breakpointPosition = null;
+    },
+
+    onTouchMove: function (e) {
+      if(!this.touching || this.scaling) return false;
+
+      e.preventDefault();
+
+      if(this.gestureImage) {
+        var rect = this.gestureImage[0].getBoundingClientRect();
+        if (rect.left >= 0 || rect.right <= this.windowWidth) {
+          this.overflow = true;
+        } else {
+          this.overflow = false;
+        }
+      } else {
+        this.oveflow = false;
+      }
+      var p = this.touchMove = $.getTouchPosition(e);
+      if(this.currentScale === 1 || this.overflow) {
+        if(this.breakpointPosition) {
+          this.wrapperDiff = p.x - this.breakpointPosition.x;
+        } else {
+          this.wrapperDiff = p.x - this.touchStart.x;
+        }
+        if(this.activeIndex === 0 && this.wrapperDiff > 0) this.wrapperDiff = Math.pow(this.wrapperDiff, .8);
+        if(this.activeIndex === this.config.items.length - 1 && this.wrapperDiff < 0) this.wrapperDiff = - Math.pow(-this.wrapperDiff, .8);
+        this.wrapperTransform = this.wrapperLastTransform + this.wrapperDiff;
+        this.doWrapperTransform();
+      } else {
+        var img = this.gestureImage;
+        this.imageDiff = {
+          x: p.x - this.touchStart.x,
+          y: p.y - this.touchStart.y
+        }
+
+        this.imageTransform = {
+          x: this.imageDiff.x + this.imageLastTransform.x,
+          y: this.imageDiff.y + this.imageLastTransform.y
+        };
+        this.doImageTransform();
+
+        this.breakpointPosition = p;
+
+        this.imageLastDiff = this.imageDiff;
+      }
+    },
+
+    onTouchEnd: function (e) {
+      if(!this.touching) return false;
+      this.touching = false;
+      if(this.scaling) return false;
+      var duration = (+ new Date) - this.touchStartTime;
+
+      if(duration < 200 && (!this.touchMove || Math.abs(this.touchStart.x - this.touchMove.x) <= 2 && Math.abs(this.touchStart.y - this.touchMove.y) <= 2)) {
+        this.onClick();
+        return;
+      }
+      if(this.wrapperDiff > 0) {
+        if(this.wrapperDiff > this.containerWidth/2 || (this.wrapperDiff > 20 && duration < 300)) {
+          this.slidePrev();
+        } else {
+          this.slideTo(this.activeIndex, 200);
+        }
+      } else {
+        if(- this.wrapperDiff > this.containerWidth/2 || (-this.wrapperDiff > 20 && duration < 300)) {
+          this.slideNext();
+        } else {
+          this.slideTo(this.activeIndex, 200);
+        }
+      }
+
+      this.imageLastTransform = this.imageTransform;
+
+      this.adjust();
+    },
+
+    onClick: function () {
+      var self = this;
+      if (this._lastClickTime && ( + new Date - this._lastClickTime < 300)) {
+        this.onDoubleClick();
+        clearTimeout(this._clickTimeout);
+      } else {
+        this._clickTimeout = setTimeout(function () {
+          self.close();
+        }, 300);
+      }
+      this._lastClickTime = + new Date;
+    },
+
+    onDoubleClick: function () {
+      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
+      this.currentScale = this.currentScale > 1 ? 1 : 2;
+      this.doImageTransform(200); 
+      this.adjust();
+    },
+
+    onGestureStart: function (e) {
+      this.scaling = true;
+      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
+    },
+
+    onGestureChange: function (e) {
+      var s = this.lastScale * e.scale;
+      if (s > this.config.maxScale) {
+        s = this.config.maxScale + Math.pow((s - this.config.maxScale), 0.5);
+      } else if (s < 1) {
+        s = Math.pow(s, .5);
+      }
+      this.currentScale = s;
+      this.doImageTransform();
+    },
+
+    onGestureEnd: function (e) {
+      if (this.currentScale > this.config.maxScale) {
+        this.currentScale = this.config.maxScale;
+        this.doImageTransform(200);
+      } else if (this.currentScale < 1) {
+        this.currentScale = 1;
+        this.doImageTransform(200);
+      }
+      this.lastScale = this.currentScale;
+      this.scaling = false;
+      this.adjust();
+    },
+
+    doWrapperTransform: function(duration, callback) {
+      if (duration === 0) {
+        var origin = this.wrapper.css('transition-property')
+        this.wrapper.css('transition-property', 'none').transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
+        this.wrapper.css('transition-property', origin);
+        callback()
+      } else {
+        this.wrapper.transitionEnd(function() {
+          callback && callback();
+        });
+        this.wrapper.transition(duration || defaults.duration).transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
+      }
+    },
+
+    doImageTransform: function(duration, callback) {
+      if(!this.gestureImage) return;
+      this.gestureImage.transition(duration || 0).transform('translate3d(' + this.imageTransform.x + 'px,' + this.imageTransform.y + 'px, 0) scale(' + this.currentScale + ')');
+      this._needAdjust = true;
+    },
+
+    adjust: function() {
+      if(!this._needAdjust) return false;
+      var img = this.gestureImage;
+      if(!img) return false;
+      if(this.currentScale === 1) {
+        this.imageTransform = this.imageLastDiff =  {x:0,y:0};
+        this.doImageTransform(200);
+        return;
+      }
+
+      var rect = img[0].getBoundingClientRect();
+
+      //调整上下
+      if(rect.height < this.containerHeight) {  // 如果高度没容器高,则自动居中
+        this.imageTransform.y = this.imageLastTransform.y = 0;
+      } else {  //如果比容器高,那么要保证上下不能有空隙
+        if(rect.top > 0) this.imageTransform.y = this.imageTransform.y - rect.top;
+        else if(rect.bottom < this.containerHeight) this.imageTransform.y = this.imageTransform.y + this.containerHeight - rect.bottom;
+      }
+
+      this.doImageTransform(200);
+      this._needAdjust = false; // must at last line, because doImageTransform will set this._needAdjust true
+    },
+
+    slideTo: function(index, duration) {
+      if(index < 0) index = 0;
+      if(index > this.config.items.length-1) index = this.config.items.length - 1;
+      this.lastActiveIndex = this.activeIndex;
+      this.activeIndex = index;
+      this.wrapperTransform = - (index * this.containerWidth);
+      this.wrapperLastTransform = this.wrapperTransform;
+      this.doWrapperTransform(duration, $.proxy(function() {
+        if(this.lastActiveIndex === this.activeIndex) return false; // active index not change
+        this.container.find('.caption-item.active').removeClass('active');
+        this.container.find('.swiper-slide-active').removeClass('swiper-slide-active');
+        this.container.find('.swiper-pagination-bullet-active').removeClass('swiper-pagination-bullet-active');
+        this.container.find('.caption-item').eq(this.activeIndex).addClass('active');
+        this.container.find('.swiper-slide').eq(this.activeIndex).addClass('swiper-slide-active');
+        this.container.find('.swiper-pagination-bullet').eq(this.activeIndex).addClass('swiper-pagination-bullet-active');
+
+        //reset image transform
+        this.container.find('.swiper-slide img[style]').transition(0).transform('translate3d(0,0,0) scale(1)');
+
+        this.lastScale = 1;
+        this.currentScale = 1;
+
+        this.imageLastTransform = { x: 0, y: 0 };
+        this.imageTransform = { x: 0, y: 0 };
+        this.imageDiff = { x: 0, y: 0 };
+        this.imageLastDiff = { x: 0, y: 0 };
+
+        if(this.config.onSlideChange) {
+          this.config.onSlideChange.call(this, this.activeIndex);
+        }
+
+      }, this));
+    },
+    slideNext: function() {
+      return this.slideTo(this.activeIndex+1, 200);
+    },
+    slidePrev: function() {
+      return this.slideTo(this.activeIndex-1, 200);
+    }
+  }
+
+  defaults = Photos.prototype.defaults = {
+    items: [],
+    autoOpen: false, //初始化完成之后立刻打开
+    onOpen: undefined,
+    onClose: undefined,
+    initIndex: 0, //打开时默认显示第几张
+    maxScale: 3,
+    onSlideChange: undefined,
+    duration: 200, // 默认动画时间,如果没有在调用函数的时候指定,则使用这个值
+    tpl: '<div class="weui-photo-browser-modal">\
+            <div class="swiper-container">\
+              <div class="swiper-wrapper">\
+                {{#items}}\
+                <div class="swiper-slide">\
+                  <div class="photo-container">\
+                    <img src="{{image}}" />\
+                  </div>\
+                </div>\
+                {{/items}}\
+              </div>\
+              <div class="caption">\
+                {{#items}}\
+                <div class="caption-item caption-item-{{@index}}">{{caption}}</div>\
+                {{/items}}\
+              </div>\
+              <div class="swiper-pagination swiper-pagination-bullets">\
+                {{#items}}\
+                <span class="swiper-pagination-bullet"></span>\
+                {{/items}}\
+              </div>\
+            </div>\
+          </div>'
+  }
+
+  $.photoBrowser = function(params) {
+    return new Photos(params);
+  }
+}($);
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.min.js
new file mode 100755
index 0000000..69f968b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/lib/swiper.min.js
@@ -0,0 +1,17 @@
+/**
+ * Swiper 3.3.1
+ * Most modern mobile touch slider and framework with hardware accelerated transitions
+ * 
+ * http://www.idangero.us/swiper/
+ * 
+ * Copyright 2016, Vladimir Kharlampidi
+ * The iDangero.us
+ * http://www.idangero.us/
+ * 
+ * Licensed under MIT
+ * 
+ * Released on: February 7, 2016
+ */
+!function(){"use strict";function e(e){e.fn.swiper=function(a){var i;return e(this).each(function(){var e=new t(this,a);i||(i=e)}),i}}var a,t=function(e,i){function s(e){return Math.floor(e)}function r(){y.autoplayTimeoutId=setTimeout(function(){y.params.loop?(y.fixLoop(),y._slideNext(),y.emit("onAutoplay",y)):y.isEnd?i.autoplayStopOnLast?y.stopAutoplay():(y._slideTo(0),y.emit("onAutoplay",y)):(y._slideNext(),y.emit("onAutoplay",y))},y.params.autoplay)}function n(e,t){var i=a(e.target);if(!i.is(t))if("string"==typeof t)i=i.parents(t);else if(t.nodeType){var s;return i.parents().each(function(e,a){a===t&&(s=t)}),s?t:void 0}if(0!==i.length)return i[0]}function o(e,a){a=a||{};var t=window.MutationObserver||window.WebkitMutationObserver,i=new t(function(e){e.forEach(function(e){y.onResize(!0),y.emit("onObserverUpdate",y,e)})});i.observe(e,{attributes:"undefined"==typeof a.attributes||a.attributes,childList:"undefined"==typeof a.childList||a.childList,characterData:"undefined"==typeof a.characterData||a.characterData}),y.observers.push(i)}function l(e){e.originalEvent&&(e=e.originalEvent);var a=e.keyCode||e.charCode;if(!y.params.allowSwipeToNext&&(y.isHorizontal()&&39===a||!y.isHorizontal()&&40===a))return!1;if(!y.params.allowSwipeToPrev&&(y.isHorizontal()&&37===a||!y.isHorizontal()&&38===a))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===a||39===a||38===a||40===a){var t=!1;if(y.container.parents(".swiper-slide").length>0&&0===y.container.parents(".swiper-slide-active").length)return;var i={left:window.pageXOffset,top:window.pageYOffset},s=window.innerWidth,r=window.innerHeight,n=y.container.offset();y.rtl&&(n.left=n.left-y.container[0].scrollLeft);for(var o=[[n.left,n.top],[n.left+y.width,n.top],[n.left,n.top+y.height],[n.left+y.width,n.top+y.height]],l=0;l<o.length;l++){var p=o[l];p[0]>=i.left&&p[0]<=i.left+s&&p[1]>=i.top&&p[1]<=i.top+r&&(t=!0)}if(!t)return}y.isHorizontal()?(37!==a&&39!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===a&&!y.rtl||37===a&&y.rtl)&&y.slideNext(),(37===a&&!y.rtl||39===a&&y.rtl)&&y.slidePrev()):(38!==a&&40!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),40===a&&y.slideNext(),38===a&&y.slidePrev())}}function p(e){e.originalEvent&&(e=e.originalEvent);var a=y.mousewheel.event,t=0,i=y.rtl?-1:1;if("mousewheel"===a)if(y.params.mousewheelForceToAxis)if(y.isHorizontal()){if(!(Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)))return;t=e.wheelDeltaX*i}else{if(!(Math.abs(e.wheelDeltaY)>Math.abs(e.wheelDeltaX)))return;t=e.wheelDeltaY}else t=Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)?-e.wheelDeltaX*i:-e.wheelDeltaY;else if("DOMMouseScroll"===a)t=-e.detail;else if("wheel"===a)if(y.params.mousewheelForceToAxis)if(y.isHorizontal()){if(!(Math.abs(e.deltaX)>Math.abs(e.deltaY)))return;t=-e.deltaX*i}else{if(!(Math.abs(e.deltaY)>Math.abs(e.deltaX)))return;t=-e.deltaY}else t=Math.abs(e.deltaX)>Math.abs(e.deltaY)?-e.deltaX*i:-e.deltaY;if(0!==t){if(y.params.mousewheelInvert&&(t=-t),y.params.freeMode){var s=y.getWrapperTranslate()+t*y.params.mousewheelSensitivity,r=y.isBeginning,n=y.isEnd;if(s>=y.minTranslate()&&(s=y.minTranslate()),s<=y.maxTranslate()&&(s=y.maxTranslate()),y.setWrapperTransition(0),y.setWrapperTranslate(s),y.updateProgress(),y.updateActiveIndex(),(!r&&y.isBeginning||!n&&y.isEnd)&&y.updateClasses(),y.params.freeModeSticky?(clearTimeout(y.mousewheel.timeout),y.mousewheel.timeout=setTimeout(function(){y.slideReset()},300)):y.params.lazyLoading&&y.lazy&&y.lazy.load(),0===s||s===y.maxTranslate())return}else{if((new window.Date).getTime()-y.mousewheel.lastScrollTime>60)if(t<0)if(y.isEnd&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slideNext();else if(y.isBeginning&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slidePrev();y.mousewheel.lastScrollTime=(new window.Date).getTime()}return y.params.autoplay&&y.stopAutoplay(),e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function d(e,t){e=a(e);var i,s,r,n=y.rtl?-1:1;i=e.attr("data-swiper-parallax")||"0",s=e.attr("data-swiper-parallax-x"),r=e.attr("data-swiper-parallax-y"),s||r?(s=s||"0",r=r||"0"):y.isHorizontal()?(s=i,r="0"):(r=i,s="0"),s=s.indexOf("%")>=0?parseInt(s,10)*t*n+"%":s*t*n+"px",r=r.indexOf("%")>=0?parseInt(r,10)*t+"%":r*t+"px",e.transform("translate3d("+s+", "+r+",0px)")}function c(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof t))return new t(e,i);var u={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,autoplayStopOnLast:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flip:{slideShadows:!0,limitRotation:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,hashnav:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,uniqueNavElements:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,paginationProgressRender:null,paginationFractionRender:null,paginationCustomRender:null,paginationType:"bullets",resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingInPrevNextAmount:1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slidePrevClass:"swiper-slide-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationCurrentClass:"swiper-pagination-current",paginationTotalClass:"swiper-pagination-total",paginationHiddenClass:"swiper-pagination-hidden",paginationProgressbarClass:"swiper-pagination-progressbar",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},m=i&&i.virtualTranslate;i=i||{};var h={};for(var f in i)if("object"!=typeof i[f]||null===i[f]||(i[f].nodeType||i[f]===window||i[f]===document||"undefined"!=typeof Dom7&&i[f]instanceof Dom7||"undefined"!=typeof jQuery&&i[f]instanceof jQuery))h[f]=i[f];else{h[f]={};for(var g in i[f])h[f][g]=i[f][g]}for(var v in u)if("undefined"==typeof i[v])i[v]=u[v];else if("object"==typeof i[v])for(var w in u[v])"undefined"==typeof i[v][w]&&(i[v][w]=u[v][w]);var y=this;if(y.params=i,y.originalParams=h,y.classNames=[],"undefined"!=typeof a&&"undefined"!=typeof Dom7&&(a=Dom7),("undefined"!=typeof a||(a="undefined"==typeof Dom7?window.Dom7||window.Zepto||window.jQuery:Dom7))&&(y.$=a,y.currentBreakpoint=void 0,y.getActiveBreakpoint=function(){if(!y.params.breakpoints)return!1;var e,a=!1,t=[];for(e in y.params.breakpoints)y.params.breakpoints.hasOwnProperty(e)&&t.push(e);t.sort(function(e,a){return parseInt(e,10)>parseInt(a,10)});for(var i=0;i<t.length;i++)e=t[i],e>=window.innerWidth&&!a&&(a=e);return a||"max"},y.setBreakpoint=function(){var e=y.getActiveBreakpoint();if(e&&y.currentBreakpoint!==e){var a=e in y.params.breakpoints?y.params.breakpoints[e]:y.originalParams,t=y.params.loop&&a.slidesPerView!==y.params.slidesPerView;for(var i in a)y.params[i]=a[i];y.currentBreakpoint=e,t&&y.destroyLoop&&y.reLoop(!0)}},y.params.breakpoints&&y.setBreakpoint(),y.container=a(e),0!==y.container.length)){if(y.container.length>1){var x=[];return y.container.each(function(){x.push(new t(this,i))}),x}y.container[0].swiper=y,y.container.data("swiper",y),y.classNames.push("swiper-container-"+y.params.direction),y.params.freeMode&&y.classNames.push("swiper-container-free-mode"),y.support.flexbox||(y.classNames.push("swiper-container-no-flexbox"),y.params.slidesPerColumn=1),y.params.autoHeight&&y.classNames.push("swiper-container-autoheight"),(y.params.parallax||y.params.watchSlidesVisibility)&&(y.params.watchSlidesProgress=!0),["cube","coverflow","flip"].indexOf(y.params.effect)>=0&&(y.support.transforms3d?(y.params.watchSlidesProgress=!0,y.classNames.push("swiper-container-3d")):y.params.effect="slide"),"slide"!==y.params.effect&&y.classNames.push("swiper-container-"+y.params.effect),"cube"===y.params.effect&&(y.params.resistanceRatio=0,y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.centeredSlides=!1,y.params.spaceBetween=0,y.params.virtualTranslate=!0,y.params.setWrapperSize=!1),"fade"!==y.params.effect&&"flip"!==y.params.effect||(y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.watchSlidesProgress=!0,y.params.spaceBetween=0,y.params.setWrapperSize=!1,"undefined"==typeof m&&(y.params.virtualTranslate=!0)),y.params.grabCursor&&y.support.touch&&(y.params.grabCursor=!1),y.wrapper=y.container.children("."+y.params.wrapperClass),y.params.pagination&&(y.paginationContainer=a(y.params.pagination),y.params.uniqueNavElements&&"string"==typeof y.params.pagination&&y.paginationContainer.length>1&&1===y.container.find(y.params.pagination).length&&(y.paginationContainer=y.container.find(y.params.pagination)),"bullets"===y.params.paginationType&&y.params.paginationClickable?y.paginationContainer.addClass("swiper-pagination-clickable"):y.params.paginationClickable=!1,y.paginationContainer.addClass("swiper-pagination-"+y.params.paginationType)),(y.params.nextButton||y.params.prevButton)&&(y.params.nextButton&&(y.nextButton=a(y.params.nextButton),y.params.uniqueNavElements&&"string"==typeof y.params.nextButton&&y.nextButton.length>1&&1===y.container.find(y.params.nextButton).length&&(y.nextButton=y.container.find(y.params.nextButton))),y.params.prevButton&&(y.prevButton=a(y.params.prevButton),y.params.uniqueNavElements&&"string"==typeof y.params.prevButton&&y.prevButton.length>1&&1===y.container.find(y.params.prevButton).length&&(y.prevButton=y.container.find(y.params.prevButton)))),y.isHorizontal=function(){return"horizontal"===y.params.direction},y.rtl=y.isHorizontal()&&("rtl"===y.container[0].dir.toLowerCase()||"rtl"===y.container.css("direction")),y.rtl&&y.classNames.push("swiper-container-rtl"),y.rtl&&(y.wrongRTL="-webkit-box"===y.wrapper.css("display")),y.params.slidesPerColumn>1&&y.classNames.push("swiper-container-multirow"),y.device.android&&y.classNames.push("swiper-container-android"),y.container.addClass(y.classNames.join(" ")),y.translate=0,y.progress=0,y.velocity=0,y.lockSwipeToNext=function(){y.params.allowSwipeToNext=!1},y.lockSwipeToPrev=function(){y.params.allowSwipeToPrev=!1},y.lockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!1},y.unlockSwipeToNext=function(){y.params.allowSwipeToNext=!0},y.unlockSwipeToPrev=function(){y.params.allowSwipeToPrev=!0},y.unlockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!0},y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab"),y.imagesToLoad=[],y.imagesLoaded=0,y.loadImage=function(e,a,t,i,s){function r(){s&&s()}var n;e.complete&&i?r():a?(n=new window.Image,n.onload=r,n.onerror=r,t&&(n.srcset=t),a&&(n.src=a)):r()},y.preloadImages=function(){function e(){"undefined"!=typeof y&&null!==y&&(void 0!==y.imagesLoaded&&y.imagesLoaded++,y.imagesLoaded===y.imagesToLoad.length&&(y.params.updateOnImagesReady&&y.update(),y.emit("onImagesReady",y)))}y.imagesToLoad=y.container.find("img");for(var a=0;a<y.imagesToLoad.length;a++)y.loadImage(y.imagesToLoad[a],y.imagesToLoad[a].currentSrc||y.imagesToLoad[a].getAttribute("src"),y.imagesToLoad[a].srcset||y.imagesToLoad[a].getAttribute("srcset"),!0,e)},y.autoplayTimeoutId=void 0,y.autoplaying=!1,y.autoplayPaused=!1,y.startAutoplay=function(){return"undefined"==typeof y.autoplayTimeoutId&&(!!y.params.autoplay&&(!y.autoplaying&&(y.autoplaying=!0,y.emit("onAutoplayStart",y),void r())))},y.stopAutoplay=function(e){y.autoplayTimeoutId&&(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplaying=!1,y.autoplayTimeoutId=void 0,y.emit("onAutoplayStop",y))},y.pauseAutoplay=function(e){y.autoplayPaused||(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplayPaused=!0,0===e?(y.autoplayPaused=!1,r()):y.wrapper.transitionEnd(function(){y&&(y.autoplayPaused=!1,y.autoplaying?r():y.stopAutoplay())}))},y.minTranslate=function(){return-y.snapGrid[0]},y.maxTranslate=function(){return-y.snapGrid[y.snapGrid.length-1]},y.updateAutoHeight=function(){var e=y.slides.eq(y.activeIndex)[0];if("undefined"!=typeof e){var a=e.offsetHeight;a&&y.wrapper.css("height",a+"px")}},y.updateContainerSize=function(){var e,a;e="undefined"!=typeof y.params.width?y.params.width:y.container[0].clientWidth,a="undefined"!=typeof y.params.height?y.params.height:y.container[0].clientHeight,0===e&&y.isHorizontal()||0===a&&!y.isHorizontal()||(e=e-parseInt(y.container.css("padding-left"),10)-parseInt(y.container.css("padding-right"),10),a=a-parseInt(y.container.css("padding-top"),10)-parseInt(y.container.css("padding-bottom"),10),y.width=e,y.height=a,y.size=y.isHorizontal()?y.width:y.height)},y.updateSlidesSize=function(){y.slides=y.wrapper.children("."+y.params.slideClass),y.snapGrid=[],y.slidesGrid=[],y.slidesSizesGrid=[];var e,a=y.params.spaceBetween,t=-y.params.slidesOffsetBefore,i=0,r=0;if("undefined"!=typeof y.size){"string"==typeof a&&a.indexOf("%")>=0&&(a=parseFloat(a.replace("%",""))/100*y.size),y.virtualSize=-a,y.rtl?y.slides.css({marginLeft:"",marginTop:""}):y.slides.css({marginRight:"",marginBottom:""});var n;y.params.slidesPerColumn>1&&(n=Math.floor(y.slides.length/y.params.slidesPerColumn)===y.slides.length/y.params.slidesPerColumn?y.slides.length:Math.ceil(y.slides.length/y.params.slidesPerColumn)*y.params.slidesPerColumn,"auto"!==y.params.slidesPerView&&"row"===y.params.slidesPerColumnFill&&(n=Math.max(n,y.params.slidesPerView*y.params.slidesPerColumn)));var o,l=y.params.slidesPerColumn,p=n/l,d=p-(y.params.slidesPerColumn*p-y.slides.length);for(e=0;e<y.slides.length;e++){o=0;var c=y.slides.eq(e);if(y.params.slidesPerColumn>1){var u,m,h;"column"===y.params.slidesPerColumnFill?(m=Math.floor(e/l),h=e-m*l,(m>d||m===d&&h===l-1)&&++h>=l&&(h=0,m++),u=m+h*n/l,c.css({"-webkit-box-ordinal-group":u,"-moz-box-ordinal-group":u,"-ms-flex-order":u,"-webkit-order":u,order:u})):(h=Math.floor(e/p),m=e-h*p),c.css({"margin-top":0!==h&&y.params.spaceBetween&&y.params.spaceBetween+"px"}).attr("data-swiper-column",m).attr("data-swiper-row",h)}"none"!==c.css("display")&&("auto"===y.params.slidesPerView?(o=y.isHorizontal()?c.outerWidth(!0):c.outerHeight(!0),y.params.roundLengths&&(o=s(o))):(o=(y.size-(y.params.slidesPerView-1)*a)/y.params.slidesPerView,y.params.roundLengths&&(o=s(o)),y.isHorizontal()?y.slides[e].style.width=o+"px":y.slides[e].style.height=o+"px"),y.slides[e].swiperSlideSize=o,y.slidesSizesGrid.push(o),y.params.centeredSlides?(t=t+o/2+i/2+a,0===e&&(t=t-y.size/2-a),Math.abs(t)<.001&&(t=0),r%y.params.slidesPerGroup===0&&y.snapGrid.push(t),y.slidesGrid.push(t)):(r%y.params.slidesPerGroup===0&&y.snapGrid.push(t),y.slidesGrid.push(t),t=t+o+a),y.virtualSize+=o+a,i=o,r++)}y.virtualSize=Math.max(y.virtualSize,y.size)+y.params.slidesOffsetAfter;var f;if(y.rtl&&y.wrongRTL&&("slide"===y.params.effect||"coverflow"===y.params.effect)&&y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.support.flexbox&&!y.params.setWrapperSize||(y.isHorizontal()?y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}):y.wrapper.css({height:y.virtualSize+y.params.spaceBetween+"px"})),y.params.slidesPerColumn>1&&(y.virtualSize=(o+y.params.spaceBetween)*n,y.virtualSize=Math.ceil(y.virtualSize/y.params.slidesPerColumn)-y.params.spaceBetween,y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.params.centeredSlides)){for(f=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<y.virtualSize+y.snapGrid[0]&&f.push(y.snapGrid[e]);y.snapGrid=f}if(!y.params.centeredSlides){for(f=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<=y.virtualSize-y.size&&f.push(y.snapGrid[e]);y.snapGrid=f,Math.floor(y.virtualSize-y.size)-Math.floor(y.snapGrid[y.snapGrid.length-1])>1&&y.snapGrid.push(y.virtualSize-y.size)}0===y.snapGrid.length&&(y.snapGrid=[0]),0!==y.params.spaceBetween&&(y.isHorizontal()?y.rtl?y.slides.css({marginLeft:a+"px"}):y.slides.css({marginRight:a+"px"}):y.slides.css({marginBottom:a+"px"})),y.params.watchSlidesProgress&&y.updateSlidesOffset()}},y.updateSlidesOffset=function(){for(var e=0;e<y.slides.length;e++)y.slides[e].swiperSlideOffset=y.isHorizontal()?y.slides[e].offsetLeft:y.slides[e].offsetTop},y.updateSlidesProgress=function(e){if("undefined"==typeof e&&(e=y.translate||0),0!==y.slides.length){"undefined"==typeof y.slides[0].swiperSlideOffset&&y.updateSlidesOffset();var a=-e;y.rtl&&(a=e),y.slides.removeClass(y.params.slideVisibleClass);for(var t=0;t<y.slides.length;t++){var i=y.slides[t],s=(a-i.swiperSlideOffset)/(i.swiperSlideSize+y.params.spaceBetween);if(y.params.watchSlidesVisibility){var r=-(a-i.swiperSlideOffset),n=r+y.slidesSizesGrid[t],o=r>=0&&r<y.size||n>0&&n<=y.size||r<=0&&n>=y.size;o&&y.slides.eq(t).addClass(y.params.slideVisibleClass)}i.progress=y.rtl?-s:s}}},y.updateProgress=function(e){"undefined"==typeof e&&(e=y.translate||0);var a=y.maxTranslate()-y.minTranslate(),t=y.isBeginning,i=y.isEnd;0===a?(y.progress=0,y.isBeginning=y.isEnd=!0):(y.progress=(e-y.minTranslate())/a,y.isBeginning=y.progress<=0,y.isEnd=y.progress>=1),y.isBeginning&&!t&&y.emit("onReachBeginning",y),y.isEnd&&!i&&y.emit("onReachEnd",y),y.params.watchSlidesProgress&&y.updateSlidesProgress(e),y.emit("onProgress",y,y.progress)},y.updateActiveIndex=function(){var e,a,t,i=y.rtl?y.translate:-y.translate;for(a=0;a<y.slidesGrid.length;a++)"undefined"!=typeof y.slidesGrid[a+1]?i>=y.slidesGrid[a]&&i<y.slidesGrid[a+1]-(y.slidesGrid[a+1]-y.slidesGrid[a])/2?e=a:i>=y.slidesGrid[a]&&i<y.slidesGrid[a+1]&&(e=a+1):i>=y.slidesGrid[a]&&(e=a);(e<0||"undefined"==typeof e)&&(e=0),t=Math.floor(e/y.params.slidesPerGroup),t>=y.snapGrid.length&&(t=y.snapGrid.length-1),e!==y.activeIndex&&(y.snapIndex=t,y.previousIndex=y.activeIndex,y.activeIndex=e,y.updateClasses())},y.updateClasses=function(){y.slides.removeClass(y.params.slideActiveClass+" "+y.params.slideNextClass+" "+y.params.slidePrevClass);var e=y.slides.eq(y.activeIndex);e.addClass(y.params.slideActiveClass);var t=e.next("."+y.params.slideClass).addClass(y.params.slideNextClass);y.params.loop&&0===t.length&&y.slides.eq(0).addClass(y.params.slideNextClass);var i=e.prev("."+y.params.slideClass).addClass(y.params.slidePrevClass);if(y.params.loop&&0===i.length&&y.slides.eq(-1).addClass(y.params.slidePrevClass),y.paginationContainer&&y.paginationContainer.length>0){var s,r=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length;if(y.params.loop?(s=Math.ceil((y.activeIndex-y.loopedSlides)/y.params.slidesPerGroup),s>y.slides.length-1-2*y.loopedSlides&&(s-=y.slides.length-2*y.loopedSlides),s>r-1&&(s-=r),s<0&&"bullets"!==y.params.paginationType&&(s=r+s)):s="undefined"!=typeof y.snapIndex?y.snapIndex:y.activeIndex||0,"bullets"===y.params.paginationType&&y.bullets&&y.bullets.length>0&&(y.bullets.removeClass(y.params.bulletActiveClass),y.paginationContainer.length>1?y.bullets.each(function(){a(this).index()===s&&a(this).addClass(y.params.bulletActiveClass)}):y.bullets.eq(s).addClass(y.params.bulletActiveClass)),"fraction"===y.params.paginationType&&(y.paginationContainer.find("."+y.params.paginationCurrentClass).text(s+1),y.paginationContainer.find("."+y.params.paginationTotalClass).text(r)),"progress"===y.params.paginationType){var n=(s+1)/r,o=n,l=1;y.isHorizontal()||(l=n,o=1),y.paginationContainer.find("."+y.params.paginationProgressbarClass).transform("translate3d(0,0,0) scaleX("+o+") scaleY("+l+")").transition(y.params.speed)}"custom"===y.params.paginationType&&y.params.paginationCustomRender&&(y.paginationContainer.html(y.params.paginationCustomRender(y,s+1,r)),y.emit("onPaginationRendered",y,y.paginationContainer[0]))}y.params.loop||(y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.isBeginning?(y.prevButton.addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(y.prevButton)):(y.prevButton.removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(y.prevButton))),y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.isEnd?(y.nextButton.addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(y.nextButton)):(y.nextButton.removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(y.nextButton))))},y.updatePagination=function(){if(y.params.pagination&&y.paginationContainer&&y.paginationContainer.length>0){var e="";if("bullets"===y.params.paginationType){for(var a=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length,t=0;t<a;t++)e+=y.params.paginationBulletRender?y.params.paginationBulletRender(t,y.params.bulletClass):"<"+y.params.paginationElement+' class="'+y.params.bulletClass+'"></'+y.params.paginationElement+">";y.paginationContainer.html(e),y.bullets=y.paginationContainer.find("."+y.params.bulletClass),y.params.paginationClickable&&y.params.a11y&&y.a11y&&y.a11y.initPagination()}"fraction"===y.params.paginationType&&(e=y.params.paginationFractionRender?y.params.paginationFractionRender(y,y.params.paginationCurrentClass,y.params.paginationTotalClass):'<span class="'+y.params.paginationCurrentClass+'"></span> / <span class="'+y.params.paginationTotalClass+'"></span>',y.paginationContainer.html(e)),"progress"===y.params.paginationType&&(e=y.params.paginationProgressRender?y.params.paginationProgressRender(y,y.params.paginationProgressbarClass):'<span class="'+y.params.paginationProgressbarClass+'"></span>',y.paginationContainer.html(e)),"custom"!==y.params.paginationType&&y.emit("onPaginationRendered",y,y.paginationContainer[0])}},y.update=function(e){function a(){i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate()),y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses()}if(y.updateContainerSize(),y.updateSlidesSize(),y.updateProgress(),y.updatePagination(),y.updateClasses(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),e){var t,i;y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode?(a(),y.params.autoHeight&&y.updateAutoHeight()):(t=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0),t||a())}else y.params.autoHeight&&y.updateAutoHeight()},y.onResize=function(e){y.params.breakpoints&&y.setBreakpoint();var a=y.params.allowSwipeToPrev,t=y.params.allowSwipeToNext;y.params.allowSwipeToPrev=y.params.allowSwipeToNext=!0,y.updateContainerSize(),y.updateSlidesSize(),("auto"===y.params.slidesPerView||y.params.freeMode||e)&&y.updatePagination(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),y.controller&&y.controller.spline&&(y.controller.spline=void 0);var i=!1;if(y.params.freeMode){var s=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate());y.setWrapperTranslate(s),y.updateActiveIndex(),y.updateClasses(),y.params.autoHeight&&y.updateAutoHeight()}else y.updateClasses(),i=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0);y.params.lazyLoading&&!i&&y.lazy&&y.lazy.load(),y.params.allowSwipeToPrev=a,y.params.allowSwipeToNext=t};var T=["mousedown","mousemove","mouseup"];window.navigator.pointerEnabled?T=["pointerdown","pointermove","pointerup"]:window.navigator.msPointerEnabled&&(T=["MSPointerDown","MSPointerMove","MSPointerUp"]),y.touchEvents={start:y.support.touch||!y.params.simulateTouch?"touchstart":T[0],move:y.support.touch||!y.params.simulateTouch?"touchmove":T[1],end:y.support.touch||!y.params.simulateTouch?"touchend":T[2]},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===y.params.touchEventsTarget?y.container:y.wrapper).addClass("swiper-wp8-"+y.params.direction),y.initEvents=function(e){var a=e?"off":"on",t=e?"removeEventListener":"addEventListener",s="container"===y.params.touchEventsTarget?y.container[0]:y.wrapper[0],r=y.support.touch?s:document,n=!!y.params.nested;y.browser.ie?(s[t](y.touchEvents.start,y.onTouchStart,!1),r[t](y.touchEvents.move,y.onTouchMove,n),r[t](y.touchEvents.end,y.onTouchEnd,!1)):(y.support.touch&&(s[t](y.touchEvents.start,y.onTouchStart,!1),s[t](y.touchEvents.move,y.onTouchMove,n),s[t](y.touchEvents.end,y.onTouchEnd,!1)),!i.simulateTouch||y.device.ios||y.device.android||(s[t]("mousedown",y.onTouchStart,!1),document[t]("mousemove",y.onTouchMove,n),document[t]("mouseup",y.onTouchEnd,!1))),window[t]("resize",y.onResize),y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.nextButton[a]("click",y.onClickNext),y.params.a11y&&y.a11y&&y.nextButton[a]("keydown",y.a11y.onEnterKey)),y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.prevButton[a]("click",y.onClickPrev),y.params.a11y&&y.a11y&&y.prevButton[a]("keydown",y.a11y.onEnterKey)),y.params.pagination&&y.params.paginationClickable&&(y.paginationContainer[a]("click","."+y.params.bulletClass,y.onClickIndex),y.params.a11y&&y.a11y&&y.paginationContainer[a]("keydown","."+y.params.bulletClass,y.a11y.onEnterKey)),(y.params.preventClicks||y.params.preventClicksPropagation)&&s[t]("click",y.preventClicks,!0)},y.attachEvents=function(){y.initEvents()},y.detachEvents=function(){y.initEvents(!0)},y.allowClick=!0,y.preventClicks=function(e){y.allowClick||(y.params.preventClicks&&e.preventDefault(),y.params.preventClicksPropagation&&y.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},y.onClickNext=function(e){e.preventDefault(),y.isEnd&&!y.params.loop||y.slideNext()},y.onClickPrev=function(e){e.preventDefault(),y.isBeginning&&!y.params.loop||y.slidePrev()},y.onClickIndex=function(e){e.preventDefault();var t=a(this).index()*y.params.slidesPerGroup;y.params.loop&&(t+=y.loopedSlides),y.slideTo(t)},y.updateClickedSlide=function(e){var t=n(e,"."+y.params.slideClass),i=!1;if(t)for(var s=0;s<y.slides.length;s++)y.slides[s]===t&&(i=!0);if(!t||!i)return y.clickedSlide=void 0,void(y.clickedIndex=void 0);if(y.clickedSlide=t,y.clickedIndex=a(t).index(),y.params.slideToClickedSlide&&void 0!==y.clickedIndex&&y.clickedIndex!==y.activeIndex){var r,o=y.clickedIndex;if(y.params.loop){if(y.animating)return;r=a(y.clickedSlide).attr("data-swiper-slide-index"),y.params.centeredSlides?o<y.loopedSlides-y.params.slidesPerView/2||o>y.slides.length-y.loopedSlides+y.params.slidesPerView/2?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o):o>y.slides.length-y.params.slidesPerView?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o)}else y.slideTo(o)}};var b,S,C,z,M,P,I,k,E,D,B="input, select, textarea, button",L=Date.now(),H=[];y.animating=!1,y.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var G,A;if(y.onTouchStart=function(e){if(e.originalEvent&&(e=e.originalEvent),G="touchstart"===e.type,G||!("which"in e)||3!==e.which){if(y.params.noSwiping&&n(e,"."+y.params.noSwipingClass))return void(y.allowClick=!0);if(!y.params.swipeHandler||n(e,y.params.swipeHandler)){var t=y.touches.currentX="touchstart"===e.type?e.targetTouches[0].pageX:e.pageX,i=y.touches.currentY="touchstart"===e.type?e.targetTouches[0].pageY:e.pageY;if(!(y.device.ios&&y.params.iOSEdgeSwipeDetection&&t<=y.params.iOSEdgeSwipeThreshold)){if(b=!0,S=!1,C=!0,M=void 0,A=void 0,y.touches.startX=t,y.touches.startY=i,z=Date.now(),y.allowClick=!0,y.updateContainerSize(),y.swipeDirection=void 0,y.params.threshold>0&&(k=!1),"touchstart"!==e.type){var s=!0;a(e.target).is(B)&&(s=!1),document.activeElement&&a(document.activeElement).is(B)&&document.activeElement.blur(),s&&e.preventDefault()}y.emit("onTouchStart",y,e)}}}},y.onTouchMove=function(e){if(e.originalEvent&&(e=e.originalEvent),!G||"mousemove"!==e.type){if(e.preventedByNestedSwiper)return y.touches.startX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,void(y.touches.startY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY);if(y.params.onlyExternal)return y.allowClick=!1,void(b&&(y.touches.startX=y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.startY=y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,z=Date.now()));if(G&&document.activeElement&&e.target===document.activeElement&&a(e.target).is(B))return S=!0,void(y.allowClick=!1);if(C&&y.emit("onTouchMove",y,e),!(e.targetTouches&&e.targetTouches.length>1)){if(y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,"undefined"==typeof M){var t=180*Math.atan2(Math.abs(y.touches.currentY-y.touches.startY),Math.abs(y.touches.currentX-y.touches.startX))/Math.PI;M=y.isHorizontal()?t>y.params.touchAngle:90-t>y.params.touchAngle}if(M&&y.emit("onTouchMoveOpposite",y,e),"undefined"==typeof A&&y.browser.ieTouch&&(y.touches.currentX===y.touches.startX&&y.touches.currentY===y.touches.startY||(A=!0)),b){if(M)return void(b=!1);if(A||!y.browser.ieTouch){y.allowClick=!1,y.emit("onSliderMove",y,e),e.preventDefault(),y.params.touchMoveStopPropagation&&!y.params.nested&&e.stopPropagation(),S||(i.loop&&y.fixLoop(),I=y.getWrapperTranslate(),y.setWrapperTransition(0),y.animating&&y.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),y.params.autoplay&&y.autoplaying&&(y.params.autoplayDisableOnInteraction?y.stopAutoplay():y.pauseAutoplay()),D=!1,y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grabbing",y.container[0].style.cursor="-moz-grabbin",y.container[0].style.cursor="grabbing")),S=!0;var s=y.touches.diff=y.isHorizontal()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY;s*=y.params.touchRatio,y.rtl&&(s=-s),y.swipeDirection=s>0?"prev":"next",P=s+I;var r=!0;if(s>0&&P>y.minTranslate()?(r=!1,y.params.resistance&&(P=y.minTranslate()-1+Math.pow(-y.minTranslate()+I+s,y.params.resistanceRatio))):s<0&&P<y.maxTranslate()&&(r=!1,y.params.resistance&&(P=y.maxTranslate()+1-Math.pow(y.maxTranslate()-I-s,y.params.resistanceRatio))),
+r&&(e.preventedByNestedSwiper=!0),!y.params.allowSwipeToNext&&"next"===y.swipeDirection&&P<I&&(P=I),!y.params.allowSwipeToPrev&&"prev"===y.swipeDirection&&P>I&&(P=I),y.params.followFinger){if(y.params.threshold>0){if(!(Math.abs(s)>y.params.threshold||k))return void(P=I);if(!k)return k=!0,y.touches.startX=y.touches.currentX,y.touches.startY=y.touches.currentY,P=I,void(y.touches.diff=y.isHorizontal()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY)}(y.params.freeMode||y.params.watchSlidesProgress)&&y.updateActiveIndex(),y.params.freeMode&&(0===H.length&&H.push({position:y.touches[y.isHorizontal()?"startX":"startY"],time:z}),H.push({position:y.touches[y.isHorizontal()?"currentX":"currentY"],time:(new window.Date).getTime()})),y.updateProgress(P),y.setWrapperTranslate(P)}}}}}},y.onTouchEnd=function(e){if(e.originalEvent&&(e=e.originalEvent),C&&y.emit("onTouchEnd",y,e),C=!1,b){y.params.grabCursor&&S&&b&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab");var t=Date.now(),i=t-z;if(y.allowClick&&(y.updateClickedSlide(e),y.emit("onTap",y,e),i<300&&t-L>300&&(E&&clearTimeout(E),E=setTimeout(function(){y&&(y.params.paginationHide&&y.paginationContainer.length>0&&!a(e.target).hasClass(y.params.bulletClass)&&y.paginationContainer.toggleClass(y.params.paginationHiddenClass),y.emit("onClick",y,e))},300)),i<300&&t-L<300&&(E&&clearTimeout(E),y.emit("onDoubleTap",y,e))),L=Date.now(),setTimeout(function(){y&&(y.allowClick=!0)},0),!b||!S||!y.swipeDirection||0===y.touches.diff||P===I)return void(b=S=!1);b=S=!1;var s;if(s=y.params.followFinger?y.rtl?y.translate:-y.translate:-P,y.params.freeMode){if(s<-y.minTranslate())return void y.slideTo(y.activeIndex);if(s>-y.maxTranslate())return void(y.slides.length<y.snapGrid.length?y.slideTo(y.snapGrid.length-1):y.slideTo(y.slides.length-1));if(y.params.freeModeMomentum){if(H.length>1){var r=H.pop(),n=H.pop(),o=r.position-n.position,l=r.time-n.time;y.velocity=o/l,y.velocity=y.velocity/2,Math.abs(y.velocity)<y.params.freeModeMinimumVelocity&&(y.velocity=0),(l>150||(new window.Date).getTime()-r.time>300)&&(y.velocity=0)}else y.velocity=0;H.length=0;var p=1e3*y.params.freeModeMomentumRatio,d=y.velocity*p,c=y.translate+d;y.rtl&&(c=-c);var u,m=!1,h=20*Math.abs(y.velocity)*y.params.freeModeMomentumBounceRatio;if(c<y.maxTranslate())y.params.freeModeMomentumBounce?(c+y.maxTranslate()<-h&&(c=y.maxTranslate()-h),u=y.maxTranslate(),m=!0,D=!0):c=y.maxTranslate();else if(c>y.minTranslate())y.params.freeModeMomentumBounce?(c-y.minTranslate()>h&&(c=y.minTranslate()+h),u=y.minTranslate(),m=!0,D=!0):c=y.minTranslate();else if(y.params.freeModeSticky){var f,g=0;for(g=0;g<y.snapGrid.length;g+=1)if(y.snapGrid[g]>-c){f=g;break}c=Math.abs(y.snapGrid[f]-c)<Math.abs(y.snapGrid[f-1]-c)||"next"===y.swipeDirection?y.snapGrid[f]:y.snapGrid[f-1],y.rtl||(c=-c)}if(0!==y.velocity)p=y.rtl?Math.abs((-c-y.translate)/y.velocity):Math.abs((c-y.translate)/y.velocity);else if(y.params.freeModeSticky)return void y.slideReset();y.params.freeModeMomentumBounce&&m?(y.updateProgress(u),y.setWrapperTransition(p),y.setWrapperTranslate(c),y.onTransitionStart(),y.animating=!0,y.wrapper.transitionEnd(function(){y&&D&&(y.emit("onMomentumBounce",y),y.setWrapperTransition(y.params.speed),y.setWrapperTranslate(u),y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))})):y.velocity?(y.updateProgress(c),y.setWrapperTransition(p),y.setWrapperTranslate(c),y.onTransitionStart(),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))):y.updateProgress(c),y.updateActiveIndex()}return void((!y.params.freeModeMomentum||i>=y.params.longSwipesMs)&&(y.updateProgress(),y.updateActiveIndex()))}var v,w=0,x=y.slidesSizesGrid[0];for(v=0;v<y.slidesGrid.length;v+=y.params.slidesPerGroup)"undefined"!=typeof y.slidesGrid[v+y.params.slidesPerGroup]?s>=y.slidesGrid[v]&&s<y.slidesGrid[v+y.params.slidesPerGroup]&&(w=v,x=y.slidesGrid[v+y.params.slidesPerGroup]-y.slidesGrid[v]):s>=y.slidesGrid[v]&&(w=v,x=y.slidesGrid[y.slidesGrid.length-1]-y.slidesGrid[y.slidesGrid.length-2]);var T=(s-y.slidesGrid[w])/x;if(i>y.params.longSwipesMs){if(!y.params.longSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&(T>=y.params.longSwipesRatio?y.slideTo(w+y.params.slidesPerGroup):y.slideTo(w)),"prev"===y.swipeDirection&&(T>1-y.params.longSwipesRatio?y.slideTo(w+y.params.slidesPerGroup):y.slideTo(w))}else{if(!y.params.shortSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&y.slideTo(w+y.params.slidesPerGroup),"prev"===y.swipeDirection&&y.slideTo(w)}}},y._slideTo=function(e,a){return y.slideTo(e,a,!0,!0)},y.slideTo=function(e,a,t,i){"undefined"==typeof t&&(t=!0),"undefined"==typeof e&&(e=0),e<0&&(e=0),y.snapIndex=Math.floor(e/y.params.slidesPerGroup),y.snapIndex>=y.snapGrid.length&&(y.snapIndex=y.snapGrid.length-1);var s=-y.snapGrid[y.snapIndex];y.params.autoplay&&y.autoplaying&&(i||!y.params.autoplayDisableOnInteraction?y.pauseAutoplay(a):y.stopAutoplay()),y.updateProgress(s);for(var r=0;r<y.slidesGrid.length;r++)-Math.floor(100*s)>=Math.floor(100*y.slidesGrid[r])&&(e=r);return!(!y.params.allowSwipeToNext&&s<y.translate&&s<y.minTranslate())&&(!(!y.params.allowSwipeToPrev&&s>y.translate&&s>y.maxTranslate()&&(y.activeIndex||0)!==e)&&("undefined"==typeof a&&(a=y.params.speed),y.previousIndex=y.activeIndex||0,y.activeIndex=e,y.rtl&&-s===y.translate||!y.rtl&&s===y.translate?(y.params.autoHeight&&y.updateAutoHeight(),y.updateClasses(),"slide"!==y.params.effect&&y.setWrapperTranslate(s),!1):(y.updateClasses(),y.onTransitionStart(t),0===a?(y.setWrapperTranslate(s),y.setWrapperTransition(0),y.onTransitionEnd(t)):(y.setWrapperTranslate(s),y.setWrapperTransition(a),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd(t)}))),!0)))},y.onTransitionStart=function(e){"undefined"==typeof e&&(e=!0),y.params.autoHeight&&y.updateAutoHeight(),y.lazy&&y.lazy.onTransitionStart(),e&&(y.emit("onTransitionStart",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeStart",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextStart",y):y.emit("onSlidePrevStart",y)))},y.onTransitionEnd=function(e){y.animating=!1,y.setWrapperTransition(0),"undefined"==typeof e&&(e=!0),y.lazy&&y.lazy.onTransitionEnd(),e&&(y.emit("onTransitionEnd",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeEnd",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextEnd",y):y.emit("onSlidePrevEnd",y))),y.params.hashnav&&y.hashnav&&y.hashnav.setHash()},y.slideNext=function(e,a,t){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex+y.params.slidesPerGroup,a,e,t)}return y.slideTo(y.activeIndex+y.params.slidesPerGroup,a,e,t)},y._slideNext=function(e){return y.slideNext(!0,e,!0)},y.slidePrev=function(e,a,t){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex-1,a,e,t)}return y.slideTo(y.activeIndex-1,a,e,t)},y._slidePrev=function(e){return y.slidePrev(!0,e,!0)},y.slideReset=function(e,a,t){return y.slideTo(y.activeIndex,a,e)},y.setWrapperTransition=function(e,a){y.wrapper.transition(e),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTransition(e),y.params.parallax&&y.parallax&&y.parallax.setTransition(e),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTransition(e),y.params.control&&y.controller&&y.controller.setTransition(e,a),y.emit("onSetTransition",y,e)},y.setWrapperTranslate=function(e,a,t){var i=0,r=0,n=0;y.isHorizontal()?i=y.rtl?-e:e:r=e,y.params.roundLengths&&(i=s(i),r=s(r)),y.params.virtualTranslate||(y.support.transforms3d?y.wrapper.transform("translate3d("+i+"px, "+r+"px, "+n+"px)"):y.wrapper.transform("translate("+i+"px, "+r+"px)")),y.translate=y.isHorizontal()?i:r;var o,l=y.maxTranslate()-y.minTranslate();o=0===l?0:(e-y.minTranslate())/l,o!==y.progress&&y.updateProgress(e),a&&y.updateActiveIndex(),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTranslate(y.translate),y.params.parallax&&y.parallax&&y.parallax.setTranslate(y.translate),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTranslate(y.translate),y.params.control&&y.controller&&y.controller.setTranslate(y.translate,t),y.emit("onSetTranslate",y,y.translate)},y.getTranslate=function(e,a){var t,i,s,r;return"undefined"==typeof a&&(a="x"),y.params.virtualTranslate?y.rtl?-y.translate:y.translate:(s=window.getComputedStyle(e,null),window.WebKitCSSMatrix?(i=s.transform||s.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),r=new window.WebKitCSSMatrix("none"===i?"":i)):(r=s.MozTransform||s.OTransform||s.MsTransform||s.msTransform||s.transform||s.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),t=r.toString().split(",")),"x"===a&&(i=window.WebKitCSSMatrix?r.m41:16===t.length?parseFloat(t[12]):parseFloat(t[4])),"y"===a&&(i=window.WebKitCSSMatrix?r.m42:16===t.length?parseFloat(t[13]):parseFloat(t[5])),y.rtl&&i&&(i=-i),i||0)},y.getWrapperTranslate=function(e){return"undefined"==typeof e&&(e=y.isHorizontal()?"x":"y"),y.getTranslate(y.wrapper[0],e)},y.observers=[],y.initObservers=function(){if(y.params.observeParents)for(var e=y.container.parents(),a=0;a<e.length;a++)o(e[a]);o(y.container[0],{childList:!1}),o(y.wrapper[0],{attributes:!1})},y.disconnectObservers=function(){for(var e=0;e<y.observers.length;e++)y.observers[e].disconnect();y.observers=[]},y.createLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove();var e=y.wrapper.children("."+y.params.slideClass);"auto"!==y.params.slidesPerView||y.params.loopedSlides||(y.params.loopedSlides=e.length),y.loopedSlides=parseInt(y.params.loopedSlides||y.params.slidesPerView,10),y.loopedSlides=y.loopedSlides+y.params.loopAdditionalSlides,y.loopedSlides>e.length&&(y.loopedSlides=e.length);var t,i=[],s=[];for(e.each(function(t,r){var n=a(this);t<y.loopedSlides&&s.push(r),t<e.length&&t>=e.length-y.loopedSlides&&i.push(r),n.attr("data-swiper-slide-index",t)}),t=0;t<s.length;t++)y.wrapper.append(a(s[t].cloneNode(!0)).addClass(y.params.slideDuplicateClass));for(t=i.length-1;t>=0;t--)y.wrapper.prepend(a(i[t].cloneNode(!0)).addClass(y.params.slideDuplicateClass))},y.destroyLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove(),y.slides.removeAttr("data-swiper-slide-index")},y.reLoop=function(e){var a=y.activeIndex-y.loopedSlides;y.destroyLoop(),y.createLoop(),y.updateSlidesSize(),e&&y.slideTo(a+y.loopedSlides,0,!1)},y.fixLoop=function(){var e;y.activeIndex<y.loopedSlides?(e=y.slides.length-3*y.loopedSlides+y.activeIndex,e+=y.loopedSlides,y.slideTo(e,0,!1,!0)):("auto"===y.params.slidesPerView&&y.activeIndex>=2*y.loopedSlides||y.activeIndex>y.slides.length-2*y.params.slidesPerView)&&(e=-y.slides.length+y.activeIndex+y.loopedSlides,e+=y.loopedSlides,y.slideTo(e,0,!1,!0))},y.appendSlide=function(e){if(y.params.loop&&y.destroyLoop(),"object"==typeof e&&e.length)for(var a=0;a<e.length;a++)e[a]&&y.wrapper.append(e[a]);else y.wrapper.append(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0)},y.prependSlide=function(e){y.params.loop&&y.destroyLoop();var a=y.activeIndex+1;if("object"==typeof e&&e.length){for(var t=0;t<e.length;t++)e[t]&&y.wrapper.prepend(e[t]);a=y.activeIndex+e.length}else y.wrapper.prepend(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.slideTo(a,0,!1)},y.removeSlide=function(e){y.params.loop&&(y.destroyLoop(),y.slides=y.wrapper.children("."+y.params.slideClass));var a,t=y.activeIndex;if("object"==typeof e&&e.length){for(var i=0;i<e.length;i++)a=e[i],y.slides[a]&&y.slides.eq(a).remove(),a<t&&t--;t=Math.max(t,0)}else a=e,y.slides[a]&&y.slides.eq(a).remove(),a<t&&t--,t=Math.max(t,0);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.params.loop?y.slideTo(t+y.loopedSlides,0,!1):y.slideTo(t,0,!1)},y.removeAllSlides=function(){for(var e=[],a=0;a<y.slides.length;a++)e.push(a);y.removeSlide(e)},y.effects={fade:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var a=y.slides.eq(e),t=a[0].swiperSlideOffset,i=-t;y.params.virtualTranslate||(i-=y.translate);var s=0;y.isHorizontal()||(s=i,i=0);var r=y.params.fade.crossFade?Math.max(1-Math.abs(a[0].progress),0):1+Math.min(Math.max(a[0].progress,-1),0);a.css({opacity:r}).transform("translate3d("+i+"px, "+s+"px, 0px)")}},setTransition:function(e){if(y.slides.transition(e),y.params.virtualTranslate&&0!==e){var a=!1;y.slides.transitionEnd(function(){if(!a&&y){a=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],t=0;t<e.length;t++)y.wrapper.trigger(e[t])}})}}},flip:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var t=y.slides.eq(e),i=t[0].progress;y.params.flip.limitRotation&&(i=Math.max(Math.min(t[0].progress,1),-1));var s=t[0].swiperSlideOffset,r=-180*i,n=r,o=0,l=-s,p=0;if(y.isHorizontal()?y.rtl&&(n=-n):(p=l,l=0,o=-n,n=0),t[0].style.zIndex=-Math.abs(Math.round(i))+y.slides.length,y.params.flip.slideShadows){var d=y.isHorizontal()?t.find(".swiper-slide-shadow-left"):t.find(".swiper-slide-shadow-top"),c=y.isHorizontal()?t.find(".swiper-slide-shadow-right"):t.find(".swiper-slide-shadow-bottom");0===d.length&&(d=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),t.append(d)),0===c.length&&(c=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),t.append(c)),d.length&&(d[0].style.opacity=Math.max(-i,0)),c.length&&(c[0].style.opacity=Math.max(i,0))}t.transform("translate3d("+l+"px, "+p+"px, 0px) rotateX("+o+"deg) rotateY("+n+"deg)")}},setTransition:function(e){if(y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.virtualTranslate&&0!==e){var t=!1;y.slides.eq(y.activeIndex).transitionEnd(function(){if(!t&&y&&a(this).hasClass(y.params.slideActiveClass)){t=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=0;i<e.length;i++)y.wrapper.trigger(e[i])}})}}},cube:{setTranslate:function(){var e,t=0;y.params.cube.shadow&&(y.isHorizontal()?(e=y.wrapper.find(".swiper-cube-shadow"),0===e.length&&(e=a('<div class="swiper-cube-shadow"></div>'),y.wrapper.append(e)),e.css({height:y.width+"px"})):(e=y.container.find(".swiper-cube-shadow"),0===e.length&&(e=a('<div class="swiper-cube-shadow"></div>'),y.container.append(e))));for(var i=0;i<y.slides.length;i++){var s=y.slides.eq(i),r=90*i,n=Math.floor(r/360);y.rtl&&(r=-r,n=Math.floor(-r/360));var o=Math.max(Math.min(s[0].progress,1),-1),l=0,p=0,d=0;i%4===0?(l=4*-n*y.size,d=0):(i-1)%4===0?(l=0,d=4*-n*y.size):(i-2)%4===0?(l=y.size+4*n*y.size,d=y.size):(i-3)%4===0&&(l=-y.size,d=3*y.size+4*y.size*n),y.rtl&&(l=-l),y.isHorizontal()||(p=l,l=0);var c="rotateX("+(y.isHorizontal()?0:-r)+"deg) rotateY("+(y.isHorizontal()?r:0)+"deg) translate3d("+l+"px, "+p+"px, "+d+"px)";if(o<=1&&o>-1&&(t=90*i+90*o,y.rtl&&(t=90*-i-90*o)),s.transform(c),y.params.cube.slideShadows){var u=y.isHorizontal()?s.find(".swiper-slide-shadow-left"):s.find(".swiper-slide-shadow-top"),m=y.isHorizontal()?s.find(".swiper-slide-shadow-right"):s.find(".swiper-slide-shadow-bottom");0===u.length&&(u=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),s.append(u)),0===m.length&&(m=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),s.append(m)),u.length&&(u[0].style.opacity=Math.max(-o,0)),m.length&&(m[0].style.opacity=Math.max(o,0))}}if(y.wrapper.css({"-webkit-transform-origin":"50% 50% -"+y.size/2+"px","-moz-transform-origin":"50% 50% -"+y.size/2+"px","-ms-transform-origin":"50% 50% -"+y.size/2+"px","transform-origin":"50% 50% -"+y.size/2+"px"}),y.params.cube.shadow)if(y.isHorizontal())e.transform("translate3d(0px, "+(y.width/2+y.params.cube.shadowOffset)+"px, "+-y.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+y.params.cube.shadowScale+")");else{var h=Math.abs(t)-90*Math.floor(Math.abs(t)/90),f=1.5-(Math.sin(2*h*Math.PI/360)/2+Math.cos(2*h*Math.PI/360)/2),g=y.params.cube.shadowScale,v=y.params.cube.shadowScale/f,w=y.params.cube.shadowOffset;e.transform("scale3d("+g+", 1, "+v+") translate3d(0px, "+(y.height/2+w)+"px, "+-y.height/2/v+"px) rotateX(-90deg)")}var x=y.isSafari||y.isUiWebView?-y.size/2:0;y.wrapper.transform("translate3d(0px,0,"+x+"px) rotateX("+(y.isHorizontal()?0:t)+"deg) rotateY("+(y.isHorizontal()?-t:0)+"deg)")},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.cube.shadow&&!y.isHorizontal()&&y.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var e=y.translate,t=y.isHorizontal()?-e+y.width/2:-e+y.height/2,i=y.isHorizontal()?y.params.coverflow.rotate:-y.params.coverflow.rotate,s=y.params.coverflow.depth,r=0,n=y.slides.length;r<n;r++){var o=y.slides.eq(r),l=y.slidesSizesGrid[r],p=o[0].swiperSlideOffset,d=(t-p-l/2)/l*y.params.coverflow.modifier,c=y.isHorizontal()?i*d:0,u=y.isHorizontal()?0:i*d,m=-s*Math.abs(d),h=y.isHorizontal()?0:y.params.coverflow.stretch*d,f=y.isHorizontal()?y.params.coverflow.stretch*d:0;Math.abs(f)<.001&&(f=0),Math.abs(h)<.001&&(h=0),Math.abs(m)<.001&&(m=0),Math.abs(c)<.001&&(c=0),Math.abs(u)<.001&&(u=0);var g="translate3d("+f+"px,"+h+"px,"+m+"px)  rotateX("+u+"deg) rotateY("+c+"deg)";if(o.transform(g),o[0].style.zIndex=-Math.abs(Math.round(d))+1,y.params.coverflow.slideShadows){var v=y.isHorizontal()?o.find(".swiper-slide-shadow-left"):o.find(".swiper-slide-shadow-top"),w=y.isHorizontal()?o.find(".swiper-slide-shadow-right"):o.find(".swiper-slide-shadow-bottom");0===v.length&&(v=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"left":"top")+'"></div>'),o.append(v)),0===w.length&&(w=a('<div class="swiper-slide-shadow-'+(y.isHorizontal()?"right":"bottom")+'"></div>'),o.append(w)),v.length&&(v[0].style.opacity=d>0?d:0),w.length&&(w[0].style.opacity=-d>0?-d:0)}}if(y.browser.ie){var x=y.wrapper[0].style;x.perspectiveOrigin=t+"px 50%"}},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},y.lazy={initialImageLoaded:!1,loadImageInSlide:function(e,t){if("undefined"!=typeof e&&("undefined"==typeof t&&(t=!0),0!==y.slides.length)){var i=y.slides.eq(e),s=i.find(".swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)");!i.hasClass("swiper-lazy")||i.hasClass("swiper-lazy-loaded")||i.hasClass("swiper-lazy-loading")||(s=s.add(i[0])),0!==s.length&&s.each(function(){var e=a(this);e.addClass("swiper-lazy-loading");var s=e.attr("data-background"),r=e.attr("data-src"),n=e.attr("data-srcset");y.loadImage(e[0],r||s,n,!1,function(){if(s?(e.css("background-image",'url("'+s+'")'),e.removeAttr("data-background")):(n&&(e.attr("srcset",n),e.removeAttr("data-srcset")),r&&(e.attr("src",r),e.removeAttr("data-src"))),e.addClass("swiper-lazy-loaded").removeClass("swiper-lazy-loading"),i.find(".swiper-lazy-preloader, .preloader").remove(),y.params.loop&&t){var a=i.attr("data-swiper-slide-index");if(i.hasClass(y.params.slideDuplicateClass)){var o=y.wrapper.children('[data-swiper-slide-index="'+a+'"]:not(.'+y.params.slideDuplicateClass+")");y.lazy.loadImageInSlide(o.index(),!1)}else{var l=y.wrapper.children("."+y.params.slideDuplicateClass+'[data-swiper-slide-index="'+a+'"]');y.lazy.loadImageInSlide(l.index(),!1)}}y.emit("onLazyImageReady",y,i[0],e[0])}),y.emit("onLazyImageLoad",y,i[0],e[0])})}},load:function(){var e;if(y.params.watchSlidesVisibility)y.wrapper.children("."+y.params.slideVisibleClass).each(function(){y.lazy.loadImageInSlide(a(this).index())});else if(y.params.slidesPerView>1)for(e=y.activeIndex;e<y.activeIndex+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);else y.lazy.loadImageInSlide(y.activeIndex);if(y.params.lazyLoadingInPrevNext)if(y.params.slidesPerView>1||y.params.lazyLoadingInPrevNextAmount&&y.params.lazyLoadingInPrevNextAmount>1){var t=y.params.lazyLoadingInPrevNextAmount,i=y.params.slidesPerView,s=Math.min(y.activeIndex+i+Math.max(t,i),y.slides.length),r=Math.max(y.activeIndex-Math.max(i,t),0);for(e=y.activeIndex+y.params.slidesPerView;e<s;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);for(e=r;e<y.activeIndex;e++)y.slides[e]&&y.lazy.loadImageInSlide(e)}else{var n=y.wrapper.children("."+y.params.slideNextClass);n.length>0&&y.lazy.loadImageInSlide(n.index());var o=y.wrapper.children("."+y.params.slidePrevClass);o.length>0&&y.lazy.loadImageInSlide(o.index())}},onTransitionStart:function(){y.params.lazyLoading&&(y.params.lazyLoadingOnTransitionStart||!y.params.lazyLoadingOnTransitionStart&&!y.lazy.initialImageLoaded)&&y.lazy.load()},onTransitionEnd:function(){y.params.lazyLoading&&!y.params.lazyLoadingOnTransitionStart&&y.lazy.load()}},y.scrollbar={isTouched:!1,setDragPosition:function(e){var a=y.scrollbar,t=y.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY,i=t-a.track.offset()[y.isHorizontal()?"left":"top"]-a.dragSize/2,s=-y.minTranslate()*a.moveDivider,r=-y.maxTranslate()*a.moveDivider;i<s?i=s:i>r&&(i=r),i=-i/a.moveDivider,y.updateProgress(i),y.setWrapperTranslate(i,!0)},dragStart:function(e){var a=y.scrollbar;a.isTouched=!0,e.preventDefault(),e.stopPropagation(),a.setDragPosition(e),clearTimeout(a.dragTimeout),a.track.transition(0),y.params.scrollbarHide&&a.track.css("opacity",1),y.wrapper.transition(100),a.drag.transition(100),y.emit("onScrollbarDragStart",y)},dragMove:function(e){var a=y.scrollbar;a.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,a.setDragPosition(e),y.wrapper.transition(0),a.track.transition(0),a.drag.transition(0),y.emit("onScrollbarDragMove",y))},dragEnd:function(e){var a=y.scrollbar;a.isTouched&&(a.isTouched=!1,y.params.scrollbarHide&&(clearTimeout(a.dragTimeout),a.dragTimeout=setTimeout(function(){a.track.css("opacity",0),a.track.transition(400)},1e3)),y.emit("onScrollbarDragEnd",y),y.params.scrollbarSnapOnRelease&&y.slideReset())},enableDraggable:function(){var e=y.scrollbar,t=y.support.touch?e.track:document;a(e.track).on(y.touchEvents.start,e.dragStart),a(t).on(y.touchEvents.move,e.dragMove),a(t).on(y.touchEvents.end,e.dragEnd)},disableDraggable:function(){var e=y.scrollbar,t=y.support.touch?e.track:document;a(e.track).off(y.touchEvents.start,e.dragStart),a(t).off(y.touchEvents.move,e.dragMove),a(t).off(y.touchEvents.end,e.dragEnd)},set:function(){if(y.params.scrollbar){var e=y.scrollbar;e.track=a(y.params.scrollbar),y.params.uniqueNavElements&&"string"==typeof y.params.scrollbar&&e.track.length>1&&1===y.container.find(y.params.scrollbar).length&&(e.track=y.container.find(y.params.scrollbar)),e.drag=e.track.find(".swiper-scrollbar-drag"),0===e.drag.length&&(e.drag=a('<div class="swiper-scrollbar-drag"></div>'),e.track.append(e.drag)),e.drag[0].style.width="",e.drag[0].style.height="",e.trackSize=y.isHorizontal()?e.track[0].offsetWidth:e.track[0].offsetHeight,e.divider=y.size/y.virtualSize,e.moveDivider=e.divider*(e.trackSize/y.size),e.dragSize=e.trackSize*e.divider,y.isHorizontal()?e.drag[0].style.width=e.dragSize+"px":e.drag[0].style.height=e.dragSize+"px",e.divider>=1?e.track[0].style.display="none":e.track[0].style.display="",y.params.scrollbarHide&&(e.track[0].style.opacity=0)}},setTranslate:function(){if(y.params.scrollbar){var e,a=y.scrollbar,t=(y.translate||0,a.dragSize);e=(a.trackSize-a.dragSize)*y.progress,y.rtl&&y.isHorizontal()?(e=-e,e>0?(t=a.dragSize-e,e=0):-e+a.dragSize>a.trackSize&&(t=a.trackSize+e)):e<0?(t=a.dragSize+e,e=0):e+a.dragSize>a.trackSize&&(t=a.trackSize-e),y.isHorizontal()?(y.support.transforms3d?a.drag.transform("translate3d("+e+"px, 0, 0)"):a.drag.transform("translateX("+e+"px)"),a.drag[0].style.width=t+"px"):(y.support.transforms3d?a.drag.transform("translate3d(0px, "+e+"px, 0)"):a.drag.transform("translateY("+e+"px)"),a.drag[0].style.height=t+"px"),y.params.scrollbarHide&&(clearTimeout(a.timeout),a.track[0].style.opacity=1,a.timeout=setTimeout(function(){a.track[0].style.opacity=0,a.track.transition(400)},1e3))}},setTransition:function(e){y.params.scrollbar&&y.scrollbar.drag.transition(e)}},y.controller={LinearSpline:function(e,a){this.x=e,this.y=a,this.lastIndex=e.length-1;var t,i;this.x.length;this.interpolate=function(e){return e?(i=s(this.x,e),t=i-1,(e-this.x[t])*(this.y[i]-this.y[t])/(this.x[i]-this.x[t])+this.y[t]):0};var s=function(){var e,a,t;return function(i,s){for(a=-1,e=i.length;e-a>1;)i[t=e+a>>1]<=s?a=t:e=t;return e}}()},getInterpolateFunction:function(e){y.controller.spline||(y.controller.spline=y.params.loop?new y.controller.LinearSpline(y.slidesGrid,e.slidesGrid):new y.controller.LinearSpline(y.snapGrid,e.snapGrid))},setTranslate:function(e,a){function i(a){e=a.rtl&&"horizontal"===a.params.direction?-y.translate:y.translate,"slide"===y.params.controlBy&&(y.controller.getInterpolateFunction(a),r=-y.controller.spline.interpolate(-e)),r&&"container"!==y.params.controlBy||(s=(a.maxTranslate()-a.minTranslate())/(y.maxTranslate()-y.minTranslate()),r=(e-y.minTranslate())*s+a.minTranslate()),y.params.controlInverse&&(r=a.maxTranslate()-r),a.updateProgress(r),a.setWrapperTranslate(r,!1,y),a.updateActiveIndex()}var s,r,n=y.params.control;if(y.isArray(n))for(var o=0;o<n.length;o++)n[o]!==a&&n[o]instanceof t&&i(n[o]);else n instanceof t&&a!==n&&i(n)},setTransition:function(e,a){function i(a){a.setWrapperTransition(e,y),0!==e&&(a.onTransitionStart(),a.wrapper.transitionEnd(function(){r&&(a.params.loop&&"slide"===y.params.controlBy&&a.fixLoop(),a.onTransitionEnd())}))}var s,r=y.params.control;if(y.isArray(r))for(s=0;s<r.length;s++)r[s]!==a&&r[s]instanceof t&&i(r[s]);else r instanceof t&&a!==r&&i(r)}},y.hashnav={init:function(){if(y.params.hashnav){y.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var a=0,t=0,i=y.slides.length;t<i;t++){var s=y.slides.eq(t),r=s.attr("data-hash");if(r===e&&!s.hasClass(y.params.slideDuplicateClass)){var n=s.index();y.slideTo(n,a,y.params.runCallbacksOnInit,!0)}}}},setHash:function(){y.hashnav.initialized&&y.params.hashnav&&(document.location.hash=y.slides.eq(y.activeIndex).attr("data-hash")||"")}},y.disableKeyboardControl=function(){y.params.keyboardControl=!1,a(document).off("keydown",l)},y.enableKeyboardControl=function(){y.params.keyboardControl=!0,a(document).on("keydown",l)},y.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},y.params.mousewheelControl){try{new window.WheelEvent("wheel"),y.mousewheel.event="wheel"}catch(O){(window.WheelEvent||y.container[0]&&"wheel"in y.container[0])&&(y.mousewheel.event="wheel")}!y.mousewheel.event&&window.WheelEvent,y.mousewheel.event||void 0===document.onmousewheel||(y.mousewheel.event="mousewheel"),y.mousewheel.event||(y.mousewheel.event="DOMMouseScroll")}y.disableMousewheelControl=function(){return!!y.mousewheel.event&&(y.container.off(y.mousewheel.event,p),!0)},y.enableMousewheelControl=function(){return!!y.mousewheel.event&&(y.container.on(y.mousewheel.event,p),!0)},y.parallax={setTranslate:function(){y.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){d(this,y.progress)}),y.slides.each(function(){var e=a(this);e.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var a=Math.min(Math.max(e[0].progress,-1),1);d(this,a)})})},setTransition:function(e){"undefined"==typeof e&&(e=y.params.speed),y.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=a(this),i=parseInt(t.attr("data-swiper-parallax-duration"),10)||e;0===e&&(i=0),t.transition(i)})}},y._plugins=[];for(var N in y.plugins){var R=y.plugins[N](y,y.params[N]);R&&y._plugins.push(R)}return y.callPlugins=function(e){for(var a=0;a<y._plugins.length;a++)e in y._plugins[a]&&y._plugins[a][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.emitterEventListeners={},y.emit=function(e){y.params[e]&&y.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var a;if(y.emitterEventListeners[e])for(a=0;a<y.emitterEventListeners[e].length;a++)y.emitterEventListeners[e][a](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);y.callPlugins&&y.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.on=function(e,a){return e=c(e),y.emitterEventListeners[e]||(y.emitterEventListeners[e]=[]),y.emitterEventListeners[e].push(a),y},y.off=function(e,a){var t;if(e=c(e),"undefined"==typeof a)return y.emitterEventListeners[e]=[],y;if(y.emitterEventListeners[e]&&0!==y.emitterEventListeners[e].length){for(t=0;t<y.emitterEventListeners[e].length;t++)y.emitterEventListeners[e][t]===a&&y.emitterEventListeners[e].splice(t,1);return y}},y.once=function(e,a){e=c(e);var t=function(){a(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),y.off(e,t)};return y.on(e,t),y},y.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,a){return e.attr("role",a),e},addLabel:function(e,a){return e.attr("aria-label",a),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(e){13===e.keyCode&&(a(e.target).is(y.params.nextButton)?(y.onClickNext(e),y.isEnd?y.a11y.notify(y.params.lastSlideMessage):y.a11y.notify(y.params.nextSlideMessage)):a(e.target).is(y.params.prevButton)&&(y.onClickPrev(e),y.isBeginning?y.a11y.notify(y.params.firstSlideMessage):y.a11y.notify(y.params.prevSlideMessage)),a(e.target).is("."+y.params.bulletClass)&&a(e.target)[0].click())},liveRegion:a('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var a=y.a11y.liveRegion;0!==a.length&&(a.html(""),a.html(e))},init:function(){y.params.nextButton&&y.nextButton&&y.nextButton.length>0&&(y.a11y.makeFocusable(y.nextButton),y.a11y.addRole(y.nextButton,"button"),y.a11y.addLabel(y.nextButton,y.params.nextSlideMessage)),y.params.prevButton&&y.prevButton&&y.prevButton.length>0&&(y.a11y.makeFocusable(y.prevButton),y.a11y.addRole(y.prevButton,"button"),y.a11y.addLabel(y.prevButton,y.params.prevSlideMessage)),a(y.container).append(y.a11y.liveRegion)},initPagination:function(){y.params.pagination&&y.params.paginationClickable&&y.bullets&&y.bullets.length&&y.bullets.each(function(){var e=a(this);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.paginationBulletMessage.replace(/{{index}}/,e.index()+1))})},destroy:function(){y.a11y.liveRegion&&y.a11y.liveRegion.length>0&&y.a11y.liveRegion.remove()}},y.init=function(){y.params.loop&&y.createLoop(),y.updateContainerSize(),y.updateSlidesSize(),y.updatePagination(),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.set(),y.params.scrollbarDraggable&&y.scrollbar.enableDraggable()),"slide"!==y.params.effect&&y.effects[y.params.effect]&&(y.params.loop||y.updateProgress(),y.effects[y.params.effect].setTranslate()),y.params.loop?y.slideTo(y.params.initialSlide+y.loopedSlides,0,y.params.runCallbacksOnInit):(y.slideTo(y.params.initialSlide,0,y.params.runCallbacksOnInit),0===y.params.initialSlide&&(y.parallax&&y.params.parallax&&y.parallax.setTranslate(),y.lazy&&y.params.lazyLoading&&(y.lazy.load(),y.lazy.initialImageLoaded=!0))),y.attachEvents(),y.params.observer&&y.support.observer&&y.initObservers(),y.params.preloadImages&&!y.params.lazyLoading&&y.preloadImages(),y.params.autoplay&&y.startAutoplay(),y.params.keyboardControl&&y.enableKeyboardControl&&y.enableKeyboardControl(),y.params.mousewheelControl&&y.enableMousewheelControl&&y.enableMousewheelControl(),
+y.params.hashnav&&y.hashnav&&y.hashnav.init(),y.params.a11y&&y.a11y&&y.a11y.init(),y.emit("onInit",y)},y.cleanupStyles=function(){y.container.removeClass(y.classNames.join(" ")).removeAttr("style"),y.wrapper.removeAttr("style"),y.slides&&y.slides.length&&y.slides.removeClass([y.params.slideVisibleClass,y.params.slideActiveClass,y.params.slideNextClass,y.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),y.paginationContainer&&y.paginationContainer.length&&y.paginationContainer.removeClass(y.params.paginationHiddenClass),y.bullets&&y.bullets.length&&y.bullets.removeClass(y.params.bulletActiveClass),y.params.prevButton&&a(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.nextButton&&a(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.track&&y.scrollbar.track.length&&y.scrollbar.track.removeAttr("style"),y.scrollbar.drag&&y.scrollbar.drag.length&&y.scrollbar.drag.removeAttr("style"))},y.destroy=function(e,a){y.detachEvents(),y.stopAutoplay(),y.params.scrollbar&&y.scrollbar&&y.params.scrollbarDraggable&&y.scrollbar.disableDraggable(),y.params.loop&&y.destroyLoop(),a&&y.cleanupStyles(),y.disconnectObservers(),y.params.keyboardControl&&y.disableKeyboardControl&&y.disableKeyboardControl(),y.params.mousewheelControl&&y.disableMousewheelControl&&y.disableMousewheelControl(),y.params.a11y&&y.a11y&&y.a11y.destroy(),y.emit("onDestroy"),e!==!1&&(y=null)},y.init(),y}};t.prototype={isSafari:function(){var e=navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1},device:function(){var e=navigator.userAgent,a=e.match(/(Android);?[\s\/]+([\d.]+)?/),t=e.match(/(iPad).*OS\s([\d_]+)/),i=e.match(/(iPod)(.*OS\s([\d_]+))?/),s=!t&&e.match(/(iPhone\sOS)\s([\d_]+)/);return{ios:t||s||i,android:a}}(),support:{touch:window.Modernizr&&Modernizr.touch===!0||function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)}(),transforms3d:window.Modernizr&&Modernizr.csstransforms3d===!0||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,a="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),t=0;t<a.length;t++)if(a[t]in e)return!0}(),observer:function(){return"MutationObserver"in window||"WebkitMutationObserver"in window}()},plugins:{}};for(var i=["jQuery","Zepto","Dom7"],s=0;s<i.length;s++)window[i[s]]&&e(window[i[s]]);var r;r="undefined"==typeof Dom7?window.Dom7||window.Zepto||window.jQuery:Dom7,r&&("transitionEnd"in r.fn||(r.fn.transitionEnd=function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<i.length;t++)s.off(i[t],a)}var t,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],s=this;if(e)for(t=0;t<i.length;t++)s.on(i[t],a);return this}),"transform"in r.fn||(r.fn.transform=function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this}),"transition"in r.fn||(r.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this})),window.Swiper=t}(),"undefined"!=typeof module?module.exports=window.Swiper:"function"==typeof define&&define.amd&&define([],function(){"use strict";return window.Swiper}),+function(e){"use strict";var a;e.fn.swiper=function(t){return this.each(function(){if(this){var i=e(this),s=i.data("swiper");return s||i.data("swiper",new Swiper(this,e.extend({},a,t))),s}})},a=e.fn.swiper.prototype.defaults={pagination:".swiper-pagination"}}($),+function(e){var a,t=function(e){this.initConfig(e),this.index=0};t.prototype={initConfig:function(t){this.config=e.extend({},a,t),this.activeIndex=this.lastActiveIndex=this.config.initIndex,this.config.items=this.config.items.map(function(e,a){return"string"==typeof e?{image:e,caption:""}:e}),this.tpl=e.t7.compile(this.config.tpl),this.config.autoOpen&&this.open()},open:function(a){if(this._open)return!1;if(!this.modal){this.modal=e(this.tpl(this.config)).appendTo(document.body),this.container=this.modal.find(".swiper-container"),this.wrapper=this.modal.find(".swiper-wrapper");var t=new Hammer(this.container[0]);t.get("pinch").set({enable:!0}),t.on("pinchstart",e.proxy(this.onGestureStart,this)),t.on("pinchmove",e.proxy(this.onGestureChange,this)),t.on("pinchend",e.proxy(this.onGestureEnd,this)),this.modal.on(e.touchEvents.start,e.proxy(this.onTouchStart,this)),this.modal.on(e.touchEvents.move,e.proxy(this.onTouchMove,this)),this.modal.on(e.touchEvents.end,e.proxy(this.onTouchEnd,this)),this.wrapper.transition(0),this.wrapper.transform("translate3d(-"+e(window).width()*this.config.initIndex+"px,0,0)"),this.container.find(".caption-item").eq(this.config.initIndex).addClass("active"),this.container.find(".swiper-pagination-bullet").eq(this.config.initIndex).addClass("swiper-pagination-bullet-active")}var i=this;this.modal.show().height(),this.modal.addClass("weui-photo-browser-modal-visible"),this.container.addClass("swiper-container-visible").transitionEnd(function(){i.initParams(),void 0!==a&&i.slideTo(a),i.config.onOpen&&i.config.onOpen.call(i)}),this._open=!0},close:function(){this.container.transitionEnd(e.proxy(function(){this.modal.hide(),this._open=!1,this.config.onClose&&this.config.onClose.call(this)},this)),this.container.removeClass("swiper-container-visible"),this.modal.removeClass("weui-photo-browser-modal-visible")},initParams:function(){return!this.containerHeight&&(this.windowWidth=e(window).width(),this.containerHeight=this.container.height(),this.containerWidth=this.container.width(),this.touchStart={},this.wrapperTransform=0,this.wrapperLastTransform=-e(window).width()*this.config.initIndex,this.wrapperDiff=0,this.lastScale=1,this.currentScale=1,this.imageLastTransform={x:0,y:0},this.imageTransform={x:0,y:0},this.imageDiff={x:0,y:0},void(this.imageLastDiff={x:0,y:0}))},onTouchStart:function(a){return!this.scaling&&(this.touching=!0,this.touchStart=e.getTouchPosition(a),this.touchMove=null,this.touchStartTime=+new Date,this.wrapperDiff=0,void(this.breakpointPosition=null))},onTouchMove:function(a){if(!this.touching||this.scaling)return!1;if(a.preventDefault(),this.gestureImage){var t=this.gestureImage[0].getBoundingClientRect();t.left>=0||t.right<=this.windowWidth?this.overflow=!0:this.overflow=!1}else this.oveflow=!1;var i=this.touchMove=e.getTouchPosition(a);if(1===this.currentScale||this.overflow)this.breakpointPosition?this.wrapperDiff=i.x-this.breakpointPosition.x:this.wrapperDiff=i.x-this.touchStart.x,0===this.activeIndex&&this.wrapperDiff>0&&(this.wrapperDiff=Math.pow(this.wrapperDiff,.8)),this.activeIndex===this.config.items.length-1&&this.wrapperDiff<0&&(this.wrapperDiff=-Math.pow(-this.wrapperDiff,.8)),this.wrapperTransform=this.wrapperLastTransform+this.wrapperDiff,this.doWrapperTransform();else{this.gestureImage;this.imageDiff={x:i.x-this.touchStart.x,y:i.y-this.touchStart.y},this.imageTransform={x:this.imageDiff.x+this.imageLastTransform.x,y:this.imageDiff.y+this.imageLastTransform.y},this.doImageTransform(),this.breakpointPosition=i,this.imageLastDiff=this.imageDiff}},onTouchEnd:function(e){if(!this.touching)return!1;if(this.touching=!1,this.scaling)return!1;var a=+new Date-this.touchStartTime;return a<200&&(!this.touchMove||Math.abs(this.touchStart.x-this.touchMove.x)<=2&&Math.abs(this.touchStart.y-this.touchMove.y)<=2)?void this.onClick():(this.wrapperDiff>0?this.wrapperDiff>this.containerWidth/2||this.wrapperDiff>20&&a<300?this.slidePrev():this.slideTo(this.activeIndex,200):-this.wrapperDiff>this.containerWidth/2||-this.wrapperDiff>20&&a<300?this.slideNext():this.slideTo(this.activeIndex,200),this.imageLastTransform=this.imageTransform,void this.adjust())},onClick:function(){var e=this;this._lastClickTime&&+new Date-this._lastClickTime<300?(this.onDoubleClick(),clearTimeout(this._clickTimeout)):this._clickTimeout=setTimeout(function(){e.close()},300),this._lastClickTime=+new Date},onDoubleClick:function(){this.gestureImage=this.container.find(".swiper-slide").eq(this.activeIndex).find("img"),this.currentScale=this.currentScale>1?1:2,this.doImageTransform(200),this.adjust()},onGestureStart:function(e){this.scaling=!0,this.gestureImage=this.container.find(".swiper-slide").eq(this.activeIndex).find("img")},onGestureChange:function(e){var a=this.lastScale*e.scale;a>this.config.maxScale?a=this.config.maxScale+Math.pow(a-this.config.maxScale,.5):a<1&&(a=Math.pow(a,.5)),this.currentScale=a,this.doImageTransform()},onGestureEnd:function(e){this.currentScale>this.config.maxScale?(this.currentScale=this.config.maxScale,this.doImageTransform(200)):this.currentScale<1&&(this.currentScale=1,this.doImageTransform(200)),this.lastScale=this.currentScale,this.scaling=!1,this.adjust()},doWrapperTransform:function(e,t){if(0===e){var i=this.wrapper.css("transition-property");this.wrapper.css("transition-property","none").transform("translate3d("+this.wrapperTransform+"px, 0, 0)"),this.wrapper.css("transition-property",i),t()}else this.wrapper.transitionEnd(function(){t&&t()}),this.wrapper.transition(e||a.duration).transform("translate3d("+this.wrapperTransform+"px, 0, 0)")},doImageTransform:function(e,a){this.gestureImage&&(this.gestureImage.transition(e||0).transform("translate3d("+this.imageTransform.x+"px,"+this.imageTransform.y+"px, 0) scale("+this.currentScale+")"),this._needAdjust=!0)},adjust:function(){if(!this._needAdjust)return!1;var e=this.gestureImage;if(!e)return!1;if(1===this.currentScale)return this.imageTransform=this.imageLastDiff={x:0,y:0},void this.doImageTransform(200);var a=e[0].getBoundingClientRect();a.height<this.containerHeight?this.imageTransform.y=this.imageLastTransform.y=0:a.top>0?this.imageTransform.y=this.imageTransform.y-a.top:a.bottom<this.containerHeight&&(this.imageTransform.y=this.imageTransform.y+this.containerHeight-a.bottom),this.doImageTransform(200),this._needAdjust=!1},slideTo:function(a,t){a<0&&(a=0),a>this.config.items.length-1&&(a=this.config.items.length-1),this.lastActiveIndex=this.activeIndex,this.activeIndex=a,this.wrapperTransform=-(a*this.containerWidth),this.wrapperLastTransform=this.wrapperTransform,this.doWrapperTransform(t,e.proxy(function(){return this.lastActiveIndex!==this.activeIndex&&(this.container.find(".caption-item.active").removeClass("active"),this.container.find(".swiper-slide-active").removeClass("swiper-slide-active"),this.container.find(".swiper-pagination-bullet-active").removeClass("swiper-pagination-bullet-active"),this.container.find(".caption-item").eq(this.activeIndex).addClass("active"),this.container.find(".swiper-slide").eq(this.activeIndex).addClass("swiper-slide-active"),this.container.find(".swiper-pagination-bullet").eq(this.activeIndex).addClass("swiper-pagination-bullet-active"),this.container.find(".swiper-slide img[style]").transition(0).transform("translate3d(0,0,0) scale(1)"),this.lastScale=1,this.currentScale=1,this.imageLastTransform={x:0,y:0},this.imageTransform={x:0,y:0},this.imageDiff={x:0,y:0},this.imageLastDiff={x:0,y:0},void(this.config.onSlideChange&&this.config.onSlideChange.call(this,this.activeIndex)))},this))},slideNext:function(){return this.slideTo(this.activeIndex+1,200)},slidePrev:function(){return this.slideTo(this.activeIndex-1,200)}},a=t.prototype.defaults={items:[],autoOpen:!1,onOpen:void 0,onClose:void 0,initIndex:0,maxScale:3,onSlideChange:void 0,duration:200,tpl:'<div class="weui-photo-browser-modal">            <div class="swiper-container">              <div class="swiper-wrapper">                {{#items}}                <div class="swiper-slide">                  <div class="photo-container">                    <img src="{{image}}" />                  </div>                </div>                {{/items}}              </div>              <div class="caption">                {{#items}}                <div class="caption-item caption-item-{{@index}}">{{caption}}</div>                {{/items}}              </div>              <div class="swiper-pagination swiper-pagination-bullets">                {{#items}}                <span class="swiper-pagination-bullet"></span>                {{/items}}              </div>            </div>          </div>'},e.photoBrowser=function(e){return new t(e)}}($);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/login.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/login.js
new file mode 100644
index 0000000..77b8b2a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/login.js
@@ -0,0 +1,69 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        this.receivedEvent('deviceready');
+    },
+
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        var phone =  window.localStorage.getItem("phone");
+        if(!isEmpty(phone)){
+            $("#phone").val(phone)
+        }
+    },
+    toRegister :function(){
+        window.location = "register.html";
+    },
+    toForget :function(){
+        window.location = "findpwd.html";
+    },
+    login: function(){
+        //loading("正在处理");
+        var phone = $("#phone").val()
+        var pwd = $("#pwd").val()
+        if(isEmpty(phone)||isEmpty(pwd)){
+            return;
+        }
+        //loadingElement('loginBtn', '登录中...')
+        $.showLoading("登录中");
+        var param={
+            "username":phone,
+            "password":pwd
+        }
+        Login(param,function(ok,ret){
+            console.log(ret)
+            if(ok){
+               if(ret.code!=200){
+                 $.alert(ret.msg, "错误");
+                 //closeLoading('loginBtn')
+                 //showOk(ret.msg)
+                 $.hideLoading();
+               }else{
+                 window.localStorage.setItem("phone",phone); 
+                 window.localStorage.setItem("phoneX",ret.phone);
+                 window.localStorage.setItem("token",ret.token); 
+                 window.localStorage.setItem("tenantid",ret.tenantid); 
+                 window.localStorage.setItem("tokenexpire",ret.expire); 
+                 window.localStorage.setItem("tokentime",ret.now); 
+                 window.localStorage.setItem("userid",ret.userid);
+                 window.localStorage.setItem("signed",ret.signed); 
+                 window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                 window.localStorage.setItem("name",ret.name);  
+                 window.location = "main.html";  
+               }     
+            }else{
+               //$.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+               //closeLoading('loginBtn')
+               //showOk("请求失败了"+ret.status+",请稍后再试")
+               $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+               $.hideLoading();
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/main.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/main.js
new file mode 100644
index 0000000..87d6f53
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/main.js
@@ -0,0 +1,229 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        console.log(CURRENT_INDEX);
+        $('#scanBtn').click(function() {
+            //window.location = "scan.html";
+            app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "scan.html";
+                })
+            })
+        });
+        $('#qrcodeBtn').click(function() {
+            app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "qrcode.html";
+                })
+            })
+        });
+        $('#cardBtn').click(function() {
+            app.checkBefore(function() {
+                app.checkOther(function() {
+                    window.location = "card.html";
+                })
+            })
+        });
+        $('#billBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "bill.html";
+            })
+        });
+        $('#moreBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "bill.html";
+            })
+        });
+        $('#secBtn').click(function() {
+            app.checkBefore(function() {
+                window.location = "security.html";
+            })
+        });
+        $('#usersec').click(function() {
+            app.checkBefore(function() {
+                window.location = "security.html";
+            })
+        });
+        this.initData();
+    },
+    initData: function() {
+        this.loadBill()
+
+    },
+    loadBill: function() {
+        $("#loaddata").show()
+        $("#nodata").hide();
+        var param = {
+            "pageno": 1
+        }
+        V1Bills(param, function(ok, ret) {
+            if (ok) {
+                console.log(ret)
+                if (ret.code == 200) {
+                    $("#maingt").text(ret.t + "!")
+                    $("#user-amount").text(ret.amount)
+                    $("#user-point").text(ret.point)
+                    if (ret.needrebind) {
+                        window.localStorage.removeItem("userid");
+                    } else {
+                        window.localStorage.setItem("userid", ret.userid);
+                    }
+                    window.localStorage.setItem("signed", ret.signed);
+                    window.localStorage.setItem("paypwdset", ret.paypwdset);
+                    window.localStorage.setItem("name", ret.name);
+                    if (ret.page && ret.page.count > 0) {
+                        GLOBAL_TODAY = ret.today;
+                        GLOBAL_YESTERDAY = ret.yesterday;
+                        app.initBillView(ret.page)
+                        app.initView();
+                    } else {
+                        $("#loaddata").hide()
+                        $("#nodatahint").text("暂无数据")
+                        $("#nodata").show();
+                        app.initView();
+                    }
+                } else {
+                    $("#loaddata").hide()
+                    $("#nodatahint").text("数据加载异常")
+                    $("#nodata").show();
+                    app.initView();
+                }
+            } else {
+                $("#loaddata").hide()
+                $("#nodatahint").text("请求数据失败")
+                $("#nodata").show();
+                app.initView();
+            }
+        })
+    },
+
+    initBillView: function(page) {
+        var html = '';
+        for (var i = 0; i < page.data.length; i++) {
+            var bean = page.data[i]
+            html += '<div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail(\'' + bean.refno + '\')">';
+            html += '<div class="aui-card-list-user-avatar"><img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />';
+            html += '</div><div class="aui-card-list-user-name">';
+            html += '<div>' + bean.transdesc + '</div>';
+            if (bean.tradeflag == 'in') {
+                html += '<div class="aui-list-item-right">+' + bean.amount + '</div>';
+            } else {
+                html += '<div class="aui-list-item-right">' + bean.amount + '</div>';
+            }
+            html += '</div><div class="aui-card-list-user-info">' + formatDateNoYear(bean.transdate, bean.transtime) + '</div></div>';
+        }
+        $("#billcontent").html(html);
+        $("#loaddata").hide()
+        $("#nodata").hide();
+        $("#billcontent").show();
+        
+    },
+    initView: function() {
+        var userid = window.localStorage.getItem("userid");
+        var signed = window.localStorage.getItem("signed");
+        if (isEmpty(userid)) {
+            $("#userbank").text("未绑定");
+            $("#userbank").css("color", "red")
+        } else {
+            $("#userbank").text("已绑定");
+            $("userbank").css("color", "#757575");
+        }
+        if (isEmpty(signed) || signed != 'yes') {
+            $("#usersign").text("未签约");
+            $("#usersign").css("color", "red")
+        } else {
+            $("#usersign").text("已签约");
+            $("usersign").css("color", "#757575");
+        }
+        var phone = window.localStorage.getItem("phoneX");
+        if (!isEmpty(phone)) {
+            $("#userphone").text(phone)
+        }
+        var name = window.localStorage.getItem("name");
+        if (isEmpty(name)) {
+            $("#username").text("匿名")
+        } else {
+            $("#username").text(name)
+            $("#homename").text(name)
+        }
+    },
+    checkBefore: function(callback) {
+        var uid = window.localStorage.getItem("token");
+        if (isEmpty(uid)) {
+            window.location = "login.html";
+        } else {
+            var userid = window.localStorage.getItem("userid");
+            if (isEmpty(userid)) {
+                var cum = new auiDialog({});
+                var confirm = cum.alert({
+                    title: "提示",
+                    msg: '为了不影响您正常使用相关功能,请先绑定银行卡',
+                    buttons: ['取消', '去绑卡']
+                }, function(ret) {
+                    if (ret.buttonIndex == 2) {
+                        window.location = 'bindcard.html'
+                    }
+                })
+            } else {
+                if (callback) {
+                    callback()
+                }
+            }
+        }
+    },
+    checkOther: function(callback) {
+        var payseted = window.localStorage.getItem("paypwdset");
+        var signed = window.localStorage.getItem("signed");
+        var cum = new auiDialog({});
+        console.log(payseted, signed)
+        if (isEmpty(payseted) || !payseted || payseted != 'true') {
+            var confirm = cum.alert({
+                title: "提示",
+                msg: '您还没有设置支付密码,无法使用该功能',
+                buttons: ['取消', '去设置']
+            }, function(ret) {
+                if (ret.buttonIndex == 2) {
+                    window.location = 'paypwdset.html'
+                }
+            })
+        } else {
+            if (isEmpty(signed) || signed != 'yes') {
+                var confirm = cum.alert({
+                    title: "提示",
+                    msg: '您尚未签约代扣免密付协议,无法使用该功能',
+                    buttons: ['取消', '去签约']
+                }, function(ret) {
+                    if (ret.buttonIndex == 2) {
+                        window.location = 'signxy.html'
+                    }
+                })
+            } else {
+                if (callback) {
+                    callback()
+                }
+            }
+        }
+    },
+    toSign:function(){
+        window.location = 'signxycheck.html'
+    },
+    toBillDetail: function(refno) {
+        window.localStorage.setItem("currentrefno", refno);
+        window.location = 'billdetail.html';
+    },
+    toCard:function(){
+        var userid = window.localStorage.getItem("userid");
+        if (isEmpty(userid)) {
+            window.location = 'bindcard.html'
+        }else{
+            window.location = 'cardinfor.html'
+        }
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/mobile.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/mobile.js
new file mode 100644
index 0000000..e5abfb7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/mobile.js
@@ -0,0 +1,19 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        this.receivedEvent('deviceready');
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdmng.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdmng.js
new file mode 100644
index 0000000..e29608c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdmng.js
@@ -0,0 +1,17 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+    },
+    editPwd: function() {
+       window.location = "editpaypwd.html";
+    },
+    findPwd: function() {
+       window.location = "findpaypwd.html";
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdset.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdset.js
new file mode 100644
index 0000000..8824574
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/paypwdset.js
@@ -0,0 +1,70 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doNext: function() {
+        var pwd =  $("#pwd").val();
+        var repwd =  $("#repwd").val();
+        if(isEmpty(pwd)||isEmpty(repwd)){
+            return;
+        }
+        if(pwd.length!=6){
+            $.alert("支付密码为6位数字", "提示");
+            return;
+        }
+        if(pwd!=repwd){
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        var paypwdtype = window.localStorage.getItem("paypwdtype"); 
+        if(isEmpty(paypwdtype)){
+            paypwdtype = "new"
+        }
+        var randomcode = window.localStorage.getItem("randomcode"); 
+        if(isEmpty(randomcode)){
+            randomcode = ""
+        }
+        $.showLoading("正在保存");
+        var param={
+            "pwd":pwd,
+            "repwd":repwd,
+            "type":paypwdtype,
+            "randcode":randomcode
+        }
+        V1Paypwd(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                     window.localStorage.removeItem("randomcode"); 
+                     var signed = window.localStorage.getItem("signed"); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     window.localStorage.removeItem("paypwdtype"); 
+                     if(isEmpty(signed)||signed!='yes'){
+                        window.location='signxy.html'   
+                     }else{
+                        $.alert("支付密码设置成功", "提示", function() {
+                            if(paypwdtype=='find'){
+                                window.location='security.html'   
+                            }else{
+                                window.location='main.html'   
+                            }
+                        });
+                     }
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/pwdset.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/pwdset.js
new file mode 100644
index 0000000..e8086a5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/pwdset.js
@@ -0,0 +1,62 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doRegister: function() {
+        var pwd =  $("#pwd").val();
+        var repwd =  $("#repwd").val();
+        if(isEmpty(pwd)||isEmpty(repwd)){
+            return;
+        }
+        if(pwd.length<6){
+            $.alert("密码至少6位以上字符", "提示");
+            return;
+        }
+        if(pwd!=repwd){
+            $.alert("两次密码不一致,请确认", "提示");
+            return;
+        }
+        var uid = window.localStorage.getItem("uid"); 
+        var code = window.localStorage.getItem("code"); 
+        $.showLoading("正在保存");
+        var param={
+            "pwd":pwd,
+            "repwd":repwd,
+            "id":uid,
+            "random":code
+        }
+        console.log(param)
+        IRegister(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                     window.localStorage.removeItem("code"); 
+                     window.localStorage.setItem("phoneX",ret.phone);
+                     window.localStorage.setItem("token",ret.token); 
+                     window.localStorage.setItem("userid",ret.userid); 
+                     window.localStorage.setItem("tenantid",ret.tenantid); 
+                     window.localStorage.setItem("tokenexpire",ret.expire); 
+                     window.localStorage.setItem("tokentime",ret.now);   
+                     window.localStorage.setItem("signed",ret.signed); 
+                     window.localStorage.setItem("paypwdset",ret.paypwdset); 
+                     $.alert("密码设置成功,您可以登录系统了", "提示", function() {
+                         window.location = "main.html"; 
+                      });
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/qrcode.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/qrcode.js
new file mode 100644
index 0000000..35fe7a3
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/qrcode.js
@@ -0,0 +1,23 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("token");
+        var qrcode = new QRCode(document.getElementById("qrcode"), {
+          text: uid,
+          width: 150,
+          height: 150,
+          colorDark : "#000000",
+          colorLight : "#ffffff",
+          correctLevel : QRCode.CorrectLevel.L
+      });
+    },
+    toBillDetail :function(refno){
+        
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/register.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/register.js
new file mode 100644
index 0000000..e0214ab
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/register.js
@@ -0,0 +1,77 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        
+    },
+    doRegister: function() {
+        var phone =  $("#phone").val();
+        var code =  $("#code").val();
+        if(isEmpty(phone)||isEmpty(code)){
+            return;
+        }
+        var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意用户协议与隐私条款", "提示");
+            return;
+        }
+        $.showLoading("正在处理");
+        var param={
+            "phone":phone,
+            "code":code,
+            "platform":device.name+","+device.platform+","+device.version,
+            "uuid":device.uuid
+        }
+        console.log(param)
+        ICheckCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                console.log(ret)
+                if(ret.code==200){
+                     
+                     window.localStorage.setItem("phone",phone); 
+                     window.localStorage.setItem("uid",ret.uid); 
+                     window.localStorage.setItem("code",ret.randcode); 
+                     window.localStorage.removeItem("name"); 
+                     window.location="pwdset.html";
+                }else{
+                     $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    },
+    getCode :function(){
+        var phone =  $("#phone").val();
+        if(isEmpty(phone)){
+            return;            
+        }
+        $.showLoading("请求中");
+        var param={
+            "phone":phone
+        }
+        IGetCode(param,function(ok,ret){
+            if(ok){
+                $.hideLoading();
+                if(ret.code==200){
+                    $("#codebtn").attr("disabled","disabled")
+                    $("#codebtn").addClass("vcodedisabled")
+                    btnTime('codebtn');
+                }else{
+                    $.alert(ret.msg, "错误");
+                } 
+            }else{
+                $.hideLoading();
+                $.alert("请求失败了"+ret.status+",请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/scan.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/scan.js
new file mode 100644
index 0000000..2172970
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/scan.js
@@ -0,0 +1,129 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        console.log(2);
+        if (typeof(QRScanner) != 'undefined') {
+            //初始化检测,申请摄像头等权限
+            console.log(1);
+            QRScanner.destroy();
+            QRScanner.prepare(onDone); // show the prompt
+        } else {
+            $.alert('插件加载失败');
+        }
+        //showRet("http://ykt.supwisdom.com:9116/epay/wxpage/index")
+        function onDone(err, status) {
+            if (err) {
+                console.log(err);
+                $.alert('启动扫描出错:' + JSON.stringify(err), '提示');
+            }
+            if (status.authorized) {
+                //绑定扫描监听
+                // `QRScanner.cancelScan()` is called.
+                QRScanner.scan(displayContents);
+
+                function displayContents(err, text) {
+                    if (err) {
+                        // an error occurred, or the scan was canceled (error code `6`)
+                        $.alert('扫描出错,请稍后再试:' + JSON.stringify(err), '提示');
+                    } else {
+                        // The scan completed, display the contents of the QR code:
+                        //$.alert(text, '提示');
+                        showRet(text);
+                        QRScanner.destroy();
+                    }
+                }
+                //开始扫描,需要将页面的背景设置成透明
+                QRScanner.show();
+                console.log("QRScanner.scan");
+            } else if (status.denied) {
+                // The video preview will remain black, and scanning is disabled. We can
+                // try to ask the user to change their mind, but we'll have to send them
+                // to their device settings with `QRScanner.openSettings()`.
+                $.alert('无法请求道相机权限,请在设置中开启', '提示');
+            } else {
+                // we didn't get permission, but we didn't get permanently denied. (On
+                // Android, a denial isn't permanent unless the user checks the "Don't
+                // ask again" box.) We can ask again at the next relevant opportunity.
+                $.alert('无法请求道相机权限,请在设置中开启', '提示');
+            }
+        }
+        this.receivedEvent()
+    },
+    receivedEvent: function() {
+        var light = false;
+        $('#lightBtn').click(function() {
+            if (light) {
+                QRScanner.enableLight();
+            } else {
+                QRScanner.disableLight();
+            }
+            light = !light;
+        });
+    },
+    goPage: function() {
+        QRScanner.destroy();
+        window.location = "main.html"
+    }
+};
+app.initialize();
+var inAppBrowserRef;
+function showRet(url) {
+    if(isEmpty(url)){
+        return;
+    }
+    var userid = window.localStorage.getItem("userid"); 
+    if(url.indexOf("?")>0){
+        url=url+'&uid='+userid;
+    }else{
+        url=url+'?uid='+userid;
+    }
+    inAppBrowserRef = cordova.ThemeableBrowser.open(url, '_blank', {
+        statusbar: {
+            color: '#03a9f4ff'
+        },
+        toolbar: {
+            height: 44,
+            color: '#03a9f4ff'
+        },
+        title: {
+            color: '#ffffffff',
+            showPageTitle: true
+        },
+        backButton: {
+            image: 'back.png',
+            imagePressed: 'back.png',
+            align: 'left',
+            event: 'backPressed'
+        },
+        closeButton: {
+            image: 'close.png',
+            imagePressed: 'close.png',
+            align: 'left',
+            event: 'closePressed'
+        },
+        backButtonCanClose: true
+    }).addEventListener('backPressed', function(e) {
+        //alert('back pressed');
+    }).addEventListener('closePressed', function(e) {
+        //alert('closePressed pressed');
+        inAppBrowserRef.close();
+        window.location = "main.html"
+    }).addEventListener(cordova.ThemeableBrowser.EVT_ERR, function(e) {
+        console.error(e.message);
+    }).addEventListener(cordova.ThemeableBrowser.EVT_WRN, function(e) {
+        console.log(e.message);
+    });
+    inAppBrowserRef.addEventListener('loadstart', loadStartCallBack);
+    inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
+}
+function loadStartCallBack(params) {
+    //console.log("1",params.url);
+}
+function beforeloadCallBack(params,callback) {
+    console.log("2",params.url);
+}
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/security.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/security.js
new file mode 100644
index 0000000..3586930
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/security.js
@@ -0,0 +1,24 @@
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+  
+    onDeviceReady: function() {
+        var uid = window.localStorage.getItem("uid");
+        var phone =  window.localStorage.getItem("phoneX");
+        
+    },
+    editPwd: function() {
+       window.location = "editpwd.html";
+    },
+    toPayPwd: function() {
+       window.location = "paypwdmng.html";
+    },
+    logout:function(){
+        window.localStorage.removeItem("token");
+        window.location = "login.html";
+    }
+};
+app.initialize();
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/server.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/server.js
new file mode 100644
index 0000000..3194de9
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/server.js
@@ -0,0 +1,298 @@
+var dev = true;
+var SERVER = "";
+var GLOBAL_TODAY="";
+var GLOBAL_YESTERDAY="";
+var CURRENT_INDEX=1;
+if (dev) {
+    SERVER = "http://172.28.43.3:8099/payapi/mobileapi";
+}
+function V1Cardinfor(callback) {
+    ajaxPost("/v1/cardinfor", {}, callback)
+}
+
+function V1Pwdset(param,callback) {
+    ajaxPost("/v1/pwdset", param, callback)
+}
+
+function V1Billdetail(param,callback) {
+    ajaxPost("/v1/billdetail", param, callback)
+}
+
+function V1Bills(param,callback) {
+    ajaxPost("/v1/bills", param, callback)
+}
+
+function V1CardLost(param,callback) {
+    ajaxPost("/v1/cardlost", param, callback)
+}
+
+function V1Signbxy(param,callback) {
+    ajaxPost("/v1/signbxy", param, callback)
+}
+
+function V1Bxy(callback) {
+    ajaxPost("/v1/bxy", {}, callback)
+}
+
+function V1Paypwd(param,callback) {
+    ajaxPost("/v1/paypwd", param, callback)
+}
+function V1Code(callback) {
+    ajaxPost("/v1/code", {}, callback)
+}
+function V1Checkcode(param,callback) {
+    ajaxPost("/v1/checkcode", param, callback)
+}
+
+function V1Bindcard(param,callback) {
+    ajaxPost("/v1/bindcard", param, callback)
+}
+
+function V1Infor(callback) {
+    ajaxPost("/v1/infor", {}, callback)
+}
+
+function IRegister(param,callback) {
+    ajaxPost("/i/register", param, callback)
+}
+
+function ICheckCode(param,callback) {
+    ajaxPost("/i/checkcode", param, callback)
+}
+
+function IGetPage(callback) {
+    ajaxPost("/i/uxy", {}, callback)
+}
+
+function IGetCode(param,callback) {
+    ajaxPost("/i/code", param, callback)
+}
+
+
+function IServeTime(callback) {
+    ajaxPost("/i/time", {}, callback)
+}
+
+function Login(param, callback) {
+    ajaxPost("/login", param, callback)
+}
+
+function ajaxGet(url, callback) {
+    var token = window.localStorage.getItem("token");
+    var tenantid = window.localStorage.getItem("tenantid");
+    $.ajax({
+        url: SERVER + url,
+        type: "GET",
+        dataType: "json",
+        headers: hd,
+        crossDomain: true,
+        success: function(result) {
+            if (callback) {
+                callback(true, result)
+            }
+        },
+        error: function(status, err) {
+            if (callback) {
+                callback(false, status)
+            }
+        }
+    });
+}
+
+function ajaxPost(url, param, callback) {
+    var token = window.localStorage.getItem("token");
+    var tenantid = window.localStorage.getItem("tenantid");
+    var hd = {};
+    hd["Authorization"] = "Bearer " + token;
+    hd["X-TENANT-ID"] = tenantid;
+    console.log(param)
+    $.ajax({
+        url: SERVER + url,
+        type: "POST",
+        contentType: "application/x-www-form-urlencoded",
+        dataType: "json",
+        data: param,
+        crossDomain: true,
+        timeout: 10000,
+        headers: hd,
+        success: function(result) {
+            if (callback) {
+                callback(true, result)
+            }
+        },
+        error: function(status, err) {
+            console.log(status,err)
+            if (status && status.status == 401) {
+                window.location = "login.html";
+            } else {
+                if (callback) {
+                    callback(false, status, err)
+                }
+            }
+        }
+    });
+}
+
+
+function formatDateShort(date) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
+}
+
+function formatDate(date, flag) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6);
+    }
+    if (date.length < 12) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
+    }
+    if (flag || date.length < 14) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12) + ":" + date.substring(12, 14);
+}
+function formatDateNoYear(date,time) {
+    if (isEmpty(date)) {
+        return date;
+    }
+    if(isEmpty(time)){
+        return date;
+    }
+    if (date.length < 8||time.length<4) {
+        return date;
+    }
+    if(!isEmpty(GLOBAL_TODAY)){
+        if(date==GLOBAL_TODAY){
+            return "今天 "+time.substring(0,2)+":"+time.substring(2,4)
+        }
+    }else if(!isEmpty(GLOBAL_YESTERDAY)){
+        if(date==GLOBAL_YESTERDAY){
+            return "昨天 "+time.substring(0,2)+":"+time.substring(2,4)
+        }
+    }
+    return date.substring(4, 6) + "-" + date.substring(6, 8) + " " +time.substring(0,2)+":"+time.substring(2,4)
+}
+
+function formateDateZH(date) {
+    if (!date || date.length == 0) {
+        return date;
+    }
+    if (date.length < 6) {
+        return date;
+    }
+    if (date.length < 8) {
+        return date.substring(0, 4) + "年" + date.substring(4, 6) + "月";
+    }
+    if (date.length < 12) {
+        return date.substring(0, 4) + "年" + date.substring(4, 6) + "月" + date.substring(6, 8) + "日";
+    }
+    if (date.length < 14) {
+        return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12);
+    }
+    return date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + " " + date.substring(8, 10) + ":" + date.substring(10, 12) + ":" + date.substring(12, 14);
+}
+
+function isNull(data) {
+    return (data == "" || data == undefined || data == null) ? true : false;
+}
+
+function checkMobile(sMobile) {
+    if (!(/^1[3|4|5|7|8|9][0-9]{9}$/.test(sMobile))) {
+        return false;
+    }
+    return true;
+}
+
+function isEmpty(str) {
+    if (!str || str == 'undefined' || str == null || str == '') {
+        return true;
+    }
+    return false;
+}
+
+function timeText(stime, t) {
+    var temp = parseInt((stime - t) / 1000);
+    if (temp <= 30) {
+        return '刚刚';
+    }
+    if (temp < 60) {
+        return temp + '秒钟前';
+    }
+    temp = parseInt(temp / 60);
+    if (temp < 60) {
+        return temp + '分钟前';
+    }
+    temp = parseInt(temp / 60);
+    if (temp < 24) {
+        return temp + '小时前';
+    }
+    temp = parseInt(temp / 24);
+    if (temp < 30) {
+        return temp + '天前';
+    }
+    temp = parseInt(temp / 30);
+    if (temp < 12) {
+        return temp + '个月前';
+    }
+    temp = parseInt(temp / 12);
+    return temp + '年前';
+}
+
+function trimTxt(str) {
+    if (isEmpty(str)) {
+        return '';
+    }
+    return str;
+}
+var wait=60;
+function btnTime(id) {
+    if (wait == 0) {
+        $("#"+id).removeAttr("disabled");      
+        $("#"+id).removeClass("vcodedisabled")    
+        $("#"+id).text("获取验证码");
+        wait = 60;
+    } else {
+        $("#"+id).attr("disabled", "disabled");
+        $("#"+id).text(wait + "s");
+        wait--;
+        setTimeout(function() {
+            btnTime(id)
+        },
+        1000)
+    }
+}
+var dialog;
+function showOk(m,callback){
+    if(!dialog||dialog==null){
+        dialog = new auiDialog({});
+    }
+    dialog.alert({
+        title:"提示",
+        msg:m,
+        buttons:['确定']
+    },function(ret){
+        if(callback){
+            callback(ret)
+        }
+    })
+}
+function alertError(msg){
+    $.alert(msg, "错误");
+}
+function alertOk(msg){
+    $.alert(msg, "提示");
+}
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxy.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxy.js
new file mode 100644
index 0000000..f97f3d4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxy.js
@@ -0,0 +1,57 @@
+var db = null;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        $.showLoading("加载中");
+        V1Bxy(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#content").html(ret.page);
+                    if(isEmpty(ret.signed)||ret.signed!='yes'){
+                        $("#btn").show();   
+                        $("#content").css("bottom","135px");
+                    }else{
+                        $("#content").css("bottom","10px");
+                    }
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("加载失败了:" + ret.status, "错误");
+            }
+        })
+    },
+    agreeXY:function(){
+        var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意签约代扣协议", "提示");
+            return;
+        }
+        $.showLoading("正在请求");
+        var param={
+            "agree":agree
+        }
+        V1Signbxy(param,function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    window.localStorage.setItem("signed",ret.signed); 
+                    window.location="main.html";
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxycheck.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxycheck.js
new file mode 100644
index 0000000..f97f3d4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/signxycheck.js
@@ -0,0 +1,57 @@
+var db = null;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        $.showLoading("加载中");
+        V1Bxy(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#content").html(ret.page);
+                    if(isEmpty(ret.signed)||ret.signed!='yes'){
+                        $("#btn").show();   
+                        $("#content").css("bottom","135px");
+                    }else{
+                        $("#content").css("bottom","10px");
+                    }
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("加载失败了:" + ret.status, "错误");
+            }
+        })
+    },
+    agreeXY:function(){
+        var agree = $("input[type=checkbox]:checked").val();
+        if(isEmpty(agree)){
+            $.alert("请同意签约代扣协议", "提示");
+            return;
+        }
+        $.showLoading("正在请求");
+        var param={
+            "agree":agree
+        }
+        V1Signbxy(param,function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    window.localStorage.setItem("signed",ret.signed); 
+                    window.location="main.html";
+                }else{
+                    $.alert(ret.msg, "错误");
+                }
+            } else {
+                $.hideLoading();
+                $.alert("请求失败了:" + ret.status+"请稍后再试", "错误");
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/uxy.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/uxy.js
new file mode 100644
index 0000000..094b649
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/js/uxy.js
@@ -0,0 +1,30 @@
+var db = null;
+var app = {
+
+    // Application Constructor
+    initialize: function() {
+        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+    },
+
+    onDeviceReady: function() {
+        //$.showLoading("加载中");
+        IGetPage(function(ok, ret, err) {
+            if (ok) {
+                $.hideLoading(); 
+                if(ret.code==200){
+                    $("#content").html(ret.page)   
+                }else{
+                    /*$.alert(ret.msg, "错误", function() {
+                        window.location = "register.html";
+                    });*/
+                }
+            } else {
+                //$.hideLoading();
+                /*$.alert("加载失败了:" + ret.status, "错误", function() {
+                    window.location = "register.html";
+                });*/
+            }
+        })
+    }
+};
+app.initialize();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login.html
new file mode 100644
index 0000000..60827f3
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/>
+    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+    <title>登录</title>
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css" />
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css" />
+    <link rel="stylesheet" type="text/css" href="css/aui.css" />
+    <link rel="stylesheet" type="text/css" href="css/index.css" />
+</head>
+<body>
+    <div class="login-top">
+        大理市民卡
+    </div>
+    <section class="aui-content" >
+       <ul class="aui-list aui-form-list">
+            <li class="aui-list-item" >
+                <div class="aui-list-item-inner" >
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-mobile" ></i>
+                    </div>
+                    <div class="aui-list-item-input">
+                        <input type="tel" pattern="[0-9]*" placeholder="请输入手机号" id="phone" maxlength="11">
+                    </div>
+                </div>
+            </li>
+            <li class="aui-list-item">
+                <div class="aui-list-item-inner" >
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-lock"></i>
+                    </div>
+                    <div class="aui-list-item-input">
+                        <input type="password"  placeholder="请输入登录密码"  id="pwd" >
+                    </div>
+                </div>
+            </li>
+        </ul>
+    </section>
+    <section class="aui-content-padded" style="margin-top: 30px;">
+        <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.login()">登录</div>
+    </section>
+    <section class="aui-content-padded" style="margin-top: 30px;">
+        <a class="aui-pull-left" href="findpwd.html" style="color: #666;">
+            忘记密码?
+        </a>
+        <a class="aui-pull-right" href="register.html" style="color: #666;">
+            新用户注册
+        </a>
+    </section>
+</body>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+
+</html>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login1.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login1.html
new file mode 100644
index 0000000..9f92162
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/login1.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>登录</title>
+</head>
+<body class="cover vertical-align-center align-center blend-soft-light" style="background: #49bce9;">
+    <div class="space"></div>
+    <div class="space"></div>
+    <div class="space"></div>
+    <h1 class="text-white" style="font-size: 35px;">大理市民卡</h1>
+    <div class="space"></div>
+    <div class="space"></div>
+    <div class="row">
+        <div class="col-90 col-center">
+            <div class="list no-border opacity-60 ">
+                <div class="item icon ion-android-phone-portrait border-white border-bottom text-white" style="display: flex;">
+                    <input class="placeholder-white text-white" type="number" style="font-size: 18px;" placeholder="请输入手机号" id="phone" maxlength="11">
+                </div>
+                <div class="item icon ion-android-lock border-white border-bottom text-white" style="display: flex;margin-top: 10px;">
+                    <input class="placeholder-white text-white" type="password" style="font-size: 18px;" placeholder="请输入密码" id="pwd">
+                </div>
+            </div>
+            <div class="space"></div>
+            <div class="space"></div>
+            <button class="border-white text-white full radius" onclick="app.login()" id="loginBtn" style="font-size: 18px;">登录</button>
+            <div class="left" style="margin-top: 20px;font-size: 16px;" onclick="app.toForget()">忘记密码?</div>
+            <div class="right"  style="margin-top: 20px;font-size: 16px;" onclick="app.toRegister()"> 新用户注册</div>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+<script type="text/javascript">
+
+</script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main.html
new file mode 100644
index 0000000..57c416c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main.html
@@ -0,0 +1,275 @@
+<!doctype html>
+<html>
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
+    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
+    <link rel="stylesheet" type="text/css" href="css/aui.css" />
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css" />
+</head>
+
+<body>
+    <div id="main1">
+        <div id="maintop">
+            <section class="aui-content " style="background-color: #03a9f4 !important;">
+                <h1 class="text-white align-left" style="font-size: 26px;color: #fff;padding: 30px 20px 0 20px;"><span id="maingt">您好!</span><span id="homename"></span></h1>
+                <div class="aui-grid aui-bg-info">
+                    <div class="aui-row" id="classify">
+                        <div class="aui-col-xs-6 top-btn" id="scanBtn">
+                            <div class="center-in"><img src="img/icon_scan.png" style="width:56px;"></div>
+                            <div class="aui-grid-label top-title">扫一扫</div>
+                        </div>
+                        <div class="aui-col-xs-6 top-btn" id="qrcodeBtn">
+                            <div class="center-in"><img src="img/icon_qrcode.png" style="width:56px;"></div>
+                            <div class="aui-grid-label top-title">付款码</div>
+                        </div>
+                    </div>
+                </div>
+            </section>
+            <section class="aui-content aui-margin-b-10">
+                <div class="aui-grid">
+                    <div class="aui-row">
+                        <div class="aui-col-xs-4" id="cardBtn">
+                            <div class="center-in"><img src="img/icon_card.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">市民卡挂失</div>
+                        </div>
+                        <div class="aui-col-xs-4" id="billBtn">
+                            <div class="center-in"><img src="img/icon_bill.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">账单查询</div>
+                        </div>
+                        <div class="aui-col-xs-4" id="secBtn">
+                            <div class="center-in"><img src="img/icon_securty.png" style="width:28px;height: 28px"></div>
+                            <div class="aui-grid-label" style="margin-top:10px;">账户安全</div>
+                        </div>
+                    </div>
+                </div>
+            </section>
+            <div class="aui-card-list">
+                <div class="aui-card-list-header" style="border-bottom: 1px solid #f2f2f2">
+                    <div class="aui-font-size-14">近期交易</div>
+                    <div class="aui-list-item-right" style="font-size: 16px;color:#49bce9" id="moreBtn">更多></div>
+                </div>
+            </div>
+        </div>
+        <div style="position: absolute;top:320px;bottom:52px;width: 100%;overflow: auto;" id="maincontent">
+            <section class="aui-content">
+                <div class="weui-loadmore" id="loaddata">
+                    <i class="weui-loading"></i>
+                    <span class="weui-loadmore__tips">正在加载</span>
+                </div>
+                <div class="weui-loadmore weui-loadmore_line" id="nodata" style="display: none" onclick="app.loadBill()">
+                    <span class="weui-loadmore__tips" style="background: transparent;" id="nodatahint">暂无数据</span>
+                </div>
+                <div class="aui-card-list" id="billcontent" style="display: none">
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user" onclick="app.toBillDetail()">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_meal.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>食堂就餐</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">2019-08-09 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_water.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>生活用水</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                    <div class="aui-card-list-header aui-card-list-user">
+                        <div class="aui-card-list-user-avatar">
+                            <img src="img/icon_car.png" class="aui-margin-r-10 aui-img-round" />
+                        </div>
+                        <div class="aui-card-list-user-name">
+                            <div>交通出行</div>
+                            <div class="aui-list-item-right">+100</div>
+                        </div>
+                        <div class="aui-card-list-user-info">今天 11:05</div>
+                    </div>
+                   
+                </div>
+            </section>
+        </div>
+    </div>
+    <div id="main2" style="display: none;">
+        <header class="aui-bar aui-bar-nav" style="padding-top:25px;font-size: 22px">
+            我的
+        </header>
+        <section class="aui-content bg-white aui-margin-b-15" style=" margin-top: -2px;">
+            <div class="aui-list aui-media-list aui-list-noborder aui-bg-info user-info">
+                <div class="aui-list-item aui-list-item-middle top-btn">
+                    <div class="aui-media-list-item-inner ">
+                        <div class="aui-list-item-media" style="width:3rem;">
+                            <img src="img/icon_header.png" class="aui-img-round" id="userlogo">
+                        </div>
+                        <div class="aui-list-item-inner">
+                            <div class="aui-list-item-text text-white aui-font-size-18" id="username">匿名</div>
+                            <div class="aui-list-item-text text-white">
+                                <div><i class="aui-iconfont aui-icon-mobile aui-font-size-14"></i><span id="userphone"></span></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <section class="aui-content aui-grid ">
+                <div class="aui-row aui-margin-t-10">
+                    <div class="aui-col-xs-4 aui-border-r">
+                        <big class="aui-text-warning" id="user-amount">0.00</big>
+                        <div class="aui-gird-lable aui-font-size-12">余额</div>
+                    </div>
+                    <div class="aui-col-xs-4 aui-border-r">
+                        <big class="aui-text-success" id="user-point">0</big>
+                        <div class="aui-gird-lable aui-font-size-12">积分</div>
+                    </div>
+                    <div class="aui-col-xs-4 ">
+                        <big class="aui-text-danger" id="user-coupon">0</big>
+                        <div class="aui-gird-lable aui-font-size-12">优惠券</div>
+                    </div>
+                </div>
+            </section>
+            
+        </section>
+        <section class="aui-content">
+            <ul class="aui-list aui-list-in aui-margin-b-15">
+                <li class="aui-list-item" onclick="app.toCard()">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-cert aui-text-info"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">银行卡</div>
+                        <div class="aui-list-item-right" id="userbank"></div>
+                    </div>
+                </li>
+                <li class="aui-list-item" onclick="app.toSign()">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">签约代扣免密付</div>
+                        <div class="aui-list-item-right" id="usersign"></div>
+                    </div>
+                </li>
+            </ul>
+            <ul class="aui-list aui-list-in">
+                <li class="aui-list-item" id="usersec">
+                    <div class="aui-list-item-label-icon">
+                        <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                    </div>
+                    <div class="aui-list-item-inner aui-list-item-arrow">
+                        <div class="aui-list-item-title">账户安全</div>
+                    </div>
+                </li>
+            </ul>
+        </section>
+    </div>
+    <footer class="aui-bar aui-bar-tab aui-border-t" id="footer">
+        <div class="aui-bar-tab-item aui-active" tapmode onclick="switchTo(1)" id="tab1">
+            <i class="aui-iconfont aui-icon-home"></i>
+            <div class="aui-bar-tab-label">首页</div>
+        </div>
+        <div class="aui-bar-tab-item" tapmode onclick="switchTo(2)" id="tab2">
+            <i class="aui-iconfont aui-icon-my"></i>
+            <div class="aui-bar-tab-label">我的</div>
+        </div>
+    </footer>
+</body>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/aui-tab.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/main.js"></script>
+<script type="text/javascript">
+var tab = new auiTab({
+    element: document.getElementById("footer"),
+}, function(ret) {
+    if (ret.index == 1) {
+        $("#main1").show();
+        $("#main2").hide();
+    } else if (ret.index == 2) {
+        $("#main1").hide();
+        $("#main2").show();
+    }
+});
+$("#maincontent").css("top", $("#maintop").height())
+</script>
+
+</html>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main1.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main1.html
new file mode 100644
index 0000000..73db78e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/main1.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="mobileui/css/imports.css">
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <title>大理市民卡</title>
+</head>
+
+<body class="has-footer">
+    <div class="footer  shadow white tab tab-bottom" style="border-top: 1px solid #F2F5F5">
+        <button class="icon ion-ios-home-outline active " style="color: #49bce9;" onclick="openTab('myTabAbout')">首页</button>
+        <button class="icon ion-ios-person-outline " style="color: #49bce9;" onclick="openTab('myTabEvents')">我的</button>
+    </div>
+    <div class="tab-content active" id="myTabAbout">
+        <div>
+            <div class="mainbg cover padding align-center" style="padding:32px 20px 20px 20px;">
+                <h1 class="text-white align-left" style="font-size: 26px;">下午好!乔伟</h1>
+                <div class="space"></div>
+                <div class="item no-border row align-center">
+                    <div class="col text-red" id="scanBtn">
+                        <img src="img/icon_scan.png" style="width:48px;">
+                        <h1 class="text-white" style="margin-top:5px;font-size: 18px;">扫一扫</h1>
+                    </div>
+                    <div class="col text-grey" id="qrcodeBtn" >
+                        <img src="img/icon_qrcode.png" style="width:48px;">
+                        <h1 class="text-white" style="margin-top:5px;font-size: 18px;">付款码</h1>
+                    </div>
+                </div>
+            </div>
+            <div class="cover padding align-center white">
+                <div class="item no-border row align-center">
+                    <div class="col text-grey" id="cardBtn">
+                        <img src="img/icon_card.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">市民卡挂失</h1>
+                    </div>
+                    <div class="col text-grey" id="billBtn">
+                        <img src="img/icon_bill.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">账单查询</h1>
+                    </div>
+                    <div class="col text-grey" id="secBtn">
+                        <img src="img/icon_securty.png" style="width:28px;height: 28px">
+                        <h1 style="margin-top:5px;font-size: 14px;">账户安全</h1>
+                    </div>
+                </div>
+            </div>
+            
+        </div>
+        <div class="content" style="top:280px;bottom:52px;">
+            <div class="list white" style="border:0;">
+                <div class="item">
+                    <h2>近期交易</h2>
+                    <div class="right" style="font-size: 16px;color:#49bce9" id="moreBtn">更多></div>
+                </div>
+            </div>
+            <div class="list white" style="margin-bottom: 6px;">
+                <div class="item" onclick="app.toBillDetail()">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_meal.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>食堂就餐</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">+ 1002.5</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item" style="padding:10px;">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_water.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>生活用水</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class=" text-strong">- 0.01</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_car.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>交通出行</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">-1.00</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="left">
+                        <img class="avatar circle" src="img/icon_meal.png" style="width: 44px;height:44px;">
+                    </div>
+                    <h2>食堂就餐</h2>
+                    <p class="text-grey" style="font-size: 12px;">今天 15:20</p>
+                    <div class="right">
+                        <ul>
+                            <li class="text-strong">+ 1002.5</li>
+                            <li class="text-red text-strong">&nbsp;</li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="item">
+                    <div class="align-center" style="color: #999">
+                        暂无数据
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="tab-content" id="myTabEvents">
+        <div class="mainbg" style="height: 3.90625vh;width: 100%"></div>
+        <div class="header mainbg" style="top: 3.6vh">
+            <h1 class="align-center text-white">我的</h1>
+        </div>
+        <div style="padding-top: 48px;">
+            <div class="row padding mainbg">
+                <div class="col-25 padding">
+                    <img class="avatar circle" src="img/icon_card.png" />
+                </div>
+                <div class="col padding">
+                    <h1 class="text-big text-white">张三</h1>
+                    <p class="text-white">134****4553</p>
+                </div>
+            </div>
+            <div class="list white">
+                <div class="item">
+                    <h2>银行卡</h2>
+                    <div class="right">
+                        <small class="maincolor">已绑定</small><i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+                <div class="item">
+                    <h2>签约代扣免密付</h2>
+                    <div class="right">
+                        <small class="maincolor">已签约</small><i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+            </div>
+            <div class="list white" style="margin-top: 8px;">
+                <div class="item">
+                    <h2>账户安全</h2>
+                    <div class="right">
+                        <i class="icon ion-ios-arrow-right"></i>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="mobileui/mobileui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="mobileui/js/button.min.js"></script>
+<script type="text/javascript" src="mobileui/js/loading.min.js"></script>
+<script type="text/javascript" src="mobileui/js/toast.min.js"></script>
+<script type="text/javascript" src="mobileui/js/tab.min.js"></script>
+<script type="text/javascript" src="mobileui/js/page.min.js"></script>
+<script type="text/javascript" src="js/login.js"></script>
+<script type="text/javascript">
+</script>
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/alert.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/alert.min.css
new file mode 100755
index 0000000..272cda2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/alert.min.css
@@ -0,0 +1 @@
+.alert-mobileui{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;z-index:99999;}.alert-mobileui .alert{font-family:Roboto,Noto,sans-serif;-webkit-font-smoothing:antialiased;position:relative;border-radius:4px;box-shadow:0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12),0 8px 10px -5px rgba(0,0,0,.4);max-width:270px}.platform-ios .alert-mobileui .alert{font-family:-apple-system,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;border-radius:8px;background-color:#fff!important;box-shadow:none}.alert-mobileui .alert h1{text-align:left;font-size:20px;font-weight:500;padding:22px 22px 0 24px}.platform-ios .alert-mobileui .alert h1{font-size:17px;font-weight:500;text-align:center;color:#000!important;padding:0;padding-top:22px}.alert-mobileui .alert p{text-align:left;font-size:16px;font-weight:400;line-height:20px;padding:0 24px;margin-top:24px;margin-bottom:24px;min-height:0;opacity:.8}.platform-ios .alert-mobileui .alert p{font-size:14px;text-align:center;color:#000!important}.alert-mobileui .alert .buttons{display:inline-block;box-sizing:border-box;width:100%}.alert-mobileui .alert .buttons button{text-transform:uppercase;display:inline-block;width:auto;min-width:70px;float:right;background:0 0;border-top:none;font-size:14px;font-weight:600;outline:0;margin-right:5px;text-transform:uppercase}.platform-ios .alert-mobileui .alert .buttons button{width:100%;text-align:center;text-transform:none;font-weight:400;font-size:16px;border-top:1px solid #ddd;padding:0 8px;margin-right:0;color:rgba(24,103,194,.81)!important;background:0 0!important}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/base.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/base.min.css
new file mode 100755
index 0000000..17e3958
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/base.min.css
@@ -0,0 +1 @@
+*{-webkit-tap-highlight-color:transparent;margin:0;padding:0;box-sizing:border-box;outline:0}body{-webkit-touch-callout:none;-webkit-text-size-adjust:none;-webkit-user-select:none;background-color:#fff;font-size:14px;height:100%;margin:0;padding:0;width:100%}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}*{box-sizing:border-box;outline:0}body{font-family:Roboto,"Helvetica Neue",sans-serif;-webkit-overflow-scrolling:touch;overflow:hidden;position:absolute}body.platform-ios{font-family:-apple-system,"Helvetica Neue",Roboto,sans-serif}a{cursor:pointer;color:#000;text-decoration:none}.content{position:absolute;width:100%;overflow:auto}.left{float:left}.right{float:right}.top{position:absolute;top:0;left:0}.bottom{position:absolute;bottom:0;left:0}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.border{border-width:1px;border-style:solid}.hidden{display:none}.opacity-90{opacity:.9}.opacity-80{opacity:.8}.opacity-70{opacity:.7}.opacity-60{opacity:.6}.opacity-50{opacity:.5}.opacity-40{opacity:.4}.opacity-30{opacity:.3}.opacity-20{opacity:.2}.opacity-10{opacity:.1}.line{width:100%;height:1px;display:block;clear:both}.icon{font-size:28px}img,video{max-width:100%}p{margin-top:5px;margin-bottom:5px}.padding{padding:10px}.padding-top{padding-top:10px}.margin{margin:10px}span.padding{padding:6px;padding-top:2px;padding-bottom:2px}.radius{border-radius:4px}.radius-big{border-radius:22px}.circle{border-radius:50%}.radius-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.radius-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.radius-top{border-top-left-radius:4px;border-top-right-radius:4px}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shadow{box-shadow:1px 1px 3px rgba(0,0,0,.2)}.space{width:100%;height:20px}.space-big{width:100%;height:50px}.space-huge{width:100%;height:100px}.margin-bottom{margin-bottom:10px}.margin-top{margin-top:10px}.text-shadow{text-shadow:1px 1px 3px rgba(0,0,0,.2)}.text-small{font-size:14px}.text-small .icon,.text-small.icon{font-size:14px!important}.icon-small{font-size:14px!important}.icon-big{font-size:50px!important}.icon-huge{font-size:65px!important}.icon-extra-huge{font-size:120px!important}.text-big{font-size:22px}.text-big .icon,.text-big.icon{font-size:22px!important}.text-extra-huge{font-size:65px}.text-extra-huge .icon,.text-extra-huge.icon{font-size:65px!important}.text-huge{font-size:32px}.text-huge .icon,.text-huge.icon{font-size:32px!important}.text-light{font-weight:300}.text-bold{font-weight:700}.text-strong{font-weight:800}.float-bottom-right{position:fixed;right:15px;bottom:15px}.float-bottom-left{position:fixed;left:15px;bottom:15px}.float-bottom-center{position:fixed;margin:auto;left:0;bottom:15px}.icon-circle{width:40px;height:40px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small{width:25px;height:25px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small i{font-size:15px}.icon-circle-big{width:80px;height:80px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-big i{font-size:70px}.backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.01;z-index:9999;transition-duration:280ms}.backdrop.show{opacity:.4}.mark{border-left-width:8px!important}.red{color:rgba(255,255,255,.9);background-color:#f44336!important}.red-100,.red-200,.red-300,.red-50{color:rgba(0,0,0,.8)}.red-50,input[type=checkbox].red-50.switch::after{background-color:#ffebee!important}.red-100,input[type=checkbox].red-100.switch::after{background-color:#ffcdd2!important}.red-200,input[type=checkbox].red-200.switch::after{background-color:#ef9a9a!important}.red-300,input[type=checkbox].red-300.switch::after{background-color:#e57373!important}.pink,.red-400,.red-500,.red-600,.red-700,.red-800,.red-900{color:rgba(255,255,255,.9)}.red-400,input[type=checkbox].red-400.switch::after{background-color:#ef5350!important}.red-500,input[type=checkbox].red-500.switch::after{background-color:#f44336!important}.red-600,input[type=checkbox].red-600.switch::after{background-color:#e53935!important}.red-700,input[type=checkbox].red-700.switch::after{background-color:#d32f2f!important}.red-800,input[type=checkbox].red-800.switch::after{background-color:#c62828!important}.red-900,input[type=checkbox].red-900.switch::after{background-color:#b71c1c!important}.pink,input[type=checkbox].pink.switch::after{background-color:#e91e63!important}.pink-100,.pink-200,.pink-50{color:rgba(0,0,0,.8)}.pink-50,input[type=checkbox].pink-50.switch::after{background-color:#fce4ec!important}.pink-100,input[type=checkbox].pink-100.switch::after{background-color:#f8bbd0!important}.pink-200,input[type=checkbox].pink-200.switch::after{background-color:#f48fb1!important}.Pink-300,.pink-400,.pink-500,.pink-600,.pink-700,.pink-800,.pink-900,.purple{color:rgba(255,255,255,.9)}.Pink-300,input[type=checkbox].Pink-300.switch::after{background-color:#f06292!important}.pink-400,input[type=checkbox].pink-400.switch::after{background-color:#ec407a!important}.pink-500,input[type=checkbox].pink-500.switch::after{background-color:#e91e63!important}.pink-600,input[type=checkbox].pink-600.switch::after{background-color:#d81b60!important}.pink-700,input[type=checkbox].pink-700.switch::after{background-color:#c2185b!important}.pink-800,input[type=checkbox].pink-800.switch::after{background-color:#ad1457!important}.pink-900,input[type=checkbox].pink-900.switch::after{background-color:#880e4f!important}.purple,input[type=checkbox].purple.switch::after{background-color:#9c27b0!important}.purple-100,.purple-200,.purple-50{color:rgba(0,0,0,.8)}.purple-50,input[type=checkbox].purple-50.switch::after{background-color:#f3e5f5!important}.purple-100,input[type=checkbox].purple-100.switch::after{background-color:#e1bee7!important}.purple-200,input[type=checkbox].purple-200.switch::after{background-color:#ce93d8!important}.deep-purple,.purple-300,.purple-400,.purple-500,.purple-600,.purple-700,.purple-800,.purple-900{color:rgba(255,255,255,.9)}.purple-300,input[type=checkbox].purple-300.switch::after{background-color:#ba68c8!important}.purple-400,input[type=checkbox].purple-400.switch::after{background-color:#ab47bc!important}.purple-500,input[type=checkbox].purple-500.switch::after{background-color:#9c27b0!important}.purple-600,input[type=checkbox].purple-600.switch::after{background-color:#8e24aa!important}.purple-700,input[type=checkbox].purple-700.switch::after{background-color:#7b1fa2!important}.purple-800,input[type=checkbox].purple-800.switch::after{background-color:#6a1b9a!important}.purple-900,input[type=checkbox].purple-900.switch::after{background-color:#4a148c!important}.deep-purple,input[type=checkbox].deep-purple.switch::after{background-color:#673ab7!important}.deep-purple-50{color:rgba(0,0,0,.8);background-color:#ede7f6!important}.deep-purple-100{color:rgba(0,0,0,.8);background-color:#d1c4e9!important}.deep-purple-200{color:rgba(0,0,0,.8);background-color:#b39ddb!important}.deep-purple-300,.deep-purple-400,.deep-purple-500,.deep-purple-600,.deep-purple-700,.deep-purple-800,.deep-purple-900,.indigo{color:rgba(255,255,255,.9)}.deep-purple-300,input[type=checkbox].deep-purple-300.switch::after{background-color:#9575cd!important}.deep-purple-400,input[type=checkbox].deep-purple-400.switch::after{background-color:#7e57c2!important}.deep-purple-500,input[type=checkbox].deep-purple-500.switch::after{background-color:#673ab7!important}.deep-purple-600,input[type=checkbox].deep-purple-600.switch::after{background-color:#5e35b1!important}.deep-purple-700,input[type=checkbox].deep-purple-700.switch::after{background-color:#512da8!important}.deep-purple-800,input[type=checkbox].deep-purple-800.switch::after{background-color:#4527a0!important}.deep-purple-900,input[type=checkbox].deep-purple-900.switch::after{background-color:#311b92!important}.indigo,input[type=checkbox].indigo.switch::after{background-color:#3f51b5!important}.indigo-100,.indigo-200,.indigo-50{color:rgba(0,0,0,.8)}.indigo-50,input[type=checkbox].indigo-50.switch::after{background-color:#e8eaf6!important}.indigo-100,input[type=checkbox].indigo-100.switch::after{background-color:#c5cae9!important}.indigo-200,input[type=checkbox].indigo-200.switch::after{background-color:#9fa8da!important}.blue,.indigo-300,.indigo-400,.indigo-500,.indigo-600,.indigo-700,.indigo-800,.indigo-900{color:rgba(255,255,255,.9)}.indigo-300,input[type=checkbox].indigo-300.switch::after{background-color:#7986cb!important}.indigo-400,input[type=checkbox].indigo-400.switch::after{background-color:#5c6bc0!important}.indigo-500,input[type=checkbox].indigo-500.switch::after{background-color:#3f51b5!important}.indigo-600,input[type=checkbox].indigo-600.switch::after{background-color:#3949ab!important}.indigo-700,input[type=checkbox].indigo-700.switch::after{background-color:#303f9f!important}.indigo-800,input[type=checkbox].indigo-800.switch::after{background-color:#283593!important}.indigo-900,input[type=checkbox].indigo-900.switch::after{background-color:#1a237e!important}.blue,input[type=checkbox].blue.switch::after{background-color:#2196f3!important}.blue-100,.blue-200,.blue-300,.blue-400,.blue-50{color:rgba(0,0,0,.8)}.blue-50,input[type=checkbox].blue-50.switch::after{background-color:#e3f2fd!important}.blue-100,input[type=checkbox].blue-100.switch::after{background-color:#bbdefb!important}.blue-200,input[type=checkbox].blue-200.switch::after{background-color:#90caf9!important}.blue-300,input[type=checkbox].blue-300.switch::after{background-color:#64b5f6!important}.blue-400,input[type=checkbox].blue-400.switch::after{background-color:#42a5f5!important}.blue-500,.blue-600,.blue-700,.blue-800,.blue-900,.light-blue{color:rgba(255,255,255,.9)}.blue-500,input[type=checkbox].blue-500.switch::after{background-color:#2196f3!important}.blue-600,input[type=checkbox].blue-600.switch::after{background-color:#1e88e5!important}.blue-700,input[type=checkbox].blue-700.switch::after{background-color:#1976d2!important}.blue-800,input[type=checkbox].blue-800.switch::after{background-color:#1565c0!important}.blue-900,input[type=checkbox].blue-900.switch::after{background-color:#0d47a1!important}.light-blue,input[type=checkbox].light-blue.switch::after{background-color:#03a9f4!important}.light-blue-100,.light-blue-200,.light-blue-300,.light-blue-400,.light-blue-50,.light-blue-500{color:rgba(0,0,0,.8)}.light-blue-50,input[type=checkbox].light-blue-50.switch::after{background-color:#e1f5fe!important}.light-blue-100,input[type=checkbox].light-blue-100.switch::after{background-color:#b3e5fc!important}.light-blue-200,input[type=checkbox].light-blue-200.switch::after{background-color:#81d4fa!important}.light-blue-300,input[type=checkbox].light-blue-300.switch::after{background-color:#4fc3f7!important}.light-blue-400,input[type=checkbox].light-blue-400.switch::after{background-color:#29b6f6!important}.light-blue-500,input[type=checkbox].light-blue-500.switch::after{background-color:#03a9f4!important}.cyan,.light-blue-600,.light-blue-700,.light-blue-800,.light-blue-900{color:rgba(255,255,255,.9)}.light-blue-600,input[type=checkbox].light-blue-600.switch::after{background-color:#039be5!important}.light-blue-700,input[type=checkbox].light-blue-700.switch::after{background-color:#0288d1!important}.light-blue-800,input[type=checkbox].light-blue-800.switch::after{background-color:#0277bd!important}.light-blue-900,input[type=checkbox].light-blue-900.switch::after{background-color:#01579b!important}.cyan,input[type=checkbox].cyan.switch::after{background-color:#00bcd4!important}.cyan-100,.cyan-200,.cyan-300,.cyan-400,.cyan-50,.cyan-500,.cyan-600{color:rgba(0,0,0,.8)}.cyan-50,input[type=checkbox].cyan-50.switch::after{background-color:#e0f7fa!important}.cyan-100,input[type=checkbox].cyan-100.switch::after{background-color:#b2ebf2!important}.cyan-200,input[type=checkbox].cyan-200.switch::after{background-color:#80deea!important}.cyan-300,input[type=checkbox].cyan-300.switch::after{background-color:#4dd0e1!important}.cyan-400,input[type=checkbox].cyan-400.switch::after{background-color:#26c6da!important}.cyan-500,input[type=checkbox].cyan-500.switch::after{background-color:#00bcd4!important}.cyan-600,input[type=checkbox].cyan-600.switch::after{background-color:#00acc1!important}.cyan-700,.cyan-800,.cyan-900,.teal{color:rgba(255,255,255,.9)}.cyan-700,input[type=checkbox].cyan-700.switch::after{background-color:#0097a7!important}.cyan-800,input[type=checkbox].cyan-800.switch::after{background-color:#00838f!important}.cyan-900,input[type=checkbox].cyan-900.switch::after{background-color:#006064!important}.teal,input[type=checkbox].teal.switch::after{background-color:#009688!important}.teal-100,.teal-200,.teal-300,.teal-400,.teal-50{color:rgba(0,0,0,.8)}.teal-50,input[type=checkbox].teal-50.switch::after{background-color:#e0f2f1!important}.teal-100,input[type=checkbox].teal-100.switch::after{background-color:#b2dfdb!important}.teal-200,input[type=checkbox].teal-200.switch::after{background-color:#80cbc4!important}.teal-300,input[type=checkbox].teal-300.switch::after{background-color:#4db6ac!important}.teal-400,input[type=checkbox].teal-400.switch::after{background-color:#26a69a!important}.green,.teal-500,.teal-600,.teal-700,.teal-800,.teal-900{color:rgba(255,255,255,.9)}.teal-500,input[type=checkbox].teal-500.switch::after{background-color:#009688!important}.teal-600,input[type=checkbox].teal-600.switch::after{background-color:#00897b!important}.teal-700,input[type=checkbox].teal-700.switch::after{background-color:#00796b!important}.teal-800,input[type=checkbox].teal-800.switch::after{background-color:#00695c!important}.teal-900,input[type=checkbox].teal-900.switch::after{background-color:#004d40!important}.green,input[type=checkbox].green.switch::after{background-color:#4caf50!important}.green-100,.green-200,.green-300,.green-400,.green-50,.green-500{color:rgba(0,0,0,.8)}.green-50,input[type=checkbox].green-50.switch::after{background-color:#e8f5e9!important}.green-100,input[type=checkbox].green-100.switch::after{background-color:#c8e6c9!important}.green-200,input[type=checkbox].green-200.switch::after{background-color:#a5d6a7!important}.green-300,input[type=checkbox].green-300.switch::after{background-color:#81c784!important}.green-400,input[type=checkbox].green-400.switch::after{background-color:#66bb6a!important}.green-500,input[type=checkbox].green-500.switch::after{background-color:#4caf50!important}.green-600,.green-700,.green-800,.green-900,.light-green{color:rgba(255,255,255,.9)}.green-600,input[type=checkbox].green-600.switch::after{background-color:#43a047!important}.green-700,input[type=checkbox].green-700.switch::after{background-color:#388e3c!important}.green-800,input[type=checkbox].green-800.switch::after{background-color:#2e7d32!important}.green-900,input[type=checkbox].green-900.switch::after{background-color:#1b5e20!important}.light-green,input[type=checkbox].light-green.switch::after{background-color:#8bc34a!important}.light-green-100,.light-green-200,.light-green-300,.light-green-400,.light-green-50,.light-green-500,.light-green-600{color:rgba(0,0,0,.8)}.light-green-50,input[type=checkbox].light-green-50.switch::after{background-color:#f1f8e9!important}.light-green-100,input[type=checkbox].light-green-100.switch::after{background-color:#dcedc8!important}.light-green-200,input[type=checkbox].light-green-200.switch::after{background-color:#c5e1a5!important}.light-green-300,input[type=checkbox].light-green-300.switch::after{background-color:#aed581!important}.light-green-400,input[type=checkbox].light-green-400.switch::after{background-color:#9ccc65!important}.light-green-500,input[type=checkbox].light-green-500.switch::after{background-color:#8bc34a!important}.light-green-600,input[type=checkbox].light-green-600.switch::after{background-color:#7cb342!important}.light-green-700,.light-green-800,.light-green-900,.lime{color:rgba(255,255,255,.9)}.light-green-700,input[type=checkbox].light-green-700.switch::after{background-color:#689f38!important}.light-green-800,input[type=checkbox].light-green-800.switch::after{background-color:#558b2f!important}.light-green-900,input[type=checkbox].light-green-900.switch::after{background-color:#33691e!important}.lime,input[type=checkbox].lime.switch::after{background-color:#cddc39!important}.lime-100,.lime-200,.lime-300,.lime-400,.lime-50,.lime-500,.lime-600,.lime-700,.lime-800{color:rgba(0,0,0,.8)}.lime-50,input[type=checkbox].lime-50.switch::after{background-color:#f9fbe7!important}.lime-100,input[type=checkbox].lime-100.switch::after{background-color:#f0f4c3!important}.lime-200,input[type=checkbox].lime-200.switch::after{background-color:#e6ee9c!important}.lime-300,input[type=checkbox].lime-300.switch::after{background-color:#dce775!important}.lime-400,input[type=checkbox].lime-400.switch::after{background-color:#d4e157!important}.lime-500,input[type=checkbox].lime-500.switch::after{background-color:#cddc39!important}.lime-600,input[type=checkbox].lime-600.switch::after{background-color:#c0ca33!important}.lime-700,input[type=checkbox].lime-700.switch::after{background-color:#afb42b!important}.lime-800,input[type=checkbox].lime-800.switch::after{background-color:#9e9d24!important}.lime-900,.yellow{color:rgba(255,255,255,.9)}.lime-900,input[type=checkbox].lime-900.switch::after{background-color:#827717!important}.yellow,input[type=checkbox].yellow.switch::after{background-color:#ffeb3b!important}.yellow-100,.yellow-200,.yellow-300,.yellow-50,.yellow-500,.yellow-600,.yellow-700,.yellow-800,.yellow-900{color:rgba(0,0,0,.8)}.yellow-50,input[type=checkbox].yellow-50.switch::after{background-color:#fffde7!important}.yellow-100,input[type=checkbox].yellow-100.switch::after{background-color:#fff9c4!important}.yellow-200,input[type=checkbox].yellow-200.switch::after{background-color:#fff59d!important}.yellow-300,input[type=checkbox].yellow-300.switch::after{background-color:#fff176!important}.yellow-400{color:rgba(0,0,0,.8);background-color:#ffee58!important}.yellow-500,input[type=checkbox].yellow-500.switch::after{background-color:#ffeb3b!important}.yellow-600,input[type=checkbox].yellow-600.switch::after{background-color:#fdd835!important}.yellow-700,input[type=checkbox].yellow-700.switch::after{background-color:#fbc02d!important}.yellow-800,input[type=checkbox].yellow-800.switch::after{background-color:#f9a825!important}.yellow-900,input[type=checkbox].yellow-900.switch::after{background-color:#f57f17!important}.amber{color:rgba(255,255,255,.9);background-color:#ffc107!important}.amber-100,.amber-200,.amber-300,.amber-50,.amber-500,.amber-600,.amber-700,.amber-800,.amber-900{color:rgba(0,0,0,.8)}.amber-50,input[type=checkbox].amber-50.switch::after{background-color:#fff8e1!important}.amber-100,input[type=checkbox].amber-100.switch::after{background-color:#ffecb3!important}.amber-200,input[type=checkbox].amber-200.switch::after{background-color:#ffe082!important}.amber-300,input[type=checkbox].amber-300.switch::after{background-color:#ffd54f!important}.amber-400{color:rgba(0,0,0,.8);background-color:#ffca28!important}.amber-500,input[type=checkbox].amber-500.switch::after{background-color:#ffc107!important}.amber-600,input[type=checkbox].amber-600.switch::after{background-color:#ffb300!important}.amber-700,input[type=checkbox].amber-700.switch::after{background-color:#ffa000!important}.amber-800,input[type=checkbox].amber-800.switch::after{background-color:#ff8f00!important}.amber-900,input[type=checkbox].amber-900.switch::after{background-color:#ff6f00!important}.orange{color:rgba(255,255,255,.9);background-color:#ff9800!important}.orange-100,.orange-200,.orange-300,.orange-400,.orange-50,.orange-500,.orange-600,.orange-700{color:rgba(0,0,0,.8)}.orange-50,input[type=checkbox].orange-50.switch::after{background-color:#fff3e0!important}.orange-100,input[type=checkbox].orange-100.switch::after{background-color:#ffe0b2!important}.orange-200,input[type=checkbox].orange-200.switch::after{background-color:#ffcc80!important}.orange-300,input[type=checkbox].orange-300.switch::after{background-color:#ffb74d!important}.orange-400,input[type=checkbox].orange-400.switch::after{background-color:#ffa726!important}.orange-500,input[type=checkbox].orange-500.switch::after{background-color:#ff9800!important}.orange-600,input[type=checkbox].orange-600.switch::after{background-color:#fb8c00!important}.orange-700,input[type=checkbox].orange-700.switch::after{background-color:#f57c00!important}.deep-orange,.orange-800,.orange-900{color:rgba(255,255,255,.9)}.orange-800,input[type=checkbox].orange-800.switch::after{background-color:#ef6c00!important}.orange-900,input[type=checkbox].orange-900.switch::after{background-color:#e65100!important}.deep-orange,input[type=checkbox].deep-orange.switch::after{background-color:#ff5722!important}.deep-orange-100,.deep-orange-200,.deep-orange-300,.deep-orange-400,.deep-orange-50{color:rgba(0,0,0,.8)}.deep-orange-50,input[type=checkbox].deep-orange-50.switch::after{background-color:#fbe9e7!important}.deep-orange-100,input[type=checkbox].deep-orange-100.switch::after{background-color:#ffccbc!important}.deep-orange-200,input[type=checkbox].deep-orange-200.switch::after{background-color:#ffab91!important}.deep-orange-300,input[type=checkbox].deep-orange-300.switch::after{background-color:#ff8a65!important}.deep-orange-400,input[type=checkbox].deep-orange-400.switch::after{background-color:#ff7043!important}.brown,.deep-orange-500,.deep-orange-600,.deep-orange-700,.deep-orange-800,.deep-orange-900{color:rgba(255,255,255,.9)}.deep-orange-500,input[type=checkbox].deep-orange-500.switch::after{background-color:#ff5722!important}.deep-orange-600,input[type=checkbox].deep-orange-600.switch::after{background-color:#f4511e!important}.deep-orange-700,input[type=checkbox].deep-orange-700.switch::after{background-color:#e64a19!important}.deep-orange-800,input[type=checkbox].deep-orange-800.switch::after{background-color:#d84315!important}.deep-orange-900,input[type=checkbox].deep-orange-900.switch::after{background-color:#bf360c!important}.brown,input[type=checkbox].brown.switch::after{background-color:#795548!important}.brown-100,.brown-200,.brown-50{color:rgba(0,0,0,.8)}.brown-50,input[type=checkbox].brown-50.switch::after{background-color:#efebe9!important}.brown-100,input[type=checkbox].brown-100.switch::after{background-color:#d7ccc8!important}.brown-200,input[type=checkbox].brown-200.switch::after{background-color:#bcaaa4!important}.brown-300,.brown-400,.brown-500,.brown-600,.brown-700,.brown-800,.brown-900,.grey{color:rgba(255,255,255,.9)}.brown-300,input[type=checkbox].brown-300.switch::after{background-color:#a1887f!important}.brown-400,input[type=checkbox].brown-400.switch::after{background-color:#8d6e63!important}.brown-500,input[type=checkbox].brown-500.switch::after{background-color:#795548!important}.brown-600,input[type=checkbox].brown-600.switch::after{background-color:#6d4c41!important}.brown-700,input[type=checkbox].brown-700.switch::after{background-color:#5d4037!important}.brown-800,input[type=checkbox].brown-800.switch::after{background-color:#4e342e!important}.brown-900,input[type=checkbox].brown-900.switch::after{background-color:#3e2723!important}.grey,input[type=checkbox].grey.switch::after{background-color:#9e9e9e!important}.grey-100,.grey-200,.grey-300,.grey-400,.grey-50,.grey-500{color:rgba(0,0,0,.8)}.grey-50,input[type=checkbox].grey-50.switch::after{background-color:#fafafa!important}.grey-100,input[type=checkbox].grey-100.switch::after{background-color:#f5f5f5!important}.grey-200,input[type=checkbox].grey-200.switch::after{background-color:#eee!important}.grey-300,input[type=checkbox].grey-300.switch::after{background-color:#e0e0e0!important}.grey-400,input[type=checkbox].grey-400.switch::after{background-color:#bdbdbd!important}.grey-500,input[type=checkbox].grey-500.switch::after{background-color:#9e9e9e!important}.blue-grey,.grey-600,.grey-700,.grey-800,.grey-900{color:rgba(255,255,255,.9)}.grey-600,input[type=checkbox].grey-600.switch::after{background-color:#757575!important}.grey-700,input[type=checkbox].grey-700.switch::after{background-color:#616161!important}.grey-800,input[type=checkbox].grey-800.switch::after{background-color:#424242!important}.grey-900,input[type=checkbox].grey-900.switch::after{background-color:#212121!important}.blue-grey,input[type=checkbox].blue-grey.switch::after{background-color:#607d8b!important}.blue-grey-100,.blue-grey-200,.blue-grey-300,.blue-grey-50{color:rgba(0,0,0,.8)}.blue-grey-50,input[type=checkbox].blue-grey-50.switch::after{background-color:#eceff1!important}.blue-grey-100,input[type=checkbox].blue-grey-100.switch::after{background-color:#cfd8dc!important}.blue-grey-200,input[type=checkbox].blue-grey-200.switch::after{background-color:#b0bec5!important}.blue-grey-300,input[type=checkbox].blue-grey-300.switch::after{background-color:#90a4ae!important}.black,.blue-grey-400,.blue-grey-500,.blue-grey-600,.blue-grey-700,.blue-grey-800,.blue-grey-900{color:rgba(255,255,255,.9)}.blue-grey-400,input[type=checkbox].blue-grey-400.switch::after{background-color:#78909c!important}.transparent{background-color:rgba(0,0,0,0)!important}.blue-grey-500,input[type=checkbox].blue-grey-500.switch::after{background-color:#607d8b!important}.blue-grey-600,input[type=checkbox].blue-grey-600.switch::after{background-color:#546e7a!important}.blue-grey-700,input[type=checkbox].blue-grey-700.switch::after{background-color:#455a64!important}.blue-grey-800,input[type=checkbox].blue-grey-800.switch::after{background-color:#37474f!important}.blue-grey-900,input[type=checkbox].blue-grey-900.switch::after{background-color:#263238!important}.black,input[type=checkbox].black.switch::after{background-color:#000!important}.black-opacity-90{background-color:rgba(0,0,0,.9)}.black-opacity-70{background-color:rgba(0,0,0,.7)}.black-opacity-50{background-color:rgba(0,0,0,.5)}.black-opacity-30{background-color:rgba(0,0,0,.3)}.black-opacity-10{background-color:rgba(0,0,0,.1)}.white{color:rgba(0,0,0,.8);background-color:#fff!important}.white-opacity-90{background-color:rgba(255,255,255,.9)}.white-opacity-70{background-color:rgba(255,255,255,.7)}.white-opacity-50{background-color:rgba(255,255,255,.5)}.white-opacity-30{background-color:rgba(255,255,255,.3)}.white-opacity-10{background-color:rgba(255,255,255,.1)}.text-red,i.red{color:#f44336}.text-red-50,i.red-50{color:#ffebee}.text-red-100,i.red-100{color:#ffcdd2}.text-red-200,i.red-200{color:#ef9a9a}.text-red-300,i.red-300{color:#e57373}.text-red-400,i.red-400{color:#ef5350}.text-red-500,i.red-500{color:#f44336}.text-red-600,i.red-600{color:#e53935}.text-red-700,i.red-700{color:#d32f2f}.text-red-800,i.red-800{color:#c62828}.text-red-900,i.red-900{color:#b71c1c}.text-pink,i.pink{color:#e91e63}.text-pink-50,i.pink-50{color:#fce4ec}.text-pink-100,i.pink-100{color:#f8bbd0}.text-pink-200,i.pink-200{color:#f48fb1}.text-Pink-300,i.Pink-300{color:#f06292}.text-pink-400,i.pink-400{color:#ec407a}.text-pink-500,i.pink-500{color:#e91e63}.text-pink-600,i.pink-600{color:#d81b60}.text-pink-700,i.pink-700{color:#c2185b}.text-pink-800,i.pink-800{color:#ad1457}.text-pink-900,i.pink-900{color:#880e4f}.text-purple,i.purple{color:#9c27b0}.text-purple-50,i.purple-50{color:#f3e5f5}.text-purple-100,i.purple-100{color:#e1bee7}.text-purple-200,i.purple-200{color:#ce93d8}.text-purple-300,i.purple-300{color:#ba68c8}.text-purple-400,i.purple-400{color:#ab47bc}.text-purple-500,i.purple-500{color:#9c27b0}.text-purple-600,i.purple-600{color:#8e24aa}.text-purple-700,i.purple-700{color:#7b1fa2}.text-purple-800,i.purple-800{color:#6a1b9a}.text-purple-900,i.purple-900{color:#4a148c}.text-deep-purple,i.deep-purple{color:#673ab7}.text-deep-purple-50,i.deep-purple-50{color:#ede7f6}.text-deep-purple-100,i.deep-purple-100{color:#d1c4e9}.text-deep-purple-200,i.deep-purple-200{color:#b39ddb}.text-deep-purple-300,i.deep-purple-300{color:#9575cd}.text-deep-purple-400,i.deep-purple-400{color:#7e57c2}.text-deep-purple-500,i.deep-purple-500{color:#673ab7}.text-deep-purple-600,i.deep-purple-600{color:#5e35b1}.text-deep-purple-700,i.deep-purple-700{color:#512da8}.text-deep-purple-800,i.deep-purple-800{color:#4527a0}.text-deep-purple-900,i.deep-purple-900{color:#311b92}.text-indigo,i.indigo{color:#3f51b5}.text-indigo-50,i.indigo-50{color:#e8eaf6}.text-indigo-100,i.indigo-100{color:#c5cae9}.text-indigo-200,i.indigo-200{color:#9fa8da}.text-indigo-300,i.indigo-300{color:#7986cb}.text-indigo-400,i.indigo-400{color:#5c6bc0}.text-indigo-500,i.indigo-500{color:#3f51b5}.text-indigo-600,i.indigo-600{color:#3949ab}.text-indigo-700,i.indigo-700{color:#303f9f}.text-indigo-800,i.indigo-800{color:#283593}.text-indigo-900,i.indigo-900{color:#1a237e}.text-blue,i.blue{color:#2196f3}.text-blue-50,i.blue-50{color:#e3f2fd}.text-blue-100,i.blue-100{color:#bbdefb}.text-blue-200,i.blue-200{color:#90caf9}.text-blue-300,i.blue-300{color:#64b5f6}.text-blue-400,i.blue-400{color:#42a5f5}.text-blue-500,i.blue-500{color:#2196f3}.text-blue-600,i.blue-600{color:#1e88e5}.text-blue-700,i.blue-700{color:#1976d2}.text-blue-800,i.blue-800{color:#1565c0}.text-blue-900,i.blue-900{color:#0d47a1}.text-light-blue,i.light-blue{color:#03a9f4}.text-light-blue-50,i.light-blue-50{color:#e1f5fe}.text-light-blue-100,i.light-blue-100{color:#b3e5fc}.text-light-blue-200,i.light-blue-200{color:#81d4fa}.text-light-blue-300,i.light-blue-300{color:#4fc3f7}.text-light-blue-400,i.light-blue-400{color:#29b6f6}.text-light-blue-500,i.light-blue-500{color:#03a9f4}.text-light-blue-600,i.light-blue-600{color:#039be5}.text-light-blue-700,i.light-blue-700{color:#0288d1}.text-light-blue-800,i.light-blue-800{color:#0277bd}.text-light-blue-900,i.light-blue-900{color:#01579b}.text-cyan,i.cyan{color:#00bcd4}.text-cyan-50,i.cyan-50{color:#e0f7fa}.text-cyan-100,i.cyan-100{color:#b2ebf2}.text-cyan-200,i.cyan-200{color:#80deea}.text-cyan-300,i.cyan-300{color:#4dd0e1}.text-cyan-400,i.cyan-400{color:#26c6da}.text-cyan-500,i.cyan-500{color:#00bcd4}.text-cyan-600,i.cyan-600{color:#00acc1}.text-cyan-700,i.cyan-700{color:#0097a7}.text-cyan-800,i.cyan-800{color:#00838f}.text-cyan-900,i.cyan-900{color:#006064}.text-teal,i.teal{color:#009688}.text-teal-50,i.teal-50{color:#e0f2f1}.text-teal-100,i.teal-100{color:#b2dfdb}.text-teal-200,i.teal-200{color:#80cbc4}.text-teal-300,i.teal-300{color:#4db6ac}.text-teal-400,i.teal-400{color:#26a69a}.text-teal-500,i.teal-500{color:#009688}.text-teal-600,i.teal-600{color:#00897b}.text-teal-700,i.teal-700{color:#00796b}.text-teal-800,i.teal-800{color:#00695c}.text-teal-900,i.teal-900{color:#004d40}.text-green,i.green{color:#4caf50}.text-green-50,i.green-50{color:#e8f5e9}.text-green-100,i.green-100{color:#c8e6c9}.text-green-200,i.green-200{color:#a5d6a7}.text-green-300,i.green-300{color:#81c784}.text-green-400,i.green-400{color:#66bb6a}.text-green-500,i.green-500{color:#4caf50}.text-green-600,i.green-600{color:#43a047}.text-green-700,i.green-700{color:#388e3c}.text-green-800,i.green-800{color:#2e7d32}.text-green-900,i.green-900{color:#1b5e20}.text-light-green,i.light-green{color:#8bc34a}.text-light-green-50,i.light-green-50{color:#f1f8e9}.text-light-green-100,i.light-green-100{color:#dcedc8}.text-light-green-200,i.light-green-200{color:#c5e1a5}.text-light-green-300,i.light-green-300{color:#aed581}.text-light-green-400,i.light-green-400{color:#9ccc65}.text-light-green-500,i.light-green-500{color:#8bc34a}.text-light-green-600,i.light-green-600{color:#7cb342}.text-light-green-700,i.light-green-700{color:#689f38}.text-light-green-800,i.light-green-800{color:#558b2f}.text-light-green-900,i.light-green-900{color:#33691e}.text-lime,i.lime{color:#cddc39}.text-lime-50,i.lime-50{color:#f9fbe7}.text-lime-100,i.lime-100{color:#f0f4c3}.text-lime-200,i.lime-200{color:#e6ee9c}.text-lime-300,i.lime-300{color:#dce775}.text-lime-400,i.lime-400{color:#d4e157}.text-lime-500,i.lime-500{color:#cddc39}.text-lime-600,i.lime-600{color:#c0ca33}.text-lime-700,i.lime-700{color:#afb42b}.text-lime-800,i.lime-800{color:#9e9d24}.text-lime-900,i.lime-900{color:#827717}.text-yellow,i.yellow{color:#ffeb3b}.text-yellow-50,i.yellow-50{color:#fffde7}.text-yellow-100,i.yellow-100{color:#fff9c4}.text-yellow-200,i.yellow-200{color:#fff59d}.text-yellow-300,i.yellow-300{color:#fff176}.text-yellow-400,i.yellow-400{color:#ffee58}.text-yellow-500,i.yellow-500{color:#ffeb3b}.text-yellow-600,i.yellow-600{color:#fdd835}.text-yellow-700,i.yellow-700{color:#fbc02d}.text-yellow-800,i.yellow-800{color:#f9a825}.text-yellow-900,i.yellow-900{color:#f57f17}.text-amber,i.amber{color:#ffc107}.text-amber-50,i.amber-50{color:#fff8e1}.text-amber-100,i.amber-100{color:#ffecb3}.text-amber-200,i.amber-200{color:#ffe082}.text-amber-300,i.amber-300{color:#ffd54f}.text-amber-400,i.amber-400{color:#ffca28}.text-amber-500,i.amber-500{color:#ffc107}.text-amber-600,i.amber-600{color:#ffb300}.text-amber-700,i.amber-700{color:#ffa000}.text-amber-800,i.amber-800{color:#ff8f00}.text-amber-900,i.amber-900{color:#ff6f00}.text-orange,i.orange{color:#ff9800}.text-orange-50,i.orange-50{color:#fff3e0}.text-orange-100,i.orange-100{color:#ffe0b2}.text-orange-200,i.orange-200{color:#ffcc80}.text-orange-300,i.orange-300{color:#ffb74d}.text-orange-400,i.orange-400{color:#ffa726}.text-orange-500,i.orange-500{color:#ff9800}.text-orange-600,i.orange-600{color:#fb8c00}.text-orange-700,i.orange-700{color:#f57c00}.text-orange-800,i.orange-800{color:#ef6c00}.text-orange-900,i.orange-900{color:#e65100}.text-deep-orange,i.deep-orange{color:#ff5722}.text-deep-orange-50,i.deep-orange-50{color:#fbe9e7}.text-deep-orange-100,i.deep-orange-100{color:#ffccbc}.text-deep-orange-200,i.deep-orange-200{color:#ffab91}.text-deep-orange-300,i.deep-orange-300{color:#ff8a65}.text-deep-orange-400,i.deep-orange-400{color:#ff7043}.text-deep-orange-500,i.deep-orange-500{color:#ff5722}.text-deep-orange-600,i.deep-orange-600{color:#f4511e}.text-deep-orange-700,i.deep-orange-700{color:#e64a19}.text-deep-orange-800,i.deep-orange-800{color:#d84315}.text-deep-orange-900,i.deep-orange-900{color:#bf360c}.text-brown,i.brown{color:#795548}.text-brown-50,i.brown-50{color:#efebe9}.text-brown-100,i.brown-100{color:#d7ccc8}.text-brown-200,i.brown-200{color:#bcaaa4}.text-brown-300,i.brown-300{color:#a1887f}.text-brown-400,i.brown-400{color:#8d6e63}.text-brown-500,i.brown-500{color:#795548}.text-brown-600,i.brown-600{color:#6d4c41}.text-brown-700,i.brown-700{color:#5d4037}.text-brown-800,i.brown-800{color:#4e342e}.text-brown-900,i.brown-900{color:#3e2723}.text-grey,i.grey{color:#9e9e9e}.text-grey-50,i.grey-50{color:#fafafa}.text-grey-100,i.grey-100{color:#f5f5f5}.text-grey-200,i.grey-200{color:#eee}.text-grey-300,i.grey-300{color:#e0e0e0}.text-grey-400,i.grey-400{color:#bdbdbd}.text-grey-500,i.grey-500{color:#9e9e9e}.text-grey-600,i.grey-600{color:#757575}.text-grey-700,i.grey-700{color:#616161}.text-grey-800,i.grey-800{color:#424242}.text-grey-900,i.grey-900{color:#212121}.text-blue-grey,i.blue-grey{color:#607d8b}.text-blue-grey-50,i.blue-grey-50{color:#eceff1}.text-blue-grey-100,i.blue-grey-100{color:#cfd8dc}.text-blue-grey-200,i.blue-grey-200{color:#b0bec5}.text-blue-grey-300,i.blue-grey-300{color:#90a4ae}.text-blue-grey-400,i.blue-grey-400{color:#78909c}.text-blue-grey-500,i.blue-grey-500{color:#607d8b}.text-blue-grey-600,i.blue-grey-600{color:#546e7a}.text-blue-grey-700,i.blue-grey-700{color:#455a64}.text-blue-grey-800,i.blue-grey-800{color:#37474f}.text-blue-grey-900,i.blue-grey-900{color:#263238}.text-black,i.black{color:#000}.text-white,i.white{color:#fff}.border-red{border:1px solid #f44336}.border-red-50{border:1px solid #ffebee}.border-red-100{border:1px solid #ffcdd2}.border-red-200{border:1px solid #ef9a9a}.border-red-300{border:1px solid #e57373}.border-red-400{border:1px solid #ef5350}.border-red-500{border:1px solid #f44336}.border-red-600{border:1px solid #e53935}.border-red-700{border:1px solid #d32f2f}.border-red-800{border:1px solid #c62828}.border-red-900{border:1px solid #b71c1c}.border-pink{border:1px solid #e91e63}.border-pink-50{border:1px solid #fce4ec}.border-pink-100{border:1px solid #f8bbd0}.border-pink-200{border:1px solid #f48fb1}.border-pink-300{border:1px solid #f06292}.border-pink-400{border:1px solid #ec407a}.border-pink-500{border:1px solid #e91e63}.border-pink-600{border:1px solid #d81b60}.border-pink-700{border:1px solid #c2185b}.border-pink-800{border:1px solid #ad1457}.border-pink-900{border:1px solid #880e4f}.border-purple{border:1px solid #9c27b0}.border-purple-50{border:1px solid #f3e5f5}.border-purple-100{border:1px solid #e1bee7}.border-purple-200{border:1px solid #ce93d8}.border-purple-300{border:1px solid #ba68c8}.border-purple-400{border:1px solid #ab47bc}.border-purple-500{border:1px solid #9c27b0}.border-purple-600{border:1px solid #8e24aa}.border-purple-700{border:1px solid #7b1fa2}.border-purple-800{border:1px solid #6a1b9a}.border-purple-900{border:1px solid #4a148c}.border-deep-purple{border:1px solid #673ab7}.border-deep-purple-50{border:1px solid #ede7f6}.border-deep-purple-100{border:1px solid #d1c4e9}.border-deep-purple-200{border:1px solid #b39ddb}.border-deep-purple-300{border:1px solid #9575cd}.border-deep-purple-400{border:1px solid #7e57c2}.border-deep-purple-500{border:1px solid #673ab7}.border-deep-purple-600{border:1px solid #5e35b1}.border-deep-purple-700{border:1px solid #512da8}.border-deep-purple-800{border:1px solid #4527a0}.border-deep-purple-900{border:1px solid #311b92}.border-indigo{border:1px solid #3f51b5}.border-indigo-50{border:1px solid #e8eaf6}.border-indigo-100{border:1px solid #c5cae9}.border-indigo-200{border:1px solid #9fa8da}.border-indigo-300{border:1px solid #7986cb}.border-indigo-400{border:1px solid #5c6bc0}.border-indigo-500{border:1px solid #3f51b5}.border-indigo-600{border:1px solid #3949ab}.border-indigo-700{border:1px solid #303f9f}.border-indigo-800{border:1px solid #283593}.border-indigo-900{border:1px solid #1a237e}.border-blue{border:1px solid #2196f3}.border-blue-50{border:1px solid #e3f2fd}.border-blue-100{border:1px solid #bbdefb}.border-blue-200{border:1px solid #90caf9}.border-blue-300{border:1px solid #64b5f6}.border-blue-400{border:1px solid #42a5f5}.border-blue-500{border:1px solid #2196f3}.border-blue-600{border:1px solid #1e88e5}.border-blue-700{border:1px solid #1976d2}.border-blue-800{border:1px solid #1565c0}.border-blue-900{border:1px solid #0d47a1}.border-light-blue{border:1px solid #03a9f4}.border-light-blue-50{border:1px solid #e1f5fe}.border-light-blue-100{border:1px solid #b3e5fc}.border-light-blue-200{border:1px solid #81d4fa}.border-light-blue-300{border:1px solid #4fc3f7}.border-light-blue-400{border:1px solid #29b6f6}.border-light-blue-500{border:1px solid #03a9f4}.border-light-blue-600{border:1px solid #039be5}.border-light-blue-700{border:1px solid #0288d1}.border-light-blue-800{border:1px solid #0277bd}.border-light-blue-900{border:1px solid #01579b}.border-cyan{border:1px solid #00bcd4}.border-cyan-50{border:1px solid #e0f7fa}.border-cyan-100{border:1px solid #b2ebf2}.border-cyan-200{border:1px solid #80deea}.border-cyan-300{border:1px solid #4dd0e1}.border-cyan-400{border:1px solid #26c6da}.border-cyan-500{border:1px solid #00bcd4}.border-cyan-600{border:1px solid #00acc1}.border-cyan-700{border:1px solid #0097a7}.border-cyan-800{border:1px solid #00838f}.border-cyan-900{border:1px solid #006064}.border-teal{border:1px solid #009688}.border-teal-50{border:1px solid #e0f2f1}.border-teal-100{border:1px solid #b2dfdb}.border-teal-200{border:1px solid #80cbc4}.border-teal-300{border:1px solid #4db6ac}.border-teal-400{border:1px solid #26a69a}.border-teal-500{border:1px solid #009688}.border-teal-600{border:1px solid #00897b}.border-teal-700{border:1px solid #00796b}.border-teal-800{border:1px solid #00695c}.border-teal-900{border:1px solid #004d40}.border-green{border:1px solid #4caf50}.border-green-50{border:1px solid #e8f5e9}.border-green-100{border:1px solid #c8e6c9}.border-green-200{border:1px solid #a5d6a7}.border-green-300{border:1px solid #81c784}.border-green-400{border:1px solid #66bb6a}.border-green-500{border:1px solid #4caf50}.border-green-600{border:1px solid #43a047}.border-green-700{border:1px solid #388e3c}.border-green-800{border:1px solid #2e7d32}.border-green-900{border:1px solid #1b5e20}.border-light-green{border:1px solid #8bc34a}.border-light-green-50{border:1px solid #f1f8e9}.border-light-green-100{border:1px solid #dcedc8}.border-light-green-200{border:1px solid #c5e1a5}.border-light-green-300{border:1px solid #aed581}.border-light-green-400{border:1px solid #9ccc65}.border-light-green-500{border:1px solid #8bc34a}.border-light-green-600{border:1px solid #7cb342}.border-light-green-700{border:1px solid #689f38}.border-light-green-800{border:1px solid #558b2f}.border-light-green-900{border:1px solid #33691e}.border-lime{border:1px solid #cddc39}.border-lime-50{border:1px solid #f9fbe7}.border-lime-100{border:1px solid #f0f4c3}.border-lime-200{border:1px solid #e6ee9c}.border-lime-300{border:1px solid #dce775}.border-lime-400{border:1px solid #d4e157}.border-lime-500{border:1px solid #cddc39}.border-lime-600{border:1px solid #c0ca33}.border-lime-700{border:1px solid #afb42b}.border-lime-800{border:1px solid #9e9d24}.border-lime-900{border:1px solid #827717}.border-yellow{border:1px solid #ffeb3b}.border-yellow-50{border:1px solid #fffde7}.border-yellow-100{border:1px solid #fff9c4}.border-yellow-200{border:1px solid #fff59d}.border-yellow-300{border:1px solid #fff176}.border-yellow-400{border:1px solid #ffee58}.border-yellow-500{border:1px solid #ffeb3b}.border-yellow-600{border:1px solid #fdd835}.border-yellow-700{border:1px solid #fbc02d}.border-yellow-800{border:1px solid #f9a825}.border-yellow-900{border:1px solid #f57f17}.border-amber{border:1px solid #ffc107}.border-amber-50{border:1px solid #fff8e1}.border-amber-100{border:1px solid #ffecb3}.border-amber-200{border:1px solid #ffe082}.border-amber-300{border:1px solid #ffd54f}.border-amber-400{border:1px solid #ffca28}.border-amber-500{border:1px solid #ffc107}.border-amber-600{border:1px solid #ffb300}.border-amber-700{border:1px solid #ffa000}.border-amber-800{border:1px solid #ff8f00}.border-amber-900{border:1px solid #ff6f00}.border-orange{border:1px solid #ff9800}.border-orange-50{border:1px solid #fff3e0}.border-orange-100{border:1px solid #ffe0b2}.border-orange-200{border:1px solid #ffcc80}.border-orange-300{border:1px solid #ffb74d}.border-orange-400{border:1px solid #ffa726}.border-orange-500{border:1px solid #ff9800}.border-orange-600{border:1px solid #fb8c00}.border-orange-700{border:1px solid #f57c00}.border-orange-800{border:1px solid #ef6c00}.border-orange-900{border:1px solid #e65100}.border-deep-orange{border:1px solid #ff5722}.border-deep-orange-50{border:1px solid #fbe9e7}.border-deep-orange-100{border:1px solid #ffccbc}.border-deep-orange-200{border:1px solid #ffab91}.border-deep-orange-300{border:1px solid #ff8a65}.border-deep-orange-400{border:1px solid #ff7043}.border-deep-orange-500{border:1px solid #ff5722}.border-deep-orange-600{border:1px solid #f4511e}.border-deep-orange-700{border:1px solid #e64a19}.border-deep-orange-800{border:1px solid #d84315}.border-deep-orange-900{border:1px solid #bf360c}.border-brown{border:1px solid #795548}.border-brown-50{border:1px solid #efebe9}.border-brown-100{border:1px solid #d7ccc8}.border-brown-200{border:1px solid #bcaaa4}.border-brown-300{border:1px solid #a1887f}.border-brown-400{border:1px solid #8d6e63}.border-brown-500{border:1px solid #795548}.border-brown-600{border:1px solid #6d4c41}.border-brown-700{border:1px solid #5d4037}.border-brown-800{border:1px solid #4e342e}.border-brown-900{border:1px solid #3e2723}.border-grey{border:1px solid #9e9e9e}.border-grey-50{border:1px solid #fafafa}.border-grey-100{border:1px solid #f5f5f5}.border-grey-200{border:1px solid #eee}.border-grey-300{border:1px solid #e0e0e0}.border-grey-400{border:1px solid #bdbdbd}.border-grey-500{border:1px solid #9e9e9e}.border-grey-600{border:1px solid #757575}.border-grey-700{border:1px solid #616161}.border-grey-800{border:1px solid #424242}.border-grey-900{border:1px solid #212121}.border-blue-grey{border:1px solid #607d8b}.border-blue-grey-50{border:1px solid #eceff1}.border-blue-grey-100{border:1px solid #cfd8dc}.border-blue-grey-200{border:1px solid #b0bec5}.border-blue-grey-300{border:1px solid #90a4ae}.border-blue-grey-400{border:1px solid #78909c}.border-blue-grey-500{border:1px solid #607d8b}.border-blue-grey-600{border:1px solid #546e7a}.border-blue-grey-700{border:1px solid #455a64}.border-blue-grey-800{border:1px solid #37474f}.border-blue-grey-900{border:1px solid #263238}.border-black{border:1px solid #000}.border-white{border:1px solid #fff}@font-face{font-family:Roboto;font-style:normal;font-weight:300;src:local('Roboto Light'),local('Roboto-Light'),url(fonts/robotolight.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:local('Roboto'),local('Roboto-Regular'),url(fonts/sTdaA6j0Psb920Vjv-mrzH-_kf6ByYO6CLYdB4HQE-Y.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:900;src:local('Roboto Black'),local('Roboto-Black'),url(fonts/robotoblack.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Ionicons;src:url(fonts/ionicons.woff?v=2.0.0) format("woff");font-weight:400;font-style:normal}i.icon{background:0 0!important}.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;min-width:22px;text-align:center}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/button.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/button.min.css
new file mode 100755
index 0000000..68b7f1b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/button.min.css
@@ -0,0 +1 @@
+button{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease;font-size:14px;border:none;background-color:rgba(0,0,0,0);color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-height:42px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer;overflow:hidden}button[disabled]{opacity:.8}button .icon{position:absolute;left:10px}button.circle{width:42px;height:42px;text-align:center;padding:0;line-height:0;font-size:22px;z-index:10}button.icon-text{padding-left:40px}button.icon-text i{font-size:22px}button.icon-text.icon-right{padding-left:12px;padding-right:40px;position:relative}button.icon-right i{position:absolute;right:12px;text-align:right;margin-top:2px}button[class*=border-]{min-height:40px;line-height:40px}button.full{width:100%}.buttons-group.big button,button.big{font-size:22px;min-height:50px;line-height:50px}button.circle.big{width:50px;height:50px;font-size:28px}button.big.icon-text{padding-left:40px}button.big.icon-text.icon-right{padding-left:12px;padding-right:40px}button.big.icon-text i{font-size:26px}.buttons-group.small button,button.small{font-size:12px;min-height:30px;line-height:30px}button.circle.small{width:30px;height:30px;font-size:18px}button.small.icon-text{padding-left:30px}button.small.icon-text.icon-right{padding-left:12px;padding-right:35px}button.small.icon-text i{font-size:18px}.buttons-group.huge button,button.huge{font-size:32px;min-height:70px;line-height:70px}button.circle.huge{width:70px;height:70px;font-size:32px}button.huge.icon-text{padding-left:40px}button.huge.icon-text.icon-right{padding-left:12px;padding-right:40px}button.huge.icon-text i{font-size:32px}.buttons-group{display:inline-block}.buttons-group button{float:left;margin-left:-1px}.buttons-group button:first-child{margin-left:0}.buttons-group.full{display:flex}.buttons-group.full button{flex:1}.ripple{position:absolute;background:rgba(255,255,255,.25);border-radius:100%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ripple.show{-webkit-animation:ripple .5s ease-out;-moz-animation:ripple .5s ease-out;-o-animation:ripple .5s ease-out;animation:ripple .5s ease-out}@-webkit-keyframes ripple{to{-webkit-transform:scale(1.5);opacity:0}}@-moz-keyframes ripple{to{-moz-transform:scale(1.5);opacity:0}}@-o-keyframes ripple{to{-o-transform:scale(1.5);opacity:0}}@keyframes ripple{to{transform:scale(1.5);opacity:0}}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chart-bar.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chart-bar.min.css
new file mode 100755
index 0000000..69d4056
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chart-bar.min.css
@@ -0,0 +1 @@
+.chart-bar{display:table;table-layout:fixed;width:100%;height:250px;background-image:linear-gradient(to top,rgba(0,0,0,.1) 2%,rgba(0,0,0,0) 2%);background-size:100% 50px;background-position:left top}.chart-bar.line-white{background-image:linear-gradient(to top,rgba(255,255,255,.1) 2%,rgba(255,255,255,0) 2%)}.chart-bar.no-line{background-image:none}.chart-bar li{position:relative;display:table-cell;vertical-align:bottom;height:250px}.chart-bar li span{margin:0 5px;display:block}.chart-bar li div{width:100%;text-align:center;padding:5px}.chart-bar li span::before{position:relative;top:0;width:100%;padding-top:5px;padding-bottom:5px;display:block;text-align:center;content:attr(title);word-wrap:break-word;overflow:hidden;opacity:.7}.chart-bar.size-1{width:80px}.chart-bar.size-1,.chart-bar.size-1 li{height:40px}.chart-bar.size-1 li span{margin:0 2px}.chart-bar.size-2{width:150px}.chart-bar.size-2,.chart-bar.size-2 li{height:60px}.chart-bar.size-2 li span{margin:0 4px}.chart-bar.size-3{width:250px}.chart-bar.size-3,.chart-bar.size-3 li{height:80px}.chart-bar.size-3 li span{margin:0 5px}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist-plugin-tooltip.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist-plugin-tooltip.min.css
new file mode 100755
index 0000000..3d4a9ac
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist-plugin-tooltip.min.css
@@ -0,0 +1 @@
+.chartist-tooltip{position:absolute;display:inline-block;opacity:0;min-width:5em;padding:.5em;background:#f4c63d;color:#453d3f;font-family:Oxygen,Helvetica,Arial,sans-serif;font-weight:700;text-align:center;pointer-events:none;z-index:1;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.chartist-tooltip:before{content:"";position:absolute;top:100%;left:50%;width:0;height:0;margin-left:-15px;border:15px solid transparent;border-top-color:#f4c63d}.chartist-tooltip.tooltip-show{opacity:1}.ct-area,.ct-line{pointer-events:none}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist.min.css
new file mode 100755
index 0000000..9170721
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartist.min.css
@@ -0,0 +1 @@
+.ct-double-octave:after,.ct-major-eleventh:after,.ct-major-second:after,.ct-major-seventh:after,.ct-major-sixth:after,.ct-major-tenth:after,.ct-major-third:after,.ct-major-twelfth:after,.ct-minor-second:after,.ct-minor-seventh:after,.ct-minor-sixth:after,.ct-minor-third:after,.ct-octave:after,.ct-perfect-fifth:after,.ct-perfect-fourth:after,.ct-square:after{content:"";clear:both}.ct-label{fill:rgba(0,0,0,.4);color:rgba(0,0,0,.4);font-size:.75rem;line-height:1}.ct-grid-background,.ct-line{fill:none}.ct-chart-bar .ct-label,.ct-chart-line .ct-label{display:block;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.ct-chart-donut .ct-label,.ct-chart-pie .ct-label{dominant-baseline:central}.ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-vertical.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-end;-webkit-justify-content:flex-end;-ms-flex-pack:flex-end;justify-content:flex-end;text-align:right;text-anchor:end}.ct-label.ct-vertical.ct-end{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-start{-webkit-box-align:flex-end;-webkit-align-items:flex-end;-ms-flex-align:flex-end;align-items:flex-end;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-end{-webkit-box-align:flex-start;-webkit-align-items:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-start{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:flex-end;-webkit-justify-content:flex-end;-ms-flex-pack:flex-end;justify-content:flex-end;text-align:right;text-anchor:end}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-end{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:flex-start;-webkit-justify-content:flex-start;-ms-flex-pack:flex-start;justify-content:flex-start;text-align:left;text-anchor:end}.ct-grid{stroke:rgba(0,0,0,.2);stroke-width:1px;stroke-dasharray:2px}.ct-point{stroke-width:10px;stroke-linecap:round}.ct-line{stroke-width:4px}.ct-area{stroke:none;fill-opacity:.1}.ct-bar{fill:none;stroke-width:10px}.ct-slice-donut{fill:none;stroke-width:60px}.ct-series-a .ct-bar,.ct-series-a .ct-line,.ct-series-a .ct-point,.ct-series-a .ct-slice-donut{stroke:#d70206}.ct-series-a .ct-area,.ct-series-a .ct-slice-donut-solid,.ct-series-a .ct-slice-pie{fill:#d70206}.ct-series-b .ct-bar,.ct-series-b .ct-line,.ct-series-b .ct-point,.ct-series-b .ct-slice-donut{stroke:#f05b4f}.ct-series-b .ct-area,.ct-series-b .ct-slice-donut-solid,.ct-series-b .ct-slice-pie{fill:#f05b4f}.ct-series-c .ct-bar,.ct-series-c .ct-line,.ct-series-c .ct-point,.ct-series-c .ct-slice-donut{stroke:#f4c63d}.ct-series-c .ct-area,.ct-series-c .ct-slice-donut-solid,.ct-series-c .ct-slice-pie{fill:#f4c63d}.ct-series-d .ct-bar,.ct-series-d .ct-line,.ct-series-d .ct-point,.ct-series-d .ct-slice-donut{stroke:#d17905}.ct-series-d .ct-area,.ct-series-d .ct-slice-donut-solid,.ct-series-d .ct-slice-pie{fill:#d17905}.ct-series-e .ct-bar,.ct-series-e .ct-line,.ct-series-e .ct-point,.ct-series-e .ct-slice-donut{stroke:#453d3f}.ct-series-e .ct-area,.ct-series-e .ct-slice-donut-solid,.ct-series-e .ct-slice-pie{fill:#453d3f}.ct-series-f .ct-bar,.ct-series-f .ct-line,.ct-series-f .ct-point,.ct-series-f .ct-slice-donut{stroke:#59922b}.ct-series-f .ct-area,.ct-series-f .ct-slice-donut-solid,.ct-series-f .ct-slice-pie{fill:#59922b}.ct-series-g .ct-bar,.ct-series-g .ct-line,.ct-series-g .ct-point,.ct-series-g .ct-slice-donut{stroke:#0544d3}.ct-series-g .ct-area,.ct-series-g .ct-slice-donut-solid,.ct-series-g .ct-slice-pie{fill:#0544d3}.ct-series-h .ct-bar,.ct-series-h .ct-line,.ct-series-h .ct-point,.ct-series-h .ct-slice-donut{stroke:#6b0392}.ct-series-h .ct-area,.ct-series-h .ct-slice-donut-solid,.ct-series-h .ct-slice-pie{fill:#6b0392}.ct-series-i .ct-bar,.ct-series-i .ct-line,.ct-series-i .ct-point,.ct-series-i .ct-slice-donut{stroke:#f05b4f}.ct-series-i .ct-area,.ct-series-i .ct-slice-donut-solid,.ct-series-i .ct-slice-pie{fill:#f05b4f}.ct-series-j .ct-bar,.ct-series-j .ct-line,.ct-series-j .ct-point,.ct-series-j .ct-slice-donut{stroke:#dda458}.ct-series-j .ct-area,.ct-series-j .ct-slice-donut-solid,.ct-series-j .ct-slice-pie{fill:#dda458}.ct-series-k .ct-bar,.ct-series-k .ct-line,.ct-series-k .ct-point,.ct-series-k .ct-slice-donut{stroke:#eacf7d}.ct-series-k .ct-area,.ct-series-k .ct-slice-donut-solid,.ct-series-k .ct-slice-pie{fill:#eacf7d}.ct-series-l .ct-bar,.ct-series-l .ct-line,.ct-series-l .ct-point,.ct-series-l .ct-slice-donut{stroke:#86797d}.ct-series-l .ct-area,.ct-series-l .ct-slice-donut-solid,.ct-series-l .ct-slice-pie{fill:#86797d}.ct-series-m .ct-bar,.ct-series-m .ct-line,.ct-series-m .ct-point,.ct-series-m .ct-slice-donut{stroke:#b2c326}.ct-series-m .ct-area,.ct-series-m .ct-slice-donut-solid,.ct-series-m .ct-slice-pie{fill:#b2c326}.ct-series-n .ct-bar,.ct-series-n .ct-line,.ct-series-n .ct-point,.ct-series-n .ct-slice-donut{stroke:#6188e2}.ct-series-n .ct-area,.ct-series-n .ct-slice-donut-solid,.ct-series-n .ct-slice-pie{fill:#6188e2}.ct-series-o .ct-bar,.ct-series-o .ct-line,.ct-series-o .ct-point,.ct-series-o .ct-slice-donut{stroke:#a748ca}.ct-series-o .ct-area,.ct-series-o .ct-slice-donut-solid,.ct-series-o .ct-slice-pie{fill:#a748ca}.ct-square{display:block;position:relative;width:100%}.ct-square:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:100%}.ct-square:after{display:table}.ct-square>svg{display:block;position:absolute;top:0;left:0}.ct-minor-second{display:block;position:relative;width:100%}.ct-minor-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:93.75%}.ct-minor-second:after{display:table}.ct-minor-second>svg{display:block;position:absolute;top:0;left:0}.ct-major-second{display:block;position:relative;width:100%}.ct-major-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:88.8888888889%}.ct-major-second:after{display:table}.ct-major-second>svg{display:block;position:absolute;top:0;left:0}.ct-minor-third{display:block;position:relative;width:100%}.ct-minor-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:83.3333333333%}.ct-minor-third:after{display:table}.ct-minor-third>svg{display:block;position:absolute;top:0;left:0}.ct-major-third{display:block;position:relative;width:100%}.ct-major-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:80%}.ct-major-third:after{display:table}.ct-major-third>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fourth{display:block;position:relative;width:100%}.ct-perfect-fourth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:75%}.ct-perfect-fourth:after{display:table}.ct-perfect-fourth>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fifth{display:block;position:relative;width:100%}.ct-perfect-fifth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:66.6666666667%}.ct-perfect-fifth:after{display:table}.ct-perfect-fifth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-sixth{display:block;position:relative;width:100%}.ct-minor-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:62.5%}.ct-minor-sixth:after{display:table}.ct-minor-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-golden-section{display:block;position:relative;width:100%}.ct-golden-section:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:61.804697157%}.ct-golden-section:after{content:"";display:table;clear:both}.ct-golden-section>svg{display:block;position:absolute;top:0;left:0}.ct-major-sixth{display:block;position:relative;width:100%}.ct-major-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:60%}.ct-major-sixth:after{display:table}.ct-major-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-seventh{display:block;position:relative;width:100%}.ct-minor-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:56.25%}.ct-minor-seventh:after{display:table}.ct-minor-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-seventh{display:block;position:relative;width:100%}.ct-major-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:53.3333333333%}.ct-major-seventh:after{display:table}.ct-major-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-octave{display:block;position:relative;width:100%}.ct-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:50%}.ct-octave:after{display:table}.ct-octave>svg{display:block;position:absolute;top:0;left:0}.ct-major-tenth{display:block;position:relative;width:100%}.ct-major-tenth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:40%}.ct-major-tenth:after{display:table}.ct-major-tenth>svg{display:block;position:absolute;top:0;left:0}.ct-major-eleventh{display:block;position:relative;width:100%}.ct-major-eleventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:37.5%}.ct-major-eleventh:after{display:table}.ct-major-eleventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-twelfth{display:block;position:relative;width:100%}.ct-major-twelfth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:33.3333333333%}.ct-major-twelfth:after{display:table}.ct-major-twelfth>svg{display:block;position:absolute;top:0;left:0}.ct-double-octave{display:block;position:relative;width:100%}.ct-double-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:25%}.ct-double-octave:after{display:table}.ct-double-octave>svg{display:block;position:absolute;top:0;left:0}.chartist-big .ct-series-a .ct-bar,.chartist-big .ct-series-a .ct-line,.chartist-big .ct-series-a .ct-point,.chartist-big .ct-series-a .ct-slice-donut,.chartist-big .ct-series-b .ct-bar,.chartist-big .ct-series-b .ct-line,.chartist-big .ct-series-b .ct-point,.chartist-big .ct-series-b .ct-slice-donut,.chartist-big .ct-series-c .ct-bar,.chartist-big .ct-series-c .ct-line,.chartist-big .ct-series-c .ct-point,.chartist-big .ct-series-c .ct-slice-donut,.chartist-big .ct-series-d .ct-bar,.chartist-big .ct-series-d .ct-line,.chartist-big .ct-series-d .ct-point,.chartist-big .ct-series-d .ct-slice-donut{stroke-width:20px}.chartist-huge .ct-series-a .ct-bar,.chartist-huge .ct-series-a .ct-line,.chartist-huge .ct-series-a .ct-point,.chartist-huge .ct-series-a .ct-slice-donut,.chartist-huge .ct-series-b .ct-bar,.chartist-huge .ct-series-b .ct-line,.chartist-huge .ct-series-b .ct-point,.chartist-huge .ct-series-b .ct-slice-donut,.chartist-huge .ct-series-c .ct-bar,.chartist-huge .ct-series-c .ct-line,.chartist-huge .ct-series-c .ct-point,.chartist-huge .ct-series-c .ct-slice-donut,.chartist-huge .ct-series-d .ct-bar,.chartist-huge .ct-series-d .ct-line,.chartist-huge .ct-series-d .ct-point,.chartist-huge .ct-series-d .ct-slice-donut{stroke-width:30px}.chartist-white.text-black .ct-label{fill:#000;color:#000}.chartist-white.text-white .ct-label{fill:#fff;color:#fff}.chartist-white .ct-label{fill:rgba(255,255,255,.4);color:rgba(255,255,255,.4)}.chartist-white .ct-grid{stroke:rgba(255,255,255,.2)}.chartist-white .ct-series-a .ct-bar,.chartist-white .ct-series-a .ct-line,.chartist-white .ct-series-a .ct-point,.chartist-white .ct-series-a .ct-slice-donut{stroke:rgba(255,255,255,1)}.chartist-white .ct-series-b .ct-bar,.chartist-white .ct-series-b .ct-line,.chartist-white .ct-series-b .ct-point,.chartist-white .ct-series-b .ct-slice-donut{stroke:rgba(255,255,255,.7)}.chartist-white .ct-series-c .ct-bar,.chartist-white .ct-series-c .ct-line,.chartist-white .ct-series-c .ct-point,.chartist-white .ct-series-c .ct-slice-donut{stroke:rgba(255,255,255,.4)}.chartist-white .ct-series-d .ct-bar,.chartist-white .ct-series-d .ct-line,.chartist-white .ct-series-d .ct-point,.chartist-white .ct-series-d .ct-slice-donut{stroke:rgba(255,255,255,.2)}.chartist-white .ct-series-a .ct-area,.chartist-white .ct-series-a .ct-slice-donut-solid,.chartist-white .ct-series-a .ct-slice-pie{fill:rgba(255,255,255,1)}.chartist-white .ct-series-b .ct-area,.chartist-white .ct-series-b .ct-slice-donut-solid,.chartist-white .ct-series-b .ct-slice-pie{fill:rgba(255,255,255,.7)}.chartist-white .ct-series-c .ct-area,.chartist-white .ct-series-c .ct-slice-donut-solid,.chartist-white .ct-series-c .ct-slice-pie{fill:rgba(255,255,255,.4)}.chartist-white .ct-series-d .ct-area,.chartist-white .ct-series-d .ct-slice-donut-solid,.chartist-white .ct-series-d .ct-slice-pie{fill:rgba(255,255,255,.2)}.chartist-red.text-black .ct-label{fill:#000;color:#000}.chartist-red.text-white .ct-label{fill:#fff;color:#fff}.chartist-red .ct-label{fill:rgba(244,67,54,.4);color:rgba(244,67,54,.4)}.chartist-red .ct-grid{stroke:rgba(244,67,54,.2)}.chartist-red .ct-series-a .ct-bar,.chartist-red .ct-series-a .ct-line,.chartist-red .ct-series-a .ct-point,.chartist-red .ct-series-a .ct-slice-donut{stroke:rgba(244,67,54,1)}.chartist-red .ct-series-b .ct-bar,.chartist-red .ct-series-b .ct-line,.chartist-red .ct-series-b .ct-point,.chartist-red .ct-series-b .ct-slice-donut{stroke:rgba(244,67,54,.7)}.chartist-red .ct-series-c .ct-bar,.chartist-red .ct-series-c .ct-line,.chartist-red .ct-series-c .ct-point,.chartist-red .ct-series-c .ct-slice-donut{stroke:rgba(244,67,54,.4)}.chartist-red .ct-series-d .ct-bar,.chartist-red .ct-series-d .ct-line,.chartist-red .ct-series-d .ct-point,.chartist-red .ct-series-d .ct-slice-donut{stroke:rgba(244,67,54,.2)}.chartist-red .ct-series-a .ct-area,.chartist-red .ct-series-a .ct-slice-donut-solid,.chartist-red .ct-series-a .ct-slice-pie{fill:rgba(244,67,54,1)}.chartist-red .ct-series-b .ct-area,.chartist-red .ct-series-b .ct-slice-donut-solid,.chartist-red .ct-series-b .ct-slice-pie{fill:rgba(244,67,54,.7)}.chartist-red .ct-series-c .ct-area,.chartist-red .ct-series-c .ct-slice-donut-solid,.chartist-red .ct-series-c .ct-slice-pie{fill:rgba(244,67,54,.4)}.chartist-red .ct-series-d .ct-area,.chartist-red .ct-series-d .ct-slice-donut-solid,.chartist-red .ct-series-d .ct-slice-pie{fill:rgba(244,67,54,.2)}.chartist-pink.text-black .ct-label{fill:#000;color:#000}.chartist-pink.text-white .ct-label{fill:#fff;color:#fff}.chartist-pink .ct-label{fill:rgba(233,30,99,.4);color:rgba(233,30,99,.4)}.chartist-pink .ct-grid{stroke:rgba(233,30,99,.2)}.chartist-pink .ct-series-a .ct-bar,.chartist-pink .ct-series-a .ct-line,.chartist-pink .ct-series-a .ct-point,.chartist-pink .ct-series-a .ct-slice-donut{stroke:rgba(233,30,99,1)}.chartist-pink .ct-series-b .ct-bar,.chartist-pink .ct-series-b .ct-line,.chartist-pink .ct-series-b .ct-point,.chartist-pink .ct-series-b .ct-slice-donut{stroke:rgba(233,30,99,.7)}.chartist-pink .ct-series-c .ct-bar,.chartist-pink .ct-series-c .ct-line,.chartist-pink .ct-series-c .ct-point,.chartist-pink .ct-series-c .ct-slice-donut{stroke:rgba(233,30,99,.4)}.chartist-pink .ct-series-d .ct-bar,.chartist-pink .ct-series-d .ct-line,.chartist-pink .ct-series-d .ct-point,.chartist-pink .ct-series-d .ct-slice-donut{stroke:rgba(233,30,99,.2)}.chartist-pink .ct-series-a .ct-area,.chartist-pink .ct-series-a .ct-slice-donut-solid,.chartist-pink .ct-series-a .ct-slice-pie{fill:rgba(233,30,99,1)}.chartist-pink .ct-series-b .ct-area,.chartist-pink .ct-series-b .ct-slice-donut-solid,.chartist-pink .ct-series-b .ct-slice-pie{fill:rgba(233,30,99,.7)}.chartist-pink .ct-series-c .ct-area,.chartist-pink .ct-series-c .ct-slice-donut-solid,.chartist-pink .ct-series-c .ct-slice-pie{fill:rgba(233,30,99,.4)}.chartist-pink .ct-series-d .ct-area,.chartist-pink .ct-series-d .ct-slice-donut-solid,.chartist-pink .ct-series-d .ct-slice-pie{fill:rgba(233,30,99,.2)}.chartist-purple.text-black .ct-label{fill:#000;color:#000}.chartist-purple.text-white .ct-label{fill:#fff;color:#fff}.chartist-purple .ct-label{fill:rgba(156,39,176,.4);color:rgba(156,39,176,.4)}.chartist-purple .ct-grid{stroke:rgba(156,39,176,.2)}.chartist-purple .ct-series-a .ct-bar,.chartist-purple .ct-series-a .ct-line,.chartist-purple .ct-series-a .ct-point,.chartist-purple .ct-series-a .ct-slice-donut{stroke:rgba(156,39,176,1)}.chartist-purple .ct-series-b .ct-bar,.chartist-purple .ct-series-b .ct-line,.chartist-purple .ct-series-b .ct-point,.chartist-purple .ct-series-b .ct-slice-donut{stroke:rgba(156,39,176,.7)}.chartist-purple .ct-series-c .ct-bar,.chartist-purple .ct-series-c .ct-line,.chartist-purple .ct-series-c .ct-point,.chartist-purple .ct-series-c .ct-slice-donut{stroke:rgba(156,39,176,.4)}.chartist-purple .ct-series-d .ct-bar,.chartist-purple .ct-series-d .ct-line,.chartist-purple .ct-series-d .ct-point,.chartist-purple .ct-series-d .ct-slice-donut{stroke:rgba(156,39,176,.2)}.chartist-purple .ct-series-a .ct-area,.chartist-purple .ct-series-a .ct-slice-donut-solid,.chartist-purple .ct-series-a .ct-slice-pie{fill:rgba(156,39,176,1)}.chartist-purple .ct-series-b .ct-area,.chartist-purple .ct-series-b .ct-slice-donut-solid,.chartist-purple .ct-series-b .ct-slice-pie{fill:rgba(156,39,176,.7)}.chartist-purple .ct-series-c .ct-area,.chartist-purple .ct-series-c .ct-slice-donut-solid,.chartist-purple .ct-series-c .ct-slice-pie{fill:rgba(156,39,176,.4)}.chartist-purple .ct-series-d .ct-area,.chartist-purple .ct-series-d .ct-slice-donut-solid,.chartist-purple .ct-series-d .ct-slice-pie{fill:rgba(156,39,176,.2)}.chartist-deep.text-white-purple .ct-label{fill:#fff;color:#fff}.chartist-deep-purple .ct-label{fill:rgba(103,58,183,.4);color:rgba(103,58,183,.4)}.chartist-deep-purple .ct-grid{stroke:rgba(103,58,183,.2)}.chartist-deep-purple .ct-series-a .ct-bar,.chartist-deep-purple .ct-series-a .ct-line,.chartist-deep-purple .ct-series-a .ct-point,.chartist-deep-purple .ct-series-a .ct-slice-donut{stroke:rgba(103,58,183,1)}.chartist-deep-purple .ct-series-b .ct-bar,.chartist-deep-purple .ct-series-b .ct-line,.chartist-deep-purple .ct-series-b .ct-point,.chartist-deep-purple .ct-series-b .ct-slice-donut{stroke:rgba(103,58,183,.7)}.chartist-deep-purple .ct-series-c .ct-bar,.chartist-deep-purple .ct-series-c .ct-line,.chartist-deep-purple .ct-series-c .ct-point,.chartist-deep-purple .ct-series-c .ct-slice-donut{stroke:rgba(103,58,183,.4)}.chartist-deep-purple .ct-series-d .ct-bar,.chartist-deep-purple .ct-series-d .ct-line,.chartist-deep-purple .ct-series-d .ct-point,.chartist-deep-purple .ct-series-d .ct-slice-donut{stroke:rgba(103,58,183,.2)}.chartist-deep-purple .ct-series-a .ct-area,.chartist-deep-purple .ct-series-a .ct-slice-donut-solid,.chartist-deep-purple .ct-series-a .ct-slice-pie{fill:rgba(103,58,183,1)}.chartist-deep-purple .ct-series-b .ct-area,.chartist-deep-purple .ct-series-b .ct-slice-donut-solid,.chartist-deep-purple .ct-series-b .ct-slice-pie{fill:rgba(103,58,183,.7)}.chartist-deep-purple .ct-series-c .ct-area,.chartist-deep-purple .ct-series-c .ct-slice-donut-solid,.chartist-deep-purple .ct-series-c .ct-slice-pie{fill:rgba(103,58,183,.4)}.chartist-deep-purple .ct-series-d .ct-area,.chartist-deep-purple .ct-series-d .ct-slice-donut-solid,.chartist-deep-purple .ct-series-d .ct-slice-pie{fill:rgba(103,58,183,.2)}.chartist-indigo.text-black .ct-label{fill:#000;color:#000}.chartist-indigo.text-white .ct-label{fill:#fff;color:#fff}.chartist-indigo .ct-label{fill:rgba(63,81,181,.4);color:rgba(63,81,181,.4)}.chartist-indigo .ct-grid{stroke:rgba(63,81,181,.2)}.chartist-indigo .ct-series-a .ct-bar,.chartist-indigo .ct-series-a .ct-line,.chartist-indigo .ct-series-a .ct-point,.chartist-indigo .ct-series-a .ct-slice-donut{stroke:rgba(63,81,181,1)}.chartist-indigo .ct-series-b .ct-bar,.chartist-indigo .ct-series-b .ct-line,.chartist-indigo .ct-series-b .ct-point,.chartist-indigo .ct-series-b .ct-slice-donut{stroke:rgba(63,81,181,.7)}.chartist-indigo .ct-series-c .ct-bar,.chartist-indigo .ct-series-c .ct-line,.chartist-indigo .ct-series-c .ct-point,.chartist-indigo .ct-series-c .ct-slice-donut{stroke:rgba(63,81,181,.4)}.chartist-indigo .ct-series-d .ct-bar,.chartist-indigo .ct-series-d .ct-line,.chartist-indigo .ct-series-d .ct-point,.chartist-indigo .ct-series-d .ct-slice-donut{stroke:rgba(63,81,181,.2)}.chartist-indigo .ct-series-a .ct-area,.chartist-indigo .ct-series-a .ct-slice-donut-solid,.chartist-indigo .ct-series-a .ct-slice-pie{fill:rgba(63,81,181,1)}.chartist-indigo .ct-series-b .ct-area,.chartist-indigo .ct-series-b .ct-slice-donut-solid,.chartist-indigo .ct-series-b .ct-slice-pie{fill:rgba(63,81,181,.7)}.chartist-indigo .ct-series-c .ct-area,.chartist-indigo .ct-series-c .ct-slice-donut-solid,.chartist-indigo .ct-series-c .ct-slice-pie{fill:rgba(63,81,181,.4)}.chartist-indigo .ct-series-d .ct-area,.chartist-indigo .ct-series-d .ct-slice-donut-solid,.chartist-indigo .ct-series-d .ct-slice-pie{fill:rgba(63,81,181,.2)}.chartist-blue.text-black .ct-label{fill:#000;color:#000}.chartist-blue.text-white .ct-label{fill:#fff;color:#fff}.chartist-blue .ct-label{fill:rgba(33,150,243,.4);color:rgba(33,150,243,.4)}.chartist-blue .ct-grid{stroke:rgba(33,150,243,.2)}.chartist-blue .ct-series-a .ct-bar,.chartist-blue .ct-series-a .ct-line,.chartist-blue .ct-series-a .ct-point,.chartist-blue .ct-series-a .ct-slice-donut{stroke:rgba(33,150,243,1)}.chartist-blue .ct-series-b .ct-bar,.chartist-blue .ct-series-b .ct-line,.chartist-blue .ct-series-b .ct-point,.chartist-blue .ct-series-b .ct-slice-donut{stroke:rgba(33,150,243,.7)}.chartist-blue .ct-series-c .ct-bar,.chartist-blue .ct-series-c .ct-line,.chartist-blue .ct-series-c .ct-point,.chartist-blue .ct-series-c .ct-slice-donut{stroke:rgba(33,150,243,.4)}.chartist-blue .ct-series-d .ct-bar,.chartist-blue .ct-series-d .ct-line,.chartist-blue .ct-series-d .ct-point,.chartist-blue .ct-series-d .ct-slice-donut{stroke:rgba(33,150,243,.2)}.chartist-blue .ct-series-a .ct-area,.chartist-blue .ct-series-a .ct-slice-donut-solid,.chartist-blue .ct-series-a .ct-slice-pie{fill:rgba(33,150,243,1)}.chartist-blue .ct-series-b .ct-area,.chartist-blue .ct-series-b .ct-slice-donut-solid,.chartist-blue .ct-series-b .ct-slice-pie{fill:rgba(33,150,243,.7)}.chartist-blue .ct-series-c .ct-area,.chartist-blue .ct-series-c .ct-slice-donut-solid,.chartist-blue .ct-series-c .ct-slice-pie{fill:rgba(33,150,243,.4)}.chartist-blue .ct-series-d .ct-area,.chartist-blue .ct-series-d .ct-slice-donut-solid,.chartist-blue .ct-series-d .ct-slice-pie{fill:rgba(33,150,243,.2)}.chartist-light.text-white-blue .ct-label{fill:#fff;color:#fff}.chartist-light-blue .ct-label{fill:rgba(3,169,244,.4);color:rgba(3,169,244,.4)}.chartist-light-blue .ct-grid{stroke:rgba(3,169,244,.2)}.chartist-light-blue .ct-series-a .ct-bar,.chartist-light-blue .ct-series-a .ct-line,.chartist-light-blue .ct-series-a .ct-point,.chartist-light-blue .ct-series-a .ct-slice-donut{stroke:rgba(3,169,244,1)}.chartist-light-blue .ct-series-b .ct-bar,.chartist-light-blue .ct-series-b .ct-line,.chartist-light-blue .ct-series-b .ct-point,.chartist-light-blue .ct-series-b .ct-slice-donut{stroke:rgba(3,169,244,.7)}.chartist-light-blue .ct-series-c .ct-bar,.chartist-light-blue .ct-series-c .ct-line,.chartist-light-blue .ct-series-c .ct-point,.chartist-light-blue .ct-series-c .ct-slice-donut{stroke:rgba(3,169,244,.4)}.chartist-light-blue .ct-series-d .ct-bar,.chartist-light-blue .ct-series-d .ct-line,.chartist-light-blue .ct-series-d .ct-point,.chartist-light-blue .ct-series-d .ct-slice-donut{stroke:rgba(3,169,244,.2)}.chartist-light-blue .ct-series-a .ct-area,.chartist-light-blue .ct-series-a .ct-slice-donut-solid,.chartist-light-blue .ct-series-a .ct-slice-pie{fill:rgba(3,169,244,1)}.chartist-light-blue .ct-series-b .ct-area,.chartist-light-blue .ct-series-b .ct-slice-donut-solid,.chartist-light-blue .ct-series-b .ct-slice-pie{fill:rgba(3,169,244,.7)}.chartist-light-blue .ct-series-c .ct-area,.chartist-light-blue .ct-series-c .ct-slice-donut-solid,.chartist-light-blue .ct-series-c .ct-slice-pie{fill:rgba(3,169,244,.4)}.chartist-light-blue .ct-series-d .ct-area,.chartist-light-blue .ct-series-d .ct-slice-donut-solid,.chartist-light-blue .ct-series-d .ct-slice-pie{fill:rgba(3,169,244,.2)}.chartist-cyan.text-black .ct-label{fill:#000;color:#000}.chartist-cyan.text-white .ct-label{fill:#fff;color:#fff}.chartist-cyan .ct-label{fill:rgba(0,188,212,.4);color:rgba(0,188,212,.4)}.chartist-cyan .ct-grid{stroke:rgba(0,188,212,.2)}.chartist-cyan .ct-series-a .ct-bar,.chartist-cyan .ct-series-a .ct-line,.chartist-cyan .ct-series-a .ct-point,.chartist-cyan .ct-series-a .ct-slice-donut{stroke:rgba(0,188,212,1)}.chartist-cyan .ct-series-b .ct-bar,.chartist-cyan .ct-series-b .ct-line,.chartist-cyan .ct-series-b .ct-point,.chartist-cyan .ct-series-b .ct-slice-donut{stroke:rgba(0,188,212,.7)}.chartist-cyan .ct-series-c .ct-bar,.chartist-cyan .ct-series-c .ct-line,.chartist-cyan .ct-series-c .ct-point,.chartist-cyan .ct-series-c .ct-slice-donut{stroke:rgba(0,188,212,.4)}.chartist-cyan .ct-series-d .ct-bar,.chartist-cyan .ct-series-d .ct-line,.chartist-cyan .ct-series-d .ct-point,.chartist-cyan .ct-series-d .ct-slice-donut{stroke:rgba(0,188,212,.2)}.chartist-cyan .ct-series-a .ct-area,.chartist-cyan .ct-series-a .ct-slice-donut-solid,.chartist-cyan .ct-series-a .ct-slice-pie{fill:rgba(0,188,212,1)}.chartist-cyan .ct-series-b .ct-area,.chartist-cyan .ct-series-b .ct-slice-donut-solid,.chartist-cyan .ct-series-b .ct-slice-pie{fill:rgba(0,188,212,.7)}.chartist-cyan .ct-series-c .ct-area,.chartist-cyan .ct-series-c .ct-slice-donut-solid,.chartist-cyan .ct-series-c .ct-slice-pie{fill:rgba(0,188,212,.4)}.chartist-cyan .ct-series-d .ct-area,.chartist-cyan .ct-series-d .ct-slice-donut-solid,.chartist-cyan .ct-series-d .ct-slice-pie{fill:rgba(0,188,212,.2)}.chartist-teal.text-black .ct-label{fill:#000;color:#000}.chartist-teal.text-white .ct-label{fill:#fff;color:#fff}.chartist-teal .ct-label{fill:rgba(0,150,136,.4);color:rgba(0,150,136,.4)}.chartist-teal .ct-grid{stroke:rgba(0,150,136,.2)}.chartist-teal .ct-series-a .ct-bar,.chartist-teal .ct-series-a .ct-line,.chartist-teal .ct-series-a .ct-point,.chartist-teal .ct-series-a .ct-slice-donut{stroke:rgba(0,150,136,1)}.chartist-teal .ct-series-b .ct-bar,.chartist-teal .ct-series-b .ct-line,.chartist-teal .ct-series-b .ct-point,.chartist-teal .ct-series-b .ct-slice-donut{stroke:rgba(0,150,136,.7)}.chartist-teal .ct-series-c .ct-bar,.chartist-teal .ct-series-c .ct-line,.chartist-teal .ct-series-c .ct-point,.chartist-teal .ct-series-c .ct-slice-donut{stroke:rgba(0,150,136,.4)}.chartist-teal .ct-series-d .ct-bar,.chartist-teal .ct-series-d .ct-line,.chartist-teal .ct-series-d .ct-point,.chartist-teal .ct-series-d .ct-slice-donut{stroke:rgba(0,150,136,.2)}.chartist-teal .ct-series-a .ct-area,.chartist-teal .ct-series-a .ct-slice-donut-solid,.chartist-teal .ct-series-a .ct-slice-pie{fill:rgba(0,150,136,1)}.chartist-teal .ct-series-b .ct-area,.chartist-teal .ct-series-b .ct-slice-donut-solid,.chartist-teal .ct-series-b .ct-slice-pie{fill:rgba(0,150,136,.7)}.chartist-teal .ct-series-c .ct-area,.chartist-teal .ct-series-c .ct-slice-donut-solid,.chartist-teal .ct-series-c .ct-slice-pie{fill:rgba(0,150,136,.4)}.chartist-teal .ct-series-d .ct-area,.chartist-teal .ct-series-d .ct-slice-donut-solid,.chartist-teal .ct-series-d .ct-slice-pie{fill:rgba(0,150,136,.2)}.chartist-green.text-black .ct-label{fill:#000;color:#000}.chartist-green.text-white .ct-label{fill:#fff;color:#fff}.chartist-green .ct-label{fill:rgba(76,175,79,.4);color:rgba(76,175,79,.4)}.chartist-green .ct-grid{stroke:rgba(76,175,79,.2)}.chartist-green .ct-series-a .ct-bar,.chartist-green .ct-series-a .ct-line,.chartist-green .ct-series-a .ct-point,.chartist-green .ct-series-a .ct-slice-donut{stroke:rgba(76,175,79,1)}.chartist-green .ct-series-b .ct-bar,.chartist-green .ct-series-b .ct-line,.chartist-green .ct-series-b .ct-point,.chartist-green .ct-series-b .ct-slice-donut{stroke:rgba(76,175,79,.7)}.chartist-green .ct-series-c .ct-bar,.chartist-green .ct-series-c .ct-line,.chartist-green .ct-series-c .ct-point,.chartist-green .ct-series-c .ct-slice-donut{stroke:rgba(76,175,79,.4)}.chartist-green .ct-series-d .ct-bar,.chartist-green .ct-series-d .ct-line,.chartist-green .ct-series-d .ct-point,.chartist-green .ct-series-d .ct-slice-donut{stroke:rgba(76,175,79,.2)}.chartist-green .ct-series-a .ct-area,.chartist-green .ct-series-a .ct-slice-donut-solid,.chartist-green .ct-series-a .ct-slice-pie{fill:rgba(76,175,79,1)}.chartist-green .ct-series-b .ct-area,.chartist-green .ct-series-b .ct-slice-donut-solid,.chartist-green .ct-series-b .ct-slice-pie{fill:rgba(76,175,79,.7)}.chartist-green .ct-series-c .ct-area,.chartist-green .ct-series-c .ct-slice-donut-solid,.chartist-green .ct-series-c .ct-slice-pie{fill:rgba(76,175,79,.4)}.chartist-green .ct-series-d .ct-area,.chartist-green .ct-series-d .ct-slice-donut-solid,.chartist-green .ct-series-d .ct-slice-pie{fill:rgba(76,175,79,.2)}.chartist-lime.text-black .ct-label{fill:#000;color:#000}.chartist-lime.text-white .ct-label{fill:#fff;color:#fff}.chartist-lime .ct-label{fill:rgba(205,220,57,.4);color:rgba(205,220,57,.4)}.chartist-lime .ct-grid{stroke:rgba(205,220,57,.2)}.chartist-lime .ct-series-a .ct-bar,.chartist-lime .ct-series-a .ct-line,.chartist-lime .ct-series-a .ct-point,.chartist-lime .ct-series-a .ct-slice-donut{stroke:rgba(205,220,57,1)}.chartist-lime .ct-series-b .ct-bar,.chartist-lime .ct-series-b .ct-line,.chartist-lime .ct-series-b .ct-point,.chartist-lime .ct-series-b .ct-slice-donut{stroke:rgba(205,220,57,.7)}.chartist-lime .ct-series-c .ct-bar,.chartist-lime .ct-series-c .ct-line,.chartist-lime .ct-series-c .ct-point,.chartist-lime .ct-series-c .ct-slice-donut{stroke:rgba(205,220,57,.4)}.chartist-lime .ct-series-d .ct-bar,.chartist-lime .ct-series-d .ct-line,.chartist-lime .ct-series-d .ct-point,.chartist-lime .ct-series-d .ct-slice-donut{stroke:rgba(205,220,57,.2)}.chartist-lime .ct-series-a .ct-area,.chartist-lime .ct-series-a .ct-slice-donut-solid,.chartist-lime .ct-series-a .ct-slice-pie{fill:rgba(205,220,57,1)}.chartist-lime .ct-series-b .ct-area,.chartist-lime .ct-series-b .ct-slice-donut-solid,.chartist-lime .ct-series-b .ct-slice-pie{fill:rgba(205,220,57,.7)}.chartist-lime .ct-series-c .ct-area,.chartist-lime .ct-series-c .ct-slice-donut-solid,.chartist-lime .ct-series-c .ct-slice-pie{fill:rgba(205,220,57,.4)}.chartist-lime .ct-series-d .ct-area,.chartist-lime .ct-series-d .ct-slice-donut-solid,.chartist-lime .ct-series-d .ct-slice-pie{fill:rgba(205,220,57,.2)}.chartist-yellow.text-black .ct-label{fill:#000;color:#000}.chartist-yellow.text-white .ct-label{fill:#fff;color:#fff}.chartist-yellow .ct-label{fill:rgba(255,235,59,.4);color:rgba(255,235,59,.4)}.chartist-yellow .ct-grid{stroke:rgba(255,235,59,.2)}.chartist-yellow .ct-series-a .ct-bar,.chartist-yellow .ct-series-a .ct-line,.chartist-yellow .ct-series-a .ct-point,.chartist-yellow .ct-series-a .ct-slice-donut{stroke:rgba(255,235,59,1)}.chartist-yellow .ct-series-b .ct-bar,.chartist-yellow .ct-series-b .ct-line,.chartist-yellow .ct-series-b .ct-point,.chartist-yellow .ct-series-b .ct-slice-donut{stroke:rgba(255,235,59,.7)}.chartist-yellow .ct-series-c .ct-bar,.chartist-yellow .ct-series-c .ct-line,.chartist-yellow .ct-series-c .ct-point,.chartist-yellow .ct-series-c .ct-slice-donut{stroke:rgba(255,235,59,.4)}.chartist-yellow .ct-series-d .ct-bar,.chartist-yellow .ct-series-d .ct-line,.chartist-yellow .ct-series-d .ct-point,.chartist-yellow .ct-series-d .ct-slice-donut{stroke:rgba(255,235,59,.2)}.chartist-yellow .ct-series-a .ct-area,.chartist-yellow .ct-series-a .ct-slice-donut-solid,.chartist-yellow .ct-series-a .ct-slice-pie{fill:rgba(255,235,59,1)}.chartist-yellow .ct-series-b .ct-area,.chartist-yellow .ct-series-b .ct-slice-donut-solid,.chartist-yellow .ct-series-b .ct-slice-pie{fill:rgba(255,235,59,.7)}.chartist-yellow .ct-series-c .ct-area,.chartist-yellow .ct-series-c .ct-slice-donut-solid,.chartist-yellow .ct-series-c .ct-slice-pie{fill:rgba(255,235,59,.4)}.chartist-yellow .ct-series-d .ct-area,.chartist-yellow .ct-series-d .ct-slice-donut-solid,.chartist-yellow .ct-series-d .ct-slice-pie{fill:rgba(255,235,59,.2)}.chartist-amber.text-black .ct-label{fill:#000;color:#000}.chartist-amber.text-white .ct-label{fill:#fff;color:#fff}.chartist-amber .ct-label{fill:rgba(255,193,7,.4);color:rgba(255,193,7,.4)}.chartist-amber .ct-grid{stroke:rgba(255,193,7,.2)}.chartist-amber .ct-series-a .ct-bar,.chartist-amber .ct-series-a .ct-line,.chartist-amber .ct-series-a .ct-point,.chartist-amber .ct-series-a .ct-slice-donut{stroke:rgba(255,193,7,1)}.chartist-amber .ct-series-b .ct-bar,.chartist-amber .ct-series-b .ct-line,.chartist-amber .ct-series-b .ct-point,.chartist-amber .ct-series-b .ct-slice-donut{stroke:rgba(255,193,7,.7)}.chartist-amber .ct-series-c .ct-bar,.chartist-amber .ct-series-c .ct-line,.chartist-amber .ct-series-c .ct-point,.chartist-amber .ct-series-c .ct-slice-donut{stroke:rgba(255,193,7,.4)}.chartist-amber .ct-series-d .ct-bar,.chartist-amber .ct-series-d .ct-line,.chartist-amber .ct-series-d .ct-point,.chartist-amber .ct-series-d .ct-slice-donut{stroke:rgba(255,193,7,.2)}.chartist-amber .ct-series-a .ct-area,.chartist-amber .ct-series-a .ct-slice-donut-solid,.chartist-amber .ct-series-a .ct-slice-pie{fill:rgba(255,193,7,1)}.chartist-amber .ct-series-b .ct-area,.chartist-amber .ct-series-b .ct-slice-donut-solid,.chartist-amber .ct-series-b .ct-slice-pie{fill:rgba(255,193,7,.7)}.chartist-amber .ct-series-c .ct-area,.chartist-amber .ct-series-c .ct-slice-donut-solid,.chartist-amber .ct-series-c .ct-slice-pie{fill:rgba(255,193,7,.4)}.chartist-amber .ct-series-d .ct-area,.chartist-amber .ct-series-d .ct-slice-donut-solid,.chartist-amber .ct-series-d .ct-slice-pie{fill:rgba(255,193,7,.2)}.chartist-orange.text-black .ct-label{fill:#000;color:#000}.chartist-orange.text-white .ct-label{fill:#fff;color:#fff}.chartist-orange .ct-label{fill:rgba(255,152,0,.4);color:rgba(255,152,0,.4)}.chartist-orange .ct-grid{stroke:rgba(255,152,0,.2)}.chartist-orange .ct-series-a .ct-bar,.chartist-orange .ct-series-a .ct-line,.chartist-orange .ct-series-a .ct-point,.chartist-orange .ct-series-a .ct-slice-donut{stroke:rgba(255,152,0,1)}.chartist-orange .ct-series-b .ct-bar,.chartist-orange .ct-series-b .ct-line,.chartist-orange .ct-series-b .ct-point,.chartist-orange .ct-series-b .ct-slice-donut{stroke:rgba(255,152,0,.7)}.chartist-orange .ct-series-c .ct-bar,.chartist-orange .ct-series-c .ct-line,.chartist-orange .ct-series-c .ct-point,.chartist-orange .ct-series-c .ct-slice-donut{stroke:rgba(255,152,0,.4)}.chartist-orange .ct-series-d .ct-bar,.chartist-orange .ct-series-d .ct-line,.chartist-orange .ct-series-d .ct-point,.chartist-orange .ct-series-d .ct-slice-donut{stroke:rgba(255,152,0,.2)}.chartist-orange .ct-series-a .ct-area,.chartist-orange .ct-series-a .ct-slice-donut-solid,.chartist-orange .ct-series-a .ct-slice-pie{fill:rgba(255,152,0,1)}.chartist-orange .ct-series-b .ct-area,.chartist-orange .ct-series-b .ct-slice-donut-solid,.chartist-orange .ct-series-b .ct-slice-pie{fill:rgba(255,152,0,.7)}.chartist-orange .ct-series-c .ct-area,.chartist-orange .ct-series-c .ct-slice-donut-solid,.chartist-orange .ct-series-c .ct-slice-pie{fill:rgba(255,152,0,.4)}.chartist-orange .ct-series-d .ct-area,.chartist-orange .ct-series-d .ct-slice-donut-solid,.chartist-orange .ct-series-d .ct-slice-pie{fill:rgba(255,152,0,.2)}.chartist-brown.text-black .ct-label{fill:#000;color:#000}.chartist-brown.text-white .ct-label{fill:#fff;color:#fff}.chartist-brown .ct-label{fill:rgba(121,85,72,.4);color:rgba(121,85,72,.4)}.chartist-brown .ct-grid{stroke:rgba(121,85,72,.2)}.chartist-brown .ct-series-a .ct-bar,.chartist-brown .ct-series-a .ct-line,.chartist-brown .ct-series-a .ct-point,.chartist-brown .ct-series-a .ct-slice-donut{stroke:rgba(121,85,72,1)}.chartist-brown .ct-series-b .ct-bar,.chartist-brown .ct-series-b .ct-line,.chartist-brown .ct-series-b .ct-point,.chartist-brown .ct-series-b .ct-slice-donut{stroke:rgba(121,85,72,.7)}.chartist-brown .ct-series-c .ct-bar,.chartist-brown .ct-series-c .ct-line,.chartist-brown .ct-series-c .ct-point,.chartist-brown .ct-series-c .ct-slice-donut{stroke:rgba(121,85,72,.4)}.chartist-brown .ct-series-d .ct-bar,.chartist-brown .ct-series-d .ct-line,.chartist-brown .ct-series-d .ct-point,.chartist-brown .ct-series-d .ct-slice-donut{stroke:rgba(121,85,72,.2)}.chartist-brown .ct-series-a .ct-area,.chartist-brown .ct-series-a .ct-slice-donut-solid,.chartist-brown .ct-series-a .ct-slice-pie{fill:rgba(121,85,72,1)}.chartist-brown .ct-series-b .ct-area,.chartist-brown .ct-series-b .ct-slice-donut-solid,.chartist-brown .ct-series-b .ct-slice-pie{fill:rgba(121,85,72,.7)}.chartist-brown .ct-series-c .ct-area,.chartist-brown .ct-series-c .ct-slice-donut-solid,.chartist-brown .ct-series-c .ct-slice-pie{fill:rgba(121,85,72,.4)}.chartist-brown .ct-series-d .ct-area,.chartist-brown .ct-series-d .ct-slice-donut-solid,.chartist-brown .ct-series-d .ct-slice-pie{fill:rgba(121,85,72,.2)}.chartist-grey.text-black .ct-label{fill:#000;color:#000}.chartist-grey.text-white .ct-label{fill:#fff;color:#fff}.chartist-grey .ct-label{fill:rgba(158,158,158,.4);color:rgba(158,158,158,.4)}.chartist-grey .ct-grid{stroke:rgba(158,158,158,.2)}.chartist-grey .ct-series-a .ct-bar,.chartist-grey .ct-series-a .ct-line,.chartist-grey .ct-series-a .ct-point,.chartist-grey .ct-series-a .ct-slice-donut{stroke:rgba(158,158,158,1)}.chartist-grey .ct-series-b .ct-bar,.chartist-grey .ct-series-b .ct-line,.chartist-grey .ct-series-b .ct-point,.chartist-grey .ct-series-b .ct-slice-donut{stroke:rgba(158,158,158,.7)}.chartist-grey .ct-series-c .ct-bar,.chartist-grey .ct-series-c .ct-line,.chartist-grey .ct-series-c .ct-point,.chartist-grey .ct-series-c .ct-slice-donut{stroke:rgba(158,158,158,.4)}.chartist-grey .ct-series-d .ct-bar,.chartist-grey .ct-series-d .ct-line,.chartist-grey .ct-series-d .ct-point,.chartist-grey .ct-series-d .ct-slice-donut{stroke:rgba(158,158,158,.2)}.chartist-grey .ct-series-a .ct-area,.chartist-grey .ct-series-a .ct-slice-donut-solid,.chartist-grey .ct-series-a .ct-slice-pie{fill:rgba(158,158,158,1)}.chartist-grey .ct-series-b .ct-area,.chartist-grey .ct-series-b .ct-slice-donut-solid,.chartist-grey .ct-series-b .ct-slice-pie{fill:rgba(158,158,158,.7)}.chartist-grey .ct-series-c .ct-area,.chartist-grey .ct-series-c .ct-slice-donut-solid,.chartist-grey .ct-series-c .ct-slice-pie{fill:rgba(158,158,158,.4)}.chartist-grey .ct-series-d .ct-area,.chartist-grey .ct-series-d .ct-slice-donut-solid,.chartist-grey .ct-series-d .ct-slice-pie{fill:rgba(158,158,158,.2)}.chartist-blue.text-white-grey .ct-label{fill:#fff;color:#fff}.chartist-blue-grey .ct-label{fill:rgba(96,125,139,.4);color:rgba(96,125,139,.4)}.chartist-blue-grey .ct-grid{stroke:rgba(96,125,139,.2)}.chartist-blue-grey .ct-series-a .ct-bar,.chartist-blue-grey .ct-series-a .ct-line,.chartist-blue-grey .ct-series-a .ct-point,.chartist-blue-grey .ct-series-a .ct-slice-donut{stroke:rgba(96,125,139,1)}.chartist-blue-grey .ct-series-b .ct-bar,.chartist-blue-grey .ct-series-b .ct-line,.chartist-blue-grey .ct-series-b .ct-point,.chartist-blue-grey .ct-series-b .ct-slice-donut{stroke:rgba(96,125,139,.7)}.chartist-blue-grey .ct-series-c .ct-bar,.chartist-blue-grey .ct-series-c .ct-line,.chartist-blue-grey .ct-series-c .ct-point,.chartist-blue-grey .ct-series-c .ct-slice-donut{stroke:rgba(96,125,139,.4)}.chartist-blue-grey .ct-series-d .ct-bar,.chartist-blue-grey .ct-series-d .ct-line,.chartist-blue-grey .ct-series-d .ct-point,.chartist-blue-grey .ct-series-d .ct-slice-donut{stroke:rgba(96,125,139,.2)}.chartist-blue-grey .ct-series-a .ct-area,.chartist-blue-grey .ct-series-a .ct-slice-donut-solid,.chartist-blue-grey .ct-series-a .ct-slice-pie{fill:rgba(96,125,139,1)}.chartist-blue-grey .ct-series-b .ct-area,.chartist-blue-grey .ct-series-b .ct-slice-donut-solid,.chartist-blue-grey .ct-series-b .ct-slice-pie{fill:rgba(96,125,139,.7)}.chartist-blue-grey .ct-series-c .ct-area,.chartist-blue-grey .ct-series-c .ct-slice-donut-solid,.chartist-blue-grey .ct-series-c .ct-slice-pie{fill:rgba(96,125,139,.4)}.chartist-blue-grey .ct-series-d .ct-area,.chartist-blue-grey .ct-series-d .ct-slice-donut-solid,.chartist-blue-grey .ct-series-d .ct-slice-pie{fill:rgba(96,125,139,.2)}.chartist-black.text-black .ct-label{fill:#000;color:#000}.chartist-black.text-white .ct-label{fill:#fff;color:#fff}.chartist-black .ct-label{fill:rgba(0,0,0,.4);color:rgba(0,0,0,.4)}.chartist-black .ct-grid{stroke:rgba(0,0,0,.2)}.chartist-black .ct-series-a .ct-bar,.chartist-black .ct-series-a .ct-line,.chartist-black .ct-series-a .ct-point,.chartist-black .ct-series-a .ct-slice-donut{stroke:rgba(0,0,0,1)}.chartist-black .ct-series-b .ct-bar,.chartist-black .ct-series-b .ct-line,.chartist-black .ct-series-b .ct-point,.chartist-black .ct-series-b .ct-slice-donut{stroke:rgba(0,0,0,.7)}.chartist-black .ct-series-c .ct-bar,.chartist-black .ct-series-c .ct-line,.chartist-black .ct-series-c .ct-point,.chartist-black .ct-series-c .ct-slice-donut{stroke:rgba(0,0,0,.4)}.chartist-black .ct-series-d .ct-bar,.chartist-black .ct-series-d .ct-line,.chartist-black .ct-series-d .ct-point,.chartist-black .ct-series-d .ct-slice-donut{stroke:rgba(0,0,0,.2)}.chartist-black .ct-series-a .ct-area,.chartist-black .ct-series-a .ct-slice-donut-solid,.chartist-black .ct-series-a .ct-slice-pie{fill:rgba(0,0,0,1)}.chartist-black .ct-series-b .ct-area,.chartist-black .ct-series-b .ct-slice-donut-solid,.chartist-black .ct-series-b .ct-slice-pie{fill:rgba(0,0,0,.7)}.chartist-black .ct-series-c .ct-area,.chartist-black .ct-series-c .ct-slice-donut-solid,.chartist-black .ct-series-c .ct-slice-pie{fill:rgba(0,0,0,.4)}.chartist-black .ct-series-d .ct-area,.chartist-black .ct-series-d .ct-slice-donut-solid,.chartist-black .ct-series-d .ct-slice-pie{fill:rgba(0,0,0,.2)}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartjs.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartjs.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/chartjs.min.css
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/cover.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/cover.min.css
new file mode 100755
index 0000000..3b133ba
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/cover.min.css
@@ -0,0 +1 @@
+.cover{padding:15px;background-position:50% 50%;background-size:cover;background-repeat:no-repeat;width:100%;position:relative}.cover.cover-200{height:300px}.cover.cover-200{height:300px}.cover.cover-400{height:400px}.cover.cover-500{height:500px}.cover.no-padding{padding:0}.cover .avatar{height:100px;border-width:4px;margin-bottom:5px}.cover .item .avatar{height:50px}.cover .float-bottom-center,.cover .float-bottom-left,.cover .float-bottom-right{margin-bottom:-30px;z-index:99;position:absolute}.cover .big.float-bottom-center,.cover .big.float-bottom-left,.cover .big.float-bottom-right{margin-bottom:-35px}.cover .small.float-bottom-center,.cover .small.float-bottom-left,.cover .small.float-bottom-right{margin-bottom:-25px}.cover .float-bottom-center{left:50%;margin-left:-21px}.cover .small.float-bottom-center{left:50%;margin-left:-15px}.cover .big.float-bottom-center{left:50%;margin-left:-25px}.cover .gradient{background:-webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,.65) 100%);background:linear-gradient(to bottom,rgba(0,0,0,0) 0,rgba(0,0,0,.65) 100%);width:100%;padding-bottom:10px;padding-top:20px}.cover.blend-multiply{background-blend-mode:multiply}.cover.blend-screen{background-blend-mode:screen}.cover.blend-overlay{background-blend-mode:overlay}.cover.blend-darken{background-blend-mode:darken}.cover.blend-lighten{background-blend-mode:lighten}.cover.blend-color-dodge{background-blend-mode:color-dodge}.cover.blend-color-burn{background-blend-mode:color-burn}.cover.blend-hard-light{background-blend-mode:hard-light}.cover.blend-soft-light{background-blend-mode:soft-light}.cover.blend-luminosity{background-blend-mode:luminosity}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/ionicons.woff b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/ionicons.woff
new file mode 100644
index 0000000..5f3a14e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/ionicons.woff
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/roboto.woff2 b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/roboto.woff2
new file mode 100644
index 0000000..46f1cde
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/roboto.woff2
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotoblack.woff2 b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotoblack.woff2
new file mode 100644
index 0000000..f193280
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotoblack.woff2
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotolight.woff2 b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotolight.woff2
new file mode 100644
index 0000000..eacda32
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/fonts/robotolight.woff2
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/gfont.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/gfont.css
new file mode 100644
index 0000000..c0fb730
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/gfont.css
@@ -0,0 +1,304 @@
+/* latin */
+@font-face {
+  font-family: 'Chewy';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Chewy Regular'), local('Chewy-Regular'), url(https://fonts.gstatic.com/s/chewy/v10/uK_94ruUb-k-wn52KjI9OPec.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Dosis';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Dosis Regular'), local('Dosis-Regular'), url(https://fonts.gstatic.com/s/dosis/v8/HhyaU5sn9vOmLzlmC_WoEoZKdbA.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Dosis';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Dosis Regular'), local('Dosis-Regular'), url(https://fonts.gstatic.com/s/dosis/v8/HhyaU5sn9vOmLzloC_WoEoZK.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin */
+@font-face {
+  font-family: 'Monoton';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Monoton'), local('Monoton-Regular'), url(https://fonts.gstatic.com/s/monoton/v8/5h1aiZUrOngCibe4TkHLQka4BU4.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OX-hpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OVuhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXuhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OUehpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXehpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OXOhpKKSTj5PW.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Open Sans';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Open Sans Light'), local('OpenSans-Light'), url(https://fonts.gstatic.com/s/opensans/v16/mem5YaGs126MiZpBA-UN_r8OUuhpKKSTjw.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Raleway Light'), local('Raleway-Light'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwIYqWqhPANqczVsq4A.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Raleway Light'), local('Raleway-Light'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwIYqWqZPANqczVs.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Raleway'), local('Raleway-Regular'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptug8zYS_SKggPNyCMIT4ttDfCmxA.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Raleway'), local('Raleway-Regular'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptug8zYS_SKggPNyC0IT4ttDfA.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  src: local('Raleway Bold'), local('Raleway-Bold'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwJYtWqhPANqczVsq4A.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  src: local('Raleway Bold'), local('Raleway-Bold'), url(https://fonts.gstatic.com/s/raleway/v13/1Ptrg8zYS_SKggPNwJYtWqZPANqczVs.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fABc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCBc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fBxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fCxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fChc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 300;
+  src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmSU5fBBc4AMP6lQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCRc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfABc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* greek-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCBc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+1F00-1FFF;
+}
+/* greek */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfBxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0370-03FF;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfCxc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfChc4AMP6lbBP.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Roboto';
+  font-style: normal;
+  font-weight: 900;
+  src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v19/KFOlCnqEu92Fr1MmYUtfBBc4AMP6lQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/grid.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/grid.min.css
new file mode 100755
index 0000000..d3e0e6e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/grid.min.css
@@ -0,0 +1 @@
+.row{display:-webkit-box;display:-ms-flexbox;display:flex}.row-between{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.row-around{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around}.row-stretch{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.column{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.wrap{-ms-flex-wrap:wrap;flex-wrap:wrap}.vertical-align-top{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.vertical-align-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.vertical-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.horizontal-align-left{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.horizontal-align-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.horizontal-align-right{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.row-center{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.col{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative}.col-10{position:relative;-ms-flex-preferred-size:10%;flex-basis:10%}.col-20{position:relative;-ms-flex-preferred-size:20%;flex-basis:20%}.col-25{position:relative;-ms-flex-preferred-size:25%;flex-basis:25%}.col-33,.col-34{position:relative;-ms-flex-preferred-size:33.3333%;flex-basis:33.3333%}.col-50{position:relative;-ms-flex-preferred-size:50%;flex-basis:50%}.col-66,.col-67{position:relative;-ms-flex-preferred-size:66.6666%;flex-basis:66.6666%}.col-75{position:relative;-ms-flex-preferred-size:75%;flex-basis:75%}.col-80{position:relative;-ms-flex-preferred-size:80%;flex-basis:80%}.col-90{position:relative;-ms-flex-preferred-size:100%;flex-basis:100%}.full-width{width:100%;margin:0 auto}.full-height{height:100%;margin:0 auto}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/header.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/header.min.css
new file mode 100755
index 0000000..0981cb8
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/header.min.css
@@ -0,0 +1 @@
+.footer,.header{font-size:18px;display:inline-block;width:100%;position:fixed;top:0;left:0;height:52px;z-index:9}.footer{top:initial;bottom:0}.header.sub{top:52px}.footer.sub{top:initial;bottom:52px}.has-header{padding-top:52px!important}.has-header.has-sub-header{padding-top:104px!important}.has-footer{padding-bottom:52px!important}.has-footer.has-sub-footer{padding-bottom:104px!important}.footer .left,.footer .right,.footer .title,.footer h1,.header .left,.header .right,.header .title,.header h1{margin-top:15px;margin-bottom:5px}.header .avatar{height:40px;margin-top:-8px;margin-left:4px}.header .border-big{border-width:2px;border-style:solid}.footer h2,.header h2{padding-top:8px;padding-left:10px}.footer p,.header p{padding-left:10px;margin:0;margin-top:-4px}.footer .left,.header .left{padding-left:5px}.footer .right,.header .right{padding-right:5px}.footer .title,.footer h1,.header .title,.header h1{margin-bottom:15px;padding-left:10px;padding-right:15px;display:inline-block}.footer button,.header button{margin-top:-10px}.footer button.icon,.header button.icon{font-size:30px;margin-top:-10px;z-index:99;background:0 0;border:none;padding:0 6px}.footer button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]),.header button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]){color:#fff}.footer button.icon.left,.footer button.icon.right,.header button.icon.left,.header button.icon.right{margin-top:5px;margin-bottom:5px}.footer button.icon.left,.header button.icon.left{margin-left:5px}.footer button.icon.right,.header button.icon.right{margin-right:5px}.footer .title.align-center,.footer h1.align-center,.footer p.align-center,.header .title.align-center,.header h1.align-center,.header p.align-center{width:100%;position:inherit;padding-right:15px;left:0;z-index:9}.footer .icon-badge,.header .icon-badge{position:absolute;margin-left:-6px;margin-top:-8px;border-radius:8px;z-index:999}.footer .buttons-group,.header .buttons-group{margin-top:15px;margin-left:5px;margin-right:5px}.footer .buttons-group.small,.header .buttons-group.small{margin-top:20px;margin-left:10px;margin-right:10px}.header input::-webkit-input-placeholder{color:rgba(0,0,0,.8)}.header input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.8)}.header input{padding:15px;position:absolute}.header .left+input{padding-right:50px}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/horizontal-scroll.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/horizontal-scroll.min.css
new file mode 100755
index 0000000..2ce80d4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/horizontal-scroll.min.css
@@ -0,0 +1 @@
+.horizontal-scroll{width:100%;position:relative;border:1px solid #ddd;display:flex;display:-moz-flex;display:-ms-flexbox;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch}.horizontal-scroll.no-scroll-bar::-webkit-scrollbar{display:none}.horizontal-scroll .item{padding:15px;display:inline-block;flex:0 0 auto;width:100%;border-right:1px solid #ddd;position:relative;font-size:18px}.horizontal-scroll .item.hidden{display:none}.horizontal-scroll .item.mark{border-right:0;border-bottom:0;border-top:0}.item .block{display:-webkit-box;display:flex}.horizontal-scroll .item.mark.margin-right{border-right:0;margin-right:10px}.horizontal-scroll .item.space-small{padding-left:5px;padding-right:5px}.horizontal-scroll.space-small .item{padding-left:5px;padding-right:5px}.horizontal-scroll .item.no-space-left{padding-left:0!important}.horizontal-scroll .item.no-space-right{padding-right:0!important}.horizontal-scroll.no-space-left .item{padding-left:0!important}.horizontal-scroll.no-space-right .item{padding-right:0!important}.horizontal-scroll.no-space-top .item{padding-top:0!important}.horizontal-scroll.no-space-bottom .item{padding-bottom:0!important}.horizontal-scroll.no-space .item{padding-left:0!important;padding-right:0!important;padding-top:0!important;padding-bottom:0!important}.horizontal-scroll .item.row{display:-moz-flex;display:-ms-flexbox;display:flex}.horizontal-scroll .item.full{width:100%}.horizontal-scroll .item.three-fourth{width:75%}.horizontal-scroll .item.half{width:50%}.horizontal-scroll .item.one-fourth{width:25%}.horizontal-scroll .item h1,.horizontal-scroll .item h2{font-size:16px;margin:0;padding:0}.horizontal-scroll .item h1{margin-top:7px}.horizontal-scroll .item p{font-size:14px;margin:0;padding:0;line-height:20px}.horizontal-scroll .left{margin-right:10px;min-width:25px}.horizontal-scroll .right{margin-right:20px;position:absolute;top:0;right:0;height:100%;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}.horizontal-scroll .right i{margin-left:5px}.horizontal-scroll .align-top{-ms-flex-align:center;-webkit-align-items:center;align-items:baseline;margin-top:10px}.horizontal-scroll .avatar{height:50px}.avatar-badge{position:absolute;margin-left:-4px;margin-top:-3px;border-radius:8px}.horizontal-scroll .item small,.horizontal-scroll .item small .icon{font-size:14px}.horizontal-scroll .item .icon{font-size:18px}.horizontal-scroll .item .icon.text-huge{font-size:32px}.horizontal-scroll .left .icon,.horizontal-scroll .right .icon{vertical-align:-webkit-baseline-middle}.horizontal-scroll .border-big{border-width:3px;border-style:solid}.horizontal-scroll.no-border{border:0}.horizontal-scroll .item.no-border.border-right,.horizontal-scroll.no-border .item.border-right{border-right-width:1px;border-right-style:solid}.horizontal-scroll .item.no-border,.horizontal-scroll.no-border .item{border:none}.horizontal-scroll .item:last-child{border-right:0}.horizontal-scroll .item .right .icon,.horizontal-scroll .item .right.icon{font-size:24px;padding:0;margin:0}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/imports.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/imports.css
new file mode 100755
index 0000000..510317d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/imports.css
@@ -0,0 +1,30 @@
+@import url("./alert.min.css");
+@import url("./base.min.css");
+@import url("./button.min.css");
+@import url("./chart-bar.min.css");
+@import url("./chartist.min.css");
+@import url("./chartist-plugin-tooltip.min.css");
+@import url("./chartjs.min.css");
+@import url("./cover.min.css");
+@import url("./grid.min.css");
+@import url("./header.min.css");
+@import url("./horizontal-scroll.min.css");
+@import url("./include.min.css");
+@import url("./input.min.css");
+@import url("./jquery.min.css");
+@import url("./list.min.css");
+@import url("./loading.min.css");
+@import url("./menu.min.css");
+@import url("./mobileui-colors.min.css");
+@import url("./mobileuijs.min.css");
+@import url("./momentjs.min.css");
+@import url("./page.min.css");
+@import url("./popover.min.css");
+@import url("./progress-circle.min.css");
+@import url("./progress-semicircle.min.css");
+@import url("./progressbarjs.min.css");
+@import url("./pulltorefresh.min.css");
+@import url("./swiper.min.css");
+@import url("./tab.min.css");
+@import url("./timeline.min.css");
+@import url("./toast.min.css");
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/include.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/include.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/include.min.css
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/input.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/input.min.css
new file mode 100755
index 0000000..e68a220
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/input.min.css
@@ -0,0 +1 @@
+input,select,textarea{border:none;background:0 0;font-size:14px;width:100%;-webkit-flex:1;-ms-flex:1;flex:1}input[disabled],select[disabled],textarea[disabled]{opacity:.8}label{font-size:14px}.item.label-fixed,.label-fixed{display:-moz-flex!important;display:-ms-flexbox!important;display:flex!important;width:100%}.label-fixed label{-webkit-flex:0 0 100px;-ms-flex:0 0 100px;flex:0 0 100px;width:100px;min-width:100px;max-width:200px}.label-float label{margin-bottom:0;-webkit-transform:translate3d(0,27px,0);transform:translate3d(0,27px,0);-webkit-transform-origin:left top;transform-origin:left top;transition:-webkit-transform 150ms ease-in-out;transition:transform 150ms ease-in-out;transition:transform 150ms ease-in-out,-webkit-transform 150ms ease-in-out;align-self:stretch;-webkit-flex:initial;-ms-flex:initial;flex:initial;display:block}.label-float label.focus{-webkit-transform:translate3d(0,0,0) scale(.8);transform:translate3d(0,0,0) scale(.8)}.item.icon{display:flex}.item.icon.radius{border-radius:6px}.item.icon:not([class*=text-]){color:#9f9f9f}.item input::-webkit-input-placeholder{color:rgba(0,0,0,.6)}.item input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.6)}.item.icon:before{position:absolute}.item.icon.icon-right:before{right:20px}.item.icon input,.item.icon select{padding-left:30px}.item.icon.icon-right input,.item.icon.icon-right select{padding-left:0;padding-right:30px}input[type=checkbox]{width:17px;height:17px;z-index:1;border:0;vertical-align:top;outline:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:2px}.platform-ios input[type=checkbox]{height:23px;width:23px;border-radius:50%}input[type=checkbox]:not(:checked){background-color:#fff!important;box-shadow:inset 0 0 0 2px rgba(0,0,0,.5)}.platform-ios input[type=checkbox]:not(:checked){box-shadow:inset 0 0 0 1px rgba(0,0,0,.4)}input[type=checkbox]:disabled{opacity:.4}input[type=checkbox]::before{content:'';position:absolute;margin-top:1px;margin-left:5px;width:5px;height:10px;border-width:2px;border-top-width:0;border-left-width:0;border-style:solid;border-color:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.platform-ios input[type=checkbox]::before{margin-top:5px;margin-left:9px;width:4px;height:9px;border-width:1px;border-top-width:0;border-left-width:0}input[type=checkbox].switch{width:36px;height:14px;box-shadow:inset 0 0 0 30px rgba(255,255,255,.4);border-radius:28px;-webkit-transition-property:all;transition-property:all;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out}.platform-ios input[type=checkbox].switch{height:32px;width:51px;box-shadow:inset 0 0 0 2px rgba(0,0,0,.05)}input[type=checkbox].switch:not(:checked){background-color:#fff!important;box-shadow:inset 0 0 0 30px rgba(0,0,0,.35)}.platform-ios input[type=checkbox].switch:not(:checked){box-shadow:inset 0 0 0 2px rgba(0,0,0,.1)}input[type=checkbox].switch::before{content:'';border-radius:28px;height:20px;width:20px;margin-left:-1px;margin-top:-3px;-webkit-transition-duration:.35s;transition-duration:.35s;box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12),0 2px 4px -1px rgba(0,0,0,.4);border:0}.platform-ios input[type=checkbox].switch::before{height:28px;width:28px;box-shadow:0 0 0 1px #e4e4e4,0 3px 2px rgba(0,0,0,.25);margin-top:2px;margin-left:2px;background-color:#fff!important}input[type=checkbox].switch:checked::before{margin-left:16px}input[type=checkbox].switch:not(:checked)::before{background-color:#fff!important}.platform-ios input[type=checkbox].switch:checked::before{margin-left:21px;box-shadow:0 3px 2px rgba(0,0,0,.25);background-color:#fff}input[type=radio]{width:20px;height:20px;border-radius:50%;position:relative;overflow:hidden;z-index:1;vertical-align:top;outline:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:0 0}.platform-ios input[type=radio]{background:0 0!important}input[type=radio]::after{content:'';width:100%;height:100%;position:absolute;border-radius:50%}.platform-ios input[type=radio]:not(:checked)::after{box-shadow:none}input[type=radio]:not(:checked)::after{box-shadow:inset 0 0 0 2px rgba(0,0,0,.4);background-color:#fff!important}input[type=radio]:checked::before{content:'';width:10px;height:10px;position:absolute;border:3px solid #fff;z-index:1;border-radius:50%;margin-top:2px;margin-left:2px}input[type=radio]:disabled{opacity:.4}.platform-ios input[type=radio]::after{background:0 0!important}.platform-ios input[type=radio]:checked::before{position:absolute;margin-top:4px;margin-left:7px;width:5px;height:12px;border-width:2px;border-top-width:0;border-left-width:0;border-style:solid;-webkit-transform:rotate(45deg);transform:rotate(45deg);border-radius:0}.item.range{position:relative;-ms-flex-item-align:center;-webkit-align-self:center;align-self:center}.item.range input{position:absolute;height:28px;width:calc(100% - 110px);margin:4px 0 5px 0;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;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:100% 2px;background-repeat:no-repeat;outline:0;border:none;box-sizing:content-box;-ms-background-position-y:500px}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background-color:#666;width:13px;height:13px;border-radius:50%}input[type=range]:active::-webkit-slider-thumb{width:20px;height:20px}.platform-ios input[type=range]::-webkit-slider-thumb{background-color:#fff;box-shadow:1px 1px 5px rgba(0,0,0,.3);width:25px;height:25px;border:1px solid rgba(0,0,0,.05);border-radius:50%}input[type=checkbox].red-50.switch::before,input[type=radio].red-50::after{background-color:#ffebee}input[type=checkbox].red-100.switch::before,input[type=radio].red-100::after{background-color:#ffcdd2}input[type=checkbox].red-200.switch::before,input[type=radio].red-200::after{background-color:#ef9a9a}input[type=checkbox].red-300.switch::before,input[type=radio].red-300::after{background-color:#e57373}input[type=checkbox].red-400.switch::before,input[type=radio].red-400::after{background-color:#ef5350}input[type=checkbox].red-500.switch::before,input[type=radio].red-500::after{background-color:#f44336}input[type=checkbox].red-600.switch::before,input[type=radio].red-600::after{background-color:#e53935}input[type=checkbox].red-700.switch::before,input[type=radio].red-700::after{background-color:#d32f2f}input[type=checkbox].red-800.switch::before,input[type=radio].red-800::after{background-color:#c62828}input[type=checkbox].red-900.switch::before,input[type=radio].red-900::after{background-color:#b71c1c}input[type=checkbox].pink.switch::before,input[type=radio].pink::after{background-color:#e91e63}input[type=checkbox].pink-50.switch::before,input[type=radio].pink-50::after{background-color:#fce4ec}input[type=checkbox].pink-100.switch::before,input[type=radio].pink-100::after{background-color:#f8bbd0}input[type=checkbox].pink-200.switch::before,input[type=radio].pink-200::after{background-color:#f48fb1}input[type=checkbox].Pink-300.switch::before,input[type=radio].Pink-300::after{background-color:#f06292}input[type=checkbox].pink-400.switch::before,input[type=radio].pink-400::after{background-color:#ec407a}input[type=checkbox].pink-500.switch::before,input[type=radio].pink-500::after{background-color:#e91e63}input[type=checkbox].pink-600.switch::before,input[type=radio].pink-600::after{background-color:#d81b60}input[type=checkbox].pink-700.switch::before,input[type=radio].pink-700::after{background-color:#c2185b}input[type=checkbox].pink-800.switch::before,input[type=radio].pink-800::after{background-color:#ad1457}input[type=checkbox].pink-900.switch::before,input[type=radio].pink-900::after{background-color:#880e4f}input[type=checkbox].purple.switch::before,input[type=radio].purple::after{background-color:#9c27b0}input[type=checkbox].purple-50.switch::before,input[type=radio].purple-50::after{background-color:#f3e5f5}input[type=checkbox].purple-100.switch::before,input[type=radio].purple-100::after{background-color:#e1bee7}input[type=checkbox].purple-200.switch::before,input[type=radio].purple-200::after{background-color:#ce93d8}input[type=checkbox].Purple-300.switch::before,input[type=radio].Purple-300::after{background-color:#ba68c8}input[type=checkbox].Purple-400.switch::before,input[type=radio].Purple-400::after{background-color:#ab47bc}input[type=checkbox].purple-500.switch::before,input[type=radio].purple-500::after{background-color:#9c27b0}input[type=checkbox].purple-600.switch::before,input[type=radio].purple-600::after{background-color:#8e24aa}input[type=checkbox].purple-700.switch::before,input[type=radio].purple-700::after{background-color:#7b1fa2}input[type=checkbox].purple-800.switch::before,input[type=radio].purple-800::after{background-color:#6a1b9a}input[type=checkbox].purple-900.switch::before,input[type=radio].purple-900::after{background-color:#4a148c}input[type=checkbox].deep-purple.switch::before,input[type=radio].deep-purple::after{background-color:#673ab7}input[type=checkbox].deep-purple-300.switch::before,input[type=radio].deep-purple-300::after{background-color:#9575cd}input[type=checkbox].deep-purple-400.switch::before,input[type=radio].deep-purple-400::after{background-color:#7e57c2}input[type=checkbox].deep-purple-500.switch::before,input[type=radio].deep-purple-500::after{background-color:#673ab7}input[type=checkbox].deep-purple-600.switch::before,input[type=radio].deep-purple-600::after{background-color:#5e35b1}input[type=checkbox].deep-purple-700.switch::before,input[type=radio].deep-purple-700::after{background-color:#512da8}input[type=checkbox].deep-purple-800.switch::before,input[type=radio].deep-purple-800::after{background-color:#4527a0}input[type=checkbox].deep-purple-900.switch::before,input[type=radio].deep-purple-900::after{background-color:#311b92}input[type=checkbox].indigo.switch::before,input[type=radio].indigo::after{background-color:#3f51b5}input[type=checkbox].indigo-50.switch::before,input[type=radio].indigo-50::after{background-color:#e8eaf6}input[type=checkbox].indigo-100.switch::before,input[type=radio].indigo-100::after{background-color:#c5cae9}input[type=checkbox].indigo-200.switch::before,input[type=radio].indigo-200::after{background-color:#9fa8da}input[type=checkbox].indigo-300.switch::before,input[type=radio].indigo-300::after{background-color:#7986cb}input[type=checkbox].indigo-400.switch::before,input[type=radio].indigo-400::after{background-color:#5c6bc0}input[type=checkbox].indigo-500.switch::before,input[type=radio].indigo-500::after{background-color:#3f51b5}input[type=checkbox].indigo-600.switch::before,input[type=radio].indigo-600::after{background-color:#3949ab}input[type=checkbox].indigo-700.switch::before,input[type=radio].indigo-700::after{background-color:#303f9f}input[type=checkbox].indigo-800.switch::before,input[type=radio].indigo-800::after{background-color:#283593}input[type=checkbox].indigo-900.switch::before,input[type=radio].indigo-900::after{background-color:#1a237e}input[type=checkbox].blue.switch::before,input[type=radio].blue::after{background-color:#2196f3}input[type=checkbox].blue-50.switch::before,input[type=radio].blue-50::after{background-color:#e3f2fd}input[type=checkbox].blue-100.switch::before,input[type=radio].blue-100::after{background-color:#bbdefb}input[type=checkbox].blue-200.switch::before,input[type=radio].blue-200::after{background-color:#90caf9}input[type=checkbox].blue-300.switch::before,input[type=radio].blue-300::after{background-color:#64b5f6}input[type=checkbox].blue-400.switch::before,input[type=radio].blue-400::after{background-color:#42a5f5}input[type=checkbox].blue-500.switch::before,input[type=radio].blue-500::after{background-color:#2196f3}input[type=checkbox].blue-600.switch::before,input[type=radio].blue-600::after{background-color:#1e88e5}input[type=checkbox].blue-700.switch::before,input[type=radio].blue-700::after{background-color:#1976d2}input[type=checkbox].blue-800.switch::before,input[type=radio].blue-800::after{background-color:#1565c0}input[type=checkbox].blue-900.switch::before,input[type=radio].blue-900::after{background-color:#0d47a1}input[type=checkbox].light-blue.switch::before,input[type=radio].light-blue::after{background-color:#03a9f4}input[type=checkbox].light-blue-50.switch::before,input[type=radio].light-blue-50::after{background-color:#e1f5fe}input[type=checkbox].light-blue-100.switch::before,input[type=radio].light-blue-100::after{background-color:#b3e5fc}input[type=checkbox].light-blue-200.switch::before,input[type=radio].light-blue-200::after{background-color:#81d4fa}input[type=checkbox].light-blue-300.switch::before,input[type=radio].light-blue-300::after{background-color:#4fc3f7}input[type=checkbox].light-blue-400.switch::before,input[type=radio].light-blue-400::after{background-color:#29b6f6}input[type=checkbox].light-blue-500.switch::before,input[type=radio].light-blue-500::after{background-color:#03a9f4}input[type=checkbox].light-blue-600.switch::before,input[type=radio].light-blue-600::after{background-color:#039be5}input[type=checkbox].light-blue-700.switch::before,input[type=radio].light-blue-700::after{background-color:#0288d1}input[type=checkbox].light-blue-800.switch::before,input[type=radio].light-blue-800::after{background-color:#0277bd}input[type=checkbox].light-blue-900.switch::before,input[type=radio].light-blue-900::after{background-color:#01579b}input[type=checkbox].cyan.switch::before,input[type=radio].cyan::after{background-color:#00bcd4}input[type=checkbox].cyan-50.switch::before,input[type=radio].cyan-50::after{background-color:#e0f7fa}input[type=checkbox].cyan-100.switch::before,input[type=radio].cyan-100::after{background-color:#b2ebf2}input[type=checkbox].cyan-200.switch::before,input[type=radio].cyan-200::after{background-color:#80deea}input[type=checkbox].cyan-300.switch::before,input[type=radio].cyan-300::after{background-color:#4dd0e1}input[type=checkbox].cyan-400.switch::before,input[type=radio].cyan-400::after{background-color:#26c6da}input[type=checkbox].cyan-500.switch::before,input[type=radio].cyan-500::after{background-color:#00bcd4}input[type=checkbox].cyan-600.switch::before,input[type=radio].cyan-600::after{background-color:#00acc1}input[type=checkbox].cyan-700.switch::before,input[type=radio].cyan-700::after{background-color:#0097a7}input[type=checkbox].cyan-800.switch::before,input[type=radio].cyan-800::after{background-color:#00838f}input[type=checkbox].cyan-900.switch::before,input[type=radio].cyan-900::after{background-color:#006064}input[type=checkbox].teal.switch::before,input[type=radio].teal::after{background-color:#009688}input[type=checkbox].teal-50.switch::before,input[type=radio].teal-50::after{background-color:#e0f2f1}input[type=checkbox].teal-100.switch::before,input[type=radio].teal-100::after{background-color:#b2dfdb}input[type=checkbox].teal-200.switch::before,input[type=radio].teal-200::after{background-color:#80cbc4}input[type=checkbox].teal-300.switch::before,input[type=radio].teal-300::after{background-color:#4db6ac}input[type=checkbox].teal-400.switch::before,input[type=radio].teal-400::after{background-color:#26a69a}input[type=checkbox].teal-500.switch::before,input[type=radio].teal-500::after{background-color:#009688}input[type=checkbox].teal-600.switch::before,input[type=radio].teal-600::after{background-color:#00897b}input[type=checkbox].teal-700.switch::before,input[type=radio].teal-700::after{background-color:#00796b}input[type=checkbox].teal-800.switch::before,input[type=radio].teal-800::after{background-color:#00695c}input[type=checkbox].teal-900.switch::before,input[type=radio].teal-900::after{background-color:#004d40}input[type=checkbox].green.switch::before,input[type=radio].green::after{background-color:#4caf50}input[type=checkbox].green-50.switch::before,input[type=radio].green-50::after{background-color:#e8f5e9}input[type=checkbox].green-100.switch::before,input[type=radio].green-100::after{background-color:#c8e6c9}input[type=checkbox].green-200.switch::before,input[type=radio].green-200::after{background-color:#a5d6a7}input[type=checkbox].green-300.switch::before,input[type=radio].green-300::after{background-color:#81c784}input[type=checkbox].green-400.switch::before,input[type=radio].green-400::after{background-color:#66bb6a}input[type=checkbox].green-500.switch::before,input[type=radio].green-500::after{background-color:#4caf50}input[type=checkbox].green-600.switch::before,input[type=radio].green-600::after{background-color:#43a047}input[type=checkbox].green-700.switch::before,input[type=radio].green-700::after{background-color:#388e3c}input[type=checkbox].green-800.switch::before,input[type=radio].green-800::after{background-color:#2e7d32}input[type=checkbox].green-900.switch::before,input[type=radio].green-900::after{background-color:#1b5e20}input[type=checkbox].light-green.switch::before,input[type=radio].light-green::after{background-color:#8bc34a}input[type=checkbox].light-green-50.switch::before,input[type=radio].light-green-50::after{background-color:#f1f8e9}input[type=checkbox].light-green-100.switch::before,input[type=radio].light-green-100::after{background-color:#dcedc8}input[type=checkbox].light-green-200.switch::before,input[type=radio].light-green-200::after{background-color:#c5e1a5}input[type=checkbox].light-green-300.switch::before,input[type=radio].light-green-300::after{background-color:#aed581}input[type=checkbox].light-green-400.switch::before,input[type=radio].light-green-400::after{background-color:#9ccc65}input[type=checkbox].light-green-500.switch::before,input[type=radio].light-green-500::after{background-color:#8bc34a}input[type=checkbox].light-green-600.switch::before,input[type=radio].light-green-600::after{background-color:#7cb342}input[type=checkbox].light-green-700.switch::before,input[type=radio].light-green-700::after{background-color:#689f38}input[type=checkbox].light-green-800.switch::before,input[type=radio].light-green-800::after{background-color:#558b2f}input[type=checkbox].light-green-900.switch::before,input[type=radio].light-green-900::after{background-color:#33691e}input[type=checkbox].lime.switch::before,input[type=radio].lime::after{background-color:#cddc39}input[type=checkbox].lime-50.switch::before,input[type=radio].lime-50::after{background-color:#f9fbe7}input[type=checkbox].lime-100.switch::before,input[type=radio].lime-100::after{background-color:#f0f4c3}input[type=checkbox].lime-200.switch::before,input[type=radio].lime-200::after{background-color:#e6ee9c}input[type=checkbox].lime-300.switch::before,input[type=radio].lime-300::after{background-color:#dce775}input[type=checkbox].lime-400.switch::before,input[type=radio].lime-400::after{background-color:#d4e157}input[type=checkbox].lime-500.switch::before,input[type=radio].lime-500::after{background-color:#cddc39}input[type=checkbox].lime-600.switch::before,input[type=radio].lime-600::after{background-color:#c0ca33}input[type=checkbox].lime-700.switch::before,input[type=radio].lime-700::after{background-color:#afb42b}input[type=checkbox].lime-800.switch::before,input[type=radio].lime-800::after{background-color:#9e9d24}input[type=checkbox].lime-900.switch::before,input[type=radio].lime-900::after{background-color:#827717}input[type=checkbox].yellow.switch::before,input[type=radio].yellow::after{background-color:#ffeb3b}input[type=checkbox].yellow-50.switch::before,input[type=radio].yellow-50::after{background-color:#fffde7}input[type=checkbox].yellow-100.switch::before,input[type=radio].yellow-100::after{background-color:#fff9c4}input[type=checkbox].yellow-200.switch::before,input[type=radio].yellow-200::after{background-color:#fff59d}input[type=checkbox].yellow-300.switch::before,input[type=radio].yellow-300::after{background-color:#fff176}input[type=checkbox].yellow-500.switch::before,input[type=radio].yellow-500::after{background-color:#ffeb3b}input[type=checkbox].yellow-600.switch::before,input[type=radio].yellow-600::after{background-color:#fdd835}input[type=checkbox].yellow-700.switch::before,input[type=radio].yellow-700::after{background-color:#fbc02d}input[type=checkbox].yellow-800.switch::before,input[type=radio].yellow-800::after{background-color:#f9a825}input[type=checkbox].yellow-900.switch::before,input[type=radio].yellow-900::after{background-color:#f57f17}input[type=checkbox].amber-50.switch::before,input[type=radio].amber-50::after{background-color:#fff8e1}input[type=checkbox].amber-100.switch::before,input[type=radio].amber-100::after{background-color:#ffecb3}input[type=checkbox].amber-200.switch::before,input[type=radio].amber-200::after{background-color:#ffe082}input[type=checkbox].amber-300.switch::before,input[type=radio].amber-300::after{background-color:#ffd54f}input[type=checkbox].amber-500.switch::before,input[type=radio].amber-500::after{background-color:#ffc107}input[type=checkbox].amber-600.switch::before,input[type=radio].amber-600::after{background-color:#ffb300}input[type=checkbox].amber-700.switch::before,input[type=radio].amber-700::after{background-color:#ffa000}input[type=checkbox].amber-800.switch::before,input[type=radio].amber-800::after{background-color:#ff8f00}input[type=checkbox].amber-900.switch::before,input[type=radio].amber-900::after{background-color:#ff6f00}input[type=checkbox].orange-50.switch::before,input[type=radio].orange-50::after{background-color:#fff3e0}input[type=checkbox].orange-100.switch::before,input[type=radio].orange-100::after{background-color:#ffe0b2}input[type=checkbox].orange-200.switch::before,input[type=radio].orange-200::after{background-color:#ffcc80}input[type=checkbox].orange-300.switch::before,input[type=radio].orange-300::after{background-color:#ffb74d}input[type=checkbox].orange-400.switch::before,input[type=radio].orange-400::after{background-color:#ffa726}input[type=checkbox].orange-500.switch::before,input[type=radio].orange-500::after{background-color:#ff9800}input[type=checkbox].orange-600.switch::before,input[type=radio].orange-600::after{background-color:#fb8c00}input[type=checkbox].orange-700.switch::before,input[type=radio].orange-700::after{background-color:#f57c00}input[type=checkbox].orange-800.switch::before,input[type=radio].orange-800::after{background-color:#ef6c00}input[type=checkbox].orange-900.switch::before,input[type=radio].orange-900::after{background-color:#e65100}input[type=checkbox].deep-orange.switch::before,input[type=radio].deep-orange::after{background-color:#ff5722}input[type=checkbox].deep-orange-50.switch::before,input[type=radio].deep-orange-50::after{background-color:#fbe9e7}input[type=checkbox].deep-orange-100.switch::before,input[type=radio].deep-orange-100::after{background-color:#ffccbc}input[type=checkbox].deep-orange-200.switch::before,input[type=radio].deep-orange-200::after{background-color:#ffab91}input[type=checkbox].deep-orange-300.switch::before,input[type=radio].deep-orange-300::after{background-color:#ff8a65}input[type=checkbox].deep-orange-400.switch::before,input[type=radio].deep-orange-400::after{background-color:#ff7043}input[type=checkbox].deep-orange-500.switch::before,input[type=radio].deep-orange-500::after{background-color:#ff5722}input[type=checkbox].deep-orange-600.switch::before,input[type=radio].deep-orange-600::after{background-color:#f4511e}input[type=checkbox].deep-orange-700.switch::before,input[type=radio].deep-orange-700::after{background-color:#e64a19}input[type=checkbox].deep-orange-800.switch::before,input[type=radio].deep-orange-800::after{background-color:#d84315}input[type=checkbox].deep-orange-900.switch::before,input[type=radio].deep-orange-900::after{background-color:#bf360c}input[type=checkbox].brown.switch::before,input[type=radio].brown::after{background-color:#795548}input[type=checkbox].brown-50.switch::before,input[type=radio].brown-50::after{background-color:#efebe9}input[type=checkbox].brown-100.switch::before,input[type=radio].brown-100::after{background-color:#d7ccc8}input[type=checkbox].brown-200.switch::before,input[type=radio].brown-200::after{background-color:#bcaaa4}input[type=checkbox].brown-300.switch::before,input[type=radio].brown-300::after{background-color:#a1887f}input[type=checkbox].brown-400.switch::before,input[type=radio].brown-400::after{background-color:#8d6e63}input[type=checkbox].brown-500.switch::before,input[type=radio].brown-500::after{background-color:#795548}input[type=checkbox].brown-600.switch::before,input[type=radio].brown-600::after{background-color:#6d4c41}input[type=checkbox].brown-700.switch::before,input[type=radio].brown-700::after{background-color:#5d4037}input[type=checkbox].brown-800.switch::before,input[type=radio].brown-800::after{background-color:#4e342e}input[type=checkbox].brown-900.switch::before,input[type=radio].brown-900::after{background-color:#3e2723}input[type=checkbox].grey.switch::before,input[type=radio].grey::after{background-color:#9e9e9e}input[type=checkbox].grey-50.switch::before,input[type=radio].grey-50::after{background-color:#fafafa}input[type=checkbox].grey-100.switch::before,input[type=radio].grey-100::after{background-color:#f5f5f5}input[type=checkbox].grey-200.switch::before,input[type=radio].grey-200::after{background-color:#eee}input[type=checkbox].grey-300.switch::before,input[type=radio].grey-300::after{background-color:#e0e0e0}input[type=checkbox].grey-400.switch::before,input[type=radio].grey-400::after{background-color:#bdbdbd}input[type=checkbox].grey-500.switch::before,input[type=radio].grey-500::after{background-color:#9e9e9e}input[type=checkbox].grey-600.switch::before,input[type=radio].grey-600::after{background-color:#757575}input[type=checkbox].grey-700.switch::before,input[type=radio].grey-700::after{background-color:#616161}input[type=checkbox].grey-800.switch::before,input[type=radio].grey-800::after{background-color:#424242}input[type=checkbox].grey-900.switch::before,input[type=radio].grey-900::after{background-color:#212121}input[type=checkbox].blue-grey.switch::before,input[type=radio].blue-grey::after{background-color:#607d8b}input[type=checkbox].blue-grey-50.switch::before,input[type=radio].blue-grey-50::after{background-color:#eceff1}input[type=checkbox].blue-grey-100.switch::before,input[type=radio].blue-grey-100::after{background-color:#cfd8dc}input[type=checkbox].blue-grey-200.switch::before,input[type=radio].blue-grey-200::after{background-color:#b0bec5}input[type=checkbox].blue-grey-300.switch::before,input[type=radio].blue-grey-300::after{background-color:#90a4ae}input[type=checkbox].blue-grey-400.switch::before,input[type=radio].blue-grey-400::after{background-color:#78909c}input[type=checkbox].blue-grey-500.switch::before,input[type=radio].blue-grey-500::after{background-color:#607d8b}input[type=checkbox].blue-grey-600.switch::before,input[type=radio].blue-grey-600::after{background-color:#546e7a}input[type=checkbox].blue-grey-700.switch::before,input[type=radio].blue-grey-700::after{background-color:#455a64}input[type=checkbox].blue-grey-800.switch::before,input[type=radio].blue-grey-800::after{background-color:#37474f}input[type=checkbox].blue-grey-900.switch::before,input[type=radio].blue-grey-900::after{background-color:#263238}input[type=checkbox].black.switch::before,input[type=radio].black::after{background-color:#000}.platform-ios input[type=radio].red-50::before{border-color:#ffebee}.platform-ios input[type=radio].red-100::before{border-color:#ffcdd2}.platform-ios input[type=radio].red-200::before{border-color:#ef9a9a}.platform-ios input[type=radio].red-300::before{border-color:#e57373}.platform-ios input[type=radio].red-400::before{border-color:#ef5350}.platform-ios input[type=radio].red-500::before{border-color:#f44336}.platform-ios input[type=radio].red-600::before{border-color:#e53935}.platform-ios input[type=radio].red-700::before{border-color:#d32f2f}.platform-ios input[type=radio].red-800::before{border-color:#c62828}.platform-ios input[type=radio].red-900::before{border-color:#b71c1c}.platform-ios input[type=radio].pink::before{border-color:#e91e63}.platform-ios input[type=radio].pink-50::before{border-color:#fce4ec}.platform-ios input[type=radio].pink-100::before{border-color:#f8bbd0}.platform-ios input[type=radio].pink-200::before{border-color:#f48fb1}.platform-ios input[type=radio].Pink-300::before{border-color:#f06292}.platform-ios input[type=radio].pink-400::before{border-color:#ec407a}.platform-ios input[type=radio].pink-500::before{border-color:#e91e63}.platform-ios input[type=radio].pink-600::before{border-color:#d81b60}.platform-ios input[type=radio].pink-700::before{border-color:#c2185b}.platform-ios input[type=radio].pink-800::before{border-color:#ad1457}.platform-ios input[type=radio].pink-900::before{border-color:#880e4f}.platform-ios input[type=radio].purple::before{border-color:#9c27b0}.platform-ios input[type=radio].purple-50::before{border-color:#f3e5f5}.platform-ios input[type=radio].purple-100::before{border-color:#e1bee7}.platform-ios input[type=radio].purple-200::before{border-color:#ce93d8}.platform-ios input[type=radio].Purple-300::before{border-color:#ba68c8}.platform-ios input[type=radio].Purple-400::before{border-color:#ab47bc}.platform-ios input[type=radio].purple-500::before{border-color:#9c27b0}.platform-ios input[type=radio].purple-600::before{border-color:#8e24aa}.platform-ios input[type=radio].purple-700::before{border-color:#7b1fa2}.platform-ios input[type=radio].purple-800::before{border-color:#6a1b9a}.platform-ios input[type=radio].purple-900::before{border-color:#4a148c}.platform-ios input[type=radio].deep-purple::before{border-color:#673ab7}.platform-ios input[type=radio].deep-purple-300::before{border-color:#9575cd}.platform-ios input[type=radio].deep-purple-400::before{border-color:#7e57c2}.platform-ios input[type=radio].deep-purple-500::before{border-color:#673ab7}.platform-ios input[type=radio].deep-purple-600::before{border-color:#5e35b1}.platform-ios input[type=radio].deep-purple-700::before{border-color:#512da8}.platform-ios input[type=radio].deep-purple-800::before{border-color:#4527a0}.platform-ios input[type=radio].deep-purple-900::before{border-color:#311b92}.platform-ios input[type=radio].indigo::before{border-color:#3f51b5}.platform-ios input[type=radio].indigo-50::before{border-color:#e8eaf6}.platform-ios input[type=radio].indigo-100::before{border-color:#c5cae9}.platform-ios input[type=radio].indigo-200::before{border-color:#9fa8da}.platform-ios input[type=radio].indigo-300::before{border-color:#7986cb}.platform-ios input[type=radio].indigo-400::before{border-color:#5c6bc0}.platform-ios input[type=radio].indigo-500::before{border-color:#3f51b5}.platform-ios input[type=radio].indigo-600::before{border-color:#3949ab}.platform-ios input[type=radio].indigo-700::before{border-color:#303f9f}.platform-ios input[type=radio].indigo-800::before{border-color:#283593}.platform-ios input[type=radio].indigo-900::before{border-color:#1a237e}.platform-ios input[type=radio].blue::before{border-color:#2196f3}.platform-ios input[type=radio].blue-50::before{border-color:#e3f2fd}.platform-ios input[type=radio].blue-100::before{border-color:#bbdefb}.platform-ios input[type=radio].blue-200::before{border-color:#90caf9}.platform-ios input[type=radio].blue-300::before{border-color:#64b5f6}.platform-ios input[type=radio].blue-400::before{border-color:#42a5f5}.platform-ios input[type=radio].blue-500::before{border-color:#2196f3}.platform-ios input[type=radio].blue-600::before{border-color:#1e88e5}.platform-ios input[type=radio].blue-700::before{border-color:#1976d2}.platform-ios input[type=radio].blue-800::before{border-color:#1565c0}.platform-ios input[type=radio].blue-900::before{border-color:#0d47a1}.platform-ios input[type=radio].light-blue::before{border-color:#03a9f4}.platform-ios input[type=radio].light-blue-50::before{border-color:#e1f5fe}.platform-ios input[type=radio].light-blue-100::before{border-color:#b3e5fc}.platform-ios input[type=radio].light-blue-200::before{border-color:#81d4fa}.platform-ios input[type=radio].light-blue-300::before{border-color:#4fc3f7}.platform-ios input[type=radio].light-blue-400::before{border-color:#29b6f6}.platform-ios input[type=radio].light-blue-500::before{border-color:#03a9f4}.platform-ios input[type=radio].light-blue-600::before{border-color:#039be5}.platform-ios input[type=radio].light-blue-700::before{border-color:#0288d1}.platform-ios input[type=radio].light-blue-800::before{border-color:#0277bd}.platform-ios input[type=radio].light-blue-900::before{border-color:#01579b}.platform-ios input[type=radio].cyan::before{border-color:#00bcd4}.platform-ios input[type=radio].cyan-50::before{border-color:#e0f7fa}.platform-ios input[type=radio].cyan-100::before{border-color:#b2ebf2}.platform-ios input[type=radio].cyan-200::before{border-color:#80deea}.platform-ios input[type=radio].cyan-300::before{border-color:#4dd0e1}.platform-ios input[type=radio].cyan-400::before{border-color:#26c6da}.platform-ios input[type=radio].cyan-500::before{border-color:#00bcd4}.platform-ios input[type=radio].cyan-600::before{border-color:#00acc1}.platform-ios input[type=radio].cyan-700::before{border-color:#0097a7}.platform-ios input[type=radio].cyan-800::before{border-color:#00838f}.platform-ios input[type=radio].cyan-900::before{border-color:#006064}.platform-ios input[type=radio].teal::before{border-color:#009688}.platform-ios input[type=radio].teal-50::before{border-color:#e0f2f1}.platform-ios input[type=radio].teal-100::before{border-color:#b2dfdb}.platform-ios input[type=radio].teal-200::before{border-color:#80cbc4}.platform-ios input[type=radio].teal-300::before{border-color:#4db6ac}.platform-ios input[type=radio].teal-400::before{border-color:#26a69a}.platform-ios input[type=radio].teal-500::before{border-color:#009688}.platform-ios input[type=radio].teal-600::before{border-color:#00897b}.platform-ios input[type=radio].teal-700::before{border-color:#00796b}.platform-ios input[type=radio].teal-800::before{border-color:#00695c}.platform-ios input[type=radio].teal-900::before{border-color:#004d40}.platform-ios input[type=radio].green::before{border-color:#4caf50}.platform-ios input[type=radio].green-50::before{border-color:#e8f5e9}.platform-ios input[type=radio].green-100::before{border-color:#c8e6c9}.platform-ios input[type=radio].green-200::before{border-color:#a5d6a7}.platform-ios input[type=radio].green-300::before{border-color:#81c784}.platform-ios input[type=radio].green-400::before{border-color:#66bb6a}.platform-ios input[type=radio].green-500::before{border-color:#4caf50}.platform-ios input[type=radio].green-600::before{border-color:#43a047}.platform-ios input[type=radio].green-700::before{border-color:#388e3c}.platform-ios input[type=radio].green-800::before{border-color:#2e7d32}.platform-ios input[type=radio].green-900::before{border-color:#1b5e20}.platform-ios input[type=radio].light-green::before{border-color:#8bc34a}.platform-ios input[type=radio].light-green-50::before{border-color:#f1f8e9}.platform-ios input[type=radio].light-green-100::before{border-color:#dcedc8}.platform-ios input[type=radio].light-green-200::before{border-color:#c5e1a5}.platform-ios input[type=radio].light-green-300::before{border-color:#aed581}.platform-ios input[type=radio].light-green-400::before{border-color:#9ccc65}.platform-ios input[type=radio].light-green-500::before{border-color:#8bc34a}.platform-ios input[type=radio].light-green-600::before{border-color:#7cb342}.platform-ios input[type=radio].light-green-700::before{border-color:#689f38}.platform-ios input[type=radio].light-green-800::before{border-color:#558b2f}.platform-ios input[type=radio].light-green-900::before{border-color:#33691e}.platform-ios input[type=radio].lime::before{border-color:#cddc39}.platform-ios input[type=radio].lime-50::before{border-color:#f9fbe7}.platform-ios input[type=radio].lime-100::before{border-color:#f0f4c3}.platform-ios input[type=radio].lime-200::before{border-color:#e6ee9c}.platform-ios input[type=radio].lime-300::before{border-color:#dce775}.platform-ios input[type=radio].lime-400::before{border-color:#d4e157}.platform-ios input[type=radio].lime-500::before{border-color:#cddc39}.platform-ios input[type=radio].lime-600::before{border-color:#c0ca33}.platform-ios input[type=radio].lime-700::before{border-color:#afb42b}.platform-ios input[type=radio].lime-800::before{border-color:#9e9d24}.platform-ios input[type=radio].lime-900::before{border-color:#827717}.platform-ios input[type=radio].yellow::before{border-color:#ffeb3b}.platform-ios input[type=radio].yellow-50::before{border-color:#fffde7}.platform-ios input[type=radio].yellow-100::before{border-color:#fff9c4}.platform-ios input[type=radio].yellow-200::before{border-color:#fff59d}.platform-ios input[type=radio].yellow-300::before{border-color:#fff176}.platform-ios input[type=radio].yellow-500::before{border-color:#ffeb3b}.platform-ios input[type=radio].yellow-600::before{border-color:#fdd835}.platform-ios input[type=radio].yellow-700::before{border-color:#fbc02d}.platform-ios input[type=radio].yellow-800::before{border-color:#f9a825}.platform-ios input[type=radio].yellow-900::before{border-color:#f57f17}.platform-ios input[type=radio].amber-50::before{border-color:#fff8e1}.platform-ios input[type=radio].amber-100::before{border-color:#ffecb3}.platform-ios input[type=radio].amber-200::before{border-color:#ffe082}.platform-ios input[type=radio].amber-300::before{border-color:#ffd54f}.platform-ios input[type=radio].amber-500::before{border-color:#ffc107}.platform-ios input[type=radio].amber-600::before{border-color:#ffb300}.platform-ios input[type=radio].amber-700::before{border-color:#ffa000}.platform-ios input[type=radio].amber-800::before{border-color:#ff8f00}.platform-ios input[type=radio].amber-900::before{border-color:#ff6f00}.platform-ios input[type=radio].orange-50::before{border-color:#fff3e0}.platform-ios input[type=radio].orange-100::before{border-color:#ffe0b2}.platform-ios input[type=radio].orange-200::before{border-color:#ffcc80}.platform-ios input[type=radio].orange-300::before{border-color:#ffb74d}.platform-ios input[type=radio].orange-400::before{border-color:#ffa726}.platform-ios input[type=radio].orange-500::before{border-color:#ff9800}.platform-ios input[type=radio].orange-600::before{border-color:#fb8c00}.platform-ios input[type=radio].orange-700::before{border-color:#f57c00}.platform-ios input[type=radio].orange-800::before{border-color:#ef6c00}.platform-ios input[type=radio].orange-900::before{border-color:#e65100}.platform-ios input[type=radio].deep-orange::before{border-color:#ff5722}.platform-ios input[type=radio].deep-orange-50::before{border-color:#fbe9e7}.platform-ios input[type=radio].deep-orange-100::before{border-color:#ffccbc}.platform-ios input[type=radio].deep-orange-200::before{border-color:#ffab91}.platform-ios input[type=radio].deep-orange-300::before{border-color:#ff8a65}.platform-ios input[type=radio].deep-orange-400::before{border-color:#ff7043}.platform-ios input[type=radio].deep-orange-500::before{border-color:#ff5722}.platform-ios input[type=radio].deep-orange-600::before{border-color:#f4511e}.platform-ios input[type=radio].deep-orange-700::before{border-color:#e64a19}.platform-ios input[type=radio].deep-orange-800::before{border-color:#d84315}.platform-ios input[type=radio].deep-orange-900::before{border-color:#bf360c}.platform-ios input[type=radio].brown::before{border-color:#795548}.platform-ios input[type=radio].brown-50::before{border-color:#efebe9}.platform-ios input[type=radio].brown-100::before{border-color:#d7ccc8}.platform-ios input[type=radio].brown-200::before{border-color:#bcaaa4}.platform-ios input[type=radio].brown-300::before{border-color:#a1887f}.platform-ios input[type=radio].brown-400::before{border-color:#8d6e63}.platform-ios input[type=radio].brown-500::before{border-color:#795548}.platform-ios input[type=radio].brown-600::before{border-color:#6d4c41}.platform-ios input[type=radio].brown-700::before{border-color:#5d4037}.platform-ios input[type=radio].brown-800::before{border-color:#4e342e}.platform-ios input[type=radio].brown-900::before{border-color:#3e2723}.platform-ios input[type=radio].grey::before{border-color:#9e9e9e}.platform-ios input[type=radio].grey-50::before{border-color:#fafafa}.platform-ios input[type=radio].grey-100::before{border-color:#f5f5f5}.platform-ios input[type=radio].grey-200::before{border-color:#eee}.platform-ios input[type=radio].grey-300::before{border-color:#e0e0e0}.platform-ios input[type=radio].grey-400::before{border-color:#bdbdbd}.platform-ios input[type=radio].grey-500::before{border-color:#9e9e9e}.platform-ios input[type=radio].grey-600::before{border-color:#757575}.platform-ios input[type=radio].grey-700::before{border-color:#616161}.platform-ios input[type=radio].grey-800::before{border-color:#424242}.platform-ios input[type=radio].grey-900::before{border-color:#212121}.platform-ios input[type=radio].blue-grey::before{border-color:#607d8b}.platform-ios input[type=radio].blue-grey-50::before{border-color:#eceff1}.platform-ios input[type=radio].blue-grey-100::before{border-color:#cfd8dc}.platform-ios input[type=radio].blue-grey-200::before{border-color:#b0bec5}.platform-ios input[type=radio].blue-grey-300::before{border-color:#90a4ae}.platform-ios input[type=radio].blue-grey-400::before{border-color:#78909c}.platform-ios input[type=radio].blue-grey-500::before{border-color:#607d8b}.platform-ios input[type=radio].blue-grey-600::before{border-color:#546e7a}.platform-ios input[type=radio].blue-grey-700::before{border-color:#455a64}.platform-ios input[type=radio].blue-grey-800::before{border-color:#37474f}.platform-ios input[type=radio].blue-grey-900::before{border-color:#263238}.platform-ios input[type=radio].black::before{border-color:#000}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/list.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/list.min.css
new file mode 100755
index 0000000..0a6114a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/list.min.css
@@ -0,0 +1 @@
+.list{width:100%;position:relative;border:1px solid #F2F5F5}.list .item{padding:10px 15px;;display:inline-block;border-bottom:1px solid #F2F5F5;width:100%;position:relative;font-size:18px}.list .item.hidden{display:none}.list ol,.list ul{list-style:none}.list .item.space-small{padding-top:5px;padding-bottom:5px}.list .item.mark{border-right:0;border-top:0}.item .block{display:-webkit-box;display:flex}.list .item.mark.margin-button{border-bottom:0;margin-bottom:10px}.list .item.no-space-top{padding-top:0!important}.list .item.no-space-bottom{padding-bottom:0!important}.list .item.row{display:-moz-flex;display:-ms-flexbox;display:flex}.list.no-border{border:0}.list .item.no-border.border-bottom,.list.no-border .item.border-bottom{border-bottom-width:1px;border-bottom-style:solid}.list .item.no-border,.list.no-border .item{border:none}.list .item.cover{padding:0;margin-left:20px;height:200px;width:-webkit-calc(100% - 40px);width:-moz-calc(100% - 40px);width:calc(100% - 40px)}.list .item.full{padding:0;display:flex}.list .item h1,.list .item h2{font-size:16px;margin:0;padding:0}.list .item h1{margin-top:7px}.list .item p{font-size:14px;margin:0;padding:0;line-height:20px}.list .item:last-child{border-bottom:0}.list .left{margin-right:10px;min-width:25px}.list .right{margin-right:20px;position:absolute;top:0;right:0;height:100%;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-align-items:center;-webkit-box-align:center;align-items:center}.list .right i{margin-left:5px}.list .align-top{-ms-flex-align:center;-webkit-align-items:center;align-items:baseline;margin-top:10px}.list .avatar{height:50px}.avatar-badge{position:absolute;margin-left:-4px;margin-top:-3px;border-radius:8px}.list .item small,.list .item small .icon{font-size:14px}.list .item .icon{font-size:18px}.list .item .icon.text-huge{font-size:32px}.list .left .icon,.list .right .icon{vertical-align:-webkit-baseline-middle}.list .border-big{border-width:3px;border-style:solid}.list .item[onclick]:active,.list a.item:active{background-color:rgba(0,0,0,.1);cursor:pointer}.list .item .right .icon,.list .item .right.icon{font-size:24px;padding:0;margin:0}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/loading.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/loading.min.css
new file mode 100755
index 0000000..65c5258
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/loading.min.css
@@ -0,0 +1 @@
+.alert-loading .alert{padding:24px;text-align:center}.loading-circle{fill:transparent;stroke:#009688;stroke-width:5;-webkit-animation:dash 2s ease infinite,rotate 2s linear infinite;-moz-animation:dash 2s ease infinite,rotate 2s linear infinite;-o-animation:dash 2s ease infinite,rotate 2s linear infinite;animation:dash 2s ease infinite,rotate 2s linear infinite;margin:auto}.loading-circle.loading-element{zoom:.55;margin-top:-20px;margin-left:-20px;position:absolute}button .loading-circle.loading-element{left:50%;margin-left:-20px;top:50%;margin-top:-20px}.loading-circle.with-message.loading-element{margin-left:-50px;margin-top:17px;top:auto;left:auto}.loading-circle.loading-element.left{float:left;position:inherit;margin-left:0}.loading-circle.loading-element.right{float:right;position:inherit;margin-left:0}.loading-circle.white-loading{stroke:rgba(255,255,255,.8)}.loading-circle.with-message{margin-right:10px}.platform-ios .loading-circle{fill:#868686;-webkit-animation:none;-moz-animation:none;-o-animation:none;animation:none;stroke:none;stroke-width:0}.platform-ios .loading-circle.loading-element.white-loading{fill:rgba(255,255,255,.8)}.platform-ios .loading-circle path:nth-of-type(1){-webkit-animation:pulse 1s infinite linear;-moz-animation:pulse 1s infinite linear;-o-animation:pulse 1s infinite linear;animation:pulse 1s infinite linear}.platform-ios .loading-circle path:nth-of-type(2){-webkit-animation:pulse 1s -83ms infinite linear;-moz-animation:pulse 1s -83ms infinite linear;-o-animation:pulse 1s -83ms infinite linear;animation:pulse 1s -83ms infinite linear}.platform-ios .loading-circle path:nth-of-type(3){-webkit-animation:pulse 1s -.166s infinite linear;-moz-animation:pulse 1s -.166s infinite linear;-o-animation:pulse 1s -.166s infinite linear;animation:pulse 1s -.166s infinite linear}.platform-ios .loading-circle path:nth-of-type(4){-webkit-animation:pulse 1s -.249s infinite linear;-moz-animation:pulse 1s -.249s infinite linear;-o-animation:pulse 1s -.249s infinite linear;animation:pulse 1s -.249s infinite linear}.platform-ios .loading-circle path:nth-of-type(5){-webkit-animation:pulse 1s -.332s infinite linear;-moz-animation:pulse 1s -.332s infinite linear;-o-animation:pulse 1s -.332s infinite linear;animation:pulse 1s -.332s infinite linear}.platform-ios .loading-circle path:nth-of-type(6){-webkit-animation:pulse 1s -.415s infinite linear;-moz-animation:pulse 1s -.415s infinite linear;-o-animation:pulse 1s -.415s infinite linear;animation:pulse 1s -.415s infinite linear}.platform-ios .loading-circle path:nth-of-type(7){-webkit-animation:pulse 1s -.498s infinite linear;-moz-animation:pulse 1s -.498s infinite linear;-o-animation:pulse 1s -.498s infinite linear;animation:pulse 1s -.498s infinite linear}.platform-ios .loading-circle path:nth-of-type(8){-webkit-animation:pulse 1s -.581s infinite linear;-moz-animation:pulse 1s -.581s infinite linear;-o-animation:pulse 1s -.581s infinite linear;animation:pulse 1s -.581s infinite linear}.platform-ios .loading-circle path:nth-of-type(9){-webkit-animation:pulse 1s -.664s infinite linear;-moz-animation:pulse 1s -.664s infinite linear;-o-animation:pulse 1s -.664s infinite linear;animation:pulse 1s -.664s infinite linear}.platform-ios .loading-circle path:nth-of-type(10){-webkit-animation:pulse 1s -.747s infinite linear;-moz-animation:pulse 1s -.747s infinite linear;-o-animation:pulse 1s -.747s infinite linear;animation:pulse 1s -.747s infinite linear}.platform-ios .alert-loading .loading-circle path:nth-of-type(11){-webkit-animation:pulse 1s -.83s infinite linear;-moz-animation:pulse 1s -.83s infinite linear;-o-animation:pulse 1s -.83s infinite linear;animation:pulse 1s -.83s infinite linear}.platform-ios .alert-loading .loading-circle path:nth-of-type(12){-webkit-animation:pulse 1s -.913s infinite linear;-moz-animation:pulse 1s -.913s infinite linear;-o-animation:pulse 1s -.913s infinite linear;animation:pulse 1s -.913s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(1){-webkit-animation:pulse-white 1s infinite linear;-moz-animation:pulse-white 1s infinite linear;-o-animation:pulse-white 1s infinite linear;animation:pulse-white 1s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(2){-webkit-animation:pulse-white 1s -83ms infinite linear;-moz-animation:pulse-white 1s -83ms infinite linear;-o-animation:pulse-white 1s -83ms infinite linear;animation:pulse-white 1s -83ms infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(3){-webkit-animation:pulse-white 1s -.166s infinite linear;-moz-animation:pulse-white 1s -.166s infinite linear;-o-animation:pulse-white 1s -.166s infinite linear;animation:pulse-white 1s -.166s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(4){-webkit-animation:pulse-white 1s -.249s infinite linear;-moz-animation:pulse-white 1s -.249s infinite linear;-o-animation:pulse-white 1s -.249s infinite linear;animation:pulse-white 1s -.249s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(5){-webkit-animation:pulse-white 1s -.332s infinite linear;-moz-animation:pulse-white 1s -.332s infinite linear;-o-animation:pulse-white 1s -.332s infinite linear;animation:pulse-white 1s -.332s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(6){-webkit-animation:pulse-white 1s -.415s infinite linear;-moz-animation:pulse-white 1s -.415s infinite linear;-o-animation:pulse-white 1s -.415s infinite linear;animation:pulse-white 1s -.415s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(7){-webkit-animation:pulse-white 1s -.498s infinite linear;-moz-animation:pulse-white 1s -.498s infinite linear;-o-animation:pulse-white 1s -.498s infinite linear;animation:pulse-white 1s -.498s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(8){-webkit-animation:pulse-white 1s -.581s infinite linear;-moz-animation:pulse-white 1s -.581s infinite linear;-o-animation:pulse-white 1s -.581s infinite linear;animation:pulse-white 1s -.581s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(9){-webkit-animation:pulse-white 1s -.664s infinite linear;-moz-animation:pulse-white 1s -.664s infinite linear;-o-animation:pulse-white 1s -.664s infinite linear;animation:pulse-white 1s -.664s infinite linear}.platform-ios .loading-circle.white-loading path:nth-of-type(10){-webkit-animation:pulse-white 1s -.747s infinite linear;-moz-animation:pulse-white 1s -.747s infinite linear;-o-animation:pulse-white 1s -.747s infinite linear;animation:pulse-white 1s -.747s infinite linear}.platform-ios .alert-loading.white-loading .loading-circle path:nth-of-type(11){-webkit-animation:pulse-white 1s -.83s infinite linear;-moz-animation:pulse-white 1s -.83s infinite linear;-o-animation:pulse-white 1s -.83s infinite linear;animation:pulse-white 1s -.83s infinite linear}.platform-ios .alert-loading.white-loading .loading-circle path:nth-of-type(12){-webkit-animation:pulse-white 1s -.913s infinite linear;-moz-animation:pulse-white 1s -.913s infinite linear;-o-animation:pulse-white 1s -.913s infinite linear;animation:pulse-white 1s -.913s infinite linear}@-webkit-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-moz-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-o-keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@keyframes pulse{50%{fill:#868686}to{fill:rgba(134,134,134,.4)}}@-webkit-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-moz-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-o-keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@keyframes pulse-white{50%{fill:rgba(255,255,255,.8)}to{fill:rgba(255,255,255,.2)}}@-webkit-keyframes iosIntro{from{-webkit-transform:scale(0);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes iosIntro{from{-moz-transform:scale(0);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-o-keyframes iosIntro{from{-o-transform:scale(0);opacity:0}to{-o-transform:scale(1);opacity:1}}@keyframes iosIntro{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}.alert-mobileui.alert-loading .alert p{margin:0;margin-top:15px!important;text-align:center}@-webkit-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-moz-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-o-keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@keyframes dash{0%{stroke-dasharray:1,95;stroke-dashoffset:0}50%{stroke-dasharray:85,95;stroke-dashoffset:-25}100%{stroke-dasharray:85,95;stroke-dashoffset:-93}}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotate{0%{-moz-transform:rotate(0)}100%{-moz-transform:rotate(360deg)}}@-o-keyframes rotate{0%{-o-transform:rotate(0)}100%{-o-transform:rotate(360deg)}}@keyframes rotate{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/menu.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/menu.min.css
new file mode 100755
index 0000000..dbfc1cd
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/menu.min.css
@@ -0,0 +1 @@
+.menu{position:fixed;top:0;left:0;width:300px;height:100%;z-index:99999;transform:translateX(-312px);-webkit-transform:translateX(-312px);-moz-transform:translateX(-312px);-o-transform:translateX(-312px);transition-duration:280ms;-webkit-transition-duration:280ms;-moz-transition-duration:280ms;-o-transition-duration:280ms;box-shadow:0 0 10px rgba(0,0,0,.25);overflow:auto}.menu.cover{width:300px}.menu.menu-right{right:0;left:auto;transform:translateX(105%);-webkit-transform:translateX(105%);-moz-transform:translateX(105%);-o-transform:translateX(105%)}.menu.open{transform:translateX(0);-webkit-transform:translateX(0);-moz-transform:translateX(0);-o-transform:translateX(0)}.menu.menu-right.open{margin-left:-312px}.platform-ios .backdrop-menu{opacity:.01}.platform-ios .menu{width:264px;box-shadow:none;transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s;transform:translateX(-264px);-webkit-transform:translateX(-264px);-moz-transform:translateX(-264px);-o-transform:translateX(-264px);box-shadow:none}.platform-ios .menu.cover{width:264px}.platform-ios .menu.menu-right{transform:translateX(105%);-webkit-transform:translateX(105%);-moz-transform:translateX(105%);-o-transform:translateX(105%);transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s}.platform-ios .menu.open{transform:translateX(-264px);-webkit-transform:translateX(-264px);-moz-transform:translateX(-264px);-o-transform:translateX(-264px);margin-left:-1px}.platform-ios .menu.menu-right.open{margin-left:-263px;transform:none;-webkit-transform:none;-moz-transform:none;-o-transform:none;box-shadow:0 0 10px rgba(0,0,0,.25)}.platform-ios .body,.platform-ios body{transition-duration:0s;-webkit-transition-duration:0s;-moz-transition-duration:0s;-o-transition-duration:0s}.platform-ios .body.side-menu,.platform-ios.side-menu{transform:translateX(264px);-webkit-transform:translateX(264px);-moz-transform:translateX(264px);-o-transform:translateX(264px);border-left:1px solid rgba(0,0,0,.15);overflow:hidden}.platform-ios .body.side-menu-right,.platform-ios .header.side-menu-right,.platform-ios.side-menu-right{margin-left:-264px}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileui-colors.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileui-colors.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileui-colors.min.css
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileuijs.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileuijs.min.css
new file mode 100755
index 0000000..d4e2495
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/mobileuijs.min.css
@@ -0,0 +1 @@
+[data]{display:none!important}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/page.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/page.min.css
new file mode 100755
index 0000000..b0e3759
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/page.min.css
@@ -0,0 +1 @@
+.page{position:absolute;top:60px;left:0;display:block;width:100%;height:100%;opacity:.01;contain:strict;background-color:#fff;overflow:auto}.platform-ios .page{top:0;left:100%;opacity:1}.page.show{opacity:1;top:0}.platform-ios .page.show{opacity:1;top:0;left:0}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/popover.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/popover.min.css
new file mode 100755
index 0000000..9b4ffcb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/popover.min.css
@@ -0,0 +1 @@
+.popover{position:absolute;z-index:10001;border-radius:3px;box-shadow:0 3px 12px 2px rgba(0,0,0,.3);overflow:hidden;display:none;background-color:#fff}.platform-ios .popover{border-radius:10px;box-shadow:none}.popover-arrow{z-index:10000;position:absolute;width:14px;height:14px;border-radius:3px;background-color:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.popover.show{display:block}.popover .item,.popover .list{border-width:0}.popover .list .item h1{margin:0}.popover .item{display:table!important;overflow:hidden;white-space:nowrap;padding:10px}.platform-ios .popover .item{border-width:1px}.popover .item:first-child{padding-top:15px}.popover .item:last-child{padding-bottom:15px}.backdrop-popover{opacity:.01}.platform-ios .backdrop-popover{opacity:.08}.popover .item[data]{display:none!important}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circle.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circle.min.css
new file mode 100755
index 0000000..5e0642d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circle.min.css
@@ -0,0 +1 @@
+.progress-circle,.progress-circle-js{margin:auto}.progress-circle-title{opacity:.8}.progress-circle-subtitle{opacity:.6}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circular.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circular.min.css
new file mode 100755
index 0000000..169eb97
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-circular.min.css
@@ -0,0 +1 @@
+.progress-circular{position:relative;font-size:30px;font-weight:300;width:100px;height:100px;border-radius:50%;background-color:rgba(0,0,0,.2);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.progress-circular>span{text-align:center;width:100%;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;z-index:5}.progress-circular::before{content:'';position:absolute;width:100px;height:100px;clip:rect(0,1em,1em,.5em)}.progress-circular::after{position:absolute;content:" ";border-radius:50%;background-color:#f5f5f5;width:94px;height:94px;text-align:center;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.progress-circular.background-blue::after{background-color:#2196f3!important}.progress-circular.background-blue>span{color:rgba(255,255,255,.9)}.progress-circular>span::before{content:'';position:absolute;left:0;top:0;border:2px solid #fff;width:100px;height:100px;clip:rect(0,150px,150px,0);border-radius:50%;-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);text-align:center;white-space:nowrap;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-semicircle.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-semicircle.min.css
new file mode 100755
index 0000000..1fa5a65
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progress-semicircle.min.css
@@ -0,0 +1 @@
+.progress-semicircle,.progress-semicircle-js{margin:auto}.progress-semicircle-title{opacity:.8}.progress-semicircle-subtitle{opacity:.6}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progressbarjs.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progressbarjs.min.css
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/progressbarjs.min.css
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/swiper.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/swiper.min.css
new file mode 100755
index 0000000..1beff1c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/swiper.min.css
@@ -0,0 +1 @@
+.swiper-container{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;z-index:1}.swiper-container-fullscreen{height:100%}.swipper-gallery{height:300px}.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%;z-index:1;height:100%;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{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-slide.vertical-align-center{display:flex;flex-direction:column;justify-content:center;padding:30px;text-align:center}.swiper-slide i{font-size:120px}.swiper-slide h1{font-size:40px;font-weight:600;width:100%}.swiper-slide h2{font-size:30px;font-weight:600;width:100%}.swiper-slide .margin-bottom{margin-bottom:25px}.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-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.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;background:#007aff}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{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-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;-moz-transform-origin:right top;-ms-transform-origin:right top;-o-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.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,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.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,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .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-slide{visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.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-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-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;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.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-zoom-container{width:100%;height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;object-fit:contain}.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)}}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/tab.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/tab.min.css
new file mode 100755
index 0000000..9904384
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/tab.min.css
@@ -0,0 +1 @@
+.tab{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.tab-content{display:none}.tab-content.active{display:block}.tab button{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;font-size:13px!important;text-transform:uppercase;opacity:.6;margin:0}.footer.tab button.icon{margin-top:0}.header.tab.shadow{box-shadow:2px 2px 3px rgba(0,0,0,.2)}.platform-ios .tab button{text-transform:none}.tab button.active{opacity:1}.tab button.icon{font-size:14px;line-height:16px}.tab button::before{display:block;font-size:25px}.tab button.active::after{content:'';position:absolute;bottom:0;left:0;width:100%;height:3px;/*background-color:#fff*/}.tab button .badge{width:20px;height:20px;margin-left:10px;text-align:center;font-size:14px;font-weight:700;border-radius:50%;margin-top:10px;position:absolute;line-height:18px;padding-top:1px}.tab.footer button.active::after{top:0}.header.tab.footer.shadow{box-shadow:-2px -2px 3px rgba(0,0,0,.2)}.platform-ios .tab button.active::after{display:none}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/timeline.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/timeline.min.css
new file mode 100755
index 0000000..0b85d62
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/timeline.min.css
@@ -0,0 +1 @@
+.timeline{font-size:14px;padding:2px}.timeline .marker{position:relative}.timeline .marker::before{background:rgba(0,0,0,.3);content:"";height:100%;width:2px;margin:0 auto;position:absolute;margin-top:10px;z-index:0;left:18px}.timeline .row:last-child .marker::before{display:none}.timeline .icon-circle,.timeline .icon-circle-big,.timeline .icon-circle-small{margin:0 auto;margin-top:10px;position:absolute;margin-left:7px}.timeline .icon-circle i::before,.timeline .icon-circle-big i::before,.timeline .icon-circle-small i::before{margin-top:4px}.timeline .avatar-group{-webkit-transform:translateX(10px);transform:translateX(10px)}.timeline .avatar-photo{background:#eaeaea;width:30px;height:30px;overflow:hidden;text-align:center;border:1px solid #d7d2d2}.timeline .avatar-photo small{margin-top:100px}.timeline .circle-more{background:#eaeaea;width:30px;height:30px;overflow:hidden;text-align:center;border-radius:50%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#bdbbbb;border:1px solid #d7d2d2;font-size:12px}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/toast.min.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/toast.min.css
new file mode 100755
index 0000000..8ee986c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/css/toast.min.css
@@ -0,0 +1 @@
+.toast{z-index:999999;position:absolute;left:0;padding:20px;text-align:center;width:100%;opacity:0;transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-webkit-transition:opacity .25s ease-in-out}.toast.show{opacity:1}.toast.toast-bottom{bottom:10px}.toast.toast-top{top:10px}.toast.toast-center{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;height:100%;top:0}.toast div{padding:10px;display:inline-block}.toast .full{display:block;width:100%}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/alert.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/alert.min.js
new file mode 100755
index 0000000..78b8212
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/alert.min.js
@@ -0,0 +1 @@
+window.alert=function(e,t){var a={};"object"==typeof e?a=e:(a.message=e,a.title=t),a.id||(a.id="ALERT"+(new Date).getTime()),a.buttons&&a.buttons.length||(a.buttons=[{label:"OK",onclick:function(){closeAlert()}}]);var n=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(n=event.target.parentNode);var d=document.createElement("div");d.className="backdrop show backdrop-alert",d.id=a.id+"_BACKDROP",n.appendChild(d);var l=document.createElement("div");l.className="alert-mobileui",l.id=a.id,d.parentNode.appendChild(l);var o=document.createElement("div");if(a.class||(a.class="white"),o.className="alert "+a.class,a.width&&(o.style.maxWidth=a.width),l.appendChild(o),a.title){var r="<h1>"+a.title+"</h1>";o.insertAdjacentHTML("beforeend",r)}if(a.message){var s="<p>"+a.message+"</p>";o.insertAdjacentHTML("beforeend",s)}a.template&&o.insertAdjacentHTML("beforeend",document.getElementById(a.template).innerHTML);var c=document.createElement("div");c.className="buttons",o.appendChild(c);for(var i in a.buttons){var m=document.createElement("button");a.buttons[i].class||(a.buttons[i].class="text-teal"),m.className=a.buttons[i].class;var p=document.createTextNode(a.buttons[i].label);m.appendChild(p),a.buttons[i].onclick||(a.buttons[i].onclick=closeAlert),m.addEventListener("click",a.buttons[i].onclick),c.appendChild(m)}var u=new CustomEvent("alertOpened");document.dispatchEvent(u)},window.closeAlert=function(e){alertId=e,alertId||(alertId=event.target.parentNode.parentNode.parentNode.id);var t=document.getElementById(alertId);t.parentNode.removeChild(t);var a=document.getElementById(alertId+"_BACKDROP");a.parentNode.removeChild(a)};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/base.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/base.min.js
new file mode 100755
index 0000000..d6d093c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/base.min.js
@@ -0,0 +1 @@
+var userAgent=navigator.userAgent||navigator.vendor||window.opera,SO={name:"unknown",code:0};/android/i.test(userAgent)&&(SO.name="Android",SO.class="platform-android",SO.code=1);/iPad|iPhone|iPod/.test(userAgent)&&!window.MSStream&&(SO.name="iOS",SO.class="platform-ios",SO.code=2);/windows phone/i.test(userAgent)&&(SO.name="Windows Phone",SO.class="platform-wp",SO.code=3);SO.class&&document.getElementsByTagName("body").length&&(document.getElementsByTagName("body")[0].className+=" "+SO.class);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/button.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/button.min.js
new file mode 100755
index 0000000..4e7054c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/button.min.js
@@ -0,0 +1 @@
+document.addEventListener("click",function(e){if(1!==SO.code)return!1;var t=e.target;if("button"!==t.tagName.toLowerCase())return!1;var o=t.getBoundingClientRect(),s=t.querySelector(".ripple");s||((s=document.createElement("span")).className="ripple",s.style.height=s.style.width=Math.max(o.width,o.height)+"px",t.appendChild(s)),s.classList.remove("show");var a=e.pageY-o.top-s.offsetHeight/2-document.body.scrollTop,l=e.pageX-o.left-s.offsetWidth/2-document.body.scrollLeft;return s.style.top=a+"px",s.style.left=l+"px",s.classList.add("show"),!1},!1);
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chart-bar.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chart-bar.min.js
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chart-bar.min.js
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist-plugin-tooltip.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist-plugin-tooltip.min.js
new file mode 100755
index 0000000..259aae0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist-plugin-tooltip.min.js
@@ -0,0 +1 @@
+!function(t,e){"function"==typeof define&&define.amd?define(["chartist"],function(o){return t.returnExportsGlobal=e(o)}):"object"==typeof exports?module.exports=e(require("chartist")):t["Chartist.plugins.tooltip"]=e(Chartist)}(this,function(t){return function(t,e,o){"use strict";function n(t){a(t,"tooltip-show")||(t.className=t.className+" tooltip-show")}function i(t){var e=new RegExp("tooltip-show\\s*","gi");t.className=t.className.replace(e,"").trim()}function a(t,e){return(" "+t.getAttribute("class")+" ").indexOf(" "+e+" ")>-1}function r(t,e){do{t=t.nextSibling}while(t&&!a(t,e));return t}var s={currency:void 0,currencyFormatCallback:void 0,tooltipOffset:{x:0,y:-20},anchorToPoint:!1,appendToBody:!1,class:void 0,pointClass:"ct-point"};o.plugins=o.plugins||{},o.plugins.tooltip=function(c){return c=o.extend({},s,c),function(s){function l(t,e,o){f.addEventListener(t,function(t){e&&!a(t.target,e)||o(t)})}function p(e){g=g||d.offsetHeight;var o,n,i=-(m=m||d.offsetWidth)/2+c.tooltipOffset.x,a=-g+c.tooltipOffset.y;if(c.appendToBody)d.style.top=e.pageY+a+"px",d.style.left=e.pageX+i+"px";else{var r=f.getBoundingClientRect(),s=e.pageX-r.left-t.pageXOffset,l=e.pageY-r.top-t.pageYOffset;!0===c.anchorToPoint&&e.target.x2&&e.target.y2&&(o=parseInt(e.target.x2.baseVal.value),n=parseInt(e.target.y2.baseVal.value)),d.style.top=(n||l)+a+"px",d.style.left=(o||s)+i+"px"}}var u=c.pointClass;s.constructor.name==o.Bar.prototype.constructor.name?u="ct-bar":s.constructor.name==o.Pie.prototype.constructor.name&&(u=s.options.donut?"ct-slice-donut":"ct-slice-pie");var f=s.container,d=f.querySelector(".chartist-tooltip");d||(d=e.createElement("div"),d.className=c.class?"chartist-tooltip "+c.class:"chartist-tooltip",c.appendToBody?e.body.appendChild(d):f.appendChild(d));var g=d.offsetHeight,m=d.offsetWidth;i(d),l("mouseover",u,function(t){var i=t.target,a="",l=(s instanceof o.Pie?i:i.parentNode)?i.parentNode.getAttribute("ct:meta")||i.parentNode.getAttribute("ct:series-name"):"",u=i.getAttribute("ct:meta")||l||"",f=!!u,h=i.getAttribute("ct:value");if(c.transformTooltipTextFnc&&"function"==typeof c.transformTooltipTextFnc&&(h=c.transformTooltipTextFnc(h)),c.tooltipFnc&&"function"==typeof c.tooltipFnc)a=c.tooltipFnc(u,h);else{if(c.metaIsHTML){var y=e.createElement("textarea");y.innerHTML=u,u=y.value}if(u='<span class="chartist-tooltip-meta">'+u+"</span>",f)a+=u+"<br>";else if(s instanceof o.Pie){var v=r(i,"ct-label");v&&(a+=function(t){return t.innerText||t.textContent}(v)+"<br>")}h&&(c.currency&&(h=void 0!=c.currencyFormatCallback?c.currencyFormatCallback(h,c):c.currency+h.replace(/(\d)(?=(\d{3})+(?:\.\d+)?$)/g,"$1,")),h='<span class="chartist-tooltip-value">'+h+"</span>",a+=h)}a&&(d.innerHTML=a,p(t),n(d),g=d.offsetHeight,m=d.offsetWidth)}),l("mouseout",u,function(){i(d)}),l("mousemove",null,function(t){!1===c.anchorToPoint&&p(t)})}}}(window,document,t),t.plugins.tooltip});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist.min.js
new file mode 100755
index 0000000..924d43a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartist.min.js
@@ -0,0 +1 @@
+!function(e,t){"function"==typeof define&&define.amd?define("Chartist",[],function(){return e.Chartist=t()}):"object"==typeof module&&module.exports?module.exports=t():e.Chartist=t()}(this,function(){var e={version:"0.11.0"};return function(e,t,i){"use strict";i.namespaces={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns/",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",ct:"http://gionkunz.github.com/chartist-js/ct"},i.noop=function(e){return e},i.alphaNumerate=function(e){return String.fromCharCode(97+e%26)},i.extend=function(e){var t,n,s;for(e=e||{},t=1;t<arguments.length;t++){n=arguments[t];for(var r in n)"object"!=typeof(s=n[r])||null===s||s instanceof Array?e[r]=s:e[r]=i.extend(e[r],s)}return e},i.replaceAll=function(e,t,i){return e.replace(new RegExp(t,"g"),i)},i.ensureUnit=function(e,t){return"number"==typeof e&&(e+=t),e},i.quantity=function(e){if("string"==typeof e){var t=/^(\d+)\s*(.*)$/g.exec(e);return{value:+t[1],unit:t[2]||void 0}}return{value:e}},i.querySelector=function(e){return e instanceof Node?e:t.querySelector(e)},i.times=function(e){return Array.apply(null,new Array(e))},i.sum=function(e,t){return e+(t||0)},i.mapMultiply=function(e){return function(t){return t*e}},i.mapAdd=function(e){return function(t){return t+e}},i.serialMap=function(e,t){var n=[],s=Math.max.apply(null,e.map(function(e){return e.length}));return i.times(s).forEach(function(i,s){var r=e.map(function(e){return e[s]});n[s]=t.apply(null,r)}),n},i.roundWithPrecision=function(e,t){var n=Math.pow(10,t||i.precision);return Math.round(e*n)/n},i.precision=8,i.escapingMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"},i.serialize=function(e){return null===e||void 0===e?e:("number"==typeof e?e=""+e:"object"==typeof e&&(e=JSON.stringify({data:e})),Object.keys(i.escapingMap).reduce(function(e,t){return i.replaceAll(e,t,i.escapingMap[t])},e))},i.deserialize=function(e){if("string"!=typeof e)return e;e=Object.keys(i.escapingMap).reduce(function(e,t){return i.replaceAll(e,i.escapingMap[t],t)},e);try{e=void 0!==(e=JSON.parse(e)).data?e.data:e}catch(e){}return e},i.createSvg=function(e,t,n,s){var r;return t=t||"100%",n=n||"100%",Array.prototype.slice.call(e.querySelectorAll("svg")).filter(function(e){return e.getAttributeNS(i.namespaces.xmlns,"ct")}).forEach(function(t){e.removeChild(t)}),r=new i.Svg("svg").attr({width:t,height:n}).addClass(s),r._node.style.width=t,r._node.style.height=n,e.appendChild(r._node),r},i.normalizeData=function(e,t,n){var s,r={raw:e,normalized:{}};return r.normalized.series=i.getDataArray({series:e.series||[]},t,n),s=r.normalized.series.every(function(e){return e instanceof Array})?Math.max.apply(null,r.normalized.series.map(function(e){return e.length})):r.normalized.series.length,r.normalized.labels=(e.labels||[]).slice(),Array.prototype.push.apply(r.normalized.labels,i.times(Math.max(0,s-r.normalized.labels.length)).map(function(){return""})),t&&i.reverseData(r.normalized),r},i.safeHasProperty=function(e,t){return null!==e&&"object"==typeof e&&e.hasOwnProperty(t)},i.isDataHoleValue=function(e){return null===e||void 0===e||"number"==typeof e&&isNaN(e)},i.reverseData=function(e){e.labels.reverse(),e.series.reverse();for(var t=0;t<e.series.length;t++)"object"==typeof e.series[t]&&void 0!==e.series[t].data?e.series[t].data.reverse():e.series[t]instanceof Array&&e.series[t].reverse()},i.getDataArray=function(e,t,n){function s(e){if(i.safeHasProperty(e,"value"))return s(e.value);if(i.safeHasProperty(e,"data"))return s(e.data);if(e instanceof Array)return e.map(s);if(!i.isDataHoleValue(e)){if(n){var t={};return"string"==typeof n?t[n]=i.getNumberOrUndefined(e):t.y=i.getNumberOrUndefined(e),t.x=e.hasOwnProperty("x")?i.getNumberOrUndefined(e.x):t.x,t.y=e.hasOwnProperty("y")?i.getNumberOrUndefined(e.y):t.y,t}return i.getNumberOrUndefined(e)}}return e.series.map(s)},i.normalizePadding=function(e,t){return t=t||0,"number"==typeof e?{top:e,right:e,bottom:e,left:e}:{top:"number"==typeof e.top?e.top:t,right:"number"==typeof e.right?e.right:t,bottom:"number"==typeof e.bottom?e.bottom:t,left:"number"==typeof e.left?e.left:t}},i.getMetaData=function(e,t){var i=e.data?e.data[t]:e[t];return i?i.meta:void 0},i.orderOfMagnitude=function(e){return Math.floor(Math.log(Math.abs(e))/Math.LN10)},i.projectLength=function(e,t,i){return t/i.range*e},i.getAvailableHeight=function(e,t){return Math.max((i.quantity(t.height).value||e.height())-(t.chartPadding.top+t.chartPadding.bottom)-t.axisX.offset,0)},i.getHighLow=function(e,t,n){function s(e){if(void 0!==e)if(e instanceof Array)for(var t=0;t<e.length;t++)s(e[t]);else{var i=n?+e[n]:+e;a&&i>r.high&&(r.high=i),o&&i<r.low&&(r.low=i)}}var r={high:void 0===(t=i.extend({},t,n?t["axis"+n.toUpperCase()]:{})).high?-Number.MAX_VALUE:+t.high,low:void 0===t.low?Number.MAX_VALUE:+t.low},a=void 0===t.high,o=void 0===t.low;return(a||o)&&s(e),(t.referenceValue||0===t.referenceValue)&&(r.high=Math.max(t.referenceValue,r.high),r.low=Math.min(t.referenceValue,r.low)),r.high<=r.low&&(0===r.low?r.high=1:r.low<0?r.high=0:r.high>0?r.low=0:(r.high=1,r.low=0)),r},i.isNumeric=function(e){return null!==e&&isFinite(e)},i.isFalseyButZero=function(e){return!e&&0!==e},i.getNumberOrUndefined=function(e){return i.isNumeric(e)?+e:void 0},i.isMultiValue=function(e){return"object"==typeof e&&("x"in e||"y"in e)},i.getMultiValue=function(e,t){return i.isMultiValue(e)?i.getNumberOrUndefined(e[t||"y"]):i.getNumberOrUndefined(e)},i.rho=function(e){function t(e,i){return e%i==0?i:t(i,e%i)}function i(e){return e*e+1}if(1===e)return e;var n,s=2,r=2;if(e%2==0)return 2;do{s=i(s)%e,r=i(i(r))%e,n=t(Math.abs(s-r),e)}while(1===n);return n},i.getBounds=function(e,t,n,s){function r(e,t){return e===(e+=t)&&(e*=1+(t>0?p:-p)),e}var a,o,l,u=0,c={high:t.high,low:t.low};c.valueRange=c.high-c.low,c.oom=i.orderOfMagnitude(c.valueRange),c.step=Math.pow(10,c.oom),c.min=Math.floor(c.low/c.step)*c.step,c.max=Math.ceil(c.high/c.step)*c.step,c.range=c.max-c.min,c.numberOfSteps=Math.round(c.range/c.step);var h=i.projectLength(e,c.step,c)<n,d=s?i.rho(c.range):0;if(s&&i.projectLength(e,1,c)>=n)c.step=1;else if(s&&d<c.step&&i.projectLength(e,d,c)>=n)c.step=d;else for(;;){if(h&&i.projectLength(e,c.step,c)<=n)c.step*=2;else{if(h||!(i.projectLength(e,c.step/2,c)>=n))break;if(c.step/=2,s&&c.step%1!=0){c.step*=2;break}}if(u++>1e3)throw new Error("Exceeded maximum number of iterations while optimizing scale step!")}var p=2.221e-16;for(c.step=Math.max(c.step,p),o=c.min,l=c.max;o+c.step<=c.low;)o=r(o,c.step);for(;l-c.step>=c.high;)l=r(l,-c.step);c.min=o,c.max=l,c.range=c.max-c.min;var m=[];for(a=c.min;a<=c.max;a=r(a,c.step)){var f=i.roundWithPrecision(a);f!==m[m.length-1]&&m.push(f)}return c.values=m,c},i.polarToCartesian=function(e,t,i,n){var s=(n-90)*Math.PI/180;return{x:e+i*Math.cos(s),y:t+i*Math.sin(s)}},i.createChartRect=function(e,t,n){var s=!(!t.axisX&&!t.axisY),r=s?t.axisY.offset:0,a=s?t.axisX.offset:0,o=e.width()||i.quantity(t.width).value||0,l=e.height()||i.quantity(t.height).value||0,u=i.normalizePadding(t.chartPadding,n);o=Math.max(o,r+u.left+u.right),l=Math.max(l,a+u.top+u.bottom);var c={padding:u,width:function(){return this.x2-this.x1},height:function(){return this.y1-this.y2}};return s?("start"===t.axisX.position?(c.y2=u.top+a,c.y1=Math.max(l-u.bottom,c.y2+1)):(c.y2=u.top,c.y1=Math.max(l-u.bottom-a,c.y2+1)),"start"===t.axisY.position?(c.x1=u.left+r,c.x2=Math.max(o-u.right,c.x1+1)):(c.x1=u.left,c.x2=Math.max(o-u.right-r,c.x1+1))):(c.x1=u.left,c.x2=Math.max(o-u.right,c.x1+1),c.y2=u.top,c.y1=Math.max(l-u.bottom,c.y2+1)),c},i.createGrid=function(e,t,n,s,r,a,o,l){var u={};u[n.units.pos+"1"]=e,u[n.units.pos+"2"]=e,u[n.counterUnits.pos+"1"]=s,u[n.counterUnits.pos+"2"]=s+r;var c=a.elem("line",u,o.join(" "));l.emit("draw",i.extend({type:"grid",axis:n,index:t,group:a,element:c},u))},i.createGridBackground=function(e,t,i,n){var s=e.elem("rect",{x:t.x1,y:t.y2,width:t.width(),height:t.height()},i,!0);n.emit("draw",{type:"gridBackground",group:e,element:s})},i.createLabel=function(e,n,s,r,a,o,l,u,c,h,d){var p,m={};if(m[a.units.pos]=e+l[a.units.pos],m[a.counterUnits.pos]=l[a.counterUnits.pos],m[a.units.len]=n,m[a.counterUnits.len]=Math.max(0,o-10),h){var f=t.createElement("span");f.className=c.join(" "),f.setAttribute("xmlns",i.namespaces.xhtml),f.innerText=r[s],f.style[a.units.len]=Math.round(m[a.units.len])+"px",f.style[a.counterUnits.len]=Math.round(m[a.counterUnits.len])+"px",p=u.foreignObject(f,i.extend({style:"overflow: visible;"},m))}else p=u.elem("text",m,c.join(" ")).text(r[s]);d.emit("draw",i.extend({type:"label",axis:a,index:s,group:u,element:p,text:r[s]},m))},i.getSeriesOption=function(e,t,i){if(e.name&&t.series&&t.series[e.name]){var n=t.series[e.name];return n.hasOwnProperty(i)?n[i]:t[i]}return t[i]},i.optionsProvider=function(t,n,s){function r(t){var r=a;if(a=i.extend({},l),n)for(o=0;o<n.length;o++){e.matchMedia(n[o][0]).matches&&(a=i.extend(a,n[o][1]))}s&&t&&s.emit("optionsChanged",{previousOptions:r,currentOptions:a})}var a,o,l=i.extend({},t),u=[];if(!e.matchMedia)throw"window.matchMedia not found! Make sure you're using a polyfill.";if(n)for(o=0;o<n.length;o++){var c=e.matchMedia(n[o][0]);c.addListener(r),u.push(c)}return r(),{removeMediaQueryListeners:function(){u.forEach(function(e){e.removeListener(r)})},getCurrentOptions:function(){return i.extend({},a)}}},i.splitIntoSegments=function(e,t,n){n=i.extend({},{increasingX:!1,fillHoles:!1},n);for(var s=[],r=!0,a=0;a<e.length;a+=2)void 0===i.getMultiValue(t[a/2].value)?n.fillHoles||(r=!0):(n.increasingX&&a>=2&&e[a]<=e[a-2]&&(r=!0),r&&(s.push({pathCoordinates:[],valueData:[]}),r=!1),s[s.length-1].pathCoordinates.push(e[a],e[a+1]),s[s.length-1].valueData.push(t[a/2]));return s}}(window,document,e),function(e,t,i){"use strict";i.Interpolation={},i.Interpolation.none=function(e){return e=i.extend({},{fillHoles:!1},e),function(t,n){for(var s=new i.Svg.Path,r=!0,a=0;a<t.length;a+=2){var o=t[a],l=t[a+1],u=n[a/2];void 0!==i.getMultiValue(u.value)?(r?s.move(o,l,!1,u):s.line(o,l,!1,u),r=!1):e.fillHoles||(r=!0)}return s}},i.Interpolation.simple=function(e){e=i.extend({},{divisor:2,fillHoles:!1},e);var t=1/Math.max(1,e.divisor);return function(n,s){for(var r,a,o,l=new i.Svg.Path,u=0;u<n.length;u+=2){var c=n[u],h=n[u+1],d=(c-r)*t,p=s[u/2];void 0!==p.value?(void 0===o?l.move(c,h,!1,p):l.curve(r+d,a,c-d,h,c,h,!1,p),r=c,a=h,o=p):e.fillHoles||(r=c=o=void 0)}return l}},i.Interpolation.cardinal=function(e){e=i.extend({},{tension:1,fillHoles:!1},e);var t=Math.min(1,Math.max(0,e.tension)),n=1-t;return function s(r,a){var o=i.splitIntoSegments(r,a,{fillHoles:e.fillHoles});if(o.length){if(o.length>1){var l=[];return o.forEach(function(e){l.push(s(e.pathCoordinates,e.valueData))}),i.Svg.Path.join(l)}if(r=o[0].pathCoordinates,a=o[0].valueData,r.length<=4)return i.Interpolation.none()(r,a);for(var u=(new i.Svg.Path).move(r[0],r[1],!1,a[0]),c=0,h=r.length;h-2>c;c+=2){var d=[{x:+r[c-2],y:+r[c-1]},{x:+r[c],y:+r[c+1]},{x:+r[c+2],y:+r[c+3]},{x:+r[c+4],y:+r[c+5]}];h-4===c?d[3]=d[2]:c||(d[0]={x:+r[c],y:+r[c+1]}),u.curve(t*(-d[0].x+6*d[1].x+d[2].x)/6+n*d[2].x,t*(-d[0].y+6*d[1].y+d[2].y)/6+n*d[2].y,t*(d[1].x+6*d[2].x-d[3].x)/6+n*d[2].x,t*(d[1].y+6*d[2].y-d[3].y)/6+n*d[2].y,d[2].x,d[2].y,!1,a[(c+2)/2])}return u}return i.Interpolation.none()([])}},i.Interpolation.monotoneCubic=function(e){return e=i.extend({},{fillHoles:!1},e),function t(n,s){var r=i.splitIntoSegments(n,s,{fillHoles:e.fillHoles,increasingX:!0});if(r.length){if(r.length>1){var a=[];return r.forEach(function(e){a.push(t(e.pathCoordinates,e.valueData))}),i.Svg.Path.join(a)}if(n=r[0].pathCoordinates,s=r[0].valueData,n.length<=4)return i.Interpolation.none()(n,s);var o,l,u=[],c=[],h=n.length/2,d=[],p=[],m=[],f=[];for(o=0;o<h;o++)u[o]=n[2*o],c[o]=n[2*o+1];for(o=0;o<h-1;o++)m[o]=c[o+1]-c[o],f[o]=u[o+1]-u[o],p[o]=m[o]/f[o];for(d[0]=p[0],d[h-1]=p[h-2],o=1;o<h-1;o++)0===p[o]||0===p[o-1]||p[o-1]>0!=p[o]>0?d[o]=0:(d[o]=3*(f[o-1]+f[o])/((2*f[o]+f[o-1])/p[o-1]+(f[o]+2*f[o-1])/p[o]),isFinite(d[o])||(d[o]=0));for(l=(new i.Svg.Path).move(u[0],c[0],!1,s[0]),o=0;o<h-1;o++)l.curve(u[o]+f[o]/3,c[o]+d[o]*f[o]/3,u[o+1]-f[o]/3,c[o+1]-d[o+1]*f[o]/3,u[o+1],c[o+1],!1,s[o+1]);return l}return i.Interpolation.none()([])}},i.Interpolation.step=function(e){return e=i.extend({},{postpone:!0,fillHoles:!1},e),function(t,n){for(var s,r,a,o=new i.Svg.Path,l=0;l<t.length;l+=2){var u=t[l],c=t[l+1],h=n[l/2];void 0!==h.value?(void 0===a?o.move(u,c,!1,h):(e.postpone?o.line(u,r,!1,a):o.line(s,c,!1,h),o.line(u,c,!1,h)),s=u,r=c,a=h):e.fillHoles||(s=r=a=void 0)}return o}}}(window,document,e),function(e,t,i){"use strict";i.EventEmitter=function(){var e=[];return{addEventHandler:function(t,i){e[t]=e[t]||[],e[t].push(i)},removeEventHandler:function(t,i){e[t]&&(i?(e[t].splice(e[t].indexOf(i),1),0===e[t].length&&delete e[t]):delete e[t])},emit:function(t,i){e[t]&&e[t].forEach(function(e){e(i)}),e["*"]&&e["*"].forEach(function(e){e(t,i)})}}}}(window,document,e),function(e,t,i){"use strict";i.Class={extend:function(e,t){var n=t||this.prototype||i.Class,s=Object.create(n);i.Class.cloneDefinitions(s,e);var r=function(){var e,t=s.constructor||function(){};return e=this===i?Object.create(s):this,t.apply(e,Array.prototype.slice.call(arguments,0)),e};return r.prototype=s,r.super=n,r.extend=this.extend,r},cloneDefinitions:function(){var e=function(e){var t=[];if(e.length)for(var i=0;i<e.length;i++)t.push(e[i]);return t}(arguments),t=e[0];return e.splice(1,e.length-1).forEach(function(e){Object.getOwnPropertyNames(e).forEach(function(i){delete t[i],Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))})}),t}}}(window,document,e),function(e,t,i){"use strict";function n(){e.addEventListener("resize",this.resizeListener),this.optionsProvider=i.optionsProvider(this.options,this.responsiveOptions,this.eventEmitter),this.eventEmitter.addEventHandler("optionsChanged",function(){this.update()}.bind(this)),this.options.plugins&&this.options.plugins.forEach(function(e){e instanceof Array?e[0](this,e[1]):e(this)}.bind(this)),this.eventEmitter.emit("data",{type:"initial",data:this.data}),this.createChart(this.optionsProvider.getCurrentOptions()),this.initializeTimeoutId=void 0}i.Base=i.Class.extend({constructor:function(e,t,s,r,a){this.container=i.querySelector(e),this.data=t||{},this.data.labels=this.data.labels||[],this.data.series=this.data.series||[],this.defaultOptions=s,this.options=r,this.responsiveOptions=a,this.eventEmitter=i.EventEmitter(),this.supportsForeignObject=i.Svg.isSupported("Extensibility"),this.supportsAnimations=i.Svg.isSupported("AnimationEventsAttribute"),this.resizeListener=function(){this.update()}.bind(this),this.container&&(this.container.__chartist__&&this.container.__chartist__.detach(),this.container.__chartist__=this),this.initializeTimeoutId=setTimeout(n.bind(this),0)},optionsProvider:void 0,container:void 0,svg:void 0,eventEmitter:void 0,createChart:function(){throw new Error("Base chart type can't be instantiated!")},update:function(e,t,n){return e&&(this.data=e||{},this.data.labels=this.data.labels||[],this.data.series=this.data.series||[],this.eventEmitter.emit("data",{type:"update",data:this.data})),t&&(this.options=i.extend({},n?this.options:this.defaultOptions,t),this.initializeTimeoutId||(this.optionsProvider.removeMediaQueryListeners(),this.optionsProvider=i.optionsProvider(this.options,this.responsiveOptions,this.eventEmitter))),this.initializeTimeoutId||this.createChart(this.optionsProvider.getCurrentOptions()),this},detach:function(){return this.initializeTimeoutId?e.clearTimeout(this.initializeTimeoutId):(e.removeEventListener("resize",this.resizeListener),this.optionsProvider.removeMediaQueryListeners()),this},on:function(e,t){return this.eventEmitter.addEventHandler(e,t),this},off:function(e,t){return this.eventEmitter.removeEventHandler(e,t),this},version:i.version,supportsForeignObject:!1})}(window,document,e),function(e,t,i){"use strict";i.Svg=i.Class.extend({constructor:function(e,n,s,r,a){e instanceof Element?this._node=e:(this._node=t.createElementNS(i.namespaces.svg,e),"svg"===e&&this.attr({"xmlns:ct":i.namespaces.ct})),n&&this.attr(n),s&&this.addClass(s),r&&(a&&r._node.firstChild?r._node.insertBefore(this._node,r._node.firstChild):r._node.appendChild(this._node))},attr:function(e,t){return"string"==typeof e?t?this._node.getAttributeNS(t,e):this._node.getAttribute(e):(Object.keys(e).forEach(function(t){if(void 0!==e[t])if(-1!==t.indexOf(":")){var n=t.split(":");this._node.setAttributeNS(i.namespaces[n[0]],t,e[t])}else this._node.setAttribute(t,e[t])}.bind(this)),this)},elem:function(e,t,n,s){return new i.Svg(e,t,n,this,s)},parent:function(){return this._node.parentNode instanceof SVGElement?new i.Svg(this._node.parentNode):null},root:function(){for(var e=this._node;"svg"!==e.nodeName;)e=e.parentNode;return new i.Svg(e)},querySelector:function(e){var t=this._node.querySelector(e);return t?new i.Svg(t):null},querySelectorAll:function(e){var t=this._node.querySelectorAll(e);return t.length?new i.Svg.List(t):null},getNode:function(){return this._node},foreignObject:function(e,n,s,r){if("string"==typeof e){var a=t.createElement("div");a.innerHTML=e,e=a.firstChild}e.setAttribute("xmlns",i.namespaces.xmlns);var o=this.elem("foreignObject",n,s,r);return o._node.appendChild(e),o},text:function(e){return this._node.appendChild(t.createTextNode(e)),this},empty:function(){for(;this._node.firstChild;)this._node.removeChild(this._node.firstChild);return this},remove:function(){return this._node.parentNode.removeChild(this._node),this.parent()},replace:function(e){return this._node.parentNode.replaceChild(e._node,this._node),e},append:function(e,t){return t&&this._node.firstChild?this._node.insertBefore(e._node,this._node.firstChild):this._node.appendChild(e._node),this},classes:function(){return this._node.getAttribute("class")?this._node.getAttribute("class").trim().split(/\s+/):[]},addClass:function(e){return this._node.setAttribute("class",this.classes(this._node).concat(e.trim().split(/\s+/)).filter(function(e,t,i){return i.indexOf(e)===t}).join(" ")),this},removeClass:function(e){var t=e.trim().split(/\s+/);return this._node.setAttribute("class",this.classes(this._node).filter(function(e){return-1===t.indexOf(e)}).join(" ")),this},removeAllClasses:function(){return this._node.setAttribute("class",""),this},height:function(){return this._node.getBoundingClientRect().height},width:function(){return this._node.getBoundingClientRect().width},animate:function(e,t,n){return void 0===t&&(t=!0),Object.keys(e).forEach(function(s){function r(e,t){var r,a,o,l={};e.easing&&(o=e.easing instanceof Array?e.easing:i.Svg.Easing[e.easing],delete e.easing),e.begin=i.ensureUnit(e.begin,"ms"),e.dur=i.ensureUnit(e.dur,"ms"),o&&(e.calcMode="spline",e.keySplines=o.join(" "),e.keyTimes="0;1"),t&&(e.fill="freeze",l[s]=e.from,this.attr(l),a=i.quantity(e.begin||0).value,e.begin="indefinite"),r=this.elem("animate",i.extend({attributeName:s},e)),t&&setTimeout(function(){try{r._node.beginElement()}catch(t){l[s]=e.to,this.attr(l),r.remove()}}.bind(this),a),n&&r._node.addEventListener("beginEvent",function(){n.emit("animationBegin",{element:this,animate:r._node,params:e})}.bind(this)),r._node.addEventListener("endEvent",function(){n&&n.emit("animationEnd",{element:this,animate:r._node,params:e}),t&&(l[s]=e.to,this.attr(l),r.remove())}.bind(this))}e[s]instanceof Array?e[s].forEach(function(e){r.bind(this)(e,!1)}.bind(this)):r.bind(this)(e[s],t)}.bind(this)),this}}),i.Svg.isSupported=function(e){return t.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#"+e,"1.1")};i.Svg.Easing={easeInSine:[.47,0,.745,.715],easeOutSine:[.39,.575,.565,1],easeInOutSine:[.445,.05,.55,.95],easeInQuad:[.55,.085,.68,.53],easeOutQuad:[.25,.46,.45,.94],easeInOutQuad:[.455,.03,.515,.955],easeInCubic:[.55,.055,.675,.19],easeOutCubic:[.215,.61,.355,1],easeInOutCubic:[.645,.045,.355,1],easeInQuart:[.895,.03,.685,.22],easeOutQuart:[.165,.84,.44,1],easeInOutQuart:[.77,0,.175,1],easeInQuint:[.755,.05,.855,.06],easeOutQuint:[.23,1,.32,1],easeInOutQuint:[.86,0,.07,1],easeInExpo:[.95,.05,.795,.035],easeOutExpo:[.19,1,.22,1],easeInOutExpo:[1,0,0,1],easeInCirc:[.6,.04,.98,.335],easeOutCirc:[.075,.82,.165,1],easeInOutCirc:[.785,.135,.15,.86],easeInBack:[.6,-.28,.735,.045],easeOutBack:[.175,.885,.32,1.275],easeInOutBack:[.68,-.55,.265,1.55]},i.Svg.List=i.Class.extend({constructor:function(e){var t=this;this.svgElements=[];for(var n=0;n<e.length;n++)this.svgElements.push(new i.Svg(e[n]));Object.keys(i.Svg.prototype).filter(function(e){return-1===["constructor","parent","querySelector","querySelectorAll","replace","append","classes","height","width"].indexOf(e)}).forEach(function(e){t[e]=function(){var n=Array.prototype.slice.call(arguments,0);return t.svgElements.forEach(function(t){i.Svg.prototype[e].apply(t,n)}),t}})}})}(window,document,e),function(e,t,i){"use strict";function n(e,t,n,s,r,a){var o=i.extend({command:r?e.toLowerCase():e.toUpperCase()},t,a?{data:a}:{});n.splice(s,0,o)}function s(e,t){e.forEach(function(i,n){r[i.command.toLowerCase()].forEach(function(s,r){t(i,s,n,r,e)})})}var r={m:["x","y"],l:["x","y"],c:["x1","y1","x2","y2","x","y"],a:["rx","ry","xAr","lAf","sf","x","y"]},a={accuracy:3};i.Svg.Path=i.Class.extend({constructor:function(e,t){this.pathElements=[],this.pos=0,this.close=e,this.options=i.extend({},a,t)},position:function(e){return void 0!==e?(this.pos=Math.max(0,Math.min(this.pathElements.length,e)),this):this.pos},remove:function(e){return this.pathElements.splice(this.pos,e),this},move:function(e,t,i,s){return n("M",{x:+e,y:+t},this.pathElements,this.pos++,i,s),this},line:function(e,t,i,s){return n("L",{x:+e,y:+t},this.pathElements,this.pos++,i,s),this},curve:function(e,t,i,s,r,a,o,l){return n("C",{x1:+e,y1:+t,x2:+i,y2:+s,x:+r,y:+a},this.pathElements,this.pos++,o,l),this},arc:function(e,t,i,s,r,a,o,l,u){return n("A",{rx:+e,ry:+t,xAr:+i,lAf:+s,sf:+r,x:+a,y:+o},this.pathElements,this.pos++,l,u),this},scale:function(e,t){return s(this.pathElements,function(i,n){i[n]*="x"===n[0]?e:t}),this},translate:function(e,t){return s(this.pathElements,function(i,n){i[n]+="x"===n[0]?e:t}),this},transform:function(e){return s(this.pathElements,function(t,i,n,s,r){var a=e(t,i,n,s,r);(a||0===a)&&(t[i]=a)}),this},parse:function(e){var t=e.replace(/([A-Za-z])([0-9])/g,"$1 $2").replace(/([0-9])([A-Za-z])/g,"$1 $2").split(/[\s,]+/).reduce(function(e,t){return t.match(/[A-Za-z]/)&&e.push([]),e[e.length-1].push(t),e},[]);"Z"===t[t.length-1][0].toUpperCase()&&t.pop();var n=t.map(function(e){var t=e.shift(),n=r[t.toLowerCase()];return i.extend({command:t},n.reduce(function(t,i,n){return t[i]=+e[n],t},{}))}),s=[this.pos,0];return Array.prototype.push.apply(s,n),Array.prototype.splice.apply(this.pathElements,s),this.pos+=n.length,this},stringify:function(){var e=Math.pow(10,this.options.accuracy);return this.pathElements.reduce(function(t,i){var n=r[i.command.toLowerCase()].map(function(t){return this.options.accuracy?Math.round(i[t]*e)/e:i[t]}.bind(this));return t+i.command+n.join(",")}.bind(this),"")+(this.close?"Z":"")},clone:function(e){var t=new i.Svg.Path(e||this.close);return t.pos=this.pos,t.pathElements=this.pathElements.slice().map(function(e){return i.extend({},e)}),t.options=i.extend({},this.options),t},splitByCommand:function(e){var t=[new i.Svg.Path];return this.pathElements.forEach(function(n){n.command===e.toUpperCase()&&0!==t[t.length-1].pathElements.length&&t.push(new i.Svg.Path),t[t.length-1].pathElements.push(n)}),t}}),i.Svg.Path.elementDescriptions=r,i.Svg.Path.join=function(e,t,n){for(var s=new i.Svg.Path(t,n),r=0;r<e.length;r++)for(var a=e[r],o=0;o<a.pathElements.length;o++)s.pathElements.push(a.pathElements[o]);return s}}(window,document,e),function(e,t,i){"use strict";var n={x:{pos:"x",len:"width",dir:"horizontal",rectStart:"x1",rectEnd:"x2",rectOffset:"y2"},y:{pos:"y",len:"height",dir:"vertical",rectStart:"y2",rectEnd:"y1",rectOffset:"x1"}};i.Axis=i.Class.extend({constructor:function(e,t,i,s){this.units=e,this.counterUnits=e===n.x?n.y:n.x,this.chartRect=t,this.axisLength=t[e.rectEnd]-t[e.rectStart],this.gridOffset=t[e.rectOffset],this.ticks=i,this.options=s},createGridAndLabels:function(e,t,n,s,r){var a=s["axis"+this.units.pos.toUpperCase()],o=this.ticks.map(this.projectValue.bind(this)),l=this.ticks.map(a.labelInterpolationFnc);o.forEach(function(u,c){var h,d={x:0,y:0};h=o[c+1]?o[c+1]-u:Math.max(this.axisLength-u,30),i.isFalseyButZero(l[c])&&""!==l[c]||("x"===this.units.pos?(u=this.chartRect.x1+u,d.x=s.axisX.labelOffset.x,"start"===s.axisX.position?d.y=this.chartRect.padding.top+s.axisX.labelOffset.y+(n?5:20):d.y=this.chartRect.y1+s.axisX.labelOffset.y+(n?5:20)):(u=this.chartRect.y1-u,d.y=s.axisY.labelOffset.y-(n?h:0),"start"===s.axisY.position?d.x=n?this.chartRect.padding.left+s.axisY.labelOffset.x:this.chartRect.x1-10:d.x=this.chartRect.x2+s.axisY.labelOffset.x+10),a.showGrid&&i.createGrid(u,c,this,this.gridOffset,this.chartRect[this.counterUnits.len](),e,[s.classNames.grid,s.classNames[this.units.dir]],r),a.showLabel&&i.createLabel(u,h,c,l,this,a.offset,d,t,[s.classNames.label,s.classNames[this.units.dir],"start"===a.position?s.classNames[a.position]:s.classNames.end],n,r))}.bind(this))},projectValue:function(e,t,i){throw new Error("Base axis can't be instantiated!")}}),i.Axis.units=n}(window,document,e),function(e,t,i){"use strict";i.AutoScaleAxis=i.Axis.extend({constructor:function(e,t,n,s){var r=s.highLow||i.getHighLow(t,s,e.pos);this.bounds=i.getBounds(n[e.rectEnd]-n[e.rectStart],r,s.scaleMinSpace||20,s.onlyInteger),this.range={min:this.bounds.min,max:this.bounds.max},i.AutoScaleAxis.super.constructor.call(this,e,n,this.bounds.values,s)},projectValue:function(e){return this.axisLength*(+i.getMultiValue(e,this.units.pos)-this.bounds.min)/this.bounds.range}})}(window,document,e),function(e,t,i){"use strict";i.FixedScaleAxis=i.Axis.extend({constructor:function(e,t,n,s){var r=s.highLow||i.getHighLow(t,s,e.pos);this.divisor=s.divisor||1,this.ticks=s.ticks||i.times(this.divisor).map(function(e,t){return r.low+(r.high-r.low)/this.divisor*t}.bind(this)),this.ticks.sort(function(e,t){return e-t}),this.range={min:r.low,max:r.high},i.FixedScaleAxis.super.constructor.call(this,e,n,this.ticks,s),this.stepLength=this.axisLength/this.divisor},projectValue:function(e){return this.axisLength*(+i.getMultiValue(e,this.units.pos)-this.range.min)/(this.range.max-this.range.min)}})}(window,document,e),function(e,t,i){"use strict";i.StepAxis=i.Axis.extend({constructor:function(e,t,n,s){i.StepAxis.super.constructor.call(this,e,n,s.ticks,s);var r=Math.max(1,s.ticks.length-(s.stretch?1:0));this.stepLength=this.axisLength/r},projectValue:function(e,t){return this.stepLength*t}})}(window,document,e),function(e,t,i){"use strict";var n={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,type:void 0},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,type:void 0,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,showLine:!0,showPoint:!0,showArea:!1,areaBase:0,lineSmooth:!0,showGridBackground:!1,low:void 0,high:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},fullWidth:!1,reverseData:!1,classNames:{chart:"ct-chart-line",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",line:"ct-line",point:"ct-point",area:"ct-area",grid:"ct-grid",gridGroup:"ct-grids",gridBackground:"ct-grid-background",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};i.Line=i.Base.extend({constructor:function(e,t,s,r){i.Line.super.constructor.call(this,e,t,n,i.extend({},n,s),r)},createChart:function(e){var t=i.normalizeData(this.data,e.reverseData,!0);this.svg=i.createSvg(this.container,e.width,e.height,e.classNames.chart);var s,r,a=this.svg.elem("g").addClass(e.classNames.gridGroup),o=this.svg.elem("g"),l=this.svg.elem("g").addClass(e.classNames.labelGroup),u=i.createChartRect(this.svg,e,n.padding);s=void 0===e.axisX.type?new i.StepAxis(i.Axis.units.x,t.normalized.series,u,i.extend({},e.axisX,{ticks:t.normalized.labels,stretch:e.fullWidth})):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,u,e.axisX),r=void 0===e.axisY.type?new i.AutoScaleAxis(i.Axis.units.y,t.normalized.series,u,i.extend({},e.axisY,{high:i.isNumeric(e.high)?e.high:e.axisY.high,low:i.isNumeric(e.low)?e.low:e.axisY.low})):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,u,e.axisY),s.createGridAndLabels(a,l,this.supportsForeignObject,e,this.eventEmitter),r.createGridAndLabels(a,l,this.supportsForeignObject,e,this.eventEmitter),e.showGridBackground&&i.createGridBackground(a,u,e.classNames.gridBackground,this.eventEmitter),t.raw.series.forEach(function(n,a){var l=o.elem("g");l.attr({"ct:series-name":n.name,"ct:meta":i.serialize(n.meta)}),l.addClass([e.classNames.series,n.className||e.classNames.series+"-"+i.alphaNumerate(a)].join(" "));var c=[],h=[];t.normalized.series[a].forEach(function(e,o){var l={x:u.x1+s.projectValue(e,o,t.normalized.series[a]),y:u.y1-r.projectValue(e,o,t.normalized.series[a])};c.push(l.x,l.y),h.push({value:e,valueIndex:o,meta:i.getMetaData(n,o)})}.bind(this));var d={lineSmooth:i.getSeriesOption(n,e,"lineSmooth"),showPoint:i.getSeriesOption(n,e,"showPoint"),showLine:i.getSeriesOption(n,e,"showLine"),showArea:i.getSeriesOption(n,e,"showArea"),areaBase:i.getSeriesOption(n,e,"areaBase")},p=("function"==typeof d.lineSmooth?d.lineSmooth:d.lineSmooth?i.Interpolation.monotoneCubic():i.Interpolation.none())(c,h);if(d.showPoint&&p.pathElements.forEach(function(t){var o=l.elem("line",{x1:t.x,y1:t.y,x2:t.x+.01,y2:t.y},e.classNames.point).attr({"ct:value":[t.data.value.x,t.data.value.y].filter(i.isNumeric).join(","),"ct:meta":i.serialize(t.data.meta)});this.eventEmitter.emit("draw",{type:"point",value:t.data.value,index:t.data.valueIndex,meta:t.data.meta,series:n,seriesIndex:a,axisX:s,axisY:r,group:l,element:o,x:t.x,y:t.y})}.bind(this)),d.showLine){var m=l.elem("path",{d:p.stringify()},e.classNames.line,!0);this.eventEmitter.emit("draw",{type:"line",values:t.normalized.series[a],path:p.clone(),chartRect:u,index:a,series:n,seriesIndex:a,seriesMeta:n.meta,axisX:s,axisY:r,group:l,element:m})}if(d.showArea&&r.range){var f=Math.max(Math.min(d.areaBase,r.range.max),r.range.min),g=u.y1-r.projectValue(f);p.splitByCommand("M").filter(function(e){return e.pathElements.length>1}).map(function(e){var t=e.pathElements[0],i=e.pathElements[e.pathElements.length-1];return e.clone(!0).position(0).remove(1).move(t.x,g).line(t.x,t.y).position(e.pathElements.length+1).line(i.x,g)}).forEach(function(i){var o=l.elem("path",{d:i.stringify()},e.classNames.area,!0);this.eventEmitter.emit("draw",{type:"area",values:t.normalized.series[a],path:i.clone(),series:n,seriesIndex:a,axisX:s,axisY:r,chartRect:u,index:a,group:l,element:o})}.bind(this))}}.bind(this)),this.eventEmitter.emit("created",{bounds:r.bounds,chartRect:u,axisX:s,axisY:r,svg:this.svg,options:e})}})}(window,document,e),function(e,t,i){"use strict";var n={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,scaleMinSpace:30,onlyInteger:!1},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:i.noop,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,high:void 0,low:void 0,referenceValue:0,chartPadding:{top:15,right:15,bottom:5,left:10},seriesBarDistance:15,stackBars:!1,stackMode:"accumulate",horizontalBars:!1,distributeSeries:!1,reverseData:!1,showGridBackground:!1,classNames:{chart:"ct-chart-bar",horizontalBars:"ct-horizontal-bars",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",bar:"ct-bar",grid:"ct-grid",gridGroup:"ct-grids",gridBackground:"ct-grid-background",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};i.Bar=i.Base.extend({constructor:function(e,t,s,r){i.Bar.super.constructor.call(this,e,t,n,i.extend({},n,s),r)},createChart:function(e){var t,s;e.distributeSeries?(t=i.normalizeData(this.data,e.reverseData,e.horizontalBars?"x":"y"),t.normalized.series=t.normalized.series.map(function(e){return[e]})):t=i.normalizeData(this.data,e.reverseData,e.horizontalBars?"x":"y"),this.svg=i.createSvg(this.container,e.width,e.height,e.classNames.chart+(e.horizontalBars?" "+e.classNames.horizontalBars:""));var r=this.svg.elem("g").addClass(e.classNames.gridGroup),a=this.svg.elem("g"),o=this.svg.elem("g").addClass(e.classNames.labelGroup);if(e.stackBars&&0!==t.normalized.series.length){var l=i.serialMap(t.normalized.series,function(){return Array.prototype.slice.call(arguments).map(function(e){return e}).reduce(function(e,t){return{x:e.x+(t&&t.x)||0,y:e.y+(t&&t.y)||0}},{x:0,y:0})});s=i.getHighLow([l],e,e.horizontalBars?"x":"y")}else s=i.getHighLow(t.normalized.series,e,e.horizontalBars?"x":"y");s.high=+e.high||(0===e.high?0:s.high),s.low=+e.low||(0===e.low?0:s.low);var u,c,h,d,p,m=i.createChartRect(this.svg,e,n.padding);c=e.distributeSeries&&e.stackBars?t.normalized.labels.slice(0,1):t.normalized.labels,e.horizontalBars?(u=d=void 0===e.axisX.type?new i.AutoScaleAxis(i.Axis.units.x,t.normalized.series,m,i.extend({},e.axisX,{highLow:s,referenceValue:0})):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,m,i.extend({},e.axisX,{highLow:s,referenceValue:0})),h=p=void 0===e.axisY.type?new i.StepAxis(i.Axis.units.y,t.normalized.series,m,{ticks:c}):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,m,e.axisY)):(h=d=void 0===e.axisX.type?new i.StepAxis(i.Axis.units.x,t.normalized.series,m,{ticks:c}):e.axisX.type.call(i,i.Axis.units.x,t.normalized.series,m,e.axisX),u=p=void 0===e.axisY.type?new i.AutoScaleAxis(i.Axis.units.y,t.normalized.series,m,i.extend({},e.axisY,{highLow:s,referenceValue:0})):e.axisY.type.call(i,i.Axis.units.y,t.normalized.series,m,i.extend({},e.axisY,{highLow:s,referenceValue:0})));var f=e.horizontalBars?m.x1+u.projectValue(0):m.y1-u.projectValue(0),g=[];h.createGridAndLabels(r,o,this.supportsForeignObject,e,this.eventEmitter),u.createGridAndLabels(r,o,this.supportsForeignObject,e,this.eventEmitter),e.showGridBackground&&i.createGridBackground(r,m,e.classNames.gridBackground,this.eventEmitter),t.raw.series.forEach(function(n,s){var r,o,l=s-(t.raw.series.length-1)/2;r=e.distributeSeries&&!e.stackBars?h.axisLength/t.normalized.series.length/2:e.distributeSeries&&e.stackBars?h.axisLength/2:h.axisLength/t.normalized.series[s].length/2,(o=a.elem("g")).attr({"ct:series-name":n.name,"ct:meta":i.serialize(n.meta)}),o.addClass([e.classNames.series,n.className||e.classNames.series+"-"+i.alphaNumerate(s)].join(" ")),t.normalized.series[s].forEach(function(a,c){var v,x,y,b;if(b=e.distributeSeries&&!e.stackBars?s:e.distributeSeries&&e.stackBars?0:c,v=e.horizontalBars?{x:m.x1+u.projectValue(a&&a.x?a.x:0,c,t.normalized.series[s]),y:m.y1-h.projectValue(a&&a.y?a.y:0,b,t.normalized.series[s])}:{x:m.x1+h.projectValue(a&&a.x?a.x:0,b,t.normalized.series[s]),y:m.y1-u.projectValue(a&&a.y?a.y:0,c,t.normalized.series[s])},h instanceof i.StepAxis&&(h.options.stretch||(v[h.units.pos]+=r*(e.horizontalBars?-1:1)),v[h.units.pos]+=e.stackBars||e.distributeSeries?0:l*e.seriesBarDistance*(e.horizontalBars?-1:1)),y=g[c]||f,g[c]=y-(f-v[h.counterUnits.pos]),void 0!==a){var w={};w[h.units.pos+"1"]=v[h.units.pos],w[h.units.pos+"2"]=v[h.units.pos],!e.stackBars||"accumulate"!==e.stackMode&&e.stackMode?(w[h.counterUnits.pos+"1"]=f,w[h.counterUnits.pos+"2"]=v[h.counterUnits.pos]):(w[h.counterUnits.pos+"1"]=y,w[h.counterUnits.pos+"2"]=g[c]),w.x1=Math.min(Math.max(w.x1,m.x1),m.x2),w.x2=Math.min(Math.max(w.x2,m.x1),m.x2),w.y1=Math.min(Math.max(w.y1,m.y2),m.y1),w.y2=Math.min(Math.max(w.y2,m.y2),m.y1);var E=i.getMetaData(n,c);x=o.elem("line",w,e.classNames.bar).attr({"ct:value":[a.x,a.y].filter(i.isNumeric).join(","),"ct:meta":i.serialize(E)}),this.eventEmitter.emit("draw",i.extend({type:"bar",value:a,index:c,meta:E,series:n,seriesIndex:s,axisX:d,axisY:p,chartRect:m,group:o,element:x},w))}}.bind(this))}.bind(this)),this.eventEmitter.emit("created",{bounds:u.bounds,chartRect:m,axisX:d,axisY:p,svg:this.svg,options:e})}})}(window,document,e),function(e,t,i){"use strict";function n(e,t,i){var n=t.x>e.x;return n&&"explode"===i||!n&&"implode"===i?"start":n&&"implode"===i||!n&&"explode"===i?"end":"middle"}var s={width:void 0,height:void 0,chartPadding:5,classNames:{chartPie:"ct-chart-pie",chartDonut:"ct-chart-donut",series:"ct-series",slicePie:"ct-slice-pie",sliceDonut:"ct-slice-donut",sliceDonutSolid:"ct-slice-donut-solid",label:"ct-label"},startAngle:0,total:void 0,donut:!1,donutSolid:!1,donutWidth:60,showLabel:!0,labelOffset:0,labelPosition:"inside",labelInterpolationFnc:i.noop,labelDirection:"neutral",reverseData:!1,ignoreEmptyValues:!1};i.Pie=i.Base.extend({constructor:function(e,t,n,r){i.Pie.super.constructor.call(this,e,t,s,i.extend({},s,n),r)},createChart:function(e){var t,r,a,o,l,u=i.normalizeData(this.data),c=[],h=e.startAngle;this.svg=i.createSvg(this.container,e.width,e.height,e.donut?e.classNames.chartDonut:e.classNames.chartPie),r=i.createChartRect(this.svg,e,s.padding),a=Math.min(r.width()/2,r.height()/2),l=e.total||u.normalized.series.reduce(function(e,t){return e+t},0);var d=i.quantity(e.donutWidth);"%"===d.unit&&(d.value*=a/100),a-=e.donut&&!e.donutSolid?d.value/2:0,o="outside"===e.labelPosition||e.donut&&!e.donutSolid?a:"center"===e.labelPosition?0:e.donutSolid?a-d.value/2:a/2,o+=e.labelOffset;var p={x:r.x1+r.width()/2,y:r.y2+r.height()/2},m=1===u.raw.series.filter(function(e){return e.hasOwnProperty("value")?0!==e.value:0!==e}).length;u.raw.series.forEach(function(e,t){c[t]=this.svg.elem("g",null,null)}.bind(this)),e.showLabel&&(t=this.svg.elem("g",null,null)),u.raw.series.forEach(function(s,r){if(0!==u.normalized.series[r]||!e.ignoreEmptyValues){c[r].attr({"ct:series-name":s.name}),c[r].addClass([e.classNames.series,s.className||e.classNames.series+"-"+i.alphaNumerate(r)].join(" "));var f=l>0?h+u.normalized.series[r]/l*360:0,g=Math.max(0,h-(0===r||m?0:.2));f-g>=359.99&&(f=g+359.99);var v,x,y,b=i.polarToCartesian(p.x,p.y,a,g),w=i.polarToCartesian(p.x,p.y,a,f),E=new i.Svg.Path(!e.donut||e.donutSolid).move(w.x,w.y).arc(a,a,0,f-h>180,0,b.x,b.y);e.donut?e.donutSolid&&(y=a-d.value,v=i.polarToCartesian(p.x,p.y,y,h-(0===r||m?0:.2)),x=i.polarToCartesian(p.x,p.y,y,f),E.line(v.x,v.y),E.arc(y,y,0,f-h>180,1,x.x,x.y)):E.line(p.x,p.y);var S=e.classNames.slicePie;e.donut&&(S=e.classNames.sliceDonut,e.donutSolid&&(S=e.classNames.sliceDonutSolid));var A=c[r].elem("path",{d:E.stringify()},S);if(A.attr({"ct:value":u.normalized.series[r],"ct:meta":i.serialize(s.meta)}),e.donut&&!e.donutSolid&&(A._node.style.strokeWidth=d.value+"px"),this.eventEmitter.emit("draw",{type:"slice",value:u.normalized.series[r],totalDataSum:l,index:r,meta:s.meta,series:s,group:c[r],element:A,path:E.clone(),center:p,radius:a,startAngle:h,endAngle:f}),e.showLabel){var z;z=1===u.raw.series.length?{x:p.x,y:p.y}:i.polarToCartesian(p.x,p.y,o,h+(f-h)/2);var M;M=u.normalized.labels&&!i.isFalseyButZero(u.normalized.labels[r])?u.normalized.labels[r]:u.normalized.series[r];var O=e.labelInterpolationFnc(M,r);if(O||0===O){var C=t.elem("text",{dx:z.x,dy:z.y,"text-anchor":n(p,z,e.labelDirection)},e.classNames.label).text(""+O);this.eventEmitter.emit("draw",{type:"label",index:r,group:t,element:C,text:""+O,x:z.x,y:z.y})}}h=f}}.bind(this)),this.eventEmitter.emit("created",{chartRect:r,svg:this.svg,options:e})},determineAnchorPosition:n})}(window,document,e),e});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartjs.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartjs.min.js
new file mode 100755
index 0000000..6fc5d34
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/chartjs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(r,l){if(!n[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[r]={exports:{}};e[r][0].call(d.exports,function(t){var n=e[r][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)a(i[r]);return a}({1:[function(t,e,n){},{}],2:[function(t,e,n){function i(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3})$/);if(i){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i[a]+i[a],16)}else if(i=t.match(/^#([a-fA-F0-9]{6})$/)){i=i[1];for(a=0;a<e.length;a++)e[a]=parseInt(i.slice(2*a,2*a+2),16)}else if(i=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/)){for(a=0;a<e.length;a++)e[a]=parseInt(i[a+1]);n=parseFloat(i[4])}else if(i=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/)){for(a=0;a<e.length;a++)e[a]=Math.round(2.55*parseFloat(i[a+1]));n=parseFloat(i[4])}else if(i=t.match(/(\w+)/)){if("transparent"==i[1])return[0,0,0,0];if(!(e=c[i[1]]))return}for(var a=0;a<e.length;a++)e[a]=u(e[a],0,255);return n=n||0==n?u(n,0,1):1,e[3]=n,e}}function a(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function o(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var n=parseFloat(e[4]);return[u(parseInt(e[1]),0,360),u(parseFloat(e[2]),0,100),u(parseFloat(e[3]),0,100),u(isNaN(n)?1:n,0,1)]}}}function r(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function u(t,e,n){return Math.min(Math.max(e,t),n)}function d(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var c=t(6);e.exports={getRgba:i,getHsla:a,getRgb:function(t){var e=i(t);return e&&e.slice(0,3)},getHsl:function(t){var e=a(t);return e&&e.slice(0,3)},getHwb:o,getAlpha:function(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0},hexString:function(t){return"#"+d(t[0])+d(t[1])+d(t[2])},rgbString:function(t,e){return e<1||t[3]&&t[3]<1?r(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:r,percentString:function(t,e){return e<1||t[3]&&t[3]<1?l(t,e):"rgb("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%)"},percentaString:l,hslString:function(t,e){return e<1||t[3]&&t[3]<1?s(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:s,hwbString:function(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in c)h[c[f]]=f},{6:6}],3:[function(t,e,n){var i=t(5),a=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.valid=!1,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};var e;"string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e))};o.prototype={isValid:function(){return this.valid},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 t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=t<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,o=2*a-1,r=n.alpha()-i.alpha(),l=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*n.red()+s*i.red(),l*n.green()+s*i.green(),l*n.blue()+s*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new o,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},o.prototype.setValues=function(t,e){var n,a=this.values,o=this.spaces,r=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)a[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(n=0;n<t.length;n++)a[t][n]=e[s[n]];l=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===l?a.alpha:l)),"alpha"===t)return!1;var u;for(n=0;n<t.length;n++)u=Math.max(0,Math.min(r[t][n],a[t][n])),a[t][n]=Math.round(u);for(var d in o)d!==t&&(a[d]=i[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},o.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=(l+s)/2,n=s==l?0:i<=.5?u/(s+l):u/(2-s-l),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],o=t[1],r=t[2],l=Math.min(a,o,r),s=Math.max(a,o,r),u=s-l;return n=0==s?0:u/s*1e3/10,s==l?e=0:a==s?e=(o-r)/u:o==s?e=2+(r-a)/u:r==s&&(e=4+(a-o)/u),(e=Math.min(60*e,360))<0&&(e+=360),i=s/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2];return[i(t)[0],100*(1/255*Math.min(e,Math.min(n,a))),100*(a=1-1/255*Math.max(e,Math.max(n,a)))]}function l(t){var e,n,i,a,o=t[0]/255,r=t[1]/255,l=t[2]/255;return a=Math.min(1-o,1-r,1-l),e=(1-o-a)/(1-a)||0,n=(1-r-a)/(1-a)||0,i=(1-l-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function s(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),o=a[0],r=a[1],l=a[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,n=500*(o-r),i=200*(r-l),[e,n,i]}function c(t){var e,n,i,a,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];e=2*s-(n=s<.5?s*(1+l):s+l-s*l),a=[0,0,0];for(var u=0;u<3;u++)(i=r+1/3*-(u-1))<0&&i++,i>1&&i--,o=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-n),l=255*i*(1-n*o),s=255*i*(1-n*(1-o)),i=255*i;switch(a){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function f(t){var e,n,i,a,o=t[0]/360,l=t[1]/100,s=t[2]/100,u=l+s;switch(u>1&&(l/=u,s/=u),e=Math.floor(6*o),n=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),a=l+i*(n-l),e){default:case 6:case 0:r=n,g=a,b=l;break;case 1:r=a,g=n,b=l;break;case 2:r=l,g=n,b=a;break;case 3:r=l,g=a,b=n;break;case 4:r=a,g=l,b=n;break;case 5:r=n,g=l,b=a}return[255*r,255*g,255*b]}function p(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,a*(1-l)+l),n=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*n,255*i]}function m(t){var e,n,i,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+-.4986*r,n=-.9689*a+1.8758*o+.0415*r,i=.0557*a+-.204*o+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,n=500*(a-o),i=200*(o-r),[e,n,i]}function x(t){var e,n,i,a,o=t[0],r=t[1],l=t[2];return o<=8?(n=100*o/903.3,a=n/100*7.787+16/116):(n=100*Math.pow((o+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i=i/108.883<=.008859?i=108.883*(a-l/200-16/116)/7.787:108.883*Math.pow(a-l/200,3),[e,n,i]}function y(t){var e,n,i,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(o*o+r*r),[a,i,n]}function k(t){return m(x(t))}function w(t){var e,n,i,a=t[0],o=t[1];return i=t[2]/360*2*Math.PI,e=o*Math.cos(i),n=o*Math.sin(i),[a,e,n]}function M(t){return S[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=o<=1?o:2-o,n=(o+a)/2,e=2*a/(o+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return l(c(t))},hsl2keyword:function(t){return s(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return l(h(t))},hsv2keyword:function(t){return s(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return l(f(t))},hwb2keyword:function(t){return s(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return i(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return s(p(t))},keyword2rgb:M,keyword2hsl:function(t){return i(M(t))},keyword2hsv:function(t){return a(M(t))},keyword2hwb:function(t){return o(M(t))},keyword2cmyk:function(t){return l(M(t))},keyword2lab:function(t){return d(M(t))},keyword2xyz:function(t){return u(M(t))},xyz2rgb:m,xyz2lab:v,xyz2lch:function(t){return y(v(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:w,lch2xyz:function(t){return x(w(t))},lch2rgb:function(t){return k(w(t))}};var S={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]},C={};for(var D in S)C[JSON.stringify(S[D])]=D},{}],5:[function(t,e,n){var i=t(4),a=function(){return new u};for(var o in i){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];(a[l]=a[l]||{})[s]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,n){e.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(t,e,n){var i=t(28)();t(26)(i),t(40)(i),t(22)(i),t(25)(i),t(30)(i),t(21)(i),t(23)(i),t(24)(i),t(29)(i),t(32)(i),t(33)(i),t(31)(i),t(27)(i),t(34)(i),t(35)(i),t(36)(i),t(37)(i),t(38)(i),t(46)(i),t(44)(i),t(45)(i),t(47)(i),t(48)(i),t(49)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(41)(i),t(42)(i),t(43)(i)),i.plugins.register(a),e.exports=i,"undefined"!=typeof window&&(window.Chart=i)},{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,40:40,41:41,42:42,43:43,44:44,45:45,46:46,47:47,48:48,49:49,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.defaults.scatter={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}},t.controllers.scatter=t.controllers.line,t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(){var e,n=this;t.DatasetController.prototype.initialize.apply(n,arguments),(e=n.getMeta()).stack=n.getDataset().stack,e.bar=!0},update:function(t){var e,n,i=this,a=i.getMeta().data;for(i._ruler=i.getRuler(),e=0,n=a.length;e<n;++e)i.updateElement(a[e],e,t)},updateElement:function(t,n,i){var a=this,o=a.chart,r=a.getMeta(),l=a.getDataset(),s=t.custom||{},u=o.options.elements.rectangle;t._xScale=a.getScaleForId(r.xAxisID),t._yScale=a.getScaleForId(r.yAxisID),t._datasetIndex=a.index,t._index=n,t._model={datasetLabel:l.label,label:o.data.labels[n],borderSkipped:s.borderSkipped?s.borderSkipped:u.borderSkipped,backgroundColor:s.backgroundColor?s.backgroundColor:e.getValueAtIndexOrDefault(l.backgroundColor,n,u.backgroundColor),borderColor:s.borderColor?s.borderColor:e.getValueAtIndexOrDefault(l.borderColor,n,u.borderColor),borderWidth:s.borderWidth?s.borderWidth:e.getValueAtIndexOrDefault(l.borderWidth,n,u.borderWidth)},a.updateElementGeometry(t,n,i),t.pivot()},updateElementGeometry:function(t,e,n){var i=this,a=t._model,o=i.getValueScale(),r=o.getBasePixel(),l=o.isHorizontal(),s=i._ruler||i.getRuler(),u=i.calculateBarValuePixels(i.index,e),d=i.calculateBarIndexPixels(i.index,e,s);a.horizontal=l,a.base=n?r:u.base,a.x=l?n?r:u.head:d.center,a.y=l?d.center:n?r:u.head,a.height=l?d.size:void 0,a.width=l?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},getStackCount:function(t){var e,n,i=this.chart,a=this.getIndexScale().options.stacked,o=void 0===t?i.data.datasets.length:t+1,r=[];for(e=0;e<o;++e)(n=i.getDatasetMeta(e)).bar&&i.isDatasetVisible(e)&&(!1===a||!0===a&&-1===r.indexOf(n.stack)||void 0===a&&(void 0===n.stack||-1===r.indexOf(n.stack)))&&r.push(n.stack);return r.length},getStackIndex:function(t){return this.getStackCount(t)-1},getRuler:function(){var t=this.getIndexScale(),n=t.options,i=this.getStackCount(),a=(t.isHorizontal()?t.width:t.height)/t.ticks.length,o=a*n.categoryPercentage,r=o/i,l=r*n.barPercentage;return l=Math.min(e.getValueOrDefault(n.barThickness,l),e.getValueOrDefault(n.maxBarThickness,1/0)),{stackCount:i,tickSize:a,categorySize:o,categorySpacing:a-o,fullBarSize:r,barSize:l,barSpacing:r-l,scale:t}},calculateBarValuePixels:function(t,e){var n,i,a,o,r,l,s=this,u=s.chart,d=s.getMeta(),c=s.getValueScale(),h=u.data.datasets,f=Number(h[t].data[e]),g=c.options.stacked,p=d.stack,m=0;if(g||void 0===g&&void 0!==p)for(n=0;n<t;++n)(i=u.getDatasetMeta(n)).bar&&i.stack===p&&i.controller.getValueScaleId()===c.id&&u.isDatasetVisible(n)&&(a=Number(h[n].data[e]),(f<0&&a<0||f>=0&&a>0)&&(m+=a));return o=c.getPixelForValue(m),r=c.getPixelForValue(m+f),l=(r-o)/2,{size:l,base:o,head:r,center:r+l/2}},calculateBarIndexPixels:function(t,e,n){var i=n.scale,a=this.chart.isCombo,o=this.getStackIndex(t),r=i.getPixelForValue(null,e,t,a),l=n.barSize;return r-=a?n.tickSize/2:0,r+=n.fullBarSize*o,r+=n.categorySpacing/2,r+=n.barSpacing/2,{size:l,base:r,head:r+l,center:r+l/2}},draw:function(){var t,n=this,i=n.chart,a=n.getMeta().data,o=n.getDataset(),r=a.length,l=0;for(e.canvas.clipArea(i.ctx,i.chartArea);l<r;++l)null===(t=o.data[l])||void 0===t||isNaN(t)||a[l].draw();e.canvas.unclipArea(i.ctx)},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;o.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.hoverBackgroundColor,i,e.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(n.hoverBorderColor,i,e.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(n.hoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model,r=this.chart.options.elements.rectangle;o.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(n.backgroundColor,i,r.backgroundColor),o.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(n.borderColor,i,r.borderColor),o.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(n.borderWidth,i,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{}],16:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+t.xLabel+", "+t.yLabel+", "+i.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var n=this,i=n.getMeta().data;e.each(i,function(e,i){n.updateElement(e,i,t)})},updateElement:function(n,i,a){var o=this,r=o.getMeta(),l=o.getScaleForId(r.xAxisID),s=o.getScaleForId(r.yAxisID),u=n.custom||{},d=o.getDataset(),c=d.data[i],h=o.chart.options.elements.point,f=o.index;e.extend(n,{_xScale:l,_yScale:s,_datasetIndex:f,_index:i,_model:{x:a?l.getPixelForDecimal(.5):l.getPixelForValue("object"==typeof c?c:NaN,i,f,o.chart.isCombo),y:a?s.getBasePixel():s.getPixelForValue(c,i,f),radius:a?0:u.radius?u.radius:o.getRadius(c),hitRadius:u.hitRadius?u.hitRadius:e.getValueAtIndexOrDefault(d.hitRadius,i,h.hitRadius)}}),t.DatasetController.prototype.removeHoverStyle.call(o,n,h);var g=n._model;g.skip=u.skip?u.skip:isNaN(g.x)||isNaN(g.y),n.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(n){var i=this;t.DatasetController.prototype.setHoverStyle.call(i,n);var a=i.chart.data.datasets[n._datasetIndex],o=n._index,r=n.custom||{};n._model.radius=r.hoverRadius?r.hoverRadius:e.getValueAtIndexOrDefault(a.hoverRadius,o,i.chart.options.elements.point.hoverRadius)+i.getRadius(a.data[o])},removeHoverStyle:function(e){var n=this;t.DatasetController.prototype.removeHoverStyle.call(n,e,n.chart.options.elements.point);var i=n.chart.data.datasets[e._datasetIndex].data[e._index],a=e.custom||{};e._model.radius=a.radius?a.radius:n.getRadius(i)}})}},{}],17:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults;n.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var o=t.getDatasetMeta(0),r=n.datasets[0],l=o.data[a],s=l&&l.custom||{},u=e.getValueAtIndexOrDefault,d=t.options.elements.arc;return{text:i,fillStyle:s.backgroundColor?s.backgroundColor:u(r.backgroundColor,a,d.backgroundColor),strokeStyle:s.borderColor?s.borderColor:u(r.borderColor,a,d.borderColor),lineWidth:s.borderWidth?s.borderWidth:u(r.borderWidth,a,d.borderWidth),hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)(a=r.getDatasetMeta(n)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,n){var i=n.labels[t.index],a=": "+n.datasets[t.datasetIndex].data[t.index];return e.isArray(i)?(i=i.slice(),i[0]+=a):i+=a,i}}}},n.pie=e.clone(n.doughnut),e.extend(n.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,n=0;n<t;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var n=this,i=n.chart,a=i.chartArea,o=i.options,r=o.elements.arc,l=a.right-a.left-r.borderWidth,s=a.bottom-a.top-r.borderWidth,u=Math.min(l,s),d={x:0,y:0},c=n.getMeta(),h=o.cutoutPercentage,f=o.circumference;if(f<2*Math.PI){var g=o.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,m={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(p),y:Math.sin(p)},b=g<=0&&0<=p||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,w=h/100,M={x:y?-1:Math.min(m.x*(m.x<0?1:w),v.x*(v.x<0?1:w)),y:k?-1:Math.min(m.y*(m.y<0?1:w),v.y*(v.y<0?1:w))},S={x:b?1:Math.max(m.x*(m.x>0?1:w),v.x*(v.x>0?1:w)),y:x?1:Math.max(m.y*(m.y>0?1:w),v.y*(v.y>0?1:w))},C={width:.5*(S.x-M.x),height:.5*(S.y-M.y)};u=Math.min(l/C.width,s/C.height),d={x:-.5*(S.x+M.x),y:-.5*(S.y+M.y)}}i.borderWidth=n.getMaxBorderWidth(c.data),i.outerRadius=Math.max((u-i.borderWidth)/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:0,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=d.x*i.outerRadius,i.offsetY=d.y*i.outerRadius,c.total=n.calculateTotal(),n.outerRadius=i.outerRadius-i.radiusLength*n.getRingIndex(n.index),n.innerRadius=Math.max(n.outerRadius-i.radiusLength,0),e.each(c.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){var a=this,o=a.chart,r=o.chartArea,l=o.options,s=l.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=a.getDataset(),g=i&&s.animateRotate?0:t.hidden?0:a.calculateCircumference(f.data[n])*(l.circumference/(2*Math.PI)),p=i&&s.animateScale?0:a.innerRadius,m=i&&s.animateScale?0:a.outerRadius,v=e.getValueAtIndexOrDefault;e.extend(t,{_datasetIndex:a.index,_index:n,_model:{x:u+o.offsetX,y:d+o.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:v(f.label,n,o.data.labels[n])}});var b=t._model;this.removeHoverStyle(t),i&&s.animateRotate||(b.startAngle=0===n?l.rotation:a.getMeta().data[n-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,n=this.getDataset(),i=this.getMeta(),a=0;return e.each(i.data,function(e,i){t=n.data[i],isNaN(t)||e.hidden||(a+=Math.abs(t))}),a},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,n=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0,i=e>i?e:i,i=n>i?n:i;return i}})}},{}],18:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return n.getValueOrDefault(t.showLine,e.showLines)}var n=t.helpers;t.defaults.line={showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,update:function(t){var i,a,o,r=this,l=r.getMeta(),s=l.dataset,u=l.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(o=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=u,s._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:o.tension?o.tension:n.getValueOrDefault(f.lineTension,c.tension),backgroundColor:o.backgroundColor?o.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:f.borderWidth||c.borderWidth,borderColor:o.borderColor?o.borderColor:f.borderColor||c.borderColor,borderCapStyle:o.borderCapStyle?o.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:o.borderDash?o.borderDash:f.borderDash||c.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:o.fill?o.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:o.steppedLine?o.steppedLine:n.getValueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:o.cubicInterpolationMode?o.cubicInterpolationMode:n.getValueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},s.pivot()),i=0,a=u.length;i<a;++i)r.updateElement(u[i],i,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),i=0,a=u.length;i<a;++i)u[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,a=this.getDataset(),o=t.custom||{};return o.backgroundColor?i=o.backgroundColor:a.pointBackgroundColor?i=n.getValueAtIndexOrDefault(a.pointBackgroundColor,e,i):a.backgroundColor&&(i=a.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,a=this.getDataset(),o=t.custom||{};return o.borderColor?i=o.borderColor:a.pointBorderColor?i=n.getValueAtIndexOrDefault(a.pointBorderColor,e,i):a.borderColor&&(i=a.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,a=this.getDataset(),o=t.custom||{};return isNaN(o.borderWidth)?isNaN(a.pointBorderWidth)?isNaN(a.borderWidth)||(i=a.borderWidth):i=n.getValueAtIndexOrDefault(a.pointBorderWidth,e,i):i=o.borderWidth,i},updateElement:function(t,e,i){var a,o,r=this,l=r.getMeta(),s=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point,p=1===(r.chart.data.labels||[]).length||1===u.data.length||r.chart.isCombo;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),a=f.getPixelForValue("object"==typeof c?c:NaN,e,d,p),o=i?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:a,y:o,skip:s.skip||isNaN(a)||isNaN(o),radius:s.radius||n.getValueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:s.pointStyle||n.getValueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,steppedLine:!!l.dataset._model&&l.dataset._model.steppedLine,hitRadius:s.hitRadius||n.getValueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n){var i,a,o,r=this,l=r.chart,s=r.getMeta(),u=r.getScaleForId(s.yAxisID),d=0,c=0;if(u.options.stacked){for(i=0;i<n;i++)if(a=l.data.datasets[i],"line"===(o=l.getDatasetMeta(i)).type&&o.yAxisID===u.id&&l.isDatasetVisible(i)){var h=Number(u.getRightValue(a.data[e]));h<0?c+=h||0:d+=h||0}var f=Number(u.getRightValue(t));return f<0?u.getPixelForValue(c+f):u.getPixelForValue(d+f)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){function t(t,e,n){return Math.max(Math.min(t,n),e)}var e,i,a,o,r,l=this,s=l.getMeta(),u=l.chart.chartArea,d=s.data||[];if(s.dataset._model.spanGaps&&(d=d.filter(function(t){return!t._model.skip})),"monotone"===s.dataset._model.cubicInterpolationMode)n.splineCurveMonotone(d);else for(e=0,i=d.length;e<i;++e)a=d[e],o=a._model,r=n.splineCurve(n.previousItem(d,e)._model,o,n.nextItem(d,e)._model,s.dataset._model.tension),o.controlPointPreviousX=r.previous.x,o.controlPointPreviousY=r.previous.y,o.controlPointNextX=r.next.x,o.controlPointNextY=r.next.y;if(l.chart.options.elements.line.capBezierPoints)for(e=0,i=d.length;e<i;++e)o=d[e]._model,o.controlPointPreviousX=t(o.controlPointPreviousX,u.left,u.right),o.controlPointPreviousY=t(o.controlPointPreviousY,u.top,u.bottom),o.controlPointNextX=t(o.controlPointNextX,u.left,u.right),o.controlPointNextY=t(o.controlPointNextY,u.top,u.bottom)},draw:function(){var n=this,i=n.chart,a=n.getMeta(),o=a.data||[],r=i.chartArea,l=o.length,s=0;for(t.canvasHelpers.clipArea(i.ctx,r),e(n.getDataset(),i.options)&&a.dataset.draw(),t.canvasHelpers.unclipArea(i.ctx);s<l;++s)o[s].draw(r)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=t._model;o.radius=a.hoverRadius||n.getValueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),o.backgroundColor=a.hoverBackgroundColor||n.getValueAtIndexOrDefault(e.pointHoverBackgroundColor,i,n.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor||n.getValueAtIndexOrDefault(e.pointHoverBorderColor,i,n.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth||n.getValueAtIndexOrDefault(e.pointHoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),r.radius=o.radius||n.getValueAtIndexOrDefault(i.pointRadius,a,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,a),r.borderColor=e.getPointBorderColor(t,a),r.borderWidth=e.getPointBorderWidth(t,a)}})}},{}],19:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var o=t.getDatasetMeta(0),r=n.datasets[0],l=o.data[a].custom||{},s=e.getValueAtIndexOrDefault,u=t.options.elements.arc;return{text:i,fillStyle:l.backgroundColor?l.backgroundColor:s(r.backgroundColor,a,u.backgroundColor),strokeStyle:l.borderColor?l.borderColor:s(r.borderColor,a,u.borderColor),lineWidth:l.borderWidth?l.borderWidth:s(r.borderWidth,a,u.borderWidth),hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,o=e.index,r=this.chart;for(n=0,i=(r.data.datasets||[]).length;n<i;++n)a=r.getDatasetMeta(n),a.data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var n=this,i=n.chart,a=i.chartArea,o=n.getMeta(),r=i.options,l=r.elements.arc,s=Math.min(a.right-a.left,a.bottom-a.top);i.outerRadius=Math.max((s-l.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),n.outerRadius=i.outerRadius-i.radiusLength*n.index,n.innerRadius=n.outerRadius-i.radiusLength,o.count=n.countVisibleElements(),e.each(o.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){for(var a=this,o=a.chart,r=a.getDataset(),l=o.options,s=l.animation,u=o.scale,d=e.getValueAtIndexOrDefault,c=o.data.labels,h=a.calculateCircumference(r.data[n]),f=u.xCenter,g=u.yCenter,p=0,m=a.getMeta(),v=0;v<n;++v)isNaN(r.data[v])||m.data[v].hidden||++p;var b=l.startAngle,x=t.hidden?0:u.getDistanceFromCenterForValue(r.data[n]),y=b+h*p,k=y+(t.hidden?0:h),w=s.animateScale?0:u.getDistanceFromCenterForValue(r.data[n]);e.extend(t,{_datasetIndex:a.index,_index:n,_scale:u,_model:{x:f,y:g,innerRadius:0,outerRadius:i?w:x,startAngle:i&&s.animateRotate?b:y,endAngle:i&&s.animateRotate?b:k,label:d(c,n,c[n])}}),a.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),n=this.getMeta(),i=0;return e.each(n.data,function(e,n){isNaN(t.data[n])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={aspectRatio:1,scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,update:function(t){var n=this,i=n.getMeta(),a=i.dataset,o=i.data,r=a.custom||{},l=n.getDataset(),s=n.chart.options.elements.line,u=n.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),e.extend(i.dataset,{_datasetIndex:n.index,_scale:u,_children:o,_loop:!0,_model:{tension:r.tension?r.tension:e.getValueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle}}),i.dataset.pivot(),e.each(o,function(e,i){n.updateElement(e,i,t)},n),n.updateBezierControlPoints()},updateElement:function(t,n,i){var a=this,o=t.custom||{},r=a.getDataset(),l=a.chart.scale,s=a.chart.options.elements.point,u=l.getPointPositionForValue(n,r.data[n]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),e.extend(t,{_datasetIndex:a.index,_index:n,_scale:l,_model:{x:i?l.xCenter:u.x,y:i?l.yCenter:u.y,tension:o.tension?o.tension:e.getValueOrDefault(r.lineTension,a.chart.options.elements.line.tension),radius:o.radius?o.radius:e.getValueAtIndexOrDefault(r.pointRadius,n,s.radius),backgroundColor:o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(r.pointBackgroundColor,n,s.backgroundColor),borderColor:o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(r.pointBorderColor,n,s.borderColor),borderWidth:o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(r.pointBorderWidth,n,s.borderWidth),pointStyle:o.pointStyle?o.pointStyle:e.getValueAtIndexOrDefault(r.pointStyle,n,s.pointStyle),hitRadius:o.hitRadius?o.hitRadius:e.getValueAtIndexOrDefault(r.pointHitRadius,n,s.hitRadius)}}),t._model.skip=o.skip?o.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,n=this.getMeta();e.each(n.data,function(i,a){var o=i._model,r=e.splineCurve(e.previousItem(n.data,a,!0)._model,o,e.nextItem(n.data,a,!0)._model,o.tension);o.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),o.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),o.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),o.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,o=t._model;o.radius=i.hoverRadius?i.hoverRadius:e.getValueAtIndexOrDefault(n.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),o.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.pointHoverBackgroundColor,a,e.getHoverColor(o.backgroundColor)),o.borderColor=i.hoverBorderColor?i.hoverBorderColor:e.getValueAtIndexOrDefault(n.pointHoverBorderColor,a,e.getHoverColor(o.borderColor)),o.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:e.getValueAtIndexOrDefault(n.pointHoverBorderWidth,a,o.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,o=t._model,r=this.chart.options.elements.point;o.radius=i.radius?i.radius:e.getValueAtIndexOrDefault(n.pointRadius,a,r.radius),o.backgroundColor=i.backgroundColor?i.backgroundColor:e.getValueAtIndexOrDefault(n.pointBackgroundColor,a,r.backgroundColor),o.borderColor=i.borderColor?i.borderColor:e.getValueAtIndexOrDefault(n.pointBorderColor,a,r.borderColor),o.borderWidth=i.borderWidth?i.borderWidth:e.getValueAtIndexOrDefault(n.pointBorderWidth,a,r.borderWidth)}})}},{}],21:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,o,r=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var n=e.findIndex(this.animations,function(e){return e.chart===t});-1!==n&&(this.animations.splice(n,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var n,i,a=this.animations,o=0;o<a.length;)n=a[o],i=n.chart,n.currentStep=(n.currentStep||0)+t,n.currentStep=Math.min(n.currentStep,n.numSteps),e.callback(n.render,[i,n],i),e.callback(n.onAnimationProgress,[n],i),n.currentStep>=n.numSteps?(e.callback(n.onAnimationComplete,[n],i),i.animating=!1,a.splice(o,1)):++o}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{}],22:[function(t,e,n){"use strict";e.exports=function(t){var e=t.canvasHelpers={};e.drawPoint=function(e,n,i,a,o){var r,l,s,u,d,c;if("object"!=typeof n||"[object HTMLImageElement]"!==(r=n.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(i)||i<=0)){switch(n){default:e.beginPath(),e.arc(a,o,i,0,2*Math.PI),e.closePath(),e.fill();break;case"triangle":e.beginPath(),d=(l=3*i/Math.sqrt(3))*Math.sqrt(3)/2,e.moveTo(a-l/2,o+d/3),e.lineTo(a+l/2,o+d/3),e.lineTo(a,o-2*d/3),e.closePath(),e.fill();break;case"rect":c=1/Math.SQRT2*i,e.beginPath(),e.fillRect(a-c,o-c,2*c,2*c),e.strokeRect(a-c,o-c,2*c,2*c);break;case"rectRounded":var h=i/Math.SQRT2,f=a-h,g=o-h,p=Math.SQRT2*i;t.helpers.drawRoundedRectangle(e,f,g,p,p,i/2),e.fill();break;case"rectRot":c=1/Math.SQRT2*i,e.beginPath(),e.moveTo(a-c,o),e.lineTo(a,o+c),e.lineTo(a+c,o),e.lineTo(a,o-c),e.closePath(),e.fill();break;case"cross":e.beginPath(),e.moveTo(a,o+i),e.lineTo(a,o-i),e.moveTo(a-i,o),e.lineTo(a+i,o),e.closePath();break;case"crossRot":e.beginPath(),s=Math.cos(Math.PI/4)*i,u=Math.sin(Math.PI/4)*i,e.moveTo(a-s,o-u),e.lineTo(a+s,o+u),e.moveTo(a-s,o+u),e.lineTo(a+s,o-u),e.closePath();break;case"star":e.beginPath(),e.moveTo(a,o+i),e.lineTo(a,o-i),e.moveTo(a-i,o),e.lineTo(a+i,o),s=Math.cos(Math.PI/4)*i,u=Math.sin(Math.PI/4)*i,e.moveTo(a-s,o-u),e.lineTo(a+s,o+u),e.moveTo(a-s,o+u),e.lineTo(a+s,o-u),e.closePath();break;case"line":e.beginPath(),e.moveTo(a-i,o),e.lineTo(a+i,o),e.closePath();break;case"dash":e.beginPath(),e.moveTo(a,o),e.lineTo(a+i,o),e.closePath()}e.stroke()}}else e.drawImage(n,a-n.width/2,o-n.height/2,n.width,n.height)},e.clipArea=function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},e.unclipArea=function(t){t.restore()},e.lineTo=function(t,e,n,i){return n.steppedLine?("after"===n.steppedLine?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y)):n.tension?void t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):void t.lineTo(n.x,n.y)},t.helpers.canvas=e}},{}],23:[function(t,e,n){"use strict";e.exports=function(t){function e(t){return"top"===t||"bottom"===t}var n=t.helpers,i=t.plugins,a=t.platform;t.types={},t.instances={},t.controllers={},n.extend(t.prototype,{construct:function(e,i){var o=this;i=function(e){var i=(e=e||{}).data=e.data||{};return i.datasets=i.datasets||[],i.labels=i.labels||[],e.options=n.configMerge(t.defaults.global,t.defaults[e.type],e.options||{}),e}(i);var r=a.acquireContext(e,i),l=r&&r.canvas,s=l&&l.height,u=l&&l.width;return o.id=n.uid(),o.ctx=r,o.canvas=l,o.config=i,o.width=u,o.height=s,o.aspectRatio=s?u/s:null,o.options=i.options,o._bufferedRender=!1,o.chart=o,o.controller=o,t.instances[o.id]=o,Object.defineProperty(o,"data",{get:function(){return o.config.data},set:function(t){o.config.data=t}}),r&&l?(o.initialize(),void o.update()):void console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return i.notify(t,"beforeInit"),n.retinaScale(t),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),i.notify(t,"afterInit"),t},clear:function(){return n.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,a=e.options,o=e.canvas,r=a.maintainAspectRatio&&e.aspectRatio||null,l=Math.floor(n.getMaximumWidth(o)),s=Math.floor(r?l/r:n.getMaximumHeight(o));if((e.width!==l||e.height!==s)&&(o.width=e.width=l,o.height=e.height=s,o.style.width=l+"px",o.style.height=s+"px",n.retinaScale(e),!t)){var u={width:l,height:s};i.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},i=t.scale;n.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),n.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildScales:function(){var i=this,a=i.options,o=i.scales={},r=[];a.scales&&(r=r.concat((a.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(a.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),a.scale&&r.push({options:a.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),n.each(r,function(a){var r=a.options,l=n.getValueOrDefault(r.type,a.dtype),s=t.scaleService.getScaleConstructor(l);if(s){e(r.position)!==e(a.dposition)&&(r.position=a.dposition);var u=new s({id:r.id,options:r,ctx:i.ctx,chart:i});o[u.id]=u,a.isDefault&&(i.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,i=[],a=[];if(n.each(e.data.datasets,function(n,o){var r=e.getDatasetMeta(o);if(r.type||(r.type=n.type||e.config.type),i.push(r.type),r.controller)r.controller.updateIndex(o);else{var l=t.controllers[r.type];if(void 0===l)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new l(e,o),a.push(r.controller)}},e),i.length>1)for(var o=1;o<i.length;o++)if(i[o]!==i[o-1]){e.isCombo=!0;break}return a},resetElements:function(){var t=this;n.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t,e){var a=this;if(function(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}(a),!1!==i.notify(a,"beforeUpdate")){a.tooltip._data=a.data;var o=a.buildOrUpdateControllers();n.each(a.data.datasets,function(t,e){a.getDatasetMeta(e).controller.buildOrUpdateElements()},a),a.updateLayout(),n.each(o,function(t){t.reset()}),a.updateDatasets(),i.notify(a,"afterUpdate"),a._bufferedRender?a._bufferedRequest={lazy:e,duration:t}:a.render(t,e)}},updateLayout:function(){var e=this;!1!==i.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),i.notify(e,"afterScaleUpdate"),i.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==i.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e<n;++e)t.updateDataset(e);i.notify(t,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this,n=e.getDatasetMeta(t),a={meta:n,index:t};!1!==i.notify(e,"beforeDatasetUpdate",[a])&&(n.controller.update(),i.notify(e,"afterDatasetUpdate",[a]))},render:function(e,a){var o=this;if(!1!==i.notify(o,"beforeRender")){var r=o.options.animation,l=function(t){i.notify(o,"afterRender"),n.callback(r&&r.onComplete,[t],o)};if(r&&(void 0!==e&&0!==e||void 0===e&&0!==r.duration)){var s=new t.Animation({numSteps:(e||r.duration)/16.66,easing:r.easing,render:function(t,e){var i=n.easingEffects[e.easing],a=e.currentStep,o=a/e.numSteps;t.draw(i(o),o,a)},onAnimationProgress:r.onProgress,onAnimationComplete:l});t.animationService.addAnimation(o,s,e,a)}else o.draw(),l(new t.Animation({numSteps:0,chart:o}));return o}},draw:function(t){var e=this;e.clear(),void 0!==t&&null!==t||(t=1),e.transition(t),!1!==i.notify(e,"beforeDraw",[t])&&(n.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e.tooltip.draw(),i.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=this,n=0,i=(e.data.datasets||[]).length;n<i;++n)e.isDatasetVisible(n)&&e.getDatasetMeta(n).controller.transition(t);e.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==i.notify(e,"beforeDatasetsDraw",[t])){for(var n=(e.data.datasets||[]).length-1;n>=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);i.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,a=n.getDatasetMeta(t),o={meta:a,index:t,easingValue:e};!1!==i.notify(n,"beforeDatasetDraw",[o])&&(a.controller.draw(e),i.notify(n,"afterDatasetDraw",[o]))},getElementAtEvent:function(e){return t.Interaction.modes.single(this,e)},getElementsAtEvent:function(e){return t.Interaction.modes.label(this,e,{intersect:!0})},getElementsAtXAxis:function(e){return t.Interaction.modes["x-axis"](this,e,{intersect:!0})},getElementsAtEventForMode:function(e,n,i){var a=t.Interaction.modes[n];return"function"==typeof a?a(this,e,i):[]},getDatasetAtEvent:function(e){return t.Interaction.modes.dataset(this,e,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e<n;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){var e,o,r,l=this,s=l.canvas;for(l.stop(),o=0,r=l.data.datasets.length;o<r;++o)(e=l.getDatasetMeta(o)).controller&&(e.controller.destroy(),e.controller=null);s&&(l.unbindEvents(),n.clear(l),a.releaseContext(l.ctx),l.canvas=null,l.ctx=null),i.notify(l,"destroy"),delete t.instances[l.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e),e.tooltip.initialize()},bindEvents:function(){var t=this,e=t._listeners={},i=function(){t.eventHandler.apply(t,arguments)};n.each(t.options.events,function(n){a.addEventListener(t,n,i),e[n]=i}),t.options.responsive&&(i=function(){t.resize()},a.addEventListener(t,"resize",i),e.resize=i)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,n.each(e,function(e,n){a.removeEventListener(t,n,e)}))},updateHoverStyle:function(t,e,n){var i,a,o,r=n?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(i=t[a])&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var e=this,n=e.tooltip;if(!1!==i.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var a=e.handleEvent(t);a|=n&&n.handleEvent(t),i.notify(e,"afterEvent",[t]);var o=e._bufferedRequest;return o?e.render(o.duration,o.lazy):a&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e=this,i=e.options||{},a=i.hover,o=!1;return e.lastActive=e.lastActive||[],"mouseout"===t.type?e.active=[]:e.active=e.getElementsAtEventForMode(t,a.mode,a),a.onHover&&a.onHover.call(e,t.native,e.active),"mouseup"!==t.type&&"click"!==t.type||i.onClick&&i.onClick.call(e,t.native,e.active),e.lastActive.length&&e.updateHoverStyle(e.lastActive,a.mode,!1),e.active.length&&a.mode&&e.updateHoverStyle(e.active,a.mode,!0),o=!n.arrayEquals(e.active,e.lastActive),e.lastActive=e.active,o}}),t.Controller=t}},{}],24:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t._chartjs?void t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),void a.forEach(function(e){var n="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return i.each(t._chartjs.listeners,function(t){"function"==typeof t[n]&&t[n].apply(t,e)}),o}})}))}function n(t,e){var n=t._chartjs;if(n){var i=n.listeners,o=i.indexOf(e);-1!==o&&i.splice(o,1),i.length>0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var i=t.helpers,a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.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(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],o=i.data;for(t=0,e=a.length;t<e;++t)o[t]=o[t]||n.createMetaData(t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t=this,i=t.getDataset(),a=i.data||(i.data=[]);t._data!==a&&(t._data&&n(t._data,t),e(a,t),t._data=a),t.resyncElements()},update:i.noop,transition:function(t){for(var e=this.getMeta(),n=e.data||[],i=n.length,a=0;a<i;++a)n[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],n=e.length,i=0;for(t.dataset&&t.dataset.draw();i<n;++i)e[i].draw()},removeHoverStyle:function(t,e){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=i.getValueAtIndexOrDefault,l=t._model;l.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,e.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,e.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=i.getValueAtIndexOrDefault,r=i.getHoverColor,l=t._model;l.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,n,r(l.backgroundColor)),l.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,n,r(l.borderColor)),l.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,n,l.borderWidth)},resyncElements:function(){var t=this,e=t.getMeta(),n=t.getDataset().data,i=e.data.length,a=n.length;a<i?e.data.splice(a,i-a):a>i&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n<e;++n)this.addElementAndReset(t+n)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=i.inherits}},{}],25:[function(t,e,n){"use strict";var i=t(3);e.exports=function(t){function e(t,e,n,a){var o,r,l,s,u,d,c,h,f,g=Object.keys(n);for(o=0,r=g.length;o<r;++o)if(l=g[o],d=n[l],e.hasOwnProperty(l)||(e[l]=d),(s=e[l])!==d&&"_"!==l[0]){if(t.hasOwnProperty(l)||(t[l]=s),u=t[l],(c=typeof d)===typeof u)if("string"===c){if((h=i(u)).valid&&(f=i(d)).valid){e[l]=f.mix(h,a).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[l]=u+(d-u)*a;continue}e[l]=d}}var n=t.helpers;t.elements={},t.Element=function(t){n.extend(this,t),this.initialize.apply(this,arguments)},n.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=n.clone(t._model)),t._start={},t},transition:function(t){var n=this,i=n._model,a=n._start,o=n._view;return i&&1!==t?(o||(o=n._view={}),a||(a=n._start={}),e(a,o,i,t),n):(n._view=i,n._start=null,n)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return n.isNumber(this._model.x)&&n.isNumber(this._model.y)}}),t.Element.extend=n.inherits}},{3:3}],26:[function(t,e,n){"use strict";var i=t(3);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!==t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function a(t,i,a){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],u=n(l),d=n(s),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(l,t,a):c,d?e(s,r,a):c):"none"}var o=t.helpers={};o.each=function(t,e,n,i){var a,r;if(o.isArray(t))if(r=t.length,i)for(a=r-1;a>=0;a--)e.call(n,t[a],a);else for(a=0;a<r;a++)e.call(n,t[a],a);else if("object"==typeof t){var l=Object.keys(t);for(r=l.length,a=0;a<r;a++)e.call(n,t[l[a]],l[a])}},o.clone=function(t){var e={};return o.each(t,function(t,n){o.isArray(t)?e[n]=t.slice(0):e[n]="object"==typeof t&&null!==t?o.clone(t):t}),e},o.extend=function(t){for(var e=function(e,n){t[n]=e},n=1,i=arguments.length;n<i;n++)o.each(arguments[n],e);return t},o.configMerge=function(e){var n=o.clone(e);return o.each(Array.prototype.slice.call(arguments,1),function(e){o.each(e,function(e,i){var a=n.hasOwnProperty(i),r=a?n[i]:{};"scales"===i?n[i]=o.scaleMerge(r,e):"scale"===i?n[i]=o.configMerge(r,t.scaleService.getScaleDefaults(e.type),e):!a||"object"!=typeof r||o.isArray(r)||null===r||"object"!=typeof e||o.isArray(e)?n[i]=e:n[i]=o.configMerge(r,e)})}),n},o.scaleMerge=function(e,n){var i=o.clone(e);return o.each(n,function(e,n){"xAxes"===n||"yAxes"===n?i.hasOwnProperty(n)?o.each(e,function(e,a){var r=o.getValueOrDefault(e.type,"xAxes"===n?"category":"linear"),l=t.scaleService.getScaleDefaults(r);a>=i[n].length||!i[n][a].type?i[n].push(o.configMerge(l,e)):e.type&&e.type!==i[n][a].type?i[n][a]=o.configMerge(i[n][a],l,e):i[n][a]=o.configMerge(i[n][a],e)}):(i[n]=[],o.each(e,function(e){var a=o.getValueOrDefault(e.type,"xAxes"===n?"category":"linear");i[n].push(o.configMerge(t.scaleService.getScaleDefaults(a),e))})):i.hasOwnProperty(n)&&"object"==typeof i[n]&&null!==i[n]&&"object"==typeof e?i[n]=o.configMerge(i[n],e):i[n]=e}),i},o.getValueAtIndexOrDefault=function(t,e,n){return void 0===t||null===t?n:o.isArray(t)?e<t.length?t[e]:n:t},o.getValueOrDefault=function(t,e){return void 0===t?e:t},o.indexOf=Array.prototype.indexOf?function(t,e){return t.indexOf(e)}:function(t,e){for(var n=0,i=t.length;n<i;++n)if(t[n]===e)return n;return-1},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return o.each(t,function(t){e(t)&&n.push(t)}),n},o.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i<a;++i)if(e.call(n,t[i],i,t))return i;return-1},o.findNextWhere=function(t,e,n){void 0!==n&&null!==n||(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},o.findPreviousWhere=function(t,e,n){void 0!==n&&null!==n||(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},o.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=o.inherits,t&&o.extend(n.prototype,t),n.__super__=e.prototype,n},o.noop=function(){},o.uid=function(){var t=0;return function(){return t++}}(),o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,n){return Math.abs(t-e)<n},o.almostWhole=function(t,e){var n=Math.round(t);return n-e<t&&n+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),o=Math.atan2(i,n);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,n,i){var a=t.skip?e:t,o=e,r=n.skip?e:n,l=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=l/(l+s),d=s/(l+s),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,n,i,a,r=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),l=r.length;for(e=0;e<l;++e)if(!(i=r[e]).model.skip){if(n=e>0?r[e-1]:null,(a=e<l-1?r[e+1]:null)&&!a.model.skip){var s=a.model.x-i.model.x;i.deltaK=0!==s?(a.model.y-i.model.y)/s:0}!n||n.model.skip?i.mK=i.deltaK:!a||a.model.skip?i.mK=n.deltaK:this.sign(n.deltaK)!==this.sign(i.deltaK)?i.mK=0:i.mK=(n.deltaK+i.deltaK)/2}var u,d,c,h;for(e=0;e<l-1;++e)i=r[e],a=r[e+1],i.model.skip||a.model.skip||(o.almostEquals(i.deltaK,0,this.EPSILON)?i.mK=a.mK=0:(u=i.mK/i.deltaK,d=a.mK/i.deltaK,(h=Math.pow(u,2)+Math.pow(d,2))<=9||(c=3/Math.sqrt(h),i.mK=u*c*i.deltaK,a.mK=d*c*i.deltaK)));var f;for(e=0;e<l;++e)(i=r[e]).model.skip||(n=e>0?r[e-1]:null,a=e<l-1?r[e+1]:null,n&&!n.model.skip&&(f=(i.model.x-n.model.x)/3,i.model.controlPointPreviousX=i.model.x-f,i.model.controlPointPreviousY=i.model.y-f*i.mK),a&&!a.model.skip&&(f=(a.model.x-i.model.x)/3,i.model.controlPointNextX=i.model.x+f,i.model.controlPointNextY=i.model.y+f*i.mK))},o.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var n=Math.floor(o.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)};var r=o.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--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){return(t/=.5)<1?.5*t*t*t:.5*((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){return(t/=.5)<1?.5*t*t*t*t:-.5*((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){return(t/=.5)<1?.5*t*t*t*t*t:.5*((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-.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(1-Math.pow(2,-10*t/1))},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1==(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1==(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.3*1.5*1),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t*1:t<2/2.75?1*(7.5625*(t-=1.5/2.75)*t+.75):t<2.5/2.75?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return t<.5?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-u-c,g=l.bottom-l.top-d-h;return n=Math.round((n-l.left-u)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-d)/g*r.height/e.currentDevicePixelRatio),{x:n,y:i}},o.addEvent=function(t,e,n){t.addEventListener?t.addEventListener(e,n):t.attachEvent?t.attachEvent("on"+e,n):t["on"+e]=n},o.removeEvent=function(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent?t.detachEvent("on"+e,n):t["on"+e]=o.noop},o.getConstraintWidth=function(t){return a(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return a(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode,n=parseInt(o.getStyle(e,"padding-left"),10),i=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode,n=parseInt(o.getStyle(e,"padding-top"),10),i=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t){var e=t.currentDevicePixelRatio=window.devicePixelRatio||1;if(1!==e){var n=t.canvas,i=t.height,a=t.width;n.height=i*e,n.width=a*e,t.ctx.scale(e,e),n.style.height=i+"px",n.style.width=a+"px"}},o.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},o.fontString=function(t,e,n){return e+" "+t+"px "+n},o.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(n,function(e){void 0!==e&&null!==e&&!0!==o.isArray(e)?l=o.measureText(t,a,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,a,r,l,e))})});var s=r.length/2;if(s>n.length){for(var u=0;u<s;u++)delete a[r[u]];r.splice(0,s)}return l},o.measureText=function(t,e,n,i,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,n.push(a)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.drawRoundedRectangle=function(t,e,n,i,a,o){t.beginPath(),t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+o),t.lineTo(e+i,n+a-o),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-o),t.lineTo(e,n+o),t.quadraticCurveTo(e,n,e+o,n),t.closePath()},o.color=i?function(e){return e instanceof CanvasGradient&&(e=t.defaults.global.defaultColor),i(e)}:function(t){return console.error("Color.js not found!"),t},o.isArray=Array.isArray?function(t){return Array.isArray(t)}:function(t){return"[object Array]"===Object.prototype.toString.call(t)},o.arrayEquals=function(t,e){var n,i,a,r;if(!t||!e||t.length!==e.length)return!1;for(n=0,i=t.length;n<i;++n)if(a=t[n],r=e[n],a instanceof Array&&r instanceof Array){if(!o.arrayEquals(a,r))return!1}else if(a!==r)return!1;return!0},o.callback=function(t,e,n){t&&"function"==typeof t.call&&t.apply(n,e)},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()},o.callCallback=o.callback}},{3:3}],27:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t.native?{x:t.x,y:t.y}:r.getRelativePosition(t,e)}function n(t,e){var n,i,a,o,r;for(i=0,o=t.data.datasets.length;i<o;++i)if(t.isDatasetVisible(i))for(n=t.getDatasetMeta(i),a=0,r=n.data.length;a<r;++a){var l=n.data[a];l._view.skip||e(l)}}function i(t,e){var i=[];return n(t,function(t){t.inRange(e.x,e.y)&&i.push(t)}),i}function a(t,e,i,a){var o=Number.POSITIVE_INFINITY,l=[];return a||(a=r.distanceBetweenPoints),n(t,function(t){if(!i||t.inRange(e.x,e.y)){var n=t.getCenterPoint(),r=a(e,n);r<o?(l=[t],o=r):r===o&&l.push(t)}}),l}function o(t,n,o){var r=e(n,t),l=o.intersect?i(t,r):a(t,r,!1,function(t,e){return Math.abs(t.x-e.x)}),s=[];return l.length?(t.data.datasets.forEach(function(e,n){if(t.isDatasetVisible(n)){var i=t.getDatasetMeta(n).data[l[0]._index];i&&!i._view.skip&&s.push(i)}}),s):[]}var r=t.helpers;t.Interaction={modes:{single:function(t,i){var a=e(i,t),o=[];return n(t,function(t){if(t.inRange(a.x,a.y))return o.push(t),o}),o.slice(0,1)},label:o,index:o,dataset:function(t,n,o){var r=e(n,t),l=o.intersect?i(t,r):a(t,r,!1);return l.length>0&&(l=t.getDatasetMeta(l[0]._datasetIndex).data),l},"x-axis":function(t,e){return o(t,e,!0)},point:function(t,n){return i(t,e(n,t))},nearest:function(t,n,i){var o=a(t,e(n,t),i.intersect);return o.length>1&&o.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),o.slice(0,1)},x:function(t,i,a){var o=e(i,t),r=[],l=!1;return n(t,function(t){t.inXRange(o.x)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),a.intersect&&!l&&(r=[]),r},y:function(t,i,a){var o=e(i,t),r=[],l=!1;return n(t,function(t){t.inYRange(o.y)&&r.push(t),t.inRange(o.x,o.y)&&(l=!0)}),a.intersect&&!l&&(r=[]),r}}}}},{}],28:[function(t,e,n){"use strict";e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,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:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t.Chart=t,t}},{}],29:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}var i=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)i=a[r],n.hasOwnProperty(i)&&(e[i]=n[i])},update:function(t,a,o){function r(t){var e=i.findNextWhere(D,function(e){return e.box===t});if(e)if(t.isHorizontal()){var n={left:Math.max(T,I),right:Math.max(F,A),top:0,bottom:0};t.update(t.fullWidth?x:S,y/2,n)}else t.update(e.minSize.width,C)}function l(t){t.isHorizontal()?(t.left=t.fullWidth?d:T,t.right=t.fullWidth?a-c:T+S,t.top=N,t.bottom=N+t.height,N=t.bottom):(t.left=W,t.right=W+t.width,t.top=R,t.bottom=R+C,W=t.right)}if(t){var s=t.options.layout,u=s?s.padding:null,d=0,c=0,h=0,f=0;isNaN(u)?(d=u.left||0,c=u.right||0,h=u.top||0,f=u.bottom||0):(d=u,c=u,h=u,f=u);var g=e(t.boxes,"left"),p=e(t.boxes,"right"),m=e(t.boxes,"top"),v=e(t.boxes,"bottom"),b=e(t.boxes,"chartArea");n(g,!0),n(p,!1),n(m,!0),n(v,!1);var x=a-d-c,y=o-h-f,k=y/2,w=(a-x/2)/(g.length+p.length),M=(o-k)/(m.length+v.length),S=x,C=y,D=[];i.each(g.concat(p,m,v),function(t){var e,n=t.isHorizontal();n?(e=t.update(t.fullWidth?x:S,M),C-=e.height):(e=t.update(w,k),S-=e.width),D.push({horizontal:n,minSize:e,box:t})});var I=0,A=0,P=0,_=0;i.each(m.concat(v),function(t){if(t.getPadding){var e=t.getPadding();I=Math.max(I,e.left),A=Math.max(A,e.right)}}),i.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();P=Math.max(P,e.top),_=Math.max(_,e.bottom)}});var T=d,F=c,R=h,L=f;i.each(g.concat(p),r),i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(m.concat(v),r),i.each(m,function(t){R+=t.height}),i.each(v,function(t){L+=t.height}),i.each(g.concat(p),function(t){var e=i.findNextWhere(D,function(e){return e.box===t}),n={left:0,right:0,top:R,bottom:L};e&&t.update(e.minSize.width,C,n)}),T=d,F=c,R=h,L=f,i.each(g,function(t){T+=t.width}),i.each(p,function(t){F+=t.width}),i.each(m,function(t){R+=t.height}),i.each(v,function(t){L+=t.height});var V=Math.max(I-T,0);T+=V,F+=Math.max(A-F,0);var O=Math.max(P-R,0);R+=O,L+=Math.max(_-L,0);var z=o-R-L,B=a-T-F;B===S&&z===C||(i.each(g,function(t){t.height=z}),i.each(p,function(t){t.height=z}),i.each(m,function(t){t.fullWidth||(t.width=B)}),i.each(v,function(t){t.fullWidth||(t.width=B)}),C=z,S=B);var W=d+V,N=h+O;i.each(g.concat(m),l),W+=S,N+=C,i.each(p,l),i.each(v,l),t.chartArea={left:T,top:R,right:T+S,bottom:R+C},i.each(b,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(S,C)})}}}}},{}],30:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.plugins={},t.plugins={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var n=e.indexOf(t);-1!==n&&e.splice(n,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,n){var i,a,o,r,l,s=this.descriptors(t),u=s.length;for(i=0;i<u;++i)if(a=s[i],o=a.plugin,"function"==typeof(l=o[e])&&((r=[t].concat(n||[])).push(a.options),!1===l.apply(o,r)))return!1;return!0},descriptors:function(n){var i=n._plugins||(n._plugins={});if(i.id===this._cacheId)return i.descriptors;var a=[],o=[],r=n&&n.config||{},l=t.defaults.global.plugins,s=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===a.indexOf(t)){var n=t.id,i=s[n];!1!==i&&(!0===i&&(i=e.clone(l[n])),a.push(t),o.push({plugin:t,options:i||{}}))}}),i.descriptors=o,i.id=this._cacheId,o}},t.pluginService=t.plugins,t.PluginBase=t.Element.extend({})}},{}],31:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e,n){return i.isArray(e)?i.longestText(t,n,e):t.measureText(e).width}function n(e){var n=i.getValueOrDefault,a=t.defaults.global,o=n(e.fontSize,a.defaultFontSize),r=n(e.fontStyle,a.defaultFontStyle),l=n(e.fontFamily,a.defaultFontFamily);return{size:o,style:r,family:l,font:i.fontString(o,r,l)}}var i=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:t.Ticks.formatters.values}},t.Scale=t.Element.extend({getPadding:function(){var t=this;return{left:t.paddingLeft||0,top:t.paddingTop||0,right:t.paddingRight||0,bottom:t.paddingBottom||0}},beforeUpdate:function(){i.callback(this.options.beforeUpdate,[this])},update:function(t,e,n){var a=this;return a.beforeUpdate(),a.maxWidth=t,a.maxHeight=e,a.margins=i.extend({left:0,right:0,top:0,bottom:0},n),a.longestTextCache=a.longestTextCache||{},a.beforeSetDimensions(),a.setDimensions(),a.afterSetDimensions(),a.beforeDataLimits(),a.determineDataLimits(),a.afterDataLimits(),a.beforeBuildTicks(),a.buildTicks(),a.afterBuildTicks(),a.beforeTickToLabelConversion(),a.convertTicksToLabels(),a.afterTickToLabelConversion(),a.beforeCalculateTickRotation(),a.calculateTickRotation(),a.afterCalculateTickRotation(),a.beforeFit(),a.fit(),a.afterFit(),a.afterUpdate(),a.minSize},afterUpdate:function(){i.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){i.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){i.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){i.callback(this.options.beforeDataLimits,[this])},determineDataLimits:i.noop,afterDataLimits:function(){i.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){i.callback(this.options.beforeBuildTicks,[this])},buildTicks:i.noop,afterBuildTicks:function(){i.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){i.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this,e=t.options.ticks;t.ticks=t.ticks.map(e.userCallback||e.callback)},afterTickToLabelConversion:function(){i.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){i.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,a=t.options.ticks,o=n(a);e.font=o.font;var r=a.minRotation||0;if(t.options.display&&t.isHorizontal())for(var l,s=i.longestText(e,o.font,t.ticks,t.longestTextCache),u=s,d=t.getPixelForTick(1)-t.getPixelForTick(0)-6;u>d&&r<a.maxRotation;){var c=i.toRadians(r);if(l=Math.cos(c),Math.sin(c)*s>t.maxHeight){r--;break}r++,u=l*s}t.labelRotation=r},afterCalculateTickRotation:function(){i.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){i.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},o=t.options,r=o.ticks,l=o.scaleLabel,s=o.gridLines,u=o.display,d=t.isHorizontal(),c=n(r),h=1.5*n(l).size,f=o.gridLines.tickMarkLength;if(a.width=d?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:u&&s.drawTicks?f:0,a.height=d?u&&s.drawTicks?f:0:t.maxHeight,l.display&&u&&(d?a.height+=h:a.width+=h),r.display&&u){var g=i.longestText(t.ctx,c.font,t.ticks,t.longestTextCache),p=i.numberOfLabelLines(t.ticks),m=.5*c.size;if(d){t.longestLabelWidth=g;var v=i.toRadians(t.labelRotation),b=Math.cos(v),x=Math.sin(v)*g+c.size*p+m*p;a.height=Math.min(t.maxHeight,a.height+x),t.ctx.font=c.font;var y=t.ticks[0],k=e(t.ctx,y,c.font),w=t.ticks[t.ticks.length-1],M=e(t.ctx,w,c.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?b*k+3:b*m+3,t.paddingRight="bottom"===o.position?b*m+3:b*M+3):(t.paddingLeft=k/2+3,t.paddingRight=M/2+3)}else r.mirror?g=0:g+=t.options.ticks.padding,a.width=Math.min(t.maxWidth,a.width+g),t.paddingTop=c.size/2,t.paddingBottom=c.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){i.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){return null===t||void 0===t?NaN:"number"!=typeof t||isFinite(t)?"object"==typeof t?t instanceof Date||t.isValid?t:this.getRightValue(this.isHorizontal()?t.x:t.y):t:NaN},getLabelForIndex:i.noop,getPixelForValue:i.noop,getValueForPixel:i.noop,getPixelForTick:function(t,e){var n=this;if(n.isHorizontal()){var i=(n.width-(n.paddingLeft+n.paddingRight))/Math.max(n.ticks.length-(n.options.gridLines.offsetGridLines?0:1),1),a=i*t+n.paddingLeft;e&&(a+=i/2);var o=n.left+Math.round(a);return o+=n.isFullWidth()?n.margins.left:0}var r=n.height-(n.paddingTop+n.paddingBottom);return n.top+t*(r/(n.ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},draw:function(e){var a=this,o=a.options;if(o.display){var r,l,s=a.ctx,u=t.defaults.global,d=o.ticks,c=o.gridLines,h=o.scaleLabel,f=0!==a.labelRotation,g=d.autoSkip,p=a.isHorizontal();d.maxTicksLimit&&(l=d.maxTicksLimit);var m=i.getValueOrDefault(d.fontColor,u.defaultFontColor),v=n(d),b=c.drawTicks?c.tickMarkLength:0,x=i.getValueOrDefault(h.fontColor,u.defaultFontColor),y=n(h),k=i.toRadians(a.labelRotation),w=Math.cos(k),M=a.longestLabelWidth*w;s.fillStyle=m;var S=[];if(p){if(r=!1,(M+d.autoSkipPadding)*a.ticks.length>a.width-(a.paddingLeft+a.paddingRight)&&(r=1+Math.floor((M+d.autoSkipPadding)*a.ticks.length/(a.width-(a.paddingLeft+a.paddingRight)))),l&&a.ticks.length>l)for(;!r||a.ticks.length/(r||1)>l;)r||(r=1),r+=1;g||(r=!1)}var C="right"===o.position?a.left:a.right-b,D="right"===o.position?a.left+b:a.right,I="bottom"===o.position?a.top:a.bottom-b,A="bottom"===o.position?a.top+b:a.bottom;if(i.each(a.ticks,function(t,n){if(void 0!==t&&null!==t){var l=a.ticks.length===n+1;if((!(r>1&&n%r>0||n%r==0&&n+r>=a.ticks.length)||l)&&void 0!==t&&null!==t){var s,h,g,m;n===(void 0!==a.zeroLineIndex?a.zeroLineIndex:0)?(s=c.zeroLineWidth,h=c.zeroLineColor,g=c.zeroLineBorderDash,m=c.zeroLineBorderDashOffset):(s=i.getValueAtIndexOrDefault(c.lineWidth,n),h=i.getValueAtIndexOrDefault(c.color,n),g=i.getValueOrDefault(c.borderDash,u.borderDash),m=i.getValueOrDefault(c.borderDashOffset,u.borderDashOffset));var v,x,y,w,M,P,_,T,F,R,L="middle",V="middle";if(p){"bottom"===o.position?(V=f?"middle":"top",L=f?"right":"center",R=a.top+b):(V=f?"middle":"bottom",L=f?"left":"center",R=a.bottom-b);var O=a.getPixelForTick(n)+i.aliasPixel(s);F=a.getPixelForTick(n,c.offsetGridLines)+d.labelOffset,v=y=M=_=O,x=I,w=A,P=e.top,T=e.bottom}else{var z,B="left"===o.position,W=d.padding;d.mirror?(L=B?"left":"right",z=W):(L=B?"right":"left",z=b+W),F=B?a.right-z:a.left+z;var N=a.getPixelForTick(n);N+=i.aliasPixel(s),R=a.getPixelForTick(n,c.offsetGridLines),v=C,y=D,M=e.left,_=e.right,x=w=P=T=N}S.push({tx1:v,ty1:x,tx2:y,ty2:w,x1:M,y1:P,x2:_,y2:T,labelX:F,labelY:R,glWidth:s,glColor:h,glBorderDash:g,glBorderDashOffset:m,rotation:-1*k,label:t,textBaseline:V,textAlign:L})}}}),i.each(S,function(t){if(c.display&&(s.save(),s.lineWidth=t.glWidth,s.strokeStyle=t.glColor,s.setLineDash&&(s.setLineDash(t.glBorderDash),s.lineDashOffset=t.glBorderDashOffset),s.beginPath(),c.drawTicks&&(s.moveTo(t.tx1,t.ty1),s.lineTo(t.tx2,t.ty2)),c.drawOnChartArea&&(s.moveTo(t.x1,t.y1),s.lineTo(t.x2,t.y2)),s.stroke(),s.restore()),d.display){s.save(),s.translate(t.labelX,t.labelY),s.rotate(t.rotation),s.font=v.font,s.textBaseline=t.textBaseline,s.textAlign=t.textAlign;var e=t.label;if(i.isArray(e))for(var n=0,a=0;n<e.length;++n)s.fillText(""+e[n],0,a),a+=1.5*v.size;else s.fillText(e,0,0);s.restore()}}),h.display){var P,_,T=0;if(p)P=a.left+(a.right-a.left)/2,_="bottom"===o.position?a.bottom-y.size/2:a.top+y.size/2;else{var F="left"===o.position;P=F?a.left+y.size/2:a.right-y.size/2,_=a.top+(a.bottom-a.top)/2,T=F?-.5*Math.PI:.5*Math.PI}s.save(),s.translate(P,_),s.rotate(T),s.textAlign="center",s.textBaseline="middle",s.fillStyle=x,s.font=y.font,s.fillText(h.labelString,0,0),s.restore()}if(c.drawBorder){s.lineWidth=i.getValueAtIndexOrDefault(c.lineWidth,0),s.strokeStyle=i.getValueAtIndexOrDefault(c.color,0);var R=a.left,L=a.right,V=a.top,O=a.bottom,z=i.aliasPixel(s.lineWidth);p?(V=O="top"===o.position?a.bottom:a.top,V+=z,O+=z):(R=L="left"===o.position?a.right:a.left,R+=z,L+=z),s.beginPath(),s.moveTo(R,V),s.lineTo(L,O),s.stroke()}}}})}},{}],32:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,n,i){this.constructors[t]=n,this.defaults[t]=e.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(n){return this.defaults.hasOwnProperty(n)?e.scaleMerge(t.defaults.scale,this.defaults[n]):{}},updateScaleDefaults:function(t,n){var i=this.defaults;i.hasOwnProperty(t)&&(i[t]=e.extend(i[t],n))},addScalesToLayout:function(n){e.each(n.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,t.layoutService.addBox(n,e)})}}}},{}],33:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.Ticks={generators:{linear:function(t,n){var i,a=[];if(t.stepSize&&t.stepSize>0)i=t.stepSize;else{var o=e.niceNum(n.max-n.min,!1);i=e.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(n.min/i)*i,l=Math.ceil(n.max/i)*i;t.min&&t.max&&t.stepSize&&e.almostWhole((t.max-t.min)/t.stepSize,i/1e3)&&(r=t.min,l=t.max);var s=(l-r)/i;s=e.almostEquals(s,Math.round(s),i/1e3)?Math.round(s):Math.ceil(s),a.push(void 0!==t.min?t.min:r);for(var u=1;u<s;++u)a.push(r+u*i);return a.push(void 0!==t.max?t.max:l),a},logarithmic:function(t,n){var i,a,o=[],r=e.getValueOrDefault,l=r(t.min,Math.pow(10,Math.floor(e.log10(n.min)))),s=Math.floor(e.log10(n.max)),u=Math.ceil(n.max/Math.pow(10,s));0===l?(i=Math.floor(e.log10(n.minNotZero)),a=Math.floor(n.minNotZero/Math.pow(10,i)),o.push(l),l=a*Math.pow(10,i)):(i=Math.floor(e.log10(l)),a=Math.floor(l/Math.pow(10,i)));do{o.push(l),10===++a&&(a=1,++i),l=a*Math.pow(10,i)}while(i<s||i===s&&a<u);var d=r(t.max,l);return o.push(d),o}},formatters:{values:function(t){return e.isArray(t)?t:""+t},linear:function(t,n,i){var a=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=e.log10(Math.abs(a)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,n,i){var a=t/Math.pow(10,Math.floor(e.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===n||n===i.length-1?t.toExponential():""}}}}},{}],34:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){var n=o.color(t);return n.alpha(e*n.alpha()).rgbaString()}function n(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function i(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a,x:t._model.x,y:t._model.y}}function a(e){var n=t.defaults.global,i=o.getValueOrDefault;return{xPadding:e.xPadding,yPadding:e.yPadding,xAlign:e.xAlign,yAlign:e.yAlign,bodyFontColor:e.bodyFontColor,_bodyFontFamily:i(e.bodyFontFamily,n.defaultFontFamily),_bodyFontStyle:i(e.bodyFontStyle,n.defaultFontStyle),_bodyAlign:e.bodyAlign,bodyFontSize:i(e.bodyFontSize,n.defaultFontSize),bodySpacing:e.bodySpacing,titleFontColor:e.titleFontColor,_titleFontFamily:i(e.titleFontFamily,n.defaultFontFamily),_titleFontStyle:i(e.titleFontStyle,n.defaultFontStyle),titleFontSize:i(e.titleFontSize,n.defaultFontSize),_titleAlign:e.titleAlign,titleSpacing:e.titleSpacing,titleMarginBottom:e.titleMarginBottom,footerFontColor:e.footerFontColor,_footerFontFamily:i(e.footerFontFamily,n.defaultFontFamily),_footerFontStyle:i(e.footerFontStyle,n.defaultFontStyle),footerFontSize:i(e.footerFontSize,n.defaultFontSize),_footerAlign:e.footerAlign,footerSpacing:e.footerSpacing,footerMarginTop:e.footerMarginTop,caretSize:e.caretSize,cornerRadius:e.cornerRadius,backgroundColor:e.backgroundColor,opacity:0,legendColorBackground:e.multiKeyBackground,displayColors:e.displayColors,borderColor:e.borderColor,borderWidth:e.borderWidth}}var o=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,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,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?n=o.xLabel:a>0&&o.index<a&&(n=i[o.index])}return n},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n&&(n+=": "),n+=t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}},t.Tooltip=t.Element.extend({initialize:function(){this._model=a(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),o=e.afterTitle.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};n(o.before,a.beforeLabel.call(i,t,e)),n(o.lines,a.label.call(i,t,e)),n(o.after,a.afterLabel.call(i,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),o=e.afterFooter.apply(t,arguments),r=[];return r=n(r,i),r=n(r,a),r=n(r,o)},update:function(e){var n,r,l=this,s=l._options,u=l._model,d=l._model=a(s),c=l._active,h=l._data,f={xAlign:u.xAlign,yAlign:u.yAlign},g={x:u.x,y:u.y},p={width:u.width,height:u.height},m={x:u.caretX,y:u.caretY};if(c.length){d.opacity=1;var v=[];m=t.Tooltip.positioners[s.position](c,l._eventPosition);var b=[];for(n=0,r=c.length;n<r;++n)b.push(i(c[n]));s.filter&&(b=b.filter(function(t){return s.filter(t,h)})),s.itemSort&&(b=b.sort(function(t,e){return s.itemSort(t,e,h)})),o.each(b,function(t){v.push(s.callbacks.labelColor.call(l,t,l._chart))}),d.title=l.getTitle(b,h),d.beforeBody=l.getBeforeBody(b,h),d.body=l.getBody(b,h),d.afterBody=l.getAfterBody(b,h),d.footer=l.getFooter(b,h),d.x=Math.round(m.x),d.y=Math.round(m.y),d.caretPadding=s.caretPadding,d.labelColors=v,d.dataPoints=b,p=function(t,e){var n=t._chart.ctx,i=2*e.yPadding,a=0,r=e.body,l=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);l+=e.beforeBody.length+e.afterBody.length;var s=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;i+=s*d,i+=s?(s-1)*e.titleSpacing:0,i+=s?e.titleMarginBottom:0,i+=l*c,i+=l?(l-1)*e.bodySpacing:0,i+=u?e.footerMarginTop:0,i+=u*h,i+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,n.measureText(t).width+f)};return n.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),n.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,n.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),a+=2*e.xPadding,{width:a,height:i}}(this,d),g=function(t,e,n){var i=t.x,a=t.y,o=t.caretSize,r=t.caretPadding,l=t.cornerRadius,s=n.xAlign,u=n.yAlign,d=o+r,c=l+r;return"right"===s?i-=e.width:"center"===s&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===s?i+=d:"right"===s&&(i-=d):"left"===s?i-=c:"right"===s&&(i+=c),{x:i,y:a}}(d,p,f=function(t,e){var n=t._model,i=t._chart,a=t._chart.chartArea,o="center",r="center";n.y<e.height?r="top":n.y>i.height-e.height&&(r="bottom");var l,s,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===r?(l=function(t){return t<=h},s=function(t){return t>h}):(l=function(t){return t<=e.width/2},s=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},l(n.x)?(o="left",u(n.x)&&(o="center",r=c(n.y))):s(n.x)&&(o="right",d(n.x)&&(o="center",r=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:o,yAlign:g.yAlign?g.yAlign:r}}(this,p))}else d.opacity=0;return d.xAlign=f.xAlign,d.yAlign=f.yAlign,d.x=g.x,d.y=g.y,d.width=p.width,d.height=p.height,d.caretX=m.x,d.caretY=m.y,l._model=d,e&&s.custom&&s.custom.call(l,d),l},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,o,r,l,s,u=n.caretSize,d=n.cornerRadius,c=n.xAlign,h=n.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===h)l=g+m/2,"left"===c?(i=f,a=i-u,o=i,r=l+u,s=l-u):(i=f+p,a=i+u,o=i,r=l-u,s=l+u);else if("left"===c?(a=f+d+u,i=a-u,o=a+u):"right"===c?(a=f+p-d-u,i=a-u,o=a+u):(a=f+p/2,i=a-u,o=a+u),"top"===h)r=g,l=r-u,s=r;else{l=(r=g+m)+u,s=r;var v=o;o=i,i=v}return{x1:i,x2:a,x3:o,y1:r,y2:l,y3:s}},drawTitle:function(t,n,i,a){var r=n.title;if(r.length){i.textAlign=n._titleAlign,i.textBaseline="top";var l=n.titleFontSize,s=n.titleSpacing;i.fillStyle=e(n.titleFontColor,a),i.font=o.fontString(l,n._titleFontStyle,n._titleFontFamily);var u,d;for(u=0,d=r.length;u<d;++u)i.fillText(r[u],t.x,t.y),t.y+=l+s,u+1===r.length&&(t.y+=n.titleMarginBottom-s)}},drawBody:function(t,n,i,a){var r=n.bodyFontSize,l=n.bodySpacing,s=n.body;i.textAlign=n._bodyAlign,i.textBaseline="top";var u=e(n.bodyFontColor,a);i.fillStyle=u,i.font=o.fontString(r,n._bodyFontStyle,n._bodyFontFamily);var d=0,c=function(e){i.fillText(e,t.x+d,t.y),t.y+=r+l};o.each(n.beforeBody,c);var h=n.displayColors;d=h?r+2:0,o.each(s,function(l,s){o.each(l.before,c),o.each(l.lines,function(o){h&&(i.fillStyle=e(n.legendColorBackground,a),i.fillRect(t.x,t.y,r,r),i.strokeStyle=e(n.labelColors[s].borderColor,a),i.strokeRect(t.x,t.y,r,r),i.fillStyle=e(n.labelColors[s].backgroundColor,a),i.fillRect(t.x+1,t.y+1,r-2,r-2),i.fillStyle=u),c(o)}),o.each(l.after,c)}),d=0,o.each(n.afterBody,c),t.y-=l},drawFooter:function(t,n,i,a){var r=n.footer;r.length&&(t.y+=n.footerMarginTop,i.textAlign=n._footerAlign,i.textBaseline="top",i.fillStyle=e(n.footerFontColor,a),i.font=o.fontString(n.footerFontSize,n._footerFontStyle,n._footerFontFamily),o.each(r,function(e){i.fillText(e,t.x,t.y),t.y+=n.footerFontSize+n.footerSpacing}))},drawBackground:function(t,n,i,a,o){i.fillStyle=e(n.backgroundColor,o),i.strokeStyle=e(n.borderColor,o),i.lineWidth=n.borderWidth;var r=n.xAlign,l=n.yAlign,s=t.x,u=t.y,d=a.width,c=a.height,h=n.cornerRadius;i.beginPath(),i.moveTo(s+h,u),"top"===l&&this.drawCaret(t,a),i.lineTo(s+d-h,u),i.quadraticCurveTo(s+d,u,s+d,u+h),"center"===l&&"right"===r&&this.drawCaret(t,a),i.lineTo(s+d,u+c-h),i.quadraticCurveTo(s+d,u+c,s+d-h,u+c),"bottom"===l&&this.drawCaret(t,a),i.lineTo(s+h,u+c),i.quadraticCurveTo(s,u+c,s,u+c-h),"center"===l&&"left"===r&&this.drawCaret(t,a),i.lineTo(s,u+h),i.quadraticCurveTo(s,u,s+h,u),i.closePath(),i.fill(),n.borderWidth>0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!o.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,o=0;for(e=0,n=t.length;e<n;++e){var r=t[e];if(r&&r.hasValue()){var l=r.tooltipPosition();i+=l.x,a+=l.y,++o}}return{x:Math.round(i/o),y:Math.round(a/o)}},nearest:function(t,e){var n,i,a,r=e.x,l=e.y,s=Number.POSITIVE_INFINITY;for(i=0,a=t.length;i<a;++i){var u=t[i];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<s&&(s=c,n=u)}}if(n){var h=n.tooltipPosition();r=h.x,l=h.y}return{x:r,y:l}}}}},{}],35:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global;n.elements.arc={backgroundColor:n.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,n){var i=this._view;if(i){for(var a=e.getAngleFromPoint(i,{x:t,y:n}),o=a.angle,r=a.distance,l=i.startAngle,s=i.endAngle;s<l;)s+=2*Math.PI;for(;o>s;)o-=2*Math.PI;for(;o<l;)o+=2*Math.PI;var u=o>=l&&o<=s,d=r>=i.innerRadius&&r<=i.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],36:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:n.defaultColor,borderWidth:3,borderColor:n.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0},t.elements.Line=t.Element.extend({draw:function(){var t,i,a,o,r=this,l=r._view,s=r._chart.ctx,u=l.spanGaps,d=r._children.slice(),c=n.elements.line,h=-1;for(r._loop&&d.length&&d.push(d[0]),s.save(),s.lineCap=l.borderCapStyle||c.borderCapStyle,s.setLineDash&&s.setLineDash(l.borderDash||c.borderDash),s.lineDashOffset=l.borderDashOffset||c.borderDashOffset,s.lineJoin=l.borderJoinStyle||c.borderJoinStyle,s.lineWidth=l.borderWidth||c.borderWidth,s.strokeStyle=l.borderColor||n.defaultColor,s.beginPath(),h=-1,t=0;t<d.length;++t)i=d[t],a=e.previousItem(d,t),o=i._view,0===t?o.skip||(s.moveTo(o.x,o.y),h=t):(a=-1===h?a:d[h],o.skip||(h!==t-1&&!u||-1===h?s.moveTo(o.x,o.y):e.canvas.lineTo(s,a._view,i._view),h=t));s.stroke(),s.restore()}})}},{}],37:[function(t,e,n){"use strict";e.exports=function(t){function e(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2)}var n=t.helpers,i=t.defaults.global,a=i.defaultColor;i.elements.point={radius:3,pointStyle:"circle",backgroundColor:a,borderWidth:1,borderColor:a,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var n=this._view;return!!n&&Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2)},inLabelRange:e,inXRange:e,inYRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.y,2)<Math.pow(e.radius+e.hitRadius,2)},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(e){var o=this._view,r=this._model,l=this._chart.ctx,s=o.pointStyle,u=o.radius,d=o.x,c=o.y,h=t.helpers.color,f=1.01,g=0;o.skip||(l.strokeStyle=o.borderColor||a,l.lineWidth=n.getValueOrDefault(o.borderWidth,i.elements.point.borderWidth),l.fillStyle=o.backgroundColor||a,void 0!==e&&(r.x<e.left||e.right*f<r.x||r.y<e.top||e.bottom*f<r.y)&&(r.x<e.left?g=(d-r.x)/(e.left-r.x):e.right*f<r.x?g=(r.x-d)/(r.x-e.right):r.y<e.top?g=(c-r.y)/(e.top-r.y):e.bottom*f<r.y&&(g=(r.y-c)/(r.y-e.bottom)),g=Math.round(100*g)/100,l.strokeStyle=h(l.strokeStyle).alpha(g).rgbString(),l.fillStyle=h(l.fillStyle).alpha(g).rgbString()),t.canvasHelpers.drawPoint(l,s,u,d,c))}})}},{}],38:[function(t,e,n){"use strict";e.exports=function(t){function e(t){return void 0!==t._view.width}function n(t){var n,i,a,o,r=t._view;if(e(t)){var l=r.width/2;n=r.x-l,i=r.x+l,a=Math.min(r.y,r.base),o=Math.max(r.y,r.base)}else{var s=r.height/2;n=Math.min(r.x,r.base),i=Math.max(r.x,r.base),a=r.y-s,o=r.y+s}return{left:n,top:a,right:i,bottom:o}}var i=t.defaults.global;i.elements.rectangle={backgroundColor:i.defaultColor,borderWidth:0,borderColor:i.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return v[(b+t)%4]}var e,n,i,a,o,r,l,s=this._chart.ctx,u=this._view,d=u.borderWidth;if(u.horizontal?(e=u.base,n=u.x,i=u.y-u.height/2,a=u.y+u.height/2,o=n>e?1:-1,r=1,l=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,a=u.base,o=1,r=a>i?1:-1,l=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==l?h*o:0),g=n+("right"!==l?-h*o:0),p=i+("top"!==l?h*r:0),m=a+("bottom"!==l?-h*r:0);f!==g&&(i=p,a=m),p!==m&&(e=f,n=g)}s.beginPath(),s.fillStyle=u.backgroundColor,s.strokeStyle=u.borderColor,s.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],b=["bottom","left","top","right"].indexOf(l,0);-1===b&&(b=0);var x=t(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=t(y),s.lineTo(x[0],x[1]);s.fill(),d&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=!1;if(this._view){var a=n(this);i=t>=a.left&&t<=a.right&&e>=a.top&&e<=a.bottom}return i},inLabelRange:function(t,i){var a=this;if(!a._view)return!1;var o=n(a);return e(a)?t>=o.left&&t<=o.right:i>=o.top&&i<=o.bottom},inXRange:function(t){var e=n(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=n(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,n,i=this._view;return e(this)?(t=i.x,n=(i.y+i.base)/2):(t=(i.x+i.base)/2,n=i.y),{x:t,y:n}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],39:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){var n=r.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}function n(t,n){var i=t.style,a=t.getAttribute("height"),o=t.getAttribute("width");if(t._chartjs={initial:{height:a,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",null===o||""===o){var r=e(t,"width");void 0!==r&&(t.width=r)}if(null===a||""===a)if(""===t.style.height)t.height=t.width/(n.options.aspectRatio||2);else{var l=e(t,"height");void 0!==r&&(t.height=l)}return t}function i(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function a(t,e){var n=l[t.type]||t.type,a=r.getRelativePosition(t,e);return i(n,e,a.x,a.y,t)}function o(t,e,n){var a=t._chartjs={ticking:!1};a.resizer=function(t){var e=document.createElement("iframe");return e.className="chartjs-hidden-iframe",e.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;",e.tabIndex=-1,r.addEvent(e,"load",function(){r.addEvent(e.contentWindow||e,"resize",t),t()}),e}(function(){a.ticking||(a.ticking=!0,r.requestAnimFrame.call(window,function(){if(a.resizer)return a.ticking=!1,e(i("resize",n))}))}),t.insertBefore(a.resizer,t.firstChild)}var r=t.helpers,l={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};return{acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(n(t,e),i):null},releaseContext:function(t){var e=t.canvas;if(e._chartjs){var n=e._chartjs.initial;["height","width"].forEach(function(t){var i=n[t];void 0===i||null===i?e.removeAttribute(t):e.setAttribute(t,i)}),r.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e._chartjs}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var l=n._chartjs||(n._chartjs={}),s=(l.proxies||(l.proxies={}))[t.id+"_"+e]=function(e){n(a(e,t))};r.addEvent(i,e,s)}else o(i.parentNode,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n._chartjs||{}).proxies||{})[t.id+"_"+e];a&&r.removeEvent(i,e,a)}else!function(t){if(t&&t._chartjs){var e=t._chartjs.resizer;e&&(e.parentNode.removeChild(e),t._chartjs.resizer=null),delete t._chartjs}}(i.parentNode)}}}},{}],40:[function(t,e,n){"use strict";var i=t(39);e.exports=function(t){t.platform={acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},t.helpers.extend(t.platform,i(t))}},{39:39}],41:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e,n){var i,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(i=parseFloat(o,10),isFinite(i)&&Math.floor(i)===i)return"-"!==o[0]&&"+"!==o[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function n(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?o=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?o=n.scaleZero:i.getBasePosition?o=i.getBasePosition():i.getBasePixel&&(o=i.getBasePixel()),void 0!==o&&null!==o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return e=i.isHorizontal(),{x:e?o:null,y:e?null:o}}return null}function i(t,e,n){var i,a=t[e].fill,o=[e];if(!n)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;o.push(a),a=i.fill}return!1}function a(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function o(t){return t&&!t.skip}function r(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o<i;++o)u.canvas.lineTo(t,e[o-1],e[o]);for(t.lineTo(n[a-1].x,n[a-1].y),o=a-1;o>0;--o)u.canvas.lineTo(t,n[o],n[o-1],!0)}}function l(t,e,n,i,a,l){var s,u,d,c,h,f,g,p=e.length,m=i.spanGaps,v=[],b=[],x=0,y=0;for(t.beginPath(),s=0,u=p+!!l;s<u;++s)d=s%p,c=e[d]._view,h=n(c,d,i),f=o(c),g=o(h),f&&g?(x=v.push(c),y=b.push(h)):x&&y&&(m?(f&&v.push(c),g&&b.push(h)):(r(t,v,b,x,y),x=y=0,v=[],b=[]));r(t,v,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}t.defaults.global.plugins.filler={propagate:!0};var s=t.defaults,u=t.helpers,d={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[];return a.length?function(t,e){return a[e]._view||null}:null},boundary:function(t){var e=t.boundary,n=e?e.x:null,i=e?e.y:null;return function(t){return{x:null===n?t.x:n,y:null===i?t.y:i}}}};return{id:"filler",afterDatasetsUpdate:function(o,r){var l,s,u,d,c=(o.data.datasets||[]).length,h=r.propagate,f=[];for(s=0;s<c;++s)l=o.getDatasetMeta(s),u=l.dataset,d=null,u&&u._model&&u instanceof t.elements.Line&&(d={visible:o.isDatasetVisible(s),fill:e(u,s,c),chart:o,el:u}),l.$filler=d,f.push(d);for(s=0;s<c;++s)(d=f[s])&&(d.fill=i(f,s,h),d.boundary=n(d),d.mapper=a(d))},beforeDatasetDraw:function(t,e){var n=e.meta.$filler;if(n){var i=n.el,a=i._view,o=i._children||[],r=n.mapper,u=a.backgroundColor||s.global.defaultColor;r&&u&&o.length&&l(t.ctx,o,r,a,u,i._loop)}}}}},{}],42:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});a.configure(e,i,n),a.addBox(e,i),e.legend=i}var i=t.helpers,a=t.layoutService,o=i.noop;return t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return i.isArray(e.datasets)?e.datasets.map(function(e,n){return{text:e.label,fillStyle:i.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(n),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:n}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){i.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:function(){var t=this,e=t.options.labels,n=e.generateLabels.call(t,t.chart);e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:o,beforeFit:o,fit:function(){var n=this,a=n.options,o=a.labels,r=a.display,l=n.ctx,s=t.defaults.global,u=i.getValueOrDefault,d=u(o.fontSize,s.defaultFontSize),c=u(o.fontStyle,s.defaultFontStyle),h=u(o.fontFamily,s.defaultFontFamily),f=i.fontString(d,c,h),g=n.legendHitBoxes=[],p=n.minSize,m=n.isHorizontal();if(m?(p.width=n.maxWidth,p.height=r?10:0):(p.width=r?10:0,p.height=n.maxHeight),r)if(l.font=f,m){var v=n.lineWidths=[0],b=n.legendItems.length?d+o.padding:0;l.textAlign="left",l.textBaseline="top",i.each(n.legendItems,function(t,i){var a=e(o,d)+d/2+l.measureText(t.text).width;v[v.length-1]+a+o.padding>=n.width&&(b+=d+o.padding,v[v.length]=n.left),g[i]={left:0,top:0,width:a,height:d},v[v.length-1]+=a+o.padding}),p.height+=b}else{var x=o.padding,y=n.columnWidths=[],k=o.padding,w=0,M=0,S=d+x;i.each(n.legendItems,function(t,n){var i=e(o,d)+d/2+l.measureText(t.text).width;M+S>p.height&&(k+=w+o.padding,y.push(w),w=0,M=0),w=Math.max(w,i),M+=S,g[n]={left:0,top:0,width:i,height:d}}),k+=w,y.push(w),p.width+=k}n.width=p.width,n.height=p.height},afterFit:o,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var n=this,a=n.options,o=a.labels,r=t.defaults.global,l=r.elements.line,s=n.width,u=n.lineWidths;if(a.display){var d,c=n.ctx,h=i.getValueOrDefault,f=h(o.fontColor,r.defaultFontColor),g=h(o.fontSize,r.defaultFontSize),p=h(o.fontStyle,r.defaultFontStyle),m=h(o.fontFamily,r.defaultFontFamily),v=i.fontString(g,p,m);c.textAlign="left",c.textBaseline="top",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var b=e(o,g),x=n.legendHitBoxes,y=function(e,n,i){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(i.fillStyle,r.defaultColor),c.lineCap=h(i.lineCap,l.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,l.borderDashOffset),c.lineJoin=h(i.lineJoin,l.borderJoinStyle),c.lineWidth=h(i.lineWidth,l.borderWidth),c.strokeStyle=h(i.strokeStyle,r.defaultColor);var o=0===h(i.lineWidth,l.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,l.borderDash)),a.labels&&a.labels.usePointStyle){var s=g*Math.SQRT2/2,u=s/Math.SQRT2,d=e+u,f=n+u;t.canvasHelpers.drawPoint(c,i.pointStyle,s,d,f)}else o||c.strokeRect(e,n,b,g),c.fillRect(e,n,b,g);c.restore()}},k=n.isHorizontal();d=k?{x:n.left+(s-u[0])/2,y:n.top+o.padding,line:0}:{x:n.left+o.padding,y:n.top+o.padding,line:0};var w=g+o.padding;i.each(n.legendItems,function(t,e){var i=c.measureText(t.text).width,a=b+g/2+i,r=d.x,l=d.y;k?r+a>=s&&(l=d.y+=w,d.line++,r=d.x=n.left+(s-u[d.line])/2):l+w>n.bottom&&(r=d.x=r+n.columnWidths[d.line]+o.padding,l=d.y=n.top+o.padding,d.line++),y(r,l,t),x[e].left=r,x[e].top=l,function(t,e,n,i){c.fillText(n.text,b+g/2+t,e),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(b+g/2+t,e+g/2),c.lineTo(b+g/2+t+i,e+g/2),c.stroke())}(r,l,t,i),k?d.x+=a+o.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var l=e.legendHitBoxes,s=0;s<l.length;++s){var u=l[s];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[s]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[s]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(e){var o=e.options.legend,r=e.legend;o?(o=i.configMerge(t.defaults.global.legend,o),r?(a.configure(e,r,o),r.options=o):n(e,o)):r&&(a.removeBox(e,r),delete e.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{}],43:[function(t,e,n){"use strict";e.exports=function(t){function e(e,n){var a=new t.Title({ctx:e.ctx,options:n,chart:e});i.configure(e,a,n),i.addBox(e,a),e.titleBlock=a}var n=t.helpers,i=t.layoutService,a=n.noop;return t.defaults.global.title={display:!1,position:"top",fullWidth:!0,weight:2e3,fontStyle:"bold",padding:10,text:""},t.Title=t.Element.extend({initialize:function(t){n.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:a,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:a,beforeSetDimensions:a,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:a,beforeBuildLabels:a,buildLabels:a,afterBuildLabels:a,beforeFit:a,fit:function(){var e=this,i=n.getValueOrDefault,a=e.options,o=t.defaults.global,r=a.display,l=i(a.fontSize,o.defaultFontSize),s=e.minSize;e.isHorizontal()?(s.width=e.maxWidth,s.height=r?l+2*a.padding:0):(s.width=r?l+2*a.padding:0,s.height=e.maxHeight),e.width=s.width,e.height=s.height},afterFit:a,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var e=this,i=e.ctx,a=n.getValueOrDefault,o=e.options,r=t.defaults.global;if(o.display){var l,s,u,d=a(o.fontSize,r.defaultFontSize),c=a(o.fontStyle,r.defaultFontStyle),h=a(o.fontFamily,r.defaultFontFamily),f=n.fontString(d,c,h),g=0,p=e.top,m=e.left,v=e.bottom,b=e.right;i.fillStyle=a(o.fontColor,r.defaultFontColor),i.font=f,e.isHorizontal()?(l=m+(b-m)/2,s=p+(v-p)/2,u=b-m):(l="left"===o.position?m+d/2:b-d/2,s=p+(v-p)/2,u=v-p,g=Math.PI*("left"===o.position?-.5:.5)),i.save(),i.translate(l,s),i.rotate(g),i.textAlign="center",i.textBaseline="middle",i.fillText(o.text,0,0,u),i.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,r=a.titleBlock;o?(o=n.configMerge(t.defaults.global.title,o),r?(i.configure(a,r,o),r.options=o):e(a,o)):r&&(t.layoutService.removeBox(a,r),delete a.titleBlock)}}}},{}],44:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,n=t.getLabels();t.minIndex=0,t.maxIndex=n.length-1;var i;void 0!==t.options.ticks.min&&(i=e.indexOf(n,t.options.ticks.min),t.minIndex=-1!==i?i:t.minIndex),void 0!==t.options.ticks.max&&(i=e.indexOf(n,t.options.ticks.max),t.maxIndex=-1!==i?i:t.maxIndex),t.min=n[t.minIndex],t.max=n[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e,n,i){var a,o=this,r=Math.max(o.maxIndex+1-o.minIndex-(o.options.gridLines.offsetGridLines?0:1),1);if(void 0!==t&&null!==t&&(a=o.isHorizontal()?t.x:t.y),void 0!==a||void 0!==t&&isNaN(e)){var l=o.getLabels();t=a||t;var s=l.indexOf(t);e=-1!==s?s:e}if(o.isHorizontal()){var u=o.width/r,d=u*(e-o.minIndex);return(o.options.gridLines.offsetGridLines&&i||o.maxIndex===o.minIndex&&i)&&(d+=u/2),o.left+Math.round(d)}var c=o.height/r,h=c*(e-o.minIndex);return o.options.gridLines.offsetGridLines&&i&&(h+=c/2),o.top+Math.round(h)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e=this,n=Math.max(e.ticks.length-(e.options.gridLines.offsetGridLines?0:1),1),i=e.isHorizontal(),a=(i?e.width:e.height)/n;return t-=i?e.left:e.top,e.options.gridLines.offsetGridLines&&(t-=a/2),t<=0?0:Math.round(t/a)},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,{position:"bottom"})}},{}],45:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:t.Ticks.formatters.linear}},i=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return r?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=n.chart,o=a.data.datasets,r=n.isHorizontal();n.min=null,n.max=null;var l=i.stacked;if(void 0===l&&e.each(o,function(e,n){if(!l){var i=a.getDatasetMeta(n);a.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(l=!0)}}),i.stacked||l){var s={};e.each(o,function(o,r){var l=a.getDatasetMeta(r),u=[l.type,void 0===i.stacked&&void 0===l.stack?r:"",l.stack].join(".");void 0===s[u]&&(s[u]={positiveValues:[],negativeValues:[]});var d=s[u].positiveValues,c=s[u].negativeValues;a.isDatasetVisible(r)&&t(l)&&e.each(o.data,function(t,e){var a=+n.getRightValue(t);isNaN(a)||l.data[e].hidden||(d[e]=d[e]||0,c[e]=c[e]||0,i.relativePoints?d[e]=100:a<0?c[e]+=a:d[e]+=a)})}),e.each(s,function(t){var i=t.positiveValues.concat(t.negativeValues),a=e.min(i),o=e.max(i);n.min=null===n.min?a:Math.min(n.min,a),n.max=null===n.max?o:Math.max(n.max,o)})}else e.each(o,function(i,o){var r=a.getDatasetMeta(o);a.isDatasetVisible(o)&&t(r)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i))})});n.min=isFinite(n.min)?n.min:0,n.max=isFinite(n.max)?n.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var n,i=this,a=i.options.ticks;if(i.isHorizontal())n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.width/50));else{var o=e.getValueOrDefault(a.fontSize,t.defaults.global.defaultFontSize);n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.height/(2*o)))}return n},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),o=n.end-i;return n.isHorizontal()?(e=n.left+n.width/o*(a-i),Math.round(e)):(e=n.bottom-n.height/o*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",i,n)}},{}],46:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=e.noop;t.LinearScaleBase=t.Scale.extend({handleTickRangeOptions:function(){var t=this,n=t.options.ticks;if(n.beginAtZero){var i=e.sign(t.min),a=e.sign(t.max);i<0&&a<0?t.max=0:i>0&&a>0&&(t.min=0)}void 0!==n.min?t.min=n.min:void 0!==n.suggestedMin&&(null===t.min?t.min=n.suggestedMin:t.min=Math.min(t.min,n.suggestedMin)),void 0!==n.max?t.max=n.max:void 0!==n.suggestedMax&&(null===t.max?t.max=n.suggestedMax:t.max=Math.max(t.max,n.suggestedMax)),t.min===t.max&&(t.max++,n.beginAtZero||t.min--)},getTickLimit:n,handleDirectionalChanges:n,buildTicks:function(){var n=this,i=n.options.ticks,a=n.getTickLimit(),o={maxTicks:a=Math.max(2,a),min:i.min,max:i.max,stepSize:e.getValueOrDefault(i.fixedStepSize,i.stepSize)},r=n.ticks=t.Ticks.generators.linear(o,n);n.handleDirectionalChanges(),n.max=e.max(r),n.min=e.min(r),i.reverse?(r.reverse(),n.start=n.max,n.end=n.min):(n.start=n.min,n.end=n.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{}],47:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:t.Ticks.formatters.logarithmic}},i=t.Scale.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=i.ticks,o=n.chart,r=o.data.datasets,l=e.getValueOrDefault,s=n.isHorizontal();n.min=null,n.max=null,n.minNotZero=null;var u=i.stacked;if(void 0===u&&e.each(r,function(e,n){if(!u){var i=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),i.stacked||u){var d={};e.each(r,function(a,r){var l=o.getDatasetMeta(r),s=[l.type,void 0===i.stacked&&void 0===l.stack?r:"",l.stack].join(".");o.isDatasetVisible(r)&&t(l)&&(void 0===d[s]&&(d[s]=[]),e.each(a.data,function(t,e){var a=d[s],o=+n.getRightValue(t);isNaN(o)||l.data[e].hidden||(a[e]=a[e]||0,i.relativePoints?a[e]=100:a[e]+=o)}))}),e.each(d,function(t){var i=e.min(t),a=e.max(t);n.min=null===n.min?i:Math.min(n.min,i),n.max=null===n.max?a:Math.max(n.max,a)})}else e.each(r,function(i,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i),0!==i&&(null===n.minNotZero||i<n.minNotZero)&&(n.minNotZero=i))})});n.min=l(a.min,n.min),n.max=l(a.max,n.max),n.min===n.max&&(0!==n.min&&null!==n.min?(n.min=Math.pow(10,Math.floor(e.log10(n.min))-1),n.max=Math.pow(10,Math.floor(e.log10(n.max))+1)):(n.min=1,n.max=10))},buildTicks:function(){var n=this,i=n.options.ticks,a={min:i.min,max:i.max},o=n.ticks=t.Ticks.generators.logarithmic(a,n);n.isHorizontal()||o.reverse(),n.max=e.max(o),n.min=e.min(o),i.reverse?(o.reverse(),n.start=n.max,n.end=n.min):(n.start=n.min,n.end=n.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},getPixelForValue:function(t){var n,i,a,o=this,r=o.start,l=+o.getRightValue(t),s=o.options.ticks;return o.isHorizontal()?(a=e.log10(o.end)-e.log10(r),0===l?i=o.left:(n=o.width,i=o.left+n/a*(e.log10(l)-e.log10(r)))):(n=o.height,0!==r||s.reverse?0===o.end&&s.reverse?(a=e.log10(o.start)-e.log10(o.minNotZero),i=l===o.end?o.top:l===o.minNotZero?o.top+.02*n:o.top+.02*n+.98*n/a*(e.log10(l)-e.log10(o.minNotZero))):0===l?i=s.reverse?o.top:o.bottom:(a=e.log10(o.end)-e.log10(r),n=o.height,i=o.bottom-n/a*(e.log10(l)-e.log10(r))):(a=e.log10(o.end)-e.log10(o.minNotZero),i=l===r?o.bottom:l===o.minNotZero?o.bottom-.02*n:o.bottom-.02*n-.98*n/a*(e.log10(l)-e.log10(o.minNotZero)))),i},getValueForPixel:function(t){var n,i,a=this,o=e.log10(a.end)-e.log10(a.start);return a.isHorizontal()?(i=a.width,n=a.start*Math.pow(10,(t-a.left)*o/i)):(i=a.height,n=Math.pow(10,(a.bottom-t)*o/i)/a.start),n}});t.scaleService.registerScaleType("logarithmic",i,n)}},{}],48:[function(t,e,n){"use strict";e.exports=function(t){function e(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function n(t){var e=t.options.pointLabels,n=c.getValueOrDefault(e.fontSize,h.defaultFontSize),i=c.getValueOrDefault(e.fontStyle,h.defaultFontStyle),a=c.getValueOrDefault(e.fontFamily,h.defaultFontFamily);return{size:n,style:i,family:a,font:c.fontString(n,i,a)}}function i(t,e,n){return c.isArray(n)?{w:c.longestText(t,t.font,n),h:n.length*e+1.5*(n.length-1)*e}:{w:t.measureText(n).width,h:e}}function a(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:t<i||t>a?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function o(t){return 0===t||180===t?"center":t<180?"left":"right"}function r(t,e,n,i){if(c.isArray(e))for(var a=n.y,o=1.5*i,r=0;r<e.length;++r)t.fillText(e[r],n.x,a),a+=o;else t.fillText(e,n.x,n.y)}function l(t,e,n){90===t||270===t?n.y-=e.h/2:(t>270||t<90)&&(n.y-=e.h)}function s(t){var i=t.ctx,a=c.getValueOrDefault,s=t.options,u=s.angleLines,d=s.pointLabels;i.lineWidth=u.lineWidth,i.strokeStyle=u.color;var f=t.getDistanceFromCenterForValue(s.reverse?t.min:t.max),g=n(t);i.textBaseline="top";for(var p=e(t)-1;p>=0;p--){if(u.display){var m=t.getPointPosition(p,f);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(d.display){var v=t.getPointPosition(p,f+5),b=a(d.fontColor,h.defaultFontColor);i.font=g.font,i.fillStyle=b;var x=t.getIndexAngle(p),y=c.toDegrees(x);i.textAlign=o(y),l(y,t._pointLabelSizes[p],v),r(i,t.pointLabels[p]||"",v,g.size)}}}function u(t,n,i,a){var o=t.ctx;if(o.strokeStyle=c.getValueAtIndexOrDefault(n.color,a-1),o.lineWidth=c.getValueAtIndexOrDefault(n.lineWidth,a-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var r=e(t);if(0===r)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var s=1;s<r;s++)l=t.getPointPosition(s,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}function d(t){return c.isNumber(t)?t:0}var c=t.helpers,h=t.defaults.global,f={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:t.Ticks.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}},g=t.LinearScaleBase.extend({setDimensions:function(){var t=this,e=t.options,n=e.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var i=c.min([t.height,t.width]),a=c.getValueOrDefault(n.fontSize,h.defaultFontSize);t.drawingArea=e.display?i/2-(a/2+n.backdropPaddingY):i/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;c.each(e.data.datasets,function(a,o){if(e.isDatasetVisible(o)){var r=e.getDatasetMeta(o);c.each(a.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||r.data[a].hidden||(n=Math.min(o,n),i=Math.max(o,i))})}}),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,e=c.getValueOrDefault(t.fontSize,h.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*e)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){this.options.pointLabels.display?function(t){var o,r,l,s=n(t),u=Math.min(t.height/2,t.width/2),d={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=s.font,t._pointLabelSizes=[];var f=e(t);for(o=0;o<f;o++){l=t.getPointPosition(o,u),r=i(t.ctx,s.size,t.pointLabels[o]||""),t._pointLabelSizes[o]=r;var g=t.getIndexAngle(o),p=c.toDegrees(g)%360,m=a(p,l.x,r.w,0,180),v=a(p,l.y,r.h,90,270);m.start<d.l&&(d.l=m.start,h.l=g),m.end>d.r&&(d.r=m.end,h.r=g),v.start<d.t&&(d.t=v.start,h.t=g),v.end>d.b&&(d.b=v.end,h.b=g)}t.setReductions(u,d,h)}(this):function(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}(this)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),o=Math.max(e.r-i.width,0)/Math.sin(n.r),r=-e.t/Math.cos(n.t),l=-Math.max(e.b-i.height,0)/Math.cos(n.b);a=d(a),o=d(o),r=d(r),l=d(l),i.drawingArea=Math.min(Math.round(t-(a+o)/2),Math.round(t-(r+l)/2)),i.setCenterPoint(a,o,r,l)},setCenterPoint:function(t,e,n,i){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,l=n+a.drawingArea,s=a.height-i-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((l+s)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/e(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,a=c.getValueOrDefault;if(e.display){var o=t.ctx,r=a(i.fontSize,h.defaultFontSize),l=a(i.fontStyle,h.defaultFontStyle),d=a(i.fontFamily,h.defaultFontFamily),f=c.fontString(r,l,d);c.each(t.ticks,function(l,s){if(s>0||e.reverse){var d=t.getDistanceFromCenterForValue(t.ticksAsNumbers[s]),c=t.yCenter-d;if(n.display&&0!==s&&u(t,n,d,s),i.display){var g=a(i.fontColor,h.defaultFontColor);if(o.font=f,i.showLabelBackdrop){var p=o.measureText(l).width;o.fillStyle=i.backdropColor,o.fillRect(t.xCenter-p/2-i.backdropPaddingX,c-r/2-i.backdropPaddingY,p+2*i.backdropPaddingX,r+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=g,o.fillText(l,t.xCenter,c)}}}),(e.angleLines.display||e.pointLabels.display)&&s(t)}}});t.scaleService.registerScaleType("radialLinear",g,f)}},{}],49:[function(t,e,n){"use strict";var i=t(1);i="function"==typeof i?i:window.moment,e.exports=function(t){function e(t,e){var n=t.options.time;if("string"==typeof n.parser)return i(e,n.parser);if("function"==typeof n.parser)return n.parser(e);if("function"==typeof e.getMonth||"number"==typeof e)return i(e);if(e.isValid&&e.isValid())return e;var a=n.format;return"string"!=typeof a&&a.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser."),a(e)):i(e,a)}function n(t,e,n,i){for(var a,o=Object.keys(r),l=o.length,s=o.indexOf(t);s<l;s++){a=o[s];var u=r[a],d=u.steps&&u.steps[u.steps.length-1]||u.maxStep;if(void 0===d||Math.ceil((n-e)/(d*u.size))<=i)break}return a}function a(t,e,n,i){var a=r[n],o=a.size,l=Math.ceil((e-t)/o),s=1,u=e-t;if(a.steps)for(var d=a.steps.length,c=0;c<d&&l>i;c++)s=a.steps[c],l=Math.ceil(u/(o*s));else for(;l>i&&i>0;)++s,l=Math.ceil(u/(o*s));return s}var o=t.helpers,r={millisecond:{size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{size:1e3,steps:[1,2,5,10,30]},minute:{size:6e4,steps:[1,2,5,10,30]},hour:{size:36e5,steps:[1,2,3,6,12]},day:{size:864e5,steps:[1,2,5]},week:{size:6048e5,maxStep:4},month:{size:2628e6,maxStep:3},quarter:{size:7884e6,maxStep:4},year:{size:3154e7,maxStep:!1}};t.Ticks.generators.time=function(t,e){var n,a,o=t.isoWeekday;return"week"===t.unit&&!1!==o?(n=i(e.min).startOf("isoWeek").isoWeekday(o).valueOf(),a=i(e.max).startOf("isoWeek").isoWeekday(o),e.max-a>0&&a.add(1,"week"),a=a.valueOf()):(n=i(e.min).startOf(t.unit).valueOf(),a=i(e.max).startOf(t.unit),e.max-a>0&&a.add(1,t.unit),a=a.valueOf()),function(t,e,n){var a=[];if(t.maxTicks){var o=t.stepSize;a.push(void 0!==t.min?t.min:n.min);for(var r=i(n.min);r.add(o,t.unit).valueOf()<n.max;)a.push(r.valueOf());var l=t.max||n.max;a[a.length-1]!==l&&a.push(l)}return a}(t,0,{min:n,max:a})};var l=t.Scale.extend({initialize:function(){if(!i)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");t.Scale.prototype.initialize.call(this)},determineDataLimits:function(){var t,n=this,i=n.options.time,a=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER,l=n.chart.data,s={labels:[],datasets:[]};o.each(l.labels,function(o,l){var u=e(n,o);u.isValid()&&(i.round&&u.startOf(i.round),t=u.valueOf(),a=Math.min(t,a),r=Math.max(t,r),s.labels[l]=t)}),o.each(l.datasets,function(l,u){var d=[];"object"==typeof l.data[0]&&null!==l.data[0]&&n.chart.isDatasetVisible(u)?o.each(l.data,function(o,l){var s=e(n,n.getRightValue(o));s.isValid()&&(i.round&&s.startOf(i.round),t=s.valueOf(),a=Math.min(t,a),r=Math.max(t,r),d[l]=t)}):d=s.labels.slice(),s.datasets[u]=d}),n.dataMin=a,n.dataMax=r,n._parsedData=s},buildTicks:function(){var i,r,l=this,s=l.options.time,u=l.dataMin,d=l.dataMax;if(s.min){var c=e(l,s.min);s.round&&c.round(s.round),i=c.valueOf()}s.max&&(r=e(l,s.max).valueOf());var h=l.getLabelCapacity(i||u),f=s.unit||n(s.minUnit,i||u,r||d,h);l.displayFormat=s.displayFormats[f];var g=s.stepSize||a(i||u,r||d,f,h);l.ticks=t.Ticks.generators.time({maxTicks:h,min:i,max:r,stepSize:g,unit:f,isoWeekday:s.isoWeekday},{min:u,max:d}),l.max=o.max(l.ticks),l.min=o.min(l.ticks)},getLabelForIndex:function(t,n){var i=this,a=i.chart.data.labels&&t<i.chart.data.labels.length?i.chart.data.labels[t]:"",o=i.chart.data.datasets[n].data[t];return null!==o&&"object"==typeof o&&(a=i.getRightValue(o)),i.options.time.tooltipFormat&&(a=e(i,a).format(i.options.time.tooltipFormat)),a},tickFormatFunction:function(t,e,n){var i=t.format(this.displayFormat),a=this.options.ticks,r=o.getValueOrDefault(a.callback,a.userCallback);return r?r(i,e,n):i},convertTicksToLabels:function(){var t=this;t.ticksAsTimestamps=t.ticks,t.ticks=t.ticks.map(function(t){return i(t)}).map(t.tickFormatFunction,t)},getPixelForOffset:function(t){var e=this,n=e.max-e.min,i=n?(t-e.min)/n:0;if(e.isHorizontal()){var a=e.width*i;return e.left+Math.round(a)}var o=e.height*i;return e.top+Math.round(o)},getPixelForValue:function(t,n,i){var a=this,o=null;if(void 0!==n&&void 0!==i&&(o=a._parsedData.datasets[i][n]),null===o&&(t&&t.isValid||(t=e(a,a.getRightValue(t))),t&&t.isValid&&t.isValid()&&(o=t.valueOf())),null!==o)return a.getPixelForOffset(o)},getPixelForTick:function(t){return this.getPixelForOffset(this.ticksAsTimestamps[t])},getValueForPixel:function(t){var e=this,n=e.isHorizontal()?e.width:e.height,a=(t-(e.isHorizontal()?e.left:e.top))/n;return i(e.min+a*(e.max-e.min))},getLabelWidth:function(e){var n=this.options.ticks,i=this.ctx.measureText(e).width,a=Math.cos(o.toRadians(n.maxRotation)),r=Math.sin(o.toRadians(n.maxRotation));return i*a+o.getValueOrDefault(n.fontSize,t.defaults.global.defaultFontSize)*r},getLabelCapacity:function(t){var e=this;e.displayFormat=e.options.time.displayFormats.millisecond;var n=e.tickFormatFunction(i(t),0,[]),a=e.getLabelWidth(n);return(e.isHorizontal()?e.width:e.height)/a}});t.scaleService.registerScaleType("time",l,{position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}})}},{1:1}]},{},[7])(7)});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/include.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/include.min.js
new file mode 100755
index 0000000..54ef4aa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/include.min.js
@@ -0,0 +1 @@
+window.include=function(n,e,t){e.indexOf(".html")<0&&(e+=".html");var i=new XMLHttpRequest;i.onload=function(){if(4==this.readyState){var e=this.responseText,i="string"==typeof n?document.getElementById(n):n;console.log(i),i&&(i.innerHTML=e),t&&t()}},i.open("GET",e+"?cache="+(new Date).getTime(),!0),i.send()},window.bindIncludeEvent=function(){document.querySelectorAll("[include]").forEach(function(n,e){window.include(n,n.getAttribute("include"))})},window.bindIncludeEvent(),document.addEventListener("openPage",function(){window.bindIncludeEvent()});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/input.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/input.min.js
new file mode 100755
index 0000000..3e585b7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/input.min.js
@@ -0,0 +1 @@
+!function e(){setTimeout(function(){var t=document.getElementsByTagName("input");for(i in t){var a=t[i].parentNode;a&&(a.className.indexOf("left")>=0||a.className.indexOf("right")>=0)&&a.parentNode.className.indexOf("item")>=0&&(a=a.parentNode),a&&a.className.indexOf("item")>=0&&a.className.indexOf("bind-input-event-click")<0&&(a.className+=" bind-input-event-click",a.addEventListener("click",function(){this.getElementsByTagName("input").length&&(this.getElementsByTagName("input")[0].focus(),"radio"!==this.getElementsByTagName("input")[0].type||this.getElementsByTagName("input")[0].disabled||(this.getElementsByTagName("input")[0].checked=!0))},!1))}var l=document.getElementsByClassName("label-float");for(i in l)l[i].className&&l[i].className.indexOf("bind-input-event-focus")<0&&l[i].querySelectorAll("input,textarea").length&&(l[i].className+=" bind-input-event-focus",l[i].querySelectorAll("input,textarea")[0].addEventListener("focus",function(){this.parentNode.getElementsByTagName("label").length&&this.parentNode.getElementsByTagName("label")[0].className.indexOf("focus")<0&&(this.parentNode.getElementsByTagName("label")[0].className+=" focus")},!1),l[i].querySelectorAll("input,textarea")[0].addEventListener("blur",function(){this.parentNode.getElementsByTagName("label").length&&this.parentNode.getElementsByTagName("label")[0].className&&!this.value.length&&(this.parentNode.getElementsByTagName("label")[0].className=this.parentNode.getElementsByTagName("label")[0].className.replace("focus",""))},!1),l[i].querySelectorAll("input,textarea")[0].value&&l[i].querySelectorAll("input,textarea")[0].value.length&&(l[i].querySelectorAll("input,textarea")[0].parentNode.getElementsByTagName("label")[0].className+=" focus"));e()},500)}();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/jquery.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/jquery.min.js
new file mode 100755
index 0000000..6756324
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/jquery.min.js
@@ -0,0 +1 @@
+!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t)}(this,function(t){var e=function(){function e(t){return null==t?String(t):B[U.call(t)]||"object"}function n(t){return"function"==e(t)}function r(t){return null!=t&&t==t.window}function i(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function o(t){return"object"==e(t)}function a(t){return o(t)&&!r(t)&&Object.getPrototypeOf(t)==Object.prototype}function s(t){var e=!!t&&"length"in t&&t.length,n=j.type(t);return"function"!=n&&!r(t)&&("array"==n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function u(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function c(t){return t in L?L[t]:L[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function l(t,e){return"number"!=typeof e||$[u(t)]?e:e+"px"}function f(t){return"children"in t?P.call(t.children):j.map(t.childNodes,function(t){if(1==t.nodeType)return t})}function h(t,e){var n,r=t?t.length:0;for(n=0;n<r;n++)this[n]=t[n];this.length=r,this.selector=e||""}function p(t,e,n){for(E in e)n&&(a(e[E])||Y(e[E]))?(a(e[E])&&!a(t[E])&&(t[E]={}),Y(e[E])&&!Y(t[E])&&(t[E]=[]),p(t[E],e[E],n)):e[E]!==b&&(t[E]=e[E])}function d(t,e){return null==e?j(t):j(t).filter(e)}function m(t,e,r,i){return n(e)?e.call(t,r,i):e}function v(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function g(t,e){var n=t.className||"",r=n&&n.baseVal!==b;if(e===b)return r?n.baseVal:n;r?n.baseVal=e:t.className=e}function y(t){try{return t?"true"==t||"false"!=t&&("null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?j.parseJSON(t):t):t}catch(e){return t}}function x(t,e){e(t);for(var n=0,r=t.childNodes.length;n<r;n++)x(t.childNodes[n],e)}var b,E,j,T,w,S,C=[],N=C.concat,O=C.filter,P=C.slice,A=t.document,D={},L={},$={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},F=/^\s*<(\w+|!)[^>]*>/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,M=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,R=/^(?:body|html)$/i,Z=/([A-Z])/g,z=["val","css","html","text","data","width","height","offset"],q=A.createElement("table"),H=A.createElement("tr"),I={tr:A.createElement("tbody"),tbody:q,thead:q,tfoot:q,td:H,th:H,"*":A.createElement("div")},V=/complete|loaded|interactive/,_=/^[\w-]*$/,B={},U=B.toString,X={},J=A.createElement("div"),W={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},Y=Array.isArray||function(t){return t instanceof Array};return X.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var r,i=t.parentNode,o=!i;return o&&(i=J).appendChild(t),r=~X.qsa(i,e).indexOf(t),o&&J.removeChild(t),r},w=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},S=function(t){return O.call(t,function(e,n){return t.indexOf(e)==n})},X.fragment=function(t,e,n){var r,i,o;return k.test(t)&&(r=j(A.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(M,"<$1></$2>")),e===b&&(e=F.test(t)&&RegExp.$1),e in I||(e="*"),(o=I[e]).innerHTML=""+t,r=j.each(P.call(o.childNodes),function(){o.removeChild(this)})),a(n)&&(i=j(r),j.each(n,function(t,e){z.indexOf(t)>-1?i[t](e):i.attr(t,e)})),r},X.Z=function(t,e){return new h(t,e)},X.isZ=function(t){return t instanceof X.Z},X.init=function(t,e){var r;if(!t)return X.Z();if("string"==typeof t)if("<"==(t=t.trim())[0]&&F.test(t))r=X.fragment(t,RegExp.$1,e),t=null;else{if(e!==b)return j(e).find(t);r=X.qsa(A,t)}else{if(n(t))return j(A).ready(t);if(X.isZ(t))return t;if(Y(t))r=function(t){return O.call(t,function(t){return null!=t})}(t);else if(o(t))r=[t],t=null;else if(F.test(t))r=X.fragment(t.trim(),RegExp.$1,e),t=null;else{if(e!==b)return j(e).find(t);r=X.qsa(A,t)}}return X.Z(r,t)},j=function(t,e){return X.init(t,e)},j.extend=function(t){var e,n=P.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){p(t,n,e)}),t},X.qsa=function(t,e){var n,r="#"==e[0],i=!r&&"."==e[0],o=r||i?e.slice(1):e,a=_.test(o);return t.getElementById&&a&&r?(n=t.getElementById(o))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:P.call(a&&!r&&t.getElementsByClassName?i?t.getElementsByClassName(o):t.getElementsByTagName(e):t.querySelectorAll(e))},j.contains=A.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},j.type=e,j.isFunction=n,j.isWindow=r,j.isArray=Y,j.isPlainObject=a,j.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},j.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},j.inArray=function(t,e,n){return C.indexOf.call(e,t,n)},j.camelCase=w,j.trim=function(t){return null==t?"":String.prototype.trim.call(t)},j.uuid=0,j.support={},j.expr={},j.noop=function(){},j.map=function(t,e){var n,r,i,o=[];if(s(t))for(r=0;r<t.length;r++)null!=(n=e(t[r],r))&&o.push(n);else for(i in t)null!=(n=e(t[i],i))&&o.push(n);return function(t){return t.length>0?j.fn.concat.apply([],t):t}(o)},j.each=function(t,e){var n,r;if(s(t)){for(n=0;n<t.length;n++)if(!1===e.call(t[n],n,t[n]))return t}else for(r in t)if(!1===e.call(t[r],r,t[r]))return t;return t},j.grep=function(t,e){return O.call(t,e)},t.JSON&&(j.parseJSON=JSON.parse),j.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(t,e){B["[object "+e+"]"]=e.toLowerCase()}),j.fn={constructor:X.Z,length:0,forEach:C.forEach,reduce:C.reduce,push:C.push,sort:C.sort,splice:C.splice,indexOf:C.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=X.isZ(e)?e.toArray():e;return N.apply(X.isZ(this)?this.toArray():this,n)},map:function(t){return j(j.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return j(P.apply(this,arguments))},ready:function(t){return V.test(A.readyState)&&A.body?t(j):A.addEventListener("DOMContentLoaded",function(){t(j)},!1),this},get:function(t){return t===b?P.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return C.every.call(this,function(e,n){return!1!==t.call(e,n,e)}),this},filter:function(t){return n(t)?this.not(this.not(t)):j(O.call(this,function(e){return X.matches(e,t)}))},add:function(t,e){return j(S(this.concat(j(t,e))))},is:function(t){return this.length>0&&X.matches(this[0],t)},not:function(t){var e=[];if(n(t)&&t.call!==b)this.each(function(n){t.call(this,n)||e.push(this)});else{var r="string"==typeof t?this.filter(t):s(t)&&n(t.item)?P.call(t):j(t);this.forEach(function(t){r.indexOf(t)<0&&e.push(t)})}return j(e)},has:function(t){return this.filter(function(){return o(t)?j.contains(this,t):j(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!o(t)?t:j(t)},last:function(){var t=this[this.length-1];return t&&!o(t)?t:j(t)},find:function(t){var e=this;return t?"object"==typeof t?j(t).filter(function(){var t=this;return C.some.call(e,function(e){return j.contains(e,t)})}):1==this.length?j(X.qsa(this[0],t)):this.map(function(){return X.qsa(this,t)}):j()},closest:function(t,e){var n=[],r="object"==typeof t&&j(t);return this.each(function(o,a){for(;a&&!(r?r.indexOf(a)>=0:X.matches(a,t));)a=a!==e&&!i(a)&&a.parentNode;a&&n.indexOf(a)<0&&n.push(a)}),j(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=j.map(n,function(t){if((t=t.parentNode)&&!i(t)&&e.indexOf(t)<0)return e.push(t),t});return d(e,t)},parent:function(t){return d(S(this.pluck("parentNode")),t)},children:function(t){return d(this.map(function(){return f(this)}),t)},contents:function(){return this.map(function(){return this.contentDocument||P.call(this.childNodes)})},siblings:function(t){return d(this.map(function(t,e){return O.call(f(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return j.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=function(t){var e,n;return D[t]||(e=A.createElement(t),A.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),D[t]=n),D[t]}(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=n(t);if(this[0]&&!e)var r=j(t).get(0),i=r.parentNode||this.length>1;return this.each(function(n){j(this).wrapAll(e?t.call(this,n):i?r.cloneNode(!0):r)})},wrapAll:function(t){if(this[0]){j(this[0]).before(t=j(t));for(var e;(e=t.children()).length;)t=e.first();j(t).append(this)}return this},wrapInner:function(t){var e=n(t);return this.each(function(n){var r=j(this),i=r.contents(),o=e?t.call(this,n):t;i.length?i.wrapAll(o):r.append(o)})},unwrap:function(){return this.parent().each(function(){j(this).replaceWith(j(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(t){return this.each(function(){var e=j(this);(t===b?"none"==e.css("display"):t)?e.show():e.hide()})},prev:function(t){return j(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return j(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var n=this.innerHTML;j(this).empty().append(m(this,t,e,n))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=m(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this.pluck("textContent").join(""):null},attr:function(t,e){var n;return"string"!=typeof t||1 in arguments?this.each(function(n){if(1===this.nodeType)if(o(t))for(E in t)v(this,E,t[E]);else v(this,t,m(this,e,n,this.getAttribute(t)))}):0 in this&&1==this[0].nodeType&&null!=(n=this[0].getAttribute(t))?n:b},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){v(this,t)},this)})},prop:function(t,e){return t=W[t]||t,1 in arguments?this.each(function(n){this[t]=m(this,e,n,this[t])}):this[0]&&this[0][t]},removeProp:function(t){return t=W[t]||t,this.each(function(){delete this[t]})},data:function(t,e){var n="data-"+t.replace(Z,"-$1").toLowerCase(),r=1 in arguments?this.attr(n,e):this.attr(n);return null!==r?y(r):b},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each(function(e){this.value=m(this,t,e,this.value)})):this[0]&&(this[0].multiple?j(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each(function(t){var n=j(this),r=m(this,e,t,n.offset()),i=n.offsetParent().offset(),o={top:r.top-i.top,left:r.left-i.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)});if(!this.length)return null;if(A.documentElement!==this[0]&&!j.contains(A.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,n){if(arguments.length<2){var r=this[0];if("string"==typeof t){if(!r)return;return r.style[w(t)]||getComputedStyle(r,"").getPropertyValue(t)}if(Y(t)){if(!r)return;var i={},o=getComputedStyle(r,"");return j.each(t,function(t,e){i[e]=r.style[w(e)]||o.getPropertyValue(e)}),i}}var a="";if("string"==e(t))n||0===n?a=u(t)+":"+l(t,n):this.each(function(){this.style.removeProperty(u(t))});else for(E in t)t[E]||0===t[E]?a+=u(E)+":"+l(E,t[E])+";":this.each(function(){this.style.removeProperty(u(E))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(j(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&C.some.call(this,function(t){return this.test(g(t))},c(t))},addClass:function(t){return t?this.each(function(e){if("className"in this){T=[];var n=g(this);m(this,t,e,n).split(/\s+/g).forEach(function(t){j(this).hasClass(t)||T.push(t)},this),T.length&&g(this,n+(n?" ":"")+T.join(" "))}}):this},removeClass:function(t){return this.each(function(e){if("className"in this){if(t===b)return g(this,"");T=g(this),m(this,t,e,T).split(/\s+/g).forEach(function(t){T=T.replace(c(t)," ")}),g(this,T.trim())}})},toggleClass:function(t,e){return t?this.each(function(n){var r=j(this);m(this,t,n,g(this)).split(/\s+/g).forEach(function(t){(e===b?!r.hasClass(t):e)?r.addClass(t):r.removeClass(t)})}):this},scrollTop:function(t){if(this.length){var e="scrollTop"in this[0];return t===b?e?this[0].scrollTop:this[0].pageYOffset:this.each(e?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var e="scrollLeft"in this[0];return t===b?e?this[0].scrollLeft:this[0].pageXOffset:this.each(e?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),r=R.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(j(t).css("margin-top"))||0,n.left-=parseFloat(j(t).css("margin-left"))||0,r.top+=parseFloat(j(e[0]).css("border-top-width"))||0,r.left+=parseFloat(j(e[0]).css("border-left-width"))||0,{top:n.top-r.top,left:n.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||A.body;t&&!R.test(t.nodeName)&&"static"==j(t).css("position");)t=t.offsetParent;return t})}},j.fn.detach=j.fn.remove,["width","height"].forEach(function(t){var e=t.replace(/./,function(t){return t[0].toUpperCase()});j.fn[t]=function(n){var o,a=this[0];return n===b?r(a)?a["inner"+e]:i(a)?a.documentElement["scroll"+e]:(o=this.offset())&&o[t]:this.each(function(e){(a=j(this)).css(t,m(this,n,e,a[t]()))})}}),["after","prepend","before","append"].forEach(function(n,r){var i=r%2;j.fn[n]=function(){var n,o,a=j.map(arguments,function(t){var r=[];return"array"==(n=e(t))?(t.forEach(function(t){return t.nodeType!==b?r.push(t):j.zepto.isZ(t)?r=r.concat(t.get()):void(r=r.concat(X.fragment(t)))}),r):"object"==n||null==t?t:X.fragment(t)}),s=this.length>1;return a.length<1?this:this.each(function(e,n){o=i?n:n.parentNode,n=0==r?n.nextSibling:1==r?n.firstChild:2==r?n:null;var u=j.contains(A.documentElement,o);a.forEach(function(e){if(s)e=e.cloneNode(!0);else if(!o)return j(e).remove();o.insertBefore(e,n),u&&x(e,function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}})})})},j.fn[i?n+"To":"insert"+(r?"Before":"After")]=function(t){return j(t)[n](this),this}}),X.Z.prototype=h.prototype=j.fn,X.uniq=S,X.deserializeValue=y,j.zepto=X,j}();return t.Zepto=e,void 0===t.$&&(t.$=e),function(e){function n(t){return t._zid||(t._zid=h++)}function r(t,e,r,o){if((e=i(e)).ns)var a=function(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}(e.ns);return(v[n(t)]||[]).filter(function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||a.test(t.ns))&&(!r||n(t.fn)===n(r))&&(!o||t.sel==o)})}function i(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function o(t,e){return t.del&&!y&&t.e in x||!!e}function a(t){return b[t]||y&&x[t]||t}function s(t,r,s,u,l,h,p){var d=n(t),m=v[d]||(v[d]=[]);r.split(/\s/).forEach(function(n){if("ready"==n)return e(document).ready(s);var r=i(n);r.fn=s,r.sel=l,r.e in b&&(s=function(t){var n=t.relatedTarget;if(!n||n!==this&&!e.contains(this,n))return r.fn.apply(this,arguments)}),r.del=h;var d=h||s;r.proxy=function(e){if(!(e=c(e)).isImmediatePropagationStopped()){e.data=u;var n=d.apply(t,e._args==f?[e]:[e].concat(e._args));return!1===n&&(e.preventDefault(),e.stopPropagation()),n}},r.i=m.length,m.push(r),"addEventListener"in t&&t.addEventListener(a(r.e),r.proxy,o(r,p))})}function u(t,e,i,s,u){var c=n(t);(e||"").split(/\s/).forEach(function(e){r(t,e,i,s).forEach(function(e){delete v[c][e.i],"removeEventListener"in t&&t.removeEventListener(a(e.e),e.proxy,o(e,u))})})}function c(t,n){return!n&&t.isDefaultPrevented||(n||(n=t),e.each(w,function(e,r){var i=n[e];t[e]=function(){return this[r]=E,i&&i.apply(n,arguments)},t[r]=j}),t.timeStamp||(t.timeStamp=Date.now()),(n.defaultPrevented!==f?n.defaultPrevented:"returnValue"in n?!1===n.returnValue:n.getPreventDefault&&n.getPreventDefault())&&(t.isDefaultPrevented=E)),t}function l(t){var e,n={originalEvent:t};for(e in t)T.test(e)||t[e]===f||(n[e]=t[e]);return c(n,t)}var f,h=1,p=Array.prototype.slice,d=e.isFunction,m=function(t){return"string"==typeof t},v={},g={},y="onfocusin"in t,x={focus:"focusin",blur:"focusout"},b={mouseenter:"mouseover",mouseleave:"mouseout"};g.click=g.mousedown=g.mouseup=g.mousemove="MouseEvents",e.event={add:s,remove:u},e.proxy=function(t,r){var i=2 in arguments&&p.call(arguments,2);if(d(t)){var o=function(){return t.apply(r,i?i.concat(p.call(arguments)):arguments)};return o._zid=n(t),o}if(m(r))return i?(i.unshift(t[r],t),e.proxy.apply(null,i)):e.proxy(t[r],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,r){return this.on(t,e,n,r,1)};var E=function(){return!0},j=function(){return!1},T=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,w={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,n,r,i,o){var a,c,h=this;return t&&!m(t)?(e.each(t,function(t,e){h.on(t,n,r,e,o)}),h):(m(n)||d(i)||!1===i||(i=r,r=n,n=f),i!==f&&!1!==r||(i=r,r=f),!1===i&&(i=j),h.each(function(f,h){o&&(a=function(t){return u(h,t.type,i),i.apply(this,arguments)}),n&&(c=function(t){var r,o=e(t.target).closest(n,h).get(0);if(o&&o!==h)return r=e.extend(l(t),{currentTarget:o,liveFired:h}),(a||i).apply(o,[r].concat(p.call(arguments,1)))}),s(h,t,i,r,n,c||a)}))},e.fn.off=function(t,n,r){var i=this;return t&&!m(t)?(e.each(t,function(t,e){i.off(t,n,e)}),i):(m(n)||d(r)||!1===r||(r=n,n=f),!1===r&&(r=j),i.each(function(){u(this,t,r,n)}))},e.fn.trigger=function(t,n){return t=m(t)||e.isPlainObject(t)?e.Event(t):c(t),t._args=n,this.each(function(){t.type in x&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)})},e.fn.triggerHandler=function(t,n){var i,o;return this.each(function(a,s){(i=l(m(t)?e.Event(t):t))._args=n,i.target=s,e.each(r(s,t.type||t),function(t,e){if(o=e.proxy(i),i.isImmediatePropagationStopped())return!1})}),o},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}}),e.Event=function(t,e){m(t)||(e=t,t=e.type);var n=document.createEvent(g[t]||"Events"),r=!0;if(e)for(var i in e)"bubbles"==i?r=!!e[i]:n[i]=e[i];return n.initEvent(t,r,!0),c(n)}}(e),function(e){function n(t,n,r,i){if(t.global)return function(t,n,r){var i=e.Event(n);return e(t).trigger(i,r),!i.isDefaultPrevented()}(n||d,r,i)}function r(t,e){var r=e.context;if(!1===e.beforeSend.call(r,t,e)||!1===n(e,r,"ajaxBeforeSend",[t,e]))return!1;n(e,r,"ajaxSend",[t,e])}function i(t,e,r,i){var o=r.context;r.success.call(o,t,"success",e),i&&i.resolveWith(o,[t,"success",e]),n(r,o,"ajaxSuccess",[e,r,t]),a("success",e,r)}function o(t,e,r,i,o){var s=i.context;i.error.call(s,r,e,t),o&&o.rejectWith(s,[r,e,t]),n(i,s,"ajaxError",[r,i,t||e]),a(e,r,i)}function a(t,r,i){var o=i.context;i.complete.call(o,r,t),n(i,o,"ajaxComplete",[r,i]),function(t){t.global&&!--e.active&&n(t,null,"ajaxStop")}(i)}function s(){}function u(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function c(t,n,r,i){return e.isFunction(n)&&(i=r,r=n,n=void 0),e.isFunction(r)||(i=r,r=void 0),{url:t,data:n,success:r,dataType:i}}function l(t,n,r,i){var o,a=e.isArray(n),s=e.isPlainObject(n);e.each(n,function(n,u){o=e.type(u),i&&(n=r?i:i+"["+(s||"object"==o||"array"==o?n:"")+"]"),!i&&a?t.add(u.name,u.value):"array"==o||!r&&"object"==o?l(t,u,r,n):t.add(n,u)})}var f,h,p=+new Date,d=t.document,m=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,v=/^(?:text|application)\/javascript/i,g=/^(?:text|application)\/xml/i,y="application/json",x="text/html",b=/^\s*$/,E=d.createElement("a");E.href=t.location.href,e.active=0,e.ajaxJSONP=function(n,a){if(!("type"in n))return e.ajax(n);var s,u,c=n.jsonpCallback,l=(e.isFunction(c)?c():c)||"Zepto"+p++,f=d.createElement("script"),h=t[l],m=function(t){e(f).triggerHandler("error",t||"abort")},v={abort:m};return a&&a.promise(v),e(f).on("load error",function(r,c){clearTimeout(u),e(f).off().remove(),"error"!=r.type&&s?i(s[0],v,n,a):o(null,c||"error",v,n,a),t[l]=h,s&&e.isFunction(h)&&h(s[0]),h=s=void 0}),!1===r(v,n)?(m("abort"),v):(t[l]=function(){s=arguments},f.src=n.url.replace(/\?(.+)=\?/,"?$1="+l),d.head.appendChild(f),n.timeout>0&&(u=setTimeout(function(){m("timeout")},n.timeout)),v)},e.ajaxSettings={type:"GET",beforeSend:s,success:s,error:s,complete:s,context:null,global:!0,xhr:function(){return new t.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:y,xml:"application/xml, text/xml",html:x,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0,dataFilter:s},e.ajax=function(a){var c,l,p=e.extend({},a||{}),m=e.Deferred&&e.Deferred();for(f in e.ajaxSettings)void 0===p[f]&&(p[f]=e.ajaxSettings[f]);!function(t){t.global&&0==e.active++&&n(t,null,"ajaxStart")}(p),p.crossDomain||((c=d.createElement("a")).href=p.url,c.href=c.href,p.crossDomain=E.protocol+"//"+E.host!=c.protocol+"//"+c.host),p.url||(p.url=t.location.toString()),(l=p.url.indexOf("#"))>-1&&(p.url=p.url.slice(0,l)),function(t){t.processData&&t.data&&"string"!=e.type(t.data)&&(t.data=e.param(t.data,t.traditional)),!t.data||t.type&&"GET"!=t.type.toUpperCase()&&"jsonp"!=t.dataType||(t.url=u(t.url,t.data),t.data=void 0)}(p);var j=p.dataType,T=/\?.+=\?/.test(p.url);if(T&&(j="jsonp"),!1!==p.cache&&(a&&!0===a.cache||"script"!=j&&"jsonp"!=j)||(p.url=u(p.url,"_="+Date.now())),"jsonp"==j)return T||(p.url=u(p.url,p.jsonp?p.jsonp+"=?":!1===p.jsonp?"":"callback=?")),e.ajaxJSONP(p,m);var w,S=p.accepts[j],C={},N=function(t,e){C[t.toLowerCase()]=[t,e]},O=/^([\w-]+:)\/\//.test(p.url)?RegExp.$1:t.location.protocol,P=p.xhr(),A=P.setRequestHeader;if(m&&m.promise(P),p.crossDomain||N("X-Requested-With","XMLHttpRequest"),N("Accept",S||"*/*"),(S=p.mimeType||S)&&(S.indexOf(",")>-1&&(S=S.split(",",2)[0]),P.overrideMimeType&&P.overrideMimeType(S)),(p.contentType||!1!==p.contentType&&p.data&&"GET"!=p.type.toUpperCase())&&N("Content-Type",p.contentType||"application/x-www-form-urlencoded"),p.headers)for(h in p.headers)N(h,p.headers[h]);if(P.setRequestHeader=N,P.onreadystatechange=function(){if(4==P.readyState){P.onreadystatechange=s,clearTimeout(w);var t,n=!1;if(P.status>=200&&P.status<300||304==P.status||0==P.status&&"file:"==O){if(j=j||function(t){return t&&(t=t.split(";",2)[0]),t&&(t==x?"html":t==y?"json":v.test(t)?"script":g.test(t)&&"xml")||"text"}(p.mimeType||P.getResponseHeader("content-type")),"arraybuffer"==P.responseType||"blob"==P.responseType)t=P.response;else{t=P.responseText;try{t=function(t,e,n){if(n.dataFilter==s)return t;var r=n.context;return n.dataFilter.call(r,t,e)}(t,j,p),"script"==j?(0,eval)(t):"xml"==j?t=P.responseXML:"json"==j&&(t=b.test(t)?null:e.parseJSON(t))}catch(t){n=t}if(n)return o(n,"parsererror",P,p,m)}i(t,P,p,m)}else o(P.statusText||null,P.status?"error":"abort",P,p,m)}},!1===r(P,p))return P.abort(),o(null,"abort",P,p,m),P;var D=!("async"in p)||p.async;if(P.open(p.type,p.url,D,p.username,p.password),p.xhrFields)for(h in p.xhrFields)P[h]=p.xhrFields[h];for(h in C)A.apply(P,C[h]);return p.timeout>0&&(w=setTimeout(function(){P.onreadystatechange=s,P.abort(),o(null,"timeout",P,p,m)},p.timeout)),P.send(p.data?p.data:null),P},e.get=function(){return e.ajax(c.apply(null,arguments))},e.post=function(){var t=c.apply(null,arguments);return t.type="POST",e.ajax(t)},e.getJSON=function(){var t=c.apply(null,arguments);return t.dataType="json",e.ajax(t)},e.fn.load=function(t,n,r){if(!this.length)return this;var i,o=this,a=t.split(/\s/),s=c(t,n,r),u=s.success;return a.length>1&&(s.url=a[0],i=a[1]),s.success=function(t){o.html(i?e("<div>").html(t.replace(m,"")).find(i):t),u&&u.apply(o,arguments)},e.ajax(s),this};var j=encodeURIComponent;e.param=function(t,n){var r=[];return r.add=function(t,n){e.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(j(t)+"="+j(n))},l(r,t,n),r.join("&").replace(/%20/g,"+")}}(e),function(t){t.fn.serializeArray=function(){var e,n,r=[],i=function(t){if(t.forEach)return t.forEach(i);r.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(r,o){n=o.type,(e=o.name)&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&i(t(o).val())}),r},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(e),function(){try{getComputedStyle(void 0)}catch(n){var e=getComputedStyle;t.getComputedStyle=function(t,n){try{return e(t,n)}catch(t){return null}}}}(),e});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/loading.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/loading.min.js
new file mode 100755
index 0000000..c230eb0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/loading.min.js
@@ -0,0 +1 @@
+window.loading=function(e){var c={};"object"==typeof e?c=e:c.message=e,c.id||(c.id="LOADING"+(new Date).getTime());var t=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(t=event.target.parentNode);var d=document.createElement("div");d.className="backdrop show backdrop-alert",d.id=c.id+"_BACKDROP",t.appendChild(d);var a=document.createElement("div");a.className="alert-mobileui alert-loading",a.id=c.id,d.parentNode.appendChild(a);var l=document.createElement("div");c.class="white",l.className="alert "+c.class,window.SO&&2===SO.code?l.innerHTML='<div class="loading-circle"><svg xmlns="http://www.w3.org/2000/svg" width="37" height="37" viewBox="0 0 27 27"><path d="M18.696,10.5c-0.275-0.479-0.113-1.09,0.365-1.367l4.759-2.751c0.482-0.273,1.095-0.11,1.37,0.368 c0.276,0.479,0.115,1.092-0.364,1.364l-4.764,2.751C19.583,11.141,18.973,10.977,18.696,10.5z"/><path d="M16.133,6.938l2.75-4.765c0.276-0.478,0.889-0.643,1.367-0.366c0.479,0.276,0.641,0.886,0.365,1.366l-2.748,4.762 C17.591,8.415,16.979,8.58,16.5,8.303C16.021,8.027,15.856,7.414,16.133,6.938z"/><path d="M13.499,7.5c-0.552,0-1-0.448-1-1.001V1c0-0.554,0.448-1,1-1c0.554,0,1.003,0.447,1.003,1v5.499 C14.5,7.053,14.053,7.5,13.499,7.5z"/><path d="M8.303,10.5c-0.277,0.477-0.888,0.641-1.365,0.365L2.175,8.114C1.697,7.842,1.532,7.229,1.808,6.75 c0.277-0.479,0.89-0.642,1.367-0.368l4.762,2.751C8.416,9.41,8.58,10.021,8.303,10.5z"/><path d="M9.133,7.937l-2.75-4.763c-0.276-0.48-0.111-1.09,0.365-1.366c0.479-0.277,1.09-0.114,1.367,0.366l2.75,4.765 c0.274,0.476,0.112,1.088-0.367,1.364C10.021,8.581,9.409,8.415,9.133,7.937z"/><path d="M6.499,14.5H1c-0.554,0-1-0.448-1-1c0-0.554,0.447-1.001,1-1.001h5.499c0.552,0,1.001,0.448,1.001,1.001 C7.5,14.052,7.052,14.5,6.499,14.5z"/><path d="M8.303,16.502c0.277,0.478,0.113,1.088-0.365,1.366l-4.762,2.749c-0.478,0.273-1.091,0.112-1.368-0.366 c-0.276-0.479-0.111-1.089,0.367-1.368l4.762-2.748C7.415,15.856,8.026,16.021,8.303,16.502z"/><path d="M10.866,20.062l-2.75,4.767c-0.277,0.475-0.89,0.639-1.367,0.362c-0.477-0.277-0.642-0.886-0.365-1.365l2.75-4.764 c0.277-0.477,0.888-0.638,1.366-0.365C10.978,18.974,11.141,19.585,10.866,20.062z"/><path d="M13.499,19.502c0.554,0,1.003,0.448,1.003,1.002v5.498c0,0.55-0.448,0.999-1.003,0.999c-0.552,0-1-0.447-1-0.999v-5.498 C12.499,19.95,12.946,19.502,13.499,19.502z"/><path d="M17.867,19.062l2.748,4.764c0.275,0.479,0.113,1.088-0.365,1.365c-0.479,0.276-1.091,0.112-1.367-0.362l-2.75-4.767 c-0.276-0.477-0.111-1.088,0.367-1.365C16.979,18.424,17.591,18.585,17.867,19.062z"/><path d="M18.696,16.502c0.276-0.48,0.887-0.646,1.365-0.367l4.765,2.748c0.479,0.279,0.64,0.889,0.364,1.368 c-0.275,0.479-0.888,0.64-1.37,0.366l-4.759-2.749C18.583,17.59,18.421,16.979,18.696,16.502z"/><path d="M25.998,12.499h-5.501c-0.552,0-1.001,0.448-1.001,1.001c0,0.552,0.447,1,1.001,1h5.501c0.554,0,1.002-0.448,1.002-1 C27,12.946,26.552,12.499,25.998,12.499z"/></svg></div>':l.innerHTML='<svg class="loading-circle" width="40" height="40" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="20" cy="20" r="15"></svg>',c.message&&(l.innerHTML+="<p>"+c.message+"</p>"),a.appendChild(l)},window.loadingElement=function(e,c,t,d){"object"!=typeof e&&(e=document.getElementById(e));var a=c?"with-message":"";d=d?"":"white-loading",t||(t="");document.createElement("div");var l="";l=window.SO&&2===SO.code?'<svg class="loading-circle loading-element '+d+" "+a+" "+t+'" xmlns="http://www.w3.org/2000/svg" width="37" height="37" viewBox="0 0 27 27"><path d="M18.696,10.5c-0.275-0.479-0.113-1.09,0.365-1.367l4.759-2.751c0.482-0.273,1.095-0.11,1.37,0.368 c0.276,0.479,0.115,1.092-0.364,1.364l-4.764,2.751C19.583,11.141,18.973,10.977,18.696,10.5z"/><path d="M16.133,6.938l2.75-4.765c0.276-0.478,0.889-0.643,1.367-0.366c0.479,0.276,0.641,0.886,0.365,1.366l-2.748,4.762 C17.591,8.415,16.979,8.58,16.5,8.303C16.021,8.027,15.856,7.414,16.133,6.938z"/><path d="M13.499,7.5c-0.552,0-1-0.448-1-1.001V1c0-0.554,0.448-1,1-1c0.554,0,1.003,0.447,1.003,1v5.499 C14.5,7.053,14.053,7.5,13.499,7.5z"/><path d="M8.303,10.5c-0.277,0.477-0.888,0.641-1.365,0.365L2.175,8.114C1.697,7.842,1.532,7.229,1.808,6.75 c0.277-0.479,0.89-0.642,1.367-0.368l4.762,2.751C8.416,9.41,8.58,10.021,8.303,10.5z"/><path d="M9.133,7.937l-2.75-4.763c-0.276-0.48-0.111-1.09,0.365-1.366c0.479-0.277,1.09-0.114,1.367,0.366l2.75,4.765 c0.274,0.476,0.112,1.088-0.367,1.364C10.021,8.581,9.409,8.415,9.133,7.937z"/><path d="M6.499,14.5H1c-0.554,0-1-0.448-1-1c0-0.554,0.447-1.001,1-1.001h5.499c0.552,0,1.001,0.448,1.001,1.001 C7.5,14.052,7.052,14.5,6.499,14.5z"/><path d="M8.303,16.502c0.277,0.478,0.113,1.088-0.365,1.366l-4.762,2.749c-0.478,0.273-1.091,0.112-1.368-0.366 c-0.276-0.479-0.111-1.089,0.367-1.368l4.762-2.748C7.415,15.856,8.026,16.021,8.303,16.502z"/><path d="M10.866,20.062l-2.75,4.767c-0.277,0.475-0.89,0.639-1.367,0.362c-0.477-0.277-0.642-0.886-0.365-1.365l2.75-4.764 c0.277-0.477,0.888-0.638,1.366-0.365C10.978,18.974,11.141,19.585,10.866,20.062z"/><path d="M13.499,19.502c0.554,0,1.003,0.448,1.003,1.002v5.498c0,0.55-0.448,0.999-1.003,0.999c-0.552,0-1-0.447-1-0.999v-5.498 C12.499,19.95,12.946,19.502,13.499,19.502z"/><path d="M17.867,19.062l2.748,4.764c0.275,0.479,0.113,1.088-0.365,1.365c-0.479,0.276-1.091,0.112-1.367-0.362l-2.75-4.767 c-0.276-0.477-0.111-1.088,0.367-1.365C16.979,18.424,17.591,18.585,17.867,19.062z"/><path d="M18.696,16.502c0.276-0.48,0.887-0.646,1.365-0.367l4.765,2.748c0.479,0.279,0.64,0.889,0.364,1.368 c-0.275,0.479-0.888,0.64-1.37,0.366l-4.759-2.749C18.583,17.59,18.421,16.979,18.696,16.502z"/><path d="M25.998,12.499h-5.501c-0.552,0-1.001,0.448-1.001,1.001c0,0.552,0.447,1,1.001,1h5.501c0.554,0,1.002-0.448,1.002-1 C27,12.946,26.552,12.499,25.998,12.499z"/></svg>':'<svg class="loading-circle loading-element '+d+" "+a+" "+t+'" width="40" height="40" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="20" cy="20" r="15"></svg>',e.oldValue=e.innerHTML,e.innerHTML=l,e.disabled=!0,c&&(e.innerHTML+=c)},window.closeLoading=function(e){if(e)"object"!=typeof e&&(e=document.getElementById(e)),e.innerHTML=e.oldValue,e.disabled=!1;else{var c=document.getElementsByClassName("alert-mobileui")[0],t=c.id;(c=document.getElementById(t)).parentNode.removeChild(c);var d=document.getElementById(t+"_BACKDROP");d.parentNode.removeChild(d)}};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/menu.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/menu.min.js
new file mode 100755
index 0000000..46cf212
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/menu.min.js
@@ -0,0 +1 @@
+window.menu={},window.openMenu=function(e){var n=e;if((e=document.getElementById(e)).className.indexOf("menu")>=0&&e.className.indexOf("open")<0){var o=document.createElement("div");if(o.className="backdrop backdrop-menu",e.parentNode.appendChild(o),setTimeout(function(){o.className+=" show"}),o.addEventListener("click",function(e){window.closeMenu(n)},!1),2===SO.code){e.style.height=window.innerHeight+"px";var d=" side-menu";if(window.menu.position="left",e.className.indexOf("menu-right")>=0){d=" side-menu-right",window.menu.position="right";var a=document.getElementsByClassName("header");if(a.length)for(i in a)a[i].className&&a[i].className.indexOf("side-menu-right")<0&&(a[i].className+=" side-menu-right")}e.parentNode.className.indexOf("body")>=0?e.parentNode.className+=d:document.getElementsByTagName("body")[0].className+=d}e.className+=" open";var t=new CustomEvent("openMenu",{detail:{menu:n}});document.dispatchEvent(t),window.menu.openFired=!0,document.addEventListener("firedCloseMenu",function(e){window.closeMenu(n)},!1)}},window.closeMenu=function(e){var n=e;if((e=document.getElementById(e)).className.indexOf("open")<0)return!1;var o=new CustomEvent("closeMenu",{detail:{menu:n}});document.dispatchEvent(o),window.menu.openFired=!1,e.className=e.className.replace("open","");var d=document.getElementsByClassName("header");if(d.length)for(i in d)d[i].className&&d[i].className.indexOf("side-menu-right")>=0&&(d[i].className=d[i].className.replace(" side-menu-right",""));var a=e.parentNode.getElementsByClassName("backdrop-menu");a&&a.length&&((a=a[0]).className=a.className.replace("show",""),setTimeout(function(){a&&a.parentNode&&a.parentNode.removeChild(a)},500)),1!==SO.code&&(e.parentNode.className.indexOf("body")>=0?e.parentNode.className=e.parentNode.className.replace("side-menu",""):document.getElementsByTagName("body")[0].className=document.getElementsByTagName("body")[0].className.replace("side-menu",""))},document.querySelector("body").addEventListener("touchstart",function(e){window.menu.xDown=e.touches[0].clientX,window.menu.yDown=e.touches[0].clientY},!1),window.menu.handleTouchMove=function(e,n){if(window.menu.xDown&&window.menu.yDown){var o=e.touches[0].clientX,i=e.touches[0].clientY;if(window.menu.xDiff=window.menu.xDown-o,window.menu.yDiff=window.menu.yDown-i,Math.abs(window.menu.xDiff)>Math.abs(window.menu.yDiff)){var d=-1!==document.getElementById(n).classList.value.indexOf("menu-right");window.menu.xDiff>0?d&&!window.menu.openFired?window.openMenu(n):!d&&window.menu.openFired&&window.closeMenu(n):d||window.menu.openFired?d&&window.menu.openFired&&window.closeMenu(n):window.openMenu(n)}window.menu.xDown=null,window.menu.yDown=null}},window.menu.enableSwiper=function(e){document.querySelector("body").addEventListener("touchmove",function(n){window.menu.handleTouchMove(n,e)},!1)};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileui-colors.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileui-colors.min.js
new file mode 100755
index 0000000..cbae6e3
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileui-colors.min.js
@@ -0,0 +1 @@
+window.colorsMobileUI=[],window.colorsMobileUI.red="rgb(244, 67, 54)",window.colorsMobileUI["red-50"]="rgb(255, 235, 238)",window.colorsMobileUI["red-100"]="rgb(255, 205, 210)",window.colorsMobileUI["red-200"]="rgb(239, 154, 154)",window.colorsMobileUI["red-300"]="rgb(229, 115, 115)",window.colorsMobileUI["red-400"]="rgb(239, 83, 80)",window.colorsMobileUI["red-500"]="rgb(244, 67, 54)",window.colorsMobileUI["red-600"]="rgb(229, 57, 53)",window.colorsMobileUI["red-700"]="rgb(211, 47, 47)",window.colorsMobileUI["red-800"]="rgb(198, 40, 40)",window.colorsMobileUI["red-900"]="rgb(183, 28, 28)",window.colorsMobileUI.pink="rgb(233, 30, 99)",window.colorsMobileUI["pink-50"]="rgb(252, 228, 236)",window.colorsMobileUI["pink-100"]="rgb(248, 187, 208)",window.colorsMobileUI["pink-200"]="rgb(244, 143, 177)",window.colorsMobileUI["Pink-300"]="rgb(240, 98, 146)",window.colorsMobileUI["pink-400"]="rgb(236, 64, 122)",window.colorsMobileUI["pink-500"]="rgb(233, 30, 99)",window.colorsMobileUI["pink-600"]="rgb(216, 27, 96)",window.colorsMobileUI["pink-700"]="rgb(194, 24, 91)",window.colorsMobileUI["pink-800"]="rgb(173, 20, 87)",window.colorsMobileUI["pink-900"]="rgb(136, 14, 79)",window.colorsMobileUI.purple="rgb(156, 39, 176)",window.colorsMobileUI["purple-50"]="rgb(243, 229, 245)",window.colorsMobileUI["purple-100"]="rgb(225, 190, 231)",window.colorsMobileUI["purple-200"]="rgb(206, 147, 216)",window.colorsMobileUI["Purple-300"]="rgb(186, 104, 200)",window.colorsMobileUI["Purple-400"]="rgb(171, 71, 188)",window.colorsMobileUI["purple-500"]="rgb(156, 39, 176)",window.colorsMobileUI["purple-600"]="rgb(142, 36, 170)",window.colorsMobileUI["purple-700"]="rgb(123, 31, 162)",window.colorsMobileUI["purple-800"]="rgb(106, 27, 154)",window.colorsMobileUI["purple-900"]="rgb(74, 20, 140)",window.colorsMobileUI["deep-purple"]="rgb(103, 58, 183)",window.colorsMobileUI["deep-purple-50"]="rgb(237, 231, 246)",window.colorsMobileUI["deep-purple-100"]="rgb(209, 196, 233)",window.colorsMobileUI["deep-purple-200"]="rgb(179, 157, 219)",window.colorsMobileUI["deep-purple-300"]="rgb(149, 117, 205)",window.colorsMobileUI["deep-purple-400"]="rgb(126, 87, 194)",window.colorsMobileUI["deep-purple-500"]="rgb(103, 58, 183)",window.colorsMobileUI["deep-purple-600"]="rgb(94, 53, 177)",window.colorsMobileUI["deep-purple-700"]="rgb(81, 45, 168)",window.colorsMobileUI["deep-purple-800"]="rgb(69, 39, 160)",window.colorsMobileUI["deep-purple-900"]="rgb(49, 27, 146)",window.colorsMobileUI.indigo="rgb(63, 81, 181)",window.colorsMobileUI["indigo-50"]="rgb(232, 234, 246)",window.colorsMobileUI["indigo-100"]="rgb(197, 202, 233)",window.colorsMobileUI["indigo-200"]="rgb(159, 168, 218)",window.colorsMobileUI["indigo-300"]="rgb(121, 134, 203)",window.colorsMobileUI["indigo-400"]="rgb(92, 107, 192)",window.colorsMobileUI["indigo-500"]="rgb(63, 81, 181)",window.colorsMobileUI["indigo-600"]="rgb(57, 73, 171)",window.colorsMobileUI["indigo-700"]="rgb(48, 63, 159)",window.colorsMobileUI["indigo-800"]="rgb(40, 53, 147)",window.colorsMobileUI["indigo-900"]="rgb(26, 35, 126)",window.colorsMobileUI.blue="rgb(33, 150, 243)",window.colorsMobileUI["blue-50"]="rgb(227, 242, 253)",window.colorsMobileUI["blue-100"]="rgb(187, 222, 251)",window.colorsMobileUI["blue-200"]="rgb(144, 202, 249)",window.colorsMobileUI["blue-300"]="rgb(100, 181, 246)",window.colorsMobileUI["blue-400"]="rgb(66, 165, 245)",window.colorsMobileUI["blue-500"]="rgb(33, 150, 243)",window.colorsMobileUI["blue-600"]="rgb(30, 136, 229)",window.colorsMobileUI["blue-700"]="rgb(25, 118, 210)",window.colorsMobileUI["blue-800"]="rgb(21, 101, 192)",window.colorsMobileUI["blue-900"]="rgb(13, 71, 161)",window.colorsMobileUI["light-blue"]="rgb(3, 169, 244)",window.colorsMobileUI["light-blue-50"]="rgb(225, 245, 254)",window.colorsMobileUI["light-blue-100"]="rgb(179, 229, 252)",window.colorsMobileUI["light-blue-200"]="rgb(129, 212, 250)",window.colorsMobileUI["light-blue-300"]="rgb(79, 195, 247)",window.colorsMobileUI["light-blue-400"]="rgb(41, 182, 246)",window.colorsMobileUI["light-blue-500"]="rgb(3, 169, 244)",window.colorsMobileUI["light-blue-600"]="rgb(3, 155, 229)",window.colorsMobileUI["light-blue-700"]="rgb(2, 136, 209)",window.colorsMobileUI["light-blue-800"]="rgb(2, 119, 189)",window.colorsMobileUI["light-blue-900"]="rgb(1, 87, 155)",window.colorsMobileUI.cyan="rgb(0, 188, 212)",window.colorsMobileUI["cyan-50"]="rgb(224, 247, 250)",window.colorsMobileUI["cyan-100"]="rgb(178, 235, 242)",window.colorsMobileUI["cyan-200"]="rgb(128, 222, 234)",window.colorsMobileUI["cyan-300"]="rgb(77, 208, 225)",window.colorsMobileUI["cyan-400"]="rgb(38, 198, 218)",window.colorsMobileUI["cyan-500"]="rgb(0, 188, 212)",window.colorsMobileUI["cyan-600"]="rgb(0, 172, 193)",window.colorsMobileUI["cyan-700"]="rgb(0, 151, 167)",window.colorsMobileUI["cyan-800"]="rgb(0, 131, 143)",window.colorsMobileUI["cyan-900"]="rgb(0, 96, 100)",window.colorsMobileUI.teal="rgb(0, 150, 136)",window.colorsMobileUI["teal-50"]="rgb(224, 242, 241)",window.colorsMobileUI["teal-100"]="rgb(178, 223, 219)",window.colorsMobileUI["teal-200"]="rgb(128, 203, 196)",window.colorsMobileUI["teal-300"]="rgb(77, 182, 172)",window.colorsMobileUI["teal-400"]="rgb(38, 166, 154)",window.colorsMobileUI["teal-500"]="rgb(0, 150, 136)",window.colorsMobileUI["teal-600"]="rgb(0, 137, 123)",window.colorsMobileUI["teal-700"]="rgb(0, 121, 107)",window.colorsMobileUI["teal-800"]="rgb(0, 105, 92)",window.colorsMobileUI["teal-900"]="rgb(0, 77, 64)",window.colorsMobileUI.green="rgb(76, 175, 80)",window.colorsMobileUI["green-50"]="rgb(232, 245, 233)",window.colorsMobileUI["green-100"]="rgb(200, 230, 201)",window.colorsMobileUI["green-200"]="rgb(165, 214, 167)",window.colorsMobileUI["green-300"]="rgb(129, 199, 132)",window.colorsMobileUI["green-400"]="rgb(102, 187, 106)",window.colorsMobileUI["green-500"]="rgb(76, 175, 80)",window.colorsMobileUI["green-600"]="rgb(67, 160, 71)",window.colorsMobileUI["green-700"]="rgb(56, 142, 60)",window.colorsMobileUI["green-800"]="rgb(46, 125, 50)",window.colorsMobileUI["green-900"]="rgb(27, 94, 32)",window.colorsMobileUI["light-green"]="rgb(139, 195, 74)",window.colorsMobileUI["light-green-50"]="rgb(241, 248, 233)",window.colorsMobileUI["light-green-100"]="rgb(220, 237, 200)",window.colorsMobileUI["light-green-200"]="rgb(197, 225, 165)",window.colorsMobileUI["light-green-300"]="rgb(174, 213, 129)",window.colorsMobileUI["light-green-400"]="rgb(156, 204, 101)",window.colorsMobileUI["light-green-500"]="rgb(139, 195, 74)",window.colorsMobileUI["light-green-600"]="rgb(124, 179, 66)",window.colorsMobileUI["light-green-700"]="rgb(104, 159, 56)",window.colorsMobileUI["light-green-800"]="rgb(85, 139, 47)",window.colorsMobileUI["light-green-900"]="rgb(51, 105, 30)",window.colorsMobileUI.lime="rgb(205, 220, 57)",window.colorsMobileUI["lime-50"]="rgb(249, 251, 231)",window.colorsMobileUI["lime-100"]="rgb(240, 244, 195)",window.colorsMobileUI["lime-200"]="rgb(230, 238, 156)",window.colorsMobileUI["lime-300"]="rgb(220, 231, 117)",window.colorsMobileUI["lime-400"]="rgb(212, 225, 87)",window.colorsMobileUI["lime-500"]="rgb(205, 220, 57)",window.colorsMobileUI["lime-600"]="rgb(192, 202, 51)",window.colorsMobileUI["lime-700"]="rgb(175, 180, 43)",window.colorsMobileUI["lime-800"]="rgb(158, 157, 36)",window.colorsMobileUI["lime-900"]="rgb(130, 119, 23)",window.colorsMobileUI.yellow="rgb(255, 235, 59)",window.colorsMobileUI["yellow-50"]="rgb(255, 253, 231)",window.colorsMobileUI["yellow-100"]="rgb(255, 249, 196)",window.colorsMobileUI["yellow-200"]="rgb(255, 245, 157)",window.colorsMobileUI["yellow-300"]="rgb(255, 241, 118)",window.colorsMobileUI["yellow-400"]="rgb(255, 238, 88)",window.colorsMobileUI["yellow-500"]="rgb(255, 235, 59)",window.colorsMobileUI["yellow-600"]="rgb(253, 216, 53)",window.colorsMobileUI["yellow-700"]="rgb(251, 192, 45)",window.colorsMobileUI["yellow-800"]="rgb(249, 168, 37)",window.colorsMobileUI["yellow-900"]="rgb(245, 127, 23)",window.colorsMobileUI.amber="rgb(255, 193, 7)",window.colorsMobileUI["amber-50"]="rgb(255, 248, 225)",window.colorsMobileUI["amber-100"]="rgb(255, 236, 179)",window.colorsMobileUI["amber-200"]="rgb(255, 224, 130)",window.colorsMobileUI["amber-300"]="rgb(255, 213, 79)",window.colorsMobileUI["amber-400"]="rgb(255, 202, 40)",window.colorsMobileUI["amber-500"]="rgb(255, 193, 7)",window.colorsMobileUI["amber-600"]="rgb(255, 179, 0)",window.colorsMobileUI["amber-700"]="rgb(255, 160, 0)",window.colorsMobileUI["amber-800"]="rgb(255, 143, 0)",window.colorsMobileUI["amber-900"]="rgb(255, 111, 0)",window.colorsMobileUI.orange="rgb(255, 152, 0)",window.colorsMobileUI["orange-50"]="rgb(255, 243, 224)",window.colorsMobileUI["orange-100"]="rgb(255, 224, 178)",window.colorsMobileUI["orange-200"]="rgb(255, 204, 128)",window.colorsMobileUI["orange-300"]="rgb(255, 183, 77)",window.colorsMobileUI["orange-400"]="rgb(255, 167, 38)",window.colorsMobileUI["orange-500"]="rgb(255, 152, 0)",window.colorsMobileUI["orange-600"]="rgb(251, 140, 0)",window.colorsMobileUI["orange-700"]="rgb(245, 124, 0)",window.colorsMobileUI["orange-800"]="rgb(239, 108, 0)",window.colorsMobileUI["orange-900"]="rgb(230, 81, 0)",window.colorsMobileUI["deep-orange"]="rgb(255, 87, 34)",window.colorsMobileUI["deep-orange-50"]="rgb(251, 233, 231)",window.colorsMobileUI["deep-orange-100"]="rgb(255, 204, 188)",window.colorsMobileUI["deep-orange-200"]="rgb(255, 171, 145)",window.colorsMobileUI["deep-orange-300"]="rgb(255, 138, 101)",window.colorsMobileUI["deep-orange-400"]="rgb(255, 112, 67)",window.colorsMobileUI["deep-orange-500"]="rgb(255, 87, 34)",window.colorsMobileUI["deep-orange-600"]="rgb(244, 81, 30)",window.colorsMobileUI["deep-orange-700"]="rgb(230, 74, 25)",window.colorsMobileUI["deep-orange-800"]="rgb(216, 67, 21)",window.colorsMobileUI["deep-orange-900"]="rgb(191, 54, 12)",window.colorsMobileUI.brown="rgb(121, 85, 72)",window.colorsMobileUI["brown-50"]="rgb(239, 235, 233)",window.colorsMobileUI["brown-100"]="rgb(215, 204, 200)",window.colorsMobileUI["brown-200"]="rgb(188, 170, 164)",window.colorsMobileUI["brown-300"]="rgb(161, 136, 127)",window.colorsMobileUI["brown-400"]="rgb(141, 110, 99)",window.colorsMobileUI["brown-500"]="rgb(121, 85, 72)",window.colorsMobileUI["brown-600"]="rgb(109, 76, 65)",window.colorsMobileUI["brown-700"]="rgb(93, 64, 55)",window.colorsMobileUI["brown-800"]="rgb(78, 52, 46)",window.colorsMobileUI["brown-900"]="rgb(62, 39, 35)",window.colorsMobileUI.grey="rgb(158, 158, 158)",window.colorsMobileUI["grey-50"]="rgb(250, 250, 250)",window.colorsMobileUI["grey-100"]="rgb(245, 245, 245)",window.colorsMobileUI["grey-200"]="rgb(238, 238, 238)",window.colorsMobileUI["grey-300"]="rgb(224, 224, 224)",window.colorsMobileUI["grey-400"]="rgb(189, 189, 189)",window.colorsMobileUI["grey-500"]="rgb(158, 158, 158)",window.colorsMobileUI["grey-600"]="rgb(117, 117, 117)",window.colorsMobileUI["grey-700"]="rgb(97, 97, 97)",window.colorsMobileUI["grey-800"]="rgb(66, 66, 66)",window.colorsMobileUI["grey-900"]="rgb(33, 33, 33)",window.colorsMobileUI["blue-grey"]="rgb(96, 125, 139)",window.colorsMobileUI["blue-grey-50"]="rgb(236, 239, 241)",window.colorsMobileUI["blue-grey-100"]="rgb(207, 216, 220)",window.colorsMobileUI["blue-grey-200"]="rgb(176, 190, 197)",window.colorsMobileUI["blue-grey-300"]="rgb(144, 164, 174)",window.colorsMobileUI["blue-grey-400"]="rgb(120, 144, 156)",window.colorsMobileUI["blue-grey-500"]="rgb(96, 125, 139)",window.colorsMobileUI["blue-grey-600"]="rgb(84, 110, 122)",window.colorsMobileUI["blue-grey-700"]="rgb(69, 90, 100)",window.colorsMobileUI["blue-grey-800"]="rgb(55, 71, 79)",window.colorsMobileUI["blue-grey-900"]="rgb(38, 50, 56)",window.colorsMobileUI.black="rgb(0, 0, 0)",window.colorsMobileUI.white="rgb(255, 255, 255)",window.colorsMobileUI["black-opacity-90"]="rgba(0, 0, 0, 0.9)",window.colorsMobileUI["white-opacity-90"]="rgba(255, 255, 255, 0.9)",window.colorsMobileUI["black-opacity-70"]="rgba(0, 0, 0, 0.8)",window.colorsMobileUI["white-opacity-70"]="rgba(255, 255, 255, 0.7)",window.colorsMobileUI["black-opacity-50"]="rgba(0, 0, 0, 0.7)",window.colorsMobileUI["white-opacity-50"]="rgba(255, 255, 255, 0.5)",window.colorsMobileUI["black-opacity-30"]="rgba(0, 0, 0, 0.6)",window.colorsMobileUI["white-opacity-30"]="rgba(255, 255, 255, 0.3)",window.colorsMobileUI["black-opacity-10"]="rgba(0, 0, 0, 0.5)",window.colorsMobileUI["white-opacity-10"]="rgba(255, 255, 255, 0.1)";
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileuijs.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileuijs.min.js
new file mode 100755
index 0000000..4a7e1b6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/mobileuijs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).superagent=t()}}(function(){return function t(e,r,n){function i(s,a){if(!r[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var h=r[s]={exports:{}};e[s][0].call(h.exports,function(t){return i(e[s][1][t]||t)},h,h.exports,t,e,r,n)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s<n.length;s++)i(n[s]);return i}({1:[function(t,e,r){var n=t("./is-object");e.exports=function(t){return"[object Function]"===(n(t)?Object.prototype.toString.call(t):"")}},{"./is-object":2}],2:[function(t,e,r){e.exports=function(t){return null!==t&&"object"==typeof t}},{}],3:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}var i=t("./is-object");e.exports=n,n.prototype.clearTimeout=function(){return clearTimeout(this._timer),clearTimeout(this._responseTimeoutTimer),delete this._timer,delete this._responseTimeoutTimer,this},n.prototype.parse=function(t){return this._parser=t,this},n.prototype.responseType=function(t){return this._responseType=t,this},n.prototype.serialize=function(t){return this._serializer=t,this},n.prototype.timeout=function(t){if(!t||"object"!=typeof t)return this._timeout=t,this._responseTimeout=0,this;for(var e in t)switch(e){case"deadline":this._timeout=t.deadline;break;case"response":this._responseTimeout=t.response;break;default:console.warn("Unknown timeout option",e)}return this},n.prototype.retry=function(t){return 0!==arguments.length&&!0!==t||(t=1),t<=0&&(t=0),this._maxRetries=t,this._retries=0,this},n.prototype._retry=function(){return this.clearTimeout(),this.req&&(this.req=null,this.req=this.request()),this._aborted=!1,this.timedout=!1,this._end()},n.prototype.then=function(t,e){if(!this._fullfilledPromise){var r=this;this._endCalled&&console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises"),this._fullfilledPromise=new Promise(function(t,e){r.end(function(r,n){r?e(r):t(n)})})}return this._fullfilledPromise.then(t,e)},n.prototype.catch=function(t){return this.then(void 0,t)},n.prototype.use=function(t){return t(this),this},n.prototype.ok=function(t){if("function"!=typeof t)throw Error("Callback required");return this._okCallback=t,this},n.prototype._isResponseOK=function(t){return!!t&&(this._okCallback?this._okCallback(t):t.status>=200&&t.status<300)},n.prototype.get=function(t){return this._header[t.toLowerCase()]},n.prototype.getHeader=n.prototype.get,n.prototype.set=function(t,e){if(i(t)){for(var r in t)this.set(r,t[r]);return this}return this._header[t.toLowerCase()]=e,this.header[t]=e,this},n.prototype.unset=function(t){return delete this._header[t.toLowerCase()],delete this.header[t],this},n.prototype.field=function(t,e){if(null===t||void 0===t)throw new Error(".field(name, val) name can not be empty");if(this._data&&console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()"),i(t)){for(var r in t)this.field(r,t[r]);return this}if(Array.isArray(e)){for(var n in e)this.field(t,e[n]);return this}if(null===e||void 0===e)throw new Error(".field(name, val) val can not be empty");return"boolean"==typeof e&&(e=""+e),this._getFormData().append(t,e),this},n.prototype.abort=function(){return this._aborted?this:(this._aborted=!0,this.xhr&&this.xhr.abort(),this.req&&this.req.abort(),this.clearTimeout(),this.emit("abort"),this)},n.prototype.withCredentials=function(t){return void 0==t&&(t=!0),this._withCredentials=t,this},n.prototype.redirects=function(t){return this._maxRedirects=t,this},n.prototype.toJSON=function(){return{method:this.method,url:this.url,data:this._data,headers:this._header}},n.prototype.send=function(t){var e=i(t),r=this._header["content-type"];if(this._formData&&console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()"),e&&!this._data)Array.isArray(t)?this._data=[]:this._isHost(t)||(this._data={});else if(t&&this._data&&this._isHost(this._data))throw Error("Can't merge these send calls");if(e&&i(this._data))for(var n in t)this._data[n]=t[n];else"string"==typeof t?(r||this.type("form"),r=this._header["content-type"],this._data="application/x-www-form-urlencoded"==r?this._data?this._data+"&"+t:t:(this._data||"")+t):this._data=t;return!e||this._isHost(t)?this:(r||this.type("json"),this)},n.prototype.sortQuery=function(t){return this._sort=void 0===t||t,this},n.prototype._timeoutError=function(t,e,r){if(!this._aborted){var n=new Error(t+e+"ms exceeded");n.timeout=e,n.code="ECONNABORTED",n.errno=r,this.timedout=!0,this.abort(),this.callback(n)}},n.prototype._setTimeouts=function(){var t=this;this._timeout&&!this._timer&&(this._timer=setTimeout(function(){t._timeoutError("Timeout of ",t._timeout,"ETIME")},this._timeout)),this._responseTimeout&&!this._responseTimeoutTimer&&(this._responseTimeoutTimer=setTimeout(function(){t._timeoutError("Response timeout of ",t._responseTimeout,"ETIMEDOUT")},this._responseTimeout))}},{"./is-object":2}],4:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}var i=t("./utils");e.exports=n,n.prototype.get=function(t){return this.header[t.toLowerCase()]},n.prototype._setHeaderProperties=function(t){var e=t["content-type"]||"";this.type=i.type(e);var r=i.params(e);for(var n in r)this[n]=r[n];this.links={};try{t.link&&(this.links=i.parseLinks(t.link))}catch(t){}},n.prototype._setStatusProperties=function(t){var e=t/100|0;this.status=this.statusCode=t,this.statusType=e,this.info=1==e,this.ok=2==e,this.redirect=3==e,this.clientError=4==e,this.serverError=5==e,this.error=(4==e||5==e)&&this.toError(),this.accepted=202==t,this.noContent=204==t,this.badRequest=400==t,this.unauthorized=401==t,this.notAcceptable=406==t,this.forbidden=403==t,this.notFound=404==t}},{"./utils":6}],5:[function(t,e,r){var n=["ECONNRESET","ETIMEDOUT","EADDRINFO","ESOCKETTIMEDOUT"];e.exports=function(t,e){return!!(t&&t.code&&~n.indexOf(t.code)||e&&e.status&&e.status>=500||t&&"timeout"in t&&"ECONNABORTED"==t.code||t&&"crossDomain"in t)}},{}],6:[function(t,e,r){r.type=function(t){return t.split(/ *; */).shift()},r.params=function(t){return t.split(/ *; */).reduce(function(t,e){var r=e.split(/ *= */),n=r.shift(),i=r.shift();return n&&i&&(t[n]=i),t},{})},r.parseLinks=function(t){return t.split(/ *, */).reduce(function(t,e){var r=e.split(/ *; */),n=r[0].slice(1,-1);return t[r[1].split(/ *= */)[1].slice(1,-1)]=n,t},{})},r.cleanHeader=function(t,e){return delete t["content-type"],delete t["content-length"],delete t["transfer-encoding"],delete t.host,e&&delete t.cookie,t}},{}],7:[function(t,e,r){function n(t){if(t)return function(t){for(var e in n.prototype)t[e]=n.prototype[e];return t}(t)}void 0!==e&&(e.exports=n),n.prototype.on=n.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},n.prototype.once=function(t,e){function r(){this.off(t,r),e.apply(this,arguments)}return r.fn=e,this.on(t,r),this},n.prototype.off=n.prototype.removeListener=n.prototype.removeAllListeners=n.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var r=this._callbacks["$"+t];if(!r)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var n,i=0;i<r.length;i++)if((n=r[i])===e||n.fn===e){r.splice(i,1);break}return this},n.prototype.emit=function(t){this._callbacks=this._callbacks||{};var e=[].slice.call(arguments,1),r=this._callbacks["$"+t];if(r)for(var n=0,i=(r=r.slice(0)).length;n<i;++n)r[n].apply(this,e);return this},n.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks["$"+t]||[]},n.prototype.hasListeners=function(t){return!!this.listeners(t).length}},{}],8:[function(t,e,r){function n(t){if(!p(t))return t;var e=[];for(var r in t)i(e,r,t[r]);return e.join("&")}function i(t,e,r){if(null!=r)if(Array.isArray(r))r.forEach(function(r){i(t,e,r)});else if(p(r))for(var n in r)i(t,e+"["+n+"]",r[n]);else t.push(encodeURIComponent(e)+"="+encodeURIComponent(r));else null===r&&t.push(encodeURIComponent(e))}function o(t){for(var e,r,n={},i=t.split("&"),o=0,s=i.length;o<s;++o)e=i[o],-1==(r=e.indexOf("="))?n[decodeURIComponent(e)]="":n[decodeURIComponent(e.slice(0,r))]=decodeURIComponent(e.slice(r+1));return n}function s(t){return/[\/+]json\b/.test(t)}function a(t){this.req=t,this.xhr=this.req.xhr,this.text="HEAD"!=this.req.method&&(""===this.xhr.responseType||"text"===this.xhr.responseType)||void 0===this.xhr.responseType?this.xhr.responseText:null,this.statusText=this.req.xhr.statusText;var e=this.xhr.status;1223===e&&(e=204),this._setStatusProperties(e),this.header=this.headers=function(t){var e,r,n,i,o=t.split(/\r?\n/),s={};o.pop();for(var a=0,u=o.length;a<u;++a)r=o[a],e=r.indexOf(":"),n=r.slice(0,e).toLowerCase(),i=v(r.slice(e+1)),s[n]=i;return s}(this.xhr.getAllResponseHeaders()),this.header["content-type"]=this.xhr.getResponseHeader("content-type"),this._setHeaderProperties(this.header),null===this.text&&t._responseType?this.body=this.xhr.response:this.body="HEAD"!=this.req.method?this._parseBody(this.text?this.text:this.xhr.response):null}function u(t,e){var r=this;this._query=this._query||[],this.method=t,this.url=e,this.header={},this._header={},this.on("end",function(){var t=null,e=null;try{e=new a(r)}catch(e){return t=new Error("Parser is unable to parse the response"),t.parse=!0,t.original=e,r.xhr?(t.rawResponse=void 0===r.xhr.responseType?r.xhr.responseText:r.xhr.response,t.status=r.xhr.status?r.xhr.status:null,t.statusCode=t.status):(t.rawResponse=null,t.status=null),r.callback(t)}r.emit("response",e);var n;try{r._isResponseOK(e)||(n=new Error(e.statusText||"Unsuccessful HTTP response"),n.original=t,n.response=e,n.status=e.status)}catch(t){n=t}n?r.callback(n,e):r.callback(null,e)})}function c(t,e,r){var n=b("DELETE",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n}var h;"undefined"!=typeof window?h=window:"undefined"!=typeof self?h=self:(console.warn("Using browser-only version of superagent in non-browser environment"),h=this);var l=t("component-emitter"),d=t("./request-base"),p=t("./is-object"),f=t("./is-function"),y=t("./response-base"),m=t("./should-retry"),b=r=e.exports=function(t,e){return"function"==typeof e?new r.Request("GET",t).end(e):1==arguments.length?new r.Request("GET",t):new r.Request(t,e)};r.Request=u,b.getXHR=function(){if(!(!h.XMLHttpRequest||h.location&&"file:"==h.location.protocol&&h.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(t){}throw Error("Browser-only verison of superagent could not find XHR")};var v="".trim?function(t){return t.trim()}:function(t){return t.replace(/(^\s*|\s*$)/g,"")};b.serializeObject=n,b.parseString=o,b.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},b.serialize={"application/x-www-form-urlencoded":n,"application/json":JSON.stringify},b.parse={"application/x-www-form-urlencoded":o,"application/json":JSON.parse},y(a.prototype),a.prototype._parseBody=function(t){var e=b.parse[this.type];return this.req._parser?this.req._parser(this,t):(!e&&s(this.type)&&(e=b.parse["application/json"]),e&&t&&(t.length||t instanceof Object)?e(t):null)},a.prototype.toError=function(){var t=this.req,e=t.method,r=t.url,n="cannot "+e+" "+r+" ("+this.status+")",i=new Error(n);return i.status=this.status,i.method=e,i.url=r,i},b.Response=a,l(u.prototype),d(u.prototype),u.prototype.type=function(t){return this.set("Content-Type",b.types[t]||t),this},u.prototype.accept=function(t){return this.set("Accept",b.types[t]||t),this},u.prototype.auth=function(t,e,r){switch("object"==typeof e&&null!==e&&(r=e),r||(r={type:"function"==typeof btoa?"basic":"auto"}),r.type){case"basic":this.set("Authorization","Basic "+btoa(t+":"+e));break;case"auto":this.username=t,this.password=e;break;case"bearer":this.set("Authorization","Bearer "+t)}return this},u.prototype.query=function(t){return"string"!=typeof t&&(t=n(t)),t&&this._query.push(t),this},u.prototype.attach=function(t,e,r){if(e){if(this._data)throw Error("superagent can't mix .send() and .attach()");this._getFormData().append(t,e,r||e.name)}return this},u.prototype._getFormData=function(){return this._formData||(this._formData=new h.FormData),this._formData},u.prototype.callback=function(t,e){if(this._maxRetries&&this._retries++<this._maxRetries&&m(t,e))return this._retry();var r=this._callback;this.clearTimeout(),t&&(this._maxRetries&&(t.retries=this._retries-1),this.emit("error",t)),r(t,e)},u.prototype.crossDomainError=function(){var t=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");t.crossDomain=!0,t.status=this.status,t.method=this.method,t.url=this.url,this.callback(t)},u.prototype.buffer=u.prototype.ca=u.prototype.agent=function(){return console.warn("This is not supported in browser version of superagent"),this},u.prototype.pipe=u.prototype.write=function(){throw Error("Streaming is not supported in browser version of superagent")},u.prototype._appendQueryString=function(){var t=this._query.join("&");if(t&&(this.url+=(this.url.indexOf("?")>=0?"&":"?")+t),this._sort){var e=this.url.indexOf("?");if(e>=0){var r=this.url.substring(e+1).split("&");f(this._sort)?r.sort(this._sort):r.sort(),this.url=this.url.substring(0,e)+"?"+r.join("&")}}},u.prototype._isHost=function(t){return t&&"object"==typeof t&&!Array.isArray(t)&&"[object Object]"!==Object.prototype.toString.call(t)},u.prototype.end=function(t){return this._endCalled&&console.warn("Warning: .end() was called twice. This is not supported in superagent"),this._endCalled=!0,this._callback=t||function(){},this._appendQueryString(),this._end()},u.prototype._end=function(){var t=this,e=this.xhr=b.getXHR(),r=this._formData||this._data;this._setTimeouts(),e.onreadystatechange=function(){var r=e.readyState;if(r>=2&&t._responseTimeoutTimer&&clearTimeout(t._responseTimeoutTimer),4==r){var n;try{n=e.status}catch(t){n=0}if(!n){if(t.timedout||t._aborted)return;return t.crossDomainError()}t.emit("end")}};var n=function(e,r){r.total>0&&(r.percent=r.loaded/r.total*100),r.direction=e,t.emit("progress",r)};if(this.hasListeners("progress"))try{e.onprogress=n.bind(null,"download"),e.upload&&(e.upload.onprogress=n.bind(null,"upload"))}catch(t){}try{this.username&&this.password?e.open(this.method,this.url,!0,this.username,this.password):e.open(this.method,this.url,!0)}catch(t){return this.callback(t)}if(this._withCredentials&&(e.withCredentials=!0),!this._formData&&"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof r&&!this._isHost(r)){var i=this._header["content-type"],o=this._serializer||b.serialize[i?i.split(";")[0]:""];!o&&s(i)&&(o=b.serialize["application/json"]),o&&(r=o(r))}for(var a in this.header)null!=this.header[a]&&this.header.hasOwnProperty(a)&&e.setRequestHeader(a,this.header[a]);return this._responseType&&(e.responseType=this._responseType),this.emit("request",this),e.send(void 0!==r?r:null),this},b.get=function(t,e,r){var n=b("GET",t);return"function"==typeof e&&(r=e,e=null),e&&n.query(e),r&&n.end(r),n},b.head=function(t,e,r){var n=b("HEAD",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.options=function(t,e,r){var n=b("OPTIONS",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.del=c,b.delete=c,b.patch=function(t,e,r){var n=b("PATCH",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.post=function(t,e,r){var n=b("POST",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n},b.put=function(t,e,r){var n=b("PUT",t);return"function"==typeof e&&(r=e,e=null),e&&n.send(e),r&&n.end(r),n}},{"./is-function":1,"./is-object":2,"./request-base":3,"./response-base":4,"./should-retry":5,"component-emitter":7}]},{},[8])(8)}),function(){var observerWatchers=[],tokenObserver=0,dataBind=function(){for(var t=document.querySelectorAll("[data]"),e=0;e<t.length;e++)if(t[e].getAttribute("data")&&!t[e].getAttribute("data-binded")){var r=t[e].getAttribute("data");(r=fetchFromObject(window,r))&&(writeElement(t[e],r),t[e].setAttribute("data-binded","mobileui"),dataObserver(t[e].getAttribute("data"),tokenObserver++))}eventLoopBind()};eventLoopBind=function(){setTimeout(function(){dataBind()},100)},reDataBind=function(t){for(var e=fetchFromObject(window,t.dataKey),r=document.querySelectorAll("[data-binded]"),n=0;n<r.length;n++)r[n].getAttribute("data-binded")===t.dataKey&&r[n].parentNode.removeChild(r[n]);r=document.querySelectorAll("[data][data-binded]");for(n=0;n<r.length;n++)r[n].getAttribute("data")===t.dataKey&&writeElement(r[n],e);t.dataValue=copyObj(e)},writeElement=function(elm,data){var bindWriteElement=function(dataObj,index){for(var html=elm.outerHTML,exp=/\${/g;match=exp.exec(html);){var prop=html.slice(match.index+2,html.length).split("}")[0],value=fetchFromObject(dataObj,prop);html=html.replace("${"+prop+"}",value)}index&&(html=html.replace(new RegExp("\\$\\$index","g"),index));for(var functionBind=html.split("$$"),i=1;i<functionBind.length;i++){var prop=functionBind[i].split("{")[1].split(",")[0].split("}")[0],value=fetchFromObject(dataObj,prop),functionName=functionBind[i].split("{")[0],functionReplace=functionBind[i].split("}")[0]+"}",functionInvoke="window.MobileUI."+functionBind[i].split("}")[0].replace(prop,"'"+value+"'").replace("{","(")+")",valueBind=eval(functionInvoke);html=html.replace(new RegExp("\\$\\$"+functionReplace,"g"),valueBind)}var divBind=document.createElement("div");elm.parentNode.insertBefore(divBind,elm),html=html.replace("data=","data-binded="),divBind.outerHTML=html};if(data.constructor===Array)for(var id in data)bindWriteElement(data[id],id);else bindWriteElement(data)},fetchFromObject=function(t,e){if(void 0===t)return console.error("Object for property ",e," is undefined!"),"";var r=e.indexOf(".");return r>-1?fetchFromObject(t[e.substring(0,r)],e.substr(r+1)):t.constructor===String||t.constructor===Number||t.constructor===Boolean||t.constructor===Date?t||"":t[e]?t[e]:""},dispatchEventObserver=function(t){var e=new CustomEvent("dataUpdated",{detail:{dataKey:t.dataKey,dataValue:t.dataValue}});document.dispatchEvent(e)},dataObserver=function(t,e){observerWatchers[e]||(observerWatchers[e]={dataKey:t,dataValue:copyObj(fetchFromObject(window,t))});var r=fetchFromObject(window,observerWatchers[e].dataKey);observerWatchers[e].dataValue.constructor===Array&&observerWatchers[e].dataValue.length!==r.length?(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])):observerWatchers[e].dataValue.constructor===Array&&observerWatchers[e].dataValue.toString()!==r.toString()?(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])):JSON.stringify(observerWatchers[e].dataValue)!==JSON.stringify(r)&&(reDataBind(observerWatchers[e]),dispatchEventObserver(observerWatchers[e])),setTimeout(function(){dataObserver(t,e)},100)},copyObj=function(t){return JSON.parse(JSON.stringify(t))},dataBind(),window.MobileUI={bind:function(){dataBind()},objectByForm:function(t){for(var e=document.getElementById(t),r={},n=e.querySelectorAll("input,textarea,select"),i=0;i<n.length;i++)if(n[i].id&&"checkbox"===n[i].type)r[n[i].id]=n[i].checked;else if(n[i].name&&"radio"===n[i].type){var o=e.querySelector('input[name="'+n[i].name+'"]:checked').value;o&&(r[n[i].name]=o)}else n[i].id&&(r[n[i].id]=n[i].value);return r},disable:function(t){for(var e=document.getElementById(t).querySelectorAll("input,textarea,select,button,a"),r=0;r<e.length;r++)e[r].setAttribute("disabled","disabled")},enable:function(t){for(var e=document.getElementById(t).querySelectorAll("input,textarea,select,button,a"),r=0;r<e.length;r++)e[r].removeAttribute("disabled")},formByObject:function(t,e){for(var r=document.getElementById(t),n=r.querySelectorAll("input,textarea,select"),i=0;i<n.length;i++)if(n[i].id&&"checkbox"===n[i].type)n[i].checked=e[n[i].id];else if(n[i].name&&"radio"===n[i].type){var o=r.querySelector('input[name="'+n[i].name+'"][value="'+e[n[i].name]+'"]');o&&(o.checked=!0)}else n[i].id&&e[n[i].id]&&(n[i].value=e[n[i].id])},clearForm:function(t){for(var e=document.getElementById(t),r=e.querySelectorAll("input,textarea,select"),n=0;n<r.length;n++)if(r[n].id&&r[n].type.indexOf("select")>=0){for(var i=r[n].options,o=0;o<i.length;o++)i[o].defaultSelected&&(r[n].selectedIndex=o,r[n].found=!0);r[n].found||(r[n].selectedIndex=0)}else r[n].id&&"checkbox"===r[n].type?r[n].checked=null!==r[n].getAttribute("checked"):r[n].name&&"radio"===r[n].type?e.querySelector('input[name="'+r[n].name+'"][checked]').checked=!0:r[n].id&&(r[n].value="")},show:function(t){document.getElementById(t).style.display="block"},hide:function(t){document.getElementById(t).style.display="none"},showHide:function(t){null===document.getElementById(t).offsetParent?this.show(t):this.hide(t)},focus:function(t){document.getElementById(t).focus()},formatMoney:function(t,e,r,n){var e=isNaN(e=Math.abs(e))?2:e,r=void 0==r?".":r,n=void 0==n?",":n,i=t<0?"-":"",o=String(parseInt(t=Math.abs(Number(t)||0).toFixed(e))),s=(s=o.length)>3?s%3:0;return i+(s?o.substr(0,s)+n:"")+o.substr(s).replace(/(\d{3})(?=\d)/g,"$1"+n)+(e?r+Math.abs(t-o).toFixed(e).slice(2):"")},ajax:superagent}}();
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/momentjs.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/momentjs.min.js
new file mode 100755
index 0000000..a2734f4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/momentjs.min.js
@@ -0,0 +1 @@
+!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 Xe.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 we(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=Ke.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),et.length>0)for(n=0;n<et.length;n++)s(r=t[i=et[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===tt&&(tt=!0,e.updateOffset(this),tt=!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),nt[t]||(w(n),nt[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();it[n]=it[n+"s"]=it[t]=e}function O(e){return"string"==typeof e?it[e]||it[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){rt[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&&(lt[e]=i),t&&(lt[t[0]]=function(){return b(i.apply(this,arguments),t[1],t[2])}),n&&(lt[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()),ut[t]=ut[t]||function(e){var t,n,s=e.match(at);for(t=0,n=s.length;t<n;t++)lt[s[t]]?s[t]=lt[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),ut[t](e)):e.localeData().invalidDate()}function C(e,t){var n=5;for(ot.lastIndex=0;n>=0&&ot.test(e);)e=e.replace(ot,function(e){return t.longDateFormat(e)||e}),ot.lastIndex=0,n-=1;return e}function F(e,t,n){Ot[e]=k(t)?t:function(e,s){return e&&n?n:t}}function U(e,t){return o(Ot,e)?Ot[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++)xt[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(xt,e)&&xt[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())?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(!Kt[e]&&"undefined"!=typeof module&&module&&module.exports){t=Bt._abbr;try{require("moment/locale/"+e)}catch(t){try{require("./locale/"+e)}catch(e){}}ae(t)}return Kt[e]}function ae(e,t){var n;return e&&(n=s(t)?ue(e):oe(e,t))&&(Bt=n),Bt._abbr}function oe(e,t){if(null!==t){var n=Xt;if(t.abbr=e,null!=Kt[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=Kt[e]._config;else if(null!=t.parentLocale){if(null==Kt[t.parentLocale])return en[t.parentLocale]||(en[t.parentLocale]=[]),en[t.parentLocale].push({name:e,config:t}),null;n=Kt[t.parentLocale]._config}return Kt[e]=new D(S(n,t)),en[e]&&en[e].forEach(function(e){oe(e.name,e.config)}),ae(e),Kt[e]}return delete Kt[e],null}function ue(e){var n;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Bt;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[bt]<0||n[bt]>11?bt:n[Pt]<1||n[Pt]>z(n[Tt],n[bt])?Pt:n[Wt]<0||n[Wt]>24||24===n[Wt]&&(0!==n[Rt]||0!==n[Ct]||0!==n[Ft])?Wt:n[Rt]<0||n[Rt]>59?Rt:n[Ct]<0||n[Ct]>59?Ct:n[Ft]<0||n[Ft]>999?Ft:-1,d(e)._overflowDayOfYear&&(t<Tt||t>Pt)&&(t=Pt),d(e)._overflowWeeks&&-1===t&&(t=Ut),d(e)._overflowWeekday&&-1===t&&(t=Nt),d(e).overflow=t),e}function de(e,t,n){return null!=e?e:null!=t?t:n}function he(t){var n=new Date(e.now());return t._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}function ce(e){var t,n,s,i,r=[];if(!e._d){for(s=he(e),e._w&&null==e._a[Pt]&&null==e._a[bt]&&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[Tt],X(ve(),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(ve(),r,a);n=de(t.gg,e._a[Tt],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[Tt]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(i=de(e._a[Tt],s[Tt]),(e._dayOfYear>V(i)||0===e._dayOfYear)&&(d(e)._overflowDayOfYear=!0),n=J(i,0,e._dayOfYear),e._a[bt]=n.getUTCMonth(),e._a[Pt]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=r[t]=s[t];for(;t<7;t++)e._a[t]=r[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[Wt]&&0===e._a[Rt]&&0===e._a[Ct]&&0===e._a[Ft]&&(e._nextDay=!0,e._a[Wt]=0),e._d=(e._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,r),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Wt]=24),e._w&&void 0!==e._w.d&&e._w.d!==e._d.getDay()&&(d(e).weekdayMismatch=!0)}}function fe(e){var t,n,s,i,r,a,o=e._i,u=tn.exec(o)||nn.exec(o);if(u){for(d(e).iso=!0,t=0,n=rn.length;t<n;t++)if(rn[t][1].exec(u[1])){i=rn[t][0],s=!1!==rn[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=an.length;t<n;t++)if(an[t][1].exec(u[3])){r=(u[2]||" ")+an[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!sn.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),ye(e)}else e._isValid=!1}function me(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);return t<=49?2e3+t:t<=999?1900+t:t}(e),jt.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}function _e(e){var t=un.exec(function(e){return e.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim()}(e._i));if(t){var n=me(t[4],t[3],t[2],t[5],t[6],t[7]);if(!function(e,t,n){return!e||zt.indexOf(e)===new Date(t[0],t[1],t[2]).getDay()||(d(n).weekdayMismatch=!0,n._isValid=!1,!1)}(t[1],n,e))return;e._a=n,e._tzm=function(e,t,n){if(e)return ln[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 ye(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(at)||[],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),lt[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[Wt]<=12&&!0===d(t).bigHour&&t._a[Wt]>0&&(d(t).bigHour=void 0),d(t).parsedDateParts=t._a.slice(0),d(t).meridiem=t._meridiem,t._a[Wt]=function(e,t,n){var s;return null==n?t: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[Wt],t._meridiem),ce(t),le(t)}else _e(t);else fe(t)}function ge(e){var n=e._i,s=e._f;return e._locale=e._locale||ue(e._l),null===n||void 0===s&&""===n?c({nullInput:!0}):("string"==typeof n&&(e._i=n=e._locale.preparse(n)),_(n)?new m(le(n)):(r(n)?e._d=n:t(s)?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],ye(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)}(e):s?ye(e):pe(e),h(e)||(e._d=null),e))}function pe(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=on.exec(t._i);null===n?(fe(t),!1===t._isValid&&(delete t._isValid,_e(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)}),ce(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)}),ce(e)}}(o):i(u)?o._d=new Date(u):e.createFromInputFallback(o)}function we(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(ge(e)));return t._nextDay&&(t.add(1,"d"),t._nextDay=void 0),t}(o)}function ve(e,t,n,s){return we(e,t,n,s,!1)}function Me(e,n){var s,i;if(1===n.length&&t(n[0])&&(n=n[0]),!n.length)return ve();for(s=n[0],i=1;i<n.length;++i)n[i].isValid()&&!n[i][e](s)||(s=n[i]);return s}function ke(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===Ht.call(cn,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<cn.length;++s)if(e[cn[s]]){if(n)return!1;parseFloat(e[cn[s]])!==g(e[cn[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 Se(e){return e instanceof ke}function De(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ye(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 Oe(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(fn)||["-",0,0],i=60*s[1]+g(s[2]);return 0===i?0:"+"===s[0]?i:-i}function xe(t,n){var s,i;return n._isUTC?(s=n.clone(),i=(_(t)||r(t)?t.valueOf():ve(t).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),e.updateOffset(s,!1),s):ve(t).local()}function Te(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function be(){return!!this.isValid()&&this._isUTC&&0===this._offset}function Pe(e,t){var n,s,r,a=e,u=null;return Se(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:i(e)?(a={},t?a[t]=e:a.milliseconds=e):(u=mn.exec(e))?(n="-"===u[1]?-1:1,a={y:0,d:g(u[Pt])*n,h:g(u[Wt])*n,m:g(u[Rt])*n,s:g(u[Ct])*n,ms:g(De(1e3*u[Ft]))*n}):(u=_n.exec(e))?(n="-"===u[1]?-1:(u[1],1),a={y:We(u[2],n),M:We(u[3],n),w:We(u[4],n),d:We(u[5],n),h:We(u[6],n),m:We(u[7],n),s:We(u[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(r=function(e,t){var n;return e.isValid()&&t.isValid()?(t=xe(t,e),e.isBefore(t)?n=Re(e,t):((n=Re(t,e)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}(ve(a.from),ve(a.to)),(a={}).ms=r.milliseconds,a.M=r.months),s=new ke(a),Se(e)&&o(e,"_locale")&&(s._locale=e._locale),s}function We(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Re(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 Ce(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=Pe(n,s),Fe(this,i,e),this}}function Fe(t,n,s,i){var r=n._milliseconds,a=De(n._days),o=De(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 Ue(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 Ne(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ue(e))&&(this._locale=t),this)}function He(){return this._locale}function Le(e,t){P(0,[e,e.length],0,t)}function Ge(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 Ve(e){return e}function je(e,t,n,s){var i=ue(),r=l().set(s,t);return i[n](r,e)}function Ie(e,t,n){if(i(e)&&(t=e,e=void 0),e=e||"",null!=t)return je(e,t,n,"month");var s,r=[];for(s=0;s<12;s++)r[s]=je(e,s,n,"month");return r}function Ee(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 je(t,(n+a)%7,s,"day");var o,u=[];for(o=0;o<7;o++)u[o]=je(t,(o+a)%7,s,"day");return u}function Ae(e,t,n,s){var i=Pe(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function ze(e){return e<0?Math.floor(e):Math.ceil(e)}function Ze(e){return 4800*e/146097}function $e(e){return 146097*e/4800}function qe(e){return function(){return this.as(e)}}function Je(e){return function(){return this.isValid()?this._data[e]:NaN}}function Be(e){return(e>0)-(e<0)||+e}function Qe(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,s=An(this._milliseconds)/1e3,i=An(this._days),r=An(this._months);t=y((e=y(s/60))/60),s%=60,e%=60;var a=n=y(r/12),o=r%=12,u=i,l=t,d=e,h=s?s.toFixed(3).replace(/\.?0+$/,""):"",c=this.asSeconds();if(!c)return"P0D";var f=c<0?"-":"",m=Be(this._months)!==Be(c)?"-":"",_=Be(this._days)!==Be(c)?"-":"",g=Be(this._milliseconds)!==Be(c)?"-":"";return f+"P"+(a?m+a+"Y":"")+(o?m+o+"M":"")+(u?_+u+"D":"")+(l||d||h?"T":"")+(l?g+l+"H":"")+(d?g+d+"M":"")+(h?g+h+"S":"")}var Xe,Ke;Ke=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 et=e.momentProperties=[],tt=!1,nt={};e.suppressDeprecationWarnings=!1,e.deprecationHandler=null;var st;st=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)o(e,t)&&n.push(t);return n};var it={},rt={},at=/(\[[^\[]*\])|(\\)?([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,ot=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,ut={},lt={},dt=/\d/,ht=/\d\d/,ct=/\d{3}/,ft=/\d{4}/,mt=/[+-]?\d{6}/,_t=/\d\d?/,yt=/\d\d\d\d?/,gt=/\d\d\d\d\d\d?/,pt=/\d{1,3}/,wt=/\d{1,4}/,vt=/[+-]?\d{1,6}/,Mt=/\d+/,kt=/[+-]?\d+/,St=/Z|[+-]\d\d:?\d\d/gi,Dt=/Z|[+-]\d\d(?::?\d\d)?/gi,Yt=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Ot={},xt={},Tt=0,bt=1,Pt=2,Wt=3,Rt=4,Ct=5,Ft=6,Ut=7,Nt=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",kt),F("YY",_t,ht),F("YYYY",wt,ft),F("YYYYY",vt,mt),F("YYYYYY",vt,mt),H(["YYYYY","YYYYYY"],Tt),H("YYYY",function(t,n){n[Tt]=2===t.length?e.parseTwoDigitYear(t):g(t)}),H("YY",function(t,n){n[Tt]=e.parseTwoDigitYear(t)}),H("Y",function(e,t){t[Tt]=parseInt(e,10)}),e.parseTwoDigitYear=function(e){return g(e)+(g(e)>68?1900:2e3)};var Ht,Lt=I("FullYear",!0);Ht=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",_t),F("MM",_t,ht),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[bt]=g(e)-1}),H(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[bt]=i:d(n).invalidMonth=e});var Gt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Vt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),jt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),It=Yt,Et=Yt;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",_t),F("ww",_t,ht),F("W",_t),F("WW",_t,ht),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",_t),F("e",_t),F("E",_t),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 At="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),zt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Zt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),$t=Yt,qt=Yt,Jt=Yt;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",_t),F("h",_t),F("k",_t),F("HH",_t,ht),F("hh",_t,ht),F("kk",_t,ht),F("hmm",yt),F("hmmss",gt),F("Hmm",yt),F("Hmmss",gt),H(["H","HH"],Wt),H(["k","kk"],function(e,t,n){var s=g(e);t[Wt]=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[Wt]=g(e),d(n).bigHour=!0}),H("hmm",function(e,t,n){var s=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s)),d(n).bigHour=!0}),H("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s,2)),t[Ct]=g(e.substr(i)),d(n).bigHour=!0}),H("Hmm",function(e,t,n){var s=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s))}),H("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Wt]=g(e.substr(0,s)),t[Rt]=g(e.substr(s,2)),t[Ct]=g(e.substr(i))});var Bt,Qt=I("Hours",!0),Xt={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:Vt,monthsShort:jt,week:{dow:0,doy:6},weekdays:At,weekdaysMin:Zt,weekdaysShort:zt,meridiemParse:/[ap]\.?m?\.?/i},Kt={},en={},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=/^\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)?)?$/,sn=/Z|[+-]\d\d(?::?\d\d)?/,rn=[["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}/]],an=[["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/]],on=/^\/?Date\((\-?\d+)/i,un=/^(?:(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}))$/,ln={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 dn=v("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=ve.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:c()}),hn=v("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=ve.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:c()}),cn=["year","quarter","month","week","day","hour","minute","second","millisecond"];Ye("Z",":"),Ye("ZZ",""),F("Z",Dt),F("ZZ",Dt),H(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Oe(Dt,e)});var fn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var mn=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,_n=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Pe.fn=ke.prototype,Pe.invalid=function(){return Pe(NaN)};var yn=Ce(1,"add"),gn=Ce(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var pn=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}),Le("gggg","weekYear"),Le("ggggg","weekYear"),Le("GGGG","isoWeekYear"),Le("GGGGG","isoWeekYear"),Y("weekYear","gg"),Y("isoWeekYear","GG"),T("weekYear",1),T("isoWeekYear",1),F("G",kt),F("g",kt),F("GG",_t,ht),F("gg",_t,ht),F("GGGG",wt,ft),F("gggg",wt,ft),F("GGGGG",vt,mt),F("ggggg",vt,mt),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",dt),H("Q",function(e,t){t[bt]=3*(g(e)-1)}),P("D",["DD",2],"Do","date"),Y("date","D"),T("date",9),F("D",_t),F("DD",_t,ht),F("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),H(["D","DD"],Pt),H("Do",function(e,t){t[Pt]=g(e.match(_t)[0])});var wn=I("Date",!0);P("DDD",["DDDD",3],"DDDo","dayOfYear"),Y("dayOfYear","DDD"),T("dayOfYear",4),F("DDD",pt),F("DDDD",ct),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",_t),F("mm",_t,ht),H(["m","mm"],Rt);var vn=I("Minutes",!1);P("s",["ss",2],0,"second"),Y("second","s"),T("second",15),F("s",_t),F("ss",_t,ht),H(["s","ss"],Ct);var Mn=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",pt,dt),F("SS",pt,ht),F("SSS",pt,ct);var kn;for(kn="SSSS";kn.length<=9;kn+="S")F(kn,Mt);for(kn="S";kn.length<=9;kn+="S")H(kn,function(e,t){t[Ft]=g(1e3*("0."+e))});var Sn=I("Milliseconds",!1);P("z",0,0,"zoneAbbr"),P("zz",0,0,"zoneName");var Dn=m.prototype;Dn.add=yn,Dn.calendar=function(t,n){var s=t||ve(),i=xe(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,ve(s)))},Dn.clone=function(){return new m(this)},Dn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=xe(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=O(t)){case"year":r=Ue(this,s)/12;break;case"month":r=Ue(this,s);break;case"quarter":r=Ue(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)},Dn.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"))},Dn.format=function(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var n=R(this,t);return this.localeData().postformat(n)},Dn.from=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||ve(e).isValid())?Pe({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Dn.fromNow=function(e){return this.from(ve(),e)},Dn.to=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||ve(e).isValid())?Pe({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Dn.toNow=function(e){return this.to(ve(),e)},Dn.get=function(e){return e=O(e),k(this[e])?this[e]():this},Dn.invalidAt=function(){return d(this).overflow},Dn.isAfter=function(e,t){var n=_(e)?e:ve(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},Dn.isBefore=function(e,t){var n=_(e)?e:ve(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},Dn.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))},Dn.isSame=function(e,t){var n,s=_(e)?e:ve(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()))},Dn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},Dn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},Dn.isValid=function(){return h(this)},Dn.lang=pn,Dn.locale=Ne,Dn.localeData=He,Dn.max=hn,Dn.min=dn,Dn.parsingFlags=function(){return u({},d(this))},Dn.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:rt[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},Dn.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},Dn.subtract=gn,Dn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},Dn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},Dn.toDate=function(){return new Date(this.valueOf())},Dn.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]")},Dn.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)},Dn.toJSON=function(){return this.isValid()?this.toISOString():null},Dn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Dn.unix=function(){return Math.floor(this.valueOf()/1e3)},Dn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Dn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Dn.year=Lt,Dn.isLeapYear=function(){return j(this.year())},Dn.weekYear=function(e){return Ge.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Dn.isoWeekYear=function(e){return Ge.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},Dn.quarter=Dn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},Dn.month=$,Dn.daysInMonth=function(){return z(this.year(),this.month())},Dn.week=Dn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},Dn.isoWeek=Dn.isoWeeks=function(e){var t=X(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},Dn.weeksInYear=function(){var e=this.localeData()._week;return K(this.year(),e.dow,e.doy)},Dn.isoWeeksInYear=function(){return K(this.year(),1,4)},Dn.date=wn,Dn.day=Dn.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},Dn.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")},Dn.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},Dn.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")},Dn.hour=Dn.hours=Qt,Dn.minute=Dn.minutes=vn,Dn.second=Dn.seconds=Mn,Dn.millisecond=Dn.milliseconds=Sn,Dn.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=Oe(Dt,t)))return this}else Math.abs(t)<16&&!s&&(t*=60);return!this._isUTC&&n&&(i=Te(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!n||this._changeInProgress?Fe(this,Pe(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Te(this)},Dn.utc=function(e){return this.utcOffset(0,e)},Dn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Te(this),"m")),this},Dn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Oe(St,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},Dn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?ve(e).utcOffset():0,(this.utcOffset()-e)%60==0)},Dn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Dn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Dn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Dn.isUtc=be,Dn.isUTC=be,Dn.zoneAbbr=function(){return this._isUTC?"UTC":""},Dn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Dn.dates=v("dates accessor is deprecated. Use date instead.",wn),Dn.months=v("months accessor is deprecated. Use month instead",$),Dn.years=v("years accessor is deprecated. Use year instead",Lt),Dn.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()}),Dn.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=ge(e))._a){var t=e._isUTC?l(e._a):ve(e._a);this._isDSTShifted=this.isValid()&&p(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var Yn=D.prototype;Yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return k(s)?s.call(t,n):s},Yn.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])},Yn.invalidDate=function(){return this._invalidDate},Yn.ordinal=function(e){return this._ordinal.replace("%d",e)},Yn.preparse=Ve,Yn.postformat=Ve,Yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return k(i)?i(e,t,n,s):i.replace(/%d/i,e)},Yn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return k(n)?n(t):n.replace(/%s/i,t)},Yn.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)},Yn.months=function(e,n){return e?t(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||Gt).test(n)?"format":"standalone"][e.month()]:t(this._months)?this._months:this._months.standalone},Yn.monthsShort=function(e,n){return e?t(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[Gt.test(n)?"format":"standalone"][e.month()]:t(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Yn.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=Ht.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ht.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ht.call(this._shortMonthsParse,a))?i:-1!==(i=Ht.call(this._longMonthsParse,a))?i:null:-1!==(i=Ht.call(this._longMonthsParse,a))?i:-1!==(i=Ht.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}},Yn.monthsRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsStrictRegex:this._monthsRegex):(o(this,"_monthsRegex")||(this._monthsRegex=Et),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},Yn.monthsShortRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(o(this,"_monthsShortRegex")||(this._monthsShortRegex=It),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},Yn.week=function(e){return X(e,this._week.dow,this._week.doy).week},Yn.firstDayOfYear=function(){return this._week.doy},Yn.firstDayOfWeek=function(){return this._week.dow},Yn.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},Yn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},Yn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},Yn.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=Ht.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ht.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ht.call(this._minWeekdaysParse,a))?i:-1!==(i=Ht.call(this._weekdaysParse,a))?i:-1!==(i=Ht.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}},Yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(o(this,"_weekdaysRegex")||(this._weekdaysRegex=$t),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},Yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(o(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qt),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(o(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Jt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},Yn.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 On=Math.abs,xn=qe("ms"),Tn=qe("s"),bn=qe("m"),Pn=qe("h"),Wn=qe("d"),Rn=qe("w"),Cn=qe("M"),Fn=qe("y"),Un=Je("milliseconds"),Nn=Je("seconds"),Hn=Je("minutes"),Ln=Je("hours"),Gn=Je("days"),Vn=Je("months"),jn=Je("years"),In=Math.round,En={ss:44,s:45,m:45,h:22,d:26,M:11},An=Math.abs,zn=ke.prototype;return zn.isValid=function(){return this._isValid},zn.abs=function(){var e=this._data;return this._milliseconds=On(this._milliseconds),this._days=On(this._days),this._months=On(this._months),e.milliseconds=On(e.milliseconds),e.seconds=On(e.seconds),e.minutes=On(e.minutes),e.hours=On(e.hours),e.months=On(e.months),e.years=On(e.years),this},zn.add=function(e,t){return Ae(this,e,t,1)},zn.subtract=function(e,t){return Ae(this,e,t,-1)},zn.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($e(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)}},zn.asMilliseconds=xn,zn.asSeconds=Tn,zn.asMinutes=bn,zn.asHours=Pn,zn.asDays=Wn,zn.asWeeks=Rn,zn.asMonths=Cn,zn.asYears=Fn,zn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12):NaN},zn._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*ze($e(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-=ze($e(i)),s=y(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},zn.clone=function(){return Pe(this)},zn.get=function(e){return e=O(e),this.isValid()?this[e+"s"]():NaN},zn.milliseconds=Un,zn.seconds=Nn,zn.minutes=Hn,zn.hours=Ln,zn.days=Gn,zn.weeks=function(){return y(this.days()/7)},zn.months=Vn,zn.years=jn,zn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=function(e,t,n){var s=Pe(e).abs(),i=In(s.as("s")),r=In(s.as("m")),a=In(s.as("h")),o=In(s.as("d")),u=In(s.as("M")),l=In(s.as("y")),d=i<=En.ss&&["s",i]||i<En.s&&["ss",i]||r<=1&&["m"]||r<En.m&&["mm",r]||a<=1&&["h"]||a<En.h&&["hh",a]||o<=1&&["d"]||o<En.d&&["dd",o]||u<=1&&["M"]||u<En.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)},zn.toISOString=Qe,zn.toString=Qe,zn.toJSON=Qe,zn.locale=Ne,zn.localeData=He,zn.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Qe),zn.lang=pn,P("X",0,0,"unix"),P("x",0,0,"valueOf"),F("x",kt),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.0",Xe=ve,e.fn=Dn,e.min=function(){return Me("isBefore",[].slice.call(arguments,0))},e.max=function(){return Me("isAfter",[].slice.call(arguments,0))},e.now=function(){return Date.now?Date.now():+new Date},e.utc=l,e.unix=function(e){return ve(1e3*e)},e.months=function(e,t){return Ie(e,t,"months")},e.isDate=r,e.locale=ae,e.invalid=c,e.duration=Pe,e.isMoment=_,e.weekdays=function(e,t,n){return Ee(e,t,n,"weekdays")},e.parseZone=function(){return ve.apply(null,arguments).parseZone()},e.localeData=ue,e.isDuration=Se,e.monthsShort=function(e,t){return Ie(e,t,"monthsShort")},e.weekdaysMin=function(e,t,n){return Ee(e,t,n,"weekdaysMin")},e.defineLocale=oe,e.updateLocale=function(e,t){if(null!=t){var n,s=Xt;null!=Kt[e]&&(s=Kt[e]._config),(n=new D(t=S(s,t))).parentLocale=Kt[e],Kt[e]=n,ae(e)}else null!=Kt[e]&&(null!=Kt[e].parentLocale?Kt[e]=Kt[e].parentLocale:null!=Kt[e]&&delete Kt[e]);return Kt[e]},e.locales=function(){return st(Kt)},e.weekdaysShort=function(e,t,n){return Ee(e,t,n,"weekdaysShort")},e.normalizeUnits=O,e.relativeTimeRounding=function(e){return void 0===e?In:"function"==typeof e&&(In=e,!0)},e.relativeTimeThreshold=function(e,t){return void 0!==En[e]&&(void 0===t?En[e]:(En[e]=t,"s"===e&&(En.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=Dn,e});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/page.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/page.min.js
new file mode 100755
index 0000000..57bdd94
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/page.min.js
@@ -0,0 +1 @@
+window.PAGE={handePage:100},document.addEventListener("deviceready",function(){document.addEventListener("backbutton",function(e){if(window.disabledBackButton)return e.preventDefault();var t=document.getElementsByClassName("box-block");t.length?(e.preventDefault(),window.backPage(t[t.length-1].id)):navigator.app.exitApp()},!1)},!1),window.dispatch=function(e,t){return(e="function"==typeof e?e:window[e]).apply(this,t||[])},window.openPage=function(e,t,n){if(2===arguments.length&&(n=t),e.indexOf(".html")<0&&(e+=".html"),document.getElementById(e)){var a=document.getElementsByClassName("box-block");if(a[a.length-1].id===document.getElementById(e).id)return!1;document.getElementById(e).parentNode.removeChild(document.getElementById(e))}var s=new XMLHttpRequest;s.onload=function(){if(4==this.readyState){var a=this.responseText;a=a.replace("backPage()","backPage('"+e+"')");var s=document.getElementsByTagName("body")[0];document.getElementsByClassName("body").length&&(s=document.getElementsByClassName("body")[0]);var d=document.createElement("div");d.setAttribute("class","box-block"),d.setAttribute("id",e),d.innerHTML=a,s.appendChild(d),function(){window.PAGE.handePage++;var a="z-index:"+window.PAGE.handePage,s=";transform: translateY(0px);will-change: transform, -webkit-transform, opacity;transition-duration: 280ms;transition-timing-function: cubic-bezier(0.36,0.66,0.04,1);";2===SO.code&&(s=";transform: translateX(0px);transition-duration: 280ms;"),window.disabledOpenPageEffect&&(s=";opacity: 1;top: 0;");var d=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");d?d+=" "+a+s:d=a+s,document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",d),n&&window.dispatch(n,[t]);var o=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("class");o+=" show";var l=function(){setTimeout(function(){document.getElementById(e)&&document.getElementById(e).querySelectorAll(".page").length?i():l()},10)};l();var m=new CustomEvent("openPage",{detail:{page:e}});document.dispatchEvent(m);var i=function(){setTimeout(function(){document.getElementById(e).getElementsByClassName("page")[0].setAttribute("class",o),setTimeout(function(){var t=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");t=t.replace(s,""),document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",t)},280)},100)}}()}},s.open("GET",e+"?cache="+(new Date).getTime(),!0),document.dispatchEvent(new Event("firedCloseMenu")),s.send()},window.backPage=function(e){if(!e){for(var t=document.querySelectorAll(".page.show"),n={zIndex:-1},a=0;a<t.length;a++){var s=Number(t[a].style.zIndex);n.zIndex<s&&(n.zIndex=s,n.element=t[a])}n.zIndex&&(e=n.element.parentElement.id)}document.getElementById(e).getElementsByClassName("page")[0];var d=";transform: translateY(0px);will-change: transform, -webkit-transform, opacity;transition-duration: 280ms;";window.disabledOpenPageEffect&&(d="");var o=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("style");o?o+=" "+d:o=d,document.getElementById(e).getElementsByClassName("page")[0].setAttribute("style",o);var l=document.getElementById(e).getElementsByClassName("page")[0].getAttribute("class");l+=l.replace("show",""),document.getElementById(e).getElementsByClassName("page")[0].setAttribute("class",l);var m=new CustomEvent("backPage",{detail:{page:e}});document.dispatchEvent(m),setTimeout(function(){var t=document.getElementById(e);t.parentElement.removeChild(t)},window.disabledOpenPageEffect?0:280)};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/popover.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/popover.min.js
new file mode 100755
index 0000000..35eca94
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/popover.min.js
@@ -0,0 +1 @@
+window.openPopover=function(e){var t=event.target.getBoundingClientRect(),o=e,e=document.getElementById(e),n=document.createElement("div");n.className="backdrop backdrop-popover",e.parentNode.appendChild(n),n.addEventListener("click",function(e){window.closePopover(o)}),e.addEventListener("click",function(e){window.closePopover(o)});var i=document.body.offsetWidth-t.left,r=document.body.offsetWidth-i;if(i-=t.width,e.style+=r>250?";top: 110%;right: "+i+"px;transform-origin: right top 0px;transform: scale(1);":";top: 110%;left: "+r+"px;transform-origin: right top 0px;transform: scale(1);",e.classList.add("show"),2===SO.code){e.style.top=t.top+t.height+"px";var s=document.createElement("div");s.classList.add("popover-arrow"),e.parentNode.appendChild(s),s.setAttribute("style","top:"+(t.top+t.height-5)+"px;left:"+(t.left+t.width/2-7)+"px")}else{var d=e.clientHeight,a=e.clientWidth;e.style.height=0,e.style.width=0,e.style.top=t.top+"px",setTimeout(function(){var t=e.getAttribute("style");t+=" ;-webkit-transition: all 200ms ease;transition: all 200ms ease;",e.setAttribute("style",t),e.style.height=d+"px",e.style.width=a+"px"})}var p=new CustomEvent("popoverOpened");document.dispatchEvent(p)},window.closePopover=function(e){var e=document.getElementById(e),t=0;2!==SO.code&&(e.style.opacity=0,t=200),setTimeout(function(){var t=document.getElementsByClassName("popover-arrow");t.length&&t[0].parentNode.removeChild(t[0]),e.classList.remove("show");var o=e.parentNode.getElementsByClassName("backdrop-popover");o&&o.length&&(o=o[0])&&o.parentNode&&o.parentNode.removeChild(o);var n=new CustomEvent("popoverClosed");document.dispatchEvent(n)},t)};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circle.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circle.min.js
new file mode 100755
index 0000000..57ad8b6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circle.min.js
@@ -0,0 +1 @@
+window.ProgressCircle={rebind:function(){for(var t=document.querySelectorAll(".progress-circle"),e=0;e<t.length;e++)t[e].classList.remove("binded"),t[e].innerHTML="";this.bind()},bind:function(){for(var t=document.querySelectorAll(".progress-circle:not(.binded)"),e=0;e<t.length;e++){var i={};i.value=Number(t[e].getAttribute("value")),i.maxValue=Number(t[e].getAttribute("maxValue"))||100,i.showValue="1"===t[e].getAttribute("showValue")||"true"===t[e].getAttribute("showValue")||!1,i.title=t[e].getAttribute("title")||"",i.subTitle=t[e].getAttribute("subTitle")||"",i.text=t[e].getAttribute("text")||"",i.color=t[e].getAttribute("color")||"blue",i.textColor=t[e].getAttribute("textColor")||"grey-800",i.textWeight=t[e].getAttribute("textWeight")||"normal",i.titleWeight=t[e].getAttribute("titleWeight")||"normal",i.subTitleWeight=t[e].getAttribute("subTitleWeight")||"normal",i.titleColor=t[e].getAttribute("titleColor")||"grey-500",i.subTitleColor=t[e].getAttribute("subTitleColor")||"grey-300",i.width=t[e].getAttribute("width")||"100%",i.height=t[e].getAttribute("height")||"300px",i.trailColor=t[e].getAttribute("trailColor")||"grey",i.strokeWidth=t[e].getAttribute("strokeWidth")||"1",i.trailWidth=t[e].getAttribute("trailWidth")||"1",i.textSize=t[e].getAttribute("textSize")||"16px",i.titleSize=t[e].getAttribute("titleSize")||"14px",i.subTitleSize=t[e].getAttribute("subTitleSize")||"12px",i.fill=t[e].getAttribute("fill")||"",i.padding=t[e].getAttribute("padding")||"0",i.durationAnimate=Number(t[e].getAttribute("duration")||"800"),this.create(t[e],i)}},create:function(t,e){t.classList.contains("binded")||(t.classList.add("binded"),t.classList.contains("progress-circle")||t.classList.add("progress-circle-js"),e.value=e.value||0,e.maxValue=e.maxValue||100,e.showValue=e.showValue||!1,e.title=e.title||"",e.subTitle=e.subTitle||"",e.text=e.text||"",e.color=e.color||"blue",e.textColor=e.textColor||"grey-800",e.textWeight=e.textWeight||"normal",e.titleWeight=e.titleWeight||"normal",e.subTitleWeight=e.subTitleWeight||"normal",e.titleColor=e.titleColor||"grey-500",e.subTitleColor=e.subTitleColor||"grey-300",e.width=e.width||"100%",e.height=e.height||"300px",e.trailColor=e.trailColor||"grey",e.strokeWidth=e.strokeWidth||"1",e.trailWidth=e.trailWidth||"1",e.textSize=e.textSize||"16px",e.titleSize=e.titleSize||"14px",e.subTitleSize=e.subTitleSize||"12px",e.fill=e.fill||"",e.padding=e.padding||"0",e.durationAnimate=e.durationAnimate||"800",t.style.width=e.width,t.style.height=e.height,t.progressCircle={},t.progressCircle.bar=new ProgressBar.Circle(t,{color:colorsMobileUI[e.color],trailColor:colorsMobileUI[e.trailColor],strokeWidth:e.strokeWidth,trailWidth:e.trailWidth,easing:"easeInOut",duration:e.durationAnimate,fill:e.fill,text:{autoStyleContainer:!0,style:{color:colorsMobileUI[e.textColor],position:"absolute",fontSize:e.textSize,fontWeight:e.textWeight,left:"50%",top:"50%",padding:0,margin:0,transform:{prefix:!0,value:"translate(-50%, -50%)"}}},svgStyle:{display:"block",width:e.width,height:e.height,padding:e.padding},from:{color:colorsMobileUI[e.color],width:e.strokeWidth},to:{color:colorsMobileUI[e.color],width:e.strokeWidth},step:function(t,i){i.path.setAttribute("stroke",t.color),i.path.setAttribute("stroke-width",t.width);var l=Math.round(i.value()*e.maxValue);e.showValue&&(l=e.value);var r="";if(e.title){o='style="';e.titleSize&&(o+=";font-size:"+e.titleSize),e.titleWeight&&(o+=";font-weight:"+e.titleWeight),e.titleColor&&(o+=";color:"+colorsMobileUI[e.titleColor]),r+="<div "+(o+='"')+' class="progress-circle-title">'+e.title+"</div>"}if(r+=l+e.text,e.subTitle){var o='style="';e.subTitleSize&&(o+=";font-size:"+e.subTitleSize),e.subTitleWeight&&(o+=";font-weight:"+e.subTitleWeight),e.subTitleColor&&(o+=";color:"+colorsMobileUI[e.subTitleColor]),r+="<div "+(o+='"')+' class="progress-circle-subtitle">'+e.subTitle+"</div>"}i.setText(r)}}),t.progressCircle.update=function(t){var i=0;t<=e.maxValue&&t>=0?i=t/e.maxValue:t<0?console.warn("Value for progress circle is too small. (Requested value is "+t+")"):(console.warn("Value for progress circle is too high. Maximum is "+e.maxValue+" and requested value is "+t+". (Value set to maximum for now.)"),i=1),this.bar.animate(i)},t.progressCircle.update(e.value))}};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circular.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circular.min.js
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-circular.min.js
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-semicircle.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-semicircle.min.js
new file mode 100755
index 0000000..70be9cf
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progress-semicircle.min.js
@@ -0,0 +1 @@
+window.ProgressSemicircle={rebind:function(){for(var t=document.querySelectorAll(".progress-semicircle"),e=0;e<t.length;e++)t[e].classList.remove("binded"),t[e].innerHTML="";this.bind()},bind:function(){for(var t=document.querySelectorAll(".progress-semicircle:not(.binded)"),e=0;e<t.length;e++){var i={};i.value=Number(t[e].getAttribute("value")),i.maxValue=Number(t[e].getAttribute("maxValue"))||100,i.title=t[e].getAttribute("title")||"",i.subTitle=t[e].getAttribute("subTitle")||"",i.text=t[e].getAttribute("text")||"",i.color=t[e].getAttribute("color")||"blue",i.textColor=t[e].getAttribute("textColor")||"grey-800",i.textWeight=t[e].getAttribute("textWeight")||"normal",i.titleWeight=t[e].getAttribute("titleWeight")||"normal",i.titleLineHeight=t[e].getAttribute("titleLineHeight")||"normal",i.subTitleWeight=t[e].getAttribute("subTitleWeight")||"normal",i.titleColor=t[e].getAttribute("titleColor")||"grey-500",i.subTitleColor=t[e].getAttribute("subTitleColor")||"grey-300",i.width=t[e].getAttribute("width")||"100%",i.height=t[e].getAttribute("height")||"300px",i.trailColor=t[e].getAttribute("trailColor")||"grey",i.strokeWidth=t[e].getAttribute("strokeWidth")||"1",i.trailWidth=t[e].getAttribute("trailWidth")||"1",i.textSize=t[e].getAttribute("textSize")||"16px",i.titleSize=t[e].getAttribute("titleSize")||"14px",i.subTitleSize=t[e].getAttribute("subTitleSize")||"12px",i.fill=t[e].getAttribute("fill")||"",i.padding=t[e].getAttribute("padding")||"0",i.textMargin=t[e].getAttribute("textMargin")||"100px 0",i.durationAnimate=Number(t[e].getAttribute("duration")||"800"),this.create(t[e],i)}},create:function(t,e){t.classList.contains("binded")||(t.classList.add("binded"),t.classList.contains("progress-semicircle")||t.classList.add("progress-semicircle-js"),e.value=e.value||0,e.maxValue=e.maxValue||100,e.title=e.title||"",e.subTitle=e.subTitle||"",e.text=e.text||"",e.color=e.color||"blue",e.textColor=e.textColor||"grey-800",e.textWeight=e.textWeight||"normal",e.titleWeight=e.titleWeight||"normal",e.subTitleWeight=e.subTitleWeight||"normal",e.titleColor=e.titleColor||"grey-500",e.subTitleColor=e.subTitleColor||"grey-300",e.width=e.width||"100%",e.height=e.height||"300px",e.trailColor=e.trailColor||"grey",e.strokeWidth=e.strokeWidth||"1",e.trailWidth=e.trailWidth||"1",e.textSize=e.textSize||"16px",e.titleSize=e.titleSize||"14px",e.subTitleSize=e.subTitleSize||"12px",e.fill=e.fill||"",e.padding=e.padding||"0",e.durationAnimate=e.durationAnimate||"800",e.textMargin=e.textMargin||"100px 0",t.style.width=e.width,t.style.height=e.height,t.progressSemicircle={},t.progressSemicircle.bar=new ProgressBar.SemiCircle(t,{color:colorsMobileUI[e.color],trailColor:colorsMobileUI[e.trailColor],strokeWidth:e.strokeWidth,trailWidth:e.trailWidth,easing:"easeInOut",duration:e.durationAnimate,fill:e.fill,text:{alignToBottom:!1,style:{color:colorsMobileUI[e.textColor],position:"absolute",fontSize:e.textSize,fontWeight:e.textWeight,left:"50%",padding:0,margin:e.textMargin}},svgStyle:{display:"block",width:e.width,height:e.height,padding:e.padding},from:{color:colorsMobileUI[e.color],width:e.strokeWidth},to:{color:colorsMobileUI[e.color],width:e.strokeWidth},step:function(t,i){i.path.setAttribute("stroke",t.color),i.path.setAttribute("stroke-width",t.width);var l=Math.round(i.value()*e.maxValue),r="";if(e.title){o='style="';e.titleSize&&(o+=";font-size:"+e.titleSize),e.titleWeight&&(o+=";font-weight:"+e.titleWeight),e.titleLineHeight&&(o+=";line-height:"+e.titleLineHeight),e.titleColor&&(o+=";color:"+colorsMobileUI[e.titleColor]),r+="<div "+(o+='"')+' class="progress-semicircle-title">'+e.title+"</div>"}if(r+=l+e.text,e.subTitle){var o='style="';e.subTitleSize&&(o+=";font-size:"+e.subTitleSize),e.subTitleWeight&&(o+=";font-weight:"+e.subTitleWeight),e.subTitleColor&&(o+=";color:"+colorsMobileUI[e.subTitleColor]),r+="<div "+(o+='"')+' class="progress-semicircle-subtitle">'+e.subTitle+"</div>"}i.setText(r)}}),t.progressSemicircle.update=function(t){var i=0;t<=e.maxValue&&t>=0?i=t/e.maxValue:t<0?console.warn("Value for progress semicircle is too small. (Requested value is "+t+")"):(console.warn("Value for progress semicircle is too high. Maximum is "+e.maxValue+" and requested value is "+t+". (Value set to maximum for now.)"),i=1),this.bar.animate(i)},t.progressSemicircle.update(e.value))}};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progressbarjs.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progressbarjs.min.js
new file mode 100755
index 0000000..24920e4
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/progressbarjs.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).ProgressBar=t()}}(function(){return function t(e,n,i){function r(s,a){if(!n[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var c=n[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return r(n||t)},c,c.exports,t,e,n,i)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s<i.length;s++)r(i[s]);return r}({1:[function(t,e,n){(function(){var t=this||Function("return this")(),i=function(){"use strict";function i(){}function r(t,e){var n;for(n in t)Object.hasOwnProperty.call(t,n)&&e(n)}function o(t,e){return r(e,function(n){t[n]=e[n]}),t}function s(t,e){r(e,function(n){void 0===t[n]&&(t[n]=e[n])})}function a(t,e,n,i,r,o,s){var a,h,c,p=o>t?0:(t-o)/r;for(a in e)e.hasOwnProperty(a)&&(h=s[a],c="function"==typeof h?h:f[h],e[a]=u(n[a],i[a],c,p));return e}function u(t,e,n,i){return t+(e-t)*n(i)}function h(t,e){var n=l.prototype.filter,i=t._filterArgs;r(n,function(r){void 0!==n[r][e]&&n[r][e].apply(t,i)})}function c(t,e,n,i,r,o,s,u,c,p,l){m=e+n+i,v=Math.min(l||y(),m),S=v>=m,x=i-(m-v),t.isPlaying()&&(S?(c(s,t._attachment,x),t.stop(!0)):(t._scheduleId=p(t._timeoutHandler,g),h(t,"beforeTween"),e+n>v?a(1,r,o,s,1,1,u):a(v,r,o,s,i,e+n,u),h(t,"afterTween"),c(r,t._attachment,x)))}function p(t,e){var n={},i=typeof e;return"string"===i||"function"===i?r(t,function(t){n[t]=e}):r(t,function(t){n[t]||(n[t]=e[t]||d)}),n}function l(t,e){this._currentState=t||{},this._configured=!1,this._scheduleFunction=_,void 0!==e&&this.setConfig(e)}var f,_,d="linear",g=1e3/60,w=Date.now?Date.now:function(){return+new Date},y="undefined"!=typeof SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:w;_="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout;var m,v,S,x;return l.prototype.tween=function(t){return this._isTweening?this:(void 0===t&&this._configured||this.setConfig(t),this._timestamp=y(),this._start(this.get(),this._attachment),this.resume())},l.prototype.setConfig=function(t){t=t||{},this._configured=!0,this._attachment=t.attachment,this._pausedAtTime=null,this._scheduleId=null,this._delay=t.delay||0,this._start=t.start||i,this._step=t.step||i,this._finish=t.finish||i,this._duration=t.duration||500,this._currentState=o({},t.from)||this.get(),this._originalState=this.get(),this._targetState=o({},t.to)||this.get();var e=this;this._timeoutHandler=function(){c(e,e._timestamp,e._delay,e._duration,e._currentState,e._originalState,e._targetState,e._easing,e._step,e._scheduleFunction)};var n=this._currentState,r=this._targetState;return s(r,n),this._easing=p(n,t.easing||d),this._filterArgs=[n,this._originalState,r,this._easing],h(this,"tweenCreated"),this},l.prototype.get=function(){return o({},this._currentState)},l.prototype.set=function(t){this._currentState=t},l.prototype.pause=function(){return this._pausedAtTime=y(),this._isPaused=!0,this},l.prototype.resume=function(){return this._isPaused&&(this._timestamp+=y()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0,this._timeoutHandler(),this},l.prototype.seek=function(t){t=Math.max(t,0);var e=y();return this._timestamp+t===0?this:(this._timestamp=e-t,this.isPlaying()||(this._isTweening=!0,this._isPaused=!1,c(this,this._timestamp,this._delay,this._duration,this._currentState,this._originalState,this._targetState,this._easing,this._step,this._scheduleFunction,e),this.pause()),this)},l.prototype.stop=function(e){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=i,(t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.oCancelAnimationFrame||t.msCancelAnimationFrame||t.mozCancelRequestAnimationFrame||t.clearTimeout)(this._scheduleId),e&&(h(this,"beforeTween"),a(1,this._currentState,this._originalState,this._targetState,1,0,this._easing),h(this,"afterTween"),h(this,"afterTweenEnd"),this._finish.call(this,this._currentState,this._attachment)),this},l.prototype.isPlaying=function(){return this._isTweening&&!this._isPaused},l.prototype.setScheduleFunction=function(t){this._scheduleFunction=t},l.prototype.dispose=function(){var t;for(t in this)this.hasOwnProperty(t)&&delete this[t]},l.prototype.filter={},l.prototype.formula={linear:function(t){return t}},f=l.prototype.formula,o(l,{now:y,each:r,tweenProps:a,tweenProp:u,applyFilter:h,shallowCopy:o,defaults:s,composeEasingObject:p}),"function"==typeof SHIFTY_DEBUG_NOW&&(t.timeoutHandler=c),"object"==typeof n?e.exports=l:void 0===t.Tweenable&&(t.Tweenable=l),l}();i.shallowCopy(i.prototype.formula,{easeInQuad:function(t){return Math.pow(t,2)},easeOutQuad:function(t){return-(Math.pow(t-1,2)-1)},easeInOutQuad:function(t){return(t/=.5)<1?.5*Math.pow(t,2):-.5*((t-=2)*t-2)},easeInCubic:function(t){return Math.pow(t,3)},easeOutCubic:function(t){return Math.pow(t-1,3)+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)},easeInQuart:function(t){return Math.pow(t,4)},easeOutQuart:function(t){return-(Math.pow(t-1,4)-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},easeInQuint:function(t){return Math.pow(t,5)},easeOutQuint:function(t){return Math.pow(t-1,5)+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*Math.pow(t,5):.5*(Math.pow(t-2,5)+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-Math.pow(t-1,2))},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeOutBounce:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},elastic:function(t){return-1*Math.pow(4,-8*t)*Math.sin((6*t-1)*(2*Math.PI)/2)+1},swingFromTo:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},swingFrom:function(t){var e=1.70158;return t*t*((e+1)*t-e)},swingTo:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},bounce:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bouncePast:function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?2-(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?2-(7.5625*(t-=2.25/2.75)*t+.9375):2-(7.5625*(t-=2.625/2.75)*t+.984375)},easeFromTo:function(t){return(t/=.5)<1?.5*Math.pow(t,4):-.5*((t-=2)*Math.pow(t,3)-2)},easeFrom:function(t){return Math.pow(t,4)},easeTo:function(t){return Math.pow(t,.25)}}),function(){function t(t,e,n,i,r,o){function s(t){return((c*t+p)*t+l)*t}function a(t){return(3*c*t+2*p)*t+l}function u(t,e){return function(t){return((f*t+_)*t+d)*t}(function(t,e){var n,i,r,o,u,c;for(r=t,c=0;8>c;c++){if(o=s(r)-t,h(o)<e)return r;if(u=a(r),h(u)<1e-6)break;r-=o/u}if(n=0,i=1,r=t,n>r)return n;if(r>i)return i;for(;i>n;){if(o=s(r),h(o-t)<e)return r;t>o?n=r:i=r,r=.5*(i-n)+n}return r}(t,e))}function h(t){return t>=0?t:0-t}var c=0,p=0,l=0,f=0,_=0,d=0;return l=3*e,p=3*(i-e)-l,c=1-l-p,d=3*n,_=3*(r-n)-d,f=1-d-_,u(t,function(t){return 1/(200*t)}(o))}function e(e,n,i,r){return function(o){return t(o,e,n,i,r,1)}}i.setBezierFunction=function(t,n,r,o,s){var a=e(n,r,o,s);return a.displayName=t,a.x1=n,a.y1=r,a.x2=o,a.y2=s,i.prototype.formula[t]=a},i.unsetBezierFunction=function(t){delete i.prototype.formula[t]}}(),function(){var t=new i;t._filterArgs=[],i.interpolate=function(e,n,r,o,s){var a=i.shallowCopy({},e),u=s||0,h=i.composeEasingObject(e,o||"linear");t.set({});var c=t._filterArgs;c.length=0,c[0]=a,c[1]=e,c[2]=n,c[3]=h,i.applyFilter(t,"tweenCreated"),i.applyFilter(t,"beforeTween");var p=function(t,e,n,r,o,s){return i.tweenProps(r,e,t,n,1,s,o)}(e,a,n,r,h,u);return i.applyFilter(t,"afterTween"),p}}(),function(t){function e(e){t.each(e,function(t){var i=e[t];"string"==typeof i&&i.match(w)&&(e[t]=function(t){return r(w,t,n)}(i))})}function n(t){var e=function(t){return 3===(t=t.replace(/#/,"")).length&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),m[0]=i(t.substr(0,2)),m[1]=i(t.substr(2,2)),m[2]=i(t.substr(4,2)),m}(t);return"rgb("+e[0]+","+e[1]+","+e[2]+")"}function i(t){return parseInt(t,16)}function r(t,e,n){var i=e.match(t),r=e.replace(t,y);if(i)for(var o,s=i.length,a=0;s>a;a++)o=i.shift(),r=r.replace(y,n(o));return r}function o(t){for(var e=t.match(_),n=e.length,i=t.match(g)[0],r=0;n>r;r++)i+=parseInt(e[r],10)+",";return i=i.slice(0,-1)+")"}function s(e){var n={};return t.each(e,function(t){var i=e[t];if("string"==typeof i){var r=h(i);n[t]={formatString:function(t){var e=t.match(f);return e?(1===e.length||t[0].match(l))&&e.unshift(""):e=["",""],e.join(y)}(i),chunkNames:function(t,e){var n,i=[],r=t.length;for(n=0;r>n;n++)i.push("_"+e+"_"+n);return i}(r,t)}}}),n}function a(e,n){t.each(n,function(t){for(var i=h(e[t]),r=i.length,o=0;r>o;o++)e[n[t].chunkNames[o]]=+i[o];delete e[t]})}function u(e,n){t.each(n,function(t){var i=e[t],s=function(t,e){v.length=0;for(var n=e.length,i=0;n>i;i++)v.push(t[e[i]]);return v}(function(t,e){for(var n,i={},r=e.length,o=0;r>o;o++)n=e[o],i[n]=t[n],delete t[n];return i}(e,n[t].chunkNames),n[t].chunkNames);i=function(t,e){for(var n=t,i=e.length,r=0;i>r;r++)n=n.replace(y,+e[r].toFixed(4));return n}(n[t].formatString,s),e[t]=function(t){return r(d,t,o)}(i)})}function h(t){return t.match(_)}function c(e,n){t.each(n,function(t){var i,r=n[t].chunkNames,o=r.length,s=e[t];if("string"==typeof s){var a=s.split(" "),u=a[a.length-1];for(i=0;o>i;i++)e[r[i]]=a[i]||u}else for(i=0;o>i;i++)e[r[i]]=s;delete e[t]})}function p(e,n){t.each(n,function(t){var i=n[t].chunkNames,r=i.length,o=e[i[0]];if("string"===typeof o){for(var s="",a=0;r>a;a++)s+=" "+e[i[a]],delete e[i[a]];e[t]=s.substr(1)}else e[t]=o})}var l=/(\d|\-|\.)/,f=/([^\-0-9\.]+)/g,_=/[0-9.\-]+/g,d=new RegExp("rgb\\("+_.source+/,\s*/.source+_.source+/,\s*/.source+_.source+"\\)","g"),g=/^.*\(/,w=/#([0-9]|[a-f]){3,6}/gi,y="VAL",m=[],v=[];t.prototype.filter.token={tweenCreated:function(t,n,i,r){e(t),e(n),e(i),this._tokenData=s(t)},beforeTween:function(t,e,n,i){c(i,this._tokenData),a(t,this._tokenData),a(e,this._tokenData),a(n,this._tokenData)},afterTween:function(t,e,n,i){u(t,this._tokenData),u(e,this._tokenData),u(n,this._tokenData),p(i,this._tokenData)}}}(i)}).call(null)},{}],2:[function(t,e,n){var i=t("./shape"),r=t("./utils"),o=function(t,e){this._pathTemplate="M 50,50 m 0,-{radius} a {radius},{radius} 0 1 1 0,{2radius} a {radius},{radius} 0 1 1 0,-{2radius}",this.containerAspectRatio=1,i.apply(this,arguments)};(o.prototype=new i).constructor=o,o.prototype._pathString=function(t){var e=t.strokeWidth;t.trailWidth&&t.trailWidth>t.strokeWidth&&(e=t.trailWidth);var n=50-e/2;return r.render(this._pathTemplate,{radius:n,"2radius":2*n})},o.prototype._trailString=function(t){return this._pathString(t)},e.exports=o},{"./shape":7,"./utils":8}],3:[function(t,e,n){var i=t("./shape"),r=t("./utils"),o=function(t,e){this._pathTemplate="M 0,{center} L 100,{center}",i.apply(this,arguments)};(o.prototype=new i).constructor=o,o.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 "+e.strokeWidth),t.setAttribute("preserveAspectRatio","none")},o.prototype._pathString=function(t){return r.render(this._pathTemplate,{center:t.strokeWidth/2})},o.prototype._trailString=function(t){return this._pathString(t)},e.exports=o},{"./shape":7,"./utils":8}],4:[function(t,e,n){e.exports={Line:t("./line"),Circle:t("./circle"),SemiCircle:t("./semicircle"),Path:t("./path"),Shape:t("./shape"),utils:t("./utils")}},{"./circle":2,"./line":3,"./path":5,"./semicircle":6,"./shape":7,"./utils":8}],5:[function(t,e,n){var i=t("shifty"),r=t("./utils"),o={easeIn:"easeInCubic",easeOut:"easeOutCubic",easeInOut:"easeInOutCubic"},s=function t(e,n){if(!(this instanceof t))throw new Error("Constructor was called without new keyword");n=r.extend({duration:800,easing:"linear",from:{},to:{},step:function(){}},n);var i;i=r.isString(e)?document.querySelector(e):e,this.path=i,this._opts=n,this._tweenable=null;var o=this.path.getTotalLength();this.path.style.strokeDasharray=o+" "+o,this.set(0)};s.prototype.value=function(){var t=1-this._getComputedDashOffset()/this.path.getTotalLength();return parseFloat(t.toFixed(6),10)},s.prototype.set=function(t){this.stop(),this.path.style.strokeDashoffset=this._progressToOffset(t);var e=this._opts.step;if(r.isFunction(e)){var n=this._easing(this._opts.easing);e(this._calculateTo(t,n),this._opts.shape||this,this._opts.attachment)}},s.prototype.stop=function(){this._stopTween(),this.path.style.strokeDashoffset=this._getComputedDashOffset()},s.prototype.animate=function(t,e,n){e=e||{},r.isFunction(e)&&(n=e,e={});var o=r.extend({},e),s=r.extend({},this._opts);e=r.extend(s,e);var a=this._easing(e.easing),u=this._resolveFromAndTo(t,a,o);this.stop(),this.path.getBoundingClientRect();var h=this._getComputedDashOffset(),c=this._progressToOffset(t),p=this;this._tweenable=new i,this._tweenable.tween({from:r.extend({offset:h},u.from),to:r.extend({offset:c},u.to),duration:e.duration,easing:a,step:function(t){p.path.style.strokeDashoffset=t.offset;var n=e.shape||p;e.step(t,n,e.attachment)},finish:function(t){r.isFunction(n)&&n()}})},s.prototype._getComputedDashOffset=function(){var t=window.getComputedStyle(this.path,null);return parseFloat(t.getPropertyValue("stroke-dashoffset"),10)},s.prototype._progressToOffset=function(t){var e=this.path.getTotalLength();return e-t*e},s.prototype._resolveFromAndTo=function(t,e,n){return n.from&&n.to?{from:n.from,to:n.to}:{from:this._calculateFrom(e),to:this._calculateTo(t,e)}},s.prototype._calculateFrom=function(t){return i.interpolate(this._opts.from,this._opts.to,this.value(),t)},s.prototype._calculateTo=function(t,e){return i.interpolate(this._opts.from,this._opts.to,t,e)},s.prototype._stopTween=function(){null!==this._tweenable&&(this._tweenable.stop(),this._tweenable=null)},s.prototype._easing=function(t){return o.hasOwnProperty(t)?o[t]:t},e.exports=s},{"./utils":8,shifty:1}],6:[function(t,e,n){var i=t("./shape"),r=t("./circle"),o=t("./utils"),s=function(t,e){this._pathTemplate="M 50,50 m -{radius},0 a {radius},{radius} 0 1 1 {2radius},0",this.containerAspectRatio=2,i.apply(this,arguments)};(s.prototype=new i).constructor=s,s.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 50")},s.prototype._initializeTextContainer=function(t,e,n){t.text.style&&(n.style.top="auto",n.style.bottom="0",t.text.alignToBottom?o.setStyle(n,"transform","translate(-50%, 0)"):o.setStyle(n,"transform","translate(-50%, 50%)"))},s.prototype._pathString=r.prototype._pathString,s.prototype._trailString=r.prototype._trailString,e.exports=s},{"./circle":2,"./shape":7,"./utils":8}],7:[function(t,e,n){var i=t("./path"),r=t("./utils"),o="Object is destroyed",s=function t(e,n){if(!(this instanceof t))throw new Error("Constructor was called without new keyword");if(0!==arguments.length){this._opts=r.extend({color:"#555",strokeWidth:1,trailColor:null,trailWidth:null,fill:null,text:{style:{color:null,position:"absolute",left:"50%",top:"50%",padding:0,margin:0,transform:{prefix:!0,value:"translate(-50%, -50%)"}},autoStyleContainer:!0,alignToBottom:!0,value:null,className:"progressbar-text"},svgStyle:{display:"block",width:"100%"},warnings:!1},n,!0),r.isObject(n)&&void 0!==n.svgStyle&&(this._opts.svgStyle=n.svgStyle),r.isObject(n)&&r.isObject(n.text)&&void 0!==n.text.style&&(this._opts.text.style=n.text.style);var o,s=this._createSvgView(this._opts);if(!(o=r.isString(e)?document.querySelector(e):e))throw new Error("Container does not exist: "+e);this._container=o,this._container.appendChild(s.svg),this._opts.warnings&&this._warnContainerAspectRatio(this._container),this._opts.svgStyle&&r.setStyles(s.svg,this._opts.svgStyle),this.svg=s.svg,this.path=s.path,this.trail=s.trail,this.text=null;var a=r.extend({attachment:void 0,shape:this},this._opts);this._progressPath=new i(s.path,a),r.isObject(this._opts.text)&&null!==this._opts.text.value&&this.setText(this._opts.text.value)}};s.prototype.animate=function(t,e,n){if(null===this._progressPath)throw new Error(o);this._progressPath.animate(t,e,n)},s.prototype.stop=function(){if(null===this._progressPath)throw new Error(o);void 0!==this._progressPath&&this._progressPath.stop()},s.prototype.destroy=function(){if(null===this._progressPath)throw new Error(o);this.stop(),this.svg.parentNode.removeChild(this.svg),this.svg=null,this.path=null,this.trail=null,this._progressPath=null,null!==this.text&&(this.text.parentNode.removeChild(this.text),this.text=null)},s.prototype.set=function(t){if(null===this._progressPath)throw new Error(o);this._progressPath.set(t)},s.prototype.value=function(){if(null===this._progressPath)throw new Error(o);return void 0===this._progressPath?0:this._progressPath.value()},s.prototype.setText=function(t){if(null===this._progressPath)throw new Error(o);null===this.text&&(this.text=this._createTextContainer(this._opts,this._container),this._container.appendChild(this.text)),r.isObject(t)?(r.removeChildren(this.text),this.text.appendChild(t)):this.text.innerHTML=t},s.prototype._createSvgView=function(t){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");this._initializeSvg(e,t);var n=null;(t.trailColor||t.trailWidth)&&(n=this._createTrail(t),e.appendChild(n));var i=this._createPath(t);return e.appendChild(i),{svg:e,path:i,trail:n}},s.prototype._initializeSvg=function(t,e){t.setAttribute("viewBox","0 0 100 100")},s.prototype._createPath=function(t){var e=this._pathString(t);return this._createPathElement(e,t)},s.prototype._createTrail=function(t){var e=this._trailString(t),n=r.extend({},t);return n.trailColor||(n.trailColor="#eee"),n.trailWidth||(n.trailWidth=n.strokeWidth),n.color=n.trailColor,n.strokeWidth=n.trailWidth,n.fill=null,this._createPathElement(e,n)},s.prototype._createPathElement=function(t,e){var n=document.createElementNS("http://www.w3.org/2000/svg","path");return n.setAttribute("d",t),n.setAttribute("stroke",e.color),n.setAttribute("stroke-width",e.strokeWidth),e.fill?n.setAttribute("fill",e.fill):n.setAttribute("fill-opacity","0"),n},s.prototype._createTextContainer=function(t,e){var n=document.createElement("div");n.className=t.text.className;var i=t.text.style;return i&&(t.text.autoStyleContainer&&(e.style.position="relative"),r.setStyles(n,i),i.color||(n.style.color=t.color)),this._initializeTextContainer(t,e,n),n},s.prototype._initializeTextContainer=function(t,e,n){},s.prototype._pathString=function(t){throw new Error("Override this function for each progress bar")},s.prototype._trailString=function(t){throw new Error("Override this function for each progress bar")},s.prototype._warnContainerAspectRatio=function(t){if(this.containerAspectRatio){var e=window.getComputedStyle(t,null),n=parseFloat(e.getPropertyValue("width"),10),i=parseFloat(e.getPropertyValue("height"),10);r.floatEquals(this.containerAspectRatio,n/i)||(console.warn("Incorrect aspect ratio of container","#"+t.id,"detected:",e.getPropertyValue("width")+"(width)","/",e.getPropertyValue("height")+"(height)","=",n/i),console.warn("Aspect ratio of should be",this.containerAspectRatio))}},e.exports=s},{"./path":5,"./utils":8}],8:[function(t,e,n){function i(t,e,n){t=t||{},e=e||{},n=n||!1;for(var r in e)if(e.hasOwnProperty(r)){var o=t[r],a=e[r];n&&s(o)&&s(a)?t[r]=i(o,a,n):t[r]=a}return t}function r(t,e,n){for(var i=t.style,r=0;r<u.length;++r){i[u[r]+o(e)]=n}i[e]=n}function o(t){return t.charAt(0).toUpperCase()+t.slice(1)}function s(t){if(function(t){return"[object Array]"===Object.prototype.toString.call(t)}(t))return!1;return"object"===typeof t&&!!t}function a(t,e){for(var n in t)if(t.hasOwnProperty(n)){e(t[n],n)}}var u="Webkit Moz O ms".split(" "),h=.001;e.exports={extend:i,render:function(t,e){var n=t;for(var i in e)if(e.hasOwnProperty(i)){var r=e[i],o="\\{"+i+"\\}",s=new RegExp(o,"g");n=n.replace(s,r)}return n},setStyle:r,setStyles:function(t,e){a(e,function(e,n){null!==e&&void 0!==e&&(s(e)&&!0===e.prefix?r(t,n,e.value):t.style[n]=e)})},capitalize:o,isString:function(t){return"string"==typeof t||t instanceof String},isFunction:function(t){return"function"==typeof t},isObject:s,forEachObject:a,floatEquals:function(t,e){return Math.abs(t-e)<h},removeChildren:function(t){for(;t.firstChild;)t.removeChild(t.firstChild)}}},{}]},{},[4])(4)});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/pulltorefresh.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/pulltorefresh.min.js
new file mode 100755
index 0000000..5b273cd
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/pulltorefresh.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.PullToRefresh=t()}(this,function(){function e(){function e(e){var t=r.handlers.filter(function(t){return t.contains(e.target)})[0];r.enable=!!t,t&&"pending"===r.state&&(o=i.setupDOM(t),t.shouldPullToRefresh()&&(r.pullStartY=e.touches[0].screenY),clearTimeout(r.timeout),i.update(t))}function t(e){o&&o.ptrElement&&r.enable&&(r.pullStartY?r.pullMoveY=e.touches[0].screenY:o.shouldPullToRefresh()&&(r.pullStartY=e.touches[0].screenY),"refreshing"!==r.state?("pending"===r.state&&(o.ptrElement.classList.add(o.classPrefix+"pull"),r.state="pulling",i.update(o)),r.pullStartY&&r.pullMoveY&&(r.dist=r.pullMoveY-r.pullStartY),r.dist>0&&(e.preventDefault(),o.ptrElement.style[o.cssProp]=r.distResisted+"px",r.distResisted=o.resistanceFunction(r.dist/o.distThreshold)*Math.min(o.distMax,r.dist),"pulling"===r.state&&r.distResisted>o.distThreshold&&(o.ptrElement.classList.add(o.classPrefix+"release"),r.state="releasing",i.update(o)),"releasing"===r.state&&r.distResisted<o.distThreshold&&(o.ptrElement.classList.remove(o.classPrefix+"release"),r.state="pulling",i.update(o)))):o.shouldPullToRefresh()&&r.pullStartY<r.pullMoveY&&e.preventDefault())}function n(){if(o&&o.ptrElement&&r.enable){if("releasing"===r.state&&r.distResisted>o.distThreshold)r.state="refreshing",o.ptrElement.style[o.cssProp]=o.distReload+"px",o.ptrElement.classList.add(o.classPrefix+"refresh"),r.timeout=setTimeout(function(){var e=o.onRefresh(function(){return i.onReset(o)});e&&"function"==typeof e.then&&e.then(function(){return i.onReset(o)}),e||o.onRefresh.length||i.onReset(o)},o.refreshTimeout);else{if("refreshing"===r.state)return;o.ptrElement.style[o.cssProp]="0px",r.state="pending"}i.update(o),o.ptrElement.classList.remove(o.classPrefix+"release"),o.ptrElement.classList.remove(o.classPrefix+"pull"),r.pullStartY=r.pullMoveY=null,r.dist=r.distResisted=0}}function s(){o&&o.mainElement.classList.toggle(o.classPrefix+"top",o.shouldPullToRefresh())}var o,l=r.supportsPassive?{passive:r.passive||!1}:void 0;return window.addEventListener("touchend",n),window.addEventListener("touchstart",e),window.addEventListener("touchmove",t,l),window.addEventListener("scroll",s),{onTouchEnd:n,onTouchStart:e,onTouchMove:t,onScroll:s,destroy:function(){window.removeEventListener("touchstart",e),window.removeEventListener("touchend",n),window.removeEventListener("touchmove",t,l),window.removeEventListener("scroll",s)}}}function t(t){var i={};return Object.keys(n).forEach(function(e){i[e]=t[e]||n[e]}),i.refreshTimeout="number"==typeof t.refreshTimeout?t.refreshTimeout:n.refreshTimeout,s.forEach(function(e){"string"==typeof i[e]&&(i[e]=document.querySelector(i[e]))}),r.events||(r.events=e()),i.contains=function(e){return i.triggerElement.contains(e)},i.destroy=function(){clearTimeout(r.timeout),r.handlers.splice(i.offset,1)},i}var n={distThreshold:60,distMax:80,distReload:50,bodyOffset:20,mainElement:"body",triggerElement:"body",ptrElement:".ptr",classPrefix:"ptr--",cssProp:"min-height",iconArrow:"&#8675;",iconRefreshing:"&hellip;",instructionsPullToRefresh:"Pull down to refresh",instructionsReleaseToRefresh:"Release to refresh",instructionsRefreshing:"Refreshing",refreshTimeout:500,getMarkup:function(){return'\n<div class="__PREFIX__box">\n  <div class="__PREFIX__content">\n    <div class="__PREFIX__icon"></div>\n    <div class="__PREFIX__text"></div>\n  </div>\n</div>'},getStyles:function(){return".__PREFIX__ptr {\n  box-shadow: inset 0 -3px 5px rgba(0, 0, 0, 0.12);\n  pointer-events: none;\n  font-size: 0.85em;\n  font-weight: bold;\n  top: 0;\n  height: 0;\n  transition: height 0.3s, min-height 0.3s;\n  text-align: center;\n  width: 100%;\n  overflow: hidden;\n  display: flex;\n  align-items: flex-end;\n  align-content: stretch;\n}\n.__PREFIX__box {\n  padding: 10px;\n  flex-basis: 100%;\n}\n.__PREFIX__pull {\n  transition: none;\n}\n.__PREFIX__text {\n  margin-top: .33em;\n  color: rgba(0, 0, 0, 0.3);\n}\n.__PREFIX__icon {\n  color: rgba(0, 0, 0, 0.3);\n  transition: transform .3s;\n}\n.__PREFIX__top {\n  touch-action: pan-x pan-down pinch-zoom;\n}\n.__PREFIX__release .__PREFIX__icon {\n  transform: rotate(180deg);\n}\n"},onInit:function(){},onRefresh:function(){return location.reload()},resistanceFunction:function(e){return Math.min(1,e/2.5)},shouldPullToRefresh:function(){return!window.scrollY}},s=["mainElement","ptrElement","triggerElement"],r={pullStartY:null,pullMoveY:null,handlers:[],styleEl:null,events:null,dist:0,state:"pending",timeout:null,distResisted:0,supportsPassive:!1};try{window.addEventListener("test",null,{get passive(){r.supportsPassive=!0}})}catch(e){}var i={setupDOM:function(e){if(!e.ptrElement){var t=document.createElement("div");e.mainElement!==document.body?e.mainElement.parentNode.insertBefore(t,e.mainElement):document.body.insertBefore(t,document.body.firstChild),t.classList.add(e.classPrefix+"ptr"),t.innerHTML=e.getMarkup().replace(/__PREFIX__/g,e.classPrefix),e.ptrElement=t,"function"==typeof e.onInit&&e.onInit(e),r.styleEl||(r.styleEl=document.createElement("style"),r.styleEl.setAttribute("id","pull-to-refresh-js-style"),document.head.appendChild(r.styleEl)),r.styleEl.textContent=e.getStyles().replace(/__PREFIX__/g,e.classPrefix).replace(/\s+/g," ")}return e},onReset:function(e){e.ptrElement.classList.remove(e.classPrefix+"refresh"),e.ptrElement.style[e.cssProp]="0px",setTimeout(function(){e.ptrElement&&e.ptrElement.parentNode&&(e.ptrElement.parentNode.removeChild(e.ptrElement),e.ptrElement=null),r.state="pending"},e.refreshTimeout)},update:function(e){var t=e.ptrElement.querySelector("."+e.classPrefix+"icon"),n=e.ptrElement.querySelector("."+e.classPrefix+"text");t&&("refreshing"===r.state?t.innerHTML=e.iconRefreshing:t.innerHTML=e.iconArrow),n&&("releasing"===r.state&&(n.innerHTML=e.instructionsReleaseToRefresh),"pulling"!==r.state&&"pending"!==r.state||(n.innerHTML=e.instructionsPullToRefresh),"refreshing"===r.state&&(n.innerHTML=e.instructionsRefreshing))}};return{setPassiveMode:function(e){r.passive=e},destroyAll:function(){r.events&&(r.events.destroy(),r.events=null),r.handlers.forEach(function(e){e.destroy()})},init:function(e){void 0===e&&(e={});var n=t(e);return n.offset=r.handlers.push(n)-1,n},_:{setupHandler:t,setupEvents:e,setupDOM:i.setupDOM,onReset:i.onReset,update:i.update}}});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/swiper.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/swiper.min.js
new file mode 100755
index 0000000..ae35ad5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/swiper.min.js
@@ -0,0 +1 @@
+!function(){"use strict";var e,a=function(s,i){function r(e){return Math.floor(e)}function n(){var e=x.params.autoplay,a=x.slides.eq(x.activeIndex);a.attr("data-swiper-autoplay")&&(e=a.attr("data-swiper-autoplay")||x.params.autoplay),x.autoplayTimeoutId=setTimeout(function(){x.params.loop?(x.fixLoop(),x._slideNext(),x.emit("onAutoplay",x)):x.isEnd?i.autoplayStopOnLast?x.stopAutoplay():(x._slideTo(0),x.emit("onAutoplay",x)):(x._slideNext(),x.emit("onAutoplay",x))},e)}function o(a,t){var s=e(a.target);if(!s.is(t))if("string"==typeof t)s=s.parents(t);else if(t.nodeType){var i;return s.parents().each(function(e,a){a===t&&(i=t)}),i?t:void 0}if(0!==s.length)return s[0]}function l(e,a){a=a||{};var t=new(window.MutationObserver||window.WebkitMutationObserver)(function(e){e.forEach(function(e){x.onResize(!0),x.emit("onObserverUpdate",x,e)})});t.observe(e,{attributes:void 0===a.attributes||a.attributes,childList:void 0===a.childList||a.childList,characterData:void 0===a.characterData||a.characterData}),x.observers.push(t)}function p(e){e.originalEvent&&(e=e.originalEvent);var a=e.keyCode||e.charCode;if(!x.params.allowSwipeToNext&&(x.isHorizontal()&&39===a||!x.isHorizontal()&&40===a))return!1;if(!x.params.allowSwipeToPrev&&(x.isHorizontal()&&37===a||!x.isHorizontal()&&38===a))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===a||39===a||38===a||40===a){var t=!1;if(x.container.parents("."+x.params.slideClass).length>0&&0===x.container.parents("."+x.params.slideActiveClass).length)return;var s={left:window.pageXOffset,top:window.pageYOffset},i=window.innerWidth,r=window.innerHeight,n=x.container.offset();x.rtl&&(n.left=n.left-x.container[0].scrollLeft);for(var o=[[n.left,n.top],[n.left+x.width,n.top],[n.left,n.top+x.height],[n.left+x.width,n.top+x.height]],l=0;l<o.length;l++){var p=o[l];p[0]>=s.left&&p[0]<=s.left+i&&p[1]>=s.top&&p[1]<=s.top+r&&(t=!0)}if(!t)return}x.isHorizontal()?(37!==a&&39!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===a&&!x.rtl||37===a&&x.rtl)&&x.slideNext(),(37===a&&!x.rtl||39===a&&x.rtl)&&x.slidePrev()):(38!==a&&40!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),40===a&&x.slideNext(),38===a&&x.slidePrev()),x.emit("onKeyPress",x,a)}}function d(e){e.originalEvent&&(e=e.originalEvent);var a=0,t=x.rtl?-1:1,s=function(e){var a=0,t=0,s=0,i=0;return"detail"in e&&(t=e.detail),"wheelDelta"in e&&(t=-e.wheelDelta/120),"wheelDeltaY"in e&&(t=-e.wheelDeltaY/120),"wheelDeltaX"in e&&(a=-e.wheelDeltaX/120),"axis"in e&&e.axis===e.HORIZONTAL_AXIS&&(a=t,t=0),s=10*a,i=10*t,"deltaY"in e&&(i=e.deltaY),"deltaX"in e&&(s=e.deltaX),(s||i)&&e.deltaMode&&(1===e.deltaMode?(s*=40,i*=40):(s*=800,i*=800)),s&&!a&&(a=s<1?-1:1),i&&!t&&(t=i<1?-1:1),{spinX:a,spinY:t,pixelX:s,pixelY:i}}(e);if(x.params.mousewheelForceToAxis)if(x.isHorizontal()){if(!(Math.abs(s.pixelX)>Math.abs(s.pixelY)))return;a=s.pixelX*t}else{if(!(Math.abs(s.pixelY)>Math.abs(s.pixelX)))return;a=s.pixelY}else a=Math.abs(s.pixelX)>Math.abs(s.pixelY)?-s.pixelX*t:-s.pixelY;if(0!==a){if(x.params.mousewheelInvert&&(a=-a),x.params.freeMode){var i=x.getWrapperTranslate()+a*x.params.mousewheelSensitivity,r=x.isBeginning,n=x.isEnd;if(i>=x.minTranslate()&&(i=x.minTranslate()),i<=x.maxTranslate()&&(i=x.maxTranslate()),x.setWrapperTransition(0),x.setWrapperTranslate(i),x.updateProgress(),x.updateActiveIndex(),(!r&&x.isBeginning||!n&&x.isEnd)&&x.updateClasses(),x.params.freeModeSticky?(clearTimeout(x.mousewheel.timeout),x.mousewheel.timeout=setTimeout(function(){x.slideReset()},300)):x.params.lazyLoading&&x.lazy&&x.lazy.load(),x.emit("onScroll",x,e),x.params.autoplay&&x.params.autoplayDisableOnInteraction&&x.stopAutoplay(),0===i||i===x.maxTranslate())return}else{if((new window.Date).getTime()-x.mousewheel.lastScrollTime>60)if(a<0)if(x.isEnd&&!x.params.loop||x.animating){if(x.params.mousewheelReleaseOnEdges)return!0}else x.slideNext(),x.emit("onScroll",x,e);else if(x.isBeginning&&!x.params.loop||x.animating){if(x.params.mousewheelReleaseOnEdges)return!0}else x.slidePrev(),x.emit("onScroll",x,e);x.mousewheel.lastScrollTime=(new window.Date).getTime()}return e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function u(a,t){a=e(a);var s,i,r,n=x.rtl?-1:1;s=a.attr("data-swiper-parallax")||"0",i=a.attr("data-swiper-parallax-x"),r=a.attr("data-swiper-parallax-y"),i||r?(i=i||"0",r=r||"0"):x.isHorizontal()?(i=s,r="0"):(r=s,i="0"),i=i.indexOf("%")>=0?parseInt(i,10)*t*n+"%":i*t*n+"px",r=r.indexOf("%")>=0?parseInt(r,10)*t+"%":r*t+"px",a.transform("translate3d("+i+", "+r+",0px)")}function c(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof a))return new a(s,i);var m={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,autoplayStopOnLast:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeMomentumVelocityRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flip:{slideShadows:!0,limitRotation:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,zoom:!1,zoomMax:3,zoomMin:1,zoomToggle:!0,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,mousewheelEventsTarged:"container",hashnav:!1,hashnavWatchState:!1,history:!1,replaceState:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,touchReleaseOnEdges:!1,uniqueNavElements:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,paginationProgressRender:null,paginationFractionRender:null,paginationCustomRender:null,paginationType:"bullets",resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingInPrevNextAmount:1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",normalizeSlideIndex:!0,allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",passiveListeners:!0,containerModifierClass:"swiper-container-",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideDuplicateActiveClass:"swiper-slide-duplicate-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slideDuplicateNextClass:"swiper-slide-duplicate-next",slidePrevClass:"swiper-slide-prev",slideDuplicatePrevClass:"swiper-slide-duplicate-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationCurrentClass:"swiper-pagination-current",paginationTotalClass:"swiper-pagination-total",paginationHiddenClass:"swiper-pagination-hidden",paginationProgressbarClass:"swiper-pagination-progressbar",paginationClickableClass:"swiper-pagination-clickable",paginationModifierClass:"swiper-pagination-",lazyLoadingClass:"swiper-lazy",lazyStatusLoadingClass:"swiper-lazy-loading",lazyStatusLoadedClass:"swiper-lazy-loaded",lazyPreloaderClass:"swiper-lazy-preloader",notificationClass:"swiper-notification",preloaderClass:"preloader",zoomContainerClass:"swiper-zoom-container",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},h=i&&i.virtualTranslate;i=i||{};var g={};for(var f in i)if("object"!=typeof i[f]||null===i[f]||(i[f].nodeType||i[f]===window||i[f]===document||void 0!==t&&i[f]instanceof t||"undefined"!=typeof jQuery&&i[f]instanceof jQuery))g[f]=i[f];else{g[f]={};for(var v in i[f])g[f][v]=i[f][v]}for(var w in m)if(void 0===i[w])i[w]=m[w];else if("object"==typeof i[w])for(var y in m[w])void 0===i[w][y]&&(i[w][y]=m[w][y]);var x=this;if(x.params=i,x.originalParams=g,x.classNames=[],void 0!==e&&void 0!==t&&(e=t),(void 0!==e||(e=void 0===t?window.Dom7||window.Zepto||window.jQuery:t))&&(x.$=e,x.currentBreakpoint=void 0,x.getActiveBreakpoint=function(){if(!x.params.breakpoints)return!1;var e,a=!1,t=[];for(e in x.params.breakpoints)x.params.breakpoints.hasOwnProperty(e)&&t.push(e);t.sort(function(e,a){return parseInt(e,10)>parseInt(a,10)});for(var s=0;s<t.length;s++)(e=t[s])>=window.innerWidth&&!a&&(a=e);return a||"max"},x.setBreakpoint=function(){var e=x.getActiveBreakpoint();if(e&&x.currentBreakpoint!==e){var a=e in x.params.breakpoints?x.params.breakpoints[e]:x.originalParams,t=x.params.loop&&a.slidesPerView!==x.params.slidesPerView;for(var s in a)x.params[s]=a[s];x.currentBreakpoint=e,t&&x.destroyLoop&&x.reLoop(!0)}},x.params.breakpoints&&x.setBreakpoint(),x.container=e(s),0!==x.container.length)){if(x.container.length>1){var T=[];return x.container.each(function(){T.push(new a(this,i))}),T}x.container[0].swiper=x,x.container.data("swiper",x),x.classNames.push(x.params.containerModifierClass+x.params.direction),x.params.freeMode&&x.classNames.push(x.params.containerModifierClass+"free-mode"),x.support.flexbox||(x.classNames.push(x.params.containerModifierClass+"no-flexbox"),x.params.slidesPerColumn=1),x.params.autoHeight&&x.classNames.push(x.params.containerModifierClass+"autoheight"),(x.params.parallax||x.params.watchSlidesVisibility)&&(x.params.watchSlidesProgress=!0),x.params.touchReleaseOnEdges&&(x.params.resistanceRatio=0),["cube","coverflow","flip"].indexOf(x.params.effect)>=0&&(x.support.transforms3d?(x.params.watchSlidesProgress=!0,x.classNames.push(x.params.containerModifierClass+"3d")):x.params.effect="slide"),"slide"!==x.params.effect&&x.classNames.push(x.params.containerModifierClass+x.params.effect),"cube"===x.params.effect&&(x.params.resistanceRatio=0,x.params.slidesPerView=1,x.params.slidesPerColumn=1,x.params.slidesPerGroup=1,x.params.centeredSlides=!1,x.params.spaceBetween=0,x.params.virtualTranslate=!0),"fade"!==x.params.effect&&"flip"!==x.params.effect||(x.params.slidesPerView=1,x.params.slidesPerColumn=1,x.params.slidesPerGroup=1,x.params.watchSlidesProgress=!0,x.params.spaceBetween=0,void 0===h&&(x.params.virtualTranslate=!0)),x.params.grabCursor&&x.support.touch&&(x.params.grabCursor=!1),x.wrapper=x.container.children("."+x.params.wrapperClass),x.params.pagination&&(x.paginationContainer=e(x.params.pagination),x.params.uniqueNavElements&&"string"==typeof x.params.pagination&&x.paginationContainer.length>1&&1===x.container.find(x.params.pagination).length&&(x.paginationContainer=x.container.find(x.params.pagination)),"bullets"===x.params.paginationType&&x.params.paginationClickable?x.paginationContainer.addClass(x.params.paginationModifierClass+"clickable"):x.params.paginationClickable=!1,x.paginationContainer.addClass(x.params.paginationModifierClass+x.params.paginationType)),(x.params.nextButton||x.params.prevButton)&&(x.params.nextButton&&(x.nextButton=e(x.params.nextButton),x.params.uniqueNavElements&&"string"==typeof x.params.nextButton&&x.nextButton.length>1&&1===x.container.find(x.params.nextButton).length&&(x.nextButton=x.container.find(x.params.nextButton))),x.params.prevButton&&(x.prevButton=e(x.params.prevButton),x.params.uniqueNavElements&&"string"==typeof x.params.prevButton&&x.prevButton.length>1&&1===x.container.find(x.params.prevButton).length&&(x.prevButton=x.container.find(x.params.prevButton)))),x.isHorizontal=function(){return"horizontal"===x.params.direction},x.rtl=x.isHorizontal()&&("rtl"===x.container[0].dir.toLowerCase()||"rtl"===x.container.css("direction")),x.rtl&&x.classNames.push(x.params.containerModifierClass+"rtl"),x.rtl&&(x.wrongRTL="-webkit-box"===x.wrapper.css("display")),x.params.slidesPerColumn>1&&x.classNames.push(x.params.containerModifierClass+"multirow"),x.device.android&&x.classNames.push(x.params.containerModifierClass+"android"),x.container.addClass(x.classNames.join(" ")),x.translate=0,x.progress=0,x.velocity=0,x.lockSwipeToNext=function(){x.params.allowSwipeToNext=!1,!1===x.params.allowSwipeToPrev&&x.params.grabCursor&&x.unsetGrabCursor()},x.lockSwipeToPrev=function(){x.params.allowSwipeToPrev=!1,!1===x.params.allowSwipeToNext&&x.params.grabCursor&&x.unsetGrabCursor()},x.lockSwipes=function(){x.params.allowSwipeToNext=x.params.allowSwipeToPrev=!1,x.params.grabCursor&&x.unsetGrabCursor()},x.unlockSwipeToNext=function(){x.params.allowSwipeToNext=!0,!0===x.params.allowSwipeToPrev&&x.params.grabCursor&&x.setGrabCursor()},x.unlockSwipeToPrev=function(){x.params.allowSwipeToPrev=!0,!0===x.params.allowSwipeToNext&&x.params.grabCursor&&x.setGrabCursor()},x.unlockSwipes=function(){x.params.allowSwipeToNext=x.params.allowSwipeToPrev=!0,x.params.grabCursor&&x.setGrabCursor()},x.setGrabCursor=function(e){x.container[0].style.cursor="move",x.container[0].style.cursor=e?"-webkit-grabbing":"-webkit-grab",x.container[0].style.cursor=e?"-moz-grabbin":"-moz-grab",x.container[0].style.cursor=e?"grabbing":"grab"},x.unsetGrabCursor=function(){x.container[0].style.cursor=""},x.params.grabCursor&&x.setGrabCursor(),x.imagesToLoad=[],x.imagesLoaded=0,x.loadImage=function(e,a,t,s,i,r){function n(){r&&r()}var o;e.complete&&i?n():a?((o=new window.Image).onload=n,o.onerror=n,s&&(o.sizes=s),t&&(o.srcset=t),a&&(o.src=a)):n()},x.preloadImages=function(){function e(){void 0!==x&&null!==x&&x&&(void 0!==x.imagesLoaded&&x.imagesLoaded++,x.imagesLoaded===x.imagesToLoad.length&&(x.params.updateOnImagesReady&&x.update(),x.emit("onImagesReady",x)))}x.imagesToLoad=x.container.find("img");for(var a=0;a<x.imagesToLoad.length;a++)x.loadImage(x.imagesToLoad[a],x.imagesToLoad[a].currentSrc||x.imagesToLoad[a].getAttribute("src"),x.imagesToLoad[a].srcset||x.imagesToLoad[a].getAttribute("srcset"),x.imagesToLoad[a].sizes||x.imagesToLoad[a].getAttribute("sizes"),!0,e)},x.autoplayTimeoutId=void 0,x.autoplaying=!1,x.autoplayPaused=!1,x.startAutoplay=function(){return void 0===x.autoplayTimeoutId&&(!!x.params.autoplay&&(!x.autoplaying&&(x.autoplaying=!0,x.emit("onAutoplayStart",x),void n())))},x.stopAutoplay=function(e){x.autoplayTimeoutId&&(x.autoplayTimeoutId&&clearTimeout(x.autoplayTimeoutId),x.autoplaying=!1,x.autoplayTimeoutId=void 0,x.emit("onAutoplayStop",x))},x.pauseAutoplay=function(e){x.autoplayPaused||(x.autoplayTimeoutId&&clearTimeout(x.autoplayTimeoutId),x.autoplayPaused=!0,0===e?(x.autoplayPaused=!1,n()):x.wrapper.transitionEnd(function(){x&&(x.autoplayPaused=!1,x.autoplaying?n():x.stopAutoplay())}))},x.minTranslate=function(){return-x.snapGrid[0]},x.maxTranslate=function(){return-x.snapGrid[x.snapGrid.length-1]},x.updateAutoHeight=function(){var e,a=[],t=0;if("auto"!==x.params.slidesPerView&&x.params.slidesPerView>1)for(e=0;e<Math.ceil(x.params.slidesPerView);e++){var s=x.activeIndex+e;if(s>x.slides.length)break;a.push(x.slides.eq(s)[0])}else a.push(x.slides.eq(x.activeIndex)[0]);for(e=0;e<a.length;e++)if(void 0!==a[e]){var i=a[e].offsetHeight;t=i>t?i:t}t&&x.wrapper.css("height",t+"px")},x.updateContainerSize=function(){var e,a;e=void 0!==x.params.width?x.params.width:x.container[0].clientWidth,a=void 0!==x.params.height?x.params.height:x.container[0].clientHeight,0===e&&x.isHorizontal()||0===a&&!x.isHorizontal()||(e=e-parseInt(x.container.css("padding-left"),10)-parseInt(x.container.css("padding-right"),10),a=a-parseInt(x.container.css("padding-top"),10)-parseInt(x.container.css("padding-bottom"),10),x.width=e,x.height=a,x.size=x.isHorizontal()?x.width:x.height)},x.updateSlidesSize=function(){x.slides=x.wrapper.children("."+x.params.slideClass),x.snapGrid=[],x.slidesGrid=[],x.slidesSizesGrid=[];var e,a=x.params.spaceBetween,t=-x.params.slidesOffsetBefore,s=0,i=0;if(void 0!==x.size){"string"==typeof a&&a.indexOf("%")>=0&&(a=parseFloat(a.replace("%",""))/100*x.size),x.virtualSize=-a,x.rtl?x.slides.css({marginLeft:"",marginTop:""}):x.slides.css({marginRight:"",marginBottom:""});var n;x.params.slidesPerColumn>1&&(n=Math.floor(x.slides.length/x.params.slidesPerColumn)===x.slides.length/x.params.slidesPerColumn?x.slides.length:Math.ceil(x.slides.length/x.params.slidesPerColumn)*x.params.slidesPerColumn,"auto"!==x.params.slidesPerView&&"row"===x.params.slidesPerColumnFill&&(n=Math.max(n,x.params.slidesPerView*x.params.slidesPerColumn)));var o,l=x.params.slidesPerColumn,p=n/l,d=p-(x.params.slidesPerColumn*p-x.slides.length);for(e=0;e<x.slides.length;e++){o=0;var u=x.slides.eq(e);if(x.params.slidesPerColumn>1){var c,m,h;"column"===x.params.slidesPerColumnFill?(h=e-(m=Math.floor(e/l))*l,(m>d||m===d&&h===l-1)&&++h>=l&&(h=0,m++),c=m+h*n/l,u.css({"-webkit-box-ordinal-group":c,"-moz-box-ordinal-group":c,"-ms-flex-order":c,"-webkit-order":c,order:c})):m=e-(h=Math.floor(e/p))*p,u.css("margin-"+(x.isHorizontal()?"top":"left"),0!==h&&x.params.spaceBetween&&x.params.spaceBetween+"px").attr("data-swiper-column",m).attr("data-swiper-row",h)}"none"!==u.css("display")&&("auto"===x.params.slidesPerView?(o=x.isHorizontal()?u.outerWidth(!0):u.outerHeight(!0),x.params.roundLengths&&(o=r(o))):(o=(x.size-(x.params.slidesPerView-1)*a)/x.params.slidesPerView,x.params.roundLengths&&(o=r(o)),x.isHorizontal()?x.slides[e].style.width=o+"px":x.slides[e].style.height=o+"px"),x.slides[e].swiperSlideSize=o,x.slidesSizesGrid.push(o),x.params.centeredSlides?(t=t+o/2+s/2+a,0===s&&0!==e&&(t=t-x.size/2-a),0===e&&(t=t-x.size/2-a),Math.abs(t)<.001&&(t=0),i%x.params.slidesPerGroup==0&&x.snapGrid.push(t),x.slidesGrid.push(t)):(i%x.params.slidesPerGroup==0&&x.snapGrid.push(t),x.slidesGrid.push(t),t=t+o+a),x.virtualSize+=o+a,s=o,i++)}x.virtualSize=Math.max(x.virtualSize,x.size)+x.params.slidesOffsetAfter;var g;if(x.rtl&&x.wrongRTL&&("slide"===x.params.effect||"coverflow"===x.params.effect)&&x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}),x.support.flexbox&&!x.params.setWrapperSize||(x.isHorizontal()?x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}):x.wrapper.css({height:x.virtualSize+x.params.spaceBetween+"px"})),x.params.slidesPerColumn>1&&(x.virtualSize=(o+x.params.spaceBetween)*n,x.virtualSize=Math.ceil(x.virtualSize/x.params.slidesPerColumn)-x.params.spaceBetween,x.isHorizontal()?x.wrapper.css({width:x.virtualSize+x.params.spaceBetween+"px"}):x.wrapper.css({height:x.virtualSize+x.params.spaceBetween+"px"}),x.params.centeredSlides)){for(g=[],e=0;e<x.snapGrid.length;e++)x.snapGrid[e]<x.virtualSize+x.snapGrid[0]&&g.push(x.snapGrid[e]);x.snapGrid=g}if(!x.params.centeredSlides){for(g=[],e=0;e<x.snapGrid.length;e++)x.snapGrid[e]<=x.virtualSize-x.size&&g.push(x.snapGrid[e]);x.snapGrid=g,Math.floor(x.virtualSize-x.size)-Math.floor(x.snapGrid[x.snapGrid.length-1])>1&&x.snapGrid.push(x.virtualSize-x.size)}0===x.snapGrid.length&&(x.snapGrid=[0]),0!==x.params.spaceBetween&&(x.isHorizontal()?x.rtl?x.slides.css({marginLeft:a+"px"}):x.slides.css({marginRight:a+"px"}):x.slides.css({marginBottom:a+"px"})),x.params.watchSlidesProgress&&x.updateSlidesOffset()}},x.updateSlidesOffset=function(){for(var e=0;e<x.slides.length;e++)x.slides[e].swiperSlideOffset=x.isHorizontal()?x.slides[e].offsetLeft:x.slides[e].offsetTop},x.currentSlidesPerView=function(){var e,a,t=1;if(x.params.centeredSlides){var s,i=x.slides[x.activeIndex].swiperSlideSize;for(e=x.activeIndex+1;e<x.slides.length;e++)x.slides[e]&&!s&&(t++,(i+=x.slides[e].swiperSlideSize)>x.size&&(s=!0));for(a=x.activeIndex-1;a>=0;a--)x.slides[a]&&!s&&(t++,(i+=x.slides[a].swiperSlideSize)>x.size&&(s=!0))}else for(e=x.activeIndex+1;e<x.slides.length;e++)x.slidesGrid[e]-x.slidesGrid[x.activeIndex]<x.size&&t++;return t},x.updateSlidesProgress=function(e){if(void 0===e&&(e=x.translate||0),0!==x.slides.length){void 0===x.slides[0].swiperSlideOffset&&x.updateSlidesOffset();var a=-e;x.rtl&&(a=e),x.slides.removeClass(x.params.slideVisibleClass);for(var t=0;t<x.slides.length;t++){var s=x.slides[t],i=(a+(x.params.centeredSlides?x.minTranslate():0)-s.swiperSlideOffset)/(s.swiperSlideSize+x.params.spaceBetween);if(x.params.watchSlidesVisibility){var r=-(a-s.swiperSlideOffset),n=r+x.slidesSizesGrid[t];(r>=0&&r<x.size||n>0&&n<=x.size||r<=0&&n>=x.size)&&x.slides.eq(t).addClass(x.params.slideVisibleClass)}s.progress=x.rtl?-i:i}}},x.updateProgress=function(e){void 0===e&&(e=x.translate||0);var a=x.maxTranslate()-x.minTranslate(),t=x.isBeginning,s=x.isEnd;0===a?(x.progress=0,x.isBeginning=x.isEnd=!0):(x.progress=(e-x.minTranslate())/a,x.isBeginning=x.progress<=0,x.isEnd=x.progress>=1),x.isBeginning&&!t&&x.emit("onReachBeginning",x),x.isEnd&&!s&&x.emit("onReachEnd",x),x.params.watchSlidesProgress&&x.updateSlidesProgress(e),x.emit("onProgress",x,x.progress)},x.updateActiveIndex=function(){var e,a,t,s=x.rtl?x.translate:-x.translate;for(a=0;a<x.slidesGrid.length;a++)void 0!==x.slidesGrid[a+1]?s>=x.slidesGrid[a]&&s<x.slidesGrid[a+1]-(x.slidesGrid[a+1]-x.slidesGrid[a])/2?e=a:s>=x.slidesGrid[a]&&s<x.slidesGrid[a+1]&&(e=a+1):s>=x.slidesGrid[a]&&(e=a);x.params.normalizeSlideIndex&&(e<0||void 0===e)&&(e=0),(t=Math.floor(e/x.params.slidesPerGroup))>=x.snapGrid.length&&(t=x.snapGrid.length-1),e!==x.activeIndex&&(x.snapIndex=t,x.previousIndex=x.activeIndex,x.activeIndex=e,x.updateClasses(),x.updateRealIndex())},x.updateRealIndex=function(){x.realIndex=parseInt(x.slides.eq(x.activeIndex).attr("data-swiper-slide-index")||x.activeIndex,10)},x.updateClasses=function(){x.slides.removeClass(x.params.slideActiveClass+" "+x.params.slideNextClass+" "+x.params.slidePrevClass+" "+x.params.slideDuplicateActiveClass+" "+x.params.slideDuplicateNextClass+" "+x.params.slideDuplicatePrevClass);var a=x.slides.eq(x.activeIndex);a.addClass(x.params.slideActiveClass),i.loop&&(a.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+x.realIndex+'"]').addClass(x.params.slideDuplicateActiveClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+x.realIndex+'"]').addClass(x.params.slideDuplicateActiveClass));var t=a.next("."+x.params.slideClass).addClass(x.params.slideNextClass);x.params.loop&&0===t.length&&(t=x.slides.eq(0)).addClass(x.params.slideNextClass);var s=a.prev("."+x.params.slideClass).addClass(x.params.slidePrevClass);if(x.params.loop&&0===s.length&&(s=x.slides.eq(-1)).addClass(x.params.slidePrevClass),i.loop&&(t.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicateNextClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicateNextClass),s.hasClass(x.params.slideDuplicateClass)?x.wrapper.children("."+x.params.slideClass+":not(."+x.params.slideDuplicateClass+')[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicatePrevClass):x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(x.params.slideDuplicatePrevClass)),x.paginationContainer&&x.paginationContainer.length>0){var r,n=x.params.loop?Math.ceil((x.slides.length-2*x.loopedSlides)/x.params.slidesPerGroup):x.snapGrid.length;if(x.params.loop?((r=Math.ceil((x.activeIndex-x.loopedSlides)/x.params.slidesPerGroup))>x.slides.length-1-2*x.loopedSlides&&(r-=x.slides.length-2*x.loopedSlides),r>n-1&&(r-=n),r<0&&"bullets"!==x.params.paginationType&&(r=n+r)):r=void 0!==x.snapIndex?x.snapIndex:x.activeIndex||0,"bullets"===x.params.paginationType&&x.bullets&&x.bullets.length>0&&(x.bullets.removeClass(x.params.bulletActiveClass),x.paginationContainer.length>1?x.bullets.each(function(){e(this).index()===r&&e(this).addClass(x.params.bulletActiveClass)}):x.bullets.eq(r).addClass(x.params.bulletActiveClass)),"fraction"===x.params.paginationType&&(x.paginationContainer.find("."+x.params.paginationCurrentClass).text(r+1),x.paginationContainer.find("."+x.params.paginationTotalClass).text(n)),"progress"===x.params.paginationType){var o=(r+1)/n,l=o,p=1;x.isHorizontal()||(p=o,l=1),x.paginationContainer.find("."+x.params.paginationProgressbarClass).transform("translate3d(0,0,0) scaleX("+l+") scaleY("+p+")").transition(x.params.speed)}"custom"===x.params.paginationType&&x.params.paginationCustomRender&&(x.paginationContainer.html(x.params.paginationCustomRender(x,r+1,n)),x.emit("onPaginationRendered",x,x.paginationContainer[0]))}x.params.loop||(x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.isBeginning?(x.prevButton.addClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.disable(x.prevButton)):(x.prevButton.removeClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.enable(x.prevButton))),x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.isEnd?(x.nextButton.addClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.disable(x.nextButton)):(x.nextButton.removeClass(x.params.buttonDisabledClass),x.params.a11y&&x.a11y&&x.a11y.enable(x.nextButton))))},x.updatePagination=function(){if(x.params.pagination&&x.paginationContainer&&x.paginationContainer.length>0){var e="";if("bullets"===x.params.paginationType){for(var a=x.params.loop?Math.ceil((x.slides.length-2*x.loopedSlides)/x.params.slidesPerGroup):x.snapGrid.length,t=0;t<a;t++)x.params.paginationBulletRender?e+=x.params.paginationBulletRender(x,t,x.params.bulletClass):e+="<"+x.params.paginationElement+' class="'+x.params.bulletClass+'"></'+x.params.paginationElement+">";x.paginationContainer.html(e),x.bullets=x.paginationContainer.find("."+x.params.bulletClass),x.params.paginationClickable&&x.params.a11y&&x.a11y&&x.a11y.initPagination()}"fraction"===x.params.paginationType&&(e=x.params.paginationFractionRender?x.params.paginationFractionRender(x,x.params.paginationCurrentClass,x.params.paginationTotalClass):'<span class="'+x.params.paginationCurrentClass+'"></span> / <span class="'+x.params.paginationTotalClass+'"></span>',x.paginationContainer.html(e)),"progress"===x.params.paginationType&&(e=x.params.paginationProgressRender?x.params.paginationProgressRender(x,x.params.paginationProgressbarClass):'<span class="'+x.params.paginationProgressbarClass+'"></span>',x.paginationContainer.html(e)),"custom"!==x.params.paginationType&&x.emit("onPaginationRendered",x,x.paginationContainer[0])}},x.update=function(e){function a(){x.rtl,x.translate;t=Math.min(Math.max(x.translate,x.maxTranslate()),x.minTranslate()),x.setWrapperTranslate(t),x.updateActiveIndex(),x.updateClasses()}if(x){x.updateContainerSize(),x.updateSlidesSize(),x.updateProgress(),x.updatePagination(),x.updateClasses(),x.params.scrollbar&&x.scrollbar&&x.scrollbar.set();var t;if(e){x.controller&&x.controller.spline&&(x.controller.spline=void 0),x.params.freeMode?(a(),x.params.autoHeight&&x.updateAutoHeight()):(("auto"===x.params.slidesPerView||x.params.slidesPerView>1)&&x.isEnd&&!x.params.centeredSlides?x.slideTo(x.slides.length-1,0,!1,!0):x.slideTo(x.activeIndex,0,!1,!0))||a()}else x.params.autoHeight&&x.updateAutoHeight()}},x.onResize=function(e){x.params.onBeforeResize&&x.params.onBeforeResize(x),x.params.breakpoints&&x.setBreakpoint();var a=x.params.allowSwipeToPrev,t=x.params.allowSwipeToNext;x.params.allowSwipeToPrev=x.params.allowSwipeToNext=!0,x.updateContainerSize(),x.updateSlidesSize(),("auto"===x.params.slidesPerView||x.params.freeMode||e)&&x.updatePagination(),x.params.scrollbar&&x.scrollbar&&x.scrollbar.set(),x.controller&&x.controller.spline&&(x.controller.spline=void 0);var s=!1;if(x.params.freeMode){var i=Math.min(Math.max(x.translate,x.maxTranslate()),x.minTranslate());x.setWrapperTranslate(i),x.updateActiveIndex(),x.updateClasses(),x.params.autoHeight&&x.updateAutoHeight()}else x.updateClasses(),s=("auto"===x.params.slidesPerView||x.params.slidesPerView>1)&&x.isEnd&&!x.params.centeredSlides?x.slideTo(x.slides.length-1,0,!1,!0):x.slideTo(x.activeIndex,0,!1,!0);x.params.lazyLoading&&!s&&x.lazy&&x.lazy.load(),x.params.allowSwipeToPrev=a,x.params.allowSwipeToNext=t,x.params.onAfterResize&&x.params.onAfterResize(x)},x.touchEventsDesktop={start:"mousedown",move:"mousemove",end:"mouseup"},window.navigator.pointerEnabled?x.touchEventsDesktop={start:"pointerdown",move:"pointermove",end:"pointerup"}:window.navigator.msPointerEnabled&&(x.touchEventsDesktop={start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}),x.touchEvents={start:x.support.touch||!x.params.simulateTouch?"touchstart":x.touchEventsDesktop.start,move:x.support.touch||!x.params.simulateTouch?"touchmove":x.touchEventsDesktop.move,end:x.support.touch||!x.params.simulateTouch?"touchend":x.touchEventsDesktop.end},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===x.params.touchEventsTarget?x.container:x.wrapper).addClass("swiper-wp8-"+x.params.direction),x.initEvents=function(e){var a=e?"off":"on",t=e?"removeEventListener":"addEventListener",s="container"===x.params.touchEventsTarget?x.container[0]:x.wrapper[0],r=x.support.touch?s:document,n=!!x.params.nested;if(x.browser.ie)s[t](x.touchEvents.start,x.onTouchStart,!1),r[t](x.touchEvents.move,x.onTouchMove,n),r[t](x.touchEvents.end,x.onTouchEnd,!1);else{if(x.support.touch){var o=!("touchstart"!==x.touchEvents.start||!x.support.passiveListener||!x.params.passiveListeners)&&{passive:!0,capture:!1};s[t](x.touchEvents.start,x.onTouchStart,o),s[t](x.touchEvents.move,x.onTouchMove,n),s[t](x.touchEvents.end,x.onTouchEnd,o)}(i.simulateTouch&&!x.device.ios&&!x.device.android||i.simulateTouch&&!x.support.touch&&x.device.ios)&&(s[t]("mousedown",x.onTouchStart,!1),document[t]("mousemove",x.onTouchMove,n),document[t]("mouseup",x.onTouchEnd,!1))}window[t]("resize",x.onResize),x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.nextButton[a]("click",x.onClickNext),x.params.a11y&&x.a11y&&x.nextButton[a]("keydown",x.a11y.onEnterKey)),x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.prevButton[a]("click",x.onClickPrev),x.params.a11y&&x.a11y&&x.prevButton[a]("keydown",x.a11y.onEnterKey)),x.params.pagination&&x.params.paginationClickable&&(x.paginationContainer[a]("click","."+x.params.bulletClass,x.onClickIndex),x.params.a11y&&x.a11y&&x.paginationContainer[a]("keydown","."+x.params.bulletClass,x.a11y.onEnterKey)),(x.params.preventClicks||x.params.preventClicksPropagation)&&s[t]("click",x.preventClicks,!0)},x.attachEvents=function(){x.initEvents()},x.detachEvents=function(){x.initEvents(!0)},x.allowClick=!0,x.preventClicks=function(e){x.allowClick||(x.params.preventClicks&&e.preventDefault(),x.params.preventClicksPropagation&&x.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},x.onClickNext=function(e){e.preventDefault(),x.isEnd&&!x.params.loop||x.slideNext()},x.onClickPrev=function(e){e.preventDefault(),x.isBeginning&&!x.params.loop||x.slidePrev()},x.onClickIndex=function(a){a.preventDefault();var t=e(this).index()*x.params.slidesPerGroup;x.params.loop&&(t+=x.loopedSlides),x.slideTo(t)},x.updateClickedSlide=function(a){var t=o(a,"."+x.params.slideClass),s=!1;if(t)for(var i=0;i<x.slides.length;i++)x.slides[i]===t&&(s=!0);if(!t||!s)return x.clickedSlide=void 0,void(x.clickedIndex=void 0);if(x.clickedSlide=t,x.clickedIndex=e(t).index(),x.params.slideToClickedSlide&&void 0!==x.clickedIndex&&x.clickedIndex!==x.activeIndex){var r,n=x.clickedIndex,l="auto"===x.params.slidesPerView?x.currentSlidesPerView():x.params.slidesPerView;if(x.params.loop){if(x.animating)return;r=parseInt(e(x.clickedSlide).attr("data-swiper-slide-index"),10),x.params.centeredSlides?n<x.loopedSlides-l/2||n>x.slides.length-x.loopedSlides+l/2?(x.fixLoop(),n=x.wrapper.children("."+x.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+x.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){x.slideTo(n)},0)):x.slideTo(n):n>x.slides.length-l?(x.fixLoop(),n=x.wrapper.children("."+x.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+x.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){x.slideTo(n)},0)):x.slideTo(n)}else x.slideTo(n)}};var b,S,C,z,M,E,P,I,k,L,D="input, select, textarea, button, video",B=Date.now(),H=[];x.animating=!1,x.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var G,X;x.onTouchStart=function(a){if(a.originalEvent&&(a=a.originalEvent),(G="touchstart"===a.type)||!("which"in a)||3!==a.which)if(x.params.noSwiping&&o(a,"."+x.params.noSwipingClass))x.allowClick=!0;else if(!x.params.swipeHandler||o(a,x.params.swipeHandler)){var t=x.touches.currentX="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,s=x.touches.currentY="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY;if(!(x.device.ios&&x.params.iOSEdgeSwipeDetection&&t<=x.params.iOSEdgeSwipeThreshold)){if(b=!0,S=!1,C=!0,M=void 0,X=void 0,x.touches.startX=t,x.touches.startY=s,z=Date.now(),x.allowClick=!0,x.updateContainerSize(),x.swipeDirection=void 0,x.params.threshold>0&&(I=!1),"touchstart"!==a.type){var i=!0;e(a.target).is(D)&&(i=!1),document.activeElement&&e(document.activeElement).is(D)&&document.activeElement.blur(),i&&a.preventDefault()}x.emit("onTouchStart",x,a)}}},x.onTouchMove=function(a){if(a.originalEvent&&(a=a.originalEvent),!G||"mousemove"!==a.type){if(a.preventedByNestedSwiper)return x.touches.startX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,void(x.touches.startY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY);if(x.params.onlyExternal)return x.allowClick=!1,void(b&&(x.touches.startX=x.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,x.touches.startY=x.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,z=Date.now()));if(G&&x.params.touchReleaseOnEdges&&!x.params.loop)if(x.isHorizontal()){if(x.touches.currentX<x.touches.startX&&x.translate<=x.maxTranslate()||x.touches.currentX>x.touches.startX&&x.translate>=x.minTranslate())return}else if(x.touches.currentY<x.touches.startY&&x.translate<=x.maxTranslate()||x.touches.currentY>x.touches.startY&&x.translate>=x.minTranslate())return;if(G&&document.activeElement&&a.target===document.activeElement&&e(a.target).is(D))return S=!0,void(x.allowClick=!1);if(C&&x.emit("onTouchMove",x,a),!(a.targetTouches&&a.targetTouches.length>1)){if(x.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,x.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,void 0===M){var t;x.isHorizontal()&&x.touches.currentY===x.touches.startY||!x.isHorizontal()&&x.touches.currentX===x.touches.startX?M=!1:(t=180*Math.atan2(Math.abs(x.touches.currentY-x.touches.startY),Math.abs(x.touches.currentX-x.touches.startX))/Math.PI,M=x.isHorizontal()?t>x.params.touchAngle:90-t>x.params.touchAngle)}if(M&&x.emit("onTouchMoveOpposite",x,a),void 0===X&&(x.touches.currentX===x.touches.startX&&x.touches.currentY===x.touches.startY||(X=!0)),b)if(M)b=!1;else if(X){x.allowClick=!1,x.emit("onSliderMove",x,a),a.preventDefault(),x.params.touchMoveStopPropagation&&!x.params.nested&&a.stopPropagation(),S||(i.loop&&x.fixLoop(),P=x.getWrapperTranslate(),x.setWrapperTransition(0),x.animating&&x.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),x.params.autoplay&&x.autoplaying&&(x.params.autoplayDisableOnInteraction?x.stopAutoplay():x.pauseAutoplay()),L=!1,!x.params.grabCursor||!0!==x.params.allowSwipeToNext&&!0!==x.params.allowSwipeToPrev||x.setGrabCursor(!0)),S=!0;var s=x.touches.diff=x.isHorizontal()?x.touches.currentX-x.touches.startX:x.touches.currentY-x.touches.startY;s*=x.params.touchRatio,x.rtl&&(s=-s),x.swipeDirection=s>0?"prev":"next",E=s+P;var r=!0;if(s>0&&E>x.minTranslate()?(r=!1,x.params.resistance&&(E=x.minTranslate()-1+Math.pow(-x.minTranslate()+P+s,x.params.resistanceRatio))):s<0&&E<x.maxTranslate()&&(r=!1,x.params.resistance&&(E=x.maxTranslate()+1-Math.pow(x.maxTranslate()-P-s,x.params.resistanceRatio))),r&&(a.preventedByNestedSwiper=!0),!x.params.allowSwipeToNext&&"next"===x.swipeDirection&&E<P&&(E=P),!x.params.allowSwipeToPrev&&"prev"===x.swipeDirection&&E>P&&(E=P),x.params.threshold>0){if(!(Math.abs(s)>x.params.threshold||I))return void(E=P);if(!I)return I=!0,x.touches.startX=x.touches.currentX,x.touches.startY=x.touches.currentY,E=P,void(x.touches.diff=x.isHorizontal()?x.touches.currentX-x.touches.startX:x.touches.currentY-x.touches.startY)}x.params.followFinger&&((x.params.freeMode||x.params.watchSlidesProgress)&&x.updateActiveIndex(),x.params.freeMode&&(0===H.length&&H.push({position:x.touches[x.isHorizontal()?"startX":"startY"],time:z}),H.push({position:x.touches[x.isHorizontal()?"currentX":"currentY"],time:(new window.Date).getTime()})),x.updateProgress(E),x.setWrapperTranslate(E))}}}},x.onTouchEnd=function(a){if(a.originalEvent&&(a=a.originalEvent),C&&x.emit("onTouchEnd",x,a),C=!1,b){x.params.grabCursor&&S&&b&&(!0===x.params.allowSwipeToNext||!0===x.params.allowSwipeToPrev)&&x.setGrabCursor(!1);var t=Date.now(),s=t-z;if(x.allowClick&&(x.updateClickedSlide(a),x.emit("onTap",x,a),s<300&&t-B>300&&(k&&clearTimeout(k),k=setTimeout(function(){x&&(x.params.paginationHide&&x.paginationContainer.length>0&&!e(a.target).hasClass(x.params.bulletClass)&&x.paginationContainer.toggleClass(x.params.paginationHiddenClass),x.emit("onClick",x,a))},300)),s<300&&t-B<300&&(k&&clearTimeout(k),x.emit("onDoubleTap",x,a))),B=Date.now(),setTimeout(function(){x&&(x.allowClick=!0)},0),b&&S&&x.swipeDirection&&0!==x.touches.diff&&E!==P){b=S=!1;var i;if(i=x.params.followFinger?x.rtl?x.translate:-x.translate:-E,x.params.freeMode){if(i<-x.minTranslate())return void x.slideTo(x.activeIndex);if(i>-x.maxTranslate())return void(x.slides.length<x.snapGrid.length?x.slideTo(x.snapGrid.length-1):x.slideTo(x.slides.length-1));if(x.params.freeModeMomentum){if(H.length>1){var r=H.pop(),n=H.pop(),o=r.position-n.position,l=r.time-n.time;x.velocity=o/l,x.velocity=x.velocity/2,Math.abs(x.velocity)<x.params.freeModeMinimumVelocity&&(x.velocity=0),(l>150||(new window.Date).getTime()-r.time>300)&&(x.velocity=0)}else x.velocity=0;x.velocity=x.velocity*x.params.freeModeMomentumVelocityRatio,H.length=0;var p=1e3*x.params.freeModeMomentumRatio,d=x.velocity*p,u=x.translate+d;x.rtl&&(u=-u);var c,m=!1,h=20*Math.abs(x.velocity)*x.params.freeModeMomentumBounceRatio;if(u<x.maxTranslate())x.params.freeModeMomentumBounce?(u+x.maxTranslate()<-h&&(u=x.maxTranslate()-h),c=x.maxTranslate(),m=!0,L=!0):u=x.maxTranslate();else if(u>x.minTranslate())x.params.freeModeMomentumBounce?(u-x.minTranslate()>h&&(u=x.minTranslate()+h),c=x.minTranslate(),m=!0,L=!0):u=x.minTranslate();else if(x.params.freeModeSticky){var g,f=0;for(f=0;f<x.snapGrid.length;f+=1)if(x.snapGrid[f]>-u){g=f;break}u=Math.abs(x.snapGrid[g]-u)<Math.abs(x.snapGrid[g-1]-u)||"next"===x.swipeDirection?x.snapGrid[g]:x.snapGrid[g-1],x.rtl||(u=-u)}if(0!==x.velocity)p=x.rtl?Math.abs((-u-x.translate)/x.velocity):Math.abs((u-x.translate)/x.velocity);else if(x.params.freeModeSticky)return void x.slideReset();x.params.freeModeMomentumBounce&&m?(x.updateProgress(c),x.setWrapperTransition(p),x.setWrapperTranslate(u),x.onTransitionStart(),x.animating=!0,x.wrapper.transitionEnd(function(){x&&L&&(x.emit("onMomentumBounce",x),x.setWrapperTransition(x.params.speed),x.setWrapperTranslate(c),x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd()}))})):x.velocity?(x.updateProgress(u),x.setWrapperTransition(p),x.setWrapperTranslate(u),x.onTransitionStart(),x.animating||(x.animating=!0,x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd()}))):x.updateProgress(u),x.updateActiveIndex()}(!x.params.freeModeMomentum||s>=x.params.longSwipesMs)&&(x.updateProgress(),x.updateActiveIndex())}else{var v,w=0,y=x.slidesSizesGrid[0];for(v=0;v<x.slidesGrid.length;v+=x.params.slidesPerGroup)void 0!==x.slidesGrid[v+x.params.slidesPerGroup]?i>=x.slidesGrid[v]&&i<x.slidesGrid[v+x.params.slidesPerGroup]&&(w=v,y=x.slidesGrid[v+x.params.slidesPerGroup]-x.slidesGrid[v]):i>=x.slidesGrid[v]&&(w=v,y=x.slidesGrid[x.slidesGrid.length-1]-x.slidesGrid[x.slidesGrid.length-2]);var T=(i-x.slidesGrid[w])/y;if(s>x.params.longSwipesMs){if(!x.params.longSwipes)return void x.slideTo(x.activeIndex);"next"===x.swipeDirection&&(T>=x.params.longSwipesRatio?x.slideTo(w+x.params.slidesPerGroup):x.slideTo(w)),"prev"===x.swipeDirection&&(T>1-x.params.longSwipesRatio?x.slideTo(w+x.params.slidesPerGroup):x.slideTo(w))}else{if(!x.params.shortSwipes)return void x.slideTo(x.activeIndex);"next"===x.swipeDirection&&x.slideTo(w+x.params.slidesPerGroup),"prev"===x.swipeDirection&&x.slideTo(w)}}}else b=S=!1}},x._slideTo=function(e,a){return x.slideTo(e,a,!0,!0)},x.slideTo=function(e,a,t,s){void 0===t&&(t=!0),void 0===e&&(e=0),e<0&&(e=0),x.snapIndex=Math.floor(e/x.params.slidesPerGroup),x.snapIndex>=x.snapGrid.length&&(x.snapIndex=x.snapGrid.length-1);var i=-x.snapGrid[x.snapIndex];if(x.params.autoplay&&x.autoplaying&&(s||!x.params.autoplayDisableOnInteraction?x.pauseAutoplay(a):x.stopAutoplay()),x.updateProgress(i),x.params.normalizeSlideIndex)for(var r=0;r<x.slidesGrid.length;r++)-Math.floor(100*i)>=Math.floor(100*x.slidesGrid[r])&&(e=r);return!(!x.params.allowSwipeToNext&&i<x.translate&&i<x.minTranslate())&&(!(!x.params.allowSwipeToPrev&&i>x.translate&&i>x.maxTranslate()&&(x.activeIndex||0)!==e)&&(void 0===a&&(a=x.params.speed),x.previousIndex=x.activeIndex||0,x.activeIndex=e,x.updateRealIndex(),x.rtl&&-i===x.translate||!x.rtl&&i===x.translate?(x.params.autoHeight&&x.updateAutoHeight(),x.updateClasses(),"slide"!==x.params.effect&&x.setWrapperTranslate(i),!1):(x.updateClasses(),x.onTransitionStart(t),0===a||x.browser.lteIE9?(x.setWrapperTranslate(i),x.setWrapperTransition(0),x.onTransitionEnd(t)):(x.setWrapperTranslate(i),x.setWrapperTransition(a),x.animating||(x.animating=!0,x.wrapper.transitionEnd(function(){x&&x.onTransitionEnd(t)}))),!0)))},x.onTransitionStart=function(e){void 0===e&&(e=!0),x.params.autoHeight&&x.updateAutoHeight(),x.lazy&&x.lazy.onTransitionStart(),e&&(x.emit("onTransitionStart",x),x.activeIndex!==x.previousIndex&&(x.emit("onSlideChangeStart",x),x.activeIndex>x.previousIndex?x.emit("onSlideNextStart",x):x.emit("onSlidePrevStart",x)))},x.onTransitionEnd=function(e){x.animating=!1,x.setWrapperTransition(0),void 0===e&&(e=!0),x.lazy&&x.lazy.onTransitionEnd(),e&&(x.emit("onTransitionEnd",x),x.activeIndex!==x.previousIndex&&(x.emit("onSlideChangeEnd",x),x.activeIndex>x.previousIndex?x.emit("onSlideNextEnd",x):x.emit("onSlidePrevEnd",x))),x.params.history&&x.history&&x.history.setHistory(x.params.history,x.activeIndex),x.params.hashnav&&x.hashnav&&x.hashnav.setHash()},x.slideNext=function(e,a,t){if(x.params.loop){if(x.animating)return!1;x.fixLoop();x.container[0].clientLeft;return x.slideTo(x.activeIndex+x.params.slidesPerGroup,a,e,t)}return x.slideTo(x.activeIndex+x.params.slidesPerGroup,a,e,t)},x._slideNext=function(e){return x.slideNext(!0,e,!0)},x.slidePrev=function(e,a,t){if(x.params.loop){if(x.animating)return!1;x.fixLoop();x.container[0].clientLeft;return x.slideTo(x.activeIndex-1,a,e,t)}return x.slideTo(x.activeIndex-1,a,e,t)},x._slidePrev=function(e){return x.slidePrev(!0,e,!0)},x.slideReset=function(e,a,t){return x.slideTo(x.activeIndex,a,e)},x.disableTouchControl=function(){return x.params.onlyExternal=!0,!0},x.enableTouchControl=function(){return x.params.onlyExternal=!1,!0},x.setWrapperTransition=function(e,a){x.wrapper.transition(e),"slide"!==x.params.effect&&x.effects[x.params.effect]&&x.effects[x.params.effect].setTransition(e),x.params.parallax&&x.parallax&&x.parallax.setTransition(e),x.params.scrollbar&&x.scrollbar&&x.scrollbar.setTransition(e),x.params.control&&x.controller&&x.controller.setTransition(e,a),x.emit("onSetTransition",x,e)},x.setWrapperTranslate=function(e,a,t){var s=0,i=0;x.isHorizontal()?s=x.rtl?-e:e:i=e,x.params.roundLengths&&(s=r(s),i=r(i)),x.params.virtualTranslate||(x.support.transforms3d?x.wrapper.transform("translate3d("+s+"px, "+i+"px, 0px)"):x.wrapper.transform("translate("+s+"px, "+i+"px)")),x.translate=x.isHorizontal()?s:i;var n=x.maxTranslate()-x.minTranslate();(0===n?0:(e-x.minTranslate())/n)!==x.progress&&x.updateProgress(e),a&&x.updateActiveIndex(),"slide"!==x.params.effect&&x.effects[x.params.effect]&&x.effects[x.params.effect].setTranslate(x.translate),x.params.parallax&&x.parallax&&x.parallax.setTranslate(x.translate),x.params.scrollbar&&x.scrollbar&&x.scrollbar.setTranslate(x.translate),x.params.control&&x.controller&&x.controller.setTranslate(x.translate,t),x.emit("onSetTranslate",x,x.translate)},x.getTranslate=function(e,a){var t,s,i,r;return void 0===a&&(a="x"),x.params.virtualTranslate?x.rtl?-x.translate:x.translate:(i=window.getComputedStyle(e,null),window.WebKitCSSMatrix?((s=i.transform||i.webkitTransform).split(",").length>6&&(s=s.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),r=new window.WebKitCSSMatrix("none"===s?"":s)):t=(r=i.MozTransform||i.OTransform||i.MsTransform||i.msTransform||i.transform||i.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,")).toString().split(","),"x"===a&&(s=window.WebKitCSSMatrix?r.m41:16===t.length?parseFloat(t[12]):parseFloat(t[4])),"y"===a&&(s=window.WebKitCSSMatrix?r.m42:16===t.length?parseFloat(t[13]):parseFloat(t[5])),x.rtl&&s&&(s=-s),s||0)},x.getWrapperTranslate=function(e){return void 0===e&&(e=x.isHorizontal()?"x":"y"),x.getTranslate(x.wrapper[0],e)},x.observers=[],x.initObservers=function(){if(x.params.observeParents)for(var e=x.container.parents(),a=0;a<e.length;a++)l(e[a]);l(x.container[0],{childList:!1}),l(x.wrapper[0],{attributes:!1})},x.disconnectObservers=function(){for(var e=0;e<x.observers.length;e++)x.observers[e].disconnect();x.observers=[]},x.createLoop=function(){x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass).remove();var a=x.wrapper.children("."+x.params.slideClass);"auto"!==x.params.slidesPerView||x.params.loopedSlides||(x.params.loopedSlides=a.length),x.loopedSlides=parseInt(x.params.loopedSlides||x.params.slidesPerView,10),x.loopedSlides=x.loopedSlides+x.params.loopAdditionalSlides,x.loopedSlides>a.length&&(x.loopedSlides=a.length);var t,s=[],i=[];for(a.each(function(t,r){var n=e(this);t<x.loopedSlides&&i.push(r),t<a.length&&t>=a.length-x.loopedSlides&&s.push(r),n.attr("data-swiper-slide-index",t)}),t=0;t<i.length;t++)x.wrapper.append(e(i[t].cloneNode(!0)).addClass(x.params.slideDuplicateClass));for(t=s.length-1;t>=0;t--)x.wrapper.prepend(e(s[t].cloneNode(!0)).addClass(x.params.slideDuplicateClass))},x.destroyLoop=function(){x.wrapper.children("."+x.params.slideClass+"."+x.params.slideDuplicateClass).remove(),x.slides.removeAttr("data-swiper-slide-index")},x.reLoop=function(e){var a=x.activeIndex-x.loopedSlides;x.destroyLoop(),x.createLoop(),x.updateSlidesSize(),e&&x.slideTo(a+x.loopedSlides,0,!1)},x.fixLoop=function(){var e;x.activeIndex<x.loopedSlides?(e=x.slides.length-3*x.loopedSlides+x.activeIndex,e+=x.loopedSlides,x.slideTo(e,0,!1,!0)):("auto"===x.params.slidesPerView&&x.activeIndex>=2*x.loopedSlides||x.activeIndex>x.slides.length-2*x.params.slidesPerView)&&(e=-x.slides.length+x.activeIndex+x.loopedSlides,e+=x.loopedSlides,x.slideTo(e,0,!1,!0))},x.appendSlide=function(e){if(x.params.loop&&x.destroyLoop(),"object"==typeof e&&e.length)for(var a=0;a<e.length;a++)e[a]&&x.wrapper.append(e[a]);else x.wrapper.append(e);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0)},x.prependSlide=function(e){x.params.loop&&x.destroyLoop();var a=x.activeIndex+1;if("object"==typeof e&&e.length){for(var t=0;t<e.length;t++)e[t]&&x.wrapper.prepend(e[t]);a=x.activeIndex+e.length}else x.wrapper.prepend(e);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0),x.slideTo(a,0,!1)},x.removeSlide=function(e){x.params.loop&&(x.destroyLoop(),x.slides=x.wrapper.children("."+x.params.slideClass));var a,t=x.activeIndex;if("object"==typeof e&&e.length){for(var s=0;s<e.length;s++)a=e[s],x.slides[a]&&x.slides.eq(a).remove(),a<t&&t--;t=Math.max(t,0)}else a=e,x.slides[a]&&x.slides.eq(a).remove(),a<t&&t--,t=Math.max(t,0);x.params.loop&&x.createLoop(),x.params.observer&&x.support.observer||x.update(!0),x.params.loop?x.slideTo(t+x.loopedSlides,0,!1):x.slideTo(t,0,!1)},x.removeAllSlides=function(){for(var e=[],a=0;a<x.slides.length;a++)e.push(a);x.removeSlide(e)},x.effects={fade:{setTranslate:function(){for(var e=0;e<x.slides.length;e++){var a=x.slides.eq(e),t=-a[0].swiperSlideOffset;x.params.virtualTranslate||(t-=x.translate);var s=0;x.isHorizontal()||(s=t,t=0);var i=x.params.fade.crossFade?Math.max(1-Math.abs(a[0].progress),0):1+Math.min(Math.max(a[0].progress,-1),0);a.css({opacity:i}).transform("translate3d("+t+"px, "+s+"px, 0px)")}},setTransition:function(e){if(x.slides.transition(e),x.params.virtualTranslate&&0!==e){var a=!1;x.slides.transitionEnd(function(){if(!a&&x){a=!0,x.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],t=0;t<e.length;t++)x.wrapper.trigger(e[t])}})}}},flip:{setTranslate:function(){for(var a=0;a<x.slides.length;a++){var t=x.slides.eq(a),s=t[0].progress;x.params.flip.limitRotation&&(s=Math.max(Math.min(t[0].progress,1),-1));var i=-180*s,r=0,n=-t[0].swiperSlideOffset,o=0;if(x.isHorizontal()?x.rtl&&(i=-i):(o=n,n=0,r=-i,i=0),t[0].style.zIndex=-Math.abs(Math.round(s))+x.slides.length,x.params.flip.slideShadows){var l=x.isHorizontal()?t.find(".swiper-slide-shadow-left"):t.find(".swiper-slide-shadow-top"),p=x.isHorizontal()?t.find(".swiper-slide-shadow-right"):t.find(".swiper-slide-shadow-bottom");0===l.length&&(l=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),t.append(l)),0===p.length&&(p=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),t.append(p)),l.length&&(l[0].style.opacity=Math.max(-s,0)),p.length&&(p[0].style.opacity=Math.max(s,0))}t.transform("translate3d("+n+"px, "+o+"px, 0px) rotateX("+r+"deg) rotateY("+i+"deg)")}},setTransition:function(a){if(x.slides.transition(a).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(a),x.params.virtualTranslate&&0!==a){var t=!1;x.slides.eq(x.activeIndex).transitionEnd(function(){if(!t&&x&&e(this).hasClass(x.params.slideActiveClass)){t=!0,x.animating=!1;for(var a=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],s=0;s<a.length;s++)x.wrapper.trigger(a[s])}})}}},cube:{setTranslate:function(){var a,t=0;x.params.cube.shadow&&(x.isHorizontal()?(0===(a=x.wrapper.find(".swiper-cube-shadow")).length&&(a=e('<div class="swiper-cube-shadow"></div>'),x.wrapper.append(a)),a.css({height:x.width+"px"})):0===(a=x.container.find(".swiper-cube-shadow")).length&&(a=e('<div class="swiper-cube-shadow"></div>'),x.container.append(a)));for(var s=0;s<x.slides.length;s++){var i=x.slides.eq(s),r=90*s,n=Math.floor(r/360);x.rtl&&(r=-r,n=Math.floor(-r/360));var o=Math.max(Math.min(i[0].progress,1),-1),l=0,p=0,d=0;s%4==0?(l=4*-n*x.size,d=0):(s-1)%4==0?(l=0,d=4*-n*x.size):(s-2)%4==0?(l=x.size+4*n*x.size,d=x.size):(s-3)%4==0&&(l=-x.size,d=3*x.size+4*x.size*n),x.rtl&&(l=-l),x.isHorizontal()||(p=l,l=0);var u="rotateX("+(x.isHorizontal()?0:-r)+"deg) rotateY("+(x.isHorizontal()?r:0)+"deg) translate3d("+l+"px, "+p+"px, "+d+"px)";if(o<=1&&o>-1&&(t=90*s+90*o,x.rtl&&(t=90*-s-90*o)),i.transform(u),x.params.cube.slideShadows){var c=x.isHorizontal()?i.find(".swiper-slide-shadow-left"):i.find(".swiper-slide-shadow-top"),m=x.isHorizontal()?i.find(".swiper-slide-shadow-right"):i.find(".swiper-slide-shadow-bottom");0===c.length&&(c=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),i.append(c)),0===m.length&&(m=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),i.append(m)),c.length&&(c[0].style.opacity=Math.max(-o,0)),m.length&&(m[0].style.opacity=Math.max(o,0))}}if(x.wrapper.css({"-webkit-transform-origin":"50% 50% -"+x.size/2+"px","-moz-transform-origin":"50% 50% -"+x.size/2+"px","-ms-transform-origin":"50% 50% -"+x.size/2+"px","transform-origin":"50% 50% -"+x.size/2+"px"}),x.params.cube.shadow)if(x.isHorizontal())a.transform("translate3d(0px, "+(x.width/2+x.params.cube.shadowOffset)+"px, "+-x.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+x.params.cube.shadowScale+")");else{var h=Math.abs(t)-90*Math.floor(Math.abs(t)/90),g=1.5-(Math.sin(2*h*Math.PI/360)/2+Math.cos(2*h*Math.PI/360)/2),f=x.params.cube.shadowScale,v=x.params.cube.shadowScale/g,w=x.params.cube.shadowOffset;a.transform("scale3d("+f+", 1, "+v+") translate3d(0px, "+(x.height/2+w)+"px, "+-x.height/2/v+"px) rotateX(-90deg)")}var y=x.isSafari||x.isUiWebView?-x.size/2:0;x.wrapper.transform("translate3d(0px,0,"+y+"px) rotateX("+(x.isHorizontal()?0:t)+"deg) rotateY("+(x.isHorizontal()?-t:0)+"deg)")},setTransition:function(e){x.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),x.params.cube.shadow&&!x.isHorizontal()&&x.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var a=x.translate,t=x.isHorizontal()?-a+x.width/2:-a+x.height/2,s=x.isHorizontal()?x.params.coverflow.rotate:-x.params.coverflow.rotate,i=x.params.coverflow.depth,r=0,n=x.slides.length;r<n;r++){var o=x.slides.eq(r),l=x.slidesSizesGrid[r],p=(t-o[0].swiperSlideOffset-l/2)/l*x.params.coverflow.modifier,d=x.isHorizontal()?s*p:0,u=x.isHorizontal()?0:s*p,c=-i*Math.abs(p),m=x.isHorizontal()?0:x.params.coverflow.stretch*p,h=x.isHorizontal()?x.params.coverflow.stretch*p:0;Math.abs(h)<.001&&(h=0),Math.abs(m)<.001&&(m=0),Math.abs(c)<.001&&(c=0),Math.abs(d)<.001&&(d=0),Math.abs(u)<.001&&(u=0);var g="translate3d("+h+"px,"+m+"px,"+c+"px)  rotateX("+u+"deg) rotateY("+d+"deg)";if(o.transform(g),o[0].style.zIndex=1-Math.abs(Math.round(p)),x.params.coverflow.slideShadows){var f=x.isHorizontal()?o.find(".swiper-slide-shadow-left"):o.find(".swiper-slide-shadow-top"),v=x.isHorizontal()?o.find(".swiper-slide-shadow-right"):o.find(".swiper-slide-shadow-bottom");0===f.length&&(f=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"left":"top")+'"></div>'),o.append(f)),0===v.length&&(v=e('<div class="swiper-slide-shadow-'+(x.isHorizontal()?"right":"bottom")+'"></div>'),o.append(v)),f.length&&(f[0].style.opacity=p>0?p:0),v.length&&(v[0].style.opacity=-p>0?-p:0)}}if(x.browser.ie){x.wrapper[0].style.perspectiveOrigin=t+"px 50%"}},setTransition:function(e){x.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},x.lazy={initialImageLoaded:!1,loadImageInSlide:function(a,t){if(void 0!==a&&(void 0===t&&(t=!0),0!==x.slides.length)){var s=x.slides.eq(a),i=s.find("."+x.params.lazyLoadingClass+":not(."+x.params.lazyStatusLoadedClass+"):not(."+x.params.lazyStatusLoadingClass+")");!s.hasClass(x.params.lazyLoadingClass)||s.hasClass(x.params.lazyStatusLoadedClass)||s.hasClass(x.params.lazyStatusLoadingClass)||(i=i.add(s[0])),0!==i.length&&i.each(function(){var a=e(this);a.addClass(x.params.lazyStatusLoadingClass);var i=a.attr("data-background"),r=a.attr("data-src"),n=a.attr("data-srcset"),o=a.attr("data-sizes");x.loadImage(a[0],r||i,n,o,!1,function(){if(void 0!==x&&null!==x&&x){if(i?(a.css("background-image",'url("'+i+'")'),a.removeAttr("data-background")):(n&&(a.attr("srcset",n),a.removeAttr("data-srcset")),o&&(a.attr("sizes",o),a.removeAttr("data-sizes")),r&&(a.attr("src",r),a.removeAttr("data-src"))),a.addClass(x.params.lazyStatusLoadedClass).removeClass(x.params.lazyStatusLoadingClass),s.find("."+x.params.lazyPreloaderClass+", ."+x.params.preloaderClass).remove(),x.params.loop&&t){var e=s.attr("data-swiper-slide-index");if(s.hasClass(x.params.slideDuplicateClass)){var l=x.wrapper.children('[data-swiper-slide-index="'+e+'"]:not(.'+x.params.slideDuplicateClass+")");x.lazy.loadImageInSlide(l.index(),!1)}else{var p=x.wrapper.children("."+x.params.slideDuplicateClass+'[data-swiper-slide-index="'+e+'"]');x.lazy.loadImageInSlide(p.index(),!1)}}x.emit("onLazyImageReady",x,s[0],a[0])}}),x.emit("onLazyImageLoad",x,s[0],a[0])})}},load:function(){var a,t=x.params.slidesPerView;if("auto"===t&&(t=0),x.lazy.initialImageLoaded||(x.lazy.initialImageLoaded=!0),x.params.watchSlidesVisibility)x.wrapper.children("."+x.params.slideVisibleClass).each(function(){x.lazy.loadImageInSlide(e(this).index())});else if(t>1)for(a=x.activeIndex;a<x.activeIndex+t;a++)x.slides[a]&&x.lazy.loadImageInSlide(a);else x.lazy.loadImageInSlide(x.activeIndex);if(x.params.lazyLoadingInPrevNext)if(t>1||x.params.lazyLoadingInPrevNextAmount&&x.params.lazyLoadingInPrevNextAmount>1){var s=x.params.lazyLoadingInPrevNextAmount,i=t,r=Math.min(x.activeIndex+i+Math.max(s,i),x.slides.length),n=Math.max(x.activeIndex-Math.max(i,s),0);for(a=x.activeIndex+t;a<r;a++)x.slides[a]&&x.lazy.loadImageInSlide(a);for(a=n;a<x.activeIndex;a++)x.slides[a]&&x.lazy.loadImageInSlide(a)}else{var o=x.wrapper.children("."+x.params.slideNextClass);o.length>0&&x.lazy.loadImageInSlide(o.index());var l=x.wrapper.children("."+x.params.slidePrevClass);l.length>0&&x.lazy.loadImageInSlide(l.index())}},onTransitionStart:function(){x.params.lazyLoading&&(x.params.lazyLoadingOnTransitionStart||!x.params.lazyLoadingOnTransitionStart&&!x.lazy.initialImageLoaded)&&x.lazy.load()},onTransitionEnd:function(){x.params.lazyLoading&&!x.params.lazyLoadingOnTransitionStart&&x.lazy.load()}},x.scrollbar={isTouched:!1,setDragPosition:function(e){var a=x.scrollbar,t=(x.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY)-a.track.offset()[x.isHorizontal()?"left":"top"]-a.dragSize/2,s=-x.minTranslate()*a.moveDivider,i=-x.maxTranslate()*a.moveDivider;t<s?t=s:t>i&&(t=i),t=-t/a.moveDivider,x.updateProgress(t),x.setWrapperTranslate(t,!0)},dragStart:function(e){var a=x.scrollbar;a.isTouched=!0,e.preventDefault(),e.stopPropagation(),a.setDragPosition(e),clearTimeout(a.dragTimeout),a.track.transition(0),x.params.scrollbarHide&&a.track.css("opacity",1),x.wrapper.transition(100),a.drag.transition(100),x.emit("onScrollbarDragStart",x)},dragMove:function(e){var a=x.scrollbar;a.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,a.setDragPosition(e),x.wrapper.transition(0),a.track.transition(0),a.drag.transition(0),x.emit("onScrollbarDragMove",x))},dragEnd:function(e){var a=x.scrollbar;a.isTouched&&(a.isTouched=!1,x.params.scrollbarHide&&(clearTimeout(a.dragTimeout),a.dragTimeout=setTimeout(function(){a.track.css("opacity",0),a.track.transition(400)},1e3)),x.emit("onScrollbarDragEnd",x),x.params.scrollbarSnapOnRelease&&x.slideReset())},draggableEvents:!1!==x.params.simulateTouch||x.support.touch?x.touchEvents:x.touchEventsDesktop,enableDraggable:function(){var a=x.scrollbar,t=x.support.touch?a.track:document;e(a.track).on(a.draggableEvents.start,a.dragStart),e(t).on(a.draggableEvents.move,a.dragMove),e(t).on(a.draggableEvents.end,a.dragEnd)},disableDraggable:function(){var a=x.scrollbar,t=x.support.touch?a.track:document;e(a.track).off(a.draggableEvents.start,a.dragStart),e(t).off(a.draggableEvents.move,a.dragMove),e(t).off(a.draggableEvents.end,a.dragEnd)},set:function(){if(x.params.scrollbar){var a=x.scrollbar;a.track=e(x.params.scrollbar),x.params.uniqueNavElements&&"string"==typeof x.params.scrollbar&&a.track.length>1&&1===x.container.find(x.params.scrollbar).length&&(a.track=x.container.find(x.params.scrollbar)),a.drag=a.track.find(".swiper-scrollbar-drag"),0===a.drag.length&&(a.drag=e('<div class="swiper-scrollbar-drag"></div>'),a.track.append(a.drag)),a.drag[0].style.width="",a.drag[0].style.height="",a.trackSize=x.isHorizontal()?a.track[0].offsetWidth:a.track[0].offsetHeight,a.divider=x.size/x.virtualSize,a.moveDivider=a.divider*(a.trackSize/x.size),a.dragSize=a.trackSize*a.divider,x.isHorizontal()?a.drag[0].style.width=a.dragSize+"px":a.drag[0].style.height=a.dragSize+"px",a.divider>=1?a.track[0].style.display="none":a.track[0].style.display="",x.params.scrollbarHide&&(a.track[0].style.opacity=0)}},setTranslate:function(){if(x.params.scrollbar){var e,a=x.scrollbar,t=(x.translate,a.dragSize);e=(a.trackSize-a.dragSize)*x.progress,x.rtl&&x.isHorizontal()?(e=-e)>0?(t=a.dragSize-e,e=0):-e+a.dragSize>a.trackSize&&(t=a.trackSize+e):e<0?(t=a.dragSize+e,e=0):e+a.dragSize>a.trackSize&&(t=a.trackSize-e),x.isHorizontal()?(x.support.transforms3d?a.drag.transform("translate3d("+e+"px, 0, 0)"):a.drag.transform("translateX("+e+"px)"),a.drag[0].style.width=t+"px"):(x.support.transforms3d?a.drag.transform("translate3d(0px, "+e+"px, 0)"):a.drag.transform("translateY("+e+"px)"),a.drag[0].style.height=t+"px"),x.params.scrollbarHide&&(clearTimeout(a.timeout),a.track[0].style.opacity=1,a.timeout=setTimeout(function(){a.track[0].style.opacity=0,a.track.transition(400)},1e3))}},setTransition:function(e){x.params.scrollbar&&x.scrollbar.drag.transition(e)}},x.controller={LinearSpline:function(e,a){var t=function(){var e,a,t;return function(s,i){for(a=-1,e=s.length;e-a>1;)s[t=e+a>>1]<=i?a=t:e=t;return e}}();this.x=e,this.y=a,this.lastIndex=e.length-1;var s,i;this.x.length;this.interpolate=function(e){return e?(i=t(this.x,e),s=i-1,(e-this.x[s])*(this.y[i]-this.y[s])/(this.x[i]-this.x[s])+this.y[s]):0}},getInterpolateFunction:function(e){x.controller.spline||(x.controller.spline=x.params.loop?new x.controller.LinearSpline(x.slidesGrid,e.slidesGrid):new x.controller.LinearSpline(x.snapGrid,e.snapGrid))},setTranslate:function(e,t){function s(a){e=a.rtl&&"horizontal"===a.params.direction?-x.translate:x.translate,"slide"===x.params.controlBy&&(x.controller.getInterpolateFunction(a),r=-x.controller.spline.interpolate(-e)),r&&"container"!==x.params.controlBy||(i=(a.maxTranslate()-a.minTranslate())/(x.maxTranslate()-x.minTranslate()),r=(e-x.minTranslate())*i+a.minTranslate()),x.params.controlInverse&&(r=a.maxTranslate()-r),a.updateProgress(r),a.setWrapperTranslate(r,!1,x),a.updateActiveIndex()}var i,r,n=x.params.control;if(Array.isArray(n))for(var o=0;o<n.length;o++)n[o]!==t&&n[o]instanceof a&&s(n[o]);else n instanceof a&&t!==n&&s(n)},setTransition:function(e,t){function s(a){a.setWrapperTransition(e,x),0!==e&&(a.onTransitionStart(),a.wrapper.transitionEnd(function(){r&&(a.params.loop&&"slide"===x.params.controlBy&&a.fixLoop(),a.onTransitionEnd())}))}var i,r=x.params.control;if(Array.isArray(r))for(i=0;i<r.length;i++)r[i]!==t&&r[i]instanceof a&&s(r[i]);else r instanceof a&&t!==r&&s(r)}},x.hashnav={onHashCange:function(e,a){var t=document.location.hash.replace("#","");t!==x.slides.eq(x.activeIndex).attr("data-hash")&&x.slideTo(x.wrapper.children("."+x.params.slideClass+'[data-hash="'+t+'"]').index())},attachEvents:function(a){var t=a?"off":"on";e(window)[t]("hashchange",x.hashnav.onHashCange)},setHash:function(){if(x.hashnav.initialized&&x.params.hashnav)if(x.params.replaceState&&window.history&&window.history.replaceState)window.history.replaceState(null,null,"#"+x.slides.eq(x.activeIndex).attr("data-hash")||"");else{var e=x.slides.eq(x.activeIndex),a=e.attr("data-hash")||e.attr("data-history");document.location.hash=a||""}},init:function(){if(x.params.hashnav&&!x.params.history){x.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var a=0,t=x.slides.length;a<t;a++){var s=x.slides.eq(a);if((s.attr("data-hash")||s.attr("data-history"))===e&&!s.hasClass(x.params.slideDuplicateClass)){var i=s.index();x.slideTo(i,0,x.params.runCallbacksOnInit,!0)}}x.params.hashnavWatchState&&x.hashnav.attachEvents()}},destroy:function(){x.params.hashnavWatchState&&x.hashnav.attachEvents(!0)}},x.history={init:function(){if(x.params.history){if(!window.history||!window.history.pushState)return x.params.history=!1,void(x.params.hashnav=!0);x.history.initialized=!0,this.paths=this.getPathValues(),(this.paths.key||this.paths.value)&&(this.scrollToSlide(0,this.paths.value,x.params.runCallbacksOnInit),x.params.replaceState||window.addEventListener("popstate",this.setHistoryPopState))}},setHistoryPopState:function(){x.history.paths=x.history.getPathValues(),x.history.scrollToSlide(x.params.speed,x.history.paths.value,!1)},getPathValues:function(){var e=window.location.pathname.slice(1).split("/"),a=e.length;return{key:e[a-2],value:e[a-1]}},setHistory:function(e,a){if(x.history.initialized&&x.params.history){var t=x.slides.eq(a),s=this.slugify(t.attr("data-history"));window.location.pathname.includes(e)||(s=e+"/"+s),x.params.replaceState?window.history.replaceState(null,null,s):window.history.pushState(null,null,s)}},slugify:function(e){return e.toString().toLowerCase().replace(/\s+/g,"-").replace(/[^\w\-]+/g,"").replace(/\-\-+/g,"-").replace(/^-+/,"").replace(/-+$/,"")},scrollToSlide:function(e,a,t){if(a)for(var s=0,i=x.slides.length;s<i;s++){var r=x.slides.eq(s);if(this.slugify(r.attr("data-history"))===a&&!r.hasClass(x.params.slideDuplicateClass)){var n=r.index();x.slideTo(n,e,t)}}else x.slideTo(0,e,t)}},x.disableKeyboardControl=function(){x.params.keyboardControl=!1,e(document).off("keydown",p)},x.enableKeyboardControl=function(){x.params.keyboardControl=!0,e(document).on("keydown",p)},x.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},x.params.mousewheelControl&&(x.mousewheel.event=navigator.userAgent.indexOf("firefox")>-1?"DOMMouseScroll":function(){var e="onwheel"in document;if(!e){var a=document.createElement("div");a.setAttribute("onwheel","return;"),e="function"==typeof a.onwheel}return!e&&document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("","")&&(e=document.implementation.hasFeature("Events.wheel","3.0")),e}()?"wheel":"mousewheel"),x.disableMousewheelControl=function(){if(!x.mousewheel.event)return!1;var a=x.container;return"container"!==x.params.mousewheelEventsTarged&&(a=e(x.params.mousewheelEventsTarged)),a.off(x.mousewheel.event,d),x.params.mousewheelControl=!1,!0},x.enableMousewheelControl=function(){if(!x.mousewheel.event)return!1;var a=x.container;return"container"!==x.params.mousewheelEventsTarged&&(a=e(x.params.mousewheelEventsTarged)),a.on(x.mousewheel.event,d),x.params.mousewheelControl=!0,!0},x.parallax={setTranslate:function(){x.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){u(this,x.progress)}),x.slides.each(function(){var a=e(this);a.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){u(this,Math.min(Math.max(a[0].progress,-1),1))})})},setTransition:function(a){void 0===a&&(a=x.params.speed),x.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=e(this),s=parseInt(t.attr("data-swiper-parallax-duration"),10)||a;0===a&&(s=0),t.transition(s)})}},x.zoom={scale:1,currentScale:1,isScaling:!1,gesture:{slide:void 0,slideWidth:void 0,slideHeight:void 0,image:void 0,imageWrap:void 0,zoomMax:x.params.zoomMax},image:{isTouched:void 0,isMoved:void 0,currentX:void 0,currentY:void 0,minX:void 0,minY:void 0,maxX:void 0,maxY:void 0,width:void 0,height:void 0,startX:void 0,startY:void 0,touchesStart:{},touchesCurrent:{}},velocity:{x:void 0,y:void 0,prevPositionX:void 0,prevPositionY:void 0,prevTime:void 0},getDistanceBetweenTouches:function(e){if(e.targetTouches.length<2)return 1;var a=e.targetTouches[0].pageX,t=e.targetTouches[0].pageY,s=e.targetTouches[1].pageX,i=e.targetTouches[1].pageY;return Math.sqrt(Math.pow(s-a,2)+Math.pow(i-t,2))},onGestureStart:function(a){var t=x.zoom;if(!x.support.gestures){if("touchstart"!==a.type||"touchstart"===a.type&&a.targetTouches.length<2)return;t.gesture.scaleStart=t.getDistanceBetweenTouches(a)}t.gesture.slide&&t.gesture.slide.length||(t.gesture.slide=e(this),0===t.gesture.slide.length&&(t.gesture.slide=x.slides.eq(x.activeIndex)),t.gesture.image=t.gesture.slide.find("img, svg, canvas"),t.gesture.imageWrap=t.gesture.image.parent("."+x.params.zoomContainerClass),t.gesture.zoomMax=t.gesture.imageWrap.attr("data-swiper-zoom")||x.params.zoomMax,0!==t.gesture.imageWrap.length)?(t.gesture.image.transition(0),t.isScaling=!0):t.gesture.image=void 0},onGestureChange:function(e){var a=x.zoom;if(!x.support.gestures){if("touchmove"!==e.type||"touchmove"===e.type&&e.targetTouches.length<2)return;a.gesture.scaleMove=a.getDistanceBetweenTouches(e)}a.gesture.image&&0!==a.gesture.image.length&&(x.support.gestures?a.scale=e.scale*a.currentScale:a.scale=a.gesture.scaleMove/a.gesture.scaleStart*a.currentScale,a.scale>a.gesture.zoomMax&&(a.scale=a.gesture.zoomMax-1+Math.pow(a.scale-a.gesture.zoomMax+1,.5)),a.scale<x.params.zoomMin&&(a.scale=x.params.zoomMin+1-Math.pow(x.params.zoomMin-a.scale+1,.5)),a.gesture.image.transform("translate3d(0,0,0) scale("+a.scale+")"))},onGestureEnd:function(e){var a=x.zoom;!x.support.gestures&&("touchend"!==e.type||"touchend"===e.type&&e.changedTouches.length<2)||a.gesture.image&&0!==a.gesture.image.length&&(a.scale=Math.max(Math.min(a.scale,a.gesture.zoomMax),x.params.zoomMin),a.gesture.image.transition(x.params.speed).transform("translate3d(0,0,0) scale("+a.scale+")"),a.currentScale=a.scale,a.isScaling=!1,1===a.scale&&(a.gesture.slide=void 0))},onTouchStart:function(e,a){var t=e.zoom;t.gesture.image&&0!==t.gesture.image.length&&(t.image.isTouched||("android"===e.device.os&&a.preventDefault(),t.image.isTouched=!0,t.image.touchesStart.x="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,t.image.touchesStart.y="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY))},onTouchMove:function(e){var a=x.zoom;if(a.gesture.image&&0!==a.gesture.image.length&&(x.allowClick=!1,a.image.isTouched&&a.gesture.slide)){a.image.isMoved||(a.image.width=a.gesture.image[0].offsetWidth,a.image.height=a.gesture.image[0].offsetHeight,a.image.startX=x.getTranslate(a.gesture.imageWrap[0],"x")||0,a.image.startY=x.getTranslate(a.gesture.imageWrap[0],"y")||0,a.gesture.slideWidth=a.gesture.slide[0].offsetWidth,a.gesture.slideHeight=a.gesture.slide[0].offsetHeight,a.gesture.imageWrap.transition(0),x.rtl&&(a.image.startX=-a.image.startX),x.rtl&&(a.image.startY=-a.image.startY));var t=a.image.width*a.scale,s=a.image.height*a.scale;if(!(t<a.gesture.slideWidth&&s<a.gesture.slideHeight)){if(a.image.minX=Math.min(a.gesture.slideWidth/2-t/2,0),a.image.maxX=-a.image.minX,a.image.minY=Math.min(a.gesture.slideHeight/2-s/2,0),a.image.maxY=-a.image.minY,a.image.touchesCurrent.x="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,a.image.touchesCurrent.y="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,!a.image.isMoved&&!a.isScaling){if(x.isHorizontal()&&Math.floor(a.image.minX)===Math.floor(a.image.startX)&&a.image.touchesCurrent.x<a.image.touchesStart.x||Math.floor(a.image.maxX)===Math.floor(a.image.startX)&&a.image.touchesCurrent.x>a.image.touchesStart.x)return void(a.image.isTouched=!1);if(!x.isHorizontal()&&Math.floor(a.image.minY)===Math.floor(a.image.startY)&&a.image.touchesCurrent.y<a.image.touchesStart.y||Math.floor(a.image.maxY)===Math.floor(a.image.startY)&&a.image.touchesCurrent.y>a.image.touchesStart.y)return void(a.image.isTouched=!1)}e.preventDefault(),e.stopPropagation(),a.image.isMoved=!0,a.image.currentX=a.image.touchesCurrent.x-a.image.touchesStart.x+a.image.startX,a.image.currentY=a.image.touchesCurrent.y-a.image.touchesStart.y+a.image.startY,a.image.currentX<a.image.minX&&(a.image.currentX=a.image.minX+1-Math.pow(a.image.minX-a.image.currentX+1,.8)),a.image.currentX>a.image.maxX&&(a.image.currentX=a.image.maxX-1+Math.pow(a.image.currentX-a.image.maxX+1,.8)),a.image.currentY<a.image.minY&&(a.image.currentY=a.image.minY+1-Math.pow(a.image.minY-a.image.currentY+1,.8)),a.image.currentY>a.image.maxY&&(a.image.currentY=a.image.maxY-1+Math.pow(a.image.currentY-a.image.maxY+1,.8)),a.velocity.prevPositionX||(a.velocity.prevPositionX=a.image.touchesCurrent.x),a.velocity.prevPositionY||(a.velocity.prevPositionY=a.image.touchesCurrent.y),a.velocity.prevTime||(a.velocity.prevTime=Date.now()),a.velocity.x=(a.image.touchesCurrent.x-a.velocity.prevPositionX)/(Date.now()-a.velocity.prevTime)/2,a.velocity.y=(a.image.touchesCurrent.y-a.velocity.prevPositionY)/(Date.now()-a.velocity.prevTime)/2,Math.abs(a.image.touchesCurrent.x-a.velocity.prevPositionX)<2&&(a.velocity.x=0),Math.abs(a.image.touchesCurrent.y-a.velocity.prevPositionY)<2&&(a.velocity.y=0),a.velocity.prevPositionX=a.image.touchesCurrent.x,a.velocity.prevPositionY=a.image.touchesCurrent.y,a.velocity.prevTime=Date.now(),a.gesture.imageWrap.transform("translate3d("+a.image.currentX+"px, "+a.image.currentY+"px,0)")}}},onTouchEnd:function(e,a){var t=e.zoom;if(t.gesture.image&&0!==t.gesture.image.length){if(!t.image.isTouched||!t.image.isMoved)return t.image.isTouched=!1,void(t.image.isMoved=!1);t.image.isTouched=!1,t.image.isMoved=!1;var s=300,i=300,r=t.velocity.x*s,n=t.image.currentX+r,o=t.velocity.y*i,l=t.image.currentY+o;0!==t.velocity.x&&(s=Math.abs((n-t.image.currentX)/t.velocity.x)),0!==t.velocity.y&&(i=Math.abs((l-t.image.currentY)/t.velocity.y));var p=Math.max(s,i);t.image.currentX=n,t.image.currentY=l;var d=t.image.width*t.scale,u=t.image.height*t.scale;t.image.minX=Math.min(t.gesture.slideWidth/2-d/2,0),t.image.maxX=-t.image.minX,t.image.minY=Math.min(t.gesture.slideHeight/2-u/2,0),t.image.maxY=-t.image.minY,t.image.currentX=Math.max(Math.min(t.image.currentX,t.image.maxX),t.image.minX),t.image.currentY=Math.max(Math.min(t.image.currentY,t.image.maxY),t.image.minY),t.gesture.imageWrap.transition(p).transform("translate3d("+t.image.currentX+"px, "+t.image.currentY+"px,0)")}},onTransitionEnd:function(e){var a=e.zoom;a.gesture.slide&&e.previousIndex!==e.activeIndex&&(a.gesture.image.transform("translate3d(0,0,0) scale(1)"),a.gesture.imageWrap.transform("translate3d(0,0,0)"),a.gesture.slide=a.gesture.image=a.gesture.imageWrap=void 0,a.scale=a.currentScale=1)},toggleZoom:function(a,t){var s=a.zoom;if(s.gesture.slide||(s.gesture.slide=a.clickedSlide?e(a.clickedSlide):a.slides.eq(a.activeIndex),s.gesture.image=s.gesture.slide.find("img, svg, canvas"),s.gesture.imageWrap=s.gesture.image.parent("."+a.params.zoomContainerClass)),s.gesture.image&&0!==s.gesture.image.length){var i,r,n,o,l,p,d,u,c,m,h,g,f,v,w,y;void 0===s.image.touchesStart.x&&t?(i="touchend"===t.type?t.changedTouches[0].pageX:t.pageX,r="touchend"===t.type?t.changedTouches[0].pageY:t.pageY):(i=s.image.touchesStart.x,r=s.image.touchesStart.y),s.scale&&1!==s.scale?(s.scale=s.currentScale=1,s.gesture.imageWrap.transition(300).transform("translate3d(0,0,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale(1)"),s.gesture.slide=void 0):(s.scale=s.currentScale=s.gesture.imageWrap.attr("data-swiper-zoom")||a.params.zoomMax,t?(w=s.gesture.slide[0].offsetWidth,y=s.gesture.slide[0].offsetHeight,n=s.gesture.slide.offset().left+w/2-i,o=s.gesture.slide.offset().top+y/2-r,d=s.gesture.image[0].offsetWidth,u=s.gesture.image[0].offsetHeight,c=d*s.scale,m=u*s.scale,f=-(h=Math.min(w/2-c/2,0)),v=-(g=Math.min(y/2-m/2,0)),l=n*s.scale,p=o*s.scale,l<h&&(l=h),l>f&&(l=f),p<g&&(p=g),p>v&&(p=v)):(l=0,p=0),s.gesture.imageWrap.transition(300).transform("translate3d("+l+"px, "+p+"px,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale("+s.scale+")"))}},attachEvents:function(a){var t=a?"off":"on";if(x.params.zoom){x.slides;var s=!("touchstart"!==x.touchEvents.start||!x.support.passiveListener||!x.params.passiveListeners)&&{passive:!0,capture:!1};x.support.gestures?(x.slides[t]("gesturestart",x.zoom.onGestureStart,s),x.slides[t]("gesturechange",x.zoom.onGestureChange,s),x.slides[t]("gestureend",x.zoom.onGestureEnd,s)):"touchstart"===x.touchEvents.start&&(x.slides[t](x.touchEvents.start,x.zoom.onGestureStart,s),x.slides[t](x.touchEvents.move,x.zoom.onGestureChange,s),x.slides[t](x.touchEvents.end,x.zoom.onGestureEnd,s)),x[t]("touchStart",x.zoom.onTouchStart),x.slides.each(function(a,s){e(s).find("."+x.params.zoomContainerClass).length>0&&e(s)[t](x.touchEvents.move,x.zoom.onTouchMove)}),x[t]("touchEnd",x.zoom.onTouchEnd),x[t]("transitionEnd",x.zoom.onTransitionEnd),x.params.zoomToggle&&x.on("doubleTap",x.zoom.toggleZoom)}},init:function(){x.zoom.attachEvents()},destroy:function(){x.zoom.attachEvents(!0)}},x._plugins=[];for(var A in x.plugins){var Y=x.plugins[A](x,x.params[A]);Y&&x._plugins.push(Y)}return x.callPlugins=function(e){for(var a=0;a<x._plugins.length;a++)e in x._plugins[a]&&x._plugins[a][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},x.emitterEventListeners={},x.emit=function(e){x.params[e]&&x.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var a;if(x.emitterEventListeners[e])for(a=0;a<x.emitterEventListeners[e].length;a++)x.emitterEventListeners[e][a](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);x.callPlugins&&x.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},x.on=function(e,a){return e=c(e),x.emitterEventListeners[e]||(x.emitterEventListeners[e]=[]),x.emitterEventListeners[e].push(a),x},x.off=function(e,a){var t;if(e=c(e),void 0===a)return x.emitterEventListeners[e]=[],x;if(x.emitterEventListeners[e]&&0!==x.emitterEventListeners[e].length){for(t=0;t<x.emitterEventListeners[e].length;t++)x.emitterEventListeners[e][t]===a&&x.emitterEventListeners[e].splice(t,1);return x}},x.once=function(e,a){e=c(e);var t=function(){a(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),x.off(e,t)};return x.on(e,t),x},x.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,a){return e.attr("role",a),e},addLabel:function(e,a){return e.attr("aria-label",a),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(a){13===a.keyCode&&(e(a.target).is(x.params.nextButton)?(x.onClickNext(a),x.isEnd?x.a11y.notify(x.params.lastSlideMessage):x.a11y.notify(x.params.nextSlideMessage)):e(a.target).is(x.params.prevButton)&&(x.onClickPrev(a),x.isBeginning?x.a11y.notify(x.params.firstSlideMessage):x.a11y.notify(x.params.prevSlideMessage)),e(a.target).is("."+x.params.bulletClass)&&e(a.target)[0].click())},liveRegion:e('<span class="'+x.params.notificationClass+'" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var a=x.a11y.liveRegion;0!==a.length&&(a.html(""),a.html(e))},init:function(){x.params.nextButton&&x.nextButton&&x.nextButton.length>0&&(x.a11y.makeFocusable(x.nextButton),x.a11y.addRole(x.nextButton,"button"),x.a11y.addLabel(x.nextButton,x.params.nextSlideMessage)),x.params.prevButton&&x.prevButton&&x.prevButton.length>0&&(x.a11y.makeFocusable(x.prevButton),x.a11y.addRole(x.prevButton,"button"),x.a11y.addLabel(x.prevButton,x.params.prevSlideMessage)),e(x.container).append(x.a11y.liveRegion)},initPagination:function(){x.params.pagination&&x.params.paginationClickable&&x.bullets&&x.bullets.length&&x.bullets.each(function(){var a=e(this);x.a11y.makeFocusable(a),x.a11y.addRole(a,"button"),x.a11y.addLabel(a,x.params.paginationBulletMessage.replace(/{{index}}/,a.index()+1))})},destroy:function(){x.a11y.liveRegion&&x.a11y.liveRegion.length>0&&x.a11y.liveRegion.remove()}},x.init=function(){x.params.loop&&x.createLoop(),x.updateContainerSize(),x.updateSlidesSize(),x.updatePagination(),x.params.scrollbar&&x.scrollbar&&(x.scrollbar.set(),x.params.scrollbarDraggable&&x.scrollbar.enableDraggable()),"slide"!==x.params.effect&&x.effects[x.params.effect]&&(x.params.loop||x.updateProgress(),x.effects[x.params.effect].setTranslate()),x.params.loop?x.slideTo(x.params.initialSlide+x.loopedSlides,0,x.params.runCallbacksOnInit):(x.slideTo(x.params.initialSlide,0,x.params.runCallbacksOnInit),0===x.params.initialSlide&&(x.parallax&&x.params.parallax&&x.parallax.setTranslate(),x.lazy&&x.params.lazyLoading&&(x.lazy.load(),x.lazy.initialImageLoaded=!0))),x.attachEvents(),x.params.observer&&x.support.observer&&x.initObservers(),x.params.preloadImages&&!x.params.lazyLoading&&x.preloadImages(),x.params.zoom&&x.zoom&&x.zoom.init(),x.params.autoplay&&x.startAutoplay(),x.params.keyboardControl&&x.enableKeyboardControl&&x.enableKeyboardControl(),x.params.mousewheelControl&&x.enableMousewheelControl&&x.enableMousewheelControl(),x.params.hashnavReplaceState&&(x.params.replaceState=x.params.hashnavReplaceState),x.params.history&&x.history&&x.history.init(),x.params.hashnav&&x.hashnav&&x.hashnav.init(),x.params.a11y&&x.a11y&&x.a11y.init(),x.emit("onInit",x)},x.cleanupStyles=function(){x.container.removeClass(x.classNames.join(" ")).removeAttr("style"),x.wrapper.removeAttr("style"),x.slides&&x.slides.length&&x.slides.removeClass([x.params.slideVisibleClass,x.params.slideActiveClass,x.params.slideNextClass,x.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),x.paginationContainer&&x.paginationContainer.length&&x.paginationContainer.removeClass(x.params.paginationHiddenClass),x.bullets&&x.bullets.length&&x.bullets.removeClass(x.params.bulletActiveClass),x.params.prevButton&&e(x.params.prevButton).removeClass(x.params.buttonDisabledClass),x.params.nextButton&&e(x.params.nextButton).removeClass(x.params.buttonDisabledClass),x.params.scrollbar&&x.scrollbar&&(x.scrollbar.track&&x.scrollbar.track.length&&x.scrollbar.track.removeAttr("style"),x.scrollbar.drag&&x.scrollbar.drag.length&&x.scrollbar.drag.removeAttr("style"))},x.destroy=function(e,a){x.detachEvents(),x.stopAutoplay(),x.params.scrollbar&&x.scrollbar&&x.params.scrollbarDraggable&&x.scrollbar.disableDraggable(),x.params.loop&&x.destroyLoop(),a&&x.cleanupStyles(),x.disconnectObservers(),x.params.zoom&&x.zoom&&x.zoom.destroy(),x.params.keyboardControl&&x.disableKeyboardControl&&x.disableKeyboardControl(),x.params.mousewheelControl&&x.disableMousewheelControl&&x.disableMousewheelControl(),x.params.a11y&&x.a11y&&x.a11y.destroy(),x.params.history&&!x.params.replaceState&&window.removeEventListener("popstate",x.history.setHistoryPopState),x.params.hashnav&&x.hashnav&&x.hashnav.destroy(),x.emit("onDestroy"),!1!==e&&(x=null)},x.init(),x}};a.prototype={isSafari:function(){var e=window.navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1,lteIE9:function(){var e=document.createElement("div");return e.innerHTML="\x3c!--[if lte IE 9]><i></i><![endif]--\x3e",1===e.getElementsByTagName("i").length}()},device:function(){var e=window.navigator.userAgent,a=e.match(/(Android);?[\s\/]+([\d.]+)?/),t=e.match(/(iPad).*OS\s([\d_]+)/),s=e.match(/(iPod)(.*OS\s([\d_]+))?/),i=!t&&e.match(/(iPhone\sOS|iOS)\s([\d_]+)/);return{ios:t||i||s,android:a}}(),support:{touch:window.Modernizr&&!0===Modernizr.touch||!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch),transforms3d:window.Modernizr&&!0===Modernizr.csstransforms3d||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,a="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),t=0;t<a.length;t++)if(a[t]in e)return!0}(),observer:"MutationObserver"in window||"WebkitMutationObserver"in window,passiveListener:function(){var e=!1;try{var a=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("testPassiveListener",null,a)}catch(e){}return e}(),gestures:"ongesturestart"in window},plugins:{}};for(var t=function(){var e=function(e){var a=0;for(a=0;a<e.length;a++)this[a]=e[a];return this.length=e.length,this},a=function(a,t){var s=[],i=0;if(a&&!t&&a instanceof e)return a;if(a)if("string"==typeof a){var r,n,o=a.trim();if(o.indexOf("<")>=0&&o.indexOf(">")>=0){var l="div";for(0===o.indexOf("<li")&&(l="ul"),0===o.indexOf("<tr")&&(l="tbody"),0!==o.indexOf("<td")&&0!==o.indexOf("<th")||(l="tr"),0===o.indexOf("<tbody")&&(l="table"),0===o.indexOf("<option")&&(l="select"),(n=document.createElement(l)).innerHTML=a,i=0;i<n.childNodes.length;i++)s.push(n.childNodes[i])}else for(r=t||"#"!==a[0]||a.match(/[ .<>:~]/)?(t||document).querySelectorAll(a):[document.getElementById(a.split("#")[1])],i=0;i<r.length;i++)r[i]&&s.push(r[i])}else if(a.nodeType||a===window||a===document)s.push(a);else if(a.length>0&&a[0].nodeType)for(i=0;i<a.length;i++)s.push(a[i]);return new e(s)};return e.prototype={addClass:function(e){if(void 0===e)return this;for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.add(a[t]);return this},removeClass:function(e){for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.remove(a[t]);return this},hasClass:function(e){return!!this[0]&&this[0].classList.contains(e)},toggleClass:function(e){for(var a=e.split(" "),t=0;t<a.length;t++)for(var s=0;s<this.length;s++)this[s].classList.toggle(a[t]);return this},attr:function(e,a){if(1===arguments.length&&"string"==typeof e)return this[0]?this[0].getAttribute(e):void 0;for(var t=0;t<this.length;t++)if(2===arguments.length)this[t].setAttribute(e,a);else for(var s in e)this[t][s]=e[s],this[t].setAttribute(s,e[s]);return this},removeAttr:function(e){for(var a=0;a<this.length;a++)this[a].removeAttribute(e);return this},data:function(e,a){if(void 0!==a){for(var t=0;t<this.length;t++){var s=this[t];s.dom7ElementDataStorage||(s.dom7ElementDataStorage={}),s.dom7ElementDataStorage[e]=a}return this}if(this[0]){var i=this[0].getAttribute("data-"+e);return i||(this[0].dom7ElementDataStorage&&e in this[0].dom7ElementDataStorage?this[0].dom7ElementDataStorage[e]:void 0)}},transform:function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this},transition:function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this},on:function(e,t,s,i){function r(e){var i=e.target;if(a(i).is(t))s.call(i,e);else for(var r=a(i).parents(),n=0;n<r.length;n++)a(r[n]).is(t)&&s.call(r[n],e)}var n,o,l=e.split(" ");for(n=0;n<this.length;n++)if("function"==typeof t||!1===t)for("function"==typeof t&&(s=arguments[1],i=arguments[2]||!1),o=0;o<l.length;o++)this[n].addEventListener(l[o],s,i);else for(o=0;o<l.length;o++)this[n].dom7LiveListeners||(this[n].dom7LiveListeners=[]),this[n].dom7LiveListeners.push({listener:s,liveListener:r}),this[n].addEventListener(l[o],r,i);return this},off:function(e,a,t,s){for(var i=e.split(" "),r=0;r<i.length;r++)for(var n=0;n<this.length;n++)if("function"==typeof a||!1===a)"function"==typeof a&&(t=arguments[1],s=arguments[2]||!1),this[n].removeEventListener(i[r],t,s);else if(this[n].dom7LiveListeners)for(var o=0;o<this[n].dom7LiveListeners.length;o++)this[n].dom7LiveListeners[o].listener===t&&this[n].removeEventListener(i[r],this[n].dom7LiveListeners[o].liveListener,s);return this},once:function(e,a,t,s){function i(n){t(n),r.off(e,a,i,s)}var r=this;"function"==typeof a&&(a=!1,t=arguments[1],s=arguments[2]),r.on(e,a,i,s)},trigger:function(e,a){for(var t=0;t<this.length;t++){var s;try{s=new window.CustomEvent(e,{detail:a,bubbles:!0,cancelable:!0})}catch(t){(s=document.createEvent("Event")).initEvent(e,!0,!0),s.detail=a}this[t].dispatchEvent(s)}return this},transitionEnd:function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<s.length;t++)i.off(s[t],a)}var t,s=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=this;if(e)for(t=0;t<s.length;t++)i.on(s[t],a);return this},width:function(){return this[0]===window?window.innerWidth:this.length>0?parseFloat(this.css("width")):null},outerWidth:function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?parseFloat(this.css("height")):null},outerHeight:function(e){return this.length>0?e?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var e=this[0],a=e.getBoundingClientRect(),t=document.body,s=e.clientTop||t.clientTop||0,i=e.clientLeft||t.clientLeft||0,r=window.pageYOffset||e.scrollTop,n=window.pageXOffset||e.scrollLeft;return{top:a.top+r-s,left:a.left+n-i}}return null},css:function(e,a){var t;if(1===arguments.length){if("string"!=typeof e){for(t=0;t<this.length;t++)for(var s in e)this[t].style[s]=e[s];return this}if(this[0])return window.getComputedStyle(this[0],null).getPropertyValue(e)}if(2===arguments.length&&"string"==typeof e){for(t=0;t<this.length;t++)this[t].style[e]=a;return this}return this},each:function(e){for(var a=0;a<this.length;a++)e.call(this[a],a,this[a]);return this},html:function(e){if(void 0===e)return this[0]?this[0].innerHTML:void 0;for(var a=0;a<this.length;a++)this[a].innerHTML=e;return this},text:function(e){if(void 0===e)return this[0]?this[0].textContent.trim():null;for(var a=0;a<this.length;a++)this[a].textContent=e;return this},is:function(t){if(!this[0])return!1;var s,i;if("string"==typeof t){var r=this[0];if(r===document)return t===document;if(r===window)return t===window;if(r.matches)return r.matches(t);if(r.webkitMatchesSelector)return r.webkitMatchesSelector(t);if(r.mozMatchesSelector)return r.mozMatchesSelector(t);if(r.msMatchesSelector)return r.msMatchesSelector(t);for(s=a(t),i=0;i<s.length;i++)if(s[i]===this[0])return!0;return!1}if(t===document)return this[0]===document;if(t===window)return this[0]===window;if(t.nodeType||t instanceof e){for(s=t.nodeType?[t]:t,i=0;i<s.length;i++)if(s[i]===this[0])return!0;return!1}return!1},index:function(){if(this[0]){for(var e=this[0],a=0;null!==(e=e.previousSibling);)1===e.nodeType&&a++;return a}},eq:function(a){if(void 0===a)return this;var t,s=this.length;return a>s-1?new e([]):a<0?(t=s+a,new e(t<0?[]:[this[t]])):new e([this[a]])},append:function(a){var t,s;for(t=0;t<this.length;t++)if("string"==typeof a){var i=document.createElement("div");for(i.innerHTML=a;i.firstChild;)this[t].appendChild(i.firstChild)}else if(a instanceof e)for(s=0;s<a.length;s++)this[t].appendChild(a[s]);else this[t].appendChild(a);return this},prepend:function(a){var t,s;for(t=0;t<this.length;t++)if("string"==typeof a){var i=document.createElement("div");for(i.innerHTML=a,s=i.childNodes.length-1;s>=0;s--)this[t].insertBefore(i.childNodes[s],this[t].childNodes[0])}else if(a instanceof e)for(s=0;s<a.length;s++)this[t].insertBefore(a[s],this[t].childNodes[0]);else this[t].insertBefore(a,this[t].childNodes[0]);return this},insertBefore:function(e){for(var t=a(e),s=0;s<this.length;s++)if(1===t.length)t[0].parentNode.insertBefore(this[s],t[0]);else if(t.length>1)for(var i=0;i<t.length;i++)t[i].parentNode.insertBefore(this[s].cloneNode(!0),t[i])},insertAfter:function(e){for(var t=a(e),s=0;s<this.length;s++)if(1===t.length)t[0].parentNode.insertBefore(this[s],t[0].nextSibling);else if(t.length>1)for(var i=0;i<t.length;i++)t[i].parentNode.insertBefore(this[s].cloneNode(!0),t[i].nextSibling)},next:function(t){return new e(this.length>0?t?this[0].nextElementSibling&&a(this[0].nextElementSibling).is(t)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.nextElementSibling;){var r=i.nextElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},prev:function(t){return new e(this.length>0?t?this[0].previousElementSibling&&a(this[0].previousElementSibling).is(t)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.previousElementSibling;){var r=i.previousElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},parent:function(e){for(var t=[],s=0;s<this.length;s++)e?a(this[s].parentNode).is(e)&&t.push(this[s].parentNode):t.push(this[s].parentNode);return a(a.unique(t))},parents:function(e){for(var t=[],s=0;s<this.length;s++)for(var i=this[s].parentNode;i;)e?a(i).is(e)&&t.push(i):t.push(i),i=i.parentNode;return a(a.unique(t))},find:function(a){for(var t=[],s=0;s<this.length;s++)for(var i=this[s].querySelectorAll(a),r=0;r<i.length;r++)t.push(i[r]);return new e(t)},children:function(t){for(var s=[],i=0;i<this.length;i++)for(var r=this[i].childNodes,n=0;n<r.length;n++)t?1===r[n].nodeType&&a(r[n]).is(t)&&s.push(r[n]):1===r[n].nodeType&&s.push(r[n]);return new e(a.unique(s))},remove:function(){for(var e=0;e<this.length;e++)this[e].parentNode&&this[e].parentNode.removeChild(this[e]);return this},add:function(){var e,t;for(e=0;e<arguments.length;e++){var s=a(arguments[e]);for(t=0;t<s.length;t++)this[this.length]=s[t],this.length++}return this}},a.fn=e.prototype,a.unique=function(e){for(var a=[],t=0;t<e.length;t++)-1===a.indexOf(e[t])&&a.push(e[t]);return a},a}(),s=["jQuery","Zepto","Dom7"],i=0;i<s.length;i++)window[s[i]]&&function(e){e.fn.swiper=function(t){var s;return e(this).each(function(){var e=new a(this,t);s||(s=e)}),s}}(window[s[i]]);var r;(r=void 0===t?window.Dom7||window.Zepto||window.jQuery:t)&&("transitionEnd"in r.fn||(r.fn.transitionEnd=function(e){function a(r){if(r.target===this)for(e.call(this,r),t=0;t<s.length;t++)i.off(s[t],a)}var t,s=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],i=this;if(e)for(t=0;t<s.length;t++)i.on(s[t],a);return this}),"transform"in r.fn||(r.fn.transform=function(e){for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransform=t.MsTransform=t.msTransform=t.MozTransform=t.OTransform=t.transform=e}return this}),"transition"in r.fn||(r.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var a=0;a<this.length;a++){var t=this[a].style;t.webkitTransitionDuration=t.MsTransitionDuration=t.msTransitionDuration=t.MozTransitionDuration=t.OTransitionDuration=t.transitionDuration=e}return this}),"outerWidth"in r.fn||(r.fn.outerWidth=function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null})),window.Swiper=a}(),"undefined"!=typeof module?module.exports=window.Swiper:"function"==typeof define&&define.amd&&define([],function(){"use strict";return window.Swiper});
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/tab.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/tab.min.js
new file mode 100755
index 0000000..94476aa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/tab.min.js
@@ -0,0 +1 @@
+window.openTab=function(e){for(var t=event.target;!t.parentNode.classList.contains("tab");){if("BODY"==t.nodeName)return console.error("The component tab not found, please check your code."),!1;t=t.parentNode}for(var a=document.getElementById(e).parentNode.getElementsByClassName("tab-content"),s=t.parentNode.getElementsByClassName("active"),n=0;n<a.length;n++)a[n].setAttribute("class",a[n].getAttribute("class").replace("active",""));for(n=0;n<s.length;n++)s[n].setAttribute("class",s[n].getAttribute("class").replace("active",""));t.setAttribute("class",t.getAttribute("class")+" active"),document.getElementById(e).setAttribute("class",document.getElementById(e).getAttribute("class")+" active")};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/toast.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/toast.min.js
new file mode 100755
index 0000000..75db5f7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/js/toast.min.js
@@ -0,0 +1 @@
+window.openToast=function(e){var t={class:"black radius padding shadow",duration:2e3,position:"bottom",onclick:window.closeToast};"string"==typeof e&&(t.message=e),"object"==typeof e&&e.message&&(t.message=e.message),"object"==typeof e&&e.class&&(t.class=e.class),"object"==typeof e&&e.duration&&(t.duration=e.duration),"object"==typeof e&&e.position&&(t.position="toast-"+e.position),"object"==typeof e&&e.onclick&&(t.onclick=e.onclick);var o=document.getElementsByTagName("body")[0];event&&event.target&&event.target.parentNode&&event.target.parentNode.className.indexOf("body")>=0&&(o=event.target.parentNode);var a=document.createElement("div");a.className="toast",a.classList.add(t.position);var n=document.createElement("div");n.className=t.class,n.innerHTML=t.message,n.onclick=t.onclick,a.appendChild(n),o.appendChild(a),setTimeout(function(){a.classList.add("show")},100),setTimeout(function(){if(!a)return!1;a.classList.remove("show"),setTimeout(function(){if(!a.parentNode)return!1;a.parentNode.removeChild(a)},400)},t.duration)},window.closeToast=function(e){e.target.parentNode.classList.remove("show"),setTimeout(function(){e.target.parentNode.parentNode.removeChild(e.target.parentNode)},400)};
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/mobileui.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/mobileui.js
new file mode 100644
index 0000000..4675be7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/mobileui.js
@@ -0,0 +1,3 @@
+/*component-base*/var userAgent=navigator.userAgent||navigator.vendor||window.opera,SO={name:"unknown",code:0};/android/i.test(userAgent)&&(SO.name="Android",SO.class="platform-android",SO.code=1);/iPad|iPhone|iPod/.test(userAgent)&&!window.MSStream&&(SO.name="iOS",SO.class="platform-ios",SO.code=2);/windows phone/i.test(userAgent)&&(SO.name="Windows Phone",SO.class="platform-wp",SO.code=3);SO.class&&document.getElementsByTagName("body").length&&(document.getElementsByTagName("body")[0].className+=" "+SO.class);
+
+/*component-button*/document.addEventListener("click",function(e){if(1!==SO.code)return!1;var t=e.target;if("button"!==t.tagName.toLowerCase())return!1;var o=t.getBoundingClientRect(),s=t.querySelector(".ripple");s||((s=document.createElement("span")).className="ripple",s.style.height=s.style.width=Math.max(o.width,o.height)+"px",t.appendChild(s)),s.classList.remove("show");var a=e.pageY-o.top-s.offsetHeight/2-document.body.scrollTop,l=e.pageX-o.left-s.offsetWidth/2-document.body.scrollLeft;return s.style.top=a+"px",s.style.left=l+"px",s.classList.add("show"),!1},!1);
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/style.css b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/style.css
new file mode 100644
index 0000000..d0433d2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/mobileui/style.css
@@ -0,0 +1,34 @@
+.component-base{display:block}*{-webkit-tap-highlight-color:transparent;margin:0;padding:0;box-sizing:border-box;outline:0}body{-webkit-touch-callout:none;-webkit-text-size-adjust:none;-webkit-user-select:none;background-color:#fff;font-size:14px;height:100%;margin:0;padding:0;width:100%}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}*{box-sizing:border-box;outline:0}body{font-family:Roboto,"Helvetica Neue",sans-serif;-webkit-overflow-scrolling:touch;overflow:hidden;position:absolute}body.platform-ios{font-family:-apple-system,"Helvetica Neue",Roboto,sans-serif}a{cursor:pointer;color:#000;text-decoration:none}.content{position:absolute;width:100%;overflow:auto}.left{float:left}.right{float:right}.top{position:absolute;top:0;left:0}.bottom{position:absolute;bottom:0;left:0}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.border{border-width:1px;border-style:solid}.hidden{display:none}.opacity-90{opacity:.9}.opacity-80{opacity:.8}.opacity-70{opacity:.7}.opacity-60{opacity:.6}.opacity-50{opacity:.5}.opacity-40{opacity:.4}.opacity-30{opacity:.3}.opacity-20{opacity:.2}.opacity-10{opacity:.1}.line{width:100%;height:1px;display:block;clear:both}.icon{font-size:28px}img,video{max-width:100%}p{margin-top:5px;margin-bottom:5px}.padding{padding:10px}.padding-top{padding-top:10px}.margin{margin:10px}span.padding{padding:6px;padding-top:2px;padding-bottom:2px}.radius{border-radius:4px}.radius-big{border-radius:22px}.circle{border-radius:50%}.radius-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.radius-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.radius-top{border-top-left-radius:4px;border-top-right-radius:4px}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shadow{box-shadow:1px 1px 3px rgba(0,0,0,.2)}.space{width:100%;height:20px}.space-big{width:100%;height:50px}.space-huge{width:100%;height:100px}.margin-bottom{margin-bottom:10px}.margin-top{margin-top:10px}.text-shadow{text-shadow:1px 1px 3px rgba(0,0,0,.2)}.text-small{font-size:14px}.text-small .icon,.text-small.icon{font-size:14px!important}.icon-small{font-size:14px!important}.icon-big{font-size:50px!important}.icon-huge{font-size:65px!important}.icon-extra-huge{font-size:120px!important}.text-big{font-size:22px}.text-big .icon,.text-big.icon{font-size:22px!important}.text-extra-huge{font-size:65px}.text-extra-huge .icon,.text-extra-huge.icon{font-size:65px!important}.text-huge{font-size:32px}.text-huge .icon,.text-huge.icon{font-size:32px!important}.text-light{font-weight:300}.text-bold{font-weight:700}.text-strong{font-weight:800}.float-bottom-right{position:fixed;right:15px;bottom:15px}.float-bottom-left{position:fixed;left:15px;bottom:15px}.float-bottom-center{position:fixed;margin:auto;left:0;bottom:15px}.icon-circle{width:40px;height:40px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small{width:25px;height:25px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-small i{font-size:15px}.icon-circle-big{width:80px;height:80px;border-radius:50%;text-align:center;display:flex;align-items:center;justify-content:center}.icon-circle-big i{font-size:70px}.backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.01;z-index:9999;transition-duration:280ms}.backdrop.show{opacity:0.3}.mark{border-left-width:8px!important}.red{color:rgba(255,255,255,.9);background-color:#f44336!important}.red-100,.red-200,.red-300,.red-50{color:rgba(0,0,0,.8)}.red-50,input[type=checkbox].red-50.switch::after{background-color:#ffebee!important}.red-100,input[type=checkbox].red-100.switch::after{background-color:#ffcdd2!important}.red-200,input[type=checkbox].red-200.switch::after{background-color:#ef9a9a!important}.red-300,input[type=checkbox].red-300.switch::after{background-color:#e57373!important}.pink,.red-400,.red-500,.red-600,.red-700,.red-800,.red-900{color:rgba(255,255,255,.9)}.red-400,input[type=checkbox].red-400.switch::after{background-color:#ef5350!important}.red-500,input[type=checkbox].red-500.switch::after{background-color:#f44336!important}.red-600,input[type=checkbox].red-600.switch::after{background-color:#e53935!important}.red-700,input[type=checkbox].red-700.switch::after{background-color:#d32f2f!important}.red-800,input[type=checkbox].red-800.switch::after{background-color:#c62828!important}.red-900,input[type=checkbox].red-900.switch::after{background-color:#b71c1c!important}.pink,input[type=checkbox].pink.switch::after{background-color:#e91e63!important}.pink-100,.pink-200,.pink-50{color:rgba(0,0,0,.8)}.pink-50,input[type=checkbox].pink-50.switch::after{background-color:#fce4ec!important}.pink-100,input[type=checkbox].pink-100.switch::after{background-color:#f8bbd0!important}.pink-200,input[type=checkbox].pink-200.switch::after{background-color:#f48fb1!important}.Pink-300,.pink-400,.pink-500,.pink-600,.pink-700,.pink-800,.pink-900,.purple{color:rgba(255,255,255,.9)}.Pink-300,input[type=checkbox].Pink-300.switch::after{background-color:#f06292!important}.pink-400,input[type=checkbox].pink-400.switch::after{background-color:#ec407a!important}.pink-500,input[type=checkbox].pink-500.switch::after{background-color:#e91e63!important}.pink-600,input[type=checkbox].pink-600.switch::after{background-color:#d81b60!important}.pink-700,input[type=checkbox].pink-700.switch::after{background-color:#c2185b!important}.pink-800,input[type=checkbox].pink-800.switch::after{background-color:#ad1457!important}.pink-900,input[type=checkbox].pink-900.switch::after{background-color:#880e4f!important}.purple,input[type=checkbox].purple.switch::after{background-color:#9c27b0!important}.purple-100,.purple-200,.purple-50{color:rgba(0,0,0,.8)}.purple-50,input[type=checkbox].purple-50.switch::after{background-color:#f3e5f5!important}.purple-100,input[type=checkbox].purple-100.switch::after{background-color:#e1bee7!important}.purple-200,input[type=checkbox].purple-200.switch::after{background-color:#ce93d8!important}.deep-purple,.purple-300,.purple-400,.purple-500,.purple-600,.purple-700,.purple-800,.purple-900{color:rgba(255,255,255,.9)}.purple-300,input[type=checkbox].purple-300.switch::after{background-color:#ba68c8!important}.purple-400,input[type=checkbox].purple-400.switch::after{background-color:#ab47bc!important}.purple-500,input[type=checkbox].purple-500.switch::after{background-color:#9c27b0!important}.purple-600,input[type=checkbox].purple-600.switch::after{background-color:#8e24aa!important}.purple-700,input[type=checkbox].purple-700.switch::after{background-color:#7b1fa2!important}.purple-800,input[type=checkbox].purple-800.switch::after{background-color:#6a1b9a!important}.purple-900,input[type=checkbox].purple-900.switch::after{background-color:#4a148c!important}.deep-purple,input[type=checkbox].deep-purple.switch::after{background-color:#673ab7!important}.deep-purple-50{color:rgba(0,0,0,.8);background-color:#ede7f6!important}.deep-purple-100{color:rgba(0,0,0,.8);background-color:#d1c4e9!important}.deep-purple-200{color:rgba(0,0,0,.8);background-color:#b39ddb!important}.deep-purple-300,.deep-purple-400,.deep-purple-500,.deep-purple-600,.deep-purple-700,.deep-purple-800,.deep-purple-900,.indigo{color:rgba(255,255,255,.9)}.deep-purple-300,input[type=checkbox].deep-purple-300.switch::after{background-color:#9575cd!important}.deep-purple-400,input[type=checkbox].deep-purple-400.switch::after{background-color:#7e57c2!important}.deep-purple-500,input[type=checkbox].deep-purple-500.switch::after{background-color:#673ab7!important}.deep-purple-600,input[type=checkbox].deep-purple-600.switch::after{background-color:#5e35b1!important}.deep-purple-700,input[type=checkbox].deep-purple-700.switch::after{background-color:#512da8!important}.deep-purple-800,input[type=checkbox].deep-purple-800.switch::after{background-color:#4527a0!important}.deep-purple-900,input[type=checkbox].deep-purple-900.switch::after{background-color:#311b92!important}.indigo,input[type=checkbox].indigo.switch::after{background-color:#3f51b5!important}.indigo-100,.indigo-200,.indigo-50{color:rgba(0,0,0,.8)}.indigo-50,input[type=checkbox].indigo-50.switch::after{background-color:#e8eaf6!important}.indigo-100,input[type=checkbox].indigo-100.switch::after{background-color:#c5cae9!important}.indigo-200,input[type=checkbox].indigo-200.switch::after{background-color:#9fa8da!important}.blue,.indigo-300,.indigo-400,.indigo-500,.indigo-600,.indigo-700,.indigo-800,.indigo-900{color:rgba(255,255,255,.9)}.indigo-300,input[type=checkbox].indigo-300.switch::after{background-color:#7986cb!important}.indigo-400,input[type=checkbox].indigo-400.switch::after{background-color:#5c6bc0!important}.indigo-500,input[type=checkbox].indigo-500.switch::after{background-color:#3f51b5!important}.indigo-600,input[type=checkbox].indigo-600.switch::after{background-color:#3949ab!important}.indigo-700,input[type=checkbox].indigo-700.switch::after{background-color:#303f9f!important}.indigo-800,input[type=checkbox].indigo-800.switch::after{background-color:#283593!important}.indigo-900,input[type=checkbox].indigo-900.switch::after{background-color:#1a237e!important}.blue,input[type=checkbox].blue.switch::after{background-color:#2196f3!important}.blue-100,.blue-200,.blue-300,.blue-400,.blue-50{color:rgba(0,0,0,.8)}.blue-50,input[type=checkbox].blue-50.switch::after{background-color:#e3f2fd!important}.blue-100,input[type=checkbox].blue-100.switch::after{background-color:#bbdefb!important}.blue-200,input[type=checkbox].blue-200.switch::after{background-color:#90caf9!important}.blue-300,input[type=checkbox].blue-300.switch::after{background-color:#64b5f6!important}.blue-400,input[type=checkbox].blue-400.switch::after{background-color:#42a5f5!important}.blue-500,.blue-600,.blue-700,.blue-800,.blue-900,.light-blue{color:rgba(255,255,255,.9)}.blue-500,input[type=checkbox].blue-500.switch::after{background-color:#2196f3!important}.blue-600,input[type=checkbox].blue-600.switch::after{background-color:#1e88e5!important}.blue-700,input[type=checkbox].blue-700.switch::after{background-color:#1976d2!important}.blue-800,input[type=checkbox].blue-800.switch::after{background-color:#1565c0!important}.blue-900,input[type=checkbox].blue-900.switch::after{background-color:#0d47a1!important}.light-blue,input[type=checkbox].light-blue.switch::after{background-color:#03a9f4!important}.light-blue-100,.light-blue-200,.light-blue-300,.light-blue-400,.light-blue-50,.light-blue-500{color:rgba(0,0,0,.8)}.light-blue-50,input[type=checkbox].light-blue-50.switch::after{background-color:#e1f5fe!important}.light-blue-100,input[type=checkbox].light-blue-100.switch::after{background-color:#b3e5fc!important}.light-blue-200,input[type=checkbox].light-blue-200.switch::after{background-color:#81d4fa!important}.light-blue-300,input[type=checkbox].light-blue-300.switch::after{background-color:#4fc3f7!important}.light-blue-400,input[type=checkbox].light-blue-400.switch::after{background-color:#29b6f6!important}.light-blue-500,input[type=checkbox].light-blue-500.switch::after{background-color:#03a9f4!important}.cyan,.light-blue-600,.light-blue-700,.light-blue-800,.light-blue-900{color:rgba(255,255,255,.9)}.light-blue-600,input[type=checkbox].light-blue-600.switch::after{background-color:#039be5!important}.light-blue-700,input[type=checkbox].light-blue-700.switch::after{background-color:#0288d1!important}.light-blue-800,input[type=checkbox].light-blue-800.switch::after{background-color:#0277bd!important}.light-blue-900,input[type=checkbox].light-blue-900.switch::after{background-color:#01579b!important}.cyan,input[type=checkbox].cyan.switch::after{background-color:#00bcd4!important}.cyan-100,.cyan-200,.cyan-300,.cyan-400,.cyan-50,.cyan-500,.cyan-600{color:rgba(0,0,0,.8)}.cyan-50,input[type=checkbox].cyan-50.switch::after{background-color:#e0f7fa!important}.cyan-100,input[type=checkbox].cyan-100.switch::after{background-color:#b2ebf2!important}.cyan-200,input[type=checkbox].cyan-200.switch::after{background-color:#80deea!important}.cyan-300,input[type=checkbox].cyan-300.switch::after{background-color:#4dd0e1!important}.cyan-400,input[type=checkbox].cyan-400.switch::after{background-color:#26c6da!important}.cyan-500,input[type=checkbox].cyan-500.switch::after{background-color:#00bcd4!important}.cyan-600,input[type=checkbox].cyan-600.switch::after{background-color:#00acc1!important}.cyan-700,.cyan-800,.cyan-900,.teal{color:rgba(255,255,255,.9)}.cyan-700,input[type=checkbox].cyan-700.switch::after{background-color:#0097a7!important}.cyan-800,input[type=checkbox].cyan-800.switch::after{background-color:#00838f!important}.cyan-900,input[type=checkbox].cyan-900.switch::after{background-color:#006064!important}.teal,input[type=checkbox].teal.switch::after{background-color:#009688!important}.teal-100,.teal-200,.teal-300,.teal-400,.teal-50{color:rgba(0,0,0,.8)}.teal-50,input[type=checkbox].teal-50.switch::after{background-color:#e0f2f1!important}.teal-100,input[type=checkbox].teal-100.switch::after{background-color:#b2dfdb!important}.teal-200,input[type=checkbox].teal-200.switch::after{background-color:#80cbc4!important}.teal-300,input[type=checkbox].teal-300.switch::after{background-color:#4db6ac!important}.teal-400,input[type=checkbox].teal-400.switch::after{background-color:#26a69a!important}.green,.teal-500,.teal-600,.teal-700,.teal-800,.teal-900{color:rgba(255,255,255,.9)}.teal-500,input[type=checkbox].teal-500.switch::after{background-color:#009688!important}.teal-600,input[type=checkbox].teal-600.switch::after{background-color:#00897b!important}.teal-700,input[type=checkbox].teal-700.switch::after{background-color:#00796b!important}.teal-800,input[type=checkbox].teal-800.switch::after{background-color:#00695c!important}.teal-900,input[type=checkbox].teal-900.switch::after{background-color:#004d40!important}.green,input[type=checkbox].green.switch::after{background-color:#4caf50!important}.green-100,.green-200,.green-300,.green-400,.green-50,.green-500{color:rgba(0,0,0,.8)}.green-50,input[type=checkbox].green-50.switch::after{background-color:#e8f5e9!important}.green-100,input[type=checkbox].green-100.switch::after{background-color:#c8e6c9!important}.green-200,input[type=checkbox].green-200.switch::after{background-color:#a5d6a7!important}.green-300,input[type=checkbox].green-300.switch::after{background-color:#81c784!important}.green-400,input[type=checkbox].green-400.switch::after{background-color:#66bb6a!important}.green-500,input[type=checkbox].green-500.switch::after{background-color:#4caf50!important}.green-600,.green-700,.green-800,.green-900,.light-green{color:rgba(255,255,255,.9)}.green-600,input[type=checkbox].green-600.switch::after{background-color:#43a047!important}.green-700,input[type=checkbox].green-700.switch::after{background-color:#388e3c!important}.green-800,input[type=checkbox].green-800.switch::after{background-color:#2e7d32!important}.green-900,input[type=checkbox].green-900.switch::after{background-color:#1b5e20!important}.light-green,input[type=checkbox].light-green.switch::after{background-color:#8bc34a!important}.light-green-100,.light-green-200,.light-green-300,.light-green-400,.light-green-50,.light-green-500,.light-green-600{color:rgba(0,0,0,.8)}.light-green-50,input[type=checkbox].light-green-50.switch::after{background-color:#f1f8e9!important}.light-green-100,input[type=checkbox].light-green-100.switch::after{background-color:#dcedc8!important}.light-green-200,input[type=checkbox].light-green-200.switch::after{background-color:#c5e1a5!important}.light-green-300,input[type=checkbox].light-green-300.switch::after{background-color:#aed581!important}.light-green-400,input[type=checkbox].light-green-400.switch::after{background-color:#9ccc65!important}.light-green-500,input[type=checkbox].light-green-500.switch::after{background-color:#8bc34a!important}.light-green-600,input[type=checkbox].light-green-600.switch::after{background-color:#7cb342!important}.light-green-700,.light-green-800,.light-green-900,.lime{color:rgba(255,255,255,.9)}.light-green-700,input[type=checkbox].light-green-700.switch::after{background-color:#689f38!important}.light-green-800,input[type=checkbox].light-green-800.switch::after{background-color:#558b2f!important}.light-green-900,input[type=checkbox].light-green-900.switch::after{background-color:#33691e!important}.lime,input[type=checkbox].lime.switch::after{background-color:#cddc39!important}.lime-100,.lime-200,.lime-300,.lime-400,.lime-50,.lime-500,.lime-600,.lime-700,.lime-800{color:rgba(0,0,0,.8)}.lime-50,input[type=checkbox].lime-50.switch::after{background-color:#f9fbe7!important}.lime-100,input[type=checkbox].lime-100.switch::after{background-color:#f0f4c3!important}.lime-200,input[type=checkbox].lime-200.switch::after{background-color:#e6ee9c!important}.lime-300,input[type=checkbox].lime-300.switch::after{background-color:#dce775!important}.lime-400,input[type=checkbox].lime-400.switch::after{background-color:#d4e157!important}.lime-500,input[type=checkbox].lime-500.switch::after{background-color:#cddc39!important}.lime-600,input[type=checkbox].lime-600.switch::after{background-color:#c0ca33!important}.lime-700,input[type=checkbox].lime-700.switch::after{background-color:#afb42b!important}.lime-800,input[type=checkbox].lime-800.switch::after{background-color:#9e9d24!important}.lime-900,.yellow{color:rgba(255,255,255,.9)}.lime-900,input[type=checkbox].lime-900.switch::after{background-color:#827717!important}.yellow,input[type=checkbox].yellow.switch::after{background-color:#ffeb3b!important}.yellow-100,.yellow-200,.yellow-300,.yellow-50,.yellow-500,.yellow-600,.yellow-700,.yellow-800,.yellow-900{color:rgba(0,0,0,.8)}.yellow-50,input[type=checkbox].yellow-50.switch::after{background-color:#fffde7!important}.yellow-100,input[type=checkbox].yellow-100.switch::after{background-color:#fff9c4!important}.yellow-200,input[type=checkbox].yellow-200.switch::after{background-color:#fff59d!important}.yellow-300,input[type=checkbox].yellow-300.switch::after{background-color:#fff176!important}.yellow-400{color:rgba(0,0,0,.8);background-color:#ffee58!important}.yellow-500,input[type=checkbox].yellow-500.switch::after{background-color:#ffeb3b!important}.yellow-600,input[type=checkbox].yellow-600.switch::after{background-color:#fdd835!important}.yellow-700,input[type=checkbox].yellow-700.switch::after{background-color:#fbc02d!important}.yellow-800,input[type=checkbox].yellow-800.switch::after{background-color:#f9a825!important}.yellow-900,input[type=checkbox].yellow-900.switch::after{background-color:#f57f17!important}.amber{color:rgba(255,255,255,.9);background-color:#ffc107!important}.amber-100,.amber-200,.amber-300,.amber-50,.amber-500,.amber-600,.amber-700,.amber-800,.amber-900{color:rgba(0,0,0,.8)}.amber-50,input[type=checkbox].amber-50.switch::after{background-color:#fff8e1!important}.amber-100,input[type=checkbox].amber-100.switch::after{background-color:#ffecb3!important}.amber-200,input[type=checkbox].amber-200.switch::after{background-color:#ffe082!important}.amber-300,input[type=checkbox].amber-300.switch::after{background-color:#ffd54f!important}.amber-400{color:rgba(0,0,0,.8);background-color:#ffca28!important}.amber-500,input[type=checkbox].amber-500.switch::after{background-color:#ffc107!important}.amber-600,input[type=checkbox].amber-600.switch::after{background-color:#ffb300!important}.amber-700,input[type=checkbox].amber-700.switch::after{background-color:#ffa000!important}.amber-800,input[type=checkbox].amber-800.switch::after{background-color:#ff8f00!important}.amber-900,input[type=checkbox].amber-900.switch::after{background-color:#ff6f00!important}.orange{color:rgba(255,255,255,.9);background-color:#ff9800!important}.orange-100,.orange-200,.orange-300,.orange-400,.orange-50,.orange-500,.orange-600,.orange-700{color:rgba(0,0,0,.8)}.orange-50,input[type=checkbox].orange-50.switch::after{background-color:#fff3e0!important}.orange-100,input[type=checkbox].orange-100.switch::after{background-color:#ffe0b2!important}.orange-200,input[type=checkbox].orange-200.switch::after{background-color:#ffcc80!important}.orange-300,input[type=checkbox].orange-300.switch::after{background-color:#ffb74d!important}.orange-400,input[type=checkbox].orange-400.switch::after{background-color:#ffa726!important}.orange-500,input[type=checkbox].orange-500.switch::after{background-color:#ff9800!important}.orange-600,input[type=checkbox].orange-600.switch::after{background-color:#fb8c00!important}.orange-700,input[type=checkbox].orange-700.switch::after{background-color:#f57c00!important}.deep-orange,.orange-800,.orange-900{color:rgba(255,255,255,.9)}.orange-800,input[type=checkbox].orange-800.switch::after{background-color:#ef6c00!important}.orange-900,input[type=checkbox].orange-900.switch::after{background-color:#e65100!important}.deep-orange,input[type=checkbox].deep-orange.switch::after{background-color:#ff5722!important}.deep-orange-100,.deep-orange-200,.deep-orange-300,.deep-orange-400,.deep-orange-50{color:rgba(0,0,0,.8)}.deep-orange-50,input[type=checkbox].deep-orange-50.switch::after{background-color:#fbe9e7!important}.deep-orange-100,input[type=checkbox].deep-orange-100.switch::after{background-color:#ffccbc!important}.deep-orange-200,input[type=checkbox].deep-orange-200.switch::after{background-color:#ffab91!important}.deep-orange-300,input[type=checkbox].deep-orange-300.switch::after{background-color:#ff8a65!important}.deep-orange-400,input[type=checkbox].deep-orange-400.switch::after{background-color:#ff7043!important}.brown,.deep-orange-500,.deep-orange-600,.deep-orange-700,.deep-orange-800,.deep-orange-900{color:rgba(255,255,255,.9)}.deep-orange-500,input[type=checkbox].deep-orange-500.switch::after{background-color:#ff5722!important}.deep-orange-600,input[type=checkbox].deep-orange-600.switch::after{background-color:#f4511e!important}.deep-orange-700,input[type=checkbox].deep-orange-700.switch::after{background-color:#e64a19!important}.deep-orange-800,input[type=checkbox].deep-orange-800.switch::after{background-color:#d84315!important}.deep-orange-900,input[type=checkbox].deep-orange-900.switch::after{background-color:#bf360c!important}.brown,input[type=checkbox].brown.switch::after{background-color:#795548!important}.brown-100,.brown-200,.brown-50{color:rgba(0,0,0,.8)}.brown-50,input[type=checkbox].brown-50.switch::after{background-color:#efebe9!important}.brown-100,input[type=checkbox].brown-100.switch::after{background-color:#d7ccc8!important}.brown-200,input[type=checkbox].brown-200.switch::after{background-color:#bcaaa4!important}.brown-300,.brown-400,.brown-500,.brown-600,.brown-700,.brown-800,.brown-900,.grey{color:rgba(255,255,255,.9)}.brown-300,input[type=checkbox].brown-300.switch::after{background-color:#a1887f!important}.brown-400,input[type=checkbox].brown-400.switch::after{background-color:#8d6e63!important}.brown-500,input[type=checkbox].brown-500.switch::after{background-color:#795548!important}.brown-600,input[type=checkbox].brown-600.switch::after{background-color:#6d4c41!important}.brown-700,input[type=checkbox].brown-700.switch::after{background-color:#5d4037!important}.brown-800,input[type=checkbox].brown-800.switch::after{background-color:#4e342e!important}.brown-900,input[type=checkbox].brown-900.switch::after{background-color:#3e2723!important}.grey,input[type=checkbox].grey.switch::after{background-color:#9e9e9e!important}.grey-100,.grey-200,.grey-300,.grey-400,.grey-50,.grey-500{color:rgba(0,0,0,.8)}.grey-50,input[type=checkbox].grey-50.switch::after{background-color:#fafafa!important}.grey-100,input[type=checkbox].grey-100.switch::after{background-color:#f5f5f5!important}.grey-200,input[type=checkbox].grey-200.switch::after{background-color:#eee!important}.grey-300,input[type=checkbox].grey-300.switch::after{background-color:#e0e0e0!important}.grey-400,input[type=checkbox].grey-400.switch::after{background-color:#bdbdbd!important}.grey-500,input[type=checkbox].grey-500.switch::after{background-color:#9e9e9e!important}.blue-grey,.grey-600,.grey-700,.grey-800,.grey-900{color:rgba(255,255,255,.9)}.grey-600,input[type=checkbox].grey-600.switch::after{background-color:#757575!important}.grey-700,input[type=checkbox].grey-700.switch::after{background-color:#616161!important}.grey-800,input[type=checkbox].grey-800.switch::after{background-color:#424242!important}.grey-900,input[type=checkbox].grey-900.switch::after{background-color:#212121!important}.blue-grey,input[type=checkbox].blue-grey.switch::after{background-color:#607d8b!important}.blue-grey-100,.blue-grey-200,.blue-grey-300,.blue-grey-50{color:rgba(0,0,0,.8)}.blue-grey-50,input[type=checkbox].blue-grey-50.switch::after{background-color:#eceff1!important}.blue-grey-100,input[type=checkbox].blue-grey-100.switch::after{background-color:#cfd8dc!important}.blue-grey-200,input[type=checkbox].blue-grey-200.switch::after{background-color:#b0bec5!important}.blue-grey-300,input[type=checkbox].blue-grey-300.switch::after{background-color:#90a4ae!important}.black,.blue-grey-400,.blue-grey-500,.blue-grey-600,.blue-grey-700,.blue-grey-800,.blue-grey-900{color:rgba(255,255,255,.9)}.blue-grey-400,input[type=checkbox].blue-grey-400.switch::after{background-color:#78909c!important}.transparent{background-color:rgba(0,0,0,0)!important}.blue-grey-500,input[type=checkbox].blue-grey-500.switch::after{background-color:#607d8b!important}.blue-grey-600,input[type=checkbox].blue-grey-600.switch::after{background-color:#546e7a!important}.blue-grey-700,input[type=checkbox].blue-grey-700.switch::after{background-color:#455a64!important}.blue-grey-800,input[type=checkbox].blue-grey-800.switch::after{background-color:#37474f!important}.blue-grey-900,input[type=checkbox].blue-grey-900.switch::after{background-color:#263238!important}.black,input[type=checkbox].black.switch::after{background-color:#000!important}.black-opacity-90{background-color:rgba(0,0,0,.9)}.black-opacity-70{background-color:rgba(0,0,0,.7)}.black-opacity-50{background-color:rgba(0,0,0,.5)}.black-opacity-30{background-color:rgba(0,0,0,.3)}.black-opacity-10{background-color:rgba(0,0,0,.1)}.white{color:rgba(0,0,0,.8);background-color:#fff!important}.white-opacity-90{background-color:rgba(255,255,255,.9)}.white-opacity-70{background-color:rgba(255,255,255,.7)}.white-opacity-50{background-color:rgba(255,255,255,.5)}.white-opacity-30{background-color:rgba(255,255,255,.3)}.white-opacity-10{background-color:rgba(255,255,255,.1)}.text-red,i.red{color:#f44336}.text-red-50,i.red-50{color:#ffebee}.text-red-100,i.red-100{color:#ffcdd2}.text-red-200,i.red-200{color:#ef9a9a}.text-red-300,i.red-300{color:#e57373}.text-red-400,i.red-400{color:#ef5350}.text-red-500,i.red-500{color:#f44336}.text-red-600,i.red-600{color:#e53935}.text-red-700,i.red-700{color:#d32f2f}.text-red-800,i.red-800{color:#c62828}.text-red-900,i.red-900{color:#b71c1c}.text-pink,i.pink{color:#e91e63}.text-pink-50,i.pink-50{color:#fce4ec}.text-pink-100,i.pink-100{color:#f8bbd0}.text-pink-200,i.pink-200{color:#f48fb1}.text-Pink-300,i.Pink-300{color:#f06292}.text-pink-400,i.pink-400{color:#ec407a}.text-pink-500,i.pink-500{color:#e91e63}.text-pink-600,i.pink-600{color:#d81b60}.text-pink-700,i.pink-700{color:#c2185b}.text-pink-800,i.pink-800{color:#ad1457}.text-pink-900,i.pink-900{color:#880e4f}.text-purple,i.purple{color:#9c27b0}.text-purple-50,i.purple-50{color:#f3e5f5}.text-purple-100,i.purple-100{color:#e1bee7}.text-purple-200,i.purple-200{color:#ce93d8}.text-purple-300,i.purple-300{color:#ba68c8}.text-purple-400,i.purple-400{color:#ab47bc}.text-purple-500,i.purple-500{color:#9c27b0}.text-purple-600,i.purple-600{color:#8e24aa}.text-purple-700,i.purple-700{color:#7b1fa2}.text-purple-800,i.purple-800{color:#6a1b9a}.text-purple-900,i.purple-900{color:#4a148c}.text-deep-purple,i.deep-purple{color:#673ab7}.text-deep-purple-50,i.deep-purple-50{color:#ede7f6}.text-deep-purple-100,i.deep-purple-100{color:#d1c4e9}.text-deep-purple-200,i.deep-purple-200{color:#b39ddb}.text-deep-purple-300,i.deep-purple-300{color:#9575cd}.text-deep-purple-400,i.deep-purple-400{color:#7e57c2}.text-deep-purple-500,i.deep-purple-500{color:#673ab7}.text-deep-purple-600,i.deep-purple-600{color:#5e35b1}.text-deep-purple-700,i.deep-purple-700{color:#512da8}.text-deep-purple-800,i.deep-purple-800{color:#4527a0}.text-deep-purple-900,i.deep-purple-900{color:#311b92}.text-indigo,i.indigo{color:#3f51b5}.text-indigo-50,i.indigo-50{color:#e8eaf6}.text-indigo-100,i.indigo-100{color:#c5cae9}.text-indigo-200,i.indigo-200{color:#9fa8da}.text-indigo-300,i.indigo-300{color:#7986cb}.text-indigo-400,i.indigo-400{color:#5c6bc0}.text-indigo-500,i.indigo-500{color:#3f51b5}.text-indigo-600,i.indigo-600{color:#3949ab}.text-indigo-700,i.indigo-700{color:#303f9f}.text-indigo-800,i.indigo-800{color:#283593}.text-indigo-900,i.indigo-900{color:#1a237e}.text-blue,i.blue{color:#2196f3}.text-blue-50,i.blue-50{color:#e3f2fd}.text-blue-100,i.blue-100{color:#bbdefb}.text-blue-200,i.blue-200{color:#90caf9}.text-blue-300,i.blue-300{color:#64b5f6}.text-blue-400,i.blue-400{color:#42a5f5}.text-blue-500,i.blue-500{color:#2196f3}.text-blue-600,i.blue-600{color:#1e88e5}.text-blue-700,i.blue-700{color:#1976d2}.text-blue-800,i.blue-800{color:#1565c0}.text-blue-900,i.blue-900{color:#0d47a1}.text-light-blue,i.light-blue{color:#03a9f4}.text-light-blue-50,i.light-blue-50{color:#e1f5fe}.text-light-blue-100,i.light-blue-100{color:#b3e5fc}.text-light-blue-200,i.light-blue-200{color:#81d4fa}.text-light-blue-300,i.light-blue-300{color:#4fc3f7}.text-light-blue-400,i.light-blue-400{color:#29b6f6}.text-light-blue-500,i.light-blue-500{color:#03a9f4}.text-light-blue-600,i.light-blue-600{color:#039be5}.text-light-blue-700,i.light-blue-700{color:#0288d1}.text-light-blue-800,i.light-blue-800{color:#0277bd}.text-light-blue-900,i.light-blue-900{color:#01579b}.text-cyan,i.cyan{color:#00bcd4}.text-cyan-50,i.cyan-50{color:#e0f7fa}.text-cyan-100,i.cyan-100{color:#b2ebf2}.text-cyan-200,i.cyan-200{color:#80deea}.text-cyan-300,i.cyan-300{color:#4dd0e1}.text-cyan-400,i.cyan-400{color:#26c6da}.text-cyan-500,i.cyan-500{color:#00bcd4}.text-cyan-600,i.cyan-600{color:#00acc1}.text-cyan-700,i.cyan-700{color:#0097a7}.text-cyan-800,i.cyan-800{color:#00838f}.text-cyan-900,i.cyan-900{color:#006064}.text-teal,i.teal{color:#009688}.text-teal-50,i.teal-50{color:#e0f2f1}.text-teal-100,i.teal-100{color:#b2dfdb}.text-teal-200,i.teal-200{color:#80cbc4}.text-teal-300,i.teal-300{color:#4db6ac}.text-teal-400,i.teal-400{color:#26a69a}.text-teal-500,i.teal-500{color:#009688}.text-teal-600,i.teal-600{color:#00897b}.text-teal-700,i.teal-700{color:#00796b}.text-teal-800,i.teal-800{color:#00695c}.text-teal-900,i.teal-900{color:#004d40}.text-green,i.green{color:#4caf50}.text-green-50,i.green-50{color:#e8f5e9}.text-green-100,i.green-100{color:#c8e6c9}.text-green-200,i.green-200{color:#a5d6a7}.text-green-300,i.green-300{color:#81c784}.text-green-400,i.green-400{color:#66bb6a}.text-green-500,i.green-500{color:#4caf50}.text-green-600,i.green-600{color:#43a047}.text-green-700,i.green-700{color:#388e3c}.text-green-800,i.green-800{color:#2e7d32}.text-green-900,i.green-900{color:#1b5e20}.text-light-green,i.light-green{color:#8bc34a}.text-light-green-50,i.light-green-50{color:#f1f8e9}.text-light-green-100,i.light-green-100{color:#dcedc8}.text-light-green-200,i.light-green-200{color:#c5e1a5}.text-light-green-300,i.light-green-300{color:#aed581}.text-light-green-400,i.light-green-400{color:#9ccc65}.text-light-green-500,i.light-green-500{color:#8bc34a}.text-light-green-600,i.light-green-600{color:#7cb342}.text-light-green-700,i.light-green-700{color:#689f38}.text-light-green-800,i.light-green-800{color:#558b2f}.text-light-green-900,i.light-green-900{color:#33691e}.text-lime,i.lime{color:#cddc39}.text-lime-50,i.lime-50{color:#f9fbe7}.text-lime-100,i.lime-100{color:#f0f4c3}.text-lime-200,i.lime-200{color:#e6ee9c}.text-lime-300,i.lime-300{color:#dce775}.text-lime-400,i.lime-400{color:#d4e157}.text-lime-500,i.lime-500{color:#cddc39}.text-lime-600,i.lime-600{color:#c0ca33}.text-lime-700,i.lime-700{color:#afb42b}.text-lime-800,i.lime-800{color:#9e9d24}.text-lime-900,i.lime-900{color:#827717}.text-yellow,i.yellow{color:#ffeb3b}.text-yellow-50,i.yellow-50{color:#fffde7}.text-yellow-100,i.yellow-100{color:#fff9c4}.text-yellow-200,i.yellow-200{color:#fff59d}.text-yellow-300,i.yellow-300{color:#fff176}.text-yellow-400,i.yellow-400{color:#ffee58}.text-yellow-500,i.yellow-500{color:#ffeb3b}.text-yellow-600,i.yellow-600{color:#fdd835}.text-yellow-700,i.yellow-700{color:#fbc02d}.text-yellow-800,i.yellow-800{color:#f9a825}.text-yellow-900,i.yellow-900{color:#f57f17}.text-amber,i.amber{color:#ffc107}.text-amber-50,i.amber-50{color:#fff8e1}.text-amber-100,i.amber-100{color:#ffecb3}.text-amber-200,i.amber-200{color:#ffe082}.text-amber-300,i.amber-300{color:#ffd54f}.text-amber-400,i.amber-400{color:#ffca28}.text-amber-500,i.amber-500{color:#ffc107}.text-amber-600,i.amber-600{color:#ffb300}.text-amber-700,i.amber-700{color:#ffa000}.text-amber-800,i.amber-800{color:#ff8f00}.text-amber-900,i.amber-900{color:#ff6f00}.text-orange,i.orange{color:#ff9800}.text-orange-50,i.orange-50{color:#fff3e0}.text-orange-100,i.orange-100{color:#ffe0b2}.text-orange-200,i.orange-200{color:#ffcc80}.text-orange-300,i.orange-300{color:#ffb74d}.text-orange-400,i.orange-400{color:#ffa726}.text-orange-500,i.orange-500{color:#ff9800}.text-orange-600,i.orange-600{color:#fb8c00}.text-orange-700,i.orange-700{color:#f57c00}.text-orange-800,i.orange-800{color:#ef6c00}.text-orange-900,i.orange-900{color:#e65100}.text-deep-orange,i.deep-orange{color:#ff5722}.text-deep-orange-50,i.deep-orange-50{color:#fbe9e7}.text-deep-orange-100,i.deep-orange-100{color:#ffccbc}.text-deep-orange-200,i.deep-orange-200{color:#ffab91}.text-deep-orange-300,i.deep-orange-300{color:#ff8a65}.text-deep-orange-400,i.deep-orange-400{color:#ff7043}.text-deep-orange-500,i.deep-orange-500{color:#ff5722}.text-deep-orange-600,i.deep-orange-600{color:#f4511e}.text-deep-orange-700,i.deep-orange-700{color:#e64a19}.text-deep-orange-800,i.deep-orange-800{color:#d84315}.text-deep-orange-900,i.deep-orange-900{color:#bf360c}.text-brown,i.brown{color:#795548}.text-brown-50,i.brown-50{color:#efebe9}.text-brown-100,i.brown-100{color:#d7ccc8}.text-brown-200,i.brown-200{color:#bcaaa4}.text-brown-300,i.brown-300{color:#a1887f}.text-brown-400,i.brown-400{color:#8d6e63}.text-brown-500,i.brown-500{color:#795548}.text-brown-600,i.brown-600{color:#6d4c41}.text-brown-700,i.brown-700{color:#5d4037}.text-brown-800,i.brown-800{color:#4e342e}.text-brown-900,i.brown-900{color:#3e2723}.text-grey,i.grey{color:#9e9e9e}.text-grey-50,i.grey-50{color:#fafafa}.text-grey-100,i.grey-100{color:#f5f5f5}.text-grey-200,i.grey-200{color:#eee}.text-grey-300,i.grey-300{color:#e0e0e0}.text-grey-400,i.grey-400{color:#bdbdbd}.text-grey-500,i.grey-500{color:#9e9e9e}.text-grey-600,i.grey-600{color:#757575}.text-grey-700,i.grey-700{color:#616161}.text-grey-800,i.grey-800{color:#424242}.text-grey-900,i.grey-900{color:#212121}.text-blue-grey,i.blue-grey{color:#607d8b}.text-blue-grey-50,i.blue-grey-50{color:#eceff1}.text-blue-grey-100,i.blue-grey-100{color:#cfd8dc}.text-blue-grey-200,i.blue-grey-200{color:#b0bec5}.text-blue-grey-300,i.blue-grey-300{color:#90a4ae}.text-blue-grey-400,i.blue-grey-400{color:#78909c}.text-blue-grey-500,i.blue-grey-500{color:#607d8b}.text-blue-grey-600,i.blue-grey-600{color:#546e7a}.text-blue-grey-700,i.blue-grey-700{color:#455a64}.text-blue-grey-800,i.blue-grey-800{color:#37474f}.text-blue-grey-900,i.blue-grey-900{color:#263238}.text-black,i.black{color:#000}.text-white,i.white{color:#fff}.border-red{border:1px solid #f44336}.border-red-50{border:1px solid #ffebee}.border-red-100{border:1px solid #ffcdd2}.border-red-200{border:1px solid #ef9a9a}.border-red-300{border:1px solid #e57373}.border-red-400{border:1px solid #ef5350}.border-red-500{border:1px solid #f44336}.border-red-600{border:1px solid #e53935}.border-red-700{border:1px solid #d32f2f}.border-red-800{border:1px solid #c62828}.border-red-900{border:1px solid #b71c1c}.border-pink{border:1px solid #e91e63}.border-pink-50{border:1px solid #fce4ec}.border-pink-100{border:1px solid #f8bbd0}.border-pink-200{border:1px solid #f48fb1}.border-pink-300{border:1px solid #f06292}.border-pink-400{border:1px solid #ec407a}.border-pink-500{border:1px solid #e91e63}.border-pink-600{border:1px solid #d81b60}.border-pink-700{border:1px solid #c2185b}.border-pink-800{border:1px solid #ad1457}.border-pink-900{border:1px solid #880e4f}.border-purple{border:1px solid #9c27b0}.border-purple-50{border:1px solid #f3e5f5}.border-purple-100{border:1px solid #e1bee7}.border-purple-200{border:1px solid #ce93d8}.border-purple-300{border:1px solid #ba68c8}.border-purple-400{border:1px solid #ab47bc}.border-purple-500{border:1px solid #9c27b0}.border-purple-600{border:1px solid #8e24aa}.border-purple-700{border:1px solid #7b1fa2}.border-purple-800{border:1px solid #6a1b9a}.border-purple-900{border:1px solid #4a148c}.border-deep-purple{border:1px solid #673ab7}.border-deep-purple-50{border:1px solid #ede7f6}.border-deep-purple-100{border:1px solid #d1c4e9}.border-deep-purple-200{border:1px solid #b39ddb}.border-deep-purple-300{border:1px solid #9575cd}.border-deep-purple-400{border:1px solid #7e57c2}.border-deep-purple-500{border:1px solid #673ab7}.border-deep-purple-600{border:1px solid #5e35b1}.border-deep-purple-700{border:1px solid #512da8}.border-deep-purple-800{border:1px solid #4527a0}.border-deep-purple-900{border:1px solid #311b92}.border-indigo{border:1px solid #3f51b5}.border-indigo-50{border:1px solid #e8eaf6}.border-indigo-100{border:1px solid #c5cae9}.border-indigo-200{border:1px solid #9fa8da}.border-indigo-300{border:1px solid #7986cb}.border-indigo-400{border:1px solid #5c6bc0}.border-indigo-500{border:1px solid #3f51b5}.border-indigo-600{border:1px solid #3949ab}.border-indigo-700{border:1px solid #303f9f}.border-indigo-800{border:1px solid #283593}.border-indigo-900{border:1px solid #1a237e}.border-blue{border:1px solid #2196f3}.border-blue-50{border:1px solid #e3f2fd}.border-blue-100{border:1px solid #bbdefb}.border-blue-200{border:1px solid #90caf9}.border-blue-300{border:1px solid #64b5f6}.border-blue-400{border:1px solid #42a5f5}.border-blue-500{border:1px solid #2196f3}.border-blue-600{border:1px solid #1e88e5}.border-blue-700{border:1px solid #1976d2}.border-blue-800{border:1px solid #1565c0}.border-blue-900{border:1px solid #0d47a1}.border-light-blue{border:1px solid #03a9f4}.border-light-blue-50{border:1px solid #e1f5fe}.border-light-blue-100{border:1px solid #b3e5fc}.border-light-blue-200{border:1px solid #81d4fa}.border-light-blue-300{border:1px solid #4fc3f7}.border-light-blue-400{border:1px solid #29b6f6}.border-light-blue-500{border:1px solid #03a9f4}.border-light-blue-600{border:1px solid #039be5}.border-light-blue-700{border:1px solid #0288d1}.border-light-blue-800{border:1px solid #0277bd}.border-light-blue-900{border:1px solid #01579b}.border-cyan{border:1px solid #00bcd4}.border-cyan-50{border:1px solid #e0f7fa}.border-cyan-100{border:1px solid #b2ebf2}.border-cyan-200{border:1px solid #80deea}.border-cyan-300{border:1px solid #4dd0e1}.border-cyan-400{border:1px solid #26c6da}.border-cyan-500{border:1px solid #00bcd4}.border-cyan-600{border:1px solid #00acc1}.border-cyan-700{border:1px solid #0097a7}.border-cyan-800{border:1px solid #00838f}.border-cyan-900{border:1px solid #006064}.border-teal{border:1px solid #009688}.border-teal-50{border:1px solid #e0f2f1}.border-teal-100{border:1px solid #b2dfdb}.border-teal-200{border:1px solid #80cbc4}.border-teal-300{border:1px solid #4db6ac}.border-teal-400{border:1px solid #26a69a}.border-teal-500{border:1px solid #009688}.border-teal-600{border:1px solid #00897b}.border-teal-700{border:1px solid #00796b}.border-teal-800{border:1px solid #00695c}.border-teal-900{border:1px solid #004d40}.border-green{border:1px solid #4caf50}.border-green-50{border:1px solid #e8f5e9}.border-green-100{border:1px solid #c8e6c9}.border-green-200{border:1px solid #a5d6a7}.border-green-300{border:1px solid #81c784}.border-green-400{border:1px solid #66bb6a}.border-green-500{border:1px solid #4caf50}.border-green-600{border:1px solid #43a047}.border-green-700{border:1px solid #388e3c}.border-green-800{border:1px solid #2e7d32}.border-green-900{border:1px solid #1b5e20}.border-light-green{border:1px solid #8bc34a}.border-light-green-50{border:1px solid #f1f8e9}.border-light-green-100{border:1px solid #dcedc8}.border-light-green-200{border:1px solid #c5e1a5}.border-light-green-300{border:1px solid #aed581}.border-light-green-400{border:1px solid #9ccc65}.border-light-green-500{border:1px solid #8bc34a}.border-light-green-600{border:1px solid #7cb342}.border-light-green-700{border:1px solid #689f38}.border-light-green-800{border:1px solid #558b2f}.border-light-green-900{border:1px solid #33691e}.border-lime{border:1px solid #cddc39}.border-lime-50{border:1px solid #f9fbe7}.border-lime-100{border:1px solid #f0f4c3}.border-lime-200{border:1px solid #e6ee9c}.border-lime-300{border:1px solid #dce775}.border-lime-400{border:1px solid #d4e157}.border-lime-500{border:1px solid #cddc39}.border-lime-600{border:1px solid #c0ca33}.border-lime-700{border:1px solid #afb42b}.border-lime-800{border:1px solid #9e9d24}.border-lime-900{border:1px solid #827717}.border-yellow{border:1px solid #ffeb3b}.border-yellow-50{border:1px solid #fffde7}.border-yellow-100{border:1px solid #fff9c4}.border-yellow-200{border:1px solid #fff59d}.border-yellow-300{border:1px solid #fff176}.border-yellow-400{border:1px solid #ffee58}.border-yellow-500{border:1px solid #ffeb3b}.border-yellow-600{border:1px solid #fdd835}.border-yellow-700{border:1px solid #fbc02d}.border-yellow-800{border:1px solid #f9a825}.border-yellow-900{border:1px solid #f57f17}.border-amber{border:1px solid #ffc107}.border-amber-50{border:1px solid #fff8e1}.border-amber-100{border:1px solid #ffecb3}.border-amber-200{border:1px solid #ffe082}.border-amber-300{border:1px solid #ffd54f}.border-amber-400{border:1px solid #ffca28}.border-amber-500{border:1px solid #ffc107}.border-amber-600{border:1px solid #ffb300}.border-amber-700{border:1px solid #ffa000}.border-amber-800{border:1px solid #ff8f00}.border-amber-900{border:1px solid #ff6f00}.border-orange{border:1px solid #ff9800}.border-orange-50{border:1px solid #fff3e0}.border-orange-100{border:1px solid #ffe0b2}.border-orange-200{border:1px solid #ffcc80}.border-orange-300{border:1px solid #ffb74d}.border-orange-400{border:1px solid #ffa726}.border-orange-500{border:1px solid #ff9800}.border-orange-600{border:1px solid #fb8c00}.border-orange-700{border:1px solid #f57c00}.border-orange-800{border:1px solid #ef6c00}.border-orange-900{border:1px solid #e65100}.border-deep-orange{border:1px solid #ff5722}.border-deep-orange-50{border:1px solid #fbe9e7}.border-deep-orange-100{border:1px solid #ffccbc}.border-deep-orange-200{border:1px solid #ffab91}.border-deep-orange-300{border:1px solid #ff8a65}.border-deep-orange-400{border:1px solid #ff7043}.border-deep-orange-500{border:1px solid #ff5722}.border-deep-orange-600{border:1px solid #f4511e}.border-deep-orange-700{border:1px solid #e64a19}.border-deep-orange-800{border:1px solid #d84315}.border-deep-orange-900{border:1px solid #bf360c}.border-brown{border:1px solid #795548}.border-brown-50{border:1px solid #efebe9}.border-brown-100{border:1px solid #d7ccc8}.border-brown-200{border:1px solid #bcaaa4}.border-brown-300{border:1px solid #a1887f}.border-brown-400{border:1px solid #8d6e63}.border-brown-500{border:1px solid #795548}.border-brown-600{border:1px solid #6d4c41}.border-brown-700{border:1px solid #5d4037}.border-brown-800{border:1px solid #4e342e}.border-brown-900{border:1px solid #3e2723}.border-grey{border:1px solid #9e9e9e}.border-grey-50{border:1px solid #fafafa}.border-grey-100{border:1px solid #f5f5f5}.border-grey-200{border:1px solid #eee}.border-grey-300{border:1px solid #e0e0e0}.border-grey-400{border:1px solid #bdbdbd}.border-grey-500{border:1px solid #9e9e9e}.border-grey-600{border:1px solid #757575}.border-grey-700{border:1px solid #616161}.border-grey-800{border:1px solid #424242}.border-grey-900{border:1px solid #212121}.border-blue-grey{border:1px solid #607d8b}.border-blue-grey-50{border:1px solid #eceff1}.border-blue-grey-100{border:1px solid #cfd8dc}.border-blue-grey-200{border:1px solid #b0bec5}.border-blue-grey-300{border:1px solid #90a4ae}.border-blue-grey-400{border:1px solid #78909c}.border-blue-grey-500{border:1px solid #607d8b}.border-blue-grey-600{border:1px solid #546e7a}.border-blue-grey-700{border:1px solid #455a64}.border-blue-grey-800{border:1px solid #37474f}.border-blue-grey-900{border:1px solid #263238}.border-black{border:1px solid #000}.border-white{border:1px solid #fff}@font-face{font-family:Roboto;font-style:normal;font-weight:300;src:local('Roboto Light'),local('Roboto-Light'),url(fonts/robotolight.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:local('Roboto'),local('Roboto-Regular'),url(fonts/sTdaA6j0Psb920Vjv-mrzH-_kf6ByYO6CLYdB4HQE-Y.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Roboto;font-style:normal;font-weight:900;src:local('Roboto Black'),local('Roboto-Black'),url(fonts/robotoblack.woff2) format('woff2');unicode-range:U+0460-052F,U+20B4,U+2DE0-2DFF,U+A640-A69F}@font-face{font-family:Ionicons;src:url(fonts/ionicons.woff?v=2.0.0) format("woff");font-weight:400;font-style:normal}i.icon{background:0 0!important}.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;min-width:22px;text-align:center}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}
+
+.component-header{display:block}.footer,.header{font-size:18px;display:inline-block;width:100%;position:fixed;top:0;left:0;height:52px;z-index:9}.footer{top:initial;bottom:0}.header.sub{top:52px}.footer.sub{top:initial;bottom:52px}.has-header{padding-top:52px!important}.has-header.has-sub-header{padding-top:104px!important}.has-footer{padding-bottom:52px!important}.has-footer.has-sub-footer{padding-bottom:104px!important}.footer .left,.footer .right,.footer .title,.footer h1,.header .left,.header .right,.header .title,.header h1{margin-top:15px;margin-bottom:5px}.header .avatar{height:40px;margin-top:-8px;margin-left:4px}.header .border-big{border-width:2px;border-style:solid}.footer h2,.header h2{padding-top:8px;padding-left:10px}.footer p,.header p{padding-left:10px;margin:0;margin-top:-4px}.footer .left,.header .left{padding-left:5px}.footer .right,.header .right{padding-right:5px}.footer .title,.footer h1,.header .title,.header h1{margin-bottom:15px;padding-left:10px;padding-right:15px;display:inline-block}.footer button,.header button{margin-top:-10px}.footer button.icon,.header button.icon{font-size:30px;margin-top:-10px;z-index:99;background:0 0;border:none;padding:0 6px}.footer button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]),.header button.icon:not([class*=red]):not([class*=pink]):not([class*=white]):not([class*=purple]):not([class*=indigo]):not([class*=blue]):not([class*=cyan]):not([class*=teal]):not([class*=green]):not([class*=lime]):not([class*=yellow]):not([class*=amber]):not([class*=orange]):not([class*=brown]):not([class*=grey]):not([class*=black]):not([class*=white]){color:#fff}.footer button.icon.left,.footer button.icon.right,.header button.icon.left,.header button.icon.right{margin-top:5px;margin-bottom:5px}.footer button.icon.left,.header button.icon.left{margin-left:5px}.footer button.icon.right,.header button.icon.right{margin-right:5px}.footer .title.align-center,.footer h1.align-center,.footer p.align-center,.header .title.align-center,.header h1.align-center,.header p.align-center{width:100%;position:inherit;padding-right:15px;left:0;z-index:9}.footer .icon-badge,.header .icon-badge{position:absolute;margin-left:-6px;margin-top:-8px;border-radius:8px;z-index:999}.footer .buttons-group,.header .buttons-group{margin-top:15px;margin-left:5px;margin-right:5px}.footer .buttons-group.small,.header .buttons-group.small{margin-top:20px;margin-left:10px;margin-right:10px}.header input::-webkit-input-placeholder{color:rgba(0,0,0,.8)}.header input.placeholder-white::-webkit-input-placeholder{color:rgba(255,255,255,.8)}.header input{padding:15px;position:absolute}.header .left+input{padding-right:50px}
+.component-button{display:block}button{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease;font-size:14px;border:none;background-color:rgba(0,0,0,0);color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-height:42px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer;overflow:hidden}button[disabled]{opacity:.8}button .icon{position:absolute;left:10px}button.circle{width:42px;height:42px;text-align:center;padding:0;line-height:0;font-size:22px;z-index:10}button.icon-text{padding-left:40px}button.icon-text i{font-size:22px}button.icon-text.icon-right{padding-left:12px;padding-right:40px;position:relative}button.icon-right i{position:absolute;right:12px;text-align:right;margin-top:2px}button[class*=border-]{min-height:40px;line-height:40px}button.full{width:100%}.buttons-group.big button,button.big{font-size:22px;min-height:50px;line-height:50px}button.circle.big{width:50px;height:50px;font-size:28px}button.big.icon-text{padding-left:40px}button.big.icon-text.icon-right{padding-left:12px;padding-right:40px}button.big.icon-text i{font-size:26px}.buttons-group.small button,button.small{font-size:12px;min-height:30px;line-height:30px}button.circle.small{width:30px;height:30px;font-size:18px}button.small.icon-text{padding-left:30px}button.small.icon-text.icon-right{padding-left:12px;padding-right:35px}button.small.icon-text i{font-size:18px}.buttons-group.huge button,button.huge{font-size:32px;min-height:70px;line-height:70px}button.circle.huge{width:70px;height:70px;font-size:32px}button.huge.icon-text{padding-left:40px}button.huge.icon-text.icon-right{padding-left:12px;padding-right:40px}button.huge.icon-text i{font-size:32px}.buttons-group{display:inline-block}.buttons-group button{float:left;margin-left:-1px}.buttons-group button:first-child{margin-left:0}.buttons-group.full{display:flex}.buttons-group.full button{flex:1}.ripple{position:absolute;background:rgba(255,255,255,.25);border-radius:100%;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ripple.show{-webkit-animation:ripple .5s ease-out;-moz-animation:ripple .5s ease-out;-o-animation:ripple .5s ease-out;animation:ripple .5s ease-out}@-webkit-keyframes ripple{to{-webkit-transform:scale(1.5);opacity:0}}@-moz-keyframes ripple{to{-moz-transform:scale(1.5);opacity:0}}@-o-keyframes ripple{to{-o-transform:scale(1.5);opacity:0}}@keyframes ripple{to{transform:scale(1.5);opacity:0}}
+.alert-mobileui .alert {
+    font-family: Roboto,Noto,sans-serif;
+    position: relative;
+    border-radius: 4px;
+    box-shadow: 0 16px 24px 2px rgba(0,0,0,.14), 0 6px 30px 5px rgba(0,0,0,.12), 0 8px 10px -5px rgba(0,0,0,.4);
+    max-width: 270px;
+    word-break: break-all;
+}
+.alert-mobileui {
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-pack: center;
+    -ms-flex-pack: center;
+    justify-content: center;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    align-items: center;
+    position: absolute;
+    top:40%;
+    left: 0;
+    right: 0;
+}
+.backdrop {
+    height: 100%;
+    background-color: #000;
+    opacity: .01;
+    z-index: 9999;
+    transition-duration: 280ms;
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdmng.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdmng.html
new file mode 100644
index 0000000..602af6e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdmng.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>支付密码管理</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">支付密码管理</div>
+    </header>
+    <section class="aui-content aui-margin-b-15 aui-margin-t-10">
+        <ul class="aui-list aui-list-in aui-margin-t-10 ">
+            <li class="aui-list-item" onclick="app.editPwd()">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-pencil aui-text-info"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">修改支付密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+            <li class="aui-list-item" onclick="app.findPwd()">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-search aui-text-danger"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">找回支付密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+        </ul>
+    </section>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/paypwdmng.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdset.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdset.html
new file mode 100644
index 0000000..1714ab1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/paypwdset.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>设置支付密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">设置支付密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">支付密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd"  pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd"  pattern="[0-9]*" placeholder="6位数字" maxlength="6">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doNext();" class="weui-btn weui-btn_primary">保存</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/paypwdset.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..5faece0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,23 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) {
+/*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..e7cdb39
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,73 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) {
+module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+  var storeKey = '__advancedHttpCookieStore__';
+
+  var store = new WebStorageCookieStore(storage, storeKey);
+  var cookieJar = new ToughCookie.CookieJar(store);
+
+  return {
+    setCookieFromString: setCookieFromString,
+    setCookie: setCookie,
+    getCookieString: getCookieString,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies
+  };
+
+  function splitCookieString(cookieStr) {
+    var cookieParts = cookieStr.split(',');
+    var splitCookies = [];
+    var processedCookie = null;
+
+    for (var i = 0; i < cookieParts.length; ++i) {
+      if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+        processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+        i++;
+      } else {
+        processedCookie = cookieParts[i];
+      }
+
+      processedCookie = processedCookie.trim();
+      splitCookies.push(processedCookie);
+    }
+
+    return splitCookies;
+  }
+
+  function setCookieFromString(url, cookieStr) {
+    if (!cookieStr) return;
+
+    var cookies = splitCookieString(cookieStr);
+
+    for (var i = 0; i < cookies.length; ++i) {
+      cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+    }
+  }
+
+  function setCookie(url, cookie, options) {
+    options = options || {};
+    options.ignoreError = false;
+    cookieJar.setCookieSync(cookie, url, options);
+  }
+
+  function getCookieString(url) {
+    return cookieJar.getCookieStringSync(url);
+  }
+
+  function clearCookies() {
+    window.localStorage.removeItem(storeKey);
+  }
+
+  function removeCookies(url, cb) {
+    cookieJar.getCookies(url, function (error, cookies) {
+      if (!cookies || cookies.length === 0) {
+        return cb(null, []);
+      }
+
+      var domain = cookies[0].domain;
+
+      cookieJar.store.removeCookies(domain, null, cb);
+    });
+  }
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..5e85416
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,11 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) {
+var globalConfigs = {
+  headers: {},
+  serializer: 'urlencoded',
+  followRedirect: true,
+  timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..855e84c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,353 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) {
+module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+  var validSerializers = ['urlencoded', 'json', 'utf8'];
+  var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+  var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+  var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+  var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+  var interface = {
+    b64EncodeUnicode: b64EncodeUnicode,
+    checkSerializer: checkSerializer,
+    checkSSLCertMode: checkSSLCertMode,
+    checkClientAuthMode: checkClientAuthMode,
+    checkClientAuthOptions: checkClientAuthOptions,
+    checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+    checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+    checkTimeoutValue: checkTimeoutValue,
+    checkFollowRedirectValue: checkFollowRedirectValue,
+    injectCookieHandler: injectCookieHandler,
+    injectRawResponseHandler: injectRawResponseHandler,
+    injectFileEntryHandler: injectFileEntryHandler,
+    getMergedHeaders: getMergedHeaders,
+    getProcessedData: getProcessedData,
+    handleMissingCallbacks: handleMissingCallbacks,
+    handleMissingOptions: handleMissingOptions
+  };
+
+  // expose all functions for testing purposes
+  if (init.debug) {
+    interface.mergeHeaders = mergeHeaders;
+    interface.checkForValidStringValue = checkForValidStringValue;
+    interface.checkKeyValuePairObject = checkKeyValuePairObject;
+    interface.checkHttpMethod = checkHttpMethod;
+    interface.checkResponseType = checkResponseType;
+    interface.checkHeadersObject = checkHeadersObject;
+    interface.checkParamsObject = checkParamsObject;
+    interface.resolveCookieString = resolveCookieString;
+    interface.createFileEntry = createFileEntry;
+    interface.getCookieHeader = getCookieHeader;
+    interface.getMatchingHostHeaders = getMatchingHostHeaders;
+    interface.getAllowedDataTypes = getAllowedDataTypes;
+  }
+
+  return interface;
+
+  // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+  function b64EncodeUnicode(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode('0x' + p1);
+    }));
+  }
+
+  function mergeHeaders(globalHeaders, localHeaders) {
+    var globalKeys = Object.keys(globalHeaders);
+    var key;
+
+    for (var i = 0; i < globalKeys.length; i++) {
+      key = globalKeys[i];
+
+      if (!localHeaders.hasOwnProperty(key)) {
+        localHeaders[key] = globalHeaders[key];
+      }
+    }
+
+    return localHeaders;
+  }
+
+  function checkForValidStringValue(list, value, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    value = value.trim().toLowerCase();
+
+    if (list.indexOf(value) === -1) {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    return value;
+  }
+
+  function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(obj) !== 'Object') {
+      throw new Error(onInvalidValueMessage);
+    }
+
+    var keys = Object.keys(obj);
+
+    for (var i = 0; i < keys.length; i++) {
+      if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+        throw new Error(onInvalidValueMessage);
+      }
+    }
+
+    return obj;
+  }
+
+  function checkHttpMethod(method) {
+    return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+  }
+
+  function checkResponseType(type) {
+    return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+  }
+
+  function checkSerializer(serializer) {
+    return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+  }
+
+  function checkSSLCertMode(mode) {
+    return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+  }
+
+  function checkClientAuthMode(mode) {
+    return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+  }
+
+  function checkClientAuthOptions(mode, options) {
+    options = options || {};
+
+    // none
+    if (mode === validClientAuthModes[0]) {
+      return {
+        alias: null,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    if (jsUtil.getTypeOf(options) !== 'Object') {
+      throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+    }
+
+    // systemstore
+    if (mode === validClientAuthModes[1]) {
+      if (jsUtil.getTypeOf(options.alias) !== 'String'
+        && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+      }
+
+      return {
+        alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    // buffer
+    if (mode === validClientAuthModes[2]) {
+      if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+      }
+
+      if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+      }
+
+      return {
+        alias: null,
+        rawPkcs: options.rawPkcs,
+        pkcsPassword: options.pkcsPassword
+      }
+    }
+  }
+
+  function checkForBlacklistedHeaderKey(key) {
+    if (key.toLowerCase() === 'cookie') {
+      throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+    }
+
+    return key;
+  }
+
+  function checkForInvalidHeaderValue(value) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(messages.INVALID_HEADERS_VALUE);
+    }
+
+    return value;
+  }
+
+  function checkTimeoutValue(timeout) {
+    if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+      throw new Error(messages.INVALID_TIMEOUT_VALUE);
+    }
+
+    return timeout;
+  }
+
+  function checkFollowRedirectValue(follow) {
+    if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+      throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+    }
+
+    return follow;
+  }
+
+  function checkHeadersObject(headers) {
+    return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+  }
+
+  function checkParamsObject(params) {
+    return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+  }
+
+  function resolveCookieString(headers) {
+    var keys = Object.keys(headers || {});
+
+    for (var i = 0; i < keys.length; ++i) {
+      if (keys[i].match(/^set-cookie$/i)) {
+        return headers[keys[i]];
+      }
+    }
+
+    return null;
+  }
+
+  function createFileEntry(rawEntry) {
+    var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+    entry.isDirectory = rawEntry.isDirectory;
+    entry.isFile = rawEntry.isFile;
+    entry.name = rawEntry.name;
+    entry.fullPath = rawEntry.fullPath;
+    entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+    entry.nativeURL = rawEntry.nativeURL;
+
+    return entry;
+  }
+
+  function injectCookieHandler(url, cb) {
+    return function (response) {
+      cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+      cb(response);
+    }
+  }
+
+  function injectRawResponseHandler(responseType, cb) {
+    return function (response) {
+      var dataType = jsUtil.getTypeOf(response.data);
+
+      // don't need post-processing if it's already binary type (on browser platform)
+      if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+        return cb(response);
+      }
+
+      // arraybuffer
+      if (responseType === validResponseTypes[1]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        response.data = buffer;
+      }
+
+      // blob
+      if (responseType === validResponseTypes[2]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        var type = response.headers['content-type'] || '';
+        var blob = new Blob([ buffer ], { type: type });
+        response.data = blob;
+      }
+
+      cb(response);
+    }
+  }
+
+  function injectFileEntryHandler(cb) {
+    return function (response) {
+      cb(createFileEntry(response.file));
+    }
+  }
+
+  function getCookieHeader(url) {
+    var cookieString = cookieHandler.getCookieString(url);
+
+    if (cookieString.length) {
+      return { Cookie: cookieHandler.getCookieString(url) };
+    }
+
+    return {};
+  }
+
+  function getMatchingHostHeaders(url, headersList) {
+    var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+    var domain = matches && matches[1];
+
+    return headersList[domain] || null;
+  }
+
+  function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+    var globalHeaders = predefinedHeaders['*'] || {};
+    var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+    var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+    mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+    mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+    return mergedHeaders;
+  }
+
+  function getAllowedDataTypes(dataSerializer) {
+    switch (dataSerializer) {
+      case 'utf8':
+        return ['String'];
+      case 'urlencoded':
+        return ['Object'];
+      default:
+        return ['Array', 'Object'];
+    }
+  }
+
+  function getProcessedData(data, dataSerializer) {
+    var currentDataType = jsUtil.getTypeOf(data);
+    var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+    if (allowedDataTypes.indexOf(currentDataType) === -1) {
+      throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+    }
+
+    if (dataSerializer === 'utf8') {
+      data = { text: data };
+    }
+
+    return data;
+  }
+
+  function handleMissingCallbacks(successFn, failFn) {
+    if (jsUtil.getTypeOf(successFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_SUCCESS);
+    }
+
+    if (jsUtil.getTypeOf(failFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_FAIL);
+    }
+  }
+
+  function handleMissingOptions(options, globals) {
+    options = options || {};
+
+    return {
+      method: checkHttpMethod(options.method || validHttpMethods[0]),
+      responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+      serializer: checkSerializer(options.serializer || globals.serializer),
+      timeout: checkTimeoutValue(options.timeout || globals.timeout),
+      followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+      headers: checkHeadersObject(options.headers || {}),
+      params: checkParamsObject(options.params || {}),
+      data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+      filePath: options.filePath || '',
+      name: options.name || ''
+    };
+  }
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..cbe1c51
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) {
+module.exports = {
+  // typeof is not working reliably in JS
+  getTypeOf: function (object) {
+    switch (Object.prototype.toString.call(object)) {
+      case '[object Array]':
+        return 'Array';
+      case '[object Blob]':
+        return 'Blob';
+      case '[object ArrayBuffer]':
+        return 'ArrayBuffer';
+      case '[object Boolean]':
+        return 'Boolean';
+      case '[object Function]':
+        return 'Function';
+      case '[object Null]':
+        return 'Null';
+      case '[object Number]':
+        return 'Number';
+      case '[object Object]':
+        return 'Object';
+      case '[object String]':
+        return 'String';
+      case '[object Undefined]':
+        return 'Undefined';
+      default:
+        return 'Unknown';
+    }
+  }
+}
+
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..800c6b7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,184 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) {
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+  function WebStorageCookieStore(storage, storeKey) {
+    ToughCookie.Store.call(this);
+    this._storage = storage;
+    this._storeKey = storeKey || '__cookieStore__';
+    this.synchronous = true;
+  }
+
+  WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+  WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+    var cookie = _.get(store, [domain, path, key], null);
+
+    callback(null, ToughCookie.Cookie.fromJSON(cookie));
+  };
+
+  WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+    if (!domain) {
+      callback(null, []);
+      return;
+    }
+
+    var that = this;
+    var cookies = [];
+    var store = this._readStore();
+    var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+    domains.forEach(function (domain) {
+      if (!store[domain]) {
+        return;
+      }
+
+      var matchingPaths = Object.keys(store[domain]);
+
+      if (path != null) {
+        matchingPaths = matchingPaths.filter(function (cookiePath) {
+          return that._isOnPath(cookiePath, path);
+        });
+      }
+
+      matchingPaths.forEach(function (path) {
+        Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    callback(null, cookies);
+  };
+
+  /**
+   * Returns whether `cookiePath` is on the given `urlPath`
+   */
+  WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+    if (!cookiePath) {
+      return false;
+    }
+
+    if (cookiePath === urlPath) {
+      return true;
+    }
+
+    if (urlPath.indexOf(cookiePath) !== 0) {
+      return false;
+    }
+
+    if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+      return false;
+    }
+
+    return true;
+  };
+
+  WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+    var store = this._readStore();
+
+    _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+    this.putCookie(newCookie, callback);
+  };
+
+
+  WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+
+    _.unset(store, [domain, path, key]);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+    var store = this._readStore();
+
+    if (path == null) {
+      _.unset(store, [domain]);
+    } else {
+      _.unset(store, [domain, path]);
+    }
+
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+    var cookies = [];
+    var store = this._readStore();
+
+    Object.keys(store).forEach(function (domain) {
+      Object.keys(store[domain]).forEach(function (path) {
+        Array.protype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    cookies.sort(function (c1, c2) {
+      return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+    });
+
+    callback(null, cookies);
+  };
+
+  WebStorageCookieStore.prototype._readStore = function () {
+    var json = this._storage.getItem(this._storeKey);
+
+    if (json !== null) {
+      try {
+        return JSON.parse(json);
+      } catch (e) { }
+    }
+
+    return {};
+  };
+
+  WebStorageCookieStore.prototype._writeStore = function (store) {
+    this._storage.setItem(this._storeKey, JSON.stringify(store));
+  };
+
+  return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..f35be77
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) {
+/**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..13efb2b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) {
+module.exports = {
+  ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+  DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+  INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+  INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+  INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+  INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+  INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+  INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+  INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+  INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+  INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+  INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+  INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+  INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+  INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+  MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+  MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a77c8e0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,202 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) {
+module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+  const publicInterface = {
+    getBasicAuthHeader: getBasicAuthHeader,
+    useBasicAuth: useBasicAuth,
+    getHeaders: getHeaders,
+    setHeader: setHeader,
+    getDataSerializer: getDataSerializer,
+    setDataSerializer: setDataSerializer,
+    setCookie: setCookie,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies,
+    getCookieString: getCookieString,
+    getRequestTimeout: getRequestTimeout,
+    setRequestTimeout: setRequestTimeout,
+    getFollowRedirect: getFollowRedirect,
+    setFollowRedirect: setFollowRedirect,
+    // @DEPRECATED
+    disableRedirect: disableRedirect,
+    // @DEPRECATED
+    setSSLCertMode: setServerTrustMode,
+    setServerTrustMode: setServerTrustMode,
+    setClientAuthMode: setClientAuthMode,
+    sendRequest: sendRequest,
+    post: post,
+    get: get,
+    put: put,
+    patch: patch,
+    delete: del,
+    head: head,
+    uploadFile: uploadFile,
+    downloadFile: downloadFile
+  };
+
+  function getBasicAuthHeader(username, password) {
+    return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+  }
+
+  function useBasicAuth(username, password) {
+    this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+  }
+
+  function getHeaders(host) {
+    return globalConfigs.headers[host || '*'] || null;
+  }
+
+  function setHeader() {
+    // this one is for being backward compatible
+    var host = '*';
+    var header = arguments[0];
+    var value = arguments[1];
+
+    if (arguments.length === 3) {
+      host = arguments[0];
+      header = arguments[1];
+      value = arguments[2];
+    }
+
+    helpers.checkForBlacklistedHeaderKey(header);
+    helpers.checkForInvalidHeaderValue(value);
+
+    globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+    globalConfigs.headers[host][header] = value;
+  }
+
+  function getDataSerializer() {
+    return globalConfigs.serializer;
+  }
+
+  function setDataSerializer(serializer) {
+    globalConfigs.serializer = helpers.checkSerializer(serializer);
+  }
+
+  function setCookie(url, cookie, options) {
+    cookieHandler.setCookie(url, cookie, options);
+  }
+
+  function clearCookies() {
+    cookieHandler.clearCookies();
+  }
+
+  function removeCookies(url, callback) {
+    cookieHandler.removeCookies(url, callback);
+  }
+
+  function getCookieString(url) {
+    return cookieHandler.getCookieString(url);
+  }
+
+  function getRequestTimeout() {
+    return globalConfigs.timeout;
+  }
+
+  function setRequestTimeout(timeout) {
+    globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+  }
+
+  function getFollowRedirect() {
+    return globalConfigs.followRedirect;
+  }
+
+  function setFollowRedirect(follow) {
+    globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+  }
+
+  // @DEPRECATED
+  function disableRedirect(disable, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    setFollowRedirect(!disable);
+    success();
+  }
+
+  function setServerTrustMode(mode, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+  }
+
+  function setClientAuthMode() {
+    var mode = arguments[0];
+    var options = null;
+    var success = arguments[1];
+    var failure = arguments[2];
+
+    if (arguments.length === 4) {
+      options = arguments[1];
+      success = arguments[2];
+      failure = arguments[3];
+    }
+
+    mode = helpers.checkClientAuthMode(mode);
+    options = helpers.checkClientAuthOptions(mode, options);
+
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+  }
+
+  function sendRequest(url, options, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    options = helpers.handleMissingOptions(options, globalConfigs);
+    url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+    var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+    var onFail = helpers.injectCookieHandler(url, failure);
+    var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+    switch (options.method) {
+      case 'post':
+      case 'put':
+      case 'patch':
+        var data = helpers.getProcessedData(options.data, options.serializer);
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+      case 'upload':
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+      case 'download':
+        var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+        return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+      default:
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+    }
+  }
+
+  function post(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+  };
+
+  function get(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+  };
+
+  function put(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+  }
+
+  function patch(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+  }
+
+  function del(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+  }
+
+  function head(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+  }
+
+  function uploadFile(url, params, headers, filePath, name, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+  }
+
+  function downloadFile(url, params, headers, filePath, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+  }
+
+  return publicInterface;
+}
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..bd8ab68
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5091 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) {
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["ToughCookie"] = factory();
+	else
+		root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var net = __webpack_require__(1);
+	var urlParse = __webpack_require__(2).parse;
+	var util = __webpack_require__(9);
+	var pubsuffix = __webpack_require__(13);
+	var Store = __webpack_require__(17).Store;
+	var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var VERSION = __webpack_require__(21).version;
+
+	var punycode;
+	try {
+	  punycode = __webpack_require__(15);
+	} catch(e) {
+	  console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+	}
+
+	// From RFC6265 S4.1.1
+	// note that it excludes \x3B ";"
+	var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+	var CONTROL_CHARS = /[\x00-\x1F]/;
+
+	// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+	// the "relaxed" mode, see:
+	// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+	var TERMINATORS = ['\n', '\r', '\0'];
+
+	// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+	// Note ';' is \x3B
+	var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+	// date-time parsing constants (RFC6265 S5.1.1)
+
+	var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+	var MONTH_TO_NUM = {
+	  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+	  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+	};
+	var NUM_TO_MONTH = [
+	  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+	];
+	var NUM_TO_DAY = [
+	  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+	];
+
+	var MAX_TIME = 2147483647000; // 31-bit max
+	var MIN_TIME = 0; // 31-bit min
+
+	/*
+	 * Parses a Natural number (i.e., non-negative integer) with either the
+	 *    <min>*<max>DIGIT ( non-digit *OCTET )
+	 * or
+	 *    <min>*<max>DIGIT
+	 * grammar (RFC6265 S5.1.1).
+	 *
+	 * The "trailingOK" boolean controls if the grammar accepts a
+	 * "( non-digit *OCTET )" trailer.
+	 */
+	function parseDigits(token, minDigits, maxDigits, trailingOK) {
+	  var count = 0;
+	  while (count < token.length) {
+	    var c = token.charCodeAt(count);
+	    // "non-digit = %x00-2F / %x3A-FF"
+	    if (c <= 0x2F || c >= 0x3A) {
+	      break;
+	    }
+	    count++;
+	  }
+
+	  // constrain to a minimum and maximum number of digits.
+	  if (count < minDigits || count > maxDigits) {
+	    return null;
+	  }
+
+	  if (!trailingOK && count != token.length) {
+	    return null;
+	  }
+
+	  return parseInt(token.substr(0,count), 10);
+	}
+
+	function parseTime(token) {
+	  var parts = token.split(':');
+	  var result = [0,0,0];
+
+	  /* RF6256 S5.1.1:
+	   *      time            = hms-time ( non-digit *OCTET )
+	   *      hms-time        = time-field ":" time-field ":" time-field
+	   *      time-field      = 1*2DIGIT
+	   */
+
+	  if (parts.length !== 3) {
+	    return null;
+	  }
+
+	  for (var i = 0; i < 3; i++) {
+	    // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+	    // followed by "( non-digit *OCTET )" so therefore the last time-field can
+	    // have a trailer
+	    var trailingOK = (i == 2);
+	    var num = parseDigits(parts[i], 1, 2, trailingOK);
+	    if (num === null) {
+	      return null;
+	    }
+	    result[i] = num;
+	  }
+
+	  return result;
+	}
+
+	function parseMonth(token) {
+	  token = String(token).substr(0,3).toLowerCase();
+	  var num = MONTH_TO_NUM[token];
+	  return num >= 0 ? num : null;
+	}
+
+	/*
+	 * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+	 */
+	function parseDate(str) {
+	  if (!str) {
+	    return;
+	  }
+
+	  /* RFC6265 S5.1.1:
+	   * 2. Process each date-token sequentially in the order the date-tokens
+	   * appear in the cookie-date
+	   */
+	  var tokens = str.split(DATE_DELIM);
+	  if (!tokens) {
+	    return;
+	  }
+
+	  var hour = null;
+	  var minute = null;
+	  var second = null;
+	  var dayOfMonth = null;
+	  var month = null;
+	  var year = null;
+
+	  for (var i=0; i<tokens.length; i++) {
+	    var token = tokens[i].trim();
+	    if (!token.length) {
+	      continue;
+	    }
+
+	    var result;
+
+	    /* 2.1. If the found-time flag is not set and the token matches the time
+	     * production, set the found-time flag and set the hour- value,
+	     * minute-value, and second-value to the numbers denoted by the digits in
+	     * the date-token, respectively.  Skip the remaining sub-steps and continue
+	     * to the next date-token.
+	     */
+	    if (second === null) {
+	      result = parseTime(token);
+	      if (result) {
+	        hour = result[0];
+	        minute = result[1];
+	        second = result[2];
+	        continue;
+	      }
+	    }
+
+	    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+	     * the day-of-month production, set the found-day-of- month flag and set
+	     * the day-of-month-value to the number denoted by the date-token.  Skip
+	     * the remaining sub-steps and continue to the next date-token.
+	     */
+	    if (dayOfMonth === null) {
+	      // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 1, 2, true);
+	      if (result !== null) {
+	        dayOfMonth = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.3. If the found-month flag is not set and the date-token matches the
+	     * month production, set the found-month flag and set the month-value to
+	     * the month denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (month === null) {
+	      result = parseMonth(token);
+	      if (result !== null) {
+	        month = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.4. If the found-year flag is not set and the date-token matches the
+	     * year production, set the found-year flag and set the year-value to the
+	     * number denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (year === null) {
+	      // "year = 2*4DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 2, 4, true);
+	      if (result !== null) {
+	        year = result;
+	        /* From S5.1.1:
+	         * 3.  If the year-value is greater than or equal to 70 and less
+	         * than or equal to 99, increment the year-value by 1900.
+	         * 4.  If the year-value is greater than or equal to 0 and less
+	         * than or equal to 69, increment the year-value by 2000.
+	         */
+	        if (year >= 70 && year <= 99) {
+	          year += 1900;
+	        } else if (year >= 0 && year <= 69) {
+	          year += 2000;
+	        }
+	      }
+	    }
+	  }
+
+	  /* RFC 6265 S5.1.1
+	   * "5. Abort these steps and fail to parse the cookie-date if:
+	   *     *  at least one of the found-day-of-month, found-month, found-
+	   *        year, or found-time flags is not set,
+	   *     *  the day-of-month-value is less than 1 or greater than 31,
+	   *     *  the year-value is less than 1601,
+	   *     *  the hour-value is greater than 23,
+	   *     *  the minute-value is greater than 59, or
+	   *     *  the second-value is greater than 59.
+	   *     (Note that leap seconds cannot be represented in this syntax.)"
+	   *
+	   * So, in order as above:
+	   */
+	  if (
+	    dayOfMonth === null || month === null || year === null || second === null ||
+	    dayOfMonth < 1 || dayOfMonth > 31 ||
+	    year < 1601 ||
+	    hour > 23 ||
+	    minute > 59 ||
+	    second > 59
+	  ) {
+	    return;
+	  }
+
+	  return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+	}
+
+	function formatDate(date) {
+	  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+	  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+	  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+	  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+	  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+	    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+	    h+':'+m+':'+s+' GMT';
+	}
+
+	// S5.1.2 Canonicalized Host Names
+	function canonicalDomain(str) {
+	  if (str == null) {
+	    return null;
+	  }
+	  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+	  // convert to IDN if any non-ASCII characters
+	  if (punycode && /[^\u0001-\u007f]/.test(str)) {
+	    str = punycode.toASCII(str);
+	  }
+
+	  return str.toLowerCase();
+	}
+
+	// S5.1.3 Domain Matching
+	function domainMatch(str, domStr, canonicalize) {
+	  if (str == null || domStr == null) {
+	    return null;
+	  }
+	  if (canonicalize !== false) {
+	    str = canonicalDomain(str);
+	    domStr = canonicalDomain(domStr);
+	  }
+
+	  /*
+	   * "The domain string and the string are identical. (Note that both the
+	   * domain string and the string will have been canonicalized to lower case at
+	   * this point)"
+	   */
+	  if (str == domStr) {
+	    return true;
+	  }
+
+	  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+	  /* "* The string is a host name (i.e., not an IP address)." */
+	  if (net.isIP(str)) {
+	    return false;
+	  }
+
+	  /* "* The domain string is a suffix of the string" */
+	  var idx = str.indexOf(domStr);
+	  if (idx <= 0) {
+	    return false; // it's a non-match (-1) or prefix (0)
+	  }
+
+	  // e.g "a.b.c".indexOf("b.c") === 2
+	  // 5 === 3+2
+	  if (str.length !== domStr.length + idx) { // it's not a suffix
+	    return false;
+	  }
+
+	  /* "* The last character of the string that is not included in the domain
+	  * string is a %x2E (".") character." */
+	  if (str.substr(idx-1,1) !== '.') {
+	    return false;
+	  }
+
+	  return true;
+	}
+
+
+	// RFC6265 S5.1.4 Paths and Path-Match
+
+	/*
+	 * "The user agent MUST use an algorithm equivalent to the following algorithm
+	 * to compute the default-path of a cookie:"
+	 *
+	 * Assumption: the path (and not query part or absolute uri) is passed in.
+	 */
+	function defaultPath(path) {
+	  // "2. If the uri-path is empty or if the first character of the uri-path is not
+	  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+	  if (!path || path.substr(0,1) !== "/") {
+	    return "/";
+	  }
+
+	  // "3. If the uri-path contains no more than one %x2F ("/") character, output
+	  // %x2F ("/") and skip the remaining step."
+	  if (path === "/") {
+	    return path;
+	  }
+
+	  var rightSlash = path.lastIndexOf("/");
+	  if (rightSlash === 0) {
+	    return "/";
+	  }
+
+	  // "4. Output the characters of the uri-path from the first character up to,
+	  // but not including, the right-most %x2F ("/")."
+	  return path.slice(0, rightSlash);
+	}
+
+	function trimTerminator(str) {
+	  for (var t = 0; t < TERMINATORS.length; t++) {
+	    var terminatorIdx = str.indexOf(TERMINATORS[t]);
+	    if (terminatorIdx !== -1) {
+	      str = str.substr(0,terminatorIdx);
+	    }
+	  }
+
+	  return str;
+	}
+
+	function parseCookiePair(cookiePair, looseMode) {
+	  cookiePair = trimTerminator(cookiePair);
+
+	  var firstEq = cookiePair.indexOf('=');
+	  if (looseMode) {
+	    if (firstEq === 0) { // '=' is immediately at start
+	      cookiePair = cookiePair.substr(1);
+	      firstEq = cookiePair.indexOf('='); // might still need to split on '='
+	    }
+	  } else { // non-loose mode
+	    if (firstEq <= 0) { // no '=' or is at start
+	      return; // needs to have non-empty "cookie-name"
+	    }
+	  }
+
+	  var cookieName, cookieValue;
+	  if (firstEq <= 0) {
+	    cookieName = "";
+	    cookieValue = cookiePair.trim();
+	  } else {
+	    cookieName = cookiePair.substr(0, firstEq).trim();
+	    cookieValue = cookiePair.substr(firstEq+1).trim();
+	  }
+
+	  if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+	    return;
+	  }
+
+	  var c = new Cookie();
+	  c.key = cookieName;
+	  c.value = cookieValue;
+	  return c;
+	}
+
+	function parse(str, options) {
+	  if (!options || typeof options !== 'object') {
+	    options = {};
+	  }
+	  str = str.trim();
+
+	  // We use a regex to parse the "name-value-pair" part of S5.2
+	  var firstSemi = str.indexOf(';'); // S5.2 step 1
+	  var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+	  var c = parseCookiePair(cookiePair, !!options.loose);
+	  if (!c) {
+	    return;
+	  }
+
+	  if (firstSemi === -1) {
+	    return c;
+	  }
+
+	  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+	  // (including the %x3B (";") in question)." plus later on in the same section
+	  // "discard the first ";" and trim".
+	  var unparsed = str.slice(firstSemi + 1).trim();
+
+	  // "If the unparsed-attributes string is empty, skip the rest of these
+	  // steps."
+	  if (unparsed.length === 0) {
+	    return c;
+	  }
+
+	  /*
+	   * S5.2 says that when looping over the items "[p]rocess the attribute-name
+	   * and attribute-value according to the requirements in the following
+	   * subsections" for every item.  Plus, for many of the individual attributes
+	   * in S5.3 it says to use the "attribute-value of the last attribute in the
+	   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
+	   * the previous value.
+	   */
+	  var cookie_avs = unparsed.split(';');
+	  while (cookie_avs.length) {
+	    var av = cookie_avs.shift().trim();
+	    if (av.length === 0) { // happens if ";;" appears
+	      continue;
+	    }
+	    var av_sep = av.indexOf('=');
+	    var av_key, av_value;
+
+	    if (av_sep === -1) {
+	      av_key = av;
+	      av_value = null;
+	    } else {
+	      av_key = av.substr(0,av_sep);
+	      av_value = av.substr(av_sep+1);
+	    }
+
+	    av_key = av_key.trim().toLowerCase();
+
+	    if (av_value) {
+	      av_value = av_value.trim();
+	    }
+
+	    switch(av_key) {
+	    case 'expires': // S5.2.1
+	      if (av_value) {
+	        var exp = parseDate(av_value);
+	        // "If the attribute-value failed to parse as a cookie date, ignore the
+	        // cookie-av."
+	        if (exp) {
+	          // over and underflow not realistically a concern: V8's getTime() seems to
+	          // store something larger than a 32-bit time_t (even with 32-bit node)
+	          c.expires = exp;
+	        }
+	      }
+	      break;
+
+	    case 'max-age': // S5.2.2
+	      if (av_value) {
+	        // "If the first character of the attribute-value is not a DIGIT or a "-"
+	        // character ...[or]... If the remainder of attribute-value contains a
+	        // non-DIGIT character, ignore the cookie-av."
+	        if (/^-?[0-9]+$/.test(av_value)) {
+	          var delta = parseInt(av_value, 10);
+	          // "If delta-seconds is less than or equal to zero (0), let expiry-time
+	          // be the earliest representable date and time."
+	          c.setMaxAge(delta);
+	        }
+	      }
+	      break;
+
+	    case 'domain': // S5.2.3
+	      // "If the attribute-value is empty, the behavior is undefined.  However,
+	      // the user agent SHOULD ignore the cookie-av entirely."
+	      if (av_value) {
+	        // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+	        // (".") character."
+	        var domain = av_value.trim().replace(/^\./, '');
+	        if (domain) {
+	          // "Convert the cookie-domain to lower case."
+	          c.domain = domain.toLowerCase();
+	        }
+	      }
+	      break;
+
+	    case 'path': // S5.2.4
+	      /*
+	       * "If the attribute-value is empty or if the first character of the
+	       * attribute-value is not %x2F ("/"):
+	       *   Let cookie-path be the default-path.
+	       * Otherwise:
+	       *   Let cookie-path be the attribute-value."
+	       *
+	       * We'll represent the default-path as null since it depends on the
+	       * context of the parsing.
+	       */
+	      c.path = av_value && av_value[0] === "/" ? av_value : null;
+	      break;
+
+	    case 'secure': // S5.2.5
+	      /*
+	       * "If the attribute-name case-insensitively matches the string "Secure",
+	       * the user agent MUST append an attribute to the cookie-attribute-list
+	       * with an attribute-name of Secure and an empty attribute-value."
+	       */
+	      c.secure = true;
+	      break;
+
+	    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+	      c.httpOnly = true;
+	      break;
+
+	    default:
+	      c.extensions = c.extensions || [];
+	      c.extensions.push(av);
+	      break;
+	    }
+	  }
+
+	  return c;
+	}
+
+	// avoid the V8 deoptimization monster!
+	function jsonParse(str) {
+	  var obj;
+	  try {
+	    obj = JSON.parse(str);
+	  } catch (e) {
+	    return e;
+	  }
+	  return obj;
+	}
+
+	function fromJSON(str) {
+	  if (!str) {
+	    return null;
+	  }
+
+	  var obj;
+	  if (typeof str === 'string') {
+	    obj = jsonParse(str);
+	    if (obj instanceof Error) {
+	      return null;
+	    }
+	  } else {
+	    // assume it's an Object
+	    obj = str;
+	  }
+
+	  var c = new Cookie();
+	  for (var i=0; i<Cookie.serializableProperties.length; i++) {
+	    var prop = Cookie.serializableProperties[i];
+	    if (obj[prop] === undefined ||
+	        obj[prop] === Cookie.prototype[prop])
+	    {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (obj[prop] === null) {
+	        c[prop] = null;
+	      } else {
+	        c[prop] = obj[prop] == "Infinity" ?
+	          "Infinity" : new Date(obj[prop]);
+	      }
+	    } else {
+	      c[prop] = obj[prop];
+	    }
+	  }
+
+	  return c;
+	}
+
+	/* Section 5.4 part 2:
+	 * "*  Cookies with longer paths are listed before cookies with
+	 *     shorter paths.
+	 *
+	 *  *  Among cookies that have equal-length path fields, cookies with
+	 *     earlier creation-times are listed before cookies with later
+	 *     creation-times."
+	 */
+
+	function cookieCompare(a,b) {
+	  var cmp = 0;
+
+	  // descending for length: b CMP a
+	  var aPathLen = a.path ? a.path.length : 0;
+	  var bPathLen = b.path ? b.path.length : 0;
+	  cmp = bPathLen - aPathLen;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // ascending for time: a CMP b
+	  var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+	  var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+	  cmp = aTime - bTime;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // break ties for the same millisecond (precision of JavaScript's clock)
+	  cmp = a.creationIndex - b.creationIndex;
+
+	  return cmp;
+	}
+
+	// Gives the permutation of all possible pathMatch()es of a given path. The
+	// array is in longest-to-shortest order.  Handy for indexing.
+	function permutePath(path) {
+	  if (path === '/') {
+	    return ['/'];
+	  }
+	  if (path.lastIndexOf('/') === path.length-1) {
+	    path = path.substr(0,path.length-1);
+	  }
+	  var permutations = [path];
+	  while (path.length > 1) {
+	    var lindex = path.lastIndexOf('/');
+	    if (lindex === 0) {
+	      break;
+	    }
+	    path = path.substr(0,lindex);
+	    permutations.push(path);
+	  }
+	  permutations.push('/');
+	  return permutations;
+	}
+
+	function getCookieContext(url) {
+	  if (url instanceof Object) {
+	    return url;
+	  }
+	  // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+	  // Therefore, we will just skip decoding for such URIs.
+	  try {
+	    url = decodeURI(url);
+	  }
+	  catch(err) {
+	    // Silently swallow error
+	  }
+
+	  return urlParse(url);
+	}
+
+	function Cookie(options) {
+	  options = options || {};
+
+	  Object.keys(options).forEach(function(prop) {
+	    if (Cookie.prototype.hasOwnProperty(prop) &&
+	        Cookie.prototype[prop] !== options[prop] &&
+	        prop.substr(0,1) !== '_')
+	    {
+	      this[prop] = options[prop];
+	    }
+	  }, this);
+
+	  this.creation = this.creation || new Date();
+
+	  // used to break creation ties in cookieCompare():
+	  Object.defineProperty(this, 'creationIndex', {
+	    configurable: false,
+	    enumerable: false, // important for assert.deepEqual checks
+	    writable: true,
+	    value: ++Cookie.cookiesCreated
+	  });
+	}
+
+	Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+	Cookie.parse = parse;
+	Cookie.fromJSON = fromJSON;
+
+	Cookie.prototype.key = "";
+	Cookie.prototype.value = "";
+
+	// the order in which the RFC has them:
+	Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+	Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+	Cookie.prototype.domain = null;
+	Cookie.prototype.path = null;
+	Cookie.prototype.secure = false;
+	Cookie.prototype.httpOnly = false;
+	Cookie.prototype.extensions = null;
+
+	// set by the CookieJar:
+	Cookie.prototype.hostOnly = null; // boolean when set
+	Cookie.prototype.pathIsDefault = null; // boolean when set
+	Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+	Cookie.prototype.lastAccessed = null; // Date when set
+	Object.defineProperty(Cookie.prototype, 'creationIndex', {
+	  configurable: true,
+	  enumerable: false,
+	  writable: true,
+	  value: 0
+	});
+
+	Cookie.serializableProperties = Object.keys(Cookie.prototype)
+	  .filter(function(prop) {
+	    return !(
+	      Cookie.prototype[prop] instanceof Function ||
+	      prop === 'creationIndex' ||
+	      prop.substr(0,1) === '_'
+	    );
+	  });
+
+	Cookie.prototype.inspect = function inspect() {
+	  var now = Date.now();
+	  return 'Cookie="'+this.toString() +
+	    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+	    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+	    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+	    '"';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+	}
+
+	Cookie.prototype.toJSON = function() {
+	  var obj = {};
+
+	  var props = Cookie.serializableProperties;
+	  for (var i=0; i<props.length; i++) {
+	    var prop = props[i];
+	    if (this[prop] === Cookie.prototype[prop]) {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (this[prop] === null) {
+	        obj[prop] = null;
+	      } else {
+	        obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+	          "Infinity" : this[prop].toISOString();
+	      }
+	    } else if (prop === 'maxAge') {
+	      if (this[prop] !== null) {
+	        // again, intentionally not ===
+	        obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+	          this[prop].toString() : this[prop];
+	      }
+	    } else {
+	      if (this[prop] !== Cookie.prototype[prop]) {
+	        obj[prop] = this[prop];
+	      }
+	    }
+	  }
+
+	  return obj;
+	};
+
+	Cookie.prototype.clone = function() {
+	  return fromJSON(this.toJSON());
+	};
+
+	Cookie.prototype.validate = function validate() {
+	  if (!COOKIE_OCTETS.test(this.value)) {
+	    return false;
+	  }
+	  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+	    return false;
+	  }
+	  if (this.maxAge != null && this.maxAge <= 0) {
+	    return false; // "Max-Age=" non-zero-digit *DIGIT
+	  }
+	  if (this.path != null && !PATH_VALUE.test(this.path)) {
+	    return false;
+	  }
+
+	  var cdomain = this.cdomain();
+	  if (cdomain) {
+	    if (cdomain.match(/\.$/)) {
+	      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+	    }
+	    var suffix = pubsuffix.getPublicSuffix(cdomain);
+	    if (suffix == null) { // it's a public suffix
+	      return false;
+	    }
+	  }
+	  return true;
+	};
+
+	Cookie.prototype.setExpires = function setExpires(exp) {
+	  if (exp instanceof Date) {
+	    this.expires = exp;
+	  } else {
+	    this.expires = parseDate(exp) || "Infinity";
+	  }
+	};
+
+	Cookie.prototype.setMaxAge = function setMaxAge(age) {
+	  if (age === Infinity || age === -Infinity) {
+	    this.maxAge = age.toString(); // so JSON.stringify() works
+	  } else {
+	    this.maxAge = age;
+	  }
+	};
+
+	// gives Cookie header format
+	Cookie.prototype.cookieString = function cookieString() {
+	  var val = this.value;
+	  if (val == null) {
+	    val = '';
+	  }
+	  if (this.key === '') {
+	    return val;
+	  }
+	  return this.key+'='+val;
+	};
+
+	// gives Set-Cookie header format
+	Cookie.prototype.toString = function toString() {
+	  var str = this.cookieString();
+
+	  if (this.expires != Infinity) {
+	    if (this.expires instanceof Date) {
+	      str += '; Expires='+formatDate(this.expires);
+	    } else {
+	      str += '; Expires='+this.expires;
+	    }
+	  }
+
+	  if (this.maxAge != null && this.maxAge != Infinity) {
+	    str += '; Max-Age='+this.maxAge;
+	  }
+
+	  if (this.domain && !this.hostOnly) {
+	    str += '; Domain='+this.domain;
+	  }
+	  if (this.path) {
+	    str += '; Path='+this.path;
+	  }
+
+	  if (this.secure) {
+	    str += '; Secure';
+	  }
+	  if (this.httpOnly) {
+	    str += '; HttpOnly';
+	  }
+	  if (this.extensions) {
+	    this.extensions.forEach(function(ext) {
+	      str += '; '+ext;
+	    });
+	  }
+
+	  return str;
+	};
+
+	// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	// S5.3 says to give the "latest representable date" for which we use Infinity
+	// For "expired" we use 0
+	Cookie.prototype.TTL = function TTL(now) {
+	  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+	   * attribute, the Max-Age attribute has precedence and controls the
+	   * expiration date of the cookie.
+	   * (Concurs with S5.3 step 3)
+	   */
+	  if (this.maxAge != null) {
+	    return this.maxAge<=0 ? 0 : this.maxAge*1000;
+	  }
+
+	  var expires = this.expires;
+	  if (expires != Infinity) {
+	    if (!(expires instanceof Date)) {
+	      expires = parseDate(expires) || Infinity;
+	    }
+
+	    if (expires == Infinity) {
+	      return Infinity;
+	    }
+
+	    return expires.getTime() - (now || Date.now());
+	  }
+
+	  return Infinity;
+	};
+
+	// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	Cookie.prototype.expiryTime = function expiryTime(now) {
+	  if (this.maxAge != null) {
+	    var relativeTo = now || this.creation || new Date();
+	    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+	    return relativeTo.getTime() + age;
+	  }
+
+	  if (this.expires == Infinity) {
+	    return Infinity;
+	  }
+	  return this.expires.getTime();
+	};
+
+	// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere), except it returns a Date
+	Cookie.prototype.expiryDate = function expiryDate(now) {
+	  var millisec = this.expiryTime(now);
+	  if (millisec == Infinity) {
+	    return new Date(MAX_TIME);
+	  } else if (millisec == -Infinity) {
+	    return new Date(MIN_TIME);
+	  } else {
+	    return new Date(millisec);
+	  }
+	};
+
+	// This replaces the "persistent-flag" parts of S5.3 step 3
+	Cookie.prototype.isPersistent = function isPersistent() {
+	  return (this.maxAge != null || this.expires != Infinity);
+	};
+
+	// Mostly S5.1.2 and S5.2.3:
+	Cookie.prototype.cdomain =
+	Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+	  if (this.domain == null) {
+	    return null;
+	  }
+	  return canonicalDomain(this.domain);
+	};
+
+	function CookieJar(store, options) {
+	  if (typeof options === "boolean") {
+	    options = {rejectPublicSuffixes: options};
+	  } else if (options == null) {
+	    options = {};
+	  }
+	  if (options.rejectPublicSuffixes != null) {
+	    this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+	  }
+	  if (options.looseMode != null) {
+	    this.enableLooseMode = options.looseMode;
+	  }
+
+	  if (!store) {
+	    store = new MemoryCookieStore();
+	  }
+	  this.store = store;
+	}
+	CookieJar.prototype.store = null;
+	CookieJar.prototype.rejectPublicSuffixes = true;
+	CookieJar.prototype.enableLooseMode = false;
+	var CAN_BE_SYNC = [];
+
+	CAN_BE_SYNC.push('setCookie');
+	CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+	  var err;
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var loose = this.enableLooseMode;
+	  if (options.loose != null) {
+	    loose = options.loose;
+	  }
+
+	  // S5.3 step 1
+	  if (!(cookie instanceof Cookie)) {
+	    cookie = Cookie.parse(cookie, { loose: loose });
+	  }
+	  if (!cookie) {
+	    err = new Error("Cookie failed to parse");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  // S5.3 step 2
+	  var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+	  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+	  // S5.3 step 4: NOOP; domain is null by default
+
+	  // S5.3 step 5: public suffixes
+	  if (this.rejectPublicSuffixes && cookie.domain) {
+	    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+	    if (suffix == null) { // e.g. "com"
+	      err = new Error("Cookie has domain set to a public suffix");
+	      return cb(options.ignoreError ? null : err);
+	    }
+	  }
+
+	  // S5.3 step 6:
+	  if (cookie.domain) {
+	    if (!domainMatch(host, cookie.cdomain(), false)) {
+	      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+	      return cb(options.ignoreError ? null : err);
+	    }
+
+	    if (cookie.hostOnly == null) { // don't reset if already set
+	      cookie.hostOnly = false;
+	    }
+
+	  } else {
+	    cookie.hostOnly = true;
+	    cookie.domain = host;
+	  }
+
+	  //S5.2.4 If the attribute-value is empty or if the first character of the
+	  //attribute-value is not %x2F ("/"):
+	  //Let cookie-path be the default-path.
+	  if (!cookie.path || cookie.path[0] !== '/') {
+	    cookie.path = defaultPath(context.pathname);
+	    cookie.pathIsDefault = true;
+	  }
+
+	  // S5.3 step 8: NOOP; secure attribute
+	  // S5.3 step 9: NOOP; httpOnly attribute
+
+	  // S5.3 step 10
+	  if (options.http === false && cookie.httpOnly) {
+	    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  var store = this.store;
+
+	  if (!store.updateCookie) {
+	    store.updateCookie = function(oldCookie, newCookie, cb) {
+	      this.putCookie(newCookie, cb);
+	    };
+	  }
+
+	  function withCookie(err, oldCookie) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    var next = function(err) {
+	      if (err) {
+	        return cb(err);
+	      } else {
+	        cb(null, cookie);
+	      }
+	    };
+
+	    if (oldCookie) {
+	      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+	      // domain, and path as the newly created cookie:"
+	      if (options.http === false && oldCookie.httpOnly) { // step 11.2
+	        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+	        return cb(options.ignoreError ? null : err);
+	      }
+	      cookie.creation = oldCookie.creation; // step 11.3
+	      cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+	      cookie.lastAccessed = now;
+	      // Step 11.4 (delete cookie) is implied by just setting the new one:
+	      store.updateCookie(oldCookie, cookie, next); // step 12
+
+	    } else {
+	      cookie.creation = cookie.lastAccessed = now;
+	      store.putCookie(cookie, next); // step 12
+	    }
+	  }
+
+	  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+	};
+
+	// RFC6365 S5.4
+	CAN_BE_SYNC.push('getCookies');
+	CookieJar.prototype.getCookies = function(url, options, cb) {
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var path = context.pathname || '/';
+
+	  var secure = options.secure;
+	  if (secure == null && context.protocol &&
+	      (context.protocol == 'https:' || context.protocol == 'wss:'))
+	  {
+	    secure = true;
+	  }
+
+	  var http = options.http;
+	  if (http == null) {
+	    http = true;
+	  }
+
+	  var now = options.now || Date.now();
+	  var expireCheck = options.expire !== false;
+	  var allPaths = !!options.allPaths;
+	  var store = this.store;
+
+	  function matchingCookie(c) {
+	    // "Either:
+	    //   The cookie's host-only-flag is true and the canonicalized
+	    //   request-host is identical to the cookie's domain.
+	    // Or:
+	    //   The cookie's host-only-flag is false and the canonicalized
+	    //   request-host domain-matches the cookie's domain."
+	    if (c.hostOnly) {
+	      if (c.domain != host) {
+	        return false;
+	      }
+	    } else {
+	      if (!domainMatch(host, c.domain, false)) {
+	        return false;
+	      }
+	    }
+
+	    // "The request-uri's path path-matches the cookie's path."
+	    if (!allPaths && !pathMatch(path, c.path)) {
+	      return false;
+	    }
+
+	    // "If the cookie's secure-only-flag is true, then the request-uri's
+	    // scheme must denote a "secure" protocol"
+	    if (c.secure && !secure) {
+	      return false;
+	    }
+
+	    // "If the cookie's http-only-flag is true, then exclude the cookie if the
+	    // cookie-string is being generated for a "non-HTTP" API"
+	    if (c.httpOnly && !http) {
+	      return false;
+	    }
+
+	    // deferred from S5.3
+	    // non-RFC: allow retention of expired cookies by choice
+	    if (expireCheck && c.expiryTime() <= now) {
+	      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+	      return false;
+	    }
+
+	    return true;
+	  }
+
+	  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    cookies = cookies.filter(matchingCookie);
+
+	    // sorting of S5.4 part 2
+	    if (options.sort !== false) {
+	      cookies = cookies.sort(cookieCompare);
+	    }
+
+	    // S5.4 part 3
+	    var now = new Date();
+	    cookies.forEach(function(c) {
+	      c.lastAccessed = now;
+	    });
+	    // TODO persist lastAccessed
+
+	    cb(null,cookies);
+	  });
+	};
+
+	CAN_BE_SYNC.push('getCookieString');
+	CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies
+	        .sort(cookieCompare)
+	        .map(function(c){
+	          return c.cookieString();
+	        })
+	        .join('; '));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('getSetCookieStrings');
+	CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies.map(function(c){
+	        return c.toString();
+	      }));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('serialize');
+	CookieJar.prototype.serialize = function(cb) {
+	  var type = this.store.constructor.name;
+	  if (type === 'Object') {
+	    type = null;
+	  }
+
+	  // update README.md "Serialization Format" if you change this, please!
+	  var serialized = {
+	    // The version of tough-cookie that serialized this jar. Generally a good
+	    // practice since future versions can make data import decisions based on
+	    // known past behavior. When/if this matters, use `semver`.
+	    version: 'tough-cookie@'+VERSION,
+
+	    // add the store type, to make humans happy:
+	    storeType: type,
+
+	    // CookieJar configuration:
+	    rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+	    // this gets filled from getAllCookies:
+	    cookies: []
+	  };
+
+	  if (!(this.store.getAllCookies &&
+	        typeof this.store.getAllCookies === 'function'))
+	  {
+	    return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+	  }
+
+	  this.store.getAllCookies(function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    serialized.cookies = cookies.map(function(cookie) {
+	      // convert to serialized 'raw' cookies
+	      cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+	      // Remove the index so new ones get assigned during deserialization
+	      delete cookie.creationIndex;
+
+	      return cookie;
+	    });
+
+	    return cb(null, serialized);
+	  });
+	};
+
+	// well-known name that JSON.stringify calls
+	CookieJar.prototype.toJSON = function() {
+	  return this.serializeSync();
+	};
+
+	// use the class method CookieJar.deserialize instead of calling this directly
+	CAN_BE_SYNC.push('_importCookies');
+	CookieJar.prototype._importCookies = function(serialized, cb) {
+	  var jar = this;
+	  var cookies = serialized.cookies;
+	  if (!cookies || !Array.isArray(cookies)) {
+	    return cb(new Error('serialized jar has no cookies array'));
+	  }
+	  cookies = cookies.slice(); // do not modify the original
+
+	  function putNext(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    if (!cookies.length) {
+	      return cb(err, jar);
+	    }
+
+	    var cookie;
+	    try {
+	      cookie = fromJSON(cookies.shift());
+	    } catch (e) {
+	      return cb(e);
+	    }
+
+	    if (cookie === null) {
+	      return putNext(null); // skip this cookie
+	    }
+
+	    jar.store.putCookie(cookie, putNext);
+	  }
+
+	  putNext();
+	};
+
+	CookieJar.deserialize = function(strOrObj, store, cb) {
+	  if (arguments.length !== 3) {
+	    // store is optional
+	    cb = store;
+	    store = null;
+	  }
+
+	  var serialized;
+	  if (typeof strOrObj === 'string') {
+	    serialized = jsonParse(strOrObj);
+	    if (serialized instanceof Error) {
+	      return cb(serialized);
+	    }
+	  } else {
+	    serialized = strOrObj;
+	  }
+
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+	  jar._importCookies(serialized, function(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    cb(null, jar);
+	  });
+	};
+
+	CookieJar.deserializeSync = function(strOrObj, store) {
+	  var serialized = typeof strOrObj === 'string' ?
+	    JSON.parse(strOrObj) : strOrObj;
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+	  // catch this mistake early:
+	  if (!jar.store.synchronous) {
+	    throw new Error('CookieJar store is not synchronous; use async API instead.');
+	  }
+
+	  jar._importCookiesSync(serialized);
+	  return jar;
+	};
+	CookieJar.fromJSON = CookieJar.deserializeSync;
+
+	CAN_BE_SYNC.push('clone');
+	CookieJar.prototype.clone = function(newStore, cb) {
+	  if (arguments.length === 1) {
+	    cb = newStore;
+	    newStore = null;
+	  }
+
+	  this.serialize(function(err,serialized) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    CookieJar.deserialize(newStore, serialized, cb);
+	  });
+	};
+
+	// Use a closure to provide a true imperative API for synchronous stores.
+	function syncWrap(method) {
+	  return function() {
+	    if (!this.store.synchronous) {
+	      throw new Error('CookieJar store is not synchronous; use async API instead.');
+	    }
+
+	    var args = Array.prototype.slice.call(arguments);
+	    var syncErr, syncResult;
+	    args.push(function syncCb(err, result) {
+	      syncErr = err;
+	      syncResult = result;
+	    });
+	    this[method].apply(this, args);
+
+	    if (syncErr) {
+	      throw syncErr;
+	    }
+	    return syncResult;
+	  };
+	}
+
+	// wrap all declared CAN_BE_SYNC methods in the sync wrapper
+	CAN_BE_SYNC.forEach(function(method) {
+	  CookieJar.prototype[method+'Sync'] = syncWrap(method);
+	});
+
+	exports.CookieJar = CookieJar;
+	exports.Cookie = Cookie;
+	exports.Store = Store;
+	exports.MemoryCookieStore = MemoryCookieStore;
+	exports.parseDate = parseDate;
+	exports.formatDate = formatDate;
+	exports.parse = parse;
+	exports.fromJSON = fromJSON;
+	exports.domainMatch = domainMatch;
+	exports.defaultPath = defaultPath;
+	exports.pathMatch = pathMatch;
+	exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+	exports.cookieCompare = cookieCompare;
+	exports.permuteDomain = __webpack_require__(19).permuteDomain;
+	exports.permutePath = permutePath;
+	exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+	/*
+	* Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+	* Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+	*/
+
+	var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+	var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+	function isIPv4(hostOrIp) {
+	  return hostOrIp.match(patternIPv4) ? true : false;
+	}
+
+	function isIPv6(hostOrIp) {
+	  return hostOrIp.match(patternIPv6) ? true : false;
+	}
+
+	function isIP(hostOrIp) {
+	  if (isIPv4(hostOrIp)) {
+	    return 4;
+	  }
+
+	  if (isIPv6(hostOrIp)) {
+	    return 6;
+	  }
+
+	  return 0;
+	}
+
+	module.exports = {
+	  isIPv4: isIPv4,
+	  isIPv6: isIPv6,
+	  isIP: isIP
+	};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var punycode = __webpack_require__(3);
+	var util = __webpack_require__(5);
+
+	exports.parse = urlParse;
+	exports.resolve = urlResolve;
+	exports.resolveObject = urlResolveObject;
+	exports.format = urlFormat;
+
+	exports.Url = Url;
+
+	function Url() {
+	  this.protocol = null;
+	  this.slashes = null;
+	  this.auth = null;
+	  this.host = null;
+	  this.port = null;
+	  this.hostname = null;
+	  this.hash = null;
+	  this.search = null;
+	  this.query = null;
+	  this.pathname = null;
+	  this.path = null;
+	  this.href = null;
+	}
+
+	// Reference: RFC 3986, RFC 1808, RFC 2396
+
+	// define these here so at least they only have to be
+	// compiled once on the first module load.
+	var protocolPattern = /^([a-z0-9.+-]+:)/i,
+	    portPattern = /:[0-9]*$/,
+
+	    // Special case for a simple path URL
+	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+	    // RFC 2396: characters reserved for delimiting URLs.
+	    // We actually just auto-escape these.
+	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+	    // RFC 2396: characters not allowed for various reasons.
+	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
+	    autoEscape = ['\''].concat(unwise),
+	    // Characters that are never ever allowed in a hostname.
+	    // Note that any invalid chars are also handled, but these
+	    // are the ones that are *expected* to be seen, so we fast-path
+	    // them.
+	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+	    hostEndingChars = ['/', '?', '#'],
+	    hostnameMaxLen = 255,
+	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+	    // protocols that can allow "unsafe" and "unwise" chars.
+	    unsafeProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that never have a hostname.
+	    hostlessProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that always contain a // bit.
+	    slashedProtocol = {
+	      'http': true,
+	      'https': true,
+	      'ftp': true,
+	      'gopher': true,
+	      'file': true,
+	      'http:': true,
+	      'https:': true,
+	      'ftp:': true,
+	      'gopher:': true,
+	      'file:': true
+	    },
+	    querystring = __webpack_require__(6);
+
+	function urlParse(url, parseQueryString, slashesDenoteHost) {
+	  if (url && util.isObject(url) && url instanceof Url) return url;
+
+	  var u = new Url;
+	  u.parse(url, parseQueryString, slashesDenoteHost);
+	  return u;
+	}
+
+	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+	  if (!util.isString(url)) {
+	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+	  }
+
+	  // Copy chrome, IE, opera backslash-handling behavior.
+	  // Back slashes before the query string get converted to forward slashes
+	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
+	  var queryIndex = url.indexOf('?'),
+	      splitter =
+	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+	      uSplit = url.split(splitter),
+	      slashRegex = /\\/g;
+	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
+	  url = uSplit.join(splitter);
+
+	  var rest = url;
+
+	  // trim before proceeding.
+	  // This is to support parse stuff like "  http://foo.com  \n"
+	  rest = rest.trim();
+
+	  if (!slashesDenoteHost && url.split('#').length === 1) {
+	    // Try fast path regexp
+	    var simplePath = simplePathPattern.exec(rest);
+	    if (simplePath) {
+	      this.path = rest;
+	      this.href = rest;
+	      this.pathname = simplePath[1];
+	      if (simplePath[2]) {
+	        this.search = simplePath[2];
+	        if (parseQueryString) {
+	          this.query = querystring.parse(this.search.substr(1));
+	        } else {
+	          this.query = this.search.substr(1);
+	        }
+	      } else if (parseQueryString) {
+	        this.search = '';
+	        this.query = {};
+	      }
+	      return this;
+	    }
+	  }
+
+	  var proto = protocolPattern.exec(rest);
+	  if (proto) {
+	    proto = proto[0];
+	    var lowerProto = proto.toLowerCase();
+	    this.protocol = lowerProto;
+	    rest = rest.substr(proto.length);
+	  }
+
+	  // figure out if it's got a host
+	  // user@server is *always* interpreted as a hostname, and url
+	  // resolution will treat //foo/bar as host=foo,path=bar because that's
+	  // how the browser resolves relative URLs.
+	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+	    var slashes = rest.substr(0, 2) === '//';
+	    if (slashes && !(proto && hostlessProtocol[proto])) {
+	      rest = rest.substr(2);
+	      this.slashes = true;
+	    }
+	  }
+
+	  if (!hostlessProtocol[proto] &&
+	      (slashes || (proto && !slashedProtocol[proto]))) {
+
+	    // there's a hostname.
+	    // the first instance of /, ?, ;, or # ends the host.
+	    //
+	    // If there is an @ in the hostname, then non-host chars *are* allowed
+	    // to the left of the last @ sign, unless some host-ending character
+	    // comes *before* the @-sign.
+	    // URLs are obnoxious.
+	    //
+	    // ex:
+	    // http://a@b@c/ => user:a@b host:c
+	    // http://a@b?@c => user:a host:c path:/?@c
+
+	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+	    // Review our test case against browsers more comprehensively.
+
+	    // find the first instance of any hostEndingChars
+	    var hostEnd = -1;
+	    for (var i = 0; i < hostEndingChars.length; i++) {
+	      var hec = rest.indexOf(hostEndingChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+
+	    // at this point, either we have an explicit point where the
+	    // auth portion cannot go past, or the last @ char is the decider.
+	    var auth, atSign;
+	    if (hostEnd === -1) {
+	      // atSign can be anywhere.
+	      atSign = rest.lastIndexOf('@');
+	    } else {
+	      // atSign must be in auth portion.
+	      // http://a@b/c@d => host:b auth:a path:/c@d
+	      atSign = rest.lastIndexOf('@', hostEnd);
+	    }
+
+	    // Now we have a portion which is definitely the auth.
+	    // Pull that off.
+	    if (atSign !== -1) {
+	      auth = rest.slice(0, atSign);
+	      rest = rest.slice(atSign + 1);
+	      this.auth = decodeURIComponent(auth);
+	    }
+
+	    // the host is the remaining to the left of the first non-host char
+	    hostEnd = -1;
+	    for (var i = 0; i < nonHostChars.length; i++) {
+	      var hec = rest.indexOf(nonHostChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+	    // if we still have not hit it, then the entire thing is a host.
+	    if (hostEnd === -1)
+	      hostEnd = rest.length;
+
+	    this.host = rest.slice(0, hostEnd);
+	    rest = rest.slice(hostEnd);
+
+	    // pull out port.
+	    this.parseHost();
+
+	    // we've indicated that there is a hostname,
+	    // so even if it's empty, it has to be present.
+	    this.hostname = this.hostname || '';
+
+	    // if hostname begins with [ and ends with ]
+	    // assume that it's an IPv6 address.
+	    var ipv6Hostname = this.hostname[0] === '[' &&
+	        this.hostname[this.hostname.length - 1] === ']';
+
+	    // validate a little.
+	    if (!ipv6Hostname) {
+	      var hostparts = this.hostname.split(/\./);
+	      for (var i = 0, l = hostparts.length; i < l; i++) {
+	        var part = hostparts[i];
+	        if (!part) continue;
+	        if (!part.match(hostnamePartPattern)) {
+	          var newpart = '';
+	          for (var j = 0, k = part.length; j < k; j++) {
+	            if (part.charCodeAt(j) > 127) {
+	              // we replace non-ASCII char with a temporary placeholder
+	              // we need this to make sure size of hostname is not
+	              // broken by replacing non-ASCII by nothing
+	              newpart += 'x';
+	            } else {
+	              newpart += part[j];
+	            }
+	          }
+	          // we test again with ASCII char only
+	          if (!newpart.match(hostnamePartPattern)) {
+	            var validParts = hostparts.slice(0, i);
+	            var notHost = hostparts.slice(i + 1);
+	            var bit = part.match(hostnamePartStart);
+	            if (bit) {
+	              validParts.push(bit[1]);
+	              notHost.unshift(bit[2]);
+	            }
+	            if (notHost.length) {
+	              rest = '/' + notHost.join('.') + rest;
+	            }
+	            this.hostname = validParts.join('.');
+	            break;
+	          }
+	        }
+	      }
+	    }
+
+	    if (this.hostname.length > hostnameMaxLen) {
+	      this.hostname = '';
+	    } else {
+	      // hostnames are always lower case.
+	      this.hostname = this.hostname.toLowerCase();
+	    }
+
+	    if (!ipv6Hostname) {
+	      // IDNA Support: Returns a punycoded representation of "domain".
+	      // It only converts parts of the domain name that
+	      // have non-ASCII characters, i.e. it doesn't matter if
+	      // you call it with a domain that already is ASCII-only.
+	      this.hostname = punycode.toASCII(this.hostname);
+	    }
+
+	    var p = this.port ? ':' + this.port : '';
+	    var h = this.hostname || '';
+	    this.host = h + p;
+	    this.href += this.host;
+
+	    // strip [ and ] from the hostname
+	    // the host field still retains them, though
+	    if (ipv6Hostname) {
+	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+	      if (rest[0] !== '/') {
+	        rest = '/' + rest;
+	      }
+	    }
+	  }
+
+	  // now rest is set to the post-host stuff.
+	  // chop off any delim chars.
+	  if (!unsafeProtocol[lowerProto]) {
+
+	    // First, make 100% sure that any "autoEscape" chars get
+	    // escaped, even if encodeURIComponent doesn't think they
+	    // need to be.
+	    for (var i = 0, l = autoEscape.length; i < l; i++) {
+	      var ae = autoEscape[i];
+	      if (rest.indexOf(ae) === -1)
+	        continue;
+	      var esc = encodeURIComponent(ae);
+	      if (esc === ae) {
+	        esc = escape(ae);
+	      }
+	      rest = rest.split(ae).join(esc);
+	    }
+	  }
+
+
+	  // chop off from the tail first.
+	  var hash = rest.indexOf('#');
+	  if (hash !== -1) {
+	    // got a fragment string.
+	    this.hash = rest.substr(hash);
+	    rest = rest.slice(0, hash);
+	  }
+	  var qm = rest.indexOf('?');
+	  if (qm !== -1) {
+	    this.search = rest.substr(qm);
+	    this.query = rest.substr(qm + 1);
+	    if (parseQueryString) {
+	      this.query = querystring.parse(this.query);
+	    }
+	    rest = rest.slice(0, qm);
+	  } else if (parseQueryString) {
+	    // no query string, but parseQueryString still requested
+	    this.search = '';
+	    this.query = {};
+	  }
+	  if (rest) this.pathname = rest;
+	  if (slashedProtocol[lowerProto] &&
+	      this.hostname && !this.pathname) {
+	    this.pathname = '/';
+	  }
+
+	  //to support http.request
+	  if (this.pathname || this.search) {
+	    var p = this.pathname || '';
+	    var s = this.search || '';
+	    this.path = p + s;
+	  }
+
+	  // finally, reconstruct the href based on what has been validated.
+	  this.href = this.format();
+	  return this;
+	};
+
+	// format a parsed object into a url string
+	function urlFormat(obj) {
+	  // ensure it's an object, and not a string url.
+	  // If it's an obj, this is a no-op.
+	  // this way, you can call url_format() on strings
+	  // to clean up potentially wonky urls.
+	  if (util.isString(obj)) obj = urlParse(obj);
+	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+	  return obj.format();
+	}
+
+	Url.prototype.format = function() {
+	  var auth = this.auth || '';
+	  if (auth) {
+	    auth = encodeURIComponent(auth);
+	    auth = auth.replace(/%3A/i, ':');
+	    auth += '@';
+	  }
+
+	  var protocol = this.protocol || '',
+	      pathname = this.pathname || '',
+	      hash = this.hash || '',
+	      host = false,
+	      query = '';
+
+	  if (this.host) {
+	    host = auth + this.host;
+	  } else if (this.hostname) {
+	    host = auth + (this.hostname.indexOf(':') === -1 ?
+	        this.hostname :
+	        '[' + this.hostname + ']');
+	    if (this.port) {
+	      host += ':' + this.port;
+	    }
+	  }
+
+	  if (this.query &&
+	      util.isObject(this.query) &&
+	      Object.keys(this.query).length) {
+	    query = querystring.stringify(this.query);
+	  }
+
+	  var search = this.search || (query && ('?' + query)) || '';
+
+	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
+	  // unless they had them to begin with.
+	  if (this.slashes ||
+	      (!protocol || slashedProtocol[protocol]) && host !== false) {
+	    host = '//' + (host || '');
+	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+	  } else if (!host) {
+	    host = '';
+	  }
+
+	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+	  if (search && search.charAt(0) !== '?') search = '?' + search;
+
+	  pathname = pathname.replace(/[?#]/g, function(match) {
+	    return encodeURIComponent(match);
+	  });
+	  search = search.replace('#', '%23');
+
+	  return protocol + host + pathname + search + hash;
+	};
+
+	function urlResolve(source, relative) {
+	  return urlParse(source, false, true).resolve(relative);
+	}
+
+	Url.prototype.resolve = function(relative) {
+	  return this.resolveObject(urlParse(relative, false, true)).format();
+	};
+
+	function urlResolveObject(source, relative) {
+	  if (!source) return relative;
+	  return urlParse(source, false, true).resolveObject(relative);
+	}
+
+	Url.prototype.resolveObject = function(relative) {
+	  if (util.isString(relative)) {
+	    var rel = new Url();
+	    rel.parse(relative, false, true);
+	    relative = rel;
+	  }
+
+	  var result = new Url();
+	  var tkeys = Object.keys(this);
+	  for (var tk = 0; tk < tkeys.length; tk++) {
+	    var tkey = tkeys[tk];
+	    result[tkey] = this[tkey];
+	  }
+
+	  // hash is always overridden, no matter what.
+	  // even href="" will remove it.
+	  result.hash = relative.hash;
+
+	  // if the relative url is empty, then there's nothing left to do here.
+	  if (relative.href === '') {
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // hrefs like //foo/bar always cut to the protocol.
+	  if (relative.slashes && !relative.protocol) {
+	    // take everything except the protocol from relative
+	    var rkeys = Object.keys(relative);
+	    for (var rk = 0; rk < rkeys.length; rk++) {
+	      var rkey = rkeys[rk];
+	      if (rkey !== 'protocol')
+	        result[rkey] = relative[rkey];
+	    }
+
+	    //urlParse appends trailing / to urls like http://www.example.com
+	    if (slashedProtocol[result.protocol] &&
+	        result.hostname && !result.pathname) {
+	      result.path = result.pathname = '/';
+	    }
+
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (relative.protocol && relative.protocol !== result.protocol) {
+	    // if it's a known url protocol, then changing
+	    // the protocol does weird things
+	    // first, if it's not file:, then we MUST have a host,
+	    // and if there was a path
+	    // to begin with, then we MUST have a path.
+	    // if it is file:, then the host is dropped,
+	    // because that's known to be hostless.
+	    // anything else is assumed to be absolute.
+	    if (!slashedProtocol[relative.protocol]) {
+	      var keys = Object.keys(relative);
+	      for (var v = 0; v < keys.length; v++) {
+	        var k = keys[v];
+	        result[k] = relative[k];
+	      }
+	      result.href = result.format();
+	      return result;
+	    }
+
+	    result.protocol = relative.protocol;
+	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
+	      var relPath = (relative.pathname || '').split('/');
+	      while (relPath.length && !(relative.host = relPath.shift()));
+	      if (!relative.host) relative.host = '';
+	      if (!relative.hostname) relative.hostname = '';
+	      if (relPath[0] !== '') relPath.unshift('');
+	      if (relPath.length < 2) relPath.unshift('');
+	      result.pathname = relPath.join('/');
+	    } else {
+	      result.pathname = relative.pathname;
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    result.host = relative.host || '';
+	    result.auth = relative.auth;
+	    result.hostname = relative.hostname || relative.host;
+	    result.port = relative.port;
+	    // to support http.request
+	    if (result.pathname || result.search) {
+	      var p = result.pathname || '';
+	      var s = result.search || '';
+	      result.path = p + s;
+	    }
+	    result.slashes = result.slashes || relative.slashes;
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+	      isRelAbs = (
+	          relative.host ||
+	          relative.pathname && relative.pathname.charAt(0) === '/'
+	      ),
+	      mustEndAbs = (isRelAbs || isSourceAbs ||
+	                    (result.host && relative.pathname)),
+	      removeAllDots = mustEndAbs,
+	      srcPath = result.pathname && result.pathname.split('/') || [],
+	      relPath = relative.pathname && relative.pathname.split('/') || [],
+	      psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+	  // if the url is a non-slashed url, then relative
+	  // links like ../.. should be able
+	  // to crawl up to the hostname, as well.  This is strange.
+	  // result.protocol has already been set by now.
+	  // Later on, put the first path part into the host field.
+	  if (psychotic) {
+	    result.hostname = '';
+	    result.port = null;
+	    if (result.host) {
+	      if (srcPath[0] === '') srcPath[0] = result.host;
+	      else srcPath.unshift(result.host);
+	    }
+	    result.host = '';
+	    if (relative.protocol) {
+	      relative.hostname = null;
+	      relative.port = null;
+	      if (relative.host) {
+	        if (relPath[0] === '') relPath[0] = relative.host;
+	        else relPath.unshift(relative.host);
+	      }
+	      relative.host = null;
+	    }
+	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+	  }
+
+	  if (isRelAbs) {
+	    // it's absolute.
+	    result.host = (relative.host || relative.host === '') ?
+	                  relative.host : result.host;
+	    result.hostname = (relative.hostname || relative.hostname === '') ?
+	                      relative.hostname : result.hostname;
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    srcPath = relPath;
+	    // fall through to the dot-handling below.
+	  } else if (relPath.length) {
+	    // it's relative
+	    // throw away the existing file, and take the new path instead.
+	    if (!srcPath) srcPath = [];
+	    srcPath.pop();
+	    srcPath = srcPath.concat(relPath);
+	    result.search = relative.search;
+	    result.query = relative.query;
+	  } else if (!util.isNullOrUndefined(relative.search)) {
+	    // just pull out the search.
+	    // like href='?foo'.
+	    // Put this after the other two cases because it simplifies the booleans
+	    if (psychotic) {
+	      result.hostname = result.host = srcPath.shift();
+	      //occationaly the auth can get stuck only in host
+	      //this especially happens in cases like
+	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                       result.host.split('@') : false;
+	      if (authInHost) {
+	        result.auth = authInHost.shift();
+	        result.host = result.hostname = authInHost.shift();
+	      }
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    //to support http.request
+	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	      result.path = (result.pathname ? result.pathname : '') +
+	                    (result.search ? result.search : '');
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (!srcPath.length) {
+	    // no path at all.  easy.
+	    // we've already handled the other stuff above.
+	    result.pathname = null;
+	    //to support http.request
+	    if (result.search) {
+	      result.path = '/' + result.search;
+	    } else {
+	      result.path = null;
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // if a url ENDs in . or .., then it must get a trailing slash.
+	  // however, if it ends in anything else non-slashy,
+	  // then it must NOT get a trailing slash.
+	  var last = srcPath.slice(-1)[0];
+	  var hasTrailingSlash = (
+	      (result.host || relative.host || srcPath.length > 1) &&
+	      (last === '.' || last === '..') || last === '');
+
+	  // strip single dots, resolve double dots to parent dir
+	  // if the path tries to go above the root, `up` ends up > 0
+	  var up = 0;
+	  for (var i = srcPath.length; i >= 0; i--) {
+	    last = srcPath[i];
+	    if (last === '.') {
+	      srcPath.splice(i, 1);
+	    } else if (last === '..') {
+	      srcPath.splice(i, 1);
+	      up++;
+	    } else if (up) {
+	      srcPath.splice(i, 1);
+	      up--;
+	    }
+	  }
+
+	  // if the path is allowed to go above the root, restore leading ..s
+	  if (!mustEndAbs && !removeAllDots) {
+	    for (; up--; up) {
+	      srcPath.unshift('..');
+	    }
+	  }
+
+	  if (mustEndAbs && srcPath[0] !== '' &&
+	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+	    srcPath.unshift('');
+	  }
+
+	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+	    srcPath.push('');
+	  }
+
+	  var isAbsolute = srcPath[0] === '' ||
+	      (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+	  // put the host back
+	  if (psychotic) {
+	    result.hostname = result.host = isAbsolute ? '' :
+	                                    srcPath.length ? srcPath.shift() : '';
+	    //occationaly the auth can get stuck only in host
+	    //this especially happens in cases like
+	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                     result.host.split('@') : false;
+	    if (authInHost) {
+	      result.auth = authInHost.shift();
+	      result.host = result.hostname = authInHost.shift();
+	    }
+	  }
+
+	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+	  if (mustEndAbs && !isAbsolute) {
+	    srcPath.unshift('');
+	  }
+
+	  if (!srcPath.length) {
+	    result.pathname = null;
+	    result.path = null;
+	  } else {
+	    result.pathname = srcPath.join('/');
+	  }
+
+	  //to support request.http
+	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	    result.path = (result.pathname ? result.pathname : '') +
+	                  (result.search ? result.search : '');
+	  }
+	  result.auth = relative.auth || result.auth;
+	  result.slashes = result.slashes || relative.slashes;
+	  result.href = result.format();
+	  return result;
+	};
+
+	Url.prototype.parseHost = function() {
+	  var host = this.host;
+	  var port = portPattern.exec(host);
+	  if (port) {
+	    port = port[0];
+	    if (port !== ':') {
+	      this.port = port.substr(1);
+	    }
+	    host = host.substr(0, host.length - port.length);
+	  }
+	  if (host) this.hostname = host;
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * http://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.3.2',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else { // in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else { // in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	module.exports = function(module) {

+		if(!module.webpackPolyfill) {

+			module.deprecate = function() {};

+			module.paths = [];

+			// module.parent = undefined by default

+			module.children = [];

+			module.webpackPolyfill = 1;

+		}

+		return module;

+	}

+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+	'use strict';
+
+	module.exports = {
+	  isString: function(arg) {
+	    return typeof(arg) === 'string';
+	  },
+	  isObject: function(arg) {
+	    return typeof(arg) === 'object' && arg !== null;
+	  },
+	  isNull: function(arg) {
+	    return arg === null;
+	  },
+	  isNullOrUndefined: function(arg) {
+	    return arg == null;
+	  }
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	exports.decode = exports.parse = __webpack_require__(7);
+	exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	// If obj.hasOwnProperty has been overridden, then calling
+	// obj.hasOwnProperty(prop) will break.
+	// See: https://github.com/joyent/node/issues/1707
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	module.exports = function(qs, sep, eq, options) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  var obj = {};
+
+	  if (typeof qs !== 'string' || qs.length === 0) {
+	    return obj;
+	  }
+
+	  var regexp = /\+/g;
+	  qs = qs.split(sep);
+
+	  var maxKeys = 1000;
+	  if (options && typeof options.maxKeys === 'number') {
+	    maxKeys = options.maxKeys;
+	  }
+
+	  var len = qs.length;
+	  // maxKeys <= 0 means that we should not limit keys count
+	  if (maxKeys > 0 && len > maxKeys) {
+	    len = maxKeys;
+	  }
+
+	  for (var i = 0; i < len; ++i) {
+	    var x = qs[i].replace(regexp, '%20'),
+	        idx = x.indexOf(eq),
+	        kstr, vstr, k, v;
+
+	    if (idx >= 0) {
+	      kstr = x.substr(0, idx);
+	      vstr = x.substr(idx + 1);
+	    } else {
+	      kstr = x;
+	      vstr = '';
+	    }
+
+	    k = decodeURIComponent(kstr);
+	    v = decodeURIComponent(vstr);
+
+	    if (!hasOwnProperty(obj, k)) {
+	      obj[k] = v;
+	    } else if (Array.isArray(obj[k])) {
+	      obj[k].push(v);
+	    } else {
+	      obj[k] = [obj[k], v];
+	    }
+	  }
+
+	  return obj;
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var stringifyPrimitive = function(v) {
+	  switch (typeof v) {
+	    case 'string':
+	      return v;
+
+	    case 'boolean':
+	      return v ? 'true' : 'false';
+
+	    case 'number':
+	      return isFinite(v) ? v : '';
+
+	    default:
+	      return '';
+	  }
+	};
+
+	module.exports = function(obj, sep, eq, name) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  if (obj === null) {
+	    obj = undefined;
+	  }
+
+	  if (typeof obj === 'object') {
+	    return Object.keys(obj).map(function(k) {
+	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+	      if (Array.isArray(obj[k])) {
+	        return obj[k].map(function(v) {
+	          return ks + encodeURIComponent(stringifyPrimitive(v));
+	        }).join(sep);
+	      } else {
+	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+	      }
+	    }).join(sep);
+
+	  }
+
+	  if (!name) return '';
+	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
+	         encodeURIComponent(stringifyPrimitive(obj));
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	var formatRegExp = /%[sdj%]/g;
+	exports.format = function(f) {
+	  if (!isString(f)) {
+	    var objects = [];
+	    for (var i = 0; i < arguments.length; i++) {
+	      objects.push(inspect(arguments[i]));
+	    }
+	    return objects.join(' ');
+	  }
+
+	  var i = 1;
+	  var args = arguments;
+	  var len = args.length;
+	  var str = String(f).replace(formatRegExp, function(x) {
+	    if (x === '%%') return '%';
+	    if (i >= len) return x;
+	    switch (x) {
+	      case '%s': return String(args[i++]);
+	      case '%d': return Number(args[i++]);
+	      case '%j':
+	        try {
+	          return JSON.stringify(args[i++]);
+	        } catch (_) {
+	          return '[Circular]';
+	        }
+	      default:
+	        return x;
+	    }
+	  });
+	  for (var x = args[i]; i < len; x = args[++i]) {
+	    if (isNull(x) || !isObject(x)) {
+	      str += ' ' + x;
+	    } else {
+	      str += ' ' + inspect(x);
+	    }
+	  }
+	  return str;
+	};
+
+
+	// Mark that a method should not be used.
+	// Returns a modified function which warns once by default.
+	// If --no-deprecation is set, then it is a no-op.
+	exports.deprecate = function(fn, msg) {
+	  // Allow for deprecating things in the process of starting up.
+	  if (isUndefined(global.process)) {
+	    return function() {
+	      return exports.deprecate(fn, msg).apply(this, arguments);
+	    };
+	  }
+
+	  if (process.noDeprecation === true) {
+	    return fn;
+	  }
+
+	  var warned = false;
+	  function deprecated() {
+	    if (!warned) {
+	      if (process.throwDeprecation) {
+	        throw new Error(msg);
+	      } else if (process.traceDeprecation) {
+	        console.trace(msg);
+	      } else {
+	        console.error(msg);
+	      }
+	      warned = true;
+	    }
+	    return fn.apply(this, arguments);
+	  }
+
+	  return deprecated;
+	};
+
+
+	var debugs = {};
+	var debugEnviron;
+	exports.debuglog = function(set) {
+	  if (isUndefined(debugEnviron))
+	    debugEnviron = process.env.NODE_DEBUG || '';
+	  set = set.toUpperCase();
+	  if (!debugs[set]) {
+	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+	      var pid = process.pid;
+	      debugs[set] = function() {
+	        var msg = exports.format.apply(exports, arguments);
+	        console.error('%s %d: %s', set, pid, msg);
+	      };
+	    } else {
+	      debugs[set] = function() {};
+	    }
+	  }
+	  return debugs[set];
+	};
+
+
+	/**
+	 * Echos the value of a value. Trys to print the value out
+	 * in the best way possible given the different types.
+	 *
+	 * @param {Object} obj The object to print out.
+	 * @param {Object} opts Optional options object that alters the output.
+	 */
+	/* legacy: obj, showHidden, depth, colors*/
+	function inspect(obj, opts) {
+	  // default options
+	  var ctx = {
+	    seen: [],
+	    stylize: stylizeNoColor
+	  };
+	  // legacy...
+	  if (arguments.length >= 3) ctx.depth = arguments[2];
+	  if (arguments.length >= 4) ctx.colors = arguments[3];
+	  if (isBoolean(opts)) {
+	    // legacy...
+	    ctx.showHidden = opts;
+	  } else if (opts) {
+	    // got an "options" object
+	    exports._extend(ctx, opts);
+	  }
+	  // set default options
+	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+	  if (isUndefined(ctx.depth)) ctx.depth = 2;
+	  if (isUndefined(ctx.colors)) ctx.colors = false;
+	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+	  if (ctx.colors) ctx.stylize = stylizeWithColor;
+	  return formatValue(ctx, obj, ctx.depth);
+	}
+	exports.inspect = inspect;
+
+
+	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+	inspect.colors = {
+	  'bold' : [1, 22],
+	  'italic' : [3, 23],
+	  'underline' : [4, 24],
+	  'inverse' : [7, 27],
+	  'white' : [37, 39],
+	  'grey' : [90, 39],
+	  'black' : [30, 39],
+	  'blue' : [34, 39],
+	  'cyan' : [36, 39],
+	  'green' : [32, 39],
+	  'magenta' : [35, 39],
+	  'red' : [31, 39],
+	  'yellow' : [33, 39]
+	};
+
+	// Don't use 'blue' not visible on cmd.exe
+	inspect.styles = {
+	  'special': 'cyan',
+	  'number': 'yellow',
+	  'boolean': 'yellow',
+	  'undefined': 'grey',
+	  'null': 'bold',
+	  'string': 'green',
+	  'date': 'magenta',
+	  // "name": intentionally not styling
+	  'regexp': 'red'
+	};
+
+
+	function stylizeWithColor(str, styleType) {
+	  var style = inspect.styles[styleType];
+
+	  if (style) {
+	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+	           '\u001b[' + inspect.colors[style][1] + 'm';
+	  } else {
+	    return str;
+	  }
+	}
+
+
+	function stylizeNoColor(str, styleType) {
+	  return str;
+	}
+
+
+	function arrayToHash(array) {
+	  var hash = {};
+
+	  array.forEach(function(val, idx) {
+	    hash[val] = true;
+	  });
+
+	  return hash;
+	}
+
+
+	function formatValue(ctx, value, recurseTimes) {
+	  // Provide a hook for user-specified inspect functions.
+	  // Check that value is an object with an inspect function on it
+	  if (ctx.customInspect &&
+	      value &&
+	      isFunction(value.inspect) &&
+	      // Filter out the util module, it's inspect function is special
+	      value.inspect !== exports.inspect &&
+	      // Also filter out any prototype objects using the circular check.
+	      !(value.constructor && value.constructor.prototype === value)) {
+	    var ret = value.inspect(recurseTimes, ctx);
+	    if (!isString(ret)) {
+	      ret = formatValue(ctx, ret, recurseTimes);
+	    }
+	    return ret;
+	  }
+
+	  // Primitive types cannot have properties
+	  var primitive = formatPrimitive(ctx, value);
+	  if (primitive) {
+	    return primitive;
+	  }
+
+	  // Look up the keys of the object.
+	  var keys = Object.keys(value);
+	  var visibleKeys = arrayToHash(keys);
+
+	  if (ctx.showHidden) {
+	    keys = Object.getOwnPropertyNames(value);
+	  }
+
+	  // IE doesn't make error fields non-enumerable
+	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+	  if (isError(value)
+	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+	    return formatError(value);
+	  }
+
+	  // Some type of object without properties can be shortcutted.
+	  if (keys.length === 0) {
+	    if (isFunction(value)) {
+	      var name = value.name ? ': ' + value.name : '';
+	      return ctx.stylize('[Function' + name + ']', 'special');
+	    }
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    }
+	    if (isDate(value)) {
+	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
+	    }
+	    if (isError(value)) {
+	      return formatError(value);
+	    }
+	  }
+
+	  var base = '', array = false, braces = ['{', '}'];
+
+	  // Make Array say that they are Array
+	  if (isArray(value)) {
+	    array = true;
+	    braces = ['[', ']'];
+	  }
+
+	  // Make functions say that they are functions
+	  if (isFunction(value)) {
+	    var n = value.name ? ': ' + value.name : '';
+	    base = ' [Function' + n + ']';
+	  }
+
+	  // Make RegExps say that they are RegExps
+	  if (isRegExp(value)) {
+	    base = ' ' + RegExp.prototype.toString.call(value);
+	  }
+
+	  // Make dates with properties first say the date
+	  if (isDate(value)) {
+	    base = ' ' + Date.prototype.toUTCString.call(value);
+	  }
+
+	  // Make error with message first say the error
+	  if (isError(value)) {
+	    base = ' ' + formatError(value);
+	  }
+
+	  if (keys.length === 0 && (!array || value.length == 0)) {
+	    return braces[0] + base + braces[1];
+	  }
+
+	  if (recurseTimes < 0) {
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    } else {
+	      return ctx.stylize('[Object]', 'special');
+	    }
+	  }
+
+	  ctx.seen.push(value);
+
+	  var output;
+	  if (array) {
+	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+	  } else {
+	    output = keys.map(function(key) {
+	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+	    });
+	  }
+
+	  ctx.seen.pop();
+
+	  return reduceToSingleString(output, base, braces);
+	}
+
+
+	function formatPrimitive(ctx, value) {
+	  if (isUndefined(value))
+	    return ctx.stylize('undefined', 'undefined');
+	  if (isString(value)) {
+	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+	                                             .replace(/'/g, "\\'")
+	                                             .replace(/\\"/g, '"') + '\'';
+	    return ctx.stylize(simple, 'string');
+	  }
+	  if (isNumber(value))
+	    return ctx.stylize('' + value, 'number');
+	  if (isBoolean(value))
+	    return ctx.stylize('' + value, 'boolean');
+	  // For some reason typeof null is "object", so special case here.
+	  if (isNull(value))
+	    return ctx.stylize('null', 'null');
+	}
+
+
+	function formatError(value) {
+	  return '[' + Error.prototype.toString.call(value) + ']';
+	}
+
+
+	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+	  var output = [];
+	  for (var i = 0, l = value.length; i < l; ++i) {
+	    if (hasOwnProperty(value, String(i))) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          String(i), true));
+	    } else {
+	      output.push('');
+	    }
+	  }
+	  keys.forEach(function(key) {
+	    if (!key.match(/^\d+$/)) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          key, true));
+	    }
+	  });
+	  return output;
+	}
+
+
+	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+	  var name, str, desc;
+	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+	  if (desc.get) {
+	    if (desc.set) {
+	      str = ctx.stylize('[Getter/Setter]', 'special');
+	    } else {
+	      str = ctx.stylize('[Getter]', 'special');
+	    }
+	  } else {
+	    if (desc.set) {
+	      str = ctx.stylize('[Setter]', 'special');
+	    }
+	  }
+	  if (!hasOwnProperty(visibleKeys, key)) {
+	    name = '[' + key + ']';
+	  }
+	  if (!str) {
+	    if (ctx.seen.indexOf(desc.value) < 0) {
+	      if (isNull(recurseTimes)) {
+	        str = formatValue(ctx, desc.value, null);
+	      } else {
+	        str = formatValue(ctx, desc.value, recurseTimes - 1);
+	      }
+	      if (str.indexOf('\n') > -1) {
+	        if (array) {
+	          str = str.split('\n').map(function(line) {
+	            return '  ' + line;
+	          }).join('\n').substr(2);
+	        } else {
+	          str = '\n' + str.split('\n').map(function(line) {
+	            return '   ' + line;
+	          }).join('\n');
+	        }
+	      }
+	    } else {
+	      str = ctx.stylize('[Circular]', 'special');
+	    }
+	  }
+	  if (isUndefined(name)) {
+	    if (array && key.match(/^\d+$/)) {
+	      return str;
+	    }
+	    name = JSON.stringify('' + key);
+	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+	      name = name.substr(1, name.length - 2);
+	      name = ctx.stylize(name, 'name');
+	    } else {
+	      name = name.replace(/'/g, "\\'")
+	                 .replace(/\\"/g, '"')
+	                 .replace(/(^"|"$)/g, "'");
+	      name = ctx.stylize(name, 'string');
+	    }
+	  }
+
+	  return name + ': ' + str;
+	}
+
+
+	function reduceToSingleString(output, base, braces) {
+	  var numLinesEst = 0;
+	  var length = output.reduce(function(prev, cur) {
+	    numLinesEst++;
+	    if (cur.indexOf('\n') >= 0) numLinesEst++;
+	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+	  }, 0);
+
+	  if (length > 60) {
+	    return braces[0] +
+	           (base === '' ? '' : base + '\n ') +
+	           ' ' +
+	           output.join(',\n  ') +
+	           ' ' +
+	           braces[1];
+	  }
+
+	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+	}
+
+
+	// NOTE: These type checking functions intentionally don't use `instanceof`
+	// because it is fragile and can be easily faked with `Object.create()`.
+	function isArray(ar) {
+	  return Array.isArray(ar);
+	}
+	exports.isArray = isArray;
+
+	function isBoolean(arg) {
+	  return typeof arg === 'boolean';
+	}
+	exports.isBoolean = isBoolean;
+
+	function isNull(arg) {
+	  return arg === null;
+	}
+	exports.isNull = isNull;
+
+	function isNullOrUndefined(arg) {
+	  return arg == null;
+	}
+	exports.isNullOrUndefined = isNullOrUndefined;
+
+	function isNumber(arg) {
+	  return typeof arg === 'number';
+	}
+	exports.isNumber = isNumber;
+
+	function isString(arg) {
+	  return typeof arg === 'string';
+	}
+	exports.isString = isString;
+
+	function isSymbol(arg) {
+	  return typeof arg === 'symbol';
+	}
+	exports.isSymbol = isSymbol;
+
+	function isUndefined(arg) {
+	  return arg === void 0;
+	}
+	exports.isUndefined = isUndefined;
+
+	function isRegExp(re) {
+	  return isObject(re) && objectToString(re) === '[object RegExp]';
+	}
+	exports.isRegExp = isRegExp;
+
+	function isObject(arg) {
+	  return typeof arg === 'object' && arg !== null;
+	}
+	exports.isObject = isObject;
+
+	function isDate(d) {
+	  return isObject(d) && objectToString(d) === '[object Date]';
+	}
+	exports.isDate = isDate;
+
+	function isError(e) {
+	  return isObject(e) &&
+	      (objectToString(e) === '[object Error]' || e instanceof Error);
+	}
+	exports.isError = isError;
+
+	function isFunction(arg) {
+	  return typeof arg === 'function';
+	}
+	exports.isFunction = isFunction;
+
+	function isPrimitive(arg) {
+	  return arg === null ||
+	         typeof arg === 'boolean' ||
+	         typeof arg === 'number' ||
+	         typeof arg === 'string' ||
+	         typeof arg === 'symbol' ||  // ES6 symbol
+	         typeof arg === 'undefined';
+	}
+	exports.isPrimitive = isPrimitive;
+
+	exports.isBuffer = __webpack_require__(11);
+
+	function objectToString(o) {
+	  return Object.prototype.toString.call(o);
+	}
+
+
+	function pad(n) {
+	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+	}
+
+
+	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+	              'Oct', 'Nov', 'Dec'];
+
+	// 26 Feb 16:19:34
+	function timestamp() {
+	  var d = new Date();
+	  var time = [pad(d.getHours()),
+	              pad(d.getMinutes()),
+	              pad(d.getSeconds())].join(':');
+	  return [d.getDate(), months[d.getMonth()], time].join(' ');
+	}
+
+
+	// log is just a thin wrapper to console.log that prepends a timestamp
+	exports.log = function() {
+	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+	};
+
+
+	/**
+	 * Inherit the prototype methods from one constructor into another.
+	 *
+	 * The Function.prototype.inherits from lang.js rewritten as a standalone
+	 * function (not on Function.prototype). NOTE: If this file is to be loaded
+	 * during bootstrapping this function needs to be rewritten using some native
+	 * functions as prototype setup using normal JavaScript does not work as
+	 * expected during bootstrapping (see mirror.js in r114903).
+	 *
+	 * @param {function} ctor Constructor function which needs to inherit the
+	 *     prototype.
+	 * @param {function} superCtor Constructor function to inherit prototype from.
+	 */
+	exports.inherits = __webpack_require__(12);
+
+	exports._extend = function(origin, add) {
+	  // Don't do anything if add isn't an object
+	  if (!add || !isObject(add)) return origin;
+
+	  var keys = Object.keys(add);
+	  var i = keys.length;
+	  while (i--) {
+	    origin[keys[i]] = add[keys[i]];
+	  }
+	  return origin;
+	};
+
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	// shim for using process in browser
+	var process = module.exports = {};
+
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+
+
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+
+
+
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+
+	    var len = queue.length;
+	    while(len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+
+	function noop() {}
+
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+
+	process.listeners = function (name) { return [] }
+
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+
+	process.cwd = function () { return '/' };
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	module.exports = function isBuffer(arg) {
+	  return arg && typeof arg === 'object'
+	    && typeof arg.copy === 'function'
+	    && typeof arg.fill === 'function'
+	    && typeof arg.readUInt8 === 'function';
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	if (typeof Object.create === 'function') {
+	  // implementation from standard node.js 'util' module
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    ctor.prototype = Object.create(superCtor.prototype, {
+	      constructor: {
+	        value: ctor,
+	        enumerable: false,
+	        writable: true,
+	        configurable: true
+	      }
+	    });
+	  };
+	} else {
+	  // old school shim for old browsers
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    var TempCtor = function () {}
+	    TempCtor.prototype = superCtor.prototype
+	    ctor.prototype = new TempCtor()
+	    ctor.prototype.constructor = ctor
+	  }
+	}
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2018, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var psl = __webpack_require__(14);
+
+	function getPublicSuffix(domain) {
+	  return psl.get(domain);
+	}
+
+	exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+	'use strict';
+
+
+	var Punycode = __webpack_require__(15);
+
+
+	var internals = {};
+
+
+	//
+	// Read rules from file.
+	//
+	internals.rules = __webpack_require__(16).map(function (rule) {
+
+	  return {
+	    rule: rule,
+	    suffix: rule.replace(/^(\*\.|\!)/, ''),
+	    punySuffix: -1,
+	    wildcard: rule.charAt(0) === '*',
+	    exception: rule.charAt(0) === '!'
+	  };
+	});
+
+
+	//
+	// Check is given string ends with `suffix`.
+	//
+	internals.endsWith = function (str, suffix) {
+
+	  return str.indexOf(suffix, str.length - suffix.length) !== -1;
+	};
+
+
+	//
+	// Find rule for a given domain.
+	//
+	internals.findRule = function (domain) {
+
+	  var punyDomain = Punycode.toASCII(domain);
+	  return internals.rules.reduce(function (memo, rule) {
+
+	    if (rule.punySuffix === -1){
+	      rule.punySuffix = Punycode.toASCII(rule.suffix);
+	    }
+	    if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+	      return memo;
+	    }
+	    // This has been commented out as it never seems to run. This is because
+	    // sub tlds always appear after their parents and we never find a shorter
+	    // match.
+	    //if (memo) {
+	    //  var memoSuffix = Punycode.toASCII(memo.suffix);
+	    //  if (memoSuffix.length >= punySuffix.length) {
+	    //    return memo;
+	    //  }
+	    //}
+	    return rule;
+	  }, null);
+	};
+
+
+	//
+	// Error codes and messages.
+	//
+	exports.errorCodes = {
+	  DOMAIN_TOO_SHORT: 'Domain name too short.',
+	  DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+	  LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+	  LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+	  LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+	  LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+	  LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+	};
+
+
+	//
+	// Validate domain name and throw if not valid.
+	//
+	// From wikipedia:
+	//
+	// Hostnames are composed of series of labels concatenated with dots, as are all
+	// domain names. Each label must be between 1 and 63 characters long, and the
+	// entire hostname (including the delimiting dots) has a maximum of 255 chars.
+	//
+	// Allowed chars:
+	//
+	// * `a-z`
+	// * `0-9`
+	// * `-` but not as a starting or ending character
+	// * `.` as a separator for the textual portions of a domain name
+	//
+	// * http://en.wikipedia.org/wiki/Domain_name
+	// * http://en.wikipedia.org/wiki/Hostname
+	//
+	internals.validate = function (input) {
+
+	  // Before we can validate we need to take care of IDNs with unicode chars.
+	  var ascii = Punycode.toASCII(input);
+
+	  if (ascii.length < 1) {
+	    return 'DOMAIN_TOO_SHORT';
+	  }
+	  if (ascii.length > 255) {
+	    return 'DOMAIN_TOO_LONG';
+	  }
+
+	  // Check each part's length and allowed chars.
+	  var labels = ascii.split('.');
+	  var label;
+
+	  for (var i = 0; i < labels.length; ++i) {
+	    label = labels[i];
+	    if (!label.length) {
+	      return 'LABEL_TOO_SHORT';
+	    }
+	    if (label.length > 63) {
+	      return 'LABEL_TOO_LONG';
+	    }
+	    if (label.charAt(0) === '-') {
+	      return 'LABEL_STARTS_WITH_DASH';
+	    }
+	    if (label.charAt(label.length - 1) === '-') {
+	      return 'LABEL_ENDS_WITH_DASH';
+	    }
+	    if (!/^[a-z0-9\-]+$/.test(label)) {
+	      return 'LABEL_INVALID_CHARS';
+	    }
+	  }
+	};
+
+
+	//
+	// Public API
+	//
+
+
+	//
+	// Parse domain.
+	//
+	exports.parse = function (input) {
+
+	  if (typeof input !== 'string') {
+	    throw new TypeError('Domain name must be a string.');
+	  }
+
+	  // Force domain to lowercase.
+	  var domain = input.slice(0).toLowerCase();
+
+	  // Handle FQDN.
+	  // TODO: Simply remove trailing dot?
+	  if (domain.charAt(domain.length - 1) === '.') {
+	    domain = domain.slice(0, domain.length - 1);
+	  }
+
+	  // Validate and sanitise input.
+	  var error = internals.validate(domain);
+	  if (error) {
+	    return {
+	      input: input,
+	      error: {
+	        message: exports.errorCodes[error],
+	        code: error
+	      }
+	    };
+	  }
+
+	  var parsed = {
+	    input: input,
+	    tld: null,
+	    sld: null,
+	    domain: null,
+	    subdomain: null,
+	    listed: false
+	  };
+
+	  var domainParts = domain.split('.');
+
+	  // Non-Internet TLD
+	  if (domainParts[domainParts.length - 1] === 'local') {
+	    return parsed;
+	  }
+
+	  var handlePunycode = function () {
+
+	    if (!/xn--/.test(domain)) {
+	      return parsed;
+	    }
+	    if (parsed.domain) {
+	      parsed.domain = Punycode.toASCII(parsed.domain);
+	    }
+	    if (parsed.subdomain) {
+	      parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+	    }
+	    return parsed;
+	  };
+
+	  var rule = internals.findRule(domain);
+
+	  // Unlisted tld.
+	  if (!rule) {
+	    if (domainParts.length < 2) {
+	      return parsed;
+	    }
+	    parsed.tld = domainParts.pop();
+	    parsed.sld = domainParts.pop();
+	    parsed.domain = [parsed.sld, parsed.tld].join('.');
+	    if (domainParts.length) {
+	      parsed.subdomain = domainParts.pop();
+	    }
+	    return handlePunycode();
+	  }
+
+	  // At this point we know the public suffix is listed.
+	  parsed.listed = true;
+
+	  var tldParts = rule.suffix.split('.');
+	  var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+	  if (rule.exception) {
+	    privateParts.push(tldParts.shift());
+	  }
+
+	  parsed.tld = tldParts.join('.');
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  if (rule.wildcard) {
+	    tldParts.unshift(privateParts.pop());
+	    parsed.tld = tldParts.join('.');
+	  }
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  parsed.sld = privateParts.pop();
+	  parsed.domain = [parsed.sld,  parsed.tld].join('.');
+
+	  if (privateParts.length) {
+	    parsed.subdomain = privateParts.join('.');
+	  }
+
+	  return handlePunycode();
+	};
+
+
+	//
+	// Get domain.
+	//
+	exports.get = function (domain) {
+
+	  if (!domain) {
+	    return null;
+	  }
+	  return exports.parse(domain).domain || null;
+	};
+
+
+	//
+	// Check whether domain belongs to a known public suffix.
+	//
+	exports.isValid = function (domain) {
+
+	  var parsed = exports.parse(domain);
+	  return Boolean(parsed.domain && parsed.listed);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw new RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * https://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.4.1',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) {
+				// in Node.js, io.js, or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else {
+				// in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else {
+			// in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	/*jshint unused:false */
+
+	function Store() {
+	}
+	exports.Store = Store;
+
+	// Stores may be synchronous, but are still required to use a
+	// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
+	// API that converts from synchronous-callbacks to imperative style.
+	Store.prototype.synchronous = false;
+
+	Store.prototype.findCookie = function(domain, path, key, cb) {
+	  throw new Error('findCookie is not implemented');
+	};
+
+	Store.prototype.findCookies = function(domain, path, cb) {
+	  throw new Error('findCookies is not implemented');
+	};
+
+	Store.prototype.putCookie = function(cookie, cb) {
+	  throw new Error('putCookie is not implemented');
+	};
+
+	Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // recommended default implementation:
+	  // return this.putCookie(newCookie, cb);
+	  throw new Error('updateCookie is not implemented');
+	};
+
+	Store.prototype.removeCookie = function(domain, path, key, cb) {
+	  throw new Error('removeCookie is not implemented');
+	};
+
+	Store.prototype.removeCookies = function(domain, path, cb) {
+	  throw new Error('removeCookies is not implemented');
+	};
+
+	Store.prototype.getAllCookies = function(cb) {
+	  throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var Store = __webpack_require__(17).Store;
+	var permuteDomain = __webpack_require__(19).permuteDomain;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var util = __webpack_require__(9);
+
+	function MemoryCookieStore() {
+	  Store.call(this);
+	  this.idx = {};
+	}
+	util.inherits(MemoryCookieStore, Store);
+	exports.MemoryCookieStore = MemoryCookieStore;
+	MemoryCookieStore.prototype.idx = null;
+
+	// Since it's just a struct in RAM, this Store is synchronous
+	MemoryCookieStore.prototype.synchronous = true;
+
+	// force a default depth:
+	MemoryCookieStore.prototype.inspect = function() {
+	  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+	}
+
+	MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+	  if (!this.idx[domain]) {
+	    return cb(null,undefined);
+	  }
+	  if (!this.idx[domain][path]) {
+	    return cb(null,undefined);
+	  }
+	  return cb(null,this.idx[domain][path][key]||null);
+	};
+
+	MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+	  var results = [];
+	  if (!domain) {
+	    return cb(null,[]);
+	  }
+
+	  var pathMatcher;
+	  if (!path) {
+	    // null means "all paths"
+	    pathMatcher = function matchAll(domainIndex) {
+	      for (var curPath in domainIndex) {
+	        var pathIndex = domainIndex[curPath];
+	        for (var key in pathIndex) {
+	          results.push(pathIndex[key]);
+	        }
+	      }
+	    };
+
+	  } else {
+	    pathMatcher = function matchRFC(domainIndex) {
+	       //NOTE: we should use path-match algorithm from S5.1.4 here
+	       //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+	       Object.keys(domainIndex).forEach(function (cookiePath) {
+	         if (pathMatch(path, cookiePath)) {
+	           var pathIndex = domainIndex[cookiePath];
+
+	           for (var key in pathIndex) {
+	             results.push(pathIndex[key]);
+	           }
+	         }
+	       });
+	     };
+	  }
+
+	  var domains = permuteDomain(domain) || [domain];
+	  var idx = this.idx;
+	  domains.forEach(function(curDomain) {
+	    var domainIndex = idx[curDomain];
+	    if (!domainIndex) {
+	      return;
+	    }
+	    pathMatcher(domainIndex);
+	  });
+
+	  cb(null,results);
+	};
+
+	MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+	  if (!this.idx[cookie.domain]) {
+	    this.idx[cookie.domain] = {};
+	  }
+	  if (!this.idx[cookie.domain][cookie.path]) {
+	    this.idx[cookie.domain][cookie.path] = {};
+	  }
+	  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // updateCookie() may avoid updating cookies that are identical.  For example,
+	  // lastAccessed may not be important to some stores and an equality
+	  // comparison could exclude that field.
+	  this.putCookie(newCookie,cb);
+	};
+
+	MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+	  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+	    delete this.idx[domain][path][key];
+	  }
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+	  if (this.idx[domain]) {
+	    if (path) {
+	      delete this.idx[domain][path];
+	    } else {
+	      delete this.idx[domain];
+	    }
+	  }
+	  return cb(null);
+	};
+
+	MemoryCookieStore.prototype.getAllCookies = function(cb) {
+	  var cookies = [];
+	  var idx = this.idx;
+
+	  var domains = Object.keys(idx);
+	  domains.forEach(function(domain) {
+	    var paths = Object.keys(idx[domain]);
+	    paths.forEach(function(path) {
+	      var keys = Object.keys(idx[domain][path]);
+	      keys.forEach(function(key) {
+	        if (key !== null) {
+	          cookies.push(idx[domain][path][key]);
+	        }
+	      });
+	    });
+	  });
+
+	  // Sort by creationIndex so deserializing retains the creation order.
+	  // When implementing your own store, this SHOULD retain the order too
+	  cookies.sort(function(a,b) {
+	    return (a.creationIndex||0) - (b.creationIndex||0);
+	  });
+
+	  cb(null, cookies);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	var pubsuffix = __webpack_require__(13);
+
+	// Gives the permutation of all possible domainMatch()es of a given domain. The
+	// array is in shortest-to-longest order.  Handy for indexing.
+	function permuteDomain (domain) {
+	  var pubSuf = pubsuffix.getPublicSuffix(domain);
+	  if (!pubSuf) {
+	    return null;
+	  }
+	  if (pubSuf == domain) {
+	    return [domain];
+	  }
+
+	  var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+	  var parts = prefix.split('.').reverse();
+	  var cur = pubSuf;
+	  var permutations = [cur];
+	  while (parts.length) {
+	    cur = parts.shift() + '.' + cur;
+	    permutations.push(cur);
+	  }
+	  return permutations;
+	}
+
+	exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	/*
+	 * "A request-path path-matches a given cookie-path if at least one of the
+	 * following conditions holds:"
+	 */
+	function pathMatch (reqPath, cookiePath) {
+	  // "o  The cookie-path and the request-path are identical."
+	  if (cookiePath === reqPath) {
+	    return true;
+	  }
+
+	  var idx = reqPath.indexOf(cookiePath);
+	  if (idx === 0) {
+	    // "o  The cookie-path is a prefix of the request-path, and the last
+	    // character of the cookie-path is %x2F ("/")."
+	    if (cookiePath.substr(-1) === "/") {
+	      return true;
+	    }
+
+	    // " o  The cookie-path is a prefix of the request-path, and the first
+	    // character of the request-path that is not included in the cookie- path
+	    // is a %x2F ("/") character."
+	    if (reqPath.substr(cookiePath.length, 1) === "/") {
+	      return true;
+	    }
+	  }
+
+	  return false;
+	}
+
+	exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..8d9228a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,106 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) {
+module.exports = function init(jsUtil) {
+  return {
+    parseUrl: parseUrl,
+    appendQueryParamsString: appendQueryParamsString,
+    serializeQueryParams: serializeQueryParams
+  }
+
+  function parseUrl(url) {
+    var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+    return match && {
+        protocol: match[1],
+        host: match[2],
+        hostname: match[3],
+        port: match[4] || '',
+        pathname: match[5],
+        search: match[6],
+        hash: match[7]
+    }
+  }
+
+  function appendQueryParamsString(url, params) {
+    if (!url.length || !params.length) {
+      return url;
+    }
+
+    var parsed = parseUrl(url);
+
+    return parsed.protocol
+      + '//'
+      + parsed.host
+      + parsed.pathname
+      + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+      + parsed.hash;
+  }
+
+  function serializeQueryParams(params, encode) {
+    return serializeObject('', params, encode);
+  }
+
+  function serializeObject(parentKey, object, encode) {
+    var parts = [];
+
+    for (var key in object) {
+      if (!object.hasOwnProperty(key)) {
+        continue;
+      }
+
+      var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+      if (jsUtil.getTypeOf(object[key]) === 'Array') {
+        parts.push(serializeArray(identifier, object[key], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+        parts.push(serializeObject(identifier, object[key], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeArray(parentKey, array, encode) {
+    var parts = [];
+
+    for (var i = 0; i < array.length; ++i) {
+      if (jsUtil.getTypeOf(array[i]) === 'Array') {
+        parts.push(serializeArray(parentKey + '[]', array[i], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+        parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeIdentifier(parentKey, key, encode) {
+    if (!parentKey.length) {
+      return encode ? encodeURIComponent(key) : key;
+    }
+
+    if (encode) {
+      return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+    } else {
+      return parentKey + '[' + key + ']';
+    }
+  }
+
+  function serializeValue(value, encode) {
+    if (encode) {
+      return encodeURIComponent(value);
+    } else {
+      return value;
+    }
+  }
+};
+
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3f614ec
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,188 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ *    var image = document.getElementById('myImage');
+ *    image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the  returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery.  The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified.  To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+        mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+    // XXX: commented out
+    // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ *     console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ *     alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+    exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..4f4b046
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,104 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+     * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+     * disable any image modifications (resize, quality change, cropping, etc.) due
+     * to implementation specific.
+     *
+     * @enum {number}
+     */
+    DestinationType: {
+        /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+        DATA_URL: 0,
+        /** Return file uri (content://media/external/images/media/2 for Android) */
+        FILE_URI: 1,
+        /** Return native uri (eg. asset-library://... for iOS) */
+        NATIVE_URI: 2
+    },
+    /**
+     * @enum {number}
+     */
+    EncodingType: {
+        /** Return JPEG encoded image */
+        JPEG: 0,
+        /** Return PNG encoded image */
+        PNG: 1
+    },
+    /**
+     * @enum {number}
+     */
+    MediaType: {
+        /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+        PICTURE: 0,
+        /** Allow selection of video only, ONLY RETURNS URL */
+        VIDEO: 1,
+        /** Allow selection from all media types */
+        ALLMEDIA: 2
+    },
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+     * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+     * change, cropping, etc.) due to implementation specific.
+     *
+     * @enum {number}
+     */
+    PictureSourceType: {
+        /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+        PHOTOLIBRARY: 0,
+        /** Take picture from camera */
+        CAMERA: 1,
+        /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+        SAVEDPHOTOALBUM: 2
+    },
+    /**
+     * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+     * @enum {number}
+     */
+    PopoverArrowDirection: {
+        ARROW_UP: 1,
+        ARROW_DOWN: 2,
+        ARROW_LEFT: 4,
+        ARROW_RIGHT: 8,
+        ARROW_ANY: 15
+    },
+    /**
+     * @enum {number}
+     */
+    Direction: {
+        /** Use the back-facing camera */
+        BACK: 0,
+        /** Use the front-facing camera */
+        FRONT: 1
+    }
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..81d7d20
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,55 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen.  Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js
new file mode 100644
index 0000000..08a2ab2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js
@@ -0,0 +1,69 @@
+cordova.define("cordova-plugin-camera.CameraPopoverHandle", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * A handle to an image picker popover.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.getPicture(onSuccess, onFail,
+ * {
+ *     destinationType: Camera.DestinationType.FILE_URI,
+ *     sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
+ *     popoverOptions: new CameraPopoverOptions(300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)
+ * });
+ *
+ * // Reposition the popover if the orientation changes.
+ * window.onorientationchange = function() {
+ *     var cameraPopoverHandle = new CameraPopoverHandle();
+ *     var cameraPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY);
+ *     cameraPopoverHandle.setPosition(cameraPopoverOptions);
+ * }
+ * @module CameraPopoverHandle
+ */
+var CameraPopoverHandle = function () {
+    /**
+     * Can be used to reposition the image selection dialog,
+     * for example, when the device orientation changes.
+     * @memberof CameraPopoverHandle
+     * @instance
+     * @method setPosition
+     * @param {module:CameraPopoverOptions} popoverOptions
+     */
+    this.setPosition = function (popoverOptions) {
+        var args = [ popoverOptions ];
+        exec(null, null, 'Camera', 'repositionPopover', args);
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-device/www/device.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..ae48e35
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+    this.available = false;
+    this.platform = null;
+    this.version = null;
+    this.uuid = null;
+    this.cordova = null;
+    this.model = null;
+    this.manufacturer = null;
+    this.isVirtual = null;
+    this.serial = null;
+
+    var me = this;
+
+    channel.onCordovaReady.subscribe(function () {
+        me.getInfo(function (info) {
+            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+            // TODO: CB-5105 native implementations should not return info.cordova
+            var buildLabel = cordova.version;
+            me.available = true;
+            me.platform = info.platform;
+            me.version = info.version;
+            me.uuid = info.uuid;
+            me.cordova = buildLabel;
+            me.model = info.model;
+            me.isVirtual = info.isVirtual;
+            me.manufacturer = info.manufacturer || 'unknown';
+            me.serial = info.serial || 'unknown';
+            channel.onCordovaInfoReady.fire();
+        }, function (e) {
+            me.available = false;
+            utils.alert('[ERROR] Error initializing Cordova: ' + e);
+        });
+    });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+    exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..bb676eb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,120 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+    // add trailing slash if it is missing
+    if ((fullPath) && !/\/$/.test(fullPath)) {
+        fullPath += '/';
+    }
+    // add trailing slash if it is missing
+    if (nativeURL && !/\/$/.test(nativeURL)) {
+        nativeURL += '/';
+    }
+    DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+    return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var FileEntry = require('./FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..417c85f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,75 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+    this.localURL = localURL || null;
+    this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+    // If we've already read and passed on this directory's entries, return an empty list.
+    if (this.hasReadEntries) {
+        successCallback([]);
+        return;
+    }
+    var reader = this;
+    var win = typeof successCallback !== 'function' ? null : function (result) {
+        var retVal = [];
+        for (var i = 0; i < result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('./DirectoryEntry'))();
+            } else if (result[i].isFile) {
+                entry = new (require('./FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+            entry.nativeURL = result[i].nativeURL;
+            retVal.push(entry);
+        }
+        reader.hasReadEntries = true;
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Entry.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..b296d99
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,263 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ * @param fileSystem
+ *            {FileSystem} the filesystem on which this entry resides
+ *            (readonly)
+ * @param nativeURL
+ *            {DOMString} an alternate URL which can be used by native
+ *            webview controls, for example media players.
+ *            (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+    this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function (entryMetadata) {
+        var metadata = new Metadata({
+            size: entryMetadata.size,
+            modificationTime: entryMetadata.lastModifiedDate
+        });
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+    // entry name
+    var name = newName || this.name;
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+        // entry name
+    var name = newName || this.name;
+    // success callback
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+    if (this.filesystem && this.filesystem.__format__) {
+        return this.filesystem.__format__(this.fullPath, this.nativeURL);
+    }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+    if (this.nativeURL) {
+        return this.nativeURL;
+    }
+    // fullPath attribute may contain the full URL in the case that
+    // toInternalURL fails.
+    return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var DirectoryEntry = require('./DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/File.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..c771786
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,81 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+    this.name = name || '';
+    this.localURL = localURL || null;
+    this.type = type || null;
+    this.lastModified = lastModifiedDate || null;
+    // For backwards compatibility, store the timestamp in lastModifiedDate as well
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..6651b55
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,95 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+    // remove trailing slash if it is present
+    if (fullPath && /\/$/.test(fullPath)) {
+        fullPath = fullPath.substring(0, fullPath.length - 1);
+    }
+    if (nativeURL && /\/$/.test(nativeURL)) {
+        nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+    }
+
+    FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+    this.file(function (filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.localURL === null || writer.localURL === '') {
+            if (errorCallback) {
+                errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+            }
+        } else {
+            if (successCallback) {
+                successCallback(writer);
+            }
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+    var localURL = this.toInternalURL();
+    var win = successCallback && function (f) {
+        var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileError.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..f378c38
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,49 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+    this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..5c03091
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,301 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._progress = null;
+    this._localURL = '';
+    this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+    return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+    return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+    return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+        return this._realReader[eventName] || null;
+    }, function (value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+    // Already loading something
+    if (reader.readyState === FileReader.LOADING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._progress = 0;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file.localURL === 'string') {
+        reader._localURL = file.localURL;
+    } else {
+        reader._localURL = '';
+        return true;
+    }
+
+    if (reader.onloadstart) {
+        reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+    if (readType === 'readAsDataURL') {
+        // Windows proxy does not support reading file slices as Data URLs
+        // so read the whole file at once.
+        CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+            // Calculate new chunk size for data URLs to be multiply of 3
+            // Otherwise concatenated base64 chunks won't be valid base64 data
+            FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+    }
+
+    if (typeof r !== 'undefined') {
+        accumulate(r);
+        this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+        if (typeof this.onprogress === 'function') {
+            this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+        }
+    }
+
+    if (typeof r === 'undefined' || this._progress < totalSize) {
+        var execArgs = [
+            this._localURL,
+            offset + this._progress,
+            offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+        if (encoding) {
+            execArgs.splice(1, 0, encoding);
+        }
+        exec(
+            readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+            readFailureCallback.bind(this),
+            'File', readType, execArgs);
+    } else {
+        this._readyState = FileReader.DONE;
+
+        if (typeof this.onload === 'function') {
+            this.onload(new ProgressEvent('load', {target: this}));
+        }
+
+        if (typeof this.onloadend === 'function') {
+            this.onloadend(new ProgressEvent('loadend', {target: this}));
+        }
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+    this._result = null;
+    this._error = new FileError(e);
+
+    if (typeof this.onerror === 'function') {
+        this.onerror(new ProgressEvent('error', {target: this}));
+    }
+
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+    if (origFileReader && !this._localURL) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target: this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding || 'UTF-8';
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+        var commaIndex = r.indexOf(',');
+        if (this._progress === 0) {
+            this._result = r;
+        } else {
+            this._result += r.substring(commaIndex + 1);
+        }
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+        var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+        resultArray.set(new Uint8Array(r), this._progress);
+        this._result = resultArray.buffer;
+    }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..ad9ea78
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,58 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+    this.name = name;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+    } else {
+        this.root = new DirectoryEntry(this.name, '/', this);
+    }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+    return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+    return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+    // Because # is a valid filename character, it must be encoded to prevent part of the
+    // path from being parsed as a URI fragment.
+    return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..6acd093
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,44 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String}   Name of file request parameter.
+ * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object}    Object with key: value params to send to the server.
+ * @param headers {Object}   Keys are header names, values are header values. Multiple
+ *                           headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+    this.fileKey = fileKey || null;
+    this.fileName = fileName || null;
+    this.mimeType = mimeType || null;
+    this.params = params || null;
+    this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..e3c3a74
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+    this.bytesSent = size;
+    this.responseCode = code;
+    this.response = content;
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..d48a089
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,327 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+    this.fileName = '';
+    this.length = 0;
+    if (file) {
+        this.localURL = file.localURL || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {'target': this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === 'function') {
+        this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+    var that = this;
+    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+    /* eslint-disable no-undef */
+    var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+    var isBinary;
+
+    // Check to see if the incoming data is a blob
+    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+        var fileReader = new FileReader();
+        /* eslint-enable no-undef */
+        fileReader.onload = function () {
+            // Call this method again, with the arraybuffer as argument
+            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+        };
+        fileReader.onerror = function () {
+            // DONE state
+            that.readyState = FileWriter.DONE;
+
+            // Save error
+            that.error = this.error;
+
+            // If onerror callback
+            if (typeof that.onerror === 'function') {
+                that.onerror(new ProgressEvent('error', {'target': that}));
+            }
+
+            // If onwriteend callback
+            if (typeof that.onwriteend === 'function') {
+                that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+            }
+        };
+
+        // WRITING state
+        this.readyState = FileWriter.WRITING;
+
+        if (supportsBinary) {
+            fileReader.readAsArrayBuffer(data);
+        } else {
+            fileReader.readAsText(data);
+        }
+        return;
+    }
+
+    // Mark data type for safer transport over the binary bridge
+    isBinary = supportsBinary && (data instanceof ArrayBuffer);
+    if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+        data = Array.apply(null, new Uint8Array(data));
+    }
+
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset && offset !== 0) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    // Offset is bigger than file size so set position
+    // to the end of the file.
+    } else if (offset > this.length) {
+        this.position = this.length;
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    } else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Flags.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..cdb12bb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,39 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags (create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..4ce6848
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,26 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..22366e1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+    if (typeof metadata === 'object') {
+        this.modificationTime = new Date(metadata.modificationTime);
+        this.size = metadata.size || 0;
+    } else if (typeof metadata === 'undefined') {
+        this.modificationTime = null;
+        this.size = 0;
+    } else {
+        /* Backwards compatiblity with platforms that only return a timestamp */
+        this.modificationTime = new Date(metadata);
+    }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..cbecdb1
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,70 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+    return function ProgressEvent (type, dict) {
+        this.type = type;
+        this.bubbles = false;
+        this.cancelBubble = false;
+        this.cancelable = false;
+        this.lengthComputable = false;
+        this.loaded = dict && dict.loaded ? dict.loaded : 0;
+        this.total = dict && dict.total ? dict.total : 0;
+        this.target = dict && dict.target ? dict.target : null;
+    };
+    // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..c74fd9c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+ */

+

+module.exports = function () {

+    // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and

+    // possibly a good flag to indicate that we're running in Chrome

+    return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;

+};

+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..4bfc0f6
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,65 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+    documentsDirectory: null,
+    // BlackBerry10: Files globally available to all apps
+    sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+    function after (paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems-roots.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
new file mode 100644
index 0000000..9351132
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems-roots.js
@@ -0,0 +1,47 @@
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+    function success (response) {
+        fsMap = {};
+        for (var i = 0; i < response.length; ++i) {
+            var fsRoot = response[i];
+            var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+            fsMap[fs.name] = fs;
+        }
+        callback(fsMap[name]);
+    }
+
+    if (fsMap) {
+        callback(fsMap[name]);
+    } else {
+        exec(success, null, 'File', 'requestAllFileSystems', []);
+    }
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..e61ceaf
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+    callback(null);
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ios/FileSystem.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ios/FileSystem.js
new file mode 100644
index 0000000..551b515
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/ios/FileSystem.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.iosFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+/* eslint no-undef : 0 */
+FILESYSTEM_PROTOCOL = 'cdvfile';
+
+module.exports = {
+    __format__: function (fullPath) {
+        var path = ('/' + this.name + (fullPath[0] === '/' ? '' : '/') + FileSystem.encodeURIPath(fullPath)).replace('//', '/');
+        return FILESYSTEM_PROTOCOL + '://localhost' + path;
+    }
+};
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..7f65219
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,84 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // For browser platform: not all browsers use this file.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var FileError = require('./FileError');
+    var FileSystem = require('./FileSystem');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Request a file system in which to store application data.
+     * @param type  local file system type
+     * @param size  indicates how much storage space, in bytes, the application expects to need
+     * @param successCallback  invoked with a FileSystem object
+     * @param errorCallback  invoked if error occurs retrieving file system
+     */
+    var requestFileSystem = function (type, size, successCallback, errorCallback) {
+        argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+        var fail = function (code) {
+            if (errorCallback) {
+                errorCallback(new FileError(code));
+            }
+        };
+
+        if (type < 0) {
+            fail(FileError.SYNTAX_ERR);
+        } else {
+            // if successful, return a FileSystem object
+            var success = function (file_system) {
+                if (file_system) {
+                    if (successCallback) {
+                        fileSystems.getFs(file_system.name, function (fs) {
+                            // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                            if (!fs) {
+                                fs = new FileSystem(file_system.name, file_system.root);
+                            }
+                            successCallback(fs);
+                        });
+                    }
+                } else {
+                    // no FileSystem object returned
+                    fail(FileError.NOT_FOUND_ERR);
+                }
+            };
+            exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+        }
+    };
+
+    module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..73715bc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Look up file system Entry referred to by local URI.
+     * @param {DOMString} uri  URI referring to a local file or directory
+     * @param successCallback  invoked with Entry object corresponding to URI
+     * @param errorCallback    invoked if error occurs retrieving file system entry
+     */
+    module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+        argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+        // error callback
+        var fail = function (error) {
+            if (errorCallback) {
+                errorCallback(new FileError(error));
+            }
+        };
+        // sanity check for 'not:valid:filename' or '/not:valid:filename'
+        // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+        if (!uri || uri.split(':').length > 2) {
+            setTimeout(function () {
+                fail(FileError.ENCODING_ERR);
+            }, 0);
+            return;
+        }
+        // if successful, return either a file or directory entry
+        var success = function (entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+                    fileSystems.getFs(fsName, function (fs) {
+                        // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                        if (!fs) {
+                            fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+                        }
+                        var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+                        successCallback(result);
+                    });
+                }
+            } else {
+                // no Entry object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+        exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+    };
+
+    module.exports.resolveLocalFileSystemURI = function () {
+        console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+        module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+    };
+})();
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..3982139
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
+/*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "authenticate",
+    [params]
+  );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "isAvailable",
+    [{}]
+  );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..a3021c2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,118 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // special patch to correctly work on Ripple emulator (CB-9760)
+    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+        module.exports = window.open.bind(window); // fallback to default window.open behaviour
+        return;
+    }
+
+    var exec = require('cordova/exec');
+    var channel = require('cordova/channel');
+    var modulemapper = require('cordova/modulemapper');
+    var urlutil = require('cordova/urlutil');
+
+    function InAppBrowser () {
+        this.channels = {
+            'loadstart': channel.create('loadstart'),
+            'loadstop': channel.create('loadstop'),
+            'loaderror': channel.create('loaderror'),
+            'exit': channel.create('exit'),
+            'customscheme': channel.create('customscheme')
+        };
+    }
+
+    InAppBrowser.prototype = {
+        _eventHandler: function (event) {
+            if (event && (event.type in this.channels)) {
+                this.channels[event.type].fire(event);
+            }
+        },
+        close: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'close', []);
+        },
+        show: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'show', []);
+        },
+        hide: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'hide', []);
+        },
+        addEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].subscribe(f);
+            }
+        },
+        removeEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].unsubscribe(f);
+            }
+        },
+
+        executeScript: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('executeScript requires exactly one of code or file to be specified');
+            }
+        },
+
+        insertCSS: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('insertCSS requires exactly one of code or file to be specified');
+            }
+        }
+    };
+
+    module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+        // Don't catch calls that write to existing frames (e.g. named iframes).
+        if (window.frames && window.frames[strWindowName]) {
+            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+            return origOpenFunc.apply(window, arguments);
+        }
+
+        strUrl = urlutil.makeAbsolute(strUrl);
+        var iab = new InAppBrowser();
+
+        callbacks = callbacks || {};
+        for (var callbackName in callbacks) {
+            iab.addEventListener(callbackName, callbacks[callbackName]);
+        }
+
+        var cb = function (eventname) {
+            iab._eventHandler(eventname);
+        };
+
+        strWindowFeatures = strWindowFeatures || '';
+
+        exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+        return iab;
+    };
+})();
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..2469e9e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,344 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) {
+// This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+  switch (string) {
+    case '1':
+      return true;
+    case '0':
+      return false;
+    default:
+    throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+  }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+  return {
+    authorized: stringToBool(statusDictionary.authorized),
+    denied: stringToBool(statusDictionary.denied),
+    restricted: stringToBool(statusDictionary.restricted),
+    prepared: stringToBool(statusDictionary.prepared),
+    scanning: stringToBool(statusDictionary.scanning),
+    previewing: stringToBool(statusDictionary.previewing),
+    showing: stringToBool(statusDictionary.showing),
+    lightEnabled: stringToBool(statusDictionary.lightEnabled),
+    canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+    canEnableLight: stringToBool(statusDictionary.canEnableLight),
+    canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+    currentCamera: parseInt(statusDictionary.currentCamera)
+  };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+  var body = document.body;
+  if (body.style) {
+    body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+    body.style.backgroundImage = '';
+    setTimeout(function() {
+      body.style.backgroundColor = 'transparent';
+    }, 1);
+    if (body.parentNode && body.parentNode.style) {
+      body.parentNode.style.backgroundColor = 'transparent';
+      body.parentNode.style.backgroundImage = '';
+    }
+  }
+}
+
+function errorCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(error) {
+    var errorCode = parseInt(error);
+    var QRScannerError = {};
+    switch (errorCode) {
+      case 0:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner experienced an unexpected error.'
+        };
+        break;
+      case 1:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_DENIED',
+          code: 1,
+          _message: 'The user denied camera access.'
+        };
+        break;
+      case 2:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_RESTRICTED',
+          code: 2,
+          _message: 'Camera access is restricted.'
+        };
+        break;
+      case 3:
+        QRScannerError = {
+          name: 'BACK_CAMERA_UNAVAILABLE',
+          code: 3,
+          _message: 'The back camera is unavailable.'
+        };
+        break;
+      case 4:
+        QRScannerError = {
+          name: 'FRONT_CAMERA_UNAVAILABLE',
+          code: 4,
+          _message: 'The front camera is unavailable.'
+        };
+        break;
+      case 5:
+        QRScannerError = {
+          name: 'CAMERA_UNAVAILABLE',
+          code: 5,
+          _message: 'The camera is unavailable.'
+        };
+        break;
+      case 6:
+        QRScannerError = {
+          name: 'SCAN_CANCELED',
+          code: 6,
+          _message: 'Scan was canceled.'
+        };
+        break;
+      case 7:
+        QRScannerError = {
+          name: 'LIGHT_UNAVAILABLE',
+          code: 7,
+          _message: 'The device light is unavailable.'
+        };
+        break;
+      case 8:
+        // Open settings is only available on iOS 8.0+.
+        QRScannerError = {
+          name: 'OPEN_SETTINGS_UNAVAILABLE',
+          code: 8,
+          _message: 'The device is unable to open settings.'
+        };
+        break;
+      default:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner returned an invalid error code.'
+        };
+        break;
+    }
+    callback(QRScannerError);
+  };
+}
+
+function successCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    callback(null, convertStatus(statusDict));
+  };
+}
+
+function doneCallback(callback, clear) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    if (clear) {
+      clearBackground();
+    }
+    callback(convertStatus(statusDict));
+  };
+}
+
+return {
+  prepare: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+  },
+  destroy: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+  },
+  scan: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to scan method.');
+    }
+    var success = function(result) {
+      callback(null, result);
+    };
+    cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+  },
+  cancelScan: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+  },
+  show: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+  },
+  hide: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+  },
+  pausePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+  },
+  resumePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+  },
+  enableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+  },
+  disableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+  },
+  useCamera: function(index, callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+  },
+  useFrontCamera: function(callback) {
+    var frontCamera = 1;
+    if (callback) {
+      this.useCamera(frontCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+    }
+  },
+  useBackCamera: function(callback) {
+    var backCamera = 0;
+    if (callback) {
+      this.useCamera(backCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+    }
+  },
+  openSettings: function(callback) {
+    if (callback) {
+      cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+    }
+  },
+  getStatus: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to getStatus method.');
+    }
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+  }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..708186f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,116 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+    "black": "#000000",
+    "darkGray": "#A9A9A9",
+    "lightGray": "#D3D3D3",
+    "white": "#FFFFFF",
+    "gray": "#808080",
+    "red": "#FF0000",
+    "green": "#00FF00",
+    "blue": "#0000FF",
+    "cyan": "#00FFFF",
+    "yellow": "#FFFF00",
+    "magenta": "#FF00FF",
+    "orange": "#FFA500",
+    "purple": "#800080",
+    "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+    isVisible: true,
+
+    overlaysWebView: function (doOverlay) {
+        exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+    },
+
+    styleDefault: function () {
+        // dark text ( to be used on a light background )
+        exec(null, null, "StatusBar", "styleDefault", []);
+    },
+
+    styleLightContent: function () {
+        // light text ( to be used on a dark background )
+        exec(null, null, "StatusBar", "styleLightContent", []);
+    },
+
+    styleBlackTranslucent: function () {
+        // #88000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+    },
+
+    styleBlackOpaque: function () {
+        // #FF000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackOpaque", []);
+    },
+
+    backgroundColorByName: function (colorname) {
+        return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+    },
+
+    backgroundColorByHexString: function (hexString) {
+        if (hexString.charAt(0) !== "#") {
+            hexString = "#" + hexString;
+        }
+
+        if (hexString.length === 4) {
+            var split = hexString.split("");
+            hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+        }
+
+        exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+    },
+
+    hide: function () {
+        exec(null, null, "StatusBar", "hide", []);
+        StatusBar.isVisible = false;
+    },
+
+    show: function () {
+        exec(null, null, "StatusBar", "show", []);
+        StatusBar.isVisible = true;
+    }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+    exec(function (res) {
+        if (typeof res == 'object') {
+            if (res.type == 'tap') {
+                cordova.fireWindowEvent('statusTap');
+            }
+        } else {
+            StatusBar.isVisible = res;
+        }
+    }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
new file mode 100644
index 0000000..9c935cb
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
@@ -0,0 +1,121 @@
+cordova.define("cordova-plugin-themeablebrowser.themeablebrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+function ThemeableBrowser() {
+   this.channels = {};
+}
+
+ThemeableBrowser.prototype = {
+    _eventHandler: function (event) {
+        if (event && (event.type in this.channels)) {
+            this.channels[event.type].fire(event);
+        }
+    },
+    close: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'close', []);
+        return this;
+    },
+    show: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'show', []);
+        return this;
+    },
+    reload: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'reload', []);
+        return this;
+    },
+    addEventListener: function (eventname,f) {
+        if (!(eventname in this.channels)) {
+            this.channels[eventname] = channel.create(eventname);
+        }
+        this.channels[eventname].subscribe(f);
+        return this;
+    },
+    removeEventListener: function(eventname, f) {
+        if (eventname in this.channels) {
+            this.channels[eventname].unsubscribe(f);
+        }
+        return this;
+    },
+
+    executeScript: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('executeScript requires exactly one of code or file to be specified');
+        }
+        return this;
+    },
+
+    insertCSS: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('insertCSS requires exactly one of code or file to be specified');
+        }
+        return this;
+    }
+};
+
+exports.open = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
+    // Don't catch calls that write to existing frames (e.g. named iframes).
+    if (window.frames && window.frames[strWindowName]) {
+        var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+        return origOpenFunc.apply(window, arguments);
+    }
+
+    strUrl = urlutil.makeAbsolute(strUrl);
+    var iab = new ThemeableBrowser();
+
+    callbacks = callbacks || {};
+    for (var callbackName in callbacks) {
+        iab.addEventListener(callbackName, callbacks[callbackName]);
+    }
+
+    var cb = function(eventname) {
+       iab._eventHandler(eventname);
+    };
+
+    strWindowFeatures = strWindowFeatures && JSON.stringify(strWindowFeatures);
+    // Slightly delay the actual native call to give the user a chance to
+    // register event listeners first, otherwise some warnings or errors may be missed.
+    setTimeout(function() {
+        exec(cb, cb, 'ThemeableBrowser', 'open', [strUrl, strWindowName, strWindowFeatures || '']);
+    }, 0);
+    return iab;
+};
+
+exports.EVT_ERR = 'ThemeableBrowserError';
+exports.EVT_WRN = 'ThemeableBrowserWarning';
+exports.ERR_CRITICAL = 'critical';
+exports.ERR_LOADFAIL = 'loadfail';
+exports.WRN_UNEXPECTED = 'unexpected';
+exports.WRN_UNDEFINED = 'undefined';
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..38a3a85
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) {
+function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+  if (!window.plugins) {
+    window.plugins = {};
+  }
+
+  window.plugins.touchid = new TouchID();
+  return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/pwdset.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/pwdset.html
new file mode 100644
index 0000000..fc201aa
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/pwdset.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>设置登录密码</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">设置登录密码</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">登录密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="pwd" placeholder="6位以上字符">
+                </div>
+            </div>
+            <div class="weui-cell">
+                <div class="weui-cell__hd"><label class="weui-label">确认密码</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="password" id="repwd" placeholder="请再次确认密码">
+                </div>
+            </div>
+        </div>
+        <div style="padding: 20px;">
+            <a href="javascript:app.doRegister();" class="weui-btn weui-btn_primary">保存</a>
+        </div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/pwdset.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/qrcode.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/qrcode.html
new file mode 100644
index 0000000..3391537
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/qrcode.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>付款码</title>
+</head>
+<body style="background: #fff"  >
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">付款码</div>
+    </header>
+    <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;margin-top: 50px;">
+        <div style="background: #fff;text-align: center;" id="qrcode"></div>
+    </div>
+    <p style="text-align: center;margin-top:20px;color:#999">请将二维码对准扫描设备</p>
+    <div style="padding: 30px;">
+        <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.refresh()">手动刷新二维码</div>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/qrcode.min.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/qrcode.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/register.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/register.html
new file mode 100644
index 0000000..34e5998
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/register.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>注册绑定</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="login.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">注册</div>
+    </header>
+    <div>
+        <div class="weui-cells weui-cells_form">
+            <div class="weui-cell" style="padding:0 10px; "> 
+                <div class="weui-cell__hd"><label class="weui-label" style="width: 80px;font-size: 14px;">手机号</label></div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="phone" style="font-size: 14px;" placeholder="请输入市民卡预留的手机号" maxlength="11">
+                </div>
+            </div>
+            <div class="weui-cell weui-cell_vcode" style="padding:0 10px; ">
+                <div class="weui-cell__hd">
+                    <label class="weui-label" style="width: 80px;font-size: 14px;">验证码</label>
+                </div>
+                <div class="weui-cell__bd">
+                    <input class="weui-input" type="tel" id="code" style="font-size: 14px;" placeholder="请输入验证码" maxlength="6">
+                </div>
+                <div class="weui-cell__ft">
+                    <button class="weui-vcode-btn" onclick="app.getCode()" id="codebtn" style="width: 100px;height: 1rem;font-size: 14px;">获取验证码</button>
+                </div>
+            </div>
+        </div>
+        <div>
+            <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+                <input id="agree" type="checkbox" class="weui-agree__checkbox" value="1">
+                <span class="weui-agree__text">
+                    我已阅读并同意
+                </span>
+            </label>
+            <a href="uxy.html" style="font-size: 13px;">《用户协议与隐私条款》</a>
+        </div>
+        <section class="aui-content-padded" style="margin-top: 30px;">
+            <div class="aui-btn aui-btn-block aui-btn-info" tapmode onclick="app.doRegister()">注册</div>
+        </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/register.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/scan.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/scan.html
new file mode 100644
index 0000000..9907fa0
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/scan.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>大理市民卡</title>
+</head>
+
+<body style="background: transparent none !important;">
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:app.goPage()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">扫一扫</div>
+        <a class="aui-pull-right aui-btn " id="lightBtn">
+            <img src="img/light.png">
+        </a>
+    </header>
+    <div class="qrscanner">
+        <div class="qrscanner-area">
+        </div>
+        <div class="through-line"></div>
+    </div>
+    <!--<div class="footer ">
+        <div class="align-center">
+            <button class="icon ion-flash" id="lightBtn"></button>
+        </div>
+    </div>-->
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/scan.js"></script>
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/security.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/security.html
new file mode 100644
index 0000000..d9811ec
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/security.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>账户安全</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">账户安全</div>
+    </header>
+    <section class="aui-content aui-margin-b-15 aui-margin-t-10">
+        <ul class="aui-list aui-list-in aui-margin-t-10 ">
+            <li class="aui-list-item" onclick="app.editPwd()">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-lock aui-text-info"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">登录密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+            <li class="aui-list-item" onclick="app.toPayPwd()">
+                <div class="aui-list-item-label-icon">
+                    <i class="aui-iconfont aui-icon-pencil aui-text-danger"></i>
+                </div>
+                <div class="aui-list-item-inner aui-list-item-arrow">
+                    <div class="aui-list-item-title">支付密码</div>
+                    <div class="aui-list-item-right"></div>
+                </div>
+            </li>
+        </ul>
+         <div style="padding: 20px;margin-top: 40px;">
+            <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
+        </div>
+    </section>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/lib/aui-dialog.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/security.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxy.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxy.html
new file mode 100644
index 0000000..cb0f1ba
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxy.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>签约代扣免密支付协议</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="main.html">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">签约代扣免密支付协议</div>
+    </header>
+    <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:135px;left: 0;right: 0" id="content">
+        
+    </div>
+    <div class="weui-footer weui-footer_fixed-bottom" style="background: #fff;display: none;" id="btn">
+            <div style="margin-top: 10px;">
+                <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+                    <input id="agree" type="checkbox" class="weui-agree__checkbox" value="yes">
+                    <span class="weui-agree__text">
+                        我已阅读并同意该协议
+                    </span>
+                </label>
+            </div>
+            <section class="aui-content-padded" style="margin-top: 20px;">
+                <div class="aui-btn aui-btn-block aui-btn-info"  tapmode onclick="app.agreeXY()">签约代扣协议</div>
+            </section>
+    </div>
+</body>
+
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/signxy.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxycheck.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxycheck.html
new file mode 100644
index 0000000..ece02b5
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/signxycheck.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>签约代扣免密支付协议</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="javascript:window.history.back()">
+            <span class="aui-iconfont aui-icon-left"></span>
+        </a>
+        <div class="aui-title">签约代扣免密支付协议</div>
+    </header>
+    <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:135px;left: 0;right: 0" id="content">
+        
+    </div>
+    <div class="weui-footer weui-footer_fixed-bottom" style="background: #fff;display: none;" id="btn">
+            <div style="margin-top: 10px;">
+                <label for="agree" class="weui-agree" style="padding: .5em 5px .5em 15px;display: inline-block;">
+                    <input id="agree" type="checkbox" class="weui-agree__checkbox" value="yes">
+                    <span class="weui-agree__text">
+                        我已阅读并同意该协议
+                    </span>
+                </label>
+            </div>
+            <section class="aui-content-padded" style="margin-top: 20px;">
+                <div class="aui-btn aui-btn-block aui-btn-info"  tapmode onclick="app.agreeXY()">签约代扣协议</div>
+            </section>
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
+<script type="text/javascript" src="js/signxycheck.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/uxy.html b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/uxy.html
new file mode 100644
index 0000000..319f8fc
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/Products/Applications/dlapp.app/www/uxy.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <link rel="stylesheet" type="text/css" href="mobileui/style.css">
+    <meta name="format-detection" content="telephone=no">
+    <meta charset="utf-8">
+    <meta name="msapplication-tap-highlight" content="no">
+    <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
+    <link rel="stylesheet" type="text/css" href="css/index.css">
+    <link rel="stylesheet" type="text/css" href="css/aui.css">
+    <link rel="stylesheet" type="text/css" href="css/weui.min.css">
+    <link rel="stylesheet" type="text/css" href="css/jquery-weui.min.css">
+    <title>用户协议与隐私条款</title>
+</head>
+<body>
+    <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
+        <a class="aui-pull-left" href="register.html">
+            <span class="aui-iconfont aui-icon-close"></span>
+        </a>
+        <div class="aui-title">用户协议与隐私条款</div>
+    </header>
+    <div style="padding:10px;overflow: scroll;position: absolute;top:74px;bottom:5px;left: 0;right: 0" id="content">
+本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。
+<br>
+1. 适用范围<br>
+
+(a) 在您注册本应用帐号时,您根据本应用要求提供的个人注册信息;<br>
+
+(b) 在您使用本应用网络服务,或访问本应用平台网页时,本应用自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;
+<br>
+(c) 本应用通过合法途径从商业伙伴处取得的用户个人数据。<br>
+
+您了解并同意,以下信息不适用本隐私权政策:<br>
+
+(a) 您在使用本应用平台提供的搜索服务时输入的关键字信息;<br>
+
+(b) 本应用收集到的您在本应用发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;<br>
+
+(c) 违反法律规定或违反本应用规则行为及本应用已对您采取的措施。<br>
+
+2. 信息使用<br>
+(a)本应用不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先得到您的许可,或该第三方和本应用(含本应用关联公司)单独或共同为您提供服务,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。
+<br>
+(b) 本应用亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。任何本应用平台用户如从事上述活动,一经发现,本应用有权立即终止与该用户的服务协议。
+<br>
+(c) 为服务用户的目的,本应用可能通过使用您的个人信息,向您提供您感兴趣的信息,包括但不限于向您发出产品和服务信息,或者与本应用合作伙伴共享信息以便他们向您发送有关其产品和服务的信息(后者需要您的事先同意)。
+<br>
+3. 信息披露<br>
+
+在如下情况下,本应用将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息:
+<br>
+(a) 经您事先同意,向第三方披露;
+<br>
+(b)为提供您所要求的产品和服务,而必须和第三方分享您的个人信息;
+<br>
+(c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;
+<br>
+(d) 如您出现违反中国有关法律、法规或者本应用服务协议或相关规则的情况,需要向第三方披露;
+<br>
+(e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;
+<br>
+(f) 在本应用平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,本应用有权决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决。
+<br>
+(g) 其它本应用根据法律、法规或者网站政策认为合适的披露。
+<br>
+4. 信息存储和交换
+<br>
+本应用收集的有关您的信息和资料将保存在本应用及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或本应用收集信息和资料所在地的境外并在境外被访问、存储和展示。
+<br>
+5. Cookie的使用
+<br>
+(a) 在您未拒绝接受cookies的情况下,本应用会在您的计算机上设定或取用cookies ,以便您能登录或使用依赖于cookies的本应用平台服务或功能。本应用使用cookies可为您提供更加周到的个性化服务,包括推广服务。
+<br>
+(b) 您有权选择接受或拒绝接受cookies。您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能无法登录或使用依赖于cookies的本应用网络服务或功能。
+<br>
+(c) 通过本应用所设cookies所取得的有关信息,将适用本政策。
+<br>
+6. 信息安全
+<br>
+(a) 本应用帐号均有安全保护功能,请妥善保管您的用户名及密码信息。本应用将通过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施,但同时也请您注意在信息网络上不存在“完善的安全措施”。
+<br>
+(b) 在使用本应用网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对
+<br>
+7.本隐私政策的更改
+<br>
+(a)如果决定更改隐私政策,我们会在本政策中、本公司网站中以及我们认为适当的位置发布这些更改,以便您了解我们如何收集、使用您的个人信息,哪些人可以访问这些信息,以及在什么情况下我们会透露这些信息。
+<br>
+(b)本公司保留随时修改本政策的权利,因此请经常查看。如对本政策作出重大更改,本公司会通过网站通知的形式告知。
+<br>
+方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,尤其是本应用用户名及密码发生泄露,请您立即联络本应用客服,以便本应用采取相应措施。
+<br>
+
+
+    </div>
+</body>
+</html>
+<script type="text/javascript" src="cordova.js"></script>
+<script type="text/javascript" src="js/lib/jquery-2.1.4.js"></script>
+<script type="text/javascript" src="js/lib/jquery-weui.js"></script>
+<script type="text/javascript" src="js/uxy.js"></script>
+<script type="text/javascript" src="js/server.js"></script>
\ No newline at end of file
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftAVFoundation.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftAVFoundation.dylib
new file mode 100755
index 0000000..5fb5c5b
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftAVFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCore.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCore.dylib
new file mode 100755
index 0000000..540c68c
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCore.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreAudio.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreAudio.dylib
new file mode 100755
index 0000000..8da548f
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreAudio.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreFoundation.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreFoundation.dylib
new file mode 100755
index 0000000..f430d8e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreGraphics.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreGraphics.dylib
new file mode 100755
index 0000000..5efc6a7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreGraphics.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreImage.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreImage.dylib
new file mode 100755
index 0000000..062df03
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreImage.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreMedia.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreMedia.dylib
new file mode 100755
index 0000000..1e51062
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftCoreMedia.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDarwin.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDarwin.dylib
new file mode 100755
index 0000000..9c40b47
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDarwin.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDispatch.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDispatch.dylib
new file mode 100755
index 0000000..c65c667
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftDispatch.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftFoundation.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftFoundation.dylib
new file mode 100755
index 0000000..6fa3d4a
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftFoundation.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftMetal.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftMetal.dylib
new file mode 100755
index 0000000..320f18e
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftMetal.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftObjectiveC.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftObjectiveC.dylib
new file mode 100755
index 0000000..52adab7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftObjectiveC.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftQuartzCore.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftQuartzCore.dylib
new file mode 100755
index 0000000..bf2c02d
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftQuartzCore.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftSwiftOnoneSupport.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftSwiftOnoneSupport.dylib
new file mode 100755
index 0000000..a6867c2
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftSwiftOnoneSupport.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftUIKit.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftUIKit.dylib
new file mode 100755
index 0000000..e0985e7
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftUIKit.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftos.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftos.dylib
new file mode 100755
index 0000000..5067145
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftos.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftsimd.dylib b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftsimd.dylib
new file mode 100755
index 0000000..09ab380
--- /dev/null
+++ b/platforms/ios/dlapp.xcarchive/SwiftSupport/iphoneos/libswiftsimd.dylib
Binary files differ
diff --git a/platforms/ios/dlapp.xcodeproj/project.pbxproj b/platforms/ios/dlapp.xcodeproj/project.pbxproj
new file mode 100755
index 0000000..70728ef
--- /dev/null
+++ b/platforms/ios/dlapp.xcodeproj/project.pbxproj
@@ -0,0 +1,660 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+/* Begin PBXBuildFile section */
+		0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0207DA571B56EA530066E2B4 /* Images.xcassets */; };
+		0FBFC45D12B44FF79785B959 /* UIImage+CropScaleOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 281DF600F6B747808087E4FC /* UIImage+CropScaleOrientation.m */; };
+		1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; };
+		1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+		2FE26256C715470F8240C690 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2625E3AABA8145E6901F06D3 /* SystemConfiguration.framework */; };
+		301BF552109A68D80062928A /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 301BF535109A57CC0062928A /* libCordova.a */; settings = {ATTRIBUTES = (Required, ); }; };
+		302D95F114D2391D003F00A1 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D95EF14D2391D003F00A1 /* MainViewController.m */; };
+		302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 302D95F014D2391D003F00A1 /* MainViewController.xib */; };
+		3772C27945674D8D9D6BA455 /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1AE7251084FD2876E0BF5 /* AFURLRequestSerialization.m */; };
+		5E2BDB8CFE4E41F39241956C /* CordovaHttpPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 07B9D06BD3024E0FBFF74967 /* CordovaHttpPlugin.m */; };
+		5F67F2BDBB534EF4A4F1F319 /* BinaryResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F753C8AE424EAE851FA1FD /* BinaryResponseSerializer.m */; };
+		5F8969599D7F41909F597D14 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FEED8E986814AC1AC60FC28 /* AFNetworkReachabilityManager.m */; };
+		6561A2871EB1420892CDE701 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04B5E1A8BB504B8FB8CE9627 /* AFHTTPSessionManager.m */; };
+		6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */; };
+		6F6B3ADF72094BF58EF5C4AC /* CDVJpegHeaderWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1836D178C8A74923B944A79E /* CDVJpegHeaderWriter.m */; };
+		6FB343627AC8409CB2AA79B7 /* CDVInAppBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 607F51FCFC7C4062A93BD011 /* CDVInAppBrowser.m */; };
+		74A56CC7F6724870ABD136F2 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11A34CB026314A2AA98A0044 /* AVFoundation.framework */; };
+		74C07CC128F9457AB281916E /* TextRequestSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDBB5C64D17465C9452AF28 /* TextRequestSerializer.m */; };
+		78A785FAE16943908BA7B6DB /* CDVFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3651F245114E52ABEB9060 /* CDVFile.m */; };
+		7D8430D010A848FBBA5FB7ED /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5192EB17EA164DFD80D433E4 /* ImageIO.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+		8ABB6F36D85243238622D4F8 /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3A85B8119074F699E1A15CD /* LocalAuthentication.framework */; };
+		8E2516CFE16944B8B9702955 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = BA6C5B1A6A6A488790CA41EB /* AFSecurityPolicy.m */; };
+		90E2E49D3A2449AB8D4D82D0 /* TextResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 57E66D7A151D45828ED66B7F /* TextResponseSerializer.m */; };
+		9224D3CE70AE4072BBEB170D /* CDVLocalFilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A8DD2DDC8694A97A56F9FA7 /* CDVLocalFilesystem.m */; };
+		94868B10923A4508B06A4310 /* CDVAssetLibraryFilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = A719A69FD70D4CC9B8104FF6 /* CDVAssetLibraryFilesystem.m */; };
+		A42AE846FF7B482FB889AAEB /* QRScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8478FFD487C4004A1CEFCA8 /* QRScanner.swift */; };
+		B69FF513D1EE4772AFF6050B /* Fingerprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2099240B64744E08C91C285 /* Fingerprint.swift */; };
+		B8EFB66D03A44372A240B05B /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 80B448E71F8941268B78692C /* CDVCamera.m */; };
+		BC39BA77AF0D4F94BC27666A /* CDVDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = A50DE9801E5E4302A78D569C /* CDVDevice.m */; };
+		BC998F935D174204820F4015 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 22AE2683802B4CB1BAF69ABF /* AFURLSessionManager.m */; };
+		C61263FC7FE642E9B25A81E5 /* DisableStatusbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 61106E22F1D348DDBDC4DC0B /* DisableStatusbar.m */; };
+		CAE5A91F948A472F9D872EC8 /* CDVStatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ABBE12B040548F8909BFC7B /* CDVStatusBar.m */; };
+		D2F2072984AE43BCBD0A430D /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D1F25845F964D87B880BFA9 /* CoreLocation.framework */; };
+		D404D18DD0114DA787E0BB43 /* SDNetworkActivityIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 148A2122F3E242E4AF09A28D /* SDNetworkActivityIndicator.m */; };
+		D834895F80744E0F96D59047 /* TouchID.m in Sources */ = {isa = PBXBuildFile; fileRef = B3CE13EED96B44C0B06B1B2C /* TouchID.m */; };
+		F46AE1B50D8B4A81B05D4100 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A673D8D8920E4086A9152FC4 /* Security.framework */; };
+		F939AD8D22BB769B006B371B /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F939AD8C22BB769B006B371B /* libsqlite3.0.tbd */; };
+		FDE92C386167415E8040F8AB /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = FDEE8379D7A34C55A616F700 /* AFURLResponseSerialization.m */; };
+		4F83621E48F143429B20FB3A /* CDVThemeableBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 28B91F31B6FD410AAF87BBDC /* CDVThemeableBrowser.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		301BF534109A57CC0062928A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = D2AAC07E0554694100DB518D;
+			remoteInfo = CordovaLib;
+		};
+		301BF550109A68C00062928A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
+			remoteInfo = CordovaLib;
+		};
+		907D8123214C687600058A10 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = C0C01EB21E3911D50056E6CB;
+			remoteInfo = Cordova;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		0207DA571B56EA530066E2B4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = dlapp/Images.xcassets; sourceTree = SOURCE_ROOT; };
+		04B5E1A8BB504B8FB8CE9627 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = "cordova-plugin-advanced-http/AFHTTPSessionManager.m"; sourceTree = "<group>"; };
+		07B9D06BD3024E0FBFF74967 /* CordovaHttpPlugin.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CordovaHttpPlugin.m; path = "cordova-plugin-advanced-http/CordovaHttpPlugin.m"; sourceTree = "<group>"; };
+		08B9BD113EDF4024B1F6D5CE /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = "cordova-plugin-advanced-http/AFURLRequestSerialization.h"; sourceTree = "<group>"; };
+		09B4181C53154D9D8E1A2C4B /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = "cordova-plugin-advanced-http/AFHTTPSessionManager.h"; sourceTree = "<group>"; };
+		11A34CB026314A2AA98A0044 /* AVFoundation.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
+		130AB7839C2A4FFF9F13C3DE /* CDVCamera.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVCamera.h; path = "cordova-plugin-camera/CDVCamera.h"; sourceTree = "<group>"; };
+		148A2122F3E242E4AF09A28D /* SDNetworkActivityIndicator.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = SDNetworkActivityIndicator.m; path = "cordova-plugin-advanced-http/SDNetworkActivityIndicator.m"; sourceTree = "<group>"; };
+		15879A58684B40158EC7A2CA /* CDVJpegHeaderWriter.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVJpegHeaderWriter.h; path = "cordova-plugin-camera/CDVJpegHeaderWriter.h"; sourceTree = "<group>"; };
+		17FD8EDA2EC0424192F6CA79 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = "cordova-plugin-advanced-http/AFSecurityPolicy.h"; sourceTree = "<group>"; };
+		1836D178C8A74923B944A79E /* CDVJpegHeaderWriter.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVJpegHeaderWriter.m; path = "cordova-plugin-camera/CDVJpegHeaderWriter.m"; sourceTree = "<group>"; };
+		1ABBE12B040548F8909BFC7B /* CDVStatusBar.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVStatusBar.m; path = "cordova-plugin-statusbar/CDVStatusBar.m"; sourceTree = "<group>"; };
+		1D1F25845F964D87B880BFA9 /* CoreLocation.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+		1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		1D6058910D05DD3D006BFB54 /* dlapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dlapp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		22AE2683802B4CB1BAF69ABF /* AFURLSessionManager.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = "cordova-plugin-advanced-http/AFURLSessionManager.m"; sourceTree = "<group>"; };
+		2625E3AABA8145E6901F06D3 /* SystemConfiguration.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		265BE52D975B49ACA2F7B3FE /* CDVDevice.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVDevice.h; path = "cordova-plugin-device/CDVDevice.h"; sourceTree = "<group>"; };
+		281DF600F6B747808087E4FC /* UIImage+CropScaleOrientation.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = "UIImage+CropScaleOrientation.m"; path = "cordova-plugin-camera/UIImage+CropScaleOrientation.m"; sourceTree = "<group>"; };
+		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		2F977C7D2E4448098AA27AE8 /* CDVAssetLibraryFilesystem.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVAssetLibraryFilesystem.h; path = "cordova-plugin-file/CDVAssetLibraryFilesystem.h"; sourceTree = "<group>"; };
+		301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = CordovaLib/CordovaLib.xcodeproj; sourceTree = "<group>"; };
+		301BF56E109A69640062928A /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = SOURCE_ROOT; };
+		302D95EE14D2391D003F00A1 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = "<group>"; };
+		302D95EF14D2391D003F00A1 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = "<group>"; };
+		302D95F014D2391D003F00A1 /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainViewController.xib; sourceTree = "<group>"; };
+		3047A50F1AB8059700498E2A /* build-debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "build-debug.xcconfig"; path = "cordova/build-debug.xcconfig"; sourceTree = SOURCE_ROOT; };
+		3047A5101AB8059700498E2A /* build-release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "build-release.xcconfig"; path = "cordova/build-release.xcconfig"; sourceTree = SOURCE_ROOT; };
+		3047A5111AB8059700498E2A /* build.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = build.xcconfig; path = cordova/build.xcconfig; sourceTree = SOURCE_ROOT; };
+		32CA4F630368D1EE00C91783 /* dlapp-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "dlapp-Prefix.pch"; sourceTree = "<group>"; };
+		3BE5364CD5E74AFDAB853364 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = "cordova-plugin-advanced-http/AFURLResponseSerialization.h"; sourceTree = "<group>"; };
+		3D1EDC804D3646E7BE4A92BF /* AFNetworking.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = "cordova-plugin-advanced-http/AFNetworking.h"; sourceTree = "<group>"; };
+		3FD6ED94AE9243B29217547A /* CDVLocalFilesystem.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVLocalFilesystem.h; path = "cordova-plugin-file/CDVLocalFilesystem.h"; sourceTree = "<group>"; };
+		41DFF309018A479EA8F43611 /* CDVInAppBrowser.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVInAppBrowser.h; path = "cordova-plugin-inappbrowser/CDVInAppBrowser.h"; sourceTree = "<group>"; };
+		4BF1AE7251084FD2876E0BF5 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = "cordova-plugin-advanced-http/AFURLRequestSerialization.m"; sourceTree = "<group>"; };
+		5192EB17EA164DFD80D433E4 /* ImageIO.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
+		57E66D7A151D45828ED66B7F /* TextResponseSerializer.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = TextResponseSerializer.m; path = "cordova-plugin-advanced-http/TextResponseSerializer.m"; sourceTree = "<group>"; };
+		607F51FCFC7C4062A93BD011 /* CDVInAppBrowser.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVInAppBrowser.m; path = "cordova-plugin-inappbrowser/CDVInAppBrowser.m"; sourceTree = "<group>"; };
+		61106E22F1D348DDBDC4DC0B /* DisableStatusbar.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = DisableStatusbar.m; path = "cordova-plugin-disable-ios11-statusbar/DisableStatusbar.m"; sourceTree = "<group>"; };
+		62C24B1E8F294AC587C6D051 /* UIImage+CropScaleOrientation.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "UIImage+CropScaleOrientation.h"; path = "cordova-plugin-camera/UIImage+CropScaleOrientation.h"; sourceTree = "<group>"; };
+		683645F69456461BB8712924 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = "cordova-plugin-advanced-http/AFNetworkReachabilityManager.h"; sourceTree = "<group>"; };
+		6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = CDVLaunchScreen.storyboard; path = dlapp/CDVLaunchScreen.storyboard; sourceTree = SOURCE_ROOT; };
+		6DC53FCFEEFD4EC89C2073E0 /* TextRequestSerializer.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = TextRequestSerializer.h; path = "cordova-plugin-advanced-http/TextRequestSerializer.h"; sourceTree = "<group>"; };
+		6FEED8E986814AC1AC60FC28 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = "cordova-plugin-advanced-http/AFNetworkReachabilityManager.m"; sourceTree = "<group>"; };
+		7601E9450D7240078C98ED9D /* CordovaHttpPlugin.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CordovaHttpPlugin.h; path = "cordova-plugin-advanced-http/CordovaHttpPlugin.h"; sourceTree = "<group>"; };
+		7E931FBE72E74C4887498E5F /* AFURLSessionManager.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = "cordova-plugin-advanced-http/AFURLSessionManager.h"; sourceTree = "<group>"; };
+		80B448E71F8941268B78692C /* CDVCamera.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVCamera.m; path = "cordova-plugin-camera/CDVCamera.m"; sourceTree = "<group>"; };
+		8895AD78E31D471583178B91 /* TextResponseSerializer.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = TextResponseSerializer.h; path = "cordova-plugin-advanced-http/TextResponseSerializer.h"; sourceTree = "<group>"; };
+		8A8DD2DDC8694A97A56F9FA7 /* CDVLocalFilesystem.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVLocalFilesystem.m; path = "cordova-plugin-file/CDVLocalFilesystem.m"; sourceTree = "<group>"; };
+		8BFF0D502E2241F0A89DF67F /* CDVStatusBar.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVStatusBar.h; path = "cordova-plugin-statusbar/CDVStatusBar.h"; sourceTree = "<group>"; };
+		8D1107310486CEB800E47090 /* dlapp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "dlapp-Info.plist"; path = "dlapp/dlapp-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = SOURCE_ROOT; };
+		901AB970F8AB4CEF82C6DC1B /* BinaryResponseSerializer.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = BinaryResponseSerializer.h; path = "cordova-plugin-advanced-http/BinaryResponseSerializer.h"; sourceTree = "<group>"; };
+		A50DE9801E5E4302A78D569C /* CDVDevice.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVDevice.m; path = "cordova-plugin-device/CDVDevice.m"; sourceTree = "<group>"; };
+		A673D8D8920E4086A9152FC4 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+		A719A69FD70D4CC9B8104FF6 /* CDVAssetLibraryFilesystem.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVAssetLibraryFilesystem.m; path = "cordova-plugin-file/CDVAssetLibraryFilesystem.m"; sourceTree = "<group>"; };
+		B19E413F59714C6285552E82 /* TouchID.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = TouchID.h; path = "cordova-plugin-touch-id/TouchID.h"; sourceTree = "<group>"; };
+		B3CE13EED96B44C0B06B1B2C /* TouchID.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = TouchID.m; path = "cordova-plugin-touch-id/TouchID.m"; sourceTree = "<group>"; };
+		B3F9D30FB27A4B26A445BA84 /* CDVExif.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVExif.h; path = "cordova-plugin-camera/CDVExif.h"; sourceTree = "<group>"; };
+		BA6C5B1A6A6A488790CA41EB /* AFSecurityPolicy.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = "cordova-plugin-advanced-http/AFSecurityPolicy.m"; sourceTree = "<group>"; };
+		C2099240B64744E08C91C285 /* Fingerprint.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = Fingerprint.swift; path = "cordova-plugin-fingerprint-aio/Fingerprint.swift"; sourceTree = "<group>"; };
+		C8478FFD487C4004A1CEFCA8 /* QRScanner.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = QRScanner.swift; path = "cordova-plugin-qrscanner/QRScanner.swift"; sourceTree = "<group>"; };
+		D4DBE4512BAD4694B7EB5217 /* SDNetworkActivityIndicator.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = SDNetworkActivityIndicator.h; path = "cordova-plugin-advanced-http/SDNetworkActivityIndicator.h"; sourceTree = "<group>"; };
+		DBDBB5C64D17465C9452AF28 /* TextRequestSerializer.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = TextRequestSerializer.m; path = "cordova-plugin-advanced-http/TextRequestSerializer.m"; sourceTree = "<group>"; };
+		DD3651F245114E52ABEB9060 /* CDVFile.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = CDVFile.m; path = "cordova-plugin-file/CDVFile.m"; sourceTree = "<group>"; };
+		DE50527E757F47D08F4E076C /* CDVFile.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = CDVFile.h; path = "cordova-plugin-file/CDVFile.h"; sourceTree = "<group>"; };
+		E9F753C8AE424EAE851FA1FD /* BinaryResponseSerializer.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = BinaryResponseSerializer.m; path = "cordova-plugin-advanced-http/BinaryResponseSerializer.m"; sourceTree = "<group>"; };
+		EB87FDF31871DA8E0020F90C /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = "<group>"; };
+		EB87FDF41871DAF40020F90C /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = "<group>"; };
+		ED33DF2A687741AEAF9F8254 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
+		F3A85B8119074F699E1A15CD /* LocalAuthentication.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
+		F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = dlapp/config.xml; sourceTree = "<group>"; };
+		F939AD8C22BB769B006B371B /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
+		FCC7E279D80D4FB9BCF2530A /* Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "Bridging-Header.h"; path = "cordova-plugin-fingerprint-aio/Bridging-Header.h"; sourceTree = "<group>"; };
+		FDEE8379D7A34C55A616F700 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = "cordova-plugin-advanced-http/AFURLResponseSerialization.m"; sourceTree = "<group>"; };
+		28B91F31B6FD410AAF87BBDC /* CDVThemeableBrowser.m */ = {isa = PBXFileReference; name = "CDVThemeableBrowser.m"; path = "cordova-plugin-themeablebrowser/CDVThemeableBrowser.m"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
+		EF1A4FA720C24397A32AF09C /* CDVThemeableBrowser.h */ = {isa = PBXFileReference; name = "CDVThemeableBrowser.h"; path = "cordova-plugin-themeablebrowser/CDVThemeableBrowser.h"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F939AD8D22BB769B006B371B /* libsqlite3.0.tbd in Frameworks */,
+				301BF552109A68D80062928A /* libCordova.a in Frameworks */,
+				F46AE1B50D8B4A81B05D4100 /* Security.framework in Frameworks */,
+				2FE26256C715470F8240C690 /* SystemConfiguration.framework in Frameworks */,
+				8ABB6F36D85243238622D4F8 /* LocalAuthentication.framework in Frameworks */,
+				7D8430D010A848FBBA5FB7ED /* ImageIO.framework in Frameworks */,
+				D2F2072984AE43BCBD0A430D /* CoreLocation.framework in Frameworks */,
+				74A56CC7F6724870ABD136F2 /* AVFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		080E96DDFE201D6D7F000001 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				302D95EE14D2391D003F00A1 /* MainViewController.h */,
+				302D95EF14D2391D003F00A1 /* MainViewController.m */,
+				302D95F014D2391D003F00A1 /* MainViewController.xib */,
+				1D3623240D0F684500981E51 /* AppDelegate.h */,
+				1D3623250D0F684500981E51 /* AppDelegate.m */,
+			);
+			name = Classes;
+			path = dlapp/Classes;
+			sourceTree = SOURCE_ROOT;
+		};
+		19C28FACFE9D520D11CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				1D6058910D05DD3D006BFB54 /* dlapp.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+			isa = PBXGroup;
+			children = (
+				EB87FDF41871DAF40020F90C /* config.xml */,
+				EB87FDF31871DA8E0020F90C /* www */,
+				EB87FDF11871DA420020F90C /* Staging */,
+				301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */,
+				080E96DDFE201D6D7F000001 /* Classes */,
+				307C750510C5A3420062BCA9 /* Plugins */,
+				29B97315FDCFA39411CA2CEA /* Other Sources */,
+				29B97317FDCFA39411CA2CEA /* Resources */,
+				29B97323FDCFA39411CA2CEA /* Frameworks */,
+				19C28FACFE9D520D11CA2CBB /* Products */,
+			);
+			name = CustomTemplate;
+			sourceTree = "<group>";
+		};
+		29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				32CA4F630368D1EE00C91783 /* dlapp-Prefix.pch */,
+				29B97316FDCFA39411CA2CEA /* main.m */,
+				ED33DF2A687741AEAF9F8254 /* Bridging-Header.h */,
+			);
+			name = "Other Sources";
+			path = dlapp;
+			sourceTree = "<group>";
+		};
+		29B97317FDCFA39411CA2CEA /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				0207DA571B56EA530066E2B4 /* Images.xcassets */,
+				3047A50E1AB8057F00498E2A /* config */,
+				8D1107310486CEB800E47090 /* dlapp-Info.plist */,
+				6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */,
+			);
+			name = Resources;
+			path = dlapp/Resources;
+			sourceTree = "<group>";
+		};
+		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				F939AD8C22BB769B006B371B /* libsqlite3.0.tbd */,
+				A673D8D8920E4086A9152FC4 /* Security.framework */,
+				2625E3AABA8145E6901F06D3 /* SystemConfiguration.framework */,
+				F3A85B8119074F699E1A15CD /* LocalAuthentication.framework */,
+				5192EB17EA164DFD80D433E4 /* ImageIO.framework */,
+				1D1F25845F964D87B880BFA9 /* CoreLocation.framework */,
+				11A34CB026314A2AA98A0044 /* AVFoundation.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		301BF52E109A57CC0062928A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				301BF535109A57CC0062928A /* libCordova.a */,
+				907D8124214C687600058A10 /* Cordova.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		3047A50E1AB8057F00498E2A /* config */ = {
+			isa = PBXGroup;
+			children = (
+				3047A50F1AB8059700498E2A /* build-debug.xcconfig */,
+				3047A5101AB8059700498E2A /* build-release.xcconfig */,
+				3047A5111AB8059700498E2A /* build.xcconfig */,
+			);
+			name = config;
+			sourceTree = "<group>";
+		};
+		307C750510C5A3420062BCA9 /* Plugins */ = {
+			isa = PBXGroup;
+			children = (
+				DD3651F245114E52ABEB9060 /* CDVFile.m */,
+				8A8DD2DDC8694A97A56F9FA7 /* CDVLocalFilesystem.m */,
+				A719A69FD70D4CC9B8104FF6 /* CDVAssetLibraryFilesystem.m */,
+				DE50527E757F47D08F4E076C /* CDVFile.h */,
+				3FD6ED94AE9243B29217547A /* CDVLocalFilesystem.h */,
+				2F977C7D2E4448098AA27AE8 /* CDVAssetLibraryFilesystem.h */,
+				07B9D06BD3024E0FBFF74967 /* CordovaHttpPlugin.m */,
+				E9F753C8AE424EAE851FA1FD /* BinaryResponseSerializer.m */,
+				57E66D7A151D45828ED66B7F /* TextResponseSerializer.m */,
+				DBDBB5C64D17465C9452AF28 /* TextRequestSerializer.m */,
+				04B5E1A8BB504B8FB8CE9627 /* AFHTTPSessionManager.m */,
+				6FEED8E986814AC1AC60FC28 /* AFNetworkReachabilityManager.m */,
+				BA6C5B1A6A6A488790CA41EB /* AFSecurityPolicy.m */,
+				4BF1AE7251084FD2876E0BF5 /* AFURLRequestSerialization.m */,
+				FDEE8379D7A34C55A616F700 /* AFURLResponseSerialization.m */,
+				22AE2683802B4CB1BAF69ABF /* AFURLSessionManager.m */,
+				148A2122F3E242E4AF09A28D /* SDNetworkActivityIndicator.m */,
+				7601E9450D7240078C98ED9D /* CordovaHttpPlugin.h */,
+				901AB970F8AB4CEF82C6DC1B /* BinaryResponseSerializer.h */,
+				8895AD78E31D471583178B91 /* TextResponseSerializer.h */,
+				6DC53FCFEEFD4EC89C2073E0 /* TextRequestSerializer.h */,
+				09B4181C53154D9D8E1A2C4B /* AFHTTPSessionManager.h */,
+				3D1EDC804D3646E7BE4A92BF /* AFNetworking.h */,
+				683645F69456461BB8712924 /* AFNetworkReachabilityManager.h */,
+				17FD8EDA2EC0424192F6CA79 /* AFSecurityPolicy.h */,
+				08B9BD113EDF4024B1F6D5CE /* AFURLRequestSerialization.h */,
+				3BE5364CD5E74AFDAB853364 /* AFURLResponseSerialization.h */,
+				7E931FBE72E74C4887498E5F /* AFURLSessionManager.h */,
+				D4DBE4512BAD4694B7EB5217 /* SDNetworkActivityIndicator.h */,
+				C2099240B64744E08C91C285 /* Fingerprint.swift */,
+				FCC7E279D80D4FB9BCF2530A /* Bridging-Header.h */,
+				1ABBE12B040548F8909BFC7B /* CDVStatusBar.m */,
+				8BFF0D502E2241F0A89DF67F /* CDVStatusBar.h */,
+				B3CE13EED96B44C0B06B1B2C /* TouchID.m */,
+				B19E413F59714C6285552E82 /* TouchID.h */,
+				61106E22F1D348DDBDC4DC0B /* DisableStatusbar.m */,
+				C8478FFD487C4004A1CEFCA8 /* QRScanner.swift */,
+				281DF600F6B747808087E4FC /* UIImage+CropScaleOrientation.m */,
+				80B448E71F8941268B78692C /* CDVCamera.m */,
+				1836D178C8A74923B944A79E /* CDVJpegHeaderWriter.m */,
+				62C24B1E8F294AC587C6D051 /* UIImage+CropScaleOrientation.h */,
+				130AB7839C2A4FFF9F13C3DE /* CDVCamera.h */,
+				15879A58684B40158EC7A2CA /* CDVJpegHeaderWriter.h */,
+				B3F9D30FB27A4B26A445BA84 /* CDVExif.h */,
+				607F51FCFC7C4062A93BD011 /* CDVInAppBrowser.m */,
+				41DFF309018A479EA8F43611 /* CDVInAppBrowser.h */,
+				A50DE9801E5E4302A78D569C /* CDVDevice.m */,
+				265BE52D975B49ACA2F7B3FE /* CDVDevice.h */,
+				28B91F31B6FD410AAF87BBDC /* CDVThemeableBrowser.m */,
+				EF1A4FA720C24397A32AF09C /* CDVThemeableBrowser.h */,
+			);
+			name = Plugins;
+			path = dlapp/Plugins;
+			sourceTree = SOURCE_ROOT;
+		};
+		EB87FDF11871DA420020F90C /* Staging */ = {
+			isa = PBXGroup;
+			children = (
+				F840E1F0165FE0F500CFE078 /* config.xml */,
+				301BF56E109A69640062928A /* www */,
+			);
+			name = Staging;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		1D6058900D05DD3D006BFB54 /* dlapp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "dlapp" */;
+			buildPhases = (
+				304B58A110DAC018002A0835 /* Copy www directory */,
+				1D60588D0D05DD3D006BFB54 /* Resources */,
+				1D60588E0D05DD3D006BFB54 /* Sources */,
+				1D60588F0D05DD3D006BFB54 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				301BF551109A68C00062928A /* PBXTargetDependency */,
+			);
+			name = dlapp;
+			productName = dlapp;
+			productReference = 1D6058910D05DD3D006BFB54 /* dlapp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		29B97313FDCFA39411CA2CEA /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 510;
+				TargetAttributes = {
+					1D6058900D05DD3D006BFB54 = {
+						DevelopmentTeam = 74UNETA6B2;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dlapp" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				en,
+			);
+			mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = 301BF52E109A57CC0062928A /* Products */;
+					ProjectRef = 301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				1D6058900D05DD3D006BFB54 /* dlapp */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		301BF535109A57CC0062928A /* libCordova.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libCordova.a;
+			remoteRef = 301BF534109A57CC0062928A /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		907D8124214C687600058A10 /* Cordova.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = Cordova.framework;
+			remoteRef = 907D8123214C687600058A10 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+		1D60588D0D05DD3D006BFB54 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */,
+				0207DA581B56EA530066E2B4 /* Images.xcassets in Resources */,
+				6AFF5BF91D6E424B00AB3073 /* CDVLaunchScreen.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		304B58A110DAC018002A0835 /* Copy www directory */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Copy www directory";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"$SRCROOT/dlapp/Scripts/copy-www-build-step.sh\"";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		1D60588E0D05DD3D006BFB54 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+				1D3623260D0F684500981E51 /* AppDelegate.m in Sources */,
+				302D95F114D2391D003F00A1 /* MainViewController.m in Sources */,
+				78A785FAE16943908BA7B6DB /* CDVFile.m in Sources */,
+				9224D3CE70AE4072BBEB170D /* CDVLocalFilesystem.m in Sources */,
+				94868B10923A4508B06A4310 /* CDVAssetLibraryFilesystem.m in Sources */,
+				5E2BDB8CFE4E41F39241956C /* CordovaHttpPlugin.m in Sources */,
+				5F67F2BDBB534EF4A4F1F319 /* BinaryResponseSerializer.m in Sources */,
+				90E2E49D3A2449AB8D4D82D0 /* TextResponseSerializer.m in Sources */,
+				74C07CC128F9457AB281916E /* TextRequestSerializer.m in Sources */,
+				6561A2871EB1420892CDE701 /* AFHTTPSessionManager.m in Sources */,
+				5F8969599D7F41909F597D14 /* AFNetworkReachabilityManager.m in Sources */,
+				8E2516CFE16944B8B9702955 /* AFSecurityPolicy.m in Sources */,
+				3772C27945674D8D9D6BA455 /* AFURLRequestSerialization.m in Sources */,
+				FDE92C386167415E8040F8AB /* AFURLResponseSerialization.m in Sources */,
+				BC998F935D174204820F4015 /* AFURLSessionManager.m in Sources */,
+				D404D18DD0114DA787E0BB43 /* SDNetworkActivityIndicator.m in Sources */,
+				B69FF513D1EE4772AFF6050B /* Fingerprint.swift in Sources */,
+				CAE5A91F948A472F9D872EC8 /* CDVStatusBar.m in Sources */,
+				D834895F80744E0F96D59047 /* TouchID.m in Sources */,
+				C61263FC7FE642E9B25A81E5 /* DisableStatusbar.m in Sources */,
+				A42AE846FF7B482FB889AAEB /* QRScanner.swift in Sources */,
+				0FBFC45D12B44FF79785B959 /* UIImage+CropScaleOrientation.m in Sources */,
+				B8EFB66D03A44372A240B05B /* CDVCamera.m in Sources */,
+				6F6B3ADF72094BF58EF5C4AC /* CDVJpegHeaderWriter.m in Sources */,
+				6FB343627AC8409CB2AA79B7 /* CDVInAppBrowser.m in Sources */,
+				BC39BA77AF0D4F94BC27666A /* CDVDevice.m in Sources */,
+				4F83621E48F143429B20FB3A /* CDVThemeableBrowser.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		301BF551109A68C00062928A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = CordovaLib;
+			targetProxy = 301BF550109A68C00062928A /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		1D6058940D05DD3E006BFB54 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3047A50F1AB8059700498E2A /* build-debug.xcconfig */;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				COPY_PHASE_STRIP = NO;
+				DEVELOPMENT_TEAM = 74UNETA6B2;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "dlapp/dlapp-Prefix.pch";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = "";
+				INFOPLIST_FILE = "dlapp/dlapp-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+				LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.supwisdom.dlapp;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 4.0;
+				TARGETED_DEVICE_FAMILY = 1;
+			};
+			name = Debug;
+		};
+		1D6058950D05DD3E006BFB54 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3047A5101AB8059700498E2A /* build-release.xcconfig */;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				COPY_PHASE_STRIP = YES;
+				DEVELOPMENT_TEAM = 74UNETA6B2;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "dlapp/dlapp-Prefix.pch";
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = "";
+				INFOPLIST_FILE = "dlapp/dlapp-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+				LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.supwisdom.dlapp;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h";
+				SWIFT_VERSION = 4.0;
+				TARGETED_DEVICE_FAMILY = 1;
+			};
+			name = Release;
+		};
+		C01FCF4F08A954540054247B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3047A5111AB8059700498E2A /* build.xcconfig */;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = "";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.supwisdom.dlapp;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = NO;
+				SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 4.0;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+			};
+			name = Debug;
+		};
+		C01FCF5008A954540054247B /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3047A5111AB8059700498E2A /* build.xcconfig */;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_THUMB_SUPPORT = NO;
+				GCC_VERSION = "";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.supwisdom.dlapp;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = NO;
+				SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME)/Bridging-Header.h";
+				SWIFT_VERSION = 4.0;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "dlapp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1D6058940D05DD3E006BFB54 /* Debug */,
+				1D6058950D05DD3E006BFB54 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "dlapp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C01FCF4F08A954540054247B /* Debug */,
+				C01FCF5008A954540054247B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/platforms/ios/dlapp.xcworkspace/contents.xcworkspacedata b/platforms/ios/dlapp.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..da2a5d5
--- /dev/null
+++ b/platforms/ios/dlapp.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:dlapp.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/platforms/ios/dlapp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/platforms/ios/dlapp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/platforms/ios/dlapp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/platforms/ios/dlapp.xcworkspace/xcshareddata/xcschemes/dlapp.xcscheme b/platforms/ios/dlapp.xcworkspace/xcshareddata/xcschemes/dlapp.xcscheme
new file mode 100644
index 0000000..a6799bb
--- /dev/null
+++ b/platforms/ios/dlapp.xcworkspace/xcshareddata/xcschemes/dlapp.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0730"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+               BuildableName = "dlapp.app"
+               BlueprintName = "dlapp"
+               ReferencedContainer = "container:dlapp.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "dlapp.app"
+            BlueprintName = "dlapp"
+            ReferencedContainer = "container:dlapp.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "dlapp.app"
+            BlueprintName = "dlapp"
+            ReferencedContainer = "container:dlapp.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "dlapp.app"
+            BlueprintName = "dlapp"
+            ReferencedContainer = "container:dlapp.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/platforms/ios/dlapp/.gitignore b/platforms/ios/dlapp/.gitignore
new file mode 100644
index 0000000..cc76483
--- /dev/null
+++ b/platforms/ios/dlapp/.gitignore
@@ -0,0 +1,5 @@
+*.mode1v3
+*.perspectivev3
+*.pbxuser
+.DS_Store
+build/
diff --git a/platforms/ios/dlapp/Bridging-Header.h b/platforms/ios/dlapp/Bridging-Header.h
new file mode 100644
index 0000000..5d8abc9
--- /dev/null
+++ b/platforms/ios/dlapp/Bridging-Header.h
@@ -0,0 +1,28 @@
+/*
+ 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.
+ */
+//
+//  Bridging-Header.h
+//  __PROJECT_NAME__
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import <Cordova/CDV.h>
diff --git a/platforms/ios/dlapp/CDVLaunchScreen.storyboard b/platforms/ios/dlapp/CDVLaunchScreen.storyboard
new file mode 100644
index 0000000..9f21416
--- /dev/null
+++ b/platforms/ios/dlapp/CDVLaunchScreen.storyboard
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LaunchStoryboard" translatesAutoresizingMaskIntoConstraints="NO" id="2ns-9I-Qjs">
+                                <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="2ns-9I-Qjs" secondAttribute="trailing" id="FZL-3Z-NFz"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="L9l-pw-wXj"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="oGN-hc-Uzj"/>
+                            <constraint firstItem="2ns-9I-Qjs" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="rS9-Wd-zY4"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="LaunchStoryboard" width="1366" height="1366"/>
+    </resources>
+</document>
diff --git a/platforms/ios/dlapp/Classes/AppDelegate.h b/platforms/ios/dlapp/Classes/AppDelegate.h
new file mode 100644
index 0000000..4703ae6
--- /dev/null
+++ b/platforms/ios/dlapp/Classes/AppDelegate.h
@@ -0,0 +1,33 @@
+/*
+ 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.
+ */
+
+//
+//  AppDelegate.h
+//  dlapp
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+
+#import <Cordova/CDVViewController.h>
+#import <Cordova/CDVAppDelegate.h>
+
+@interface AppDelegate : CDVAppDelegate {}
+
+@end
diff --git a/platforms/ios/dlapp/Classes/AppDelegate.m b/platforms/ios/dlapp/Classes/AppDelegate.m
new file mode 100644
index 0000000..c4998ec
--- /dev/null
+++ b/platforms/ios/dlapp/Classes/AppDelegate.m
@@ -0,0 +1,39 @@
+/*
+ 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.
+ */
+
+//
+//  AppDelegate.m
+//  dlapp
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+
+#import "AppDelegate.h"
+#import "MainViewController.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
+{
+    self.viewController = [[MainViewController alloc] init];
+    return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Classes/MainViewController.h b/platforms/ios/dlapp/Classes/MainViewController.h
new file mode 100644
index 0000000..a83c4ba
--- /dev/null
+++ b/platforms/ios/dlapp/Classes/MainViewController.h
@@ -0,0 +1,40 @@
+/*
+ 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.
+ */
+
+//
+//  MainViewController.h
+//  dlapp
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+
+#import <Cordova/CDVViewController.h>
+#import <Cordova/CDVCommandDelegateImpl.h>
+#import <Cordova/CDVCommandQueue.h>
+
+@interface MainViewController : CDVViewController
+
+@end
+
+@interface MainCommandDelegate : CDVCommandDelegateImpl
+@end
+
+@interface MainCommandQueue : CDVCommandQueue
+@end
diff --git a/platforms/ios/dlapp/Classes/MainViewController.m b/platforms/ios/dlapp/Classes/MainViewController.m
new file mode 100644
index 0000000..9c34af0
--- /dev/null
+++ b/platforms/ios/dlapp/Classes/MainViewController.m
@@ -0,0 +1,148 @@
+/*
+ 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.
+ */
+
+//
+//  MainViewController.h
+//  dlapp
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+
+#import "MainViewController.h"
+
+@implementation MainViewController
+
+- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Uncomment to override the CDVCommandDelegateImpl used
+        // _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
+        // Uncomment to override the CDVCommandQueue used
+        // _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
+    }
+    return self;
+}
+
+- (id)init
+{
+    self = [super init];
+    if (self) {
+        // Uncomment to override the CDVCommandDelegateImpl used
+        // _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
+        // Uncomment to override the CDVCommandQueue used
+        // _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
+    }
+    return self;
+}
+
+- (void)didReceiveMemoryWarning
+{
+    // Releases the view if it doesn't have a superview.
+    [super didReceiveMemoryWarning];
+
+    // Release any cached data, images, etc that aren't in use.
+}
+
+#pragma mark View lifecycle
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
+    // you can do so here.
+
+    [super viewWillAppear:animated];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view from its nib.
+}
+
+- (void)viewDidUnload
+{
+    [super viewDidUnload];
+    // Release any retained subviews of the main view.
+    // e.g. self.myOutlet = nil;
+}
+
+/* Comment out the block below to over-ride */
+
+/*
+- (UIWebView*) newCordovaViewWithFrame:(CGRect)bounds
+{
+    return[super newCordovaViewWithFrame:bounds];
+}
+
+// CB-12098
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000  
+- (NSUInteger)supportedInterfaceOrientations
+#else  
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations
+#endif
+{
+    return [super supportedInterfaceOrientations];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
+{
+    return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+}
+
+- (BOOL)shouldAutorotate 
+{
+    return [super shouldAutorotate];
+}
+*/
+
+@end
+
+@implementation MainCommandDelegate
+
+/* To override the methods, uncomment the line in the init function(s)
+   in MainViewController.m
+ */
+
+#pragma mark CDVCommandDelegate implementation
+
+- (id)getCommandInstance:(NSString*)className
+{
+    return [super getCommandInstance:className];
+}
+
+- (NSString*)pathForResource:(NSString*)resourcepath
+{
+    return [super pathForResource:resourcepath];
+}
+
+@end
+
+@implementation MainCommandQueue
+
+/* To override, uncomment the line in the init function(s)
+   in MainViewController.m
+ */
+- (BOOL)execute:(CDVInvokedUrlCommand*)command
+{
+    return [super execute:command];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Classes/MainViewController.xib b/platforms/ios/dlapp/Classes/MainViewController.xib
new file mode 100644
index 0000000..57de704
--- /dev/null
+++ b/platforms/ios/dlapp/Classes/MainViewController.xib
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" colorMatched="YES">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MainViewController">
+            <connections>
+                <outlet property="view" destination="1" id="3"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="1">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+        </view>
+    </objects>
+</document>
diff --git a/platforms/ios/dlapp/Entitlements-Debug.plist b/platforms/ios/dlapp/Entitlements-Debug.plist
new file mode 100644
index 0000000..1ed4ae5
--- /dev/null
+++ b/platforms/ios/dlapp/Entitlements-Debug.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+    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.
+-->
+<plist version="1.0">
+    <dict>
+    </dict>
+</plist>
diff --git a/platforms/ios/dlapp/Entitlements-Release.plist b/platforms/ios/dlapp/Entitlements-Release.plist
new file mode 100644
index 0000000..1ed4ae5
--- /dev/null
+++ b/platforms/ios/dlapp/Entitlements-Release.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+    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.
+-->
+<plist version="1.0">
+    <dict>
+    </dict>
+</plist>
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon24x24@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon24x24@2x.png
new file mode 100644
index 0000000..ed81661
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon24x24@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon27.5x27.5@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon27.5x27.5@2x.png
new file mode 100644
index 0000000..ec313ad
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon27.5x27.5@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png
new file mode 100644
index 0000000..d9c5f4b
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png
new file mode 100644
index 0000000..ba532dd
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png
new file mode 100644
index 0000000..678fba0
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon44x44@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon44x44@2x.png
new file mode 100644
index 0000000..b6fbccf
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon44x44@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon86x86@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon86x86@2x.png
new file mode 100644
index 0000000..b0f903c
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon86x86@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon98x98@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon98x98@2x.png
new file mode 100644
index 0000000..3bca15b
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/AppIcon98x98@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/Contents.json b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2ce78c1
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,241 @@
+{
+  "images" : [
+    {
+      "size" : "20x20",
+      "idiom" : "iphone",
+      "filename" : "icon-20@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "iphone",
+      "filename" : "icon-20@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "icon-29.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "icon-29@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "icon-29@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "icon-40@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "iphone",
+      "filename" : "icon-60@2x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "icon.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "icon@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "icon-60@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "icon-60@3x.png",
+      "scale" : "3x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "ipad",
+      "filename" : "icon-20.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "20x20",
+      "idiom" : "ipad",
+      "filename" : "icon-20@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "ipad",
+      "filename" : "icon-29.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "ipad",
+      "filename" : "icon-29@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "icon-40.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "ipad",
+      "filename" : "icon-40@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "50x50",
+      "idiom" : "ipad",
+      "filename" : "icon-50.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "50x50",
+      "idiom" : "ipad",
+      "filename" : "icon-50@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "icon-72.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "icon-72@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "icon-76.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "icon-76@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "83.5x83.5",
+      "idiom" : "ipad",
+      "filename" : "icon-83.5@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "1024x1024",
+      "idiom" : "ios-marketing",
+      "filename" : "icon-1024.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "24x24",
+      "idiom" : "watch",
+      "filename" : "icon-24@2x.png",
+      "scale" : "2x",
+      "role" : "notificationCenter",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "27.5x27.5",
+      "idiom" : "watch",
+      "filename" : "icon-27.5@2x.png",
+      "scale" : "2x",
+      "role" : "notificationCenter",
+      "subtype" : "42mm"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "watch",
+      "filename" : "icon-29@2x.png",
+      "role" : "companionSettings",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "watch",
+      "filename" : "icon-29@3x.png",
+      "role" : "companionSettings",
+      "scale" : "3x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "watch",
+      "filename" : "icon-40@2x.png",
+      "scale" : "2x",
+      "role" : "appLauncher",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "44x44",
+      "idiom" : "watch",
+      "filename" : "icon-44@2x.png",
+      "scale" : "2x",
+      "role" : "appLauncher",
+      "subtype" : "40mm"
+    },
+    {
+      "size" : "50x50",
+      "idiom" : "watch",
+      "filename" : "icon-50@2x.png",
+      "scale" : "2x",
+      "role" : "appLauncher",
+      "subtype" : "44mm"
+    },
+    {
+      "size" : "86x86",
+      "idiom" : "watch",
+      "filename" : "icon-86@2x.png",
+      "scale" : "2x",
+      "role" : "quickLook",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "98x98",
+      "idiom" : "watch",
+      "filename" : "icon-98@2x.png",
+      "scale" : "2x",
+      "role" : "quickLook",
+      "subtype" : "42mm"
+    },
+    {
+      "size" : "108x108",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "quickLook",
+      "subtype" : "44mm"
+    },
+    {
+      "size" : "1024x1024",
+      "idiom" : "watch-marketing",
+      "filename" : "icon-1024.png",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-1024.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-1024.png
new file mode 100644
index 0000000..ab1a5c0
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-1024.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20.png
new file mode 100644
index 0000000..256350a
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@2x.png
new file mode 100644
index 0000000..cb6b99f
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@3x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@3x.png
new file mode 100644
index 0000000..5d8dbc8
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-20@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-24@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-24@2x.png
new file mode 100644
index 0000000..f0babf9
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-24@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-27.5@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-27.5@2x.png
new file mode 100644
index 0000000..78f21bb
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-27.5@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29.png
new file mode 100644
index 0000000..5dff98e
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@2x.png
new file mode 100644
index 0000000..34b3908
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@3x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@3x.png
new file mode 100644
index 0000000..c63fd77
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-29@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40.png
new file mode 100644
index 0000000..cb6b99f
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
new file mode 100644
index 0000000..678fba0
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-40@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-44@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-44@2x.png
new file mode 100644
index 0000000..01c5af7
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-44@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50.png
new file mode 100644
index 0000000..49fd544
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
new file mode 100644
index 0000000..e0a0caa
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-50@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
new file mode 100644
index 0000000..a723c4a
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@3x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
new file mode 100644
index 0000000..8649aad
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-60@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72.png
new file mode 100644
index 0000000..4edb4c6
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
new file mode 100644
index 0000000..3c7efa4
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-72@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76.png
new file mode 100644
index 0000000..a2630ad
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
new file mode 100644
index 0000000..a0335db
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-76@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
new file mode 100644
index 0000000..2dd5230
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-83.5@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-86@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-86@2x.png
new file mode 100644
index 0000000..f32a034
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-86@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-98@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-98@2x.png
new file mode 100644
index 0000000..85ec9e3
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-98@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small.png
new file mode 100644
index 0000000..3a3ba64
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@2x.png
new file mode 100644
index 0000000..d9c5f4b
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@3x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@3x.png
new file mode 100644
index 0000000..ba532dd
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon-small@3x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon.png
new file mode 100644
index 0000000..051cfb3
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon@2x.png b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon@2x.png
new file mode 100644
index 0000000..dcb403f
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/AppIcon.appiconset/icon@2x.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/Contents.json b/platforms/ios/dlapp/Images.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Contents.json b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000..58735de
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,176 @@
+{
+  "images" : [
+    {
+      "extent": "full-screen",
+      "idiom": "iphone",
+      "subtype": "2436h",
+      "filename": "Default-2436h.png",
+      "minimum-system-version": "11.0",
+      "orientation": "portrait",
+      "scale": "3x"
+    },
+    {
+      "extent": "full-screen",
+      "idiom": "iphone",
+      "subtype": "2436h",
+      "filename": "Default-Landscape-2436h.png",
+      "minimum-system-version": "11.0",
+      "orientation": "landscape",
+      "scale": "3x"
+    },
+    {
+      "extent" : "full-screen",
+      "idiom" : "iphone",
+      "subtype" : "736h",
+      "filename" : "Default-736h.png",
+      "minimum-system-version" : "8.0",
+      "orientation" : "portrait",
+      "scale" : "3x"
+    },
+    {
+      "extent" : "full-screen",
+      "idiom" : "iphone",
+      "subtype" : "736h",
+      "filename" : "Default-Landscape-736h.png",
+      "minimum-system-version" : "8.0",
+      "orientation" : "landscape",
+      "scale" : "3x"
+    },
+    {
+      "extent" : "full-screen",
+      "idiom" : "iphone",
+      "subtype" : "667h",
+      "filename" : "Default-667h.png",
+      "minimum-system-version" : "8.0",
+      "orientation" : "portrait",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "filename" : "Default@2x~iphone.png",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    },
+    {
+      "extent" : "full-screen",
+      "idiom" : "iphone",
+      "subtype" : "retina4",
+      "filename" : "Default-568h@2x~iphone.png",
+      "minimum-system-version" : "7.0",
+      "orientation" : "portrait",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "filename" : "Default-Portrait~ipad.png",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "filename" : "Default-Landscape~ipad.png",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "filename" : "Default-Portrait@2x~ipad.png",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "filename" : "Default-Landscape@2x~ipad.png",
+      "extent" : "full-screen",
+      "minimum-system-version" : "7.0",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "filename" : "Default~iphone.png",
+      "extent" : "full-screen",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "filename" : "Default@2x~iphone.png",
+      "extent" : "full-screen",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "iphone",
+      "filename" : "Default-568h@2x~iphone.png",
+      "extent" : "full-screen",
+      "subtype" : "retina4",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "extent" : "to-status-bar",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "filename" : "Default-Portrait~ipad.png",
+      "extent" : "full-screen",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "extent" : "to-status-bar",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "filename": "Default-Landscape~ipad.png",
+      "extent" : "full-screen",
+      "scale" : "1x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "extent" : "to-status-bar",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "portrait",
+      "idiom" : "ipad",
+      "filename" : "Default-Portrait@2x~ipad.png",
+      "extent" : "full-screen",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "extent" : "to-status-bar",
+      "scale" : "2x"
+    },
+    {
+      "orientation" : "landscape",
+      "idiom" : "ipad",
+      "filename": "Default-Landscape@2x~ipad.png",
+      "extent" : "full-screen",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-2436h.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-2436h.png
new file mode 100644
index 0000000..483e491
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-2436h.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png
new file mode 100644
index 0000000..c3e9666
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-568h@2x~iphone.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-667h.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-667h.png
new file mode 100644
index 0000000..8ad05fb
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-667h.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-736h.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-736h.png
new file mode 100644
index 0000000..1197c0d
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-736h.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-2436h.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-2436h.png
new file mode 100644
index 0000000..f926b05
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-2436h.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png
new file mode 100644
index 0000000..29a3120
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape-736h.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png
new file mode 100644
index 0000000..9efa9ac
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png
new file mode 100644
index 0000000..2e48525
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Landscape~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png
new file mode 100644
index 0000000..c8114ff
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png
new file mode 100644
index 0000000..911233f
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default-Portrait~ipad.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png
new file mode 100644
index 0000000..2ed9e12
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png
new file mode 100644
index 0000000..2b19050
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchImage.launchimage/Default~iphone.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/LaunchStoryboard.imageset/Contents.json b/platforms/ios/dlapp/Images.xcassets/LaunchStoryboard.imageset/Contents.json
new file mode 100644
index 0000000..621019d
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/LaunchStoryboard.imageset/Contents.json
@@ -0,0 +1,168 @@
+{
+  "images": [
+    {
+      "idiom": "universal",
+      "scale": "1x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "1x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "1x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "1x"
+    },
+    {
+      "idiom": "universal",
+      "scale": "2x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "2x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "2x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "2x"
+    },
+    {
+      "idiom": "universal",
+      "scale": "3x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "3x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "3x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "universal",
+      "scale": "3x"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "1x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "1x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "1x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "1x"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "2x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "2x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "2x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "ipad",
+      "scale": "2x"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "1x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "1x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "1x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "1x"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "2x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "2x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "2x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "2x"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "3x",
+      "width-class": "compact",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "3x",
+      "width-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "3x",
+      "height-class": "compact"
+    },
+    {
+      "idiom": "iphone",
+      "scale": "3x"
+    }
+  ],
+  "info": {
+    "author": "Xcode",
+    "version": 1
+  }
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Images.xcassets/back.imageset/Contents.json b/platforms/ios/dlapp/Images.xcassets/back.imageset/Contents.json
new file mode 100644
index 0000000..5907dbd
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/back.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "back.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Images.xcassets/back.imageset/back.png b/platforms/ios/dlapp/Images.xcassets/back.imageset/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/back.imageset/back.png
Binary files differ
diff --git a/platforms/ios/dlapp/Images.xcassets/close.imageset/Contents.json b/platforms/ios/dlapp/Images.xcassets/close.imageset/Contents.json
new file mode 100644
index 0000000..0b53002
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/close.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "close.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Images.xcassets/close.imageset/close.png b/platforms/ios/dlapp/Images.xcassets/close.imageset/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/ios/dlapp/Images.xcassets/close.imageset/close.png
Binary files differ
diff --git a/platforms/ios/dlapp/Plugins/README b/platforms/ios/dlapp/Plugins/README
new file mode 100644
index 0000000..87df09f
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/README
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+Put the .h and .m files of your plugin here. The .js files of your plugin belong in the www folder.
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.h
new file mode 100644
index 0000000..5ce279a
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.h
@@ -0,0 +1,295 @@
+// AFHTTPSessionManager.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#if !TARGET_OS_WATCH
+#import <SystemConfiguration/SystemConfiguration.h>
+#endif
+#import <TargetConditionals.h>
+
+#if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV
+#import <MobileCoreServices/MobileCoreServices.h>
+#else
+#import <CoreServices/CoreServices.h>
+#endif
+
+#import "AFURLSessionManager.h"
+
+/**
+ `AFHTTPSessionManager` is a subclass of `AFURLSessionManager` with convenience methods for making HTTP requests. When a `baseURL` is provided, requests made with the `GET` / `POST` / et al. convenience methods can be made with relative paths.
+
+ ## Subclassing Notes
+
+ Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application.
+
+ For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect.
+
+ ## Methods to Override
+
+ To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:completionHandler:`.
+
+ ## Serialization
+
+ Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to `<AFURLRequestSerialization>`.
+
+ Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `<AFURLResponseSerialization>`
+
+ ## URL Construction Using Relative Paths
+
+ For HTTP convenience methods, the request serializer constructs URLs from the path relative to the `-baseURL`, using `NSURL +URLWithString:relativeToURL:`, when provided. If `baseURL` is `nil`, `path` needs to resolve to a valid `NSURL` object using `NSURL +URLWithString:`.
+
+ Below are a few examples of how `baseURL` and relative paths interact:
+
+    NSURL *baseURL = [NSURL URLWithString:@"http://example.com/v1/"];
+    [NSURL URLWithString:@"foo" relativeToURL:baseURL];                  // http://example.com/v1/foo
+    [NSURL URLWithString:@"foo?bar=baz" relativeToURL:baseURL];          // http://example.com/v1/foo?bar=baz
+    [NSURL URLWithString:@"/foo" relativeToURL:baseURL];                 // http://example.com/foo
+    [NSURL URLWithString:@"foo/" relativeToURL:baseURL];                 // http://example.com/v1/foo
+    [NSURL URLWithString:@"/foo/" relativeToURL:baseURL];                // http://example.com/foo/
+    [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/
+
+ Also important to note is that a trailing slash will be added to any `baseURL` without one. This would otherwise cause unexpected behavior when constructing URLs using paths without a leading slash.
+
+ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AFHTTPSessionManager : AFURLSessionManager <NSSecureCoding, NSCopying>
+
+/**
+ The URL used to construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods.
+ */
+@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
+
+/**
+ Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies.
+
+ @warning `requestSerializer` must not be `nil`.
+ */
+@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer;
+
+/**
+ Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`.
+
+ @warning `responseSerializer` must not be `nil`.
+ */
+@property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer;
+
+///---------------------
+/// @name Initialization
+///---------------------
+
+/**
+ Creates and returns an `AFHTTPSessionManager` object.
+ */
++ (instancetype)manager;
+
+/**
+ Initializes an `AFHTTPSessionManager` object with the specified base URL.
+
+ @param url The base URL for the HTTP client.
+
+ @return The newly-initialized HTTP client
+ */
+- (instancetype)initWithBaseURL:(nullable NSURL *)url;
+
+/**
+ Initializes an `AFHTTPSessionManager` object with the specified base URL.
+
+ This is the designated initializer.
+
+ @param url The base URL for the HTTP client.
+ @param configuration The configuration used to create the managed session.
+
+ @return The newly-initialized HTTP client
+ */
+- (instancetype)initWithBaseURL:(nullable NSURL *)url
+           sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
+
+///---------------------------
+/// @name Making HTTP Requests
+///---------------------------
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `GET` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
+                   parameters:(nullable id)parameters
+                      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `GET` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param downloadProgress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
+                            parameters:(nullable id)parameters
+                              progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
+                               success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                               failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `HEAD` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes a single arguments: the data task.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
+                    parameters:(nullable id)parameters
+                       success:(nullable void (^)(NSURLSessionDataTask *task))success
+                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `POST` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(nullable id)parameters
+                       success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `POST` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                             parameters:(nullable id)parameters
+                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
+                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(nullable id)parameters
+     constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
+                       success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol.
+ @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
+                             parameters:(nullable id)parameters
+              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
+                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
+                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `PUT` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
+                   parameters:(nullable id)parameters
+                      success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `PATCH` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
+                     parameters:(nullable id)parameters
+                        success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                        failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+/**
+ Creates and runs an `NSURLSessionDataTask` with a `DELETE` request.
+
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded according to the client request serializer.
+ @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer.
+ @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred.
+
+ @see -dataTaskWithRequest:completionHandler:
+ */
+- (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
+                      parameters:(nullable id)parameters
+                         success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
+                         failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.m
new file mode 100644
index 0000000..2b0c1d0
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFHTTPSessionManager.m
@@ -0,0 +1,355 @@
+// AFHTTPSessionManager.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFHTTPSessionManager.h"
+
+#import "AFURLRequestSerialization.h"
+#import "AFURLResponseSerialization.h"
+
+#import <Availability.h>
+#import <TargetConditionals.h>
+#import <Security/Security.h>
+
+#import <netinet/in.h>
+#import <netinet6/in6.h>
+#import <arpa/inet.h>
+#import <ifaddrs.h>
+#import <netdb.h>
+
+#if TARGET_OS_IOS || TARGET_OS_TV
+#import <UIKit/UIKit.h>
+#elif TARGET_OS_WATCH
+#import <WatchKit/WatchKit.h>
+#endif
+
+@interface AFHTTPSessionManager ()
+@property (readwrite, nonatomic, strong) NSURL *baseURL;
+@end
+
+@implementation AFHTTPSessionManager
+@dynamic responseSerializer;
+
++ (instancetype)manager {
+    return [[[self class] alloc] initWithBaseURL:nil];
+}
+
+- (instancetype)init {
+    return [self initWithBaseURL:nil];
+}
+
+- (instancetype)initWithBaseURL:(NSURL *)url {
+    return [self initWithBaseURL:url sessionConfiguration:nil];
+}
+
+- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
+    return [self initWithBaseURL:nil sessionConfiguration:configuration];
+}
+
+- (instancetype)initWithBaseURL:(NSURL *)url
+           sessionConfiguration:(NSURLSessionConfiguration *)configuration
+{
+    self = [super initWithSessionConfiguration:configuration];
+    if (!self) {
+        return nil;
+    }
+
+    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
+    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
+        url = [url URLByAppendingPathComponent:@""];
+    }
+
+    self.baseURL = url;
+
+    self.requestSerializer = [AFHTTPRequestSerializer serializer];
+    self.responseSerializer = [AFJSONResponseSerializer serializer];
+
+    return self;
+}
+
+#pragma mark -
+
+- (void)setRequestSerializer:(AFHTTPRequestSerializer <AFURLRequestSerialization> *)requestSerializer {
+    NSParameterAssert(requestSerializer);
+
+    _requestSerializer = requestSerializer;
+}
+
+- (void)setResponseSerializer:(AFHTTPResponseSerializer <AFURLResponseSerialization> *)responseSerializer {
+    NSParameterAssert(responseSerializer);
+
+    [super setResponseSerializer:responseSerializer];
+}
+
+#pragma mark -
+
+- (NSURLSessionDataTask *)GET:(NSString *)URLString
+                   parameters:(id)parameters
+                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+
+    return [self GET:URLString parameters:parameters progress:nil success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)GET:(NSString *)URLString
+                   parameters:(id)parameters
+                     progress:(void (^)(NSProgress * _Nonnull))downloadProgress
+                      success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
+                      failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
+{
+
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
+                                                        URLString:URLString
+                                                       parameters:parameters
+                                                   uploadProgress:nil
+                                                 downloadProgress:downloadProgress
+                                                          success:success
+                                                          failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)HEAD:(NSString *)URLString
+                    parameters:(id)parameters
+                       success:(void (^)(NSURLSessionDataTask *task))success
+                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) {
+        if (success) {
+            success(task);
+        }
+    } failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(id)parameters
+                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    return [self POST:URLString parameters:parameters progress:nil success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(id)parameters
+                      progress:(void (^)(NSProgress * _Nonnull))uploadProgress
+                       success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
+                       failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(nullable id)parameters
+     constructingBodyWithBlock:(nullable void (^)(id<AFMultipartFormData> _Nonnull))block
+                       success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
+                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
+{
+    return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure];
+}
+
+- (NSURLSessionDataTask *)POST:(NSString *)URLString
+                    parameters:(id)parameters
+     constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
+                      progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
+                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSError *serializationError = nil;
+    NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
+    if (serializationError) {
+        if (failure) {
+            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
+                failure(nil, serializationError);
+            });
+        }
+
+        return nil;
+    }
+
+    __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
+        if (error) {
+            if (failure) {
+                failure(task, error);
+            }
+        } else {
+            if (success) {
+                success(task, responseObject);
+            }
+        }
+    }];
+
+    [task resume];
+
+    return task;
+}
+
+- (NSURLSessionDataTask *)PUT:(NSString *)URLString
+                   parameters:(id)parameters
+                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)PATCH:(NSString *)URLString
+                     parameters:(id)parameters
+                        success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)DELETE:(NSString *)URLString
+                      parameters:(id)parameters
+                         success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
+                         failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
+{
+    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
+
+    [dataTask resume];
+
+    return dataTask;
+}
+
+- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
+                                       URLString:(NSString *)URLString
+                                      parameters:(id)parameters
+                                  uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
+                                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
+                                         success:(void (^)(NSURLSessionDataTask *, id))success
+                                         failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
+{
+    NSError *serializationError = nil;
+    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
+    if (serializationError) {
+        if (failure) {
+            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
+                failure(nil, serializationError);
+            });
+        }
+
+        return nil;
+    }
+
+    __block NSURLSessionDataTask *dataTask = nil;
+    dataTask = [self dataTaskWithRequest:request
+                          uploadProgress:uploadProgress
+                        downloadProgress:downloadProgress
+                       completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
+        if (error) {
+            if (failure) {
+                failure(dataTask, error);
+            }
+        } else {
+            if (success) {
+                success(dataTask, responseObject);
+            }
+        }
+    }];
+
+    return dataTask;
+}
+
+#pragma mark - NSObject
+
+- (NSString *)description {
+    return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue];
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+    return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))];
+    NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
+    if (!configuration) {
+        NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"];
+        if (configurationIdentifier) {
+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100)
+            configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier];
+#else
+            configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier];
+#endif
+        }
+    }
+
+    self = [self initWithBaseURL:baseURL sessionConfiguration:configuration];
+    if (!self) {
+        return nil;
+    }
+
+    self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))];
+    self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
+    AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))];
+    if (decodedPolicy) {
+        self.securityPolicy = decodedPolicy;
+    }
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))];
+    if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) {
+        [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"];
+    } else {
+        [coder encodeObject:self.session.configuration.identifier forKey:@"identifier"];
+    }
+    [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))];
+    [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))];
+    [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration];
+
+    HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone];
+    HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone];
+    HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone];
+    return HTTPClient;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.h
new file mode 100644
index 0000000..0feb18d
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.h
@@ -0,0 +1,206 @@
+// AFNetworkReachabilityManager.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+#if !TARGET_OS_WATCH
+#import <SystemConfiguration/SystemConfiguration.h>
+
+typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
+    AFNetworkReachabilityStatusUnknown          = -1,
+    AFNetworkReachabilityStatusNotReachable     = 0,
+    AFNetworkReachabilityStatusReachableViaWWAN = 1,
+    AFNetworkReachabilityStatusReachableViaWiFi = 2,
+};
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces.
+
+ Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability.
+
+ See Apple's Reachability Sample Code ( https://developer.apple.com/library/ios/samplecode/reachability/ )
+
+ @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined.
+ */
+@interface AFNetworkReachabilityManager : NSObject
+
+/**
+ The current network reachability status.
+ */
+@property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
+
+/**
+ Whether or not the network is currently reachable.
+ */
+@property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable;
+
+/**
+ Whether or not the network is currently reachable via WWAN.
+ */
+@property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
+
+/**
+ Whether or not the network is currently reachable via WiFi.
+ */
+@property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
+
+///---------------------
+/// @name Initialization
+///---------------------
+
+/**
+ Returns the shared network reachability manager.
+ */
++ (instancetype)sharedManager;
+
+/**
+ Creates and returns a network reachability manager with the default socket address.
+ 
+ @return An initialized network reachability manager, actively monitoring the default socket address.
+ */
++ (instancetype)manager;
+
+/**
+ Creates and returns a network reachability manager for the specified domain.
+
+ @param domain The domain used to evaluate network reachability.
+
+ @return An initialized network reachability manager, actively monitoring the specified domain.
+ */
++ (instancetype)managerForDomain:(NSString *)domain;
+
+/**
+ Creates and returns a network reachability manager for the socket address.
+
+ @param address The socket address (`sockaddr_in6`) used to evaluate network reachability.
+
+ @return An initialized network reachability manager, actively monitoring the specified socket address.
+ */
++ (instancetype)managerForAddress:(const void *)address;
+
+/**
+ Initializes an instance of a network reachability manager from the specified reachability object.
+
+ @param reachability The reachability object to monitor.
+
+ @return An initialized network reachability manager, actively monitoring the specified reachability.
+ */
+- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER;
+
+///--------------------------------------------------
+/// @name Starting & Stopping Reachability Monitoring
+///--------------------------------------------------
+
+/**
+ Starts monitoring for changes in network reachability status.
+ */
+- (void)startMonitoring;
+
+/**
+ Stops monitoring for changes in network reachability status.
+ */
+- (void)stopMonitoring;
+
+///-------------------------------------------------
+/// @name Getting Localized Reachability Description
+///-------------------------------------------------
+
+/**
+ Returns a localized string representation of the current network reachability status.
+ */
+- (NSString *)localizedNetworkReachabilityStatusString;
+
+///---------------------------------------------------
+/// @name Setting Network Reachability Change Callback
+///---------------------------------------------------
+
+/**
+ Sets a callback to be executed when the network availability of the `baseURL` host changes.
+
+ @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`.
+ */
+- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block;
+
+@end
+
+///----------------
+/// @name Constants
+///----------------
+
+/**
+ ## Network Reachability
+
+ The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses.
+
+ enum {
+ AFNetworkReachabilityStatusUnknown,
+ AFNetworkReachabilityStatusNotReachable,
+ AFNetworkReachabilityStatusReachableViaWWAN,
+ AFNetworkReachabilityStatusReachableViaWiFi,
+ }
+
+ `AFNetworkReachabilityStatusUnknown`
+ The `baseURL` host reachability is not known.
+
+ `AFNetworkReachabilityStatusNotReachable`
+ The `baseURL` host cannot be reached.
+
+ `AFNetworkReachabilityStatusReachableViaWWAN`
+ The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS.
+
+ `AFNetworkReachabilityStatusReachableViaWiFi`
+ The `baseURL` host can be reached via a Wi-Fi connection.
+
+ ### Keys for Notification UserInfo Dictionary
+
+ Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification.
+
+ `AFNetworkingReachabilityNotificationStatusItem`
+ A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification.
+ The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status.
+ */
+
+///--------------------
+/// @name Notifications
+///--------------------
+
+/**
+ Posted when network reachability changes.
+ This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability.
+
+ @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (`Prefix.pch`).
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;
+FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem;
+
+///--------------------
+/// @name Functions
+///--------------------
+
+/**
+ Returns a localized string representation of an `AFNetworkReachabilityStatus` value.
+ */
+FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status);
+
+NS_ASSUME_NONNULL_END
+#endif
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.m
new file mode 100644
index 0000000..d458364
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworkReachabilityManager.m
@@ -0,0 +1,263 @@
+// AFNetworkReachabilityManager.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFNetworkReachabilityManager.h"
+#if !TARGET_OS_WATCH
+
+#import <netinet/in.h>
+#import <netinet6/in6.h>
+#import <arpa/inet.h>
+#import <ifaddrs.h>
+#import <netdb.h>
+
+NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
+NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem";
+
+typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status);
+
+NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) {
+    switch (status) {
+        case AFNetworkReachabilityStatusNotReachable:
+            return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil);
+        case AFNetworkReachabilityStatusReachableViaWWAN:
+            return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil);
+        case AFNetworkReachabilityStatusReachableViaWiFi:
+            return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil);
+        case AFNetworkReachabilityStatusUnknown:
+        default:
+            return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil);
+    }
+}
+
+static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) {
+    BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
+    BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
+    BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0));
+    BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0);
+    BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction));
+
+    AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown;
+    if (isNetworkReachable == NO) {
+        status = AFNetworkReachabilityStatusNotReachable;
+    }
+#if	TARGET_OS_IPHONE
+    else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
+        status = AFNetworkReachabilityStatusReachableViaWWAN;
+    }
+#endif
+    else {
+        status = AFNetworkReachabilityStatusReachableViaWiFi;
+    }
+
+    return status;
+}
+
+/**
+ * Queue a status change notification for the main thread.
+ *
+ * This is done to ensure that the notifications are received in the same order
+ * as they are sent. If notifications are sent directly, it is possible that
+ * a queued notification (for an earlier status condition) is processed after
+ * the later update, resulting in the listener being left in the wrong state.
+ */
+static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) {
+    AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (block) {
+            block(status);
+        }
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) };
+        [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo];
+    });
+}
+
+static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
+    AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info);
+}
+
+
+static const void * AFNetworkReachabilityRetainCallback(const void *info) {
+    return Block_copy(info);
+}
+
+static void AFNetworkReachabilityReleaseCallback(const void *info) {
+    if (info) {
+        Block_release(info);
+    }
+}
+
+@interface AFNetworkReachabilityManager ()
+@property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability;
+@property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus;
+@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock;
+@end
+
+@implementation AFNetworkReachabilityManager
+
++ (instancetype)sharedManager {
+    static AFNetworkReachabilityManager *_sharedManager = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _sharedManager = [self manager];
+    });
+
+    return _sharedManager;
+}
+
++ (instancetype)managerForDomain:(NSString *)domain {
+    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]);
+
+    AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
+    
+    CFRelease(reachability);
+
+    return manager;
+}
+
++ (instancetype)managerForAddress:(const void *)address {
+    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address);
+    AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability];
+
+    CFRelease(reachability);
+    
+    return manager;
+}
+
++ (instancetype)manager
+{
+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
+    struct sockaddr_in6 address;
+    bzero(&address, sizeof(address));
+    address.sin6_len = sizeof(address);
+    address.sin6_family = AF_INET6;
+#else
+    struct sockaddr_in address;
+    bzero(&address, sizeof(address));
+    address.sin_len = sizeof(address);
+    address.sin_family = AF_INET;
+#endif
+    return [self managerForAddress:&address];
+}
+
+- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    _networkReachability = CFRetain(reachability);
+    self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown;
+
+    return self;
+}
+
+- (instancetype)init NS_UNAVAILABLE
+{
+    return nil;
+}
+
+- (void)dealloc {
+    [self stopMonitoring];
+    
+    if (_networkReachability != NULL) {
+        CFRelease(_networkReachability);
+    }
+}
+
+#pragma mark -
+
+- (BOOL)isReachable {
+    return [self isReachableViaWWAN] || [self isReachableViaWiFi];
+}
+
+- (BOOL)isReachableViaWWAN {
+    return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN;
+}
+
+- (BOOL)isReachableViaWiFi {
+    return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi;
+}
+
+#pragma mark -
+
+- (void)startMonitoring {
+    [self stopMonitoring];
+
+    if (!self.networkReachability) {
+        return;
+    }
+
+    __weak __typeof(self)weakSelf = self;
+    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
+        __strong __typeof(weakSelf)strongSelf = weakSelf;
+
+        strongSelf.networkReachabilityStatus = status;
+        if (strongSelf.networkReachabilityStatusBlock) {
+            strongSelf.networkReachabilityStatusBlock(status);
+        }
+
+    };
+
+    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
+    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
+    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
+        SCNetworkReachabilityFlags flags;
+        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
+            AFPostReachabilityStatusChange(flags, callback);
+        }
+    });
+}
+
+- (void)stopMonitoring {
+    if (!self.networkReachability) {
+        return;
+    }
+
+    SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
+}
+
+#pragma mark -
+
+- (NSString *)localizedNetworkReachabilityStatusString {
+    return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus);
+}
+
+#pragma mark -
+
+- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block {
+    self.networkReachabilityStatusBlock = block;
+}
+
+#pragma mark - NSKeyValueObserving
+
++ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
+    if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) {
+        return [NSSet setWithObject:@"networkReachabilityStatus"];
+    }
+
+    return [super keyPathsForValuesAffectingValueForKey:key];
+}
+
+@end
+#endif
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworking.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworking.h
new file mode 100644
index 0000000..e2fb2f4
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFNetworking.h
@@ -0,0 +1,41 @@
+// AFNetworking.h
+//
+// Copyright (c) 2013 AFNetworking (http://afnetworking.com/)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import <Availability.h>
+#import <TargetConditionals.h>
+
+#ifndef _AFNETWORKING_
+    #define _AFNETWORKING_
+
+    #import "AFURLRequestSerialization.h"
+    #import "AFURLResponseSerialization.h"
+    #import "AFSecurityPolicy.h"
+
+#if !TARGET_OS_WATCH
+    #import "AFNetworkReachabilityManager.h"
+#endif
+
+    #import "AFURLSessionManager.h"
+    #import "AFHTTPSessionManager.h"
+
+#endif /* _AFNETWORKING_ */
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.h
new file mode 100644
index 0000000..c005efa
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.h
@@ -0,0 +1,154 @@
+// AFSecurityPolicy.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import <Security/Security.h>
+
+typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
+    AFSSLPinningModeNone,
+    AFSSLPinningModePublicKey,
+    AFSSLPinningModeCertificate,
+};
+
+/**
+ `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections.
+
+ Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AFSecurityPolicy : NSObject <NSSecureCoding, NSCopying>
+
+/**
+ The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`.
+ */
+@property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode;
+
+/**
+ The certificates used to evaluate server trust according to the SSL pinning mode. 
+
+  By default, this property is set to any (`.cer`) certificates included in the target compiling AFNetworking. Note that if you are using AFNetworking as embedded framework, no certificates will be pinned by default. Use `certificatesInBundle` to load certificates from your target, and then create a new policy by calling `policyWithPinningMode:withPinnedCertificates`.
+ 
+ Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches.
+ */
+@property (nonatomic, strong, nullable) NSSet <NSData *> *pinnedCertificates;
+
+/**
+ Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`.
+ */
+@property (nonatomic, assign) BOOL allowInvalidCertificates;
+
+/**
+ Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`.
+ */
+@property (nonatomic, assign) BOOL validatesDomainName;
+
+///-----------------------------------------
+/// @name Getting Certificates from the Bundle
+///-----------------------------------------
+
+/**
+ Returns any certificates included in the bundle. If you are using AFNetworking as an embedded framework, you must use this method to find the certificates you have included in your app bundle, and use them when creating your security policy by calling `policyWithPinningMode:withPinnedCertificates`.
+
+ @return The certificates included in the given bundle.
+ */
++ (NSSet <NSData *> *)certificatesInBundle:(NSBundle *)bundle;
+
+///-----------------------------------------
+/// @name Getting Specific Security Policies
+///-----------------------------------------
+
+/**
+ Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys.
+
+ @return The default security policy.
+ */
++ (instancetype)defaultPolicy;
+
+///---------------------
+/// @name Initialization
+///---------------------
+
+/**
+ Creates and returns a security policy with the specified pinning mode.
+
+ @param pinningMode The SSL pinning mode.
+
+ @return A new security policy.
+ */
++ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode;
+
+/**
+ Creates and returns a security policy with the specified pinning mode.
+
+ @param pinningMode The SSL pinning mode.
+ @param pinnedCertificates The certificates to pin against.
+
+ @return A new security policy.
+ */
++ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet <NSData *> *)pinnedCertificates;
+
+///------------------------------
+/// @name Evaluating Server Trust
+///------------------------------
+
+/**
+ Whether or not the specified server trust should be accepted, based on the security policy.
+
+ This method should be used when responding to an authentication challenge from a server.
+
+ @param serverTrust The X.509 certificate trust of the server.
+ @param domain The domain of serverTrust. If `nil`, the domain will not be validated.
+
+ @return Whether or not to trust the server.
+ */
+- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
+                  forDomain:(nullable NSString *)domain;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+///----------------
+/// @name Constants
+///----------------
+
+/**
+ ## SSL Pinning Modes
+
+ The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes.
+
+ enum {
+ AFSSLPinningModeNone,
+ AFSSLPinningModePublicKey,
+ AFSSLPinningModeCertificate,
+ }
+
+ `AFSSLPinningModeNone`
+ Do not used pinned certificates to validate servers.
+
+ `AFSSLPinningModePublicKey`
+ Validate host certificates against public keys of pinned certificates.
+
+ `AFSSLPinningModeCertificate`
+ Validate host certificates against pinned certificates.
+*/
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.m
new file mode 100644
index 0000000..4c04e22
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFSecurityPolicy.m
@@ -0,0 +1,353 @@
+// AFSecurityPolicy.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFSecurityPolicy.h"
+
+#import <AssertMacros.h>
+
+#if !TARGET_OS_IOS && !TARGET_OS_WATCH && !TARGET_OS_TV
+static NSData * AFSecKeyGetData(SecKeyRef key) {
+    CFDataRef data = NULL;
+
+    __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out);
+
+    return (__bridge_transfer NSData *)data;
+
+_out:
+    if (data) {
+        CFRelease(data);
+    }
+
+    return nil;
+}
+#endif
+
+static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) {
+#if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV
+    return [(__bridge id)key1 isEqual:(__bridge id)key2];
+#else
+    return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)];
+#endif
+}
+
+static id AFPublicKeyForCertificate(NSData *certificate) {
+    id allowedPublicKey = nil;
+    SecCertificateRef allowedCertificate;
+    SecCertificateRef allowedCertificates[1];
+    CFArrayRef tempCertificates = nil;
+    SecPolicyRef policy = nil;
+    SecTrustRef allowedTrust = nil;
+    SecTrustResultType result;
+
+    allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
+    __Require_Quiet(allowedCertificate != NULL, _out);
+
+    allowedCertificates[0] = allowedCertificate;
+    tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
+
+    policy = SecPolicyCreateBasicX509();
+    __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out);
+    __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out);
+
+    allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust);
+
+_out:
+    if (allowedTrust) {
+        CFRelease(allowedTrust);
+    }
+
+    if (policy) {
+        CFRelease(policy);
+    }
+
+    if (tempCertificates) {
+        CFRelease(tempCertificates);
+    }
+
+    if (allowedCertificate) {
+        CFRelease(allowedCertificate);
+    }
+
+    return allowedPublicKey;
+}
+
+static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
+    BOOL isValid = NO;
+    SecTrustResultType result;
+    __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out);
+
+    isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
+
+_out:
+    return isValid;
+}
+
+static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) {
+    CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
+    NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
+
+    for (CFIndex i = 0; i < certificateCount; i++) {
+        SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
+        [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)];
+    }
+
+    return [NSArray arrayWithArray:trustChain];
+}
+
+static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
+    SecPolicyRef policy = SecPolicyCreateBasicX509();
+    CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
+    NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
+    for (CFIndex i = 0; i < certificateCount; i++) {
+        SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
+
+        SecCertificateRef someCertificates[] = {certificate};
+        CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL);
+
+        SecTrustRef trust;
+        __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out);
+
+        SecTrustResultType result;
+        __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out);
+
+        [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)];
+
+    _out:
+        if (trust) {
+            CFRelease(trust);
+        }
+
+        if (certificates) {
+            CFRelease(certificates);
+        }
+
+        continue;
+    }
+    CFRelease(policy);
+
+    return [NSArray arrayWithArray:trustChain];
+}
+
+#pragma mark -
+
+@interface AFSecurityPolicy()
+@property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode;
+@property (readwrite, nonatomic, strong) NSSet *pinnedPublicKeys;
+@end
+
+@implementation AFSecurityPolicy
+
++ (NSSet *)certificatesInBundle:(NSBundle *)bundle {
+    NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"www/certificates"];
+    NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]];
+
+    for (NSString *path in paths) {
+        NSData *certificateData = [NSData dataWithContentsOfFile:path];
+        [certificates addObject:certificateData];
+    }
+
+    return [NSSet setWithSet:certificates];
+}
+
++ (NSSet *)defaultPinnedCertificates {
+    static NSSet *_defaultPinnedCertificates = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+        _defaultPinnedCertificates = [self certificatesInBundle:bundle];
+    });
+
+    return _defaultPinnedCertificates;
+}
+
++ (instancetype)defaultPolicy {
+    AFSecurityPolicy *securityPolicy = [[self alloc] init];
+    securityPolicy.SSLPinningMode = AFSSLPinningModeNone;
+
+    return securityPolicy;
+}
+
++ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode {
+    return [self policyWithPinningMode:pinningMode withPinnedCertificates:[self defaultPinnedCertificates]];
+}
+
++ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates {
+    AFSecurityPolicy *securityPolicy = [[self alloc] init];
+    securityPolicy.SSLPinningMode = pinningMode;
+
+    [securityPolicy setPinnedCertificates:pinnedCertificates];
+
+    return securityPolicy;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.validatesDomainName = YES;
+
+    return self;
+}
+
+- (void)setPinnedCertificates:(NSSet *)pinnedCertificates {
+    _pinnedCertificates = pinnedCertificates;
+
+    if (self.pinnedCertificates) {
+        NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]];
+        for (NSData *certificate in self.pinnedCertificates) {
+            id publicKey = AFPublicKeyForCertificate(certificate);
+            if (!publicKey) {
+                continue;
+            }
+            [mutablePinnedPublicKeys addObject:publicKey];
+        }
+        self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys];
+    } else {
+        self.pinnedPublicKeys = nil;
+    }
+}
+
+#pragma mark -
+
+- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
+                  forDomain:(NSString *)domain
+{
+    if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) {
+        // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html
+        //  According to the docs, you should only trust your provided certs for evaluation.
+        //  Pinned certificates are added to the trust. Without pinned certificates,
+        //  there is nothing to evaluate against.
+        //
+        //  From Apple Docs:
+        //          "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors).
+        //           Instead, add your own (self-signed) CA certificate to the list of trusted anchors."
+        NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning.");
+        return NO;
+    }
+
+    NSMutableArray *policies = [NSMutableArray array];
+    if (self.validatesDomainName) {
+        [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
+    } else {
+        [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
+    }
+
+    SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
+
+    if (self.SSLPinningMode == AFSSLPinningModeNone) {
+        return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust);
+    } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) {
+        return NO;
+    }
+
+    switch (self.SSLPinningMode) {
+        case AFSSLPinningModeNone:
+        default:
+            return NO;
+        case AFSSLPinningModeCertificate: {
+            NSMutableArray *pinnedCertificates = [NSMutableArray array];
+            for (NSData *certificateData in self.pinnedCertificates) {
+                [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
+            }
+            SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
+
+            if (!AFServerTrustIsValid(serverTrust)) {
+                return NO;
+            }
+
+            // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA)
+            NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust);
+
+            for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) {
+                if ([self.pinnedCertificates containsObject:trustChainCertificate]) {
+                    return YES;
+                }
+            }
+
+            return NO;
+        }
+        case AFSSLPinningModePublicKey: {
+            NSUInteger trustedPublicKeyCount = 0;
+            NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
+
+            for (id trustChainPublicKey in publicKeys) {
+                for (id pinnedPublicKey in self.pinnedPublicKeys) {
+                    if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
+                        trustedPublicKeyCount += 1;
+                    }
+                }
+            }
+            return trustedPublicKeyCount > 0;
+        }
+    }
+
+    return NO;
+}
+
+#pragma mark - NSKeyValueObserving
+
++ (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys {
+    return [NSSet setWithObject:@"pinnedCertificates"];
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+    return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+
+    self = [self init];
+    if (!self) {
+        return nil;
+    }
+
+    self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue];
+    self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))];
+    self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))];
+    self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))];
+    [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))];
+    [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))];
+    [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init];
+    securityPolicy.SSLPinningMode = self.SSLPinningMode;
+    securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates;
+    securityPolicy.validatesDomainName = self.validatesDomainName;
+    securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone];
+
+    return securityPolicy;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.h
new file mode 100644
index 0000000..694696b
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.h
@@ -0,0 +1,479 @@
+// AFURLRequestSerialization.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import <TargetConditionals.h>
+
+#if TARGET_OS_IOS || TARGET_OS_TV
+#import <UIKit/UIKit.h>
+#elif TARGET_OS_WATCH
+#import <WatchKit/WatchKit.h>
+#endif
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ Returns a percent-escaped string following RFC 3986 for a query string key or value.
+ RFC 3986 states that the following characters are "reserved" characters.
+ - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
+ - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
+
+ In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
+ query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
+ should be percent-escaped in the query string.
+ 
+ @param string The string to be percent-escaped.
+ 
+ @return The percent-escaped string.
+ */
+FOUNDATION_EXPORT NSString * AFPercentEscapedStringFromString(NSString *string);
+
+/**
+ A helper method to generate encoded url query parameters for appending to the end of a URL.
+
+ @param parameters A dictionary of key/values to be encoded.
+
+ @return A url encoded query string
+ */
+FOUNDATION_EXPORT NSString * AFQueryStringFromParameters(NSDictionary *parameters);
+
+/**
+ The `AFURLRequestSerialization` protocol is adopted by an object that encodes parameters for a specified HTTP requests. Request serializers may encode parameters as query strings, HTTP bodies, setting the appropriate HTTP header fields as necessary.
+
+ For example, a JSON request serializer may set the HTTP body of the request to a JSON representation, and set the `Content-Type` HTTP header field value to `application/json`.
+ */
+@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>
+
+/**
+ Returns a request with the specified parameters encoded into a copy of the original request.
+
+ @param request The original request.
+ @param parameters The parameters to be encoded.
+ @param error The error that occurred while attempting to encode the request parameters.
+
+ @return A serialized request.
+ */
+- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
+                               withParameters:(nullable id)parameters
+                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
+
+@end
+
+#pragma mark -
+
+/**
+
+ */
+typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) {
+    AFHTTPRequestQueryStringDefaultStyle = 0,
+};
+
+@protocol AFMultipartFormData;
+
+/**
+ `AFHTTPRequestSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation.
+
+ Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPRequestSerializer` in order to ensure consistent default behavior.
+ */
+@interface AFHTTPRequestSerializer : NSObject <AFURLRequestSerialization>
+
+/**
+ The string encoding used to serialize parameters. `NSUTF8StringEncoding` by default.
+ */
+@property (nonatomic, assign) NSStringEncoding stringEncoding;
+
+/**
+ Whether created requests can use the device’s cellular radio (if present). `YES` by default.
+
+ @see NSMutableURLRequest -setAllowsCellularAccess:
+ */
+@property (nonatomic, assign) BOOL allowsCellularAccess;
+
+/**
+ The cache policy of created requests. `NSURLRequestUseProtocolCachePolicy` by default.
+
+ @see NSMutableURLRequest -setCachePolicy:
+ */
+@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
+
+/**
+ Whether created requests should use the default cookie handling. `YES` by default.
+
+ @see NSMutableURLRequest -setHTTPShouldHandleCookies:
+ */
+@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;
+
+/**
+ Whether created requests can continue transmitting data before receiving a response from an earlier transmission. `NO` by default
+
+ @see NSMutableURLRequest -setHTTPShouldUsePipelining:
+ */
+@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;
+
+/**
+ The network service type for created requests. `NSURLNetworkServiceTypeDefault` by default.
+
+ @see NSMutableURLRequest -setNetworkServiceType:
+ */
+@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;
+
+/**
+ The timeout interval, in seconds, for created requests. The default timeout interval is 60 seconds.
+
+ @see NSMutableURLRequest -setTimeoutInterval:
+ */
+@property (nonatomic, assign) NSTimeInterval timeoutInterval;
+
+///---------------------------------------
+/// @name Configuring HTTP Request Headers
+///---------------------------------------
+
+/**
+ Default HTTP header field values to be applied to serialized requests. By default, these include the following:
+
+ - `Accept-Language` with the contents of `NSLocale +preferredLanguages`
+ - `User-Agent` with the contents of various bundle identifiers and OS designations
+
+ @discussion To add or remove default request headers, use `setValue:forHTTPHeaderField:`.
+ */
+@property (readonly, nonatomic, strong) NSDictionary <NSString *, NSString *> *HTTPRequestHeaders;
+
+/**
+ Creates and returns a serializer with default configuration.
+ */
++ (instancetype)serializer;
+
+/**
+ Sets the value for the HTTP headers set in request objects made by the HTTP client. If `nil`, removes the existing value for that header.
+
+ @param field The HTTP header to set a default value for
+ @param value The value set as default for the specified header, or `nil`
+ */
+- (void)setValue:(nullable NSString *)value
+forHTTPHeaderField:(NSString *)field;
+
+/**
+ Returns the value for the HTTP headers set in the request serializer.
+
+ @param field The HTTP header to retrieve the default value for
+
+ @return The value set as default for the specified header, or `nil`
+ */
+- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;
+
+/**
+ Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header.
+
+ @param username The HTTP basic auth username
+ @param password The HTTP basic auth password
+ */
+- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
+                                       password:(NSString *)password;
+
+/**
+ Clears any existing value for the "Authorization" HTTP header.
+ */
+- (void)clearAuthorizationHeader;
+
+///-------------------------------------------------------
+/// @name Configuring Query String Parameter Serialization
+///-------------------------------------------------------
+
+/**
+ HTTP methods for which serialized requests will encode parameters as a query string. `GET`, `HEAD`, and `DELETE` by default.
+ */
+@property (nonatomic, strong) NSSet <NSString *> *HTTPMethodsEncodingParametersInURI;
+
+/**
+ Set the method of query string serialization according to one of the pre-defined styles.
+
+ @param style The serialization style.
+
+ @see AFHTTPRequestQueryStringSerializationStyle
+ */
+- (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style;
+
+/**
+ Set the a custom method of query string serialization according to the specified block.
+
+ @param block A block that defines a process of encoding parameters into a query string. This block returns the query string and takes three arguments: the request, the parameters to encode, and the error that occurred when attempting to encode parameters for the given request.
+ */
+- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block;
+
+///-------------------------------
+/// @name Creating Request Objects
+///-------------------------------
+
+/**
+ Creates an `NSMutableURLRequest` object with the specified HTTP method and URL string.
+
+ If the HTTP method is `GET`, `HEAD`, or `DELETE`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. Otherwise, the parameters will be encoded according to the value of the `parameterEncoding` property, and set as the request body.
+
+ @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. This parameter must not be `nil`.
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body.
+ @param error The error that occurred while constructing the request.
+
+ @return An `NSMutableURLRequest` object.
+ */
+- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
+                                 URLString:(NSString *)URLString
+                                parameters:(nullable id)parameters
+                                     error:(NSError * _Nullable __autoreleasing *)error;
+
+/**
+ Creates an `NSMutableURLRequest` object with the specified HTTP method and URLString, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. See http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2
+
+ Multipart form requests are automatically streamed, reading files directly from disk along with in-memory data in a single HTTP body. The resulting `NSMutableURLRequest` object has an `HTTPBodyStream` property, so refrain from setting `HTTPBodyStream` or `HTTPBody` on this request object, as it will clear out the multipart form body stream.
+
+ @param method The HTTP method for the request. This parameter must not be `GET` or `HEAD`, or `nil`.
+ @param URLString The URL string used to create the request URL.
+ @param parameters The parameters to be encoded and set in the request HTTP body.
+ @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol.
+ @param error The error that occurred while constructing the request.
+
+ @return An `NSMutableURLRequest` object
+ */
+- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
+                                              URLString:(NSString *)URLString
+                                             parameters:(nullable NSDictionary <NSString *, id> *)parameters
+                              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
+                                                  error:(NSError * _Nullable __autoreleasing *)error;
+
+/**
+ Creates an `NSMutableURLRequest` by removing the `HTTPBodyStream` from a request, and asynchronously writing its contents into the specified file, invoking the completion handler when finished.
+
+ @param request The multipart form request. The `HTTPBodyStream` property of `request` must not be `nil`.
+ @param fileURL The file URL to write multipart form contents to.
+ @param handler A handler block to execute.
+
+ @discussion There is a bug in `NSURLSessionTask` that causes requests to not send a `Content-Length` header when streaming contents from an HTTP body, which is notably problematic when interacting with the Amazon S3 webservice. As a workaround, this method takes a request constructed with `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:`, or any other request with an `HTTPBodyStream`, writes the contents to the specified file and returns a copy of the original request with the `HTTPBodyStream` property set to `nil`. From here, the file can either be passed to `AFURLSessionManager -uploadTaskWithRequest:fromFile:progress:completionHandler:`, or have its contents read into an `NSData` that's assigned to the `HTTPBody` property of the request.
+
+ @see https://github.com/AFNetworking/AFNetworking/issues/1398
+ */
+- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
+                             writingStreamContentsToFile:(NSURL *)fileURL
+                                       completionHandler:(nullable void (^)(NSError * _Nullable error))handler;
+
+@end
+
+#pragma mark -
+
+/**
+ The `AFMultipartFormData` protocol defines the methods supported by the parameter in the block argument of `AFHTTPRequestSerializer -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:`.
+ */
+@protocol AFMultipartFormData
+
+/**
+ Appends the HTTP header `Content-Disposition: file; filename=#{generated filename}; name=#{name}"` and `Content-Type: #{generated mimeType}`, followed by the encoded file data and the multipart form boundary.
+
+ The filename and MIME type for this data in the form will be automatically generated, using the last path component of the `fileURL` and system associated MIME type for the `fileURL` extension, respectively.
+
+ @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`.
+ @param name The name to be associated with the specified data. This parameter must not be `nil`.
+ @param error If an error occurs, upon return contains an `NSError` object that describes the problem.
+
+ @return `YES` if the file data was successfully appended, otherwise `NO`.
+ */
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
+                         name:(NSString *)name
+                        error:(NSError * _Nullable __autoreleasing *)error;
+
+/**
+ Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
+
+ @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`.
+ @param name The name to be associated with the specified data. This parameter must not be `nil`.
+ @param fileName The file name to be used in the `Content-Disposition` header. This parameter must not be `nil`.
+ @param mimeType The declared MIME type of the file data. This parameter must not be `nil`.
+ @param error If an error occurs, upon return contains an `NSError` object that describes the problem.
+
+ @return `YES` if the file data was successfully appended otherwise `NO`.
+ */
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
+                         name:(NSString *)name
+                     fileName:(NSString *)fileName
+                     mimeType:(NSString *)mimeType
+                        error:(NSError * _Nullable __autoreleasing *)error;
+
+/**
+ Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary.
+
+ @param inputStream The input stream to be appended to the form data
+ @param name The name to be associated with the specified input stream. This parameter must not be `nil`.
+ @param fileName The filename to be associated with the specified input stream. This parameter must not be `nil`.
+ @param length The length of the specified input stream in bytes.
+ @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`.
+ */
+- (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream
+                             name:(NSString *)name
+                         fileName:(NSString *)fileName
+                           length:(int64_t)length
+                         mimeType:(NSString *)mimeType;
+
+/**
+ Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary.
+
+ @param data The data to be encoded and appended to the form data.
+ @param name The name to be associated with the specified data. This parameter must not be `nil`.
+ @param fileName The filename to be associated with the specified data. This parameter must not be `nil`.
+ @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`.
+ */
+- (void)appendPartWithFileData:(NSData *)data
+                          name:(NSString *)name
+                      fileName:(NSString *)fileName
+                      mimeType:(NSString *)mimeType;
+
+/**
+ Appends the HTTP headers `Content-Disposition: form-data; name=#{name}"`, followed by the encoded data and the multipart form boundary.
+
+ @param data The data to be encoded and appended to the form data.
+ @param name The name to be associated with the specified data. This parameter must not be `nil`.
+ */
+
+- (void)appendPartWithFormData:(NSData *)data
+                          name:(NSString *)name;
+
+
+/**
+ Appends HTTP headers, followed by the encoded data and the multipart form boundary.
+
+ @param headers The HTTP headers to be appended to the form data.
+ @param body The data to be encoded and appended to the form data. This parameter must not be `nil`.
+ */
+- (void)appendPartWithHeaders:(nullable NSDictionary <NSString *, NSString *> *)headers
+                         body:(NSData *)body;
+
+/**
+ Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream.
+
+ When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Setting a maximum packet size and delay according to the recommended values (`kAFUploadStream3GSuggestedPacketSize` and `kAFUploadStream3GSuggestedDelay`) lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, there is no definite way to distinguish between a 3G, EDGE, or LTE connection over `NSURLConnection`. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth.
+
+ @param numberOfBytes Maximum packet size, in number of bytes. The default packet size for an input stream is 16kb.
+ @param delay Duration of delay each time a packet is read. By default, no delay is set.
+ */
+- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
+                                  delay:(NSTimeInterval)delay;
+
+@end
+
+#pragma mark -
+
+/**
+ `AFJSONRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSJSONSerialization`, setting the `Content-Type` of the encoded request to `application/json`.
+ */
+@interface AFJSONRequestSerializer : AFHTTPRequestSerializer
+
+/**
+ Options for writing the request JSON data from Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONWritingOptions". `0` by default.
+ */
+@property (nonatomic, assign) NSJSONWritingOptions writingOptions;
+
+/**
+ Creates and returns a JSON serializer with specified reading and writing options.
+
+ @param writingOptions The specified JSON writing options.
+ */
++ (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions;
+
+@end
+
+#pragma mark -
+
+/**
+ `AFPropertyListRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSPropertyListSerializer`, setting the `Content-Type` of the encoded request to `application/x-plist`.
+ */
+@interface AFPropertyListRequestSerializer : AFHTTPRequestSerializer
+
+/**
+ The property list format. Possible values are described in "NSPropertyListFormat".
+ */
+@property (nonatomic, assign) NSPropertyListFormat format;
+
+/**
+ @warning The `writeOptions` property is currently unused.
+ */
+@property (nonatomic, assign) NSPropertyListWriteOptions writeOptions;
+
+/**
+ Creates and returns a property list serializer with a specified format, read options, and write options.
+
+ @param format The property list format.
+ @param writeOptions The property list write options.
+
+ @warning The `writeOptions` property is currently unused.
+ */
++ (instancetype)serializerWithFormat:(NSPropertyListFormat)format
+                        writeOptions:(NSPropertyListWriteOptions)writeOptions;
+
+@end
+
+#pragma mark -
+
+///----------------
+/// @name Constants
+///----------------
+
+/**
+ ## Error Domains
+
+ The following error domain is predefined.
+
+ - `NSString * const AFURLRequestSerializationErrorDomain`
+
+ ### Constants
+
+ `AFURLRequestSerializationErrorDomain`
+ AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`.
+ */
+FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain;
+
+/**
+ ## User info dictionary keys
+
+ These keys may exist in the user info dictionary, in addition to those defined for NSError.
+
+ - `NSString * const AFNetworkingOperationFailingURLRequestErrorKey`
+
+ ### Constants
+
+ `AFNetworkingOperationFailingURLRequestErrorKey`
+ The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey;
+
+/**
+ ## Throttling Bandwidth for HTTP Request Input Streams
+
+ @see -throttleBandwidthWithPacketSize:delay:
+
+ ### Constants
+
+ `kAFUploadStream3GSuggestedPacketSize`
+ Maximum packet size, in number of bytes. Equal to 16kb.
+
+ `kAFUploadStream3GSuggestedDelay`
+ Duration of delay each time a packet is read. Equal to 0.2 seconds.
+ */
+FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize;
+FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay;
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.m
new file mode 100644
index 0000000..a47e2e6
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLRequestSerialization.m
@@ -0,0 +1,1355 @@
+// AFURLRequestSerialization.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFURLRequestSerialization.h"
+
+#if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV
+#import <MobileCoreServices/MobileCoreServices.h>
+#else
+#import <CoreServices/CoreServices.h>
+#endif
+
+NSString * const AFURLRequestSerializationErrorDomain = @"com.alamofire.error.serialization.request";
+NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"com.alamofire.serialization.request.error.response";
+
+typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, id parameters, NSError *__autoreleasing *error);
+
+/**
+ Returns a percent-escaped string following RFC 3986 for a query string key or value.
+ RFC 3986 states that the following characters are "reserved" characters.
+    - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
+    - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
+
+ In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
+ query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
+ should be percent-escaped in the query string.
+    - parameter string: The string to be percent-escaped.
+    - returns: The percent-escaped string.
+ */
+NSString * AFPercentEscapedStringFromString(NSString *string) {
+    static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
+    static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
+
+    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
+    [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];
+
+	// FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028
+    // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
+
+    static NSUInteger const batchSize = 50;
+
+    NSUInteger index = 0;
+    NSMutableString *escaped = @"".mutableCopy;
+
+    while (index < string.length) {
+        NSUInteger length = MIN(string.length - index, batchSize);
+        NSRange range = NSMakeRange(index, length);
+
+        // To avoid breaking up character sequences such as 👴🏻👮🏽
+        range = [string rangeOfComposedCharacterSequencesForRange:range];
+
+        NSString *substring = [string substringWithRange:range];
+        NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
+        [escaped appendString:encoded];
+
+        index += range.length;
+    }
+
+	return escaped;
+}
+
+#pragma mark -
+
+@interface AFQueryStringPair : NSObject
+@property (readwrite, nonatomic, strong) id field;
+@property (readwrite, nonatomic, strong) id value;
+
+- (instancetype)initWithField:(id)field value:(id)value;
+
+- (NSString *)URLEncodedStringValue;
+@end
+
+@implementation AFQueryStringPair
+
+- (instancetype)initWithField:(id)field value:(id)value {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.field = field;
+    self.value = value;
+
+    return self;
+}
+
+- (NSString *)URLEncodedStringValue {
+    if (!self.value || [self.value isEqual:[NSNull null]]) {
+        return AFPercentEscapedStringFromString([self.field description]);
+    } else {
+        return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])];
+    }
+}
+
+@end
+
+#pragma mark -
+
+FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
+FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value);
+
+NSString * AFQueryStringFromParameters(NSDictionary *parameters) {
+    NSMutableArray *mutablePairs = [NSMutableArray array];
+    for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
+        [mutablePairs addObject:[pair URLEncodedStringValue]];
+    }
+
+    return [mutablePairs componentsJoinedByString:@"&"];
+}
+
+NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
+    return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
+}
+
+NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
+    NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
+
+    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
+
+    if ([value isKindOfClass:[NSDictionary class]]) {
+        NSDictionary *dictionary = value;
+        // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
+        for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
+            id nestedValue = dictionary[nestedKey];
+            if (nestedValue) {
+                [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
+            }
+        }
+    } else if ([value isKindOfClass:[NSArray class]]) {
+        NSArray *array = value;
+        for (id nestedValue in array) {
+            [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
+        }
+    } else if ([value isKindOfClass:[NSSet class]]) {
+        NSSet *set = value;
+        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
+            [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
+        }
+    } else {
+        [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
+    }
+
+    return mutableQueryStringComponents;
+}
+
+#pragma mark -
+
+@interface AFStreamingMultipartFormData : NSObject <AFMultipartFormData>
+- (instancetype)initWithURLRequest:(NSMutableURLRequest *)urlRequest
+                    stringEncoding:(NSStringEncoding)encoding;
+
+- (NSMutableURLRequest *)requestByFinalizingMultipartFormData;
+@end
+
+#pragma mark -
+
+static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
+    static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))];
+    });
+
+    return _AFHTTPRequestSerializerObservedKeyPaths;
+}
+
+static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerObserverContext;
+
+@interface AFHTTPRequestSerializer ()
+@property (readwrite, nonatomic, strong) NSMutableSet *mutableObservedChangedKeyPaths;
+@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders;
+@property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle;
+@property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization;
+@end
+
+@implementation AFHTTPRequestSerializer
+
++ (instancetype)serializer {
+    return [[self alloc] init];
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.stringEncoding = NSUTF8StringEncoding;
+
+    self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];
+
+    // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
+    NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
+    [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        float q = 1.0f - (idx * 0.1f);
+        [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
+        *stop = q <= 0.5f;
+    }];
+    [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];
+
+    NSString *userAgent = nil;
+#if TARGET_OS_IOS
+    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
+    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
+#elif TARGET_OS_WATCH
+    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
+    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
+#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+    userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
+#endif
+    if (userAgent) {
+        if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
+            NSMutableString *mutableUserAgent = [userAgent mutableCopy];
+            if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
+                userAgent = mutableUserAgent;
+            }
+        }
+        [self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
+    }
+
+    // HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
+    self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];
+
+    self.mutableObservedChangedKeyPaths = [NSMutableSet set];
+    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
+        if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
+            [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
+        }
+    }
+
+    return self;
+}
+
+- (void)dealloc {
+    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
+        if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
+            [self removeObserver:self forKeyPath:keyPath context:AFHTTPRequestSerializerObserverContext];
+        }
+    }
+}
+
+#pragma mark -
+
+// Workarounds for crashing behavior using Key-Value Observing with XCTest
+// See https://github.com/AFNetworking/AFNetworking/issues/2523
+
+- (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
+    _allowsCellularAccess = allowsCellularAccess;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
+}
+
+- (void)setCachePolicy:(NSURLRequestCachePolicy)cachePolicy {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))];
+    _cachePolicy = cachePolicy;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))];
+}
+
+- (void)setHTTPShouldHandleCookies:(BOOL)HTTPShouldHandleCookies {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))];
+    _HTTPShouldHandleCookies = HTTPShouldHandleCookies;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))];
+}
+
+- (void)setHTTPShouldUsePipelining:(BOOL)HTTPShouldUsePipelining {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))];
+    _HTTPShouldUsePipelining = HTTPShouldUsePipelining;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))];
+}
+
+- (void)setNetworkServiceType:(NSURLRequestNetworkServiceType)networkServiceType {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))];
+    _networkServiceType = networkServiceType;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))];
+}
+
+- (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval {
+    [self willChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))];
+    _timeoutInterval = timeoutInterval;
+    [self didChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))];
+}
+
+#pragma mark -
+
+- (NSDictionary *)HTTPRequestHeaders {
+    return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
+}
+
+- (void)setValue:(NSString *)value
+forHTTPHeaderField:(NSString *)field
+{
+	[self.mutableHTTPRequestHeaders setValue:value forKey:field];
+}
+
+- (NSString *)valueForHTTPHeaderField:(NSString *)field {
+    return [self.mutableHTTPRequestHeaders valueForKey:field];
+}
+
+- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
+                                       password:(NSString *)password
+{
+    NSData *basicAuthCredentials = [[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding];
+    NSString *base64AuthCredentials = [basicAuthCredentials base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0];
+    [self setValue:[NSString stringWithFormat:@"Basic %@", base64AuthCredentials] forHTTPHeaderField:@"Authorization"];
+}
+
+- (void)clearAuthorizationHeader {
+	[self.mutableHTTPRequestHeaders removeObjectForKey:@"Authorization"];
+}
+
+#pragma mark -
+
+- (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style {
+    self.queryStringSerializationStyle = style;
+    self.queryStringSerialization = nil;
+}
+
+- (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, id, NSError *__autoreleasing *))block {
+    self.queryStringSerialization = block;
+}
+
+#pragma mark -
+
+- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
+                                 URLString:(NSString *)URLString
+                                parameters:(id)parameters
+                                     error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(method);
+    NSParameterAssert(URLString);
+
+    NSURL *url = [NSURL URLWithString:URLString];
+
+    NSParameterAssert(url);
+
+    NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
+    mutableRequest.HTTPMethod = method;
+
+    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
+        if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
+            [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
+        }
+    }
+
+    mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
+
+	return mutableRequest;
+}
+
+- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
+                                              URLString:(NSString *)URLString
+                                             parameters:(NSDictionary *)parameters
+                              constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
+                                                  error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(method);
+    NSParameterAssert(![method isEqualToString:@"GET"] && ![method isEqualToString:@"HEAD"]);
+
+    NSMutableURLRequest *mutableRequest = [self requestWithMethod:method URLString:URLString parameters:nil error:error];
+
+    __block AFStreamingMultipartFormData *formData = [[AFStreamingMultipartFormData alloc] initWithURLRequest:mutableRequest stringEncoding:NSUTF8StringEncoding];
+
+    if (parameters) {
+        for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
+            NSData *data = nil;
+            if ([pair.value isKindOfClass:[NSData class]]) {
+                data = pair.value;
+            } else if ([pair.value isEqual:[NSNull null]]) {
+                data = [NSData data];
+            } else {
+                data = [[pair.value description] dataUsingEncoding:self.stringEncoding];
+            }
+
+            if (data) {
+                [formData appendPartWithFormData:data name:[pair.field description]];
+            }
+        }
+    }
+
+    if (block) {
+        block(formData);
+    }
+
+    return [formData requestByFinalizingMultipartFormData];
+}
+
+- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
+                             writingStreamContentsToFile:(NSURL *)fileURL
+                                       completionHandler:(void (^)(NSError *error))handler
+{
+    NSParameterAssert(request.HTTPBodyStream);
+    NSParameterAssert([fileURL isFileURL]);
+
+    NSInputStream *inputStream = request.HTTPBodyStream;
+    NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:fileURL append:NO];
+    __block NSError *error = nil;
+
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+        [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+
+        [inputStream open];
+        [outputStream open];
+
+        while ([inputStream hasBytesAvailable] && [outputStream hasSpaceAvailable]) {
+            uint8_t buffer[1024];
+
+            NSInteger bytesRead = [inputStream read:buffer maxLength:1024];
+            if (inputStream.streamError || bytesRead < 0) {
+                error = inputStream.streamError;
+                break;
+            }
+
+            NSInteger bytesWritten = [outputStream write:buffer maxLength:(NSUInteger)bytesRead];
+            if (outputStream.streamError || bytesWritten < 0) {
+                error = outputStream.streamError;
+                break;
+            }
+
+            if (bytesRead == 0 && bytesWritten == 0) {
+                break;
+            }
+        }
+
+        [outputStream close];
+        [inputStream close];
+
+        if (handler) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                handler(error);
+            });
+        }
+    });
+
+    NSMutableURLRequest *mutableRequest = [request mutableCopy];
+    mutableRequest.HTTPBodyStream = nil;
+
+    return mutableRequest;
+}
+
+#pragma mark - AFURLRequestSerialization
+
+- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
+                               withParameters:(id)parameters
+                                        error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(request);
+
+    NSMutableURLRequest *mutableRequest = [request mutableCopy];
+
+    [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
+        if (![request valueForHTTPHeaderField:field]) {
+            [mutableRequest setValue:value forHTTPHeaderField:field];
+        }
+    }];
+
+    NSString *query = nil;
+    if (parameters) {
+        if (self.queryStringSerialization) {
+            NSError *serializationError;
+            query = self.queryStringSerialization(request, parameters, &serializationError);
+
+            if (serializationError) {
+                if (error) {
+                    *error = serializationError;
+                }
+
+                return nil;
+            }
+        } else {
+            switch (self.queryStringSerializationStyle) {
+                case AFHTTPRequestQueryStringDefaultStyle:
+                    query = AFQueryStringFromParameters(parameters);
+                    break;
+            }
+        }
+    }
+
+    if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
+        if (query && query.length > 0) {
+            mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
+        }
+    } else {
+        // #2864: an empty string is a valid x-www-form-urlencoded payload
+        if (!query) {
+            query = @"";
+        }
+        if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
+            [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
+        }
+        [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
+    }
+
+    return mutableRequest;
+}
+
+#pragma mark - NSKeyValueObserving
+
++ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
+    if ([AFHTTPRequestSerializerObservedKeyPaths() containsObject:key]) {
+        return NO;
+    }
+
+    return [super automaticallyNotifiesObserversForKey:key];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(__unused id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context
+{
+    if (context == AFHTTPRequestSerializerObserverContext) {
+        if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
+            [self.mutableObservedChangedKeyPaths removeObject:keyPath];
+        } else {
+            [self.mutableObservedChangedKeyPaths addObject:keyPath];
+        }
+    }
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+    return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [self init];
+    if (!self) {
+        return nil;
+    }
+
+    self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy];
+    self.queryStringSerializationStyle = (AFHTTPRequestQueryStringSerializationStyle)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [coder encodeObject:self.mutableHTTPRequestHeaders forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))];
+    [coder encodeInteger:self.queryStringSerializationStyle forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone];
+    serializer.queryStringSerializationStyle = self.queryStringSerializationStyle;
+    serializer.queryStringSerialization = self.queryStringSerialization;
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+static NSString * AFCreateMultipartFormBoundary() {
+    return [NSString stringWithFormat:@"Boundary+%08X%08X", arc4random(), arc4random()];
+}
+
+static NSString * const kAFMultipartFormCRLF = @"\r\n";
+
+static inline NSString * AFMultipartFormInitialBoundary(NSString *boundary) {
+    return [NSString stringWithFormat:@"--%@%@", boundary, kAFMultipartFormCRLF];
+}
+
+static inline NSString * AFMultipartFormEncapsulationBoundary(NSString *boundary) {
+    return [NSString stringWithFormat:@"%@--%@%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF];
+}
+
+static inline NSString * AFMultipartFormFinalBoundary(NSString *boundary) {
+    return [NSString stringWithFormat:@"%@--%@--%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF];
+}
+
+static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
+    NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
+    NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
+    if (!contentType) {
+        return @"application/octet-stream";
+    } else {
+        return contentType;
+    }
+}
+
+NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16;
+NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
+
+@interface AFHTTPBodyPart : NSObject
+@property (nonatomic, assign) NSStringEncoding stringEncoding;
+@property (nonatomic, strong) NSDictionary *headers;
+@property (nonatomic, copy) NSString *boundary;
+@property (nonatomic, strong) id body;
+@property (nonatomic, assign) unsigned long long bodyContentLength;
+@property (nonatomic, strong) NSInputStream *inputStream;
+
+@property (nonatomic, assign) BOOL hasInitialBoundary;
+@property (nonatomic, assign) BOOL hasFinalBoundary;
+
+@property (readonly, nonatomic, assign, getter = hasBytesAvailable) BOOL bytesAvailable;
+@property (readonly, nonatomic, assign) unsigned long long contentLength;
+
+- (NSInteger)read:(uint8_t *)buffer
+        maxLength:(NSUInteger)length;
+@end
+
+@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
+@property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
+@property (nonatomic, assign) NSTimeInterval delay;
+@property (nonatomic, strong) NSInputStream *inputStream;
+@property (readonly, nonatomic, assign) unsigned long long contentLength;
+@property (readonly, nonatomic, assign, getter = isEmpty) BOOL empty;
+
+- (instancetype)initWithStringEncoding:(NSStringEncoding)encoding;
+- (void)setInitialAndFinalBoundaries;
+- (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart;
+@end
+
+#pragma mark -
+
+@interface AFStreamingMultipartFormData ()
+@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
+@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
+@property (readwrite, nonatomic, copy) NSString *boundary;
+@property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream;
+@end
+
+@implementation AFStreamingMultipartFormData
+
+- (instancetype)initWithURLRequest:(NSMutableURLRequest *)urlRequest
+                    stringEncoding:(NSStringEncoding)encoding
+{
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.request = urlRequest;
+    self.stringEncoding = encoding;
+    self.boundary = AFCreateMultipartFormBoundary();
+    self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
+
+    return self;
+}
+
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
+                         name:(NSString *)name
+                        error:(NSError * __autoreleasing *)error
+{
+    NSParameterAssert(fileURL);
+    NSParameterAssert(name);
+
+    NSString *fileName = [fileURL lastPathComponent];
+    NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]);
+
+    return [self appendPartWithFileURL:fileURL name:name fileName:fileName mimeType:mimeType error:error];
+}
+
+- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
+                         name:(NSString *)name
+                     fileName:(NSString *)fileName
+                     mimeType:(NSString *)mimeType
+                        error:(NSError * __autoreleasing *)error
+{
+    NSParameterAssert(fileURL);
+    NSParameterAssert(name);
+    NSParameterAssert(fileName);
+    NSParameterAssert(mimeType);
+
+    if (![fileURL isFileURL]) {
+        NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil)};
+        if (error) {
+            *error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
+        }
+
+        return NO;
+    } else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
+        NSDictionary *userInfo = @{NSLocalizedFailureReasonErrorKey: NSLocalizedStringFromTable(@"File URL not reachable.", @"AFNetworking", nil)};
+        if (error) {
+            *error = [[NSError alloc] initWithDomain:AFURLRequestSerializationErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
+        }
+
+        return NO;
+    }
+
+    NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:error];
+    if (!fileAttributes) {
+        return NO;
+    }
+
+    NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
+    [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
+    [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
+
+    AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
+    bodyPart.stringEncoding = self.stringEncoding;
+    bodyPart.headers = mutableHeaders;
+    bodyPart.boundary = self.boundary;
+    bodyPart.body = fileURL;
+    bodyPart.bodyContentLength = [fileAttributes[NSFileSize] unsignedLongLongValue];
+    [self.bodyStream appendHTTPBodyPart:bodyPart];
+
+    return YES;
+}
+
+- (void)appendPartWithInputStream:(NSInputStream *)inputStream
+                             name:(NSString *)name
+                         fileName:(NSString *)fileName
+                           length:(int64_t)length
+                         mimeType:(NSString *)mimeType
+{
+    NSParameterAssert(name);
+    NSParameterAssert(fileName);
+    NSParameterAssert(mimeType);
+
+    NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
+    [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
+    [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
+
+    AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
+    bodyPart.stringEncoding = self.stringEncoding;
+    bodyPart.headers = mutableHeaders;
+    bodyPart.boundary = self.boundary;
+    bodyPart.body = inputStream;
+
+    bodyPart.bodyContentLength = (unsigned long long)length;
+
+    [self.bodyStream appendHTTPBodyPart:bodyPart];
+}
+
+- (void)appendPartWithFileData:(NSData *)data
+                          name:(NSString *)name
+                      fileName:(NSString *)fileName
+                      mimeType:(NSString *)mimeType
+{
+    NSParameterAssert(name);
+    NSParameterAssert(fileName);
+    NSParameterAssert(mimeType);
+
+    NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
+    [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
+    [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
+
+    [self appendPartWithHeaders:mutableHeaders body:data];
+}
+
+- (void)appendPartWithFormData:(NSData *)data
+                          name:(NSString *)name
+{
+    NSParameterAssert(name);
+
+    NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
+    [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
+
+    [self appendPartWithHeaders:mutableHeaders body:data];
+}
+
+- (void)appendPartWithHeaders:(NSDictionary *)headers
+                         body:(NSData *)body
+{
+    NSParameterAssert(body);
+
+    AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
+    bodyPart.stringEncoding = self.stringEncoding;
+    bodyPart.headers = headers;
+    bodyPart.boundary = self.boundary;
+    bodyPart.bodyContentLength = [body length];
+    bodyPart.body = body;
+
+    [self.bodyStream appendHTTPBodyPart:bodyPart];
+}
+
+- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
+                                  delay:(NSTimeInterval)delay
+{
+    self.bodyStream.numberOfBytesInPacket = numberOfBytes;
+    self.bodyStream.delay = delay;
+}
+
+- (NSMutableURLRequest *)requestByFinalizingMultipartFormData {
+    if ([self.bodyStream isEmpty]) {
+        return self.request;
+    }
+
+    // Reset the initial and final boundaries to ensure correct Content-Length
+    [self.bodyStream setInitialAndFinalBoundaries];
+    [self.request setHTTPBodyStream:self.bodyStream];
+
+    [self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", self.boundary] forHTTPHeaderField:@"Content-Type"];
+    [self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
+
+    return self.request;
+}
+
+@end
+
+#pragma mark -
+
+@interface NSStream ()
+@property (readwrite) NSStreamStatus streamStatus;
+@property (readwrite, copy) NSError *streamError;
+@end
+
+@interface AFMultipartBodyStream () <NSCopying>
+@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
+@property (readwrite, nonatomic, strong) NSMutableArray *HTTPBodyParts;
+@property (readwrite, nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
+@property (readwrite, nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
+@property (readwrite, nonatomic, strong) NSOutputStream *outputStream;
+@property (readwrite, nonatomic, strong) NSMutableData *buffer;
+@end
+
+@implementation AFMultipartBodyStream
+#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1100)
+@synthesize delegate;
+#endif
+@synthesize streamStatus;
+@synthesize streamError;
+
+- (instancetype)initWithStringEncoding:(NSStringEncoding)encoding {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.stringEncoding = encoding;
+    self.HTTPBodyParts = [NSMutableArray array];
+    self.numberOfBytesInPacket = NSIntegerMax;
+
+    return self;
+}
+
+- (void)setInitialAndFinalBoundaries {
+    if ([self.HTTPBodyParts count] > 0) {
+        for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
+            bodyPart.hasInitialBoundary = NO;
+            bodyPart.hasFinalBoundary = NO;
+        }
+
+        [[self.HTTPBodyParts firstObject] setHasInitialBoundary:YES];
+        [[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES];
+    }
+}
+
+- (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart {
+    [self.HTTPBodyParts addObject:bodyPart];
+}
+
+- (BOOL)isEmpty {
+    return [self.HTTPBodyParts count] == 0;
+}
+
+#pragma mark - NSInputStream
+
+- (NSInteger)read:(uint8_t *)buffer
+        maxLength:(NSUInteger)length
+{
+    if ([self streamStatus] == NSStreamStatusClosed) {
+        return 0;
+    }
+
+    NSInteger totalNumberOfBytesRead = 0;
+
+    while ((NSUInteger)totalNumberOfBytesRead < MIN(length, self.numberOfBytesInPacket)) {
+        if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
+            if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
+                break;
+            }
+        } else {
+            NSUInteger maxLength = MIN(length, self.numberOfBytesInPacket) - (NSUInteger)totalNumberOfBytesRead;
+            NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:&buffer[totalNumberOfBytesRead] maxLength:maxLength];
+            if (numberOfBytesRead == -1) {
+                self.streamError = self.currentHTTPBodyPart.inputStream.streamError;
+                break;
+            } else {
+                totalNumberOfBytesRead += numberOfBytesRead;
+
+                if (self.delay > 0.0f) {
+                    [NSThread sleepForTimeInterval:self.delay];
+                }
+            }
+        }
+    }
+
+    return totalNumberOfBytesRead;
+}
+
+- (BOOL)getBuffer:(__unused uint8_t **)buffer
+           length:(__unused NSUInteger *)len
+{
+    return NO;
+}
+
+- (BOOL)hasBytesAvailable {
+    return [self streamStatus] == NSStreamStatusOpen;
+}
+
+#pragma mark - NSStream
+
+- (void)open {
+    if (self.streamStatus == NSStreamStatusOpen) {
+        return;
+    }
+
+    self.streamStatus = NSStreamStatusOpen;
+
+    [self setInitialAndFinalBoundaries];
+    self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
+}
+
+- (void)close {
+    self.streamStatus = NSStreamStatusClosed;
+}
+
+- (id)propertyForKey:(__unused NSString *)key {
+    return nil;
+}
+
+- (BOOL)setProperty:(__unused id)property
+             forKey:(__unused NSString *)key
+{
+    return NO;
+}
+
+- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
+                  forMode:(__unused NSString *)mode
+{}
+
+- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
+                  forMode:(__unused NSString *)mode
+{}
+
+- (unsigned long long)contentLength {
+    unsigned long long length = 0;
+    for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
+        length += [bodyPart contentLength];
+    }
+
+    return length;
+}
+
+#pragma mark - Undocumented CFReadStream Bridged Methods
+
+- (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
+                     forMode:(__unused CFStringRef)aMode
+{}
+
+- (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
+                         forMode:(__unused CFStringRef)aMode
+{}
+
+- (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
+                 callback:(__unused CFReadStreamClientCallBack)inCallback
+                  context:(__unused CFStreamClientContext *)inContext {
+    return NO;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
+
+    for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
+        [bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
+    }
+
+    [bodyStreamCopy setInitialAndFinalBoundaries];
+
+    return bodyStreamCopy;
+}
+
+@end
+
+#pragma mark -
+
+typedef enum {
+    AFEncapsulationBoundaryPhase = 1,
+    AFHeaderPhase                = 2,
+    AFBodyPhase                  = 3,
+    AFFinalBoundaryPhase         = 4,
+} AFHTTPBodyPartReadPhase;
+
+@interface AFHTTPBodyPart () <NSCopying> {
+    AFHTTPBodyPartReadPhase _phase;
+    NSInputStream *_inputStream;
+    unsigned long long _phaseReadOffset;
+}
+
+- (BOOL)transitionToNextPhase;
+- (NSInteger)readData:(NSData *)data
+           intoBuffer:(uint8_t *)buffer
+            maxLength:(NSUInteger)length;
+@end
+
+@implementation AFHTTPBodyPart
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    [self transitionToNextPhase];
+
+    return self;
+}
+
+- (void)dealloc {
+    if (_inputStream) {
+        [_inputStream close];
+        _inputStream = nil;
+    }
+}
+
+- (NSInputStream *)inputStream {
+    if (!_inputStream) {
+        if ([self.body isKindOfClass:[NSData class]]) {
+            _inputStream = [NSInputStream inputStreamWithData:self.body];
+        } else if ([self.body isKindOfClass:[NSURL class]]) {
+            _inputStream = [NSInputStream inputStreamWithURL:self.body];
+        } else if ([self.body isKindOfClass:[NSInputStream class]]) {
+            _inputStream = self.body;
+        } else {
+            _inputStream = [NSInputStream inputStreamWithData:[NSData data]];
+        }
+    }
+
+    return _inputStream;
+}
+
+- (NSString *)stringForHeaders {
+    NSMutableString *headerString = [NSMutableString string];
+    for (NSString *field in [self.headers allKeys]) {
+        [headerString appendString:[NSString stringWithFormat:@"%@: %@%@", field, [self.headers valueForKey:field], kAFMultipartFormCRLF]];
+    }
+    [headerString appendString:kAFMultipartFormCRLF];
+
+    return [NSString stringWithString:headerString];
+}
+
+- (unsigned long long)contentLength {
+    unsigned long long length = 0;
+
+    NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding];
+    length += [encapsulationBoundaryData length];
+
+    NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
+    length += [headersData length];
+
+    length += _bodyContentLength;
+
+    NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]);
+    length += [closingBoundaryData length];
+
+    return length;
+}
+
+- (BOOL)hasBytesAvailable {
+    // Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the available buffer
+    if (_phase == AFFinalBoundaryPhase) {
+        return YES;
+    }
+
+    switch (self.inputStream.streamStatus) {
+        case NSStreamStatusNotOpen:
+        case NSStreamStatusOpening:
+        case NSStreamStatusOpen:
+        case NSStreamStatusReading:
+        case NSStreamStatusWriting:
+            return YES;
+        case NSStreamStatusAtEnd:
+        case NSStreamStatusClosed:
+        case NSStreamStatusError:
+        default:
+            return NO;
+    }
+}
+
+- (NSInteger)read:(uint8_t *)buffer
+        maxLength:(NSUInteger)length
+{
+    NSInteger totalNumberOfBytesRead = 0;
+
+    if (_phase == AFEncapsulationBoundaryPhase) {
+        NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding];
+        totalNumberOfBytesRead += [self readData:encapsulationBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
+    }
+
+    if (_phase == AFHeaderPhase) {
+        NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
+        totalNumberOfBytesRead += [self readData:headersData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
+    }
+
+    if (_phase == AFBodyPhase) {
+        NSInteger numberOfBytesRead = 0;
+
+        numberOfBytesRead = [self.inputStream read:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
+        if (numberOfBytesRead == -1) {
+            return -1;
+        } else {
+            totalNumberOfBytesRead += numberOfBytesRead;
+
+            if ([self.inputStream streamStatus] >= NSStreamStatusAtEnd) {
+                [self transitionToNextPhase];
+            }
+        }
+    }
+
+    if (_phase == AFFinalBoundaryPhase) {
+        NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]);
+        totalNumberOfBytesRead += [self readData:closingBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
+    }
+
+    return totalNumberOfBytesRead;
+}
+
+- (NSInteger)readData:(NSData *)data
+           intoBuffer:(uint8_t *)buffer
+            maxLength:(NSUInteger)length
+{
+    NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length));
+    [data getBytes:buffer range:range];
+
+    _phaseReadOffset += range.length;
+
+    if (((NSUInteger)_phaseReadOffset) >= [data length]) {
+        [self transitionToNextPhase];
+    }
+
+    return (NSInteger)range.length;
+}
+
+- (BOOL)transitionToNextPhase {
+    if (![[NSThread currentThread] isMainThread]) {
+        dispatch_sync(dispatch_get_main_queue(), ^{
+            [self transitionToNextPhase];
+        });
+        return YES;
+    }
+
+    switch (_phase) {
+        case AFEncapsulationBoundaryPhase:
+            _phase = AFHeaderPhase;
+            break;
+        case AFHeaderPhase:
+            [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
+            [self.inputStream open];
+            _phase = AFBodyPhase;
+            break;
+        case AFBodyPhase:
+            [self.inputStream close];
+            _phase = AFFinalBoundaryPhase;
+            break;
+        case AFFinalBoundaryPhase:
+        default:
+            _phase = AFEncapsulationBoundaryPhase;
+            break;
+    }
+    _phaseReadOffset = 0;
+
+    return YES;
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFHTTPBodyPart *bodyPart = [[[self class] allocWithZone:zone] init];
+
+    bodyPart.stringEncoding = self.stringEncoding;
+    bodyPart.headers = self.headers;
+    bodyPart.bodyContentLength = self.bodyContentLength;
+    bodyPart.body = self.body;
+    bodyPart.boundary = self.boundary;
+
+    return bodyPart;
+}
+
+@end
+
+#pragma mark -
+
+@implementation AFJSONRequestSerializer
+
++ (instancetype)serializer {
+    return [self serializerWithWritingOptions:(NSJSONWritingOptions)0];
+}
+
++ (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions
+{
+    AFJSONRequestSerializer *serializer = [[self alloc] init];
+    serializer.writingOptions = writingOptions;
+
+    return serializer;
+}
+
+#pragma mark - AFURLRequestSerialization
+
+- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
+                               withParameters:(id)parameters
+                                        error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(request);
+
+    if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
+        return [super requestBySerializingRequest:request withParameters:parameters error:error];
+    }
+
+    NSMutableURLRequest *mutableRequest = [request mutableCopy];
+
+    [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
+        if (![request valueForHTTPHeaderField:field]) {
+            [mutableRequest setValue:value forHTTPHeaderField:field];
+        }
+    }];
+
+    if (parameters) {
+        if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
+            [mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
+        }
+
+        [mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
+    }
+
+    return mutableRequest;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.writingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writingOptions))] unsignedIntegerValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeInteger:self.writingOptions forKey:NSStringFromSelector(@selector(writingOptions))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFJSONRequestSerializer *serializer = [super copyWithZone:zone];
+    serializer.writingOptions = self.writingOptions;
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+@implementation AFPropertyListRequestSerializer
+
++ (instancetype)serializer {
+    return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 writeOptions:0];
+}
+
++ (instancetype)serializerWithFormat:(NSPropertyListFormat)format
+                        writeOptions:(NSPropertyListWriteOptions)writeOptions
+{
+    AFPropertyListRequestSerializer *serializer = [[self alloc] init];
+    serializer.format = format;
+    serializer.writeOptions = writeOptions;
+
+    return serializer;
+}
+
+#pragma mark - AFURLRequestSerializer
+
+- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
+                               withParameters:(id)parameters
+                                        error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(request);
+
+    if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
+        return [super requestBySerializingRequest:request withParameters:parameters error:error];
+    }
+
+    NSMutableURLRequest *mutableRequest = [request mutableCopy];
+
+    [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
+        if (![request valueForHTTPHeaderField:field]) {
+            [mutableRequest setValue:value forHTTPHeaderField:field];
+        }
+    }];
+
+    if (parameters) {
+        if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
+            [mutableRequest setValue:@"application/x-plist" forHTTPHeaderField:@"Content-Type"];
+        }
+
+        [mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]];
+    }
+
+    return mutableRequest;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
+    self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeInteger:self.format forKey:NSStringFromSelector(@selector(format))];
+    [coder encodeObject:@(self.writeOptions) forKey:NSStringFromSelector(@selector(writeOptions))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFPropertyListRequestSerializer *serializer = [super copyWithZone:zone];
+    serializer.format = self.format;
+    serializer.writeOptions = self.writeOptions;
+
+    return serializer;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.h
new file mode 100644
index 0000000..10e0fef
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.h
@@ -0,0 +1,318 @@
+// AFURLResponseSerialization.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import <CoreGraphics/CoreGraphics.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data.
+
+ For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object.
+ */
+@protocol AFURLResponseSerialization <NSObject, NSSecureCoding, NSCopying>
+
+/**
+ The response object decoded from the data associated with a specified response.
+
+ @param response The response to be processed.
+ @param data The response data to be decoded.
+ @param error The error that occurred while attempting to decode the response data.
+
+ @return The object decoded from the specified response data.
+ */
+- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
+                           data:(nullable NSData *)data
+                          error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
+
+@end
+
+#pragma mark -
+
+/**
+ `AFHTTPResponseSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation.
+
+ Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPResponseSerializer` in order to ensure consistent default behavior.
+ */
+@interface AFHTTPResponseSerializer : NSObject <AFURLResponseSerialization>
+
+- (instancetype)init;
+
+/**
+ The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default.
+ */
+@property (nonatomic, assign) NSStringEncoding stringEncoding;
+
+/**
+ Creates and returns a serializer with default configuration.
+ */
++ (instancetype)serializer;
+
+///-----------------------------------------
+/// @name Configuring Response Serialization
+///-----------------------------------------
+
+/**
+ The acceptable HTTP status codes for responses. When non-`nil`, responses with status codes not contained by the set will result in an error during validation.
+
+ See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+ */
+@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes;
+
+/**
+ The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation.
+ */
+@property (nonatomic, copy, nullable) NSSet <NSString *> *acceptableContentTypes;
+
+/**
+ Validates the specified response and data.
+
+ In its base implementation, this method checks for an acceptable status code and content type. Subclasses may wish to add other domain-specific checks.
+
+ @param response The response to be validated.
+ @param data The data associated with the response.
+ @param error The error that occurred while attempting to validate the response.
+
+ @return `YES` if the response is valid, otherwise `NO`.
+ */
+- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response
+                    data:(nullable NSData *)data
+                   error:(NSError * _Nullable __autoreleasing *)error;
+
+@end
+
+#pragma mark -
+
+
+/**
+ `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses.
+
+ By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types:
+
+ - `application/json`
+ - `text/json`
+ - `text/javascript`
+ */
+@interface AFJSONResponseSerializer : AFHTTPResponseSerializer
+
+- (instancetype)init;
+
+/**
+ Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default.
+ */
+@property (nonatomic, assign) NSJSONReadingOptions readingOptions;
+
+/**
+ Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`.
+ */
+@property (nonatomic, assign) BOOL removesKeysWithNullValues;
+
+/**
+ Creates and returns a JSON serializer with specified reading and writing options.
+
+ @param readingOptions The specified JSON reading options.
+ */
++ (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions;
+
+@end
+
+#pragma mark -
+
+/**
+ `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects.
+
+ By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types:
+
+ - `application/xml`
+ - `text/xml`
+ */
+@interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer
+
+@end
+
+#pragma mark -
+
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+
+/**
+ `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects.
+
+ By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types:
+
+ - `application/xml`
+ - `text/xml`
+ */
+@interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer
+
+- (instancetype)init;
+
+/**
+ Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default.
+ */
+@property (nonatomic, assign) NSUInteger options;
+
+/**
+ Creates and returns an XML document serializer with the specified options.
+
+ @param mask The XML document options.
+ */
++ (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask;
+
+@end
+
+#endif
+
+#pragma mark -
+
+/**
+ `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects.
+
+ By default, `AFPropertyListResponseSerializer` accepts the following MIME types:
+
+ - `application/x-plist`
+ */
+@interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer
+
+- (instancetype)init;
+
+/**
+ The property list format. Possible values are described in "NSPropertyListFormat".
+ */
+@property (nonatomic, assign) NSPropertyListFormat format;
+
+/**
+ The property list reading options. Possible values are described in "NSPropertyListMutabilityOptions."
+ */
+@property (nonatomic, assign) NSPropertyListReadOptions readOptions;
+
+/**
+ Creates and returns a property list serializer with a specified format, read options, and write options.
+
+ @param format The property list format.
+ @param readOptions The property list reading options.
+ */
++ (instancetype)serializerWithFormat:(NSPropertyListFormat)format
+                         readOptions:(NSPropertyListReadOptions)readOptions;
+
+@end
+
+#pragma mark -
+
+/**
+ `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses.
+
+ By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage:
+
+ - `image/tiff`
+ - `image/jpeg`
+ - `image/gif`
+ - `image/png`
+ - `image/ico`
+ - `image/x-icon`
+ - `image/bmp`
+ - `image/x-bmp`
+ - `image/x-xbitmap`
+ - `image/x-win-bitmap`
+ */
+@interface AFImageResponseSerializer : AFHTTPResponseSerializer
+
+#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
+/**
+ The scale factor used when interpreting the image data to construct `responseImage`. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of scale of the main screen by default, which automatically scales images for retina displays, for instance.
+ */
+@property (nonatomic, assign) CGFloat imageScale;
+
+/**
+ Whether to automatically inflate response image data for compressed formats (such as PNG or JPEG). Enabling this can significantly improve drawing performance on iOS when used with `setCompletionBlockWithSuccess:failure:`, as it allows a bitmap representation to be constructed in the background rather than on the main thread. `YES` by default.
+ */
+@property (nonatomic, assign) BOOL automaticallyInflatesResponseImage;
+#endif
+
+@end
+
+#pragma mark -
+
+/**
+ `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer.
+ */
+@interface AFCompoundResponseSerializer : AFHTTPResponseSerializer
+
+/**
+ The component response serializers.
+ */
+@property (readonly, nonatomic, copy) NSArray <id<AFURLResponseSerialization>> *responseSerializers;
+
+/**
+ Creates and returns a compound serializer comprised of the specified response serializers.
+
+ @warning Each response serializer specified must be a subclass of `AFHTTPResponseSerializer`, and response to `-validateResponse:data:error:`.
+ */
++ (instancetype)compoundSerializerWithResponseSerializers:(NSArray <id<AFURLResponseSerialization>> *)responseSerializers;
+
+@end
+
+///----------------
+/// @name Constants
+///----------------
+
+/**
+ ## Error Domains
+
+ The following error domain is predefined.
+
+ - `NSString * const AFURLResponseSerializationErrorDomain`
+
+ ### Constants
+
+ `AFURLResponseSerializationErrorDomain`
+ AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`.
+ */
+FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain;
+
+/**
+ ## User info dictionary keys
+
+ These keys may exist in the user info dictionary, in addition to those defined for NSError.
+
+ - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey`
+ - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey`
+
+ ### Constants
+
+ `AFNetworkingOperationFailingURLResponseErrorKey`
+ The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`.
+
+ `AFNetworkingOperationFailingURLResponseDataErrorKey`
+ The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey;
+
+FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey;
+
+/**
+`AFNetworkingOperationFailingURLResponseBodyErrorKey`
+The corresponding value is an `NSString` containing the decoded error message.
+ */
+
+FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseBodyErrorKey;
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.m
new file mode 100755
index 0000000..f88d938
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLResponseSerialization.m
@@ -0,0 +1,806 @@
+// AFURLResponseSerialization.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFURLResponseSerialization.h"
+
+#import <TargetConditionals.h>
+
+#if TARGET_OS_IOS
+#import <UIKit/UIKit.h>
+#elif TARGET_OS_WATCH
+#import <WatchKit/WatchKit.h>
+#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+#import <Cocoa/Cocoa.h>
+#endif
+
+NSString * const AFURLResponseSerializationErrorDomain = @"com.alamofire.error.serialization.response";
+NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"com.alamofire.serialization.response.error.response";
+NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey = @"com.alamofire.serialization.response.error.data";
+NSString * const AFNetworkingOperationFailingURLResponseBodyErrorKey = @"com.alamofire.serialization.response.error.body";
+
+static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
+    if (!error) {
+        return underlyingError;
+    }
+
+    if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
+        return error;
+    }
+
+    NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
+    mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;
+
+    return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
+}
+
+static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
+    if ([error.domain isEqualToString:domain] && error.code == code) {
+        return YES;
+    } else if (error.userInfo[NSUnderlyingErrorKey]) {
+        return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
+    }
+
+    return NO;
+}
+
+static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
+    if ([JSONObject isKindOfClass:[NSArray class]]) {
+        NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
+        for (id value in (NSArray *)JSONObject) {
+            [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
+        }
+
+        return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
+    } else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
+        NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
+        for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
+            id value = (NSDictionary *)JSONObject[key];
+            if (!value || [value isEqual:[NSNull null]]) {
+                [mutableDictionary removeObjectForKey:key];
+            } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
+                mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions);
+            }
+        }
+
+        return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
+    }
+
+    return JSONObject;
+}
+
+@implementation AFHTTPResponseSerializer
+
++ (instancetype)serializer {
+    return [[self alloc] init];
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.stringEncoding = NSUTF8StringEncoding;
+
+    self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
+    self.acceptableContentTypes = nil;
+
+    return self;
+}
+
+#pragma mark -
+
+- (BOOL)validateResponse:(NSHTTPURLResponse *)response
+                    data:(NSData *)data
+                   error:(NSError * __autoreleasing *)error
+{
+    BOOL responseIsValid = YES;
+    NSError *validationError = nil;
+
+    if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
+        if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]] &&
+            !([response MIMEType] == nil && [data length] == 0)) {
+
+            if ([data length] > 0 && [response URL]) {
+                NSMutableDictionary *mutableUserInfo = [@{
+                                                          NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
+                                                          NSURLErrorFailingURLErrorKey:[response URL],
+                                                          AFNetworkingOperationFailingURLResponseErrorKey: response,
+                                                        } mutableCopy];
+                if (data) {
+                    mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
+                }
+
+                validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
+            }
+
+            responseIsValid = NO;
+        }
+
+        if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
+            NSMutableDictionary *mutableUserInfo = [@{
+                                               NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
+                                               NSURLErrorFailingURLErrorKey:[response URL],
+                                               AFNetworkingOperationFailingURLResponseErrorKey: response,
+                                       } mutableCopy];
+
+            if (data) {
+                mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
+            }
+
+            validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
+
+            responseIsValid = NO;
+        }
+    }
+
+    if (error && !responseIsValid) {
+        *error = validationError;
+    }
+
+    return responseIsValid;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    [self validateResponse:(NSHTTPURLResponse *)response data:data error:error];
+
+    return data;
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+    return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [self init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableStatusCodes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
+    self.acceptableContentTypes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [coder encodeObject:self.acceptableStatusCodes forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
+    [coder encodeObject:self.acceptableContentTypes forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFHTTPResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.acceptableStatusCodes = [self.acceptableStatusCodes copyWithZone:zone];
+    serializer.acceptableContentTypes = [self.acceptableContentTypes copyWithZone:zone];
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+@implementation AFJSONResponseSerializer
+
++ (instancetype)serializer {
+    return [self serializerWithReadingOptions:(NSJSONReadingOptions)0];
+}
+
++ (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions {
+    AFJSONResponseSerializer *serializer = [[self alloc] init];
+    serializer.readingOptions = readingOptions;
+
+    return serializer;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
+
+    return self;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+            return nil;
+        }
+    }
+
+    id responseObject = nil;
+    NSError *serializationError = nil;
+    // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
+    // See https://github.com/rails/rails/issues/1742
+    BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
+    if (data.length > 0 && !isSpace) {
+        responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
+    } else {
+        return nil;
+    }
+
+    if (self.removesKeysWithNullValues && responseObject) {
+        responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
+    }
+
+    if (error) {
+        *error = AFErrorWithUnderlyingError(serializationError, *error);
+    }
+
+    return responseObject;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.readingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readingOptions))] unsignedIntegerValue];
+    self.removesKeysWithNullValues = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))] boolValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeObject:@(self.readingOptions) forKey:NSStringFromSelector(@selector(readingOptions))];
+    [coder encodeObject:@(self.removesKeysWithNullValues) forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.readingOptions = self.readingOptions;
+    serializer.removesKeysWithNullValues = self.removesKeysWithNullValues;
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+@implementation AFXMLParserResponseSerializer
+
++ (instancetype)serializer {
+    AFXMLParserResponseSerializer *serializer = [[self alloc] init];
+
+    return serializer;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil];
+
+    return self;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSHTTPURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+            return nil;
+        }
+    }
+
+    return [[NSXMLParser alloc] initWithData:data];
+}
+
+@end
+
+#pragma mark -
+
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+
+@implementation AFXMLDocumentResponseSerializer
+
++ (instancetype)serializer {
+    return [self serializerWithXMLDocumentOptions:0];
+}
+
++ (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask {
+    AFXMLDocumentResponseSerializer *serializer = [[self alloc] init];
+    serializer.options = mask;
+
+    return serializer;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil];
+
+    return self;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+            return nil;
+        }
+    }
+
+    NSError *serializationError = nil;
+    NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:self.options error:&serializationError];
+
+    if (error) {
+        *error = AFErrorWithUnderlyingError(serializationError, *error);
+    }
+
+    return document;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.options = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(options))] unsignedIntegerValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeObject:@(self.options) forKey:NSStringFromSelector(@selector(options))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFXMLDocumentResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.options = self.options;
+
+    return serializer;
+}
+
+@end
+
+#endif
+
+#pragma mark -
+
+@implementation AFPropertyListResponseSerializer
+
++ (instancetype)serializer {
+    return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 readOptions:0];
+}
+
++ (instancetype)serializerWithFormat:(NSPropertyListFormat)format
+                         readOptions:(NSPropertyListReadOptions)readOptions
+{
+    AFPropertyListResponseSerializer *serializer = [[self alloc] init];
+    serializer.format = format;
+    serializer.readOptions = readOptions;
+
+    return serializer;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/x-plist", nil];
+
+    return self;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+            return nil;
+        }
+    }
+
+    id responseObject;
+    NSError *serializationError = nil;
+
+    if (data) {
+        responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError];
+    }
+
+    if (error) {
+        *error = AFErrorWithUnderlyingError(serializationError, *error);
+    }
+
+    return responseObject;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
+    self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeObject:@(self.format) forKey:NSStringFromSelector(@selector(format))];
+    [coder encodeObject:@(self.readOptions) forKey:NSStringFromSelector(@selector(readOptions))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFPropertyListResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.format = self.format;
+    serializer.readOptions = self.readOptions;
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+@interface UIImage (AFNetworkingSafeImageLoading)
++ (UIImage *)af_safeImageWithData:(NSData *)data;
+@end
+
+static NSLock* imageLock = nil;
+
+@implementation UIImage (AFNetworkingSafeImageLoading)
+
++ (UIImage *)af_safeImageWithData:(NSData *)data {
+    UIImage* image = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        imageLock = [[NSLock alloc] init];
+    });
+
+    [imageLock lock];
+    image = [UIImage imageWithData:data];
+    [imageLock unlock];
+    return image;
+}
+
+@end
+
+static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) {
+    UIImage *image = [UIImage af_safeImageWithData:data];
+    if (image.images) {
+        return image;
+    }
+
+    return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation];
+}
+
+static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *response, NSData *data, CGFloat scale) {
+    if (!data || [data length] == 0) {
+        return nil;
+    }
+
+    CGImageRef imageRef = NULL;
+    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
+
+    if ([response.MIMEType isEqualToString:@"image/png"]) {
+        imageRef = CGImageCreateWithPNGDataProvider(dataProvider,  NULL, true, kCGRenderingIntentDefault);
+    } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) {
+        imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault);
+
+        if (imageRef) {
+            CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef);
+            CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace);
+
+            // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so fall back to AFImageWithDataAtScale
+            if (imageColorSpaceModel == kCGColorSpaceModelCMYK) {
+                CGImageRelease(imageRef);
+                imageRef = NULL;
+            }
+        }
+    }
+
+    CGDataProviderRelease(dataProvider);
+
+    UIImage *image = AFImageWithDataAtScale(data, scale);
+    if (!imageRef) {
+        if (image.images || !image) {
+            return image;
+        }
+
+        imageRef = CGImageCreateCopy([image CGImage]);
+        if (!imageRef) {
+            return nil;
+        }
+    }
+
+    size_t width = CGImageGetWidth(imageRef);
+    size_t height = CGImageGetHeight(imageRef);
+    size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
+
+    if (width * height > 1024 * 1024 || bitsPerComponent > 8) {
+        CGImageRelease(imageRef);
+
+        return image;
+    }
+
+    // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate
+    size_t bytesPerRow = 0;
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
+    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
+
+    if (colorSpaceModel == kCGColorSpaceModelRGB) {
+        uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wassign-enum"
+        if (alpha == kCGImageAlphaNone) {
+            bitmapInfo &= ~kCGBitmapAlphaInfoMask;
+            bitmapInfo |= kCGImageAlphaNoneSkipFirst;
+        } else if (!(alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast)) {
+            bitmapInfo &= ~kCGBitmapAlphaInfoMask;
+            bitmapInfo |= kCGImageAlphaPremultipliedFirst;
+        }
+#pragma clang diagnostic pop
+    }
+
+    CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
+
+    CGColorSpaceRelease(colorSpace);
+
+    if (!context) {
+        CGImageRelease(imageRef);
+
+        return image;
+    }
+
+    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), imageRef);
+    CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context);
+
+    CGContextRelease(context);
+
+    UIImage *inflatedImage = [[UIImage alloc] initWithCGImage:inflatedImageRef scale:scale orientation:image.imageOrientation];
+
+    CGImageRelease(inflatedImageRef);
+    CGImageRelease(imageRef);
+
+    return inflatedImage;
+}
+#endif
+
+
+@implementation AFImageResponseSerializer
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil];
+
+#if TARGET_OS_IOS || TARGET_OS_TV
+    self.imageScale = [[UIScreen mainScreen] scale];
+    self.automaticallyInflatesResponseImage = YES;
+#elif TARGET_OS_WATCH
+    self.imageScale = [[WKInterfaceDevice currentDevice] screenScale];
+    self.automaticallyInflatesResponseImage = YES;
+#endif
+
+    return self;
+}
+
+#pragma mark - AFURLResponseSerializer
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+            return nil;
+        }
+    }
+
+#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
+    if (self.automaticallyInflatesResponseImage) {
+        return AFInflatedImageFromResponseWithDataAtScale((NSHTTPURLResponse *)response, data, self.imageScale);
+    } else {
+        return AFImageWithDataAtScale(data, self.imageScale);
+    }
+#else
+    // Ensure that the image is set to it's correct pixel width and height
+    NSBitmapImageRep *bitimage = [[NSBitmapImageRep alloc] initWithData:data];
+    NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize([bitimage pixelsWide], [bitimage pixelsHigh])];
+    [image addRepresentation:bitimage];
+
+    return image;
+#endif
+
+    return nil;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+#if TARGET_OS_IOS  || TARGET_OS_TV || TARGET_OS_WATCH
+    NSNumber *imageScale = [decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(imageScale))];
+#if CGFLOAT_IS_DOUBLE
+    self.imageScale = [imageScale doubleValue];
+#else
+    self.imageScale = [imageScale floatValue];
+#endif
+
+    self.automaticallyInflatesResponseImage = [decoder decodeBoolForKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))];
+#endif
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
+    [coder encodeObject:@(self.imageScale) forKey:NSStringFromSelector(@selector(imageScale))];
+    [coder encodeBool:self.automaticallyInflatesResponseImage forKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))];
+#endif
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFImageResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+
+#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
+    serializer.imageScale = self.imageScale;
+    serializer.automaticallyInflatesResponseImage = self.automaticallyInflatesResponseImage;
+#endif
+
+    return serializer;
+}
+
+@end
+
+#pragma mark -
+
+@interface AFCompoundResponseSerializer ()
+@property (readwrite, nonatomic, copy) NSArray *responseSerializers;
+@end
+
+@implementation AFCompoundResponseSerializer
+
++ (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers {
+    AFCompoundResponseSerializer *serializer = [[self alloc] init];
+    serializer.responseSerializers = responseSerializers;
+
+    return serializer;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+    for (id <AFURLResponseSerialization> serializer in self.responseSerializers) {
+        if (![serializer isKindOfClass:[AFHTTPResponseSerializer class]]) {
+            continue;
+        }
+
+        NSError *serializerError = nil;
+        id responseObject = [serializer responseObjectForResponse:response data:data error:&serializerError];
+        if (responseObject) {
+            if (error) {
+                *error = AFErrorWithUnderlyingError(serializerError, *error);
+            }
+
+            return responseObject;
+        }
+    }
+
+    return [super responseObjectForResponse:response data:data error:error];
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    self.responseSerializers = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(responseSerializers))];
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [super encodeWithCoder:coder];
+
+    [coder encodeObject:self.responseSerializers forKey:NSStringFromSelector(@selector(responseSerializers))];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    AFCompoundResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
+    serializer.responseSerializers = self.responseSerializers;
+
+    return serializer;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.h
new file mode 100644
index 0000000..89909fe
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.h
@@ -0,0 +1,500 @@
+// AFURLSessionManager.h
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+
+#import "AFURLResponseSerialization.h"
+#import "AFURLRequestSerialization.h"
+#import "AFSecurityPolicy.h"
+#if !TARGET_OS_WATCH
+#import "AFNetworkReachabilityManager.h"
+#endif
+
+/**
+ `AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to `<NSURLSessionTaskDelegate>`, `<NSURLSessionDataDelegate>`, `<NSURLSessionDownloadDelegate>`, and `<NSURLSessionDelegate>`.
+
+ ## Subclassing Notes
+
+ This is the base class for `AFHTTPSessionManager`, which adds functionality specific to making HTTP requests. If you are looking to extend `AFURLSessionManager` specifically for HTTP, consider subclassing `AFHTTPSessionManager` instead.
+
+ ## NSURLSession & NSURLSessionTask Delegate Methods
+
+ `AFURLSessionManager` implements the following delegate methods:
+
+ ### `NSURLSessionDelegate`
+
+ - `URLSession:didBecomeInvalidWithError:`
+ - `URLSession:didReceiveChallenge:completionHandler:`
+ - `URLSessionDidFinishEventsForBackgroundURLSession:`
+
+ ### `NSURLSessionTaskDelegate`
+
+ - `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:`
+ - `URLSession:task:didReceiveChallenge:completionHandler:`
+ - `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`
+ - `URLSession:task:needNewBodyStream:`
+ - `URLSession:task:didCompleteWithError:`
+
+ ### `NSURLSessionDataDelegate`
+
+ - `URLSession:dataTask:didReceiveResponse:completionHandler:`
+ - `URLSession:dataTask:didBecomeDownloadTask:`
+ - `URLSession:dataTask:didReceiveData:`
+ - `URLSession:dataTask:willCacheResponse:completionHandler:`
+
+ ### `NSURLSessionDownloadDelegate`
+
+ - `URLSession:downloadTask:didFinishDownloadingToURL:`
+ - `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`
+ - `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`
+
+ If any of these methods are overridden in a subclass, they _must_ call the `super` implementation first.
+
+ ## Network Reachability Monitoring
+
+ Network reachability status and change monitoring is available through the `reachabilityManager` property. Applications may choose to monitor network reachability conditions in order to prevent or suspend any outbound requests. See `AFNetworkReachabilityManager` for more details.
+
+ ## NSCoding Caveats
+
+ - Encoded managers do not include any block properties. Be sure to set delegate callback blocks when using `-initWithCoder:` or `NSKeyedUnarchiver`.
+
+ ## NSCopying Caveats
+
+ - `-copy` and `-copyWithZone:` return a new manager with a new `NSURLSession` created from the configuration of the original.
+ - Operation copies do not include any delegate callback blocks, as they often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ session manager when copied.
+
+ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance.
+ */
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>
+
+/**
+ The managed session.
+ */
+@property (readonly, nonatomic, strong) NSURLSession *session;
+
+/**
+ The operation queue on which delegate callbacks are run.
+ */
+@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;
+
+/**
+ Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`.
+
+ @warning `responseSerializer` must not be `nil`.
+ */
+@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
+
+///-------------------------------
+/// @name Managing Security Policy
+///-------------------------------
+
+/**
+ The security policy used by created session to evaluate server trust for secure connections. `AFURLSessionManager` uses the `defaultPolicy` unless otherwise specified.
+ */
+@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
+
+#if !TARGET_OS_WATCH
+///--------------------------------------
+/// @name Monitoring Network Reachability
+///--------------------------------------
+
+/**
+ The network reachability manager. `AFURLSessionManager` uses the `sharedManager` by default.
+ */
+@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
+#endif
+
+///----------------------------
+/// @name Getting Session Tasks
+///----------------------------
+
+/**
+ The data, upload, and download tasks currently run by the managed session.
+ */
+@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;
+
+/**
+ The data tasks currently run by the managed session.
+ */
+@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;
+
+/**
+ The upload tasks currently run by the managed session.
+ */
+@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;
+
+/**
+ The download tasks currently run by the managed session.
+ */
+@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;
+
+///-------------------------------
+/// @name Managing Callback Queues
+///-------------------------------
+
+/**
+ The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used.
+ */
+@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;
+
+/**
+ The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used.
+ */
+@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;
+
+///---------------------------------
+/// @name Working Around System Bugs
+///---------------------------------
+
+/**
+ Whether to attempt to retry creation of upload tasks for background sessions when initial call returns `nil`. `NO` by default.
+
+ @bug As of iOS 7.0, there is a bug where upload tasks created for background tasks are sometimes `nil`. As a workaround, if this property is `YES`, AFNetworking will follow Apple's recommendation to try creating the task again.
+
+ @see https://github.com/AFNetworking/AFNetworking/issues/1675
+ */
+@property (nonatomic, assign) BOOL attemptsToRecreateUploadTasksForBackgroundSessions;
+
+///---------------------
+/// @name Initialization
+///---------------------
+
+/**
+ Creates and returns a manager for a session created with the specified configuration. This is the designated initializer.
+
+ @param configuration The configuration used to create the managed session.
+
+ @return A manager for a newly-created session.
+ */
+- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
+
+/**
+ Invalidates the managed session, optionally canceling pending tasks.
+
+ @param cancelPendingTasks Whether or not to cancel pending tasks.
+ */
+- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks;
+
+///-------------------------
+/// @name Running Data Tasks
+///-------------------------
+
+/**
+ Creates an `NSURLSessionDataTask` with the specified request.
+
+ @param request The HTTP request for the request.
+ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
+ */
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler;
+
+/**
+ Creates an `NSURLSessionDataTask` with the specified request.
+
+ @param request The HTTP request for the request.
+ @param uploadProgressBlock A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param downloadProgressBlock A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
+ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
+ */
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+                               uploadProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
+                             downloadProgress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
+                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler;
+
+///---------------------------
+/// @name Running Upload Tasks
+///---------------------------
+
+/**
+ Creates an `NSURLSessionUploadTask` with the specified request for a local file.
+
+ @param request The HTTP request for the request.
+ @param fileURL A URL to the local file to be uploaded.
+ @param uploadProgressBlock A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
+
+ @see `attemptsToRecreateUploadTasksForBackgroundSessions`
+ */
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+                                         fromFile:(NSURL *)fileURL
+                                         progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
+                                completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError  * _Nullable error))completionHandler;
+
+/**
+ Creates an `NSURLSessionUploadTask` with the specified request for an HTTP body.
+
+ @param request The HTTP request for the request.
+ @param bodyData A data object containing the HTTP body to be uploaded.
+ @param uploadProgressBlock A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
+ */
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+                                         fromData:(nullable NSData *)bodyData
+                                         progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
+                                completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
+
+/**
+ Creates an `NSURLSessionUploadTask` with the specified streaming request.
+
+ @param request The HTTP request for the request.
+ @param uploadProgressBlock A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
+ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
+ */
+- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
+                                                 progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock
+                                        completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;
+
+///-----------------------------
+/// @name Running Download Tasks
+///-----------------------------
+
+/**
+ Creates an `NSURLSessionDownloadTask` with the specified request.
+
+ @param request The HTTP request for the request.
+ @param downloadProgressBlock A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
+ @param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL.
+ @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any.
+
+ @warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method.
+ */
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
+                                             progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
+                                          destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
+                                    completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;
+
+/**
+ Creates an `NSURLSessionDownloadTask` with the specified resume data.
+
+ @param resumeData The data used to resume downloading.
+ @param downloadProgressBlock A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
+ @param destination A block object to be executed in order to determine the destination of the downloaded file. This block takes two arguments, the target path & the server response, and returns the desired file URL of the resulting download. The temporary file used during the download will be automatically deleted after being moved to the returned URL.
+ @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any.
+ */
+- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
+                                                progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock
+                                             destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
+                                       completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;
+
+///---------------------------------
+/// @name Getting Progress for Tasks
+///---------------------------------
+
+/**
+ Returns the upload progress of the specified task.
+
+ @param task The session task. Must not be `nil`.
+
+ @return An `NSProgress` object reporting the upload progress of a task, or `nil` if the progress is unavailable.
+ */
+- (nullable NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task;
+
+/**
+ Returns the download progress of the specified task.
+
+ @param task The session task. Must not be `nil`.
+
+ @return An `NSProgress` object reporting the download progress of a task, or `nil` if the progress is unavailable.
+ */
+- (nullable NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task;
+
+///-----------------------------------------
+/// @name Setting Session Delegate Callbacks
+///-----------------------------------------
+
+/**
+ Sets a block to be executed when the managed session becomes invalid, as handled by the `NSURLSessionDelegate` method `URLSession:didBecomeInvalidWithError:`.
+
+ @param block A block object to be executed when the managed session becomes invalid. The block has no return value, and takes two arguments: the session, and the error related to the cause of invalidation.
+ */
+- (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block;
+
+/**
+ Sets a block to be executed when a connection level authentication challenge has occurred, as handled by the `NSURLSessionDelegate` method `URLSession:didReceiveChallenge:completionHandler:`.
+
+ @param block A block object to be executed when a connection level authentication challenge has occurred. The block returns the disposition of the authentication challenge, and takes three arguments: the session, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge.
+ */
+- (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
+
+///--------------------------------------
+/// @name Setting Task Delegate Callbacks
+///--------------------------------------
+
+/**
+ Sets a block to be executed when a task requires a new request body stream to send to the remote server, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:needNewBodyStream:`.
+
+ @param block A block object to be executed when a task requires a new request body stream.
+ */
+- (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block;
+
+/**
+ Sets a block to be executed when an HTTP request is attempting to perform a redirection to a different URL, as handled by the `NSURLSessionTaskDelegate` method `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:`.
+
+ @param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response.
+ */
+- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block;
+
+/**
+ Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`.
+
+ @param block A block object to be executed when a session task has received a request specific authentication challenge. The block returns the disposition of the authentication challenge, and takes four arguments: the session, the task, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge.
+ */
+- (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
+
+/**
+ Sets a block to be executed periodically to track upload progress, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`.
+
+ @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes five arguments: the session, the task, the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread.
+ */
+- (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block;
+
+/**
+ Sets a block to be executed as the last message related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didCompleteWithError:`.
+
+ @param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any error that occurred in the process of executing the task.
+ */
+- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * _Nullable error))block;
+
+///-------------------------------------------
+/// @name Setting Data Task Delegate Callbacks
+///-------------------------------------------
+
+/**
+ Sets a block to be executed when a data task has received a response, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveResponse:completionHandler:`.
+
+ @param block A block object to be executed when a data task has received a response. The block returns the disposition of the session response, and takes three arguments: the session, the data task, and the received response.
+ */
+- (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block;
+
+/**
+ Sets a block to be executed when a data task has become a download task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didBecomeDownloadTask:`.
+
+ @param block A block object to be executed when a data task has become a download task. The block has no return value, and takes three arguments: the session, the data task, and the download task it has become.
+ */
+- (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block;
+
+/**
+ Sets a block to be executed when a data task receives data, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveData:`.
+
+ @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the session, the data task, and the data received. This block may be called multiple times, and will execute on the session manager operation queue.
+ */
+- (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block;
+
+/**
+ Sets a block to be executed to determine the caching behavior of a data task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:willCacheResponse:completionHandler:`.
+
+ @param block A block object to be executed to determine the caching behavior of a data task. The block returns the response to cache, and takes three arguments: the session, the data task, and the proposed cached URL response.
+ */
+- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block;
+
+/**
+ Sets a block to be executed once all messages enqueued for a session have been delivered, as handled by the `NSURLSessionDataDelegate` method `URLSessionDidFinishEventsForBackgroundURLSession:`.
+
+ @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session.
+ */
+- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block;
+
+///-----------------------------------------------
+/// @name Setting Download Task Delegate Callbacks
+///-----------------------------------------------
+
+/**
+ Sets a block to be executed when a download task has completed a download, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didFinishDownloadingToURL:`.
+
+ @param block A block object to be executed when a download task has completed. The block returns the URL the download should be moved to, and takes three arguments: the session, the download task, and the temporary location of the downloaded file. If the file manager encounters an error while attempting to move the temporary file to the destination, an `AFURLSessionDownloadTaskDidFailToMoveFileNotification` will be posted, with the download task as its object, and the user info of the error.
+ */
+- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * _Nullable  (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block;
+
+/**
+ Sets a block to be executed periodically to track download progress, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`.
+
+ @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes five arguments: the session, the download task, the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the session manager operation queue.
+ */
+- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block;
+
+/**
+ Sets a block to be executed when a download task has been resumed, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`.
+
+ @param block A block object to be executed when a download task has been resumed. The block has no return value and takes four arguments: the session, the download task, the file offset of the resumed download, and the total number of bytes expected to be downloaded.
+ */
+- (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block;
+
+@end
+
+///--------------------
+/// @name Notifications
+///--------------------
+
+/**
+ Posted when a task resumes.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification;
+
+/**
+ Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification;
+
+/**
+ Posted when a task suspends its execution.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification;
+
+/**
+ Posted when a session is invalidated.
+ */
+FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification;
+
+/**
+ Posted when a session download task encountered an error when moving the temporary download file to a specified destination.
+ */
+FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification;
+
+/**
+ The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if response data exists for the task.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey;
+
+/**
+ The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if the response was serialized.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey;
+
+/**
+ The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if the task has an associated response serializer.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey;
+
+/**
+ The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if an the response data has been stored directly to disk.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey;
+
+/**
+ Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidCompleteNotification` if an error exists.
+ */
+FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey;
+
+NS_ASSUME_NONNULL_END
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.m
new file mode 100644
index 0000000..af01bda
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/AFURLSessionManager.m
@@ -0,0 +1,1239 @@
+// AFURLSessionManager.m
+// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "AFURLSessionManager.h"
+#import <objc/runtime.h>
+
+#ifndef NSFoundationVersionNumber_iOS_8_0
+#define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug 1140.11
+#else
+#define NSFoundationVersionNumber_With_Fixed_5871104061079552_bug NSFoundationVersionNumber_iOS_8_0
+#endif
+
+static dispatch_queue_t url_session_manager_creation_queue() {
+    static dispatch_queue_t af_url_session_manager_creation_queue;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL);
+    });
+
+    return af_url_session_manager_creation_queue;
+}
+
+static void url_session_manager_create_task_safely(dispatch_block_t block) {
+    if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
+        // Fix of bug
+        // Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
+        // Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
+        dispatch_sync(url_session_manager_creation_queue(), block);
+    } else {
+        block();
+    }
+}
+
+static dispatch_queue_t url_session_manager_processing_queue() {
+    static dispatch_queue_t af_url_session_manager_processing_queue;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        af_url_session_manager_processing_queue = dispatch_queue_create("com.alamofire.networking.session.manager.processing", DISPATCH_QUEUE_CONCURRENT);
+    });
+
+    return af_url_session_manager_processing_queue;
+}
+
+static dispatch_group_t url_session_manager_completion_group() {
+    static dispatch_group_t af_url_session_manager_completion_group;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        af_url_session_manager_completion_group = dispatch_group_create();
+    });
+
+    return af_url_session_manager_completion_group;
+}
+
+NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
+NSString * const AFNetworkingTaskDidCompleteNotification = @"com.alamofire.networking.task.complete";
+NSString * const AFNetworkingTaskDidSuspendNotification = @"com.alamofire.networking.task.suspend";
+NSString * const AFURLSessionDidInvalidateNotification = @"com.alamofire.networking.session.invalidate";
+NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification = @"com.alamofire.networking.session.download.file-manager-error";
+
+NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey = @"com.alamofire.networking.task.complete.serializedresponse";
+NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey = @"com.alamofire.networking.task.complete.responseserializer";
+NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata";
+NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error";
+NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath";
+
+static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";
+
+static NSUInteger const AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask = 3;
+
+typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error);
+typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
+
+typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request);
+typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
+typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session);
+
+typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
+typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
+typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error);
+
+typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response);
+typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
+typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data);
+typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse);
+
+typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location);
+typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
+typedef void (^AFURLSessionDownloadTaskDidResumeBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes);
+typedef void (^AFURLSessionTaskProgressBlock)(NSProgress *);
+
+typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id responseObject, NSError *error);
+
+
+#pragma mark -
+
+@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
+@property (nonatomic, weak) AFURLSessionManager *manager;
+@property (nonatomic, strong) NSMutableData *mutableData;
+@property (nonatomic, strong) NSProgress *uploadProgress;
+@property (nonatomic, strong) NSProgress *downloadProgress;
+@property (nonatomic, copy) NSURL *downloadFileURL;
+@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
+@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
+@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
+@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
+@end
+
+@implementation AFURLSessionManagerTaskDelegate
+
+- (instancetype)init {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    self.mutableData = [NSMutableData data];
+    self.uploadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
+    self.uploadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown;
+
+    self.downloadProgress = [[NSProgress alloc] initWithParent:nil userInfo:nil];
+    self.downloadProgress.totalUnitCount = NSURLSessionTransferSizeUnknown;
+    return self;
+}
+
+#pragma mark - NSProgress Tracking
+
+- (void)setupProgressForTask:(NSURLSessionTask *)task {
+    __weak __typeof__(task) weakTask = task;
+
+    self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
+    self.downloadProgress.totalUnitCount = task.countOfBytesExpectedToReceive;
+    [self.uploadProgress setCancellable:YES];
+    [self.uploadProgress setCancellationHandler:^{
+        __typeof__(weakTask) strongTask = weakTask;
+        [strongTask cancel];
+    }];
+    [self.uploadProgress setPausable:YES];
+    [self.uploadProgress setPausingHandler:^{
+        __typeof__(weakTask) strongTask = weakTask;
+        [strongTask suspend];
+    }];
+    if ([self.uploadProgress respondsToSelector:@selector(setResumingHandler:)]) {
+        [self.uploadProgress setResumingHandler:^{
+            __typeof__(weakTask) strongTask = weakTask;
+            [strongTask resume];
+        }];
+    }
+
+    [self.downloadProgress setCancellable:YES];
+    [self.downloadProgress setCancellationHandler:^{
+        __typeof__(weakTask) strongTask = weakTask;
+        [strongTask cancel];
+    }];
+    [self.downloadProgress setPausable:YES];
+    [self.downloadProgress setPausingHandler:^{
+        __typeof__(weakTask) strongTask = weakTask;
+        [strongTask suspend];
+    }];
+
+    if ([self.downloadProgress respondsToSelector:@selector(setResumingHandler:)]) {
+        [self.downloadProgress setResumingHandler:^{
+            __typeof__(weakTask) strongTask = weakTask;
+            [strongTask resume];
+        }];
+    }
+
+    [task addObserver:self
+           forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))
+              options:NSKeyValueObservingOptionNew
+              context:NULL];
+    [task addObserver:self
+           forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))
+              options:NSKeyValueObservingOptionNew
+              context:NULL];
+
+    [task addObserver:self
+           forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))
+              options:NSKeyValueObservingOptionNew
+              context:NULL];
+    [task addObserver:self
+           forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))
+              options:NSKeyValueObservingOptionNew
+              context:NULL];
+
+    [self.downloadProgress addObserver:self
+                            forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
+                               options:NSKeyValueObservingOptionNew
+                               context:NULL];
+    [self.uploadProgress addObserver:self
+                          forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
+                             options:NSKeyValueObservingOptionNew
+                             context:NULL];
+}
+
+- (void)cleanUpProgressForTask:(NSURLSessionTask *)task {
+    [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))];
+    [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))];
+    [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))];
+    [task removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))];
+    [self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
+    [self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
+    if ([object isKindOfClass:[NSURLSessionTask class]] || [object isKindOfClass:[NSURLSessionDownloadTask class]]) {
+        if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) {
+            self.downloadProgress.completedUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))]) {
+            self.downloadProgress.totalUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) {
+            self.uploadProgress.completedUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToSend))]) {
+            self.uploadProgress.totalUnitCount = [change[NSKeyValueChangeNewKey] longLongValue];
+        }
+    }
+    else if ([object isEqual:self.downloadProgress]) {
+        if (self.downloadProgressBlock) {
+            self.downloadProgressBlock(object);
+        }
+    }
+    else if ([object isEqual:self.uploadProgress]) {
+        if (self.uploadProgressBlock) {
+            self.uploadProgressBlock(object);
+        }
+    }
+}
+
+#pragma mark - NSURLSessionTaskDelegate
+
+- (void)URLSession:(__unused NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didCompleteWithError:(NSError *)error
+{
+    __strong AFURLSessionManager *manager = self.manager;
+
+    __block id responseObject = nil;
+
+    __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+    userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
+
+    //Performance Improvement from #2672
+    NSData *data = nil;
+    if (self.mutableData) {
+        data = [self.mutableData copy];
+        //We no longer need the reference, so nil it out to gain back some memory.
+        self.mutableData = nil;
+    }
+
+    if (self.downloadFileURL) {
+        userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
+    } else if (data) {
+        userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
+    }
+
+    if (error) {
+        userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
+
+        dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
+            if (self.completionHandler) {
+                self.completionHandler(task.response, responseObject, error);
+            }
+
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
+            });
+        });
+    } else {
+        dispatch_async(url_session_manager_processing_queue(), ^{
+            NSError *serializationError = nil;
+            responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
+
+            if (self.downloadFileURL) {
+                responseObject = self.downloadFileURL;
+            }
+
+            if (responseObject) {
+                userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
+            }
+
+            if (serializationError) {
+                userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
+            }
+
+            dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
+                if (self.completionHandler) {
+                    self.completionHandler(task.response, responseObject, serializationError);
+                }
+
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
+                });
+            });
+        });
+    }
+}
+
+#pragma mark - NSURLSessionDataTaskDelegate
+
+- (void)URLSession:(__unused NSURLSession *)session
+          dataTask:(__unused NSURLSessionDataTask *)dataTask
+    didReceiveData:(NSData *)data
+{
+    [self.mutableData appendData:data];
+}
+
+#pragma mark - NSURLSessionDownloadTaskDelegate
+
+- (void)URLSession:(NSURLSession *)session
+      downloadTask:(NSURLSessionDownloadTask *)downloadTask
+didFinishDownloadingToURL:(NSURL *)location
+{
+    NSError *fileManagerError = nil;
+    self.downloadFileURL = nil;
+
+    if (self.downloadTaskDidFinishDownloading) {
+        self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
+        if (self.downloadFileURL) {
+            [[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError];
+
+            if (fileManagerError) {
+                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
+            }
+        }
+    }
+}
+
+@end
+
+#pragma mark -
+
+/**
+ *  A workaround for issues related to key-value observing the `state` of an `NSURLSessionTask`.
+ *
+ *  See:
+ *  - https://github.com/AFNetworking/AFNetworking/issues/1477
+ *  - https://github.com/AFNetworking/AFNetworking/issues/2638
+ *  - https://github.com/AFNetworking/AFNetworking/pull/2702
+ */
+
+static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
+    Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
+    Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
+    method_exchangeImplementations(originalMethod, swizzledMethod);
+}
+
+static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
+    return class_addMethod(theClass, selector,  method_getImplementation(method),  method_getTypeEncoding(method));
+}
+
+static NSString * const AFNSURLSessionTaskDidResumeNotification  = @"com.alamofire.networking.nsurlsessiontask.resume";
+static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend";
+
+@interface _AFURLSessionTaskSwizzling : NSObject
+
+@end
+
+@implementation _AFURLSessionTaskSwizzling
+
++ (void)load {
+    /**
+     WARNING: Trouble Ahead
+     https://github.com/AFNetworking/AFNetworking/pull/2702
+     */
+
+    if (NSClassFromString(@"NSURLSessionTask")) {
+        /**
+         iOS 7 and iOS 8 differ in NSURLSessionTask implementation, which makes the next bit of code a bit tricky.
+         Many Unit Tests have been built to validate as much of this behavior has possible.
+         Here is what we know:
+            - NSURLSessionTasks are implemented with class clusters, meaning the class you request from the API isn't actually the type of class you will get back.
+            - Simply referencing `[NSURLSessionTask class]` will not work. You need to ask an `NSURLSession` to actually create an object, and grab the class from there.
+            - On iOS 7, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `__NSCFURLSessionTask`.
+            - On iOS 8, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `NSURLSessionTask`.
+            - On iOS 7, `__NSCFLocalSessionTask` and `__NSCFURLSessionTask` are the only two classes that have their own implementations of `resume` and `suspend`, and `__NSCFLocalSessionTask` DOES NOT CALL SUPER. This means both classes need to be swizzled.
+            - On iOS 8, `NSURLSessionTask` is the only class that implements `resume` and `suspend`. This means this is the only class that needs to be swizzled.
+            - Because `NSURLSessionTask` is not involved in the class hierarchy for every version of iOS, its easier to add the swizzled methods to a dummy class and manage them there.
+
+         Some Assumptions:
+            - No implementations of `resume` or `suspend` call super. If this were to change in a future version of iOS, we'd need to handle it.
+            - No background task classes override `resume` or `suspend`
+
+         The current solution:
+            1) Grab an instance of `__NSCFLocalDataTask` by asking an instance of `NSURLSession` for a data task.
+            2) Grab a pointer to the original implementation of `af_resume`
+            3) Check to see if the current class has an implementation of resume. If so, continue to step 4.
+            4) Grab the super class of the current class.
+            5) Grab a pointer for the current class to the current implementation of `resume`.
+            6) Grab a pointer for the super class to the current implementation of `resume`.
+            7) If the current class implementation of `resume` is not equal to the super class implementation of `resume` AND the current implementation of `resume` is not equal to the original implementation of `af_resume`, THEN swizzle the methods
+            8) Set the current class to the super class, and repeat steps 3-8
+         */
+        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
+        NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration];
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnonnull"
+        NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil];
+#pragma clang diagnostic pop
+        IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume)));
+        Class currentClass = [localDataTask class];
+
+        while (class_getInstanceMethod(currentClass, @selector(resume))) {
+            Class superClass = [currentClass superclass];
+            IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume)));
+            IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume)));
+            if (classResumeIMP != superclassResumeIMP &&
+                originalAFResumeIMP != classResumeIMP) {
+                [self swizzleResumeAndSuspendMethodForClass:currentClass];
+            }
+            currentClass = [currentClass superclass];
+        }
+
+        [localDataTask cancel];
+        [session finishTasksAndInvalidate];
+    }
+}
+
++ (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass {
+    Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume));
+    Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend));
+
+    if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) {
+        af_swizzleSelector(theClass, @selector(resume), @selector(af_resume));
+    }
+
+    if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) {
+        af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend));
+    }
+}
+
+- (NSURLSessionTaskState)state {
+    NSAssert(NO, @"State method should never be called in the actual dummy class");
+    return NSURLSessionTaskStateCanceling;
+}
+
+- (void)af_resume {
+    NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
+    NSURLSessionTaskState state = [self state];
+    [self af_resume];
+
+    if (state != NSURLSessionTaskStateRunning) {
+        [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self];
+    }
+}
+
+- (void)af_suspend {
+    NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
+    NSURLSessionTaskState state = [self state];
+    [self af_suspend];
+
+    if (state != NSURLSessionTaskStateSuspended) {
+        [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self];
+    }
+}
+@end
+
+#pragma mark -
+
+@interface AFURLSessionManager ()
+@property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
+@property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue;
+@property (readwrite, nonatomic, strong) NSURLSession *session;
+@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
+@property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks;
+@property (readwrite, nonatomic, strong) NSLock *lock;
+@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
+@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
+@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
+@property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
+@property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge;
+@property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
+@property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
+@property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
+@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
+@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
+@property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
+@property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
+@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
+@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
+@property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
+@end
+
+@implementation AFURLSessionManager
+
+- (instancetype)init {
+    return [self initWithSessionConfiguration:nil];
+}
+
+- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
+    self = [super init];
+    if (!self) {
+        return nil;
+    }
+
+    if (!configuration) {
+        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
+    }
+
+    self.sessionConfiguration = configuration;
+
+    self.operationQueue = [[NSOperationQueue alloc] init];
+    self.operationQueue.maxConcurrentOperationCount = 1;
+
+    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
+
+    self.responseSerializer = [AFJSONResponseSerializer serializer];
+
+    self.securityPolicy = [AFSecurityPolicy defaultPolicy];
+
+#if !TARGET_OS_WATCH
+    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
+#endif
+
+    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
+
+    self.lock = [[NSLock alloc] init];
+    self.lock.name = AFURLSessionManagerLockName;
+
+    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
+        for (NSURLSessionDataTask *task in dataTasks) {
+            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
+        }
+
+        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
+            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
+        }
+
+        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
+            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
+        }
+    }];
+
+    return self;
+}
+
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark -
+
+- (NSString *)taskDescriptionForSessionTasks {
+    return [NSString stringWithFormat:@"%p", self];
+}
+
+- (void)taskDidResume:(NSNotification *)notification {
+    NSURLSessionTask *task = notification.object;
+    if ([task respondsToSelector:@selector(taskDescription)]) {
+        if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task];
+            });
+        }
+    }
+}
+
+- (void)taskDidSuspend:(NSNotification *)notification {
+    NSURLSessionTask *task = notification.object;
+    if ([task respondsToSelector:@selector(taskDescription)]) {
+        if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task];
+            });
+        }
+    }
+}
+
+#pragma mark -
+
+- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
+    NSParameterAssert(task);
+
+    AFURLSessionManagerTaskDelegate *delegate = nil;
+    [self.lock lock];
+    delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
+    [self.lock unlock];
+
+    return delegate;
+}
+
+- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
+            forTask:(NSURLSessionTask *)task
+{
+    NSParameterAssert(task);
+    NSParameterAssert(delegate);
+
+    [self.lock lock];
+    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
+    [delegate setupProgressForTask:task];
+    [self addNotificationObserverForTask:task];
+    [self.lock unlock];
+}
+
+- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
+                uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
+             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
+    delegate.manager = self;
+    delegate.completionHandler = completionHandler;
+
+    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
+    [self setDelegate:delegate forTask:dataTask];
+
+    delegate.uploadProgressBlock = uploadProgressBlock;
+    delegate.downloadProgressBlock = downloadProgressBlock;
+}
+
+- (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask
+                        progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+               completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
+    delegate.manager = self;
+    delegate.completionHandler = completionHandler;
+
+    uploadTask.taskDescription = self.taskDescriptionForSessionTasks;
+
+    [self setDelegate:delegate forTask:uploadTask];
+
+    delegate.uploadProgressBlock = uploadProgressBlock;
+}
+
+- (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
+                          progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
+                       destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
+                 completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
+{
+    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
+    delegate.manager = self;
+    delegate.completionHandler = completionHandler;
+
+    if (destination) {
+        delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
+            return destination(location, task.response);
+        };
+    }
+
+    downloadTask.taskDescription = self.taskDescriptionForSessionTasks;
+
+    [self setDelegate:delegate forTask:downloadTask];
+
+    delegate.downloadProgressBlock = downloadProgressBlock;
+}
+
+- (void)removeDelegateForTask:(NSURLSessionTask *)task {
+    NSParameterAssert(task);
+
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
+    [self.lock lock];
+    [delegate cleanUpProgressForTask:task];
+    [self removeNotificationObserverForTask:task];
+    [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
+    [self.lock unlock];
+}
+
+#pragma mark -
+
+- (NSArray *)tasksForKeyPath:(NSString *)keyPath {
+    __block NSArray *tasks = nil;
+    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
+    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
+        if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
+            tasks = dataTasks;
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) {
+            tasks = uploadTasks;
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) {
+            tasks = downloadTasks;
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) {
+            tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
+        }
+
+        dispatch_semaphore_signal(semaphore);
+    }];
+
+    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
+
+    return tasks;
+}
+
+- (NSArray *)tasks {
+    return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
+}
+
+- (NSArray *)dataTasks {
+    return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
+}
+
+- (NSArray *)uploadTasks {
+    return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
+}
+
+- (NSArray *)downloadTasks {
+    return [self tasksForKeyPath:NSStringFromSelector(_cmd)];
+}
+
+#pragma mark -
+
+- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks {
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (cancelPendingTasks) {
+            [self.session invalidateAndCancel];
+        } else {
+            [self.session finishTasksAndInvalidate];
+        }
+    });
+}
+
+#pragma mark -
+
+- (void)setResponseSerializer:(id <AFURLResponseSerialization>)responseSerializer {
+    NSParameterAssert(responseSerializer);
+
+    _responseSerializer = responseSerializer;
+}
+
+#pragma mark -
+- (void)addNotificationObserverForTask:(NSURLSessionTask *)task {
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task];
+}
+
+- (void)removeNotificationObserverForTask:(NSURLSessionTask *)task {
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidSuspendNotification object:task];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:AFNSURLSessionTaskDidResumeNotification object:task];
+}
+
+#pragma mark -
+
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+                            completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    return [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:completionHandler];
+}
+
+- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
+                               uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+                             downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
+                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler {
+
+    __block NSURLSessionDataTask *dataTask = nil;
+    url_session_manager_create_task_safely(^{
+        dataTask = [self.session dataTaskWithRequest:request];
+    });
+
+    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
+
+    return dataTask;
+}
+
+#pragma mark -
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+                                         fromFile:(NSURL *)fileURL
+                                         progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+                                completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    __block NSURLSessionUploadTask *uploadTask = nil;
+    url_session_manager_create_task_safely(^{
+        uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
+    });
+
+    if (!uploadTask && self.attemptsToRecreateUploadTasksForBackgroundSessions && self.session.configuration.identifier) {
+        for (NSUInteger attempts = 0; !uploadTask && attempts < AFMaximumNumberOfAttemptsToRecreateBackgroundSessionUploadTask; attempts++) {
+            uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
+        }
+    }
+
+    [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
+
+    return uploadTask;
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
+                                         fromData:(NSData *)bodyData
+                                         progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+                                completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    __block NSURLSessionUploadTask *uploadTask = nil;
+    url_session_manager_create_task_safely(^{
+        uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData];
+    });
+
+    [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
+
+    return uploadTask;
+}
+
+- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
+                                                 progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
+                                        completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
+{
+    __block NSURLSessionUploadTask *uploadTask = nil;
+    url_session_manager_create_task_safely(^{
+        uploadTask = [self.session uploadTaskWithStreamedRequest:request];
+    });
+
+    [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];
+
+    return uploadTask;
+}
+
+#pragma mark -
+
+- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
+                                             progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
+                                          destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
+                                    completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
+{
+    __block NSURLSessionDownloadTask *downloadTask = nil;
+    url_session_manager_create_task_safely(^{
+        downloadTask = [self.session downloadTaskWithRequest:request];
+    });
+
+    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];
+
+    return downloadTask;
+}
+
+- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
+                                                progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
+                                             destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
+                                       completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
+{
+    __block NSURLSessionDownloadTask *downloadTask = nil;
+    url_session_manager_create_task_safely(^{
+        downloadTask = [self.session downloadTaskWithResumeData:resumeData];
+    });
+
+    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];
+
+    return downloadTask;
+}
+
+#pragma mark -
+- (NSProgress *)uploadProgressForTask:(NSURLSessionTask *)task {
+    return [[self delegateForTask:task] uploadProgress];
+}
+
+- (NSProgress *)downloadProgressForTask:(NSURLSessionTask *)task {
+    return [[self delegateForTask:task] downloadProgress];
+}
+
+#pragma mark -
+
+- (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block {
+    self.sessionDidBecomeInvalid = block;
+}
+
+- (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block {
+    self.sessionDidReceiveAuthenticationChallenge = block;
+}
+
+- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block {
+    self.didFinishEventsForBackgroundURLSession = block;
+}
+
+#pragma mark -
+
+- (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block {
+    self.taskNeedNewBodyStream = block;
+}
+
+- (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block {
+    self.taskWillPerformHTTPRedirection = block;
+}
+
+- (void)setTaskDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block {
+    self.taskDidReceiveAuthenticationChallenge = block;
+}
+
+- (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block {
+    self.taskDidSendBodyData = block;
+}
+
+- (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block {
+    self.taskDidComplete = block;
+}
+
+#pragma mark -
+
+- (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block {
+    self.dataTaskDidReceiveResponse = block;
+}
+
+- (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block {
+    self.dataTaskDidBecomeDownloadTask = block;
+}
+
+- (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block {
+    self.dataTaskDidReceiveData = block;
+}
+
+- (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block {
+    self.dataTaskWillCacheResponse = block;
+}
+
+#pragma mark -
+
+- (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block {
+    self.downloadTaskDidFinishDownloading = block;
+}
+
+- (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block {
+    self.downloadTaskDidWriteData = block;
+}
+
+- (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block {
+    self.downloadTaskDidResume = block;
+}
+
+#pragma mark - NSObject
+
+- (NSString *)description {
+    return [NSString stringWithFormat:@"<%@: %p, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, self.session, self.operationQueue];
+}
+
+- (BOOL)respondsToSelector:(SEL)selector {
+    if (selector == @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)) {
+        return self.taskWillPerformHTTPRedirection != nil;
+    } else if (selector == @selector(URLSession:dataTask:didReceiveResponse:completionHandler:)) {
+        return self.dataTaskDidReceiveResponse != nil;
+    } else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) {
+        return self.dataTaskWillCacheResponse != nil;
+    } else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) {
+        return self.didFinishEventsForBackgroundURLSession != nil;
+    }
+
+    return [[self class] instancesRespondToSelector:selector];
+}
+
+#pragma mark - NSURLSessionDelegate
+
+- (void)URLSession:(NSURLSession *)session
+didBecomeInvalidWithError:(NSError *)error
+{
+    if (self.sessionDidBecomeInvalid) {
+        self.sessionDidBecomeInvalid(session, error);
+    }
+
+    [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session];
+}
+
+- (void)URLSession:(NSURLSession *)session
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
+{
+    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+    __block NSURLCredential *credential = nil;
+
+    if (self.sessionDidReceiveAuthenticationChallenge) {
+        disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential);
+    } else {
+        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
+            if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
+                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
+                if (credential) {
+                    disposition = NSURLSessionAuthChallengeUseCredential;
+                } else {
+                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+                }
+            } else {
+                disposition = NSURLSessionAuthChallengeRejectProtectionSpace;
+            }
+        } else {
+            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+        }
+    }
+
+    if (completionHandler) {
+        completionHandler(disposition, credential);
+    }
+}
+
+#pragma mark - NSURLSessionTaskDelegate
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+willPerformHTTPRedirection:(NSHTTPURLResponse *)response
+        newRequest:(NSURLRequest *)request
+ completionHandler:(void (^)(NSURLRequest *))completionHandler
+{
+    NSURLRequest *redirectRequest = request;
+
+    if (self.taskWillPerformHTTPRedirection) {
+        redirectRequest = self.taskWillPerformHTTPRedirection(session, task, response, request);
+    }
+
+    if (completionHandler) {
+        completionHandler(redirectRequest);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
+{
+    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+    __block NSURLCredential *credential = nil;
+
+    if (self.taskDidReceiveAuthenticationChallenge) {
+        disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
+    } else {
+        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
+            if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
+                disposition = NSURLSessionAuthChallengeUseCredential;
+                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
+            } else {
+                disposition = NSURLSessionAuthChallengeRejectProtectionSpace;
+            }
+        } else {
+            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+        }
+    }
+
+    if (completionHandler) {
+        completionHandler(disposition, credential);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+ needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
+{
+    NSInputStream *inputStream = nil;
+
+    if (self.taskNeedNewBodyStream) {
+        inputStream = self.taskNeedNewBodyStream(session, task);
+    } else if (task.originalRequest.HTTPBodyStream && [task.originalRequest.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
+        inputStream = [task.originalRequest.HTTPBodyStream copy];
+    }
+
+    if (completionHandler) {
+        completionHandler(inputStream);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+   didSendBodyData:(int64_t)bytesSent
+    totalBytesSent:(int64_t)totalBytesSent
+totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
+{
+
+    int64_t totalUnitCount = totalBytesExpectedToSend;
+    if(totalUnitCount == NSURLSessionTransferSizeUnknown) {
+        NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"];
+        if(contentLength) {
+            totalUnitCount = (int64_t) [contentLength longLongValue];
+        }
+    }
+
+    if (self.taskDidSendBodyData) {
+        self.taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalUnitCount);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didCompleteWithError:(NSError *)error
+{
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
+
+    // delegate may be nil when completing a task in the background
+    if (delegate) {
+        [delegate URLSession:session task:task didCompleteWithError:error];
+
+        [self removeDelegateForTask:task];
+    }
+
+    if (self.taskDidComplete) {
+        self.taskDidComplete(session, task, error);
+    }
+}
+
+#pragma mark - NSURLSessionDataDelegate
+
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+didReceiveResponse:(NSURLResponse *)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
+{
+    NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
+
+    if (self.dataTaskDidReceiveResponse) {
+        disposition = self.dataTaskDidReceiveResponse(session, dataTask, response);
+    }
+
+    if (completionHandler) {
+        completionHandler(disposition);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
+{
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
+    if (delegate) {
+        [self removeDelegateForTask:dataTask];
+        [self setDelegate:delegate forTask:downloadTask];
+    }
+
+    if (self.dataTaskDidBecomeDownloadTask) {
+        self.dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+    didReceiveData:(NSData *)data
+{
+
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:dataTask];
+    [delegate URLSession:session dataTask:dataTask didReceiveData:data];
+
+    if (self.dataTaskDidReceiveData) {
+        self.dataTaskDidReceiveData(session, dataTask, data);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+ willCacheResponse:(NSCachedURLResponse *)proposedResponse
+ completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
+{
+    NSCachedURLResponse *cachedResponse = proposedResponse;
+
+    if (self.dataTaskWillCacheResponse) {
+        cachedResponse = self.dataTaskWillCacheResponse(session, dataTask, proposedResponse);
+    }
+
+    if (completionHandler) {
+        completionHandler(cachedResponse);
+    }
+}
+
+- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
+    if (self.didFinishEventsForBackgroundURLSession) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self.didFinishEventsForBackgroundURLSession(session);
+        });
+    }
+}
+
+#pragma mark - NSURLSessionDownloadDelegate
+
+- (void)URLSession:(NSURLSession *)session
+      downloadTask:(NSURLSessionDownloadTask *)downloadTask
+didFinishDownloadingToURL:(NSURL *)location
+{
+    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
+    if (self.downloadTaskDidFinishDownloading) {
+        NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
+        if (fileURL) {
+            delegate.downloadFileURL = fileURL;
+            NSError *error = nil;
+            [[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error];
+            if (error) {
+                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
+            }
+
+            return;
+        }
+    }
+
+    if (delegate) {
+        [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+      downloadTask:(NSURLSessionDownloadTask *)downloadTask
+      didWriteData:(int64_t)bytesWritten
+ totalBytesWritten:(int64_t)totalBytesWritten
+totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
+{
+    if (self.downloadTaskDidWriteData) {
+        self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
+    }
+}
+
+- (void)URLSession:(NSURLSession *)session
+      downloadTask:(NSURLSessionDownloadTask *)downloadTask
+ didResumeAtOffset:(int64_t)fileOffset
+expectedTotalBytes:(int64_t)expectedTotalBytes
+{
+    if (self.downloadTaskDidResume) {
+        self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
+    }
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+    return YES;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
+
+    self = [self initWithSessionConfiguration:configuration];
+    if (!self) {
+        return nil;
+    }
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+    [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"];
+}
+
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+    return [[[self class] allocWithZone:zone] initWithSessionConfiguration:self.session.configuration];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.h
new file mode 100644
index 0000000..92af266
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.h
@@ -0,0 +1,8 @@
+#import <Foundation/Foundation.h>
+#import "AFURLResponseSerialization.h"
+
+@interface BinaryResponseSerializer : AFHTTPResponseSerializer
+
++ (instancetype)serializer;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.m
new file mode 100644
index 0000000..a891f8f
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/BinaryResponseSerializer.m
@@ -0,0 +1,126 @@
+#import "BinaryResponseSerializer.h"
+
+static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
+  if (!error) {
+    return underlyingError;
+  }
+
+  if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
+    return error;
+  }
+
+  NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
+  mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;
+
+  return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
+}
+
+static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
+  if ([error.domain isEqualToString:domain] && error.code == code) {
+    return YES;
+  } else if (error.userInfo[NSUnderlyingErrorKey]) {
+    return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
+  }
+
+  return NO;
+}
+
+@implementation BinaryResponseSerializer
+
++ (instancetype)serializer {
+  BinaryResponseSerializer *serializer = [[self alloc] init];
+  return serializer;
+}
+
+- (instancetype)init {
+  self = [super init];
+
+  if (!self) {
+    return nil;
+  }
+
+  self.acceptableContentTypes = nil;
+
+  return self;
+}
+
+- (NSString*)decodeResponseData:(NSData*)rawResponseData withEncoding:(CFStringEncoding)cfEncoding {
+  NSStringEncoding nsEncoding;
+  NSString* decoded = nil;
+
+  if (cfEncoding != kCFStringEncodingInvalidId) {
+    nsEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
+  }
+
+  NSStringEncoding supportedEncodings[6] = {
+    NSUTF8StringEncoding, NSWindowsCP1252StringEncoding, NSISOLatin1StringEncoding,
+    NSISOLatin2StringEncoding, NSASCIIStringEncoding, NSUnicodeStringEncoding
+  };
+
+  for (int i = 0; i < sizeof(supportedEncodings) / sizeof(NSStringEncoding) && !decoded; ++i) {
+    if (cfEncoding == kCFStringEncodingInvalidId || nsEncoding == supportedEncodings[i]) {
+      decoded = [[NSString alloc] initWithData:rawResponseData encoding:supportedEncodings[i]];
+    }
+  }
+
+  return decoded;
+}
+
+- (CFStringEncoding) getEncoding:(NSURLResponse *)response {
+  CFStringEncoding encoding = kCFStringEncodingInvalidId;
+
+  if (response.textEncodingName) {
+    encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
+  }
+
+  return encoding;
+}
+
+#pragma mark -
+
+- (BOOL)validateResponse:(NSHTTPURLResponse *)response
+                    data:(NSData *)data
+                   error:(NSError * __autoreleasing *)error
+{
+  if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
+    if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
+      NSMutableDictionary *mutableUserInfo = [@{
+        NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
+        NSURLErrorFailingURLErrorKey: [response URL],
+        AFNetworkingOperationFailingURLResponseErrorKey: response,
+      } mutableCopy];
+
+      if (data) {
+        mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
+
+        // trying to decode error message in body
+        mutableUserInfo[AFNetworkingOperationFailingURLResponseBodyErrorKey] = [self decodeResponseData:data withEncoding:[self getEncoding:response]];
+      }
+
+      if (error) {
+        *error = [NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo];
+      }
+
+      return NO;
+    }
+  }
+
+  return YES;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+  if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
+    if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+      return nil;
+    }
+  }
+
+  return [data base64EncodedStringWithOptions:0];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.h
new file mode 100644
index 0000000..e9daee1
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.h
@@ -0,0 +1,16 @@
+#import <Foundation/Foundation.h>
+
+#import <Cordova/CDVPlugin.h>
+
+@interface CordovaHttpPlugin : CDVPlugin
+
+- (void)setServerTrustMode:(CDVInvokedUrlCommand*)command;
+- (void)post:(CDVInvokedUrlCommand*)command;
+- (void)get:(CDVInvokedUrlCommand*)command;
+- (void)put:(CDVInvokedUrlCommand*)command;
+- (void)patch:(CDVInvokedUrlCommand*)command;
+- (void)delete:(CDVInvokedUrlCommand*)command;
+- (void)uploadFile:(CDVInvokedUrlCommand*)command;
+- (void)downloadFile:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.m
new file mode 100644
index 0000000..13d4369
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/CordovaHttpPlugin.m
@@ -0,0 +1,579 @@
+#import "CordovaHttpPlugin.h"
+#import "CDVFile.h"
+#import "BinaryResponseSerializer.h"
+#import "TextResponseSerializer.h"
+#import "TextRequestSerializer.h"
+#import "AFHTTPSessionManager.h"
+#import "SDNetworkActivityIndicator.h"
+
+@interface CordovaHttpPlugin()
+
+- (void)setRequestHeaders:(NSDictionary*)headers forManager:(AFHTTPSessionManager*)manager;
+- (void)handleSuccess:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response andData:(id)data;
+- (void)handleError:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response error:(NSError*)error;
+- (NSNumber*)getStatusCode:(NSError*) error;
+- (NSMutableDictionary*)copyHeaderFields:(NSDictionary*)headerFields;
+- (void)setTimeout:(NSTimeInterval)timeout forManager:(AFHTTPSessionManager*)manager;
+- (void)setRedirect:(bool)redirect forManager:(AFHTTPSessionManager*)manager;
+
+@end
+
+@implementation CordovaHttpPlugin {
+    AFSecurityPolicy *securityPolicy;
+}
+
+- (void)pluginInitialize {
+    securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+}
+
+- (void)setRequestSerializer:(NSString*)serializerName forManager:(AFHTTPSessionManager*)manager {
+    if ([serializerName isEqualToString:@"json"]) {
+        manager.requestSerializer = [AFJSONRequestSerializer serializer];
+    } else if ([serializerName isEqualToString:@"utf8"]) {
+        manager.requestSerializer = [TextRequestSerializer serializer];
+    } else {
+        manager.requestSerializer = [AFHTTPRequestSerializer serializer];
+    }
+}
+
+- (void)setRequestHeaders:(NSDictionary*)headers forManager:(AFHTTPSessionManager*)manager {
+    [headers enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
+        [manager.requestSerializer setValue:obj forHTTPHeaderField:key];
+    }];
+}
+
+- (void)setRedirect:(bool)followRedirect forManager:(AFHTTPSessionManager*)manager {
+    [manager setTaskWillPerformHTTPRedirectionBlock:^NSURLRequest * _Nonnull(NSURLSession * _Nonnull session,
+        NSURLSessionTask * _Nonnull task, NSURLResponse * _Nonnull response, NSURLRequest * _Nonnull request) {
+
+        if (followRedirect) {
+            return request;
+        } else {
+            return nil;
+        }
+    }];
+}
+
+- (void)setTimeout:(NSTimeInterval)timeout forManager:(AFHTTPSessionManager*)manager {
+    [manager.requestSerializer setTimeoutInterval:timeout];
+}
+
+- (void)setResponseSerializer:(NSString*)responseType forManager:(AFHTTPSessionManager*)manager {
+    if ([responseType isEqualToString: @"text"]) {
+        manager.responseSerializer = [TextResponseSerializer serializer];
+    } else {
+        manager.responseSerializer = [BinaryResponseSerializer serializer];
+    }
+}
+
+
+- (void)handleSuccess:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response andData:(id)data {
+    if (response != nil) {
+        [dictionary setValue:response.URL.absoluteString forKey:@"url"];
+        [dictionary setObject:[NSNumber numberWithInt:(int)response.statusCode] forKey:@"status"];
+        [dictionary setObject:[self copyHeaderFields:response.allHeaderFields] forKey:@"headers"];
+    }
+
+    if (data != nil) {
+        [dictionary setObject:data forKey:@"data"];
+    }
+}
+
+- (void)handleError:(NSMutableDictionary*)dictionary withResponse:(NSHTTPURLResponse*)response error:(NSError*)error {
+    if (response != nil) {
+        [dictionary setValue:response.URL.absoluteString forKey:@"url"];
+        [dictionary setObject:[NSNumber numberWithInt:(int)response.statusCode] forKey:@"status"];
+        [dictionary setObject:[self copyHeaderFields:response.allHeaderFields] forKey:@"headers"];
+        if (error.userInfo[AFNetworkingOperationFailingURLResponseBodyErrorKey]) {
+            [dictionary setObject:error.userInfo[AFNetworkingOperationFailingURLResponseBodyErrorKey] forKey:@"error"];
+        }
+    } else {
+        [dictionary setObject:[self getStatusCode:error] forKey:@"status"];
+        [dictionary setObject:[error localizedDescription] forKey:@"error"];
+    }
+}
+
+- (void)handleException:(NSException*)exception withCommand:(CDVInvokedUrlCommand*)command {
+  CordovaHttpPlugin* __weak weakSelf = self;
+
+  NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+  [dictionary setValue:exception.userInfo forKey:@"error"];
+  [dictionary setObject:[NSNumber numberWithInt:-1] forKey:@"status"];
+
+  CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+  [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (NSNumber*)getStatusCode:(NSError*) error {
+    switch ([error code]) {
+        case -1001:
+            // timeout
+            return [NSNumber numberWithInt:-4];
+        case -1002:
+            // unsupported URL
+            return [NSNumber numberWithInt:-5];
+        case -1003:
+            // server not found
+            return [NSNumber numberWithInt:-3];
+        case -1009:
+            // no connection
+            return [NSNumber numberWithInt:-6];
+        case -1200: // secure connection failed
+        case -1201: // certificate has bad date
+        case -1202: // certificate untrusted
+        case -1203: // certificate has unknown root
+        case -1204: // certificate is not yet valid
+            // configuring SSL failed
+            return [NSNumber numberWithInt:-2];
+        default:
+            return [NSNumber numberWithInt:-1];
+    }
+}
+
+- (NSMutableDictionary*)copyHeaderFields:(NSDictionary *)headerFields {
+    NSMutableDictionary *headerFieldsCopy = [[NSMutableDictionary alloc] initWithCapacity:headerFields.count];
+    NSString *headerKeyCopy;
+
+    for (NSString *headerKey in headerFields.allKeys) {
+        headerKeyCopy = [[headerKey mutableCopy] lowercaseString];
+        [headerFieldsCopy setValue:[headerFields objectForKey:headerKey] forKey:headerKeyCopy];
+    }
+
+    return headerFieldsCopy;
+}
+
+- (void)setServerTrustMode:(CDVInvokedUrlCommand*)command {
+    NSString *certMode = [command.arguments objectAtIndex:0];
+
+    if ([certMode isEqualToString: @"default"] || [certMode isEqualToString: @"legacy"]) {
+        securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+        securityPolicy.allowInvalidCertificates = NO;
+        securityPolicy.validatesDomainName = YES;
+    } else if ([certMode isEqualToString: @"nocheck"]) {
+        securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+        securityPolicy.allowInvalidCertificates = YES;
+        securityPolicy.validatesDomainName = NO;
+    } else if ([certMode isEqualToString: @"pinned"]) {
+        securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
+        securityPolicy.allowInvalidCertificates = NO;
+        securityPolicy.validatesDomainName = YES;
+    }
+
+    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (void)get:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *headers = [command.arguments objectAtIndex:1];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:2] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:3] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:4];
+
+    [self setRequestSerializer: @"default" forManager: manager];
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager GET:url parameters:nil success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)head:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *headers = [command.arguments objectAtIndex:1];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:2] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:3] boolValue];
+
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager HEAD:url parameters:nil success:^(NSURLSessionTask *task) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            // no 'body' for HEAD request, omitting 'data'
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)delete:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *headers = [command.arguments objectAtIndex:1];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:2] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:3] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:4];
+
+    [self setRequestSerializer: @"default" forManager: manager];
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager DELETE:url parameters:nil success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)post:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *data = [command.arguments objectAtIndex:1];
+    NSString *serializerName = [command.arguments objectAtIndex:2];
+    NSDictionary *headers = [command.arguments objectAtIndex:3];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:4] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:5] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:6];
+
+    [self setRequestSerializer: serializerName forManager: manager];
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager POST:url parameters:data success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)put:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *data = [command.arguments objectAtIndex:1];
+    NSString *serializerName = [command.arguments objectAtIndex:2];
+    NSDictionary *headers = [command.arguments objectAtIndex:3];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:4] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:5] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:6];
+
+    [self setRequestSerializer: serializerName forManager: manager];
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager PUT:url parameters:data success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)patch:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *data = [command.arguments objectAtIndex:1];
+    NSString *serializerName = [command.arguments objectAtIndex:2];
+    NSDictionary *headers = [command.arguments objectAtIndex:3];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:4] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:5] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:6];
+
+    [self setRequestSerializer: serializerName forManager: manager];
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager PATCH:url parameters:data success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)uploadFile:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *headers = [command.arguments objectAtIndex:1];
+    NSString *filePath = [command.arguments objectAtIndex: 2];
+    NSString *name = [command.arguments objectAtIndex: 3];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:4] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:5] boolValue];
+    NSString *responseType = [command.arguments objectAtIndex:6];
+
+    NSURL *fileURL = [NSURL URLWithString: filePath];
+
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+    [self setResponseSerializer:responseType forManager:manager];
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
+            NSError *error;
+            [formData appendPartWithFileURL:fileURL name:name error:&error];
+            if (error) {
+                NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+                [dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
+                [dictionary setObject:@"Could not add file to post body." forKey:@"error"];
+                CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+                [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+                [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+                return;
+            }
+        } progress:nil success:^(NSURLSessionTask *task, id responseObject) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:responseObject];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+- (void)downloadFile:(CDVInvokedUrlCommand*)command {
+    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+    manager.securityPolicy = securityPolicy;
+    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
+
+    NSString *url = [command.arguments objectAtIndex:0];
+    NSDictionary *headers = [command.arguments objectAtIndex:1];
+    NSString *filePath = [command.arguments objectAtIndex: 2];
+    NSTimeInterval timeoutInSeconds = [[command.arguments objectAtIndex:3] doubleValue];
+    bool followRedirect = [[command.arguments objectAtIndex:4] boolValue];
+
+    [self setRequestHeaders: headers forManager: manager];
+    [self setTimeout:timeoutInSeconds forManager:manager];
+    [self setRedirect:followRedirect forManager:manager];
+
+    if ([filePath hasPrefix:@"file://"]) {
+        filePath = [filePath substringFromIndex:7];
+    }
+
+    CordovaHttpPlugin* __weak weakSelf = self;
+    [[SDNetworkActivityIndicator sharedActivityIndicator] startActivity];
+
+    @try {
+        [manager GET:url parameters:nil success:^(NSURLSessionTask *task, id responseObject) {
+            /*
+             *
+             * 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.
+             *
+             * Modified by Andrew Stephan for Sync OnSet
+             *
+             */
+            // Download response is okay; begin streaming output to file
+            NSString* parentPath = [filePath stringByDeletingLastPathComponent];
+
+            // create parent directories if needed
+            NSError *error;
+            if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
+                NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+                [dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
+                if (error) {
+                    [dictionary setObject:[NSString stringWithFormat:@"Could not create path to save downloaded file: %@", [error localizedDescription]] forKey:@"error"];
+                } else {
+                    [dictionary setObject:@"Could not create path to save downloaded file" forKey:@"error"];
+                }
+                CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+                [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+                [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+                return;
+            }
+            NSData *data = (NSData *)responseObject;
+            if (![data writeToFile:filePath atomically:YES]) {
+                NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+                [dictionary setObject:[NSNumber numberWithInt:500] forKey:@"status"];
+                [dictionary setObject:@"Could not write the data to the given filePath." forKey:@"error"];
+                CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+                [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+                [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+                return;
+            }
+
+            id filePlugin = [self.commandDelegate getCommandInstance:@"File"];
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleSuccess:dictionary withResponse:(NSHTTPURLResponse*)task.response andData:nil];
+            [dictionary setObject:[filePlugin getDirectoryEntry:filePath isDirectory:NO] forKey:@"file"];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        } failure:^(NSURLSessionTask *task, NSError *error) {
+            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+            [self handleError:dictionary withResponse:(NSHTTPURLResponse*)task.response error:error];
+            [dictionary setObject:@"There was an error downloading the file" forKey:@"error"];
+
+            CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:dictionary];
+            [weakSelf.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+            [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        }];
+    }
+    @catch (NSException *exception) {
+        [[SDNetworkActivityIndicator sharedActivityIndicator] stopActivity];
+        [self handleException:exception withCommand:command];
+    }
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.h
new file mode 100644
index 0000000..2c43aa6
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.h
@@ -0,0 +1,18 @@
+/*
+ * This file is part of the SDNetworkActivityIndicator package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface SDNetworkActivityIndicator : NSObject
+
++ (id)sharedActivityIndicator;
+- (void)startActivity;
+- (void)stopActivity;
+- (void)stopAllActivity;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.m
new file mode 100644
index 0000000..c917b9a
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/SDNetworkActivityIndicator.m
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the SDNetworkActivityIndicator package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDNetworkActivityIndicator.h"
+
+@interface SDNetworkActivityIndicator()
+{
+    @private NSUInteger counter;
+}
+@end
+
+
+@implementation SDNetworkActivityIndicator
+
++ (instancetype) sharedActivityIndicator
+{
+    static id _sharedInstance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _sharedInstance = [[self alloc] init];
+    });
+    
+    return _sharedInstance;
+}
+
+- (id)init
+{
+    if ((self = [super init]))
+    {
+        counter = 0;
+    }
+
+    return self;
+}
+
+- (void)startActivity
+{
+    @synchronized(self)
+    {
+        counter++;
+        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
+    }
+}
+
+- (void)stopActivity
+{
+    @synchronized(self)
+    {
+        if (counter > 0 && --counter == 0)
+        {
+            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
+        }
+    }
+}
+
+- (void)stopAllActivity
+{
+    @synchronized(self)
+    {
+        counter = 0;
+        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
+    }
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.h
new file mode 100644
index 0000000..56ddad4
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.h
@@ -0,0 +1,8 @@
+#import <Foundation/Foundation.h>
+#import "AFURLRequestSerialization.h"
+
+@interface TextRequestSerializer : AFHTTPRequestSerializer
+
++ (instancetype)serializer;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.m
new file mode 100644
index 0000000..31c1c2e
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextRequestSerializer.m
@@ -0,0 +1,53 @@
+#import "TextRequestSerializer.h"
+
+@implementation TextRequestSerializer
+
++ (instancetype)serializer
+{
+    TextRequestSerializer *serializer = [[self alloc] init];
+    return serializer;
+}
+
+#pragma mark - AFURLRequestSerialization
+
+- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
+                               withParameters:(id)parameters
+                                        error:(NSError *__autoreleasing *)error
+{
+    NSParameterAssert(request);
+
+    if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
+        return [super requestBySerializingRequest:request withParameters:parameters error:error];
+    }
+
+    NSMutableURLRequest *mutableRequest = [request mutableCopy];
+
+    [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
+        if (![request valueForHTTPHeaderField:field]) {
+            [mutableRequest setValue:value forHTTPHeaderField:field];
+        }
+    }];
+
+    if (parameters) {
+        if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
+            [mutableRequest setValue:@"text/plain; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
+        }
+
+        [mutableRequest setHTTPBody: [[parameters valueForKey:@"text"] dataUsingEncoding:NSUTF8StringEncoding]];
+    }
+
+    return mutableRequest;
+}
+
+#pragma mark - NSSecureCoding
+
+- (instancetype)initWithCoder:(NSCoder *)decoder {
+    self = [super initWithCoder:decoder];
+    if (!self) {
+        return nil;
+    }
+
+    return self;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.h b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.h
new file mode 100644
index 0000000..d086a8c
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.h
@@ -0,0 +1,8 @@
+#import <Foundation/Foundation.h>
+#import "AFURLResponseSerialization.h"
+
+@interface TextResponseSerializer : AFHTTPResponseSerializer
+
++ (instancetype)serializer;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.m b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.m
new file mode 100644
index 0000000..76b6530
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-advanced-http/TextResponseSerializer.m
@@ -0,0 +1,145 @@
+#import "TextResponseSerializer.h"
+
+static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
+  if (!error) {
+    return underlyingError;
+  }
+
+  if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
+    return error;
+  }
+
+  NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
+  mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;
+
+  return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
+}
+
+static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
+  if ([error.domain isEqualToString:domain] && error.code == code) {
+    return YES;
+  } else if (error.userInfo[NSUnderlyingErrorKey]) {
+    return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
+  }
+
+  return NO;
+}
+
+@implementation TextResponseSerializer
+
++ (instancetype)serializer {
+  TextResponseSerializer *serializer = [[self alloc] init];
+  return serializer;
+}
+
+- (instancetype)init {
+  self = [super init];
+
+  if (!self) {
+    return nil;
+  }
+
+  self.acceptableContentTypes = nil;
+
+  return self;
+}
+
+- (NSString*)decodeResponseData:(NSData*)rawResponseData withEncoding:(CFStringEncoding)cfEncoding {
+  NSStringEncoding nsEncoding;
+  NSString* decoded = nil;
+
+  if (cfEncoding != kCFStringEncodingInvalidId) {
+    nsEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
+  }
+
+  NSStringEncoding supportedEncodings[6] = {
+    NSUTF8StringEncoding, NSWindowsCP1252StringEncoding, NSISOLatin1StringEncoding,
+    NSISOLatin2StringEncoding, NSASCIIStringEncoding, NSUnicodeStringEncoding
+  };
+
+  for (int i = 0; i < sizeof(supportedEncodings) / sizeof(NSStringEncoding) && !decoded; ++i) {
+    if (cfEncoding == kCFStringEncodingInvalidId || nsEncoding == supportedEncodings[i]) {
+      decoded = [[NSString alloc] initWithData:rawResponseData encoding:supportedEncodings[i]];
+    }
+  }
+
+  return decoded;
+}
+
+- (CFStringEncoding) getEncoding:(NSURLResponse *)response {
+  CFStringEncoding encoding = kCFStringEncodingInvalidId;
+
+  if (response.textEncodingName) {
+    encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
+  }
+
+  return encoding;
+}
+
+#pragma mark -
+
+- (BOOL)validateResponse:(NSHTTPURLResponse *)response
+                    data:(NSData *)data
+                 decoded:(NSString **)decoded
+                   error:(NSError * __autoreleasing *)error
+{
+  BOOL responseIsValid = YES;
+  NSError *validationError = nil;
+
+  if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
+    if (data) {
+      *decoded = [self decodeResponseData:data withEncoding:[self getEncoding:response]];
+    }
+
+    if (data && !*decoded) {
+      NSMutableDictionary *mutableUserInfo = [@{
+        NSURLErrorFailingURLErrorKey:[response URL],
+        AFNetworkingOperationFailingURLResponseErrorKey: response,
+        AFNetworkingOperationFailingURLResponseDataErrorKey: data,
+        AFNetworkingOperationFailingURLResponseBodyErrorKey: @"Could not decode response data due to invalid or unknown charset encoding",
+      } mutableCopy];
+
+      validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
+      responseIsValid = NO;
+    } else if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
+      NSMutableDictionary *mutableUserInfo = [@{
+        NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
+        NSURLErrorFailingURLErrorKey: [response URL],
+        AFNetworkingOperationFailingURLResponseErrorKey: response,
+      } mutableCopy];
+
+      if (data) {
+        mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
+        mutableUserInfo[AFNetworkingOperationFailingURLResponseBodyErrorKey] = *decoded;
+      }
+
+      validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
+      responseIsValid = NO;
+    }
+  }
+
+  if (error && !responseIsValid) {
+    *error = validationError;
+  }
+
+  return responseIsValid;
+}
+
+#pragma mark - AFURLResponseSerialization
+
+- (id)responseObjectForResponse:(NSURLResponse *)response
+                           data:(NSData *)data
+                          error:(NSError *__autoreleasing *)error
+{
+  NSString* decoded = nil;
+
+  if (![self validateResponse:(NSHTTPURLResponse *)response data:data decoded:&decoded error:error]) {
+    if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
+      return nil;
+    }
+  }
+
+  return decoded;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.h b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.h
new file mode 100644
index 0000000..f64f66c
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.h
@@ -0,0 +1,116 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import <CoreLocation/CLLocationManager.h>
+#import <Cordova/CDVPlugin.h>
+
+enum CDVDestinationType {
+    DestinationTypeDataUrl = 0,
+    DestinationTypeFileUri,
+    DestinationTypeNativeUri
+};
+typedef NSUInteger CDVDestinationType;
+
+enum CDVEncodingType {
+    EncodingTypeJPEG = 0,
+    EncodingTypePNG
+};
+typedef NSUInteger CDVEncodingType;
+
+enum CDVMediaType {
+    MediaTypePicture = 0,
+    MediaTypeVideo,
+    MediaTypeAll
+};
+typedef NSUInteger CDVMediaType;
+
+@interface CDVPictureOptions : NSObject
+
+@property (strong) NSNumber* quality;
+@property (assign) CDVDestinationType destinationType;
+@property (assign) UIImagePickerControllerSourceType sourceType;
+@property (assign) CGSize targetSize;
+@property (assign) CDVEncodingType encodingType;
+@property (assign) CDVMediaType mediaType;
+@property (assign) BOOL allowsEditing;
+@property (assign) BOOL correctOrientation;
+@property (assign) BOOL saveToPhotoAlbum;
+@property (strong) NSDictionary* popoverOptions;
+@property (assign) UIImagePickerControllerCameraDevice cameraDirection;
+
+@property (assign) BOOL popoverSupported;
+@property (assign) BOOL usesGeolocation;
+@property (assign) BOOL cropToSize;
+
++ (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVCameraPicker : UIImagePickerController
+
+@property (strong) CDVPictureOptions* pictureOptions;
+
+@property (copy)   NSString* callbackId;
+@property (copy)   NSString* postUrl;
+@property (strong) UIPopoverController* pickerPopoverController;
+@property (assign) BOOL cropToSize;
+@property (strong) UIView* webView;
+
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)options;
+
+@end
+
+// ======================================================================= //
+
+@interface CDVCamera : CDVPlugin <UIImagePickerControllerDelegate,
+                       UINavigationControllerDelegate,
+                       UIPopoverControllerDelegate,
+                       CLLocationManagerDelegate>
+{}
+
+@property (strong) CDVCameraPicker* pickerController;
+@property (strong) NSMutableDictionary *metadata;
+@property (strong, nonatomic) CLLocationManager *locationManager;
+@property (strong) NSData* data;
+
+/*
+ * getPicture
+ *
+ * arguments:
+ *	1: this is the javascript function that will be called with the results, the first parameter passed to the
+ *		javascript function is the picture as a Base64 encoded string
+ *  2: this is the javascript function to be called if there was an error
+ * options:
+ *	quality: integer between 1 and 100
+ */
+- (void)takePicture:(CDVInvokedUrlCommand*)command;
+- (void)cleanup:(CDVInvokedUrlCommand*)command;
+- (void)repositionPopover:(CDVInvokedUrlCommand*)command;
+
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info;
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
+- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
+- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
+
+- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
+- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.m b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.m
new file mode 100644
index 0000000..c71de05
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVCamera.m
@@ -0,0 +1,772 @@
+/*
+ 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.
+ */
+
+#import "CDVCamera.h"
+#import "CDVJpegHeaderWriter.h"
+#import "UIImage+CropScaleOrientation.h"
+#import <ImageIO/CGImageProperties.h>
+#import <AssetsLibrary/ALAssetRepresentation.h>
+#import <AssetsLibrary/AssetsLibrary.h>
+#import <AVFoundation/AVFoundation.h>
+#import <ImageIO/CGImageSource.h>
+#import <ImageIO/CGImageProperties.h>
+#import <ImageIO/CGImageDestination.h>
+#import <MobileCoreServices/UTCoreTypes.h>
+#import <objc/message.h>
+
+#ifndef __CORDOVA_4_0_0
+    #import <Cordova/NSData+Base64.h>
+#endif
+
+#define CDV_PHOTO_PREFIX @"cdv_photo_"
+
+static NSSet* org_apache_cordova_validArrowDirections;
+
+static NSString* toBase64(NSData* data) {
+    SEL s1 = NSSelectorFromString(@"cdv_base64EncodedString");
+    SEL s2 = NSSelectorFromString(@"base64EncodedString");
+    SEL s3 = NSSelectorFromString(@"base64EncodedStringWithOptions:");
+
+    if ([data respondsToSelector:s1]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s1];
+        return func(data, s1);
+    } else if ([data respondsToSelector:s2]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s2];
+        return func(data, s2);
+    } else if ([data respondsToSelector:s3]) {
+        NSString* (*func)(id, SEL, NSUInteger) = (void *)[data methodForSelector:s3];
+        return func(data, s3, 0);
+    } else {
+        return nil;
+    }
+}
+
+@implementation CDVPictureOptions
+
++ (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command
+{
+    CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
+
+    pictureOptions.quality = [command argumentAtIndex:0 withDefault:@(50)];
+    pictureOptions.destinationType = [[command argumentAtIndex:1 withDefault:@(DestinationTypeFileUri)] unsignedIntegerValue];
+    pictureOptions.sourceType = [[command argumentAtIndex:2 withDefault:@(UIImagePickerControllerSourceTypeCamera)] unsignedIntegerValue];
+
+    NSNumber* targetWidth = [command argumentAtIndex:3 withDefault:nil];
+    NSNumber* targetHeight = [command argumentAtIndex:4 withDefault:nil];
+    pictureOptions.targetSize = CGSizeMake(0, 0);
+    if ((targetWidth != nil) && (targetHeight != nil)) {
+        pictureOptions.targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
+    }
+
+    pictureOptions.encodingType = [[command argumentAtIndex:5 withDefault:@(EncodingTypeJPEG)] unsignedIntegerValue];
+    pictureOptions.mediaType = [[command argumentAtIndex:6 withDefault:@(MediaTypePicture)] unsignedIntegerValue];
+    pictureOptions.allowsEditing = [[command argumentAtIndex:7 withDefault:@(NO)] boolValue];
+    pictureOptions.correctOrientation = [[command argumentAtIndex:8 withDefault:@(NO)] boolValue];
+    pictureOptions.saveToPhotoAlbum = [[command argumentAtIndex:9 withDefault:@(NO)] boolValue];
+    pictureOptions.popoverOptions = [command argumentAtIndex:10 withDefault:nil];
+    pictureOptions.cameraDirection = [[command argumentAtIndex:11 withDefault:@(UIImagePickerControllerCameraDeviceRear)] unsignedIntegerValue];
+
+    pictureOptions.popoverSupported = NO;
+    pictureOptions.usesGeolocation = NO;
+
+    return pictureOptions;
+}
+
+@end
+
+
+@interface CDVCamera ()
+
+@property (readwrite, assign) BOOL hasPendingOperation;
+
+@end
+
+@implementation CDVCamera
+
++ (void)initialize
+{
+    org_apache_cordova_validArrowDirections = [[NSSet alloc] initWithObjects:[NSNumber numberWithInt:UIPopoverArrowDirectionUp], [NSNumber numberWithInt:UIPopoverArrowDirectionDown], [NSNumber numberWithInt:UIPopoverArrowDirectionLeft], [NSNumber numberWithInt:UIPopoverArrowDirectionRight], [NSNumber numberWithInt:UIPopoverArrowDirectionAny], nil];
+}
+
+@synthesize hasPendingOperation, pickerController, locationManager;
+
+- (NSURL*) urlTransformer:(NSURL*)url
+{
+    NSURL* urlToTransform = url;
+
+    // for backwards compatibility - we check if this property is there
+    SEL sel = NSSelectorFromString(@"urlTransformer");
+    if ([self.commandDelegate respondsToSelector:sel]) {
+        // grab the block from the commandDelegate
+        NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(self.commandDelegate, sel);
+        // if block is not null, we call it
+        if (urlTransformer) {
+            urlToTransform = urlTransformer(url);
+        }
+    }
+
+    return urlToTransform;
+}
+
+- (BOOL)usesGeolocation
+{
+    id useGeo = [self.commandDelegate.settings objectForKey:[@"CameraUsesGeolocation" lowercaseString]];
+    return [(NSNumber*)useGeo boolValue];
+}
+
+- (BOOL)popoverSupported
+{
+    return (NSClassFromString(@"UIPopoverController") != nil) &&
+           (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
+}
+
+- (void)takePicture:(CDVInvokedUrlCommand*)command
+{
+    self.hasPendingOperation = YES;
+
+    __weak CDVCamera* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^{
+
+        CDVPictureOptions* pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
+        pictureOptions.popoverSupported = [weakSelf popoverSupported];
+        pictureOptions.usesGeolocation = [weakSelf usesGeolocation];
+        pictureOptions.cropToSize = NO;
+
+        BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType];
+        if (!hasCamera) {
+            NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)pictureOptions.sourceType);
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No camera available"];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            return;
+        }
+
+        // Validate the app has permission to access the camera
+        if (pictureOptions.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) {
+            AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+            if (authStatus == AVAuthorizationStatusDenied ||
+                authStatus == AVAuthorizationStatusRestricted) {
+                // If iOS 8+, offer a link to the Settings app
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+                NSString* settingsButton = (&UIApplicationOpenSettingsURLString != NULL)
+                    ? NSLocalizedString(@"Settings", nil)
+                    : nil;
+#pragma clang diagnostic pop
+
+                // Denied; show an alert
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [[[UIAlertView alloc] initWithTitle:[[NSBundle mainBundle]
+                                                         objectForInfoDictionaryKey:@"CFBundleDisplayName"]
+                                                message:NSLocalizedString(@"Access to the camera has been prohibited; please enable it in the Settings app to continue.", nil)
+                                               delegate:weakSelf
+                                      cancelButtonTitle:NSLocalizedString(@"OK", nil)
+                                      otherButtonTitles:settingsButton, nil] show];
+                });
+            }
+        }
+
+        CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+        weakSelf.pickerController = cameraPicker;
+
+        cameraPicker.delegate = weakSelf;
+        cameraPicker.callbackId = command.callbackId;
+        // we need to capture this state for memory warnings that dealloc this object
+        cameraPicker.webView = weakSelf.webView;
+
+        // Perform UI operations on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            // If a popover is already open, close it; we only want one at a time.
+            if (([[weakSelf pickerController] pickerPopoverController] != nil) && [[[weakSelf pickerController] pickerPopoverController] isPopoverVisible]) {
+                [[[weakSelf pickerController] pickerPopoverController] dismissPopoverAnimated:YES];
+                [[[weakSelf pickerController] pickerPopoverController] setDelegate:nil];
+                [[weakSelf pickerController] setPickerPopoverController:nil];
+            }
+
+            if ([weakSelf popoverSupported] && (pictureOptions.sourceType != UIImagePickerControllerSourceTypeCamera)) {
+                if (cameraPicker.pickerPopoverController == nil) {
+                    cameraPicker.pickerPopoverController = [[NSClassFromString(@"UIPopoverController") alloc] initWithContentViewController:cameraPicker];
+                }
+                [weakSelf displayPopover:pictureOptions.popoverOptions];
+                weakSelf.hasPendingOperation = NO;
+            } else {
+                cameraPicker.modalPresentationStyle = UIModalPresentationCurrentContext;
+                [weakSelf.viewController presentViewController:cameraPicker animated:YES completion:^{
+                    weakSelf.hasPendingOperation = NO;
+                }];
+            }
+        });
+    }];
+}
+
+// Delegate for camera permission UIAlertView
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    // If Settings button (on iOS 8), open the settings app
+    if (buttonIndex == 1) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+        if (&UIApplicationOpenSettingsURLString != NULL) {
+            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+        }
+#pragma clang diagnostic pop
+    }
+
+    // Dismiss the view
+    [[self.pickerController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];   // error callback expects string ATM
+
+    [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
+
+    self.hasPendingOperation = NO;
+    self.pickerController = nil;
+}
+
+- (void)repositionPopover:(CDVInvokedUrlCommand*)command
+{
+    if (([[self pickerController] pickerPopoverController] != nil) && [[[self pickerController] pickerPopoverController] isPopoverVisible]) {
+
+        [[[self pickerController] pickerPopoverController] dismissPopoverAnimated:NO];
+
+        NSDictionary* options = [command argumentAtIndex:0 withDefault:nil];
+        [self displayPopover:options];
+    }
+}
+
+- (NSInteger)integerValueForKey:(NSDictionary*)dict key:(NSString*)key defaultValue:(NSInteger)defaultValue
+{
+    NSInteger value = defaultValue;
+
+    NSNumber* val = [dict valueForKey:key];  // value is an NSNumber
+
+    if (val != nil) {
+        value = [val integerValue];
+    }
+    return value;
+}
+
+- (void)displayPopover:(NSDictionary*)options
+{
+    NSInteger x = 0;
+    NSInteger y = 32;
+    NSInteger width = 320;
+    NSInteger height = 480;
+    UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
+
+    if (options) {
+        x = [self integerValueForKey:options key:@"x" defaultValue:0];
+        y = [self integerValueForKey:options key:@"y" defaultValue:32];
+        width = [self integerValueForKey:options key:@"width" defaultValue:320];
+        height = [self integerValueForKey:options key:@"height" defaultValue:480];
+        arrowDirection = [self integerValueForKey:options key:@"arrowDir" defaultValue:UIPopoverArrowDirectionAny];
+        if (![org_apache_cordova_validArrowDirections containsObject:[NSNumber numberWithUnsignedInteger:arrowDirection]]) {
+            arrowDirection = UIPopoverArrowDirectionAny;
+        }
+    }
+
+    [[[self pickerController] pickerPopoverController] setDelegate:self];
+    [[[self pickerController] pickerPopoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
+                                                                 inView:[self.webView superview]
+                                               permittedArrowDirections:arrowDirection
+                                                               animated:YES];
+}
+
+- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
+{
+    if([navigationController isKindOfClass:[UIImagePickerController class]]){
+        UIImagePickerController* cameraPicker = (UIImagePickerController*)navigationController;
+
+        if(![cameraPicker.mediaTypes containsObject:(NSString*)kUTTypeImage]){
+            [viewController.navigationItem setTitle:NSLocalizedString(@"Videos", nil)];
+        }
+    }
+}
+
+- (void)cleanup:(CDVInvokedUrlCommand*)command
+{
+    // empty the tmp directory
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    NSError* err = nil;
+    BOOL hasErrors = NO;
+
+    // clear contents of NSTemporaryDirectory
+    NSString* tempDirectoryPath = NSTemporaryDirectory();
+    NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath];
+    NSString* fileName = nil;
+    BOOL result;
+
+    while ((fileName = [directoryEnumerator nextObject])) {
+        // only delete the files we created
+        if (![fileName hasPrefix:CDV_PHOTO_PREFIX]) {
+            continue;
+        }
+        NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName];
+        result = [fileMgr removeItemAtPath:filePath error:&err];
+        if (!result && err) {
+            NSLog(@"Failed to delete: %@ (error: %@)", filePath, err);
+            hasErrors = YES;
+        }
+    }
+
+    CDVPluginResult* pluginResult;
+    if (hasErrors) {
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:@"One or more files failed to be deleted."];
+    } else {
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    }
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (void)popoverControllerDidDismissPopover:(id)popoverController
+{
+    UIPopoverController* pc = (UIPopoverController*)popoverController;
+
+    [pc dismissPopoverAnimated:YES];
+    pc.delegate = nil;
+    if (self.pickerController && self.pickerController.callbackId && self.pickerController.pickerPopoverController) {
+        self.pickerController.pickerPopoverController = nil;
+        NSString* callbackId = self.pickerController.callbackId;
+        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];   // error callback expects string ATM
+        [self.commandDelegate sendPluginResult:result callbackId:callbackId];
+    }
+    self.hasPendingOperation = NO;
+}
+
+- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options
+{
+    NSData* data = nil;
+
+    switch (options.encodingType) {
+        case EncodingTypePNG:
+            data = UIImagePNGRepresentation(image);
+            break;
+        case EncodingTypeJPEG:
+        {
+            if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO) && (([options.quality integerValue] == 100) || (options.sourceType != UIImagePickerControllerSourceTypeCamera))){
+                // use image unedited as requested , don't resize
+                data = UIImageJPEGRepresentation(image, 1.0);
+            } else {
+                data = UIImageJPEGRepresentation(image, [options.quality floatValue] / 100.0f);
+            }
+
+            if (options.usesGeolocation) {
+                NSDictionary* controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
+                if (controllerMetadata) {
+                    self.data = data;
+                    self.metadata = [[NSMutableDictionary alloc] init];
+
+                    NSMutableDictionary* EXIFDictionary = [[controllerMetadata objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
+                    if (EXIFDictionary)	{
+                        [self.metadata setObject:EXIFDictionary forKey:(NSString*)kCGImagePropertyExifDictionary];
+                    }
+
+                    if (IsAtLeastiOSVersion(@"8.0")) {
+                        [[self locationManager] performSelector:NSSelectorFromString(@"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
+                    }
+                    [[self locationManager] startUpdatingLocation];
+                }
+            }
+        }
+            break;
+        default:
+            break;
+    };
+
+    return data;
+}
+
+- (NSString*)tempFilePath:(NSString*)extension
+{
+    NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
+    NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
+    NSString* filePath;
+
+    // generate unique file name
+    int i = 1;
+    do {
+        filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, extension];
+    } while ([fileMgr fileExistsAtPath:filePath]);
+
+    return filePath;
+}
+
+- (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options
+{
+    // get the image
+    UIImage* image = nil;
+    if (options.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
+        image = [info objectForKey:UIImagePickerControllerEditedImage];
+    } else {
+        image = [info objectForKey:UIImagePickerControllerOriginalImage];
+    }
+
+    if (options.correctOrientation) {
+        image = [image imageCorrectedForCaptureOrientation];
+    }
+
+    UIImage* scaledImage = nil;
+
+    if ((options.targetSize.width > 0) && (options.targetSize.height > 0)) {
+        // if cropToSize, resize image and crop to target size, otherwise resize to fit target without cropping
+        if (options.cropToSize) {
+            scaledImage = [image imageByScalingAndCroppingForSize:options.targetSize];
+        } else {
+            scaledImage = [image imageByScalingNotCroppingForSize:options.targetSize];
+        }
+    }
+
+    return (scaledImage == nil ? image : scaledImage);
+}
+
+- (void)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info completion:(void (^)(CDVPluginResult* res))completion
+{
+    CDVPluginResult* result = nil;
+    BOOL saveToPhotoAlbum = options.saveToPhotoAlbum;
+    UIImage* image = nil;
+
+    switch (options.destinationType) {
+        case DestinationTypeNativeUri:
+        {
+            NSURL* url = [info objectForKey:UIImagePickerControllerReferenceURL];
+            saveToPhotoAlbum = NO;
+            // If, for example, we use sourceType = Camera, URL might be nil because image is stored in memory.
+            // In this case we must save image to device before obtaining an URI.
+            if (url == nil) {
+                image = [self retrieveImage:info options:options];
+                ALAssetsLibrary* library = [ALAssetsLibrary new];
+                [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:^(NSURL *assetURL, NSError *error) {
+                    CDVPluginResult* resultToReturn = nil;
+                    if (error) {
+                        resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
+                    } else {
+                        NSString* nativeUri = [[self urlTransformer:assetURL] absoluteString];
+                        resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
+                    }
+                    completion(resultToReturn);
+                }];
+                return;
+            } else {
+                NSString* nativeUri = [[self urlTransformer:url] absoluteString];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
+            }
+        }
+            break;
+        case DestinationTypeFileUri:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            if (data) {
+
+                NSString* extension = options.encodingType == EncodingTypePNG? @"png" : @"jpg";
+                NSString* filePath = [self tempFilePath:extension];
+                NSError* err = nil;
+
+                // save file
+                if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
+                } else {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]];
+                }
+            }
+        }
+            break;
+        case DestinationTypeDataUrl:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            if (data)  {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(data)];
+            }
+        }
+            break;
+        default:
+            break;
+    };
+
+    if (saveToPhotoAlbum && image) {
+        ALAssetsLibrary* library = [ALAssetsLibrary new];
+        [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:nil];
+    }
+
+    completion(result);
+}
+
+- (CDVPluginResult*)resultForVideo:(NSDictionary*)info
+{
+    NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
+}
+
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
+{
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+
+    dispatch_block_t invoke = ^(void) {
+        __block CDVPluginResult* result = nil;
+
+        NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
+        if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
+            [weakSelf resultForImage:cameraPicker.pictureOptions info:info completion:^(CDVPluginResult* res) {
+                if (![self usesGeolocation] || picker.sourceType != UIImagePickerControllerSourceTypeCamera) {
+                    [weakSelf.commandDelegate sendPluginResult:res callbackId:cameraPicker.callbackId];
+                    weakSelf.hasPendingOperation = NO;
+                    weakSelf.pickerController = nil;
+                }
+            }];
+        }
+        else {
+            result = [weakSelf resultForVideo:info];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+            weakSelf.hasPendingOperation = NO;
+            weakSelf.pickerController = nil;
+        }
+    };
+
+    if (cameraPicker.pictureOptions.popoverSupported && (cameraPicker.pickerPopoverController != nil)) {
+        [cameraPicker.pickerPopoverController dismissPopoverAnimated:YES];
+        cameraPicker.pickerPopoverController.delegate = nil;
+        cameraPicker.pickerPopoverController = nil;
+        invoke();
+    } else {
+        [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
+    }
+}
+
+// older api calls newer didFinishPickingMediaWithInfo
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo
+{
+    NSDictionary* imageInfo = [NSDictionary dictionaryWithObject:image forKey:UIImagePickerControllerOriginalImage];
+
+    [self imagePickerController:picker didFinishPickingMediaWithInfo:imageInfo];
+}
+
+- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
+{
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+
+    dispatch_block_t invoke = ^ (void) {
+        CDVPluginResult* result;
+        if (picker.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] != ALAuthorizationStatusAuthorized) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];
+        } else if (picker.sourceType != UIImagePickerControllerSourceTypeCamera && [ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
+        } else {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No Image Selected"];
+        }
+
+
+        [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+
+        weakSelf.hasPendingOperation = NO;
+        weakSelf.pickerController = nil;
+    };
+
+    [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
+}
+
+- (CLLocationManager*)locationManager
+{
+	if (locationManager != nil) {
+		return locationManager;
+	}
+
+	locationManager = [[CLLocationManager alloc] init];
+	[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
+	[locationManager setDelegate:self];
+
+	return locationManager;
+}
+
+- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
+{
+    if (locationManager == nil) {
+        return;
+    }
+
+    [self.locationManager stopUpdatingLocation];
+    self.locationManager = nil;
+
+    NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
+
+    CLLocationDegrees latitude  = newLocation.coordinate.latitude;
+    CLLocationDegrees longitude = newLocation.coordinate.longitude;
+
+    // latitude
+    if (latitude < 0.0) {
+        latitude = latitude * -1.0f;
+        [GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
+    } else {
+        [GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
+    }
+    [GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
+
+    // longitude
+    if (longitude < 0.0) {
+        longitude = longitude * -1.0f;
+        [GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
+    }
+    else {
+        [GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
+    }
+    [GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
+
+    // altitude
+    CGFloat altitude = newLocation.altitude;
+    if (!isnan(altitude)){
+        if (altitude < 0) {
+            altitude = -altitude;
+            [GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
+        } else {
+            [GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
+        }
+        [GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
+    }
+
+    // Time and date
+    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+    [formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
+    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
+    [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
+    [formatter setDateFormat:@"yyyy:MM:dd"];
+    [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
+
+    [self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
+    [self imagePickerControllerReturnImageResult];
+}
+
+- (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error
+{
+    if (locationManager == nil) {
+        return;
+    }
+
+    [self.locationManager stopUpdatingLocation];
+    self.locationManager = nil;
+
+    [self imagePickerControllerReturnImageResult];
+}
+
+- (void)imagePickerControllerReturnImageResult
+{
+    CDVPictureOptions* options = self.pickerController.pictureOptions;
+    CDVPluginResult* result = nil;
+
+    if (self.metadata) {
+        CGImageSourceRef sourceImage = CGImageSourceCreateWithData((__bridge CFDataRef)self.data, NULL);
+        CFStringRef sourceType = CGImageSourceGetType(sourceImage);
+
+        CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)self.data, sourceType, 1, NULL);
+        CGImageDestinationAddImageFromSource(destinationImage, sourceImage, 0, (__bridge CFDictionaryRef)self.metadata);
+        CGImageDestinationFinalize(destinationImage);
+
+        CFRelease(sourceImage);
+        CFRelease(destinationImage);
+    }
+
+    switch (options.destinationType) {
+        case DestinationTypeFileUri:
+        {
+            NSError* err = nil;
+            NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
+            NSString* filePath = [self tempFilePath:extension];
+
+            // save file
+            if (![self.data writeToFile:filePath options:NSAtomicWrite error:&err]) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
+            }
+            else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]];
+            }
+        }
+            break;
+        case DestinationTypeDataUrl:
+        {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
+        }
+            break;
+        case DestinationTypeNativeUri:
+        default:
+            break;
+    };
+
+    if (result) {
+        [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
+    }
+
+    self.hasPendingOperation = NO;
+    self.pickerController = nil;
+    self.data = nil;
+    self.metadata = nil;
+
+    if (options.saveToPhotoAlbum) {
+        ALAssetsLibrary *library = [ALAssetsLibrary new];
+        [library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
+    }
+}
+
+@end
+
+@implementation CDVCameraPicker
+
+- (BOOL)prefersStatusBarHidden
+{
+    return YES;
+}
+
+- (UIViewController*)childViewControllerForStatusBarHidden
+{
+    return nil;
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
+    if ([self respondsToSelector:sel]) {
+        [self performSelector:sel withObject:nil afterDelay:0];
+    }
+
+    [super viewWillAppear:animated];
+}
+
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)pictureOptions;
+{
+    CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
+    cameraPicker.pictureOptions = pictureOptions;
+    cameraPicker.sourceType = pictureOptions.sourceType;
+    cameraPicker.allowsEditing = pictureOptions.allowsEditing;
+
+    if (cameraPicker.sourceType == UIImagePickerControllerSourceTypeCamera) {
+        // We only allow taking pictures (no video) in this API.
+        cameraPicker.mediaTypes = @[(NSString*)kUTTypeImage];
+        // We can only set the camera device if we're actually using the camera.
+        cameraPicker.cameraDevice = pictureOptions.cameraDirection;
+    } else if (pictureOptions.mediaType == MediaTypeAll) {
+        cameraPicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:cameraPicker.sourceType];
+    } else {
+        NSArray* mediaArray = @[(NSString*)(pictureOptions.mediaType == MediaTypeVideo ? kUTTypeMovie : kUTTypeImage)];
+        cameraPicker.mediaTypes = mediaArray;
+    }
+
+    return cameraPicker;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVExif.h b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVExif.h
new file mode 100644
index 0000000..3e8adbd
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVExif.h
@@ -0,0 +1,43 @@
+/*
+ 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.
+ */
+
+#ifndef CordovaLib_ExifData_h
+#define CordovaLib_ExifData_h
+
+// exif data types
+typedef enum exifDataTypes {
+    EDT_UBYTE = 1,      // 8 bit unsigned integer
+    EDT_ASCII_STRING,   // 8 bits containing 7 bit ASCII code, null terminated
+    EDT_USHORT,         // 16 bit unsigned integer
+    EDT_ULONG,          // 32 bit unsigned integer
+    EDT_URATIONAL,      // 2 longs, first is numerator and second is denominator
+    EDT_SBYTE,
+    EDT_UNDEFINED,      // 8 bits
+    EDT_SSHORT,
+    EDT_SLONG,          // 32bit signed integer (2's complement)
+    EDT_SRATIONAL,      // 2 SLONGS, first long is numerator, second is denominator
+    EDT_SINGLEFLOAT,
+    EDT_DOUBLEFLOAT
+} ExifDataTypes;
+
+// maps integer code for exif data types to width in bytes
+static const int DataTypeToWidth[] = {1,1,2,4,8,1,1,2,4,8,4,8};
+
+static const int RECURSE_HORIZON = 8;
+#endif
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.h b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.h
new file mode 100644
index 0000000..3b43ef0
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.h
@@ -0,0 +1,62 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface CDVJpegHeaderWriter : NSObject {
+    NSDictionary * SubIFDTagFormatDict;
+    NSDictionary * IFD0TagFormatDict;
+}
+
+- (NSData*) spliceExifBlockIntoJpeg: (NSData*) jpegdata
+                      withExifBlock: (NSString*) exifstr;
+- (NSString*) createExifAPP1 : (NSDictionary*) datadict;
+- (NSString*) formattedHexStringFromDecimalNumber: (NSNumber*) numb 
+                                       withPlaces: (NSNumber*) width;
+- (NSString*) formatNumberWithLeadingZeroes: (NSNumber*) numb 
+                                 withPlaces: (NSNumber*) places;
+- (NSString*) decimalToUnsignedRational: (NSNumber*) numb
+                    withResultNumerator: (NSNumber**) numerator
+                  withResultDenominator: (NSNumber**) denominator;
+- (void) continuedFraction: (double) val
+          withFractionList: (NSMutableArray*) fractionlist 
+               withHorizon: (int) horizon;
+//- (void) expandContinuedFraction: (NSArray*) fractionlist;
+- (void) splitDouble: (double) val 
+         withIntComponent: (int*) rightside 
+         withFloatRemainder: (double*) leftside;
+- (NSString*) formatRationalWithNumerator: (NSNumber*) numerator
+                          withDenominator: (NSNumber*) denominator
+                               asSigned: (Boolean) signedFlag;
+- (NSString*) hexStringFromData : (NSData*) data;
+- (NSNumber*) numericFromHexString : (NSString *) hexstring;
+
+/*
+- (void) readExifMetaData : (NSData*) imgdata;
+- (void) spliceImageData : (NSData*) imgdata withExifData: (NSDictionary*) exifdata;
+- (void) locateExifMetaData : (NSData*) imgdata;
+- (NSString*) createExifAPP1 : (NSDictionary*) datadict;
+- (void) createExifDataString : (NSDictionary*) datadict;
+- (NSString*) createDataElement : (NSString*) element
+              withElementData: (NSString*) data
+              withExternalDataBlock: (NSDictionary*) memblock;
+- (NSString*) hexStringFromData : (NSData*) data;
+- (NSNumber*) numericFromHexString : (NSString *) hexstring;
+*/
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.m b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.m
new file mode 100644
index 0000000..4d3ea24
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/CDVJpegHeaderWriter.m
@@ -0,0 +1,547 @@
+/*
+ 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.
+ */
+
+#import "CDVJpegHeaderWriter.h"
+#include "CDVExif.h"
+
+/* macros for tag info shorthand:
+   tagno        : tag number
+   typecode     : data type
+   components   : number of components
+   appendString (TAGINF_W_APPEND only) : string to append to data
+      Exif date data format include an extra 0x00 to the end of the data
+ */
+#define TAGINF(tagno, typecode, components) [NSArray arrayWithObjects: tagno, typecode, components, nil]
+#define TAGINF_W_APPEND(tagno, typecode, components, appendString) [NSArray arrayWithObjects: tagno, typecode, components, appendString, nil]
+
+const uint mJpegId = 0xffd8; // JPEG format marker
+const uint mExifMarker = 0xffe1; // APP1 jpeg header marker
+const uint mExif = 0x45786966; // ASCII 'Exif', first characters of valid exif header after size
+const uint mMotorallaByteAlign = 0x4d4d; // 'MM', motorola byte align, msb first or 'sane'
+const uint mIntelByteAlgin = 0x4949; // 'II', Intel byte align, lsb first or 'batshit crazy reverso world'
+const uint mTiffLength = 0x2a; // after byte align bits, next to bits are 0x002a(MM) or 0x2a00(II), tiff version number
+
+
+@implementation CDVJpegHeaderWriter
+
+- (id) init {    
+    self = [super init];
+    // supported tags for exif IFD
+    IFD0TagFormatDict = [[NSDictionary alloc] initWithObjectsAndKeys:
+                  //      TAGINF(@"010e", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"ImageDescription",
+                        TAGINF_W_APPEND(@"0132", [NSNumber numberWithInt:EDT_ASCII_STRING], @20, @"00"), @"DateTime",
+                        TAGINF(@"010f", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Make",
+                        TAGINF(@"0110", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Model",
+                        TAGINF(@"0131", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Software",
+                        TAGINF(@"011a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"XResolution",
+                        TAGINF(@"011b", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"YResolution",
+                        // currently supplied outside of Exif data block by UIImagePickerControllerMediaMetadata, this is set manually in CDVCamera.m
+    /*                    TAGINF(@"0112", [NSNumber numberWithInt:EDT_USHORT], @1), @"Orientation",
+                       
+                        // rest of the tags are supported by exif spec, but are not specified by UIImagePickerControllerMediaMedadata
+                        // should camera hardware supply these values in future versions, or if they can be derived, ImageHeaderWriter will include them gracefully
+                        TAGINF(@"0128", [NSNumber numberWithInt:EDT_USHORT], @1), @"ResolutionUnit",
+                        TAGINF(@"013e", [NSNumber numberWithInt:EDT_URATIONAL], @2), @"WhitePoint",
+                        TAGINF(@"013f", [NSNumber numberWithInt:EDT_URATIONAL], @6), @"PrimaryChromaticities",
+                        TAGINF(@"0211", [NSNumber numberWithInt:EDT_URATIONAL], @3), @"YCbCrCoefficients",
+                        TAGINF(@"0213", [NSNumber numberWithInt:EDT_USHORT], @1), @"YCbCrPositioning",
+                        TAGINF(@"0214", [NSNumber numberWithInt:EDT_URATIONAL], @6), @"ReferenceBlackWhite",
+                        TAGINF(@"8298", [NSNumber numberWithInt:EDT_URATIONAL], @0), @"Copyright",
+                         
+                        // offset to exif subifd, we determine this dynamically based on the size of the main exif IFD
+                        TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1), @"ExifOffset",*/
+                        nil];
+
+
+    // supported tages for exif subIFD
+    SubIFDTagFormatDict = [[NSDictionary alloc] initWithObjectsAndKeys:
+                           //TAGINF(@"9000", [NSNumber numberWithInt:], @), @"ExifVersion",
+                           //TAGINF(@"9202",[NSNumber numberWithInt:EDT_URATIONAL],@1), @"ApertureValue",
+                           //TAGINF(@"9203",[NSNumber numberWithInt:EDT_SRATIONAL],@1), @"BrightnessValue",
+                           TAGINF(@"a001",[NSNumber numberWithInt:EDT_USHORT],@1), @"ColorSpace",
+                           TAGINF_W_APPEND(@"9004",[NSNumber numberWithInt:EDT_ASCII_STRING],@20,@"00"), @"DateTimeDigitized",
+                           TAGINF_W_APPEND(@"9003",[NSNumber numberWithInt:EDT_ASCII_STRING],@20,@"00"), @"DateTimeOriginal",
+                           TAGINF(@"a402", [NSNumber numberWithInt:EDT_USHORT], @1), @"ExposureMode",
+                           TAGINF(@"8822", [NSNumber numberWithInt:EDT_USHORT], @1), @"ExposureProgram",
+                           //TAGINF(@"829a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"ExposureTime",
+                           //TAGINF(@"829d", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"FNumber",
+                           TAGINF(@"9209", [NSNumber numberWithInt:EDT_USHORT], @1), @"Flash",
+                           // FocalLengthIn35mmFilm
+                           TAGINF(@"a405", [NSNumber numberWithInt:EDT_USHORT], @1), @"FocalLenIn35mmFilm",
+                           //TAGINF(@"920a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"FocalLength",
+                           //TAGINF(@"8827", [NSNumber numberWithInt:EDT_USHORT], @2), @"ISOSpeedRatings",
+                           TAGINF(@"9207", [NSNumber numberWithInt:EDT_USHORT],@1), @"MeteringMode",
+                           // specific to compressed data
+                           TAGINF(@"a002", [NSNumber numberWithInt:EDT_ULONG],@1), @"PixelXDimension",
+                           TAGINF(@"a003", [NSNumber numberWithInt:EDT_ULONG],@1), @"PixelYDimension",
+                           // data type undefined, but this is a DSC camera, so value is always 1, treat as ushort
+                           TAGINF(@"a301", [NSNumber numberWithInt:EDT_USHORT],@1), @"SceneType",
+                           TAGINF(@"a217",[NSNumber numberWithInt:EDT_USHORT],@1), @"SensingMethod",
+                           //TAGINF(@"9201", [NSNumber numberWithInt:EDT_SRATIONAL], @1), @"ShutterSpeedValue",
+                           // specifies location of main subject in scene (x,y,wdith,height) expressed before rotation processing
+                           //TAGINF(@"9214", [NSNumber numberWithInt:EDT_USHORT], @4), @"SubjectArea",
+                           TAGINF(@"a403", [NSNumber numberWithInt:EDT_USHORT], @1), @"WhiteBalance",
+                           nil];
+    return self;
+}
+
+- (NSData*) spliceExifBlockIntoJpeg: (NSData*) jpegdata withExifBlock: (NSString*) exifstr {
+    
+    CDVJpegHeaderWriter * exifWriter = [[CDVJpegHeaderWriter alloc] init];
+    
+    NSMutableData * exifdata = [NSMutableData dataWithCapacity: [exifstr length]/2];
+    int idx;
+    for (idx = 0; idx+1 < [exifstr length]; idx+=2) {
+        NSRange range = NSMakeRange(idx, 2);
+        NSString* hexStr = [exifstr substringWithRange:range];
+        NSScanner* scanner = [NSScanner scannerWithString:hexStr];
+        unsigned int intValue;
+        [scanner scanHexInt:&intValue];
+        [exifdata appendBytes:&intValue length:1];
+    }
+    
+    NSMutableData * ddata = [NSMutableData dataWithCapacity: [jpegdata length]];
+    NSMakeRange(0,4);
+    int loc = 0;
+    bool done = false;
+    // read the jpeg data until we encounter the app1==0xFFE1 marker
+    while (loc+1 < [jpegdata length]) {
+        NSData * blag = [jpegdata subdataWithRange: NSMakeRange(loc,2)];
+        if( [[blag description] isEqualToString : @"<ffe1>"]) {
+            // read the APP1 block size bits
+            NSString * the = [exifWriter hexStringFromData:[jpegdata subdataWithRange: NSMakeRange(loc+2,2)]];
+            NSNumber * app1width = [exifWriter numericFromHexString:the];
+            //consume the original app1 block
+            [ddata appendData:exifdata];
+            // advance our loc marker past app1
+            loc += [app1width intValue] + 2;
+            done = true;
+        } else {
+            if(!done) {
+                [ddata appendData:blag];
+                loc += 2;
+            } else {
+                break;
+            }
+        }
+    }
+    // copy the remaining data
+    [ddata appendData:[jpegdata subdataWithRange: NSMakeRange(loc,[jpegdata length]-loc)]];
+    return ddata;
+}
+
+
+
+/**
+ * Create the Exif data block as a hex string
+ *   jpeg uses Application Markers (APP's) as markers for application data
+ *   APP1 is the application marker reserved for exif data
+ *
+ *   (NSDictionary*) datadict - with subdictionaries marked '{TIFF}' and '{EXIF}' as returned by imagePickerController with a valid
+ *                              didFinishPickingMediaWithInfo data dict, under key @"UIImagePickerControllerMediaMetadata"
+ *
+ *   the following constructs a hex string to Exif specifications, and is therefore brittle
+ *   altering the order of arguments to the string constructors, modifying field sizes or formats,
+ *   and any other minor change will likely prevent the exif data from being read
+ */
+- (NSString*) createExifAPP1 : (NSDictionary*) datadict {
+    NSMutableString * app1; // holds finalized product
+    NSString * exifIFD; // exif information file directory
+    NSString * subExifIFD; // subexif information file directory
+    
+    // FFE1 is the hex APP1 marker code, and will allow client apps to read the data
+    NSString * app1marker = @"ffe1";
+    // SSSS size, to be determined
+    // EXIF ascii characters followed by 2bytes of zeros
+    NSString * exifmarker = @"457869660000";
+    // Tiff header: 4d4d is motorolla byte align (big endian), 002a is hex for 42
+    NSString * tiffheader = @"4d4d002a";
+    //first IFD offset from the Tiff header to IFD0. Since we are writing it, we know it's address 0x08
+    NSString * ifd0offset = @"00000008";
+    // current offset to next data area
+    int currentDataOffset = 0;
+    
+    //data labeled as TIFF in UIImagePickerControllerMediaMetaData is part of the EXIF IFD0 portion of APP1
+    exifIFD = [self createExifIFDFromDict: [datadict objectForKey:@"{TIFF}"] withFormatDict: IFD0TagFormatDict isIFD0:YES currentDataOffset:&currentDataOffset];
+
+    //data labeled as EXIF in UIImagePickerControllerMediaMetaData is part of the EXIF Sub IFD portion of APP1
+    subExifIFD = [self createExifIFDFromDict: [datadict objectForKey:@"{Exif}"] withFormatDict: SubIFDTagFormatDict isIFD0:NO currentDataOffset:&currentDataOffset];
+    /*
+    NSLog(@"SUB EXIF IFD %@  WITH SIZE: %d",exifIFD,[exifIFD length]);
+    
+    NSLog(@"SUB EXIF IFD %@  WITH SIZE: %d",subExifIFD,[subExifIFD length]);
+    */
+    // construct the complete app1 data block
+    app1 = [[NSMutableString alloc] initWithFormat: @"%@%04x%@%@%@%@%@",
+            app1marker,
+            (unsigned int)(16 + ([exifIFD length]/2) + ([subExifIFD length]/2)) /*16+[exifIFD length]/2*/,
+            exifmarker,
+            tiffheader,
+            ifd0offset,
+            exifIFD,
+            subExifIFD];
+     
+    return app1;
+}
+
+// returns hex string representing a valid exif information file directory constructed from the datadict and formatdict
+- (NSString*) createExifIFDFromDict : (NSDictionary*) datadict
+                     withFormatDict : (NSDictionary*) formatdict
+                             isIFD0 : (BOOL) ifd0flag
+                  currentDataOffset : (int*) dataoffset {
+    NSArray * datakeys = [datadict allKeys]; // all known data keys
+    NSArray * knownkeys = [formatdict  allKeys]; // only keys in knowkeys are considered for entry in this IFD
+    NSMutableArray * ifdblock = [[NSMutableArray alloc] initWithCapacity: [datadict count]]; // all ifd entries
+    NSMutableArray * ifddatablock = [[NSMutableArray alloc] initWithCapacity: [datadict count]]; // data block entries
+ //   ifd0flag = NO; // ifd0 requires a special flag and has offset to next ifd appended to end
+    
+    // iterate through known provided data keys
+    for (int i = 0; i < [datakeys count]; i++) {
+        NSString * key = [datakeys objectAtIndex:i];
+        // don't muck about with unknown keys
+        if ([knownkeys indexOfObject: key] != NSNotFound) {
+            // create new IFD entry
+            NSString * entry = [self  createIFDElement: key
+                                            withFormat: [formatdict objectForKey:key]
+                                      withElementData: [datadict objectForKey:key]];
+            // create the IFD entry's data block
+            NSString * data = [self createIFDElementDataWithFormat: [formatdict objectForKey:key]
+                                                   withData: [datadict objectForKey:key]];
+            if (entry) {
+                [ifdblock addObject:entry];
+                if(!data) {
+                    [ifdblock addObject:@""];
+                } else {
+                    [ifddatablock addObject:data];
+                }
+            }
+        }
+    }
+    
+    NSMutableString * exifstr = [[NSMutableString alloc] initWithCapacity: [ifdblock count] * 24];
+    NSMutableString * dbstr = [[NSMutableString alloc] initWithCapacity: 100];
+    
+    int addr=*dataoffset; // current offset/address in datablock
+    if (ifd0flag) {
+        // calculate offset to datablock based on ifd file entry count
+        addr += 14+(12*([ifddatablock count]+1)); // +1 for tag 0x8769, exifsubifd offset
+    } else {
+        // current offset + numSubIFDs (2-bytes) + 12*numSubIFDs + endMarker (4-bytes)
+        addr += 2+(12*[ifddatablock count])+4;
+    }
+    
+    for (int i = 0; i < [ifdblock count]; i++) {
+        NSString * entry = [ifdblock objectAtIndex:i];
+        NSString * data = [ifddatablock objectAtIndex:i];
+        
+        // check if the data fits into 4 bytes
+        if( [data length] <= 8) {
+            // concatenate the entry and the (4byte) data entry into the final IFD entry and append to exif ifd string
+            [exifstr appendFormat : @"%@%@", entry, data];
+        } else {
+            [exifstr appendFormat : @"%@%08x", entry, addr];
+            [dbstr appendFormat: @"%@", data];
+            addr+= [data length] / 2;
+            /*
+            NSLog(@"=====data-length[%i]=======",[data length]);
+            NSLog(@"addr-offset[%i]",addr);
+            NSLog(@"entry[%@]",entry);
+            NSLog(@"data[%@]",data);
+             */
+        }
+    }
+    
+    // calculate IFD0 terminal offset tags, currently ExifSubIFD
+    unsigned int entrycount = (unsigned int)[ifdblock count];
+    if (ifd0flag) {
+        // 18 accounts for 8769's width + offset to next ifd, 8 accounts for start of header
+        NSNumber * offset = [NSNumber numberWithUnsignedInteger:[exifstr length] / 2 + [dbstr length] / 2 + 18+8];
+        
+        [self appendExifOffsetTagTo: exifstr
+                        withOffset : offset];
+        entrycount++;
+    }
+    *dataoffset = addr;
+    return [[NSString alloc] initWithFormat: @"%04x%@%@%@",
+            entrycount,
+            exifstr,
+            @"00000000", // offset to next IFD, 0 since there is none
+            dbstr]; // lastly, the datablock
+}
+
+// Creates an exif formatted exif information file directory entry
+- (NSString*) createIFDElement: (NSString*) elementName withFormat: (NSArray*) formtemplate withElementData: (NSString*) data  {
+    //NSArray * fielddata = [formatdict objectForKey: elementName];// format data of desired field
+    if (formtemplate) {
+        // format string @"%@%@%@%@", tag number, data format, components, value
+        NSNumber * dataformat = [formtemplate objectAtIndex:1];
+        NSNumber * components = [formtemplate objectAtIndex:2];
+        if([components intValue] == 0) {
+            components = [NSNumber numberWithUnsignedInteger:[data length] * DataTypeToWidth[[dataformat intValue]-1]];
+        }
+
+        return [[NSString alloc] initWithFormat: @"%@%@%08x",
+                                                [formtemplate objectAtIndex:0], // the field code
+                                                [self formatNumberWithLeadingZeroes: dataformat withPlaces: @4], // the data type code
+                                                [components intValue]]; // number of components
+    }
+    return NULL;
+}
+
+/**
+ * appends exif IFD0 tag 8769 "ExifOffset" to the string provided
+ * (NSMutableString*) str - string you wish to append the 8769 tag to: APP1 or IFD0 hex data string 
+ *  //  TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1), @"ExifOffset",
+ */
+- (void) appendExifOffsetTagTo: (NSMutableString*) str withOffset : (NSNumber*) offset {
+    NSArray * format = TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1);
+    
+    NSString * entry = [self  createIFDElement: @"ExifOffset"
+                                withFormat: format
+                               withElementData: [offset stringValue]];
+    
+    NSString * data = [self createIFDElementDataWithFormat: format
+                                                  withData: [offset stringValue]];
+    [str appendFormat:@"%@%@", entry, data];
+}
+
+// formats the Information File Directory Data to exif format
+- (NSString*) createIFDElementDataWithFormat: (NSArray*) dataformat withData: (NSString*) data {
+    NSMutableString * datastr = nil;
+    NSNumber * tmp = nil;
+    NSNumber * formatcode = [dataformat objectAtIndex:1];
+    NSUInteger formatItemsCount = [dataformat count];
+    NSNumber * num = @0;
+    NSNumber * denom = @0;
+    
+    switch ([formatcode intValue]) {
+        case EDT_UBYTE:
+            break;
+        case EDT_ASCII_STRING:
+            datastr = [[NSMutableString alloc] init];
+            for (int i = 0; i < [data length]; i++) {
+                [datastr appendFormat:@"%02x",[data characterAtIndex:i]];
+            }
+            if (formatItemsCount > 3) {
+                // We have additional data to append.
+                // currently used by Date format to append final 0x00 but can be used by other data types as well in the future
+                [datastr appendString:[dataformat objectAtIndex:3]];
+            }
+            if ([datastr length] < 8) {
+                NSString * format = [NSString stringWithFormat:@"%%0%dd", (int)(8 - [datastr length])];
+                [datastr appendFormat:format,0];
+            }
+            return datastr;
+        case EDT_USHORT:
+            return [[NSString alloc] initWithFormat : @"%@%@",
+                    [self formattedHexStringFromDecimalNumber: [NSNumber numberWithInt: [data intValue]] withPlaces: @4],
+                    @"0000"];
+        case EDT_ULONG:
+            tmp = [NSNumber numberWithUnsignedLong:[data intValue]];
+            return [NSString stringWithFormat : @"%@",
+                    [self formattedHexStringFromDecimalNumber: tmp withPlaces: @8]];
+        case EDT_URATIONAL:
+            return [self decimalToUnsignedRational: [NSNumber numberWithDouble:[data doubleValue]]
+                               withResultNumerator: &num
+                             withResultDenominator: &denom];
+        case EDT_SBYTE:
+            
+            break;
+        case EDT_UNDEFINED:
+            break;     // 8 bits
+        case EDT_SSHORT:
+            break;
+        case EDT_SLONG:
+            break;          // 32bit signed integer (2's complement)
+        case EDT_SRATIONAL:
+            break;     // 2 SLONGS, first long is numerator, second is denominator
+        case EDT_SINGLEFLOAT:
+            break;
+        case EDT_DOUBLEFLOAT:
+            break;
+    }
+    return datastr;
+}
+
+//======================================================================================================================
+// Utility Methods
+//======================================================================================================================
+
+// creates a formatted little endian hex string from a number and width specifier
+- (NSString*) formattedHexStringFromDecimalNumber: (NSNumber*) numb withPlaces: (NSNumber*) width {
+    NSMutableString * str = [[NSMutableString alloc] initWithCapacity:[width intValue]];
+    NSString * formatstr = [[NSString alloc] initWithFormat: @"%%%@%dx", @"0", [width intValue]];
+    [str appendFormat:formatstr, [numb intValue]];
+    return str;
+}
+
+// format number as string with leading 0's
+- (NSString*) formatNumberWithLeadingZeroes: (NSNumber *) numb withPlaces: (NSNumber *) places { 
+    NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
+    NSString *formatstr = [@"" stringByPaddingToLength:[places unsignedIntegerValue] withString:@"0" startingAtIndex:0];
+    [formatter setPositiveFormat:formatstr];
+    return [formatter stringFromNumber:numb];
+}
+
+// approximate a decimal with a rational by method of continued fraction
+// can be collasped into decimalToUnsignedRational after testing
+- (void) decimalToRational: (NSNumber *) numb
+       withResultNumerator: (NSNumber**) numerator
+     withResultDenominator: (NSNumber**) denominator {
+    NSMutableArray * fractionlist = [[NSMutableArray alloc] initWithCapacity:8];
+    
+    [self continuedFraction: [numb doubleValue]
+           withFractionList: fractionlist
+                withHorizon: 8];
+    
+    // simplify complex fraction represented by partial fraction list
+    [self expandContinuedFraction: fractionlist
+              withResultNumerator: numerator
+            withResultDenominator: denominator];
+
+}
+
+// approximate a decimal with an unsigned rational by method of continued fraction
+- (NSString*) decimalToUnsignedRational: (NSNumber *) numb
+                          withResultNumerator: (NSNumber**) numerator
+                        withResultDenominator: (NSNumber**) denominator {
+    NSMutableArray * fractionlist = [[NSMutableArray alloc] initWithCapacity:8];
+    
+    // generate partial fraction list
+    [self continuedFraction: [numb doubleValue]
+           withFractionList: fractionlist
+                withHorizon: 8];
+    
+    // simplify complex fraction represented by partial fraction list
+    [self expandContinuedFraction: fractionlist
+              withResultNumerator: numerator
+            withResultDenominator: denominator];
+    
+    return [self formatFractionList: fractionlist];
+}
+
+// recursive implementation of decimal approximation by continued fraction
+- (void) continuedFraction: (double) val
+          withFractionList: (NSMutableArray*) fractionlist
+               withHorizon: (int) horizon {
+    int whole;
+    double remainder;
+    // 1. split term
+    [self splitDouble: val withIntComponent: &whole withFloatRemainder: &remainder];
+    [fractionlist addObject: [NSNumber numberWithInt:whole]];
+    
+    // 2. calculate reciprocal of remainder
+    if (!remainder) return; // early exit, exact fraction found, avoids recip/0
+    double recip = 1 / remainder;
+
+    // 3. exit condition
+    if ([fractionlist count] > horizon) {
+        return;
+    }
+    
+    // 4. recurse
+    [self continuedFraction:recip withFractionList: fractionlist withHorizon: horizon];
+    
+}
+
+// expand continued fraction list, creating a single level rational approximation
+-(void) expandContinuedFraction: (NSArray*) fractionlist
+                  withResultNumerator: (NSNumber**) numerator
+                withResultDenominator: (NSNumber**) denominator {
+    NSUInteger i = 0;
+    int den = 0;
+    int num = 0;
+    if ([fractionlist count] == 1) {
+        *numerator = [NSNumber numberWithInt:[[fractionlist objectAtIndex:0] intValue]];
+        *denominator = @1;
+        return;
+    }
+    
+    //begin at the end of the list
+    i = [fractionlist count] - 1;
+    num = 1;
+    den = [[fractionlist objectAtIndex:i] intValue];
+    
+    while (i > 0) {
+        int t = [[fractionlist objectAtIndex: i-1] intValue];
+        num = t * den + num;
+        if (i==1) {
+            break;
+        } else {
+            t = num;
+            num = den;
+            den = t;
+        }
+        i--;
+    }
+    // set result parameters values
+    *numerator = [NSNumber numberWithInt: num];
+    *denominator = [NSNumber numberWithInt: den];
+}
+
+// formats expanded fraction list to string matching exif specification
+- (NSString*) formatFractionList: (NSArray *) fractionlist {
+    NSMutableString * str = [[NSMutableString alloc] initWithCapacity:16];
+    
+    if ([fractionlist count] == 1){
+        [str appendFormat: @"%08x00000001", [[fractionlist objectAtIndex:0] intValue]];
+    }
+    return str;
+}
+
+// format rational as
+- (NSString*) formatRationalWithNumerator: (NSNumber*) numerator withDenominator: (NSNumber*) denominator asSigned: (Boolean) signedFlag {
+    NSMutableString * str = [[NSMutableString alloc] initWithCapacity:16];
+    if (signedFlag) {
+        long num = [numerator longValue];
+        long den = [denominator longValue];
+        [str appendFormat: @"%08lx%08lx", num >= 0 ? num : ~ABS(num) + 1, num >= 0 ? den : ~ABS(den) + 1];
+    } else {
+        [str appendFormat: @"%08lx%08lx", [numerator unsignedLongValue], [denominator unsignedLongValue]];
+    }
+    return str;
+}
+
+// split a floating point number into two integer values representing the left and right side of the decimal
+- (void) splitDouble: (double) val withIntComponent: (int*) rightside withFloatRemainder: (double*) leftside {
+    *rightside = val; // convert numb to int representation, which truncates the decimal portion
+    *leftside = val - *rightside;
+}
+
+
+//
+- (NSString*) hexStringFromData : (NSData*) data {
+    //overflow detection
+    const unsigned char *dataBuffer = [data bytes];
+    return [[NSString alloc] initWithFormat: @"%02x%02x",
+            (unsigned char)dataBuffer[0],
+            (unsigned char)dataBuffer[1]];
+}
+
+// convert a hex string to a number
+- (NSNumber*) numericFromHexString : (NSString *) hexstring {
+    NSScanner * scan = NULL;
+    unsigned int numbuf= 0;
+    
+    scan = [NSScanner scannerWithString:hexstring];
+    [scan scanHexInt:&numbuf];
+    return [NSNumber numberWithInt:numbuf];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.h b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.h
new file mode 100644
index 0000000..31bc42f
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.h
@@ -0,0 +1,29 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;
+- (UIImage*)imageCorrectedForCaptureOrientation;
+- (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation;
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize;
+
+@end
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.m b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.m
new file mode 100644
index 0000000..a66a5d8
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-camera/UIImage+CropScaleOrientation.m
@@ -0,0 +1,175 @@
+/*
+ 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.
+ */
+
+#import "UIImage+CropScaleOrientation.h"
+
+@implementation UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGFloat scaledWidth = targetWidth;
+    CGFloat scaledHeight = targetHeight;
+    CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        if (widthFactor > heightFactor) {
+            scaleFactor = widthFactor; // scale to fit height
+        } else {
+            scaleFactor = heightFactor; // scale to fit width
+        }
+        scaledWidth = width * scaleFactor;
+        scaledHeight = height * scaleFactor;
+        
+        // center the image
+        if (widthFactor > heightFactor) {
+            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
+        } else if (widthFactor < heightFactor) {
+            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
+        }
+    }
+    
+    UIGraphicsBeginImageContext(targetSize); // this will crop
+    
+    CGRect thumbnailRect = CGRectZero;
+    thumbnailRect.origin = thumbnailPoint;
+    thumbnailRect.size.width = scaledWidth;
+    thumbnailRect.size.height = scaledHeight;
+    
+    [sourceImage drawInRect:thumbnailRect];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation
+{
+    float rotation_radians = 0;
+    bool perpendicular = false;
+    
+    switch (imageOrientation) {
+        case UIImageOrientationUp :
+            rotation_radians = 0.0;
+            break;
+            
+        case UIImageOrientationDown:
+            rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
+            break;
+            
+        case UIImageOrientationRight:
+            rotation_radians = M_PI_2;
+            perpendicular = true;
+            break;
+            
+        case UIImageOrientationLeft:
+            rotation_radians = -M_PI_2;
+            perpendicular = true;
+            break;
+            
+        default:
+            break;
+    }
+    
+    UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    // Rotate around the center point
+    CGContextTranslateCTM(context, self.size.width / 2, self.size.height / 2);
+    CGContextRotateCTM(context, rotation_radians);
+    
+    CGContextScaleCTM(context, 1.0, -1.0);
+    float width = perpendicular ? self.size.height : self.size.width;
+    float height = perpendicular ? self.size.width : self.size.height;
+    CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [self CGImage]);
+    
+    // Move the origin back since the rotation might've change it (if its 90 degrees)
+    if (perpendicular) {
+        CGContextTranslateCTM(context, -self.size.height / 2, -self.size.width / 2);
+    }
+    
+    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageCorrectedForCaptureOrientation
+{
+    return [self imageCorrectedForCaptureOrientation:[self imageOrientation]];
+}
+
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGSize scaledSize = targetSize;
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
+        if (widthFactor > heightFactor) {
+            scaleFactor = heightFactor; // scale to fit height
+        } else {
+            scaleFactor = widthFactor; // scale to fit width
+        }
+        scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
+    }
+    
+    // If the pixels are floats, it causes a white line in iOS8 and probably other versions too
+    scaledSize.width = (int)scaledSize.width;
+    scaledSize.height = (int)scaledSize.height;
+    
+    UIGraphicsBeginImageContext(scaledSize); // this will resize
+    
+    [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.h b/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.h
new file mode 100644
index 0000000..a146d88
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.h
@@ -0,0 +1,30 @@
+/*
+ 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import <Cordova/CDVPlugin.h>
+
+@interface CDVDevice : CDVPlugin
+{}
+
++ (NSString*)cordovaVersion;
+
+- (void)getDeviceInfo:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.m b/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.m
new file mode 100644
index 0000000..4d75a57
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-device/CDVDevice.m
@@ -0,0 +1,112 @@
+/*
+ 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.
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include "TargetConditionals.h"
+
+#import <Cordova/CDV.h>
+#import "CDVDevice.h"
+
+@implementation UIDevice (ModelVersion)
+
+- (NSString*)modelVersion
+{
+    size_t size;
+
+    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+    char* machine = malloc(size);
+    sysctlbyname("hw.machine", machine, &size, NULL, 0);
+    NSString* platform = [NSString stringWithUTF8String:machine];
+    free(machine);
+
+    return platform;
+}
+
+@end
+
+@interface CDVDevice () {}
+@end
+
+@implementation CDVDevice
+
+- (NSString*)uniqueAppInstanceIdentifier:(UIDevice*)device
+{
+    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+    static NSString* UUID_KEY = @"CDVUUID";
+    
+    // Check user defaults first to maintain backwards compaitibility with previous versions
+    // which didn't user identifierForVendor
+    NSString* app_uuid = [userDefaults stringForKey:UUID_KEY];
+    if (app_uuid == nil) {
+        if ([device respondsToSelector:@selector(identifierForVendor)]) {
+            app_uuid = [[device identifierForVendor] UUIDString];
+        } else {
+            CFUUIDRef uuid = CFUUIDCreate(NULL);
+            app_uuid = (__bridge_transfer NSString *)CFUUIDCreateString(NULL, uuid);
+            CFRelease(uuid);
+        }
+
+        [userDefaults setObject:app_uuid forKey:UUID_KEY];
+        [userDefaults synchronize];
+    }
+    
+    return app_uuid;
+}
+
+- (void)getDeviceInfo:(CDVInvokedUrlCommand*)command
+{
+    NSDictionary* deviceProperties = [self deviceProperties];
+    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:deviceProperties];
+
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (NSDictionary*)deviceProperties
+{
+    UIDevice* device = [UIDevice currentDevice];
+
+    return @{
+             @"manufacturer": @"Apple",
+             @"model": [device modelVersion],
+             @"platform": @"iOS",
+             @"version": [device systemVersion],
+             @"uuid": [self uniqueAppInstanceIdentifier:device],
+             @"cordova": [[self class] cordovaVersion],
+             @"isVirtual": @([self isVirtual])
+             };
+}
+
++ (NSString*)cordovaVersion
+{
+    return CDV_VERSION;
+}
+
+- (BOOL)isVirtual
+{
+    #if TARGET_OS_SIMULATOR
+        return true;
+    #elif TARGET_IPHONE_SIMULATOR
+        return true;
+    #else
+        return false;
+    #endif
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-disable-ios11-statusbar/DisableStatusbar.m b/platforms/ios/dlapp/Plugins/cordova-plugin-disable-ios11-statusbar/DisableStatusbar.m
new file mode 100644
index 0000000..f0f5763
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-disable-ios11-statusbar/DisableStatusbar.m
@@ -0,0 +1,18 @@
+#import <Cordova/CDV.h>
+
+@interface DisableStatusbar : CDVPlugin
+
+@end
+
+@implementation DisableStatusbar
+
+- (void)pluginInitialize
+{
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+    if (@available(iOS 11.0, *)) {
+        [self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
+    }
+#endif
+}
+
+@end
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.h b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.h
new file mode 100644
index 0000000..e09e225
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.h
@@ -0,0 +1,30 @@
+/*
+ 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.
+ */
+
+#import "CDVFile.h"
+
+extern NSString* const kCDVAssetsLibraryPrefix;
+extern NSString* const kCDVAssetsLibraryScheme;
+
+@interface CDVAssetLibraryFilesystem : NSObject<CDVFileSystem> {
+}
+
+- (id) initWithName:(NSString *)name;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.m b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.m
new file mode 100644
index 0000000..8486b7b
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVAssetLibraryFilesystem.m
@@ -0,0 +1,253 @@
+/*
+ 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.
+ */
+
+#import "CDVFile.h"
+#import "CDVAssetLibraryFilesystem.h"
+#import <Cordova/CDV.h>
+#import <AssetsLibrary/ALAsset.h>
+#import <AssetsLibrary/ALAssetRepresentation.h>
+#import <AssetsLibrary/ALAssetsLibrary.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+
+NSString* const kCDVAssetsLibraryPrefix = @"assets-library://";
+NSString* const kCDVAssetsLibraryScheme = @"assets-library";
+
+@implementation CDVAssetLibraryFilesystem
+@synthesize name=_name, urlTransformer;
+
+
+/*
+ The CDVAssetLibraryFilesystem works with resources which are identified
+ by iOS as
+   asset-library://<path>
+ and represents them internally as URLs of the form
+   cdvfile://localhost/assets-library/<path>
+ */
+
+- (NSURL *)assetLibraryURLForLocalURL:(CDVFilesystemURL *)url
+{
+    if ([url.url.scheme isEqualToString:kCDVFilesystemURLPrefix]) {
+        NSString *path = [[url.url absoluteString] substringFromIndex:[@"cdvfile://localhost/assets-library" length]];
+        return [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@", path]];
+    }
+    return url.url;
+}
+
+- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
+{
+    NSDictionary* entry = [self makeEntryForLocalURL:url];
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
+}
+
+- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
+    return [self makeEntryForPath:url.fullPath isDirectory:NO];
+}
+
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
+{
+    NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
+    NSString* lastPart = [fullPath lastPathComponent];
+    if (isDir && ![fullPath hasSuffix:@"/"]) {
+        fullPath = [fullPath stringByAppendingString:@"/"];
+    }
+    [dirEntry setObject:[NSNumber numberWithBool:!isDir]  forKey:@"isFile"];
+    [dirEntry setObject:[NSNumber numberWithBool:isDir]  forKey:@"isDirectory"];
+    [dirEntry setObject:fullPath forKey:@"fullPath"];
+    [dirEntry setObject:lastPart forKey:@"name"];
+    [dirEntry setObject:self.name forKey: @"filesystemName"];
+
+    NSURL* nativeURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@",fullPath]];
+    if (self.urlTransformer) {
+        nativeURL = self.urlTransformer(nativeURL);
+    }
+    dirEntry[@"nativeURL"] = [nativeURL absoluteString];
+
+    return dirEntry;
+}
+
+/* helper function to get the mimeType from the file extension
+ * IN:
+ *	NSString* fullPath - filename (may include path)
+ * OUT:
+ *	NSString* the mime type as type/subtype.  nil if not able to determine
+ */
++ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
+{
+    NSString* mimeType = nil;
+
+    if (fullPath) {
+        CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
+        if (typeId) {
+            mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
+            if (!mimeType) {
+                // special case for m4a
+                if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
+                    mimeType = @"audio/mp4";
+                } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
+                    mimeType = @"audio/wav";
+                } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
+                    mimeType = @"text/css";
+                }
+            }
+            CFRelease(typeId);
+        }
+    }
+    return mimeType;
+}
+
+- (id)initWithName:(NSString *)name
+{
+    if (self) {
+        self.name = name;
+    }
+    return self;
+}
+
+- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
+{
+    // return unsupported result for assets-library URLs
+   return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."];
+}
+
+- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
+{
+    // we don't (yet?) support getting the parent of an asset
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR];
+}
+
+- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
+{
+    // setMetadata doesn't make sense for asset library files
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
+}
+
+- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
+{
+    // return error for assets-library URLs
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
+}
+
+- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
+{
+    // return error for assets-library URLs
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."];
+}
+
+- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
+{
+    // return unsupported result for assets-library URLs
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."];
+}
+
+- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
+{
+    // assets-library files can't be truncated
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
+}
+
+- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
+{
+    // text can't be written into assets-library files
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
+}
+
+- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
+{
+    // Copying to an assets library file is not doable, since we can't write it.
+    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
+    callback(result);
+}
+
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
+{
+    NSString *path = nil;
+    if ([[url.url scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
+        path = [url.url path];
+    } else {
+       path = url.fullPath;
+    }
+    if ([path hasSuffix:@"/"]) {
+      path = [path substringToIndex:([path length]-1)];
+    }
+    return path;
+}
+
+- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
+{
+    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
+        if (asset) {
+            // We have the asset!  Get the data and send it off.
+            ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+            NSUInteger size = (end > start) ? (end - start) : [assetRepresentation size];
+            Byte* buffer = (Byte*)malloc(size);
+            NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:start length:size error:nil];
+            NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+            NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
+
+            callback(data, MIMEType, NO_ERROR);
+        } else {
+            callback(nil, nil, NOT_FOUND_ERR);
+        }
+    };
+
+    ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
+        // Retrieving the asset failed for some reason.  Send the appropriate error.
+        NSLog(@"Error: %@", error);
+        callback(nil, nil, SECURITY_ERR);
+    };
+
+    ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+    [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
+}
+
+- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
+{
+    // In this case, we need to use an asynchronous method to retrieve the file.
+    // Because of this, we can't just assign to `result` and send it at the end of the method.
+    // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
+    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
+        if (asset) {
+            // We have the asset!  Populate the dictionary and send it off.
+            NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
+            ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+            [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[assetRepresentation size]] forKey:@"size"];
+            [fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
+            NSString* filename = [assetRepresentation filename];
+            [fileInfo setObject:filename forKey:@"name"];
+            [fileInfo setObject:[CDVAssetLibraryFilesystem getMimeTypeFromPath:filename] forKey:@"type"];
+            NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate];
+            NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000];
+            [fileInfo setObject:msDate forKey:@"lastModifiedDate"];
+
+            callback([CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]);
+        } else {
+            // We couldn't find the asset.  Send the appropriate error.
+            callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]);
+        }
+    };
+    ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
+        // Retrieving the asset failed for some reason.  Send the appropriate error.
+        callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]);
+    };
+
+    ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+    [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
+    return;
+}
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.h b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.h
new file mode 100644
index 0000000..987c66b
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.h
@@ -0,0 +1,157 @@
+/*
+ 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <Cordova/CDVPlugin.h>
+
+extern NSString* const kCDVAssetsLibraryPrefix;
+extern NSString* const kCDVFilesystemURLPrefix;
+
+enum CDVFileError {
+    NO_ERROR = 0,
+    NOT_FOUND_ERR = 1,
+    SECURITY_ERR = 2,
+    ABORT_ERR = 3,
+    NOT_READABLE_ERR = 4,
+    ENCODING_ERR = 5,
+    NO_MODIFICATION_ALLOWED_ERR = 6,
+    INVALID_STATE_ERR = 7,
+    SYNTAX_ERR = 8,
+    INVALID_MODIFICATION_ERR = 9,
+    QUOTA_EXCEEDED_ERR = 10,
+    TYPE_MISMATCH_ERR = 11,
+    PATH_EXISTS_ERR = 12
+};
+typedef int CDVFileError;
+
+@interface CDVFilesystemURL : NSObject  {
+    NSURL *_url;
+    NSString *_fileSystemName;
+    NSString *_fullPath;
+}
+
+- (id) initWithString:(NSString*)strURL;
+- (id) initWithURL:(NSURL*)URL;
++ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL;
++ (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL;
+
+- (NSString *)absoluteURL;
+
+@property (atomic) NSURL *url;
+@property (atomic) NSString *fileSystemName;
+@property (atomic) NSString *fullPath;
+
+@end
+
+@interface CDVFilesystemURLProtocol : NSURLProtocol
+@end
+
+@protocol CDVFileSystem
+- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url;
+- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options;
+- (CDVPluginResult *)getParentForURL:(CDVFilesystemURL *)localURI;
+- (CDVPluginResult *)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options;
+- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI;
+- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI;
+- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI;
+- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos;
+- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend;
+- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback;
+- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback;
+- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback;
+
+- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url;
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir;
+
+@property (nonatomic,strong) NSString *name;
+@property (nonatomic, copy) NSURL*(^urlTransformer)(NSURL*);
+
+@optional
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURI;
+- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path;
+
+@end
+
+@interface CDVFile : CDVPlugin {
+    NSString* rootDocsPath;
+    NSString* appDocsPath;
+    NSString* appLibraryPath;
+    NSString* appTempPath;
+
+    NSMutableArray* fileSystems_;
+    BOOL userHasAllowed;
+}
+
+- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath;
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir;
+- (NSDictionary *)makeEntryForURL:(NSURL *)URL;
+- (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath;
+
+- (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL;
+
+/* Native Registration API */
+- (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs;
+- (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName;
+
+/* Exec API */
+- (void)requestFileSystem:(CDVInvokedUrlCommand*)command;
+- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command;
+- (void)getDirectory:(CDVInvokedUrlCommand*)command;
+- (void)getFile:(CDVInvokedUrlCommand*)command;
+- (void)getParent:(CDVInvokedUrlCommand*)command;
+- (void)removeRecursively:(CDVInvokedUrlCommand*)command;
+- (void)remove:(CDVInvokedUrlCommand*)command;
+- (void)copyTo:(CDVInvokedUrlCommand*)command;
+- (void)moveTo:(CDVInvokedUrlCommand*)command;
+- (void)getFileMetadata:(CDVInvokedUrlCommand*)command;
+- (void)readEntries:(CDVInvokedUrlCommand*)command;
+- (void)readAsText:(CDVInvokedUrlCommand*)command;
+- (void)readAsDataURL:(CDVInvokedUrlCommand*)command;
+- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command;
+- (void)write:(CDVInvokedUrlCommand*)command;
+- (void)testFileExists:(CDVInvokedUrlCommand*)command;
+- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command;
+- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command;
+- (void)truncate:(CDVInvokedUrlCommand*)command;
+- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy;
+
+/* Compatibilty with older File API */
+- (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
+- (NSDictionary *)getDirectoryEntry:(NSString *)target isDirectory:(BOOL)bDirRequest;
+
+/* Conversion between filesystem paths and URLs */
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)URL;
+
+/* Internal methods for testing */
+- (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command;
+
+@property (nonatomic, strong) NSString* rootDocsPath;
+@property (nonatomic, strong) NSString* appDocsPath;
+@property (nonatomic, strong) NSString* appLibraryPath;
+@property (nonatomic, strong) NSString* appTempPath;
+@property (nonatomic, strong) NSString* persistentPath;
+@property (nonatomic, strong) NSString* temporaryPath;
+@property (nonatomic, strong) NSMutableArray* fileSystems;
+
+@property BOOL userHasAllowed;
+
+@end
+
+#define kW3FileTemporary @"temporary"
+#define kW3FilePersistent @"persistent"
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.m b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.m
new file mode 100644
index 0000000..59e7d64
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVFile.m
@@ -0,0 +1,1119 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDV.h>
+#import "CDVFile.h"
+#import "CDVLocalFilesystem.h"
+#import "CDVAssetLibraryFilesystem.h"
+#import <objc/message.h>
+
+static NSString* toBase64(NSData* data) {
+    SEL s1 = NSSelectorFromString(@"cdv_base64EncodedString");
+    SEL s2 = NSSelectorFromString(@"base64EncodedString");
+    SEL s3 = NSSelectorFromString(@"base64EncodedStringWithOptions:");
+    
+    if ([data respondsToSelector:s1]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s1];
+        return func(data, s1);
+    } else if ([data respondsToSelector:s2]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s2];
+        return func(data, s2);
+    } else if ([data respondsToSelector:s3]) {
+        NSString* (*func)(id, SEL, NSUInteger) = (void *)[data methodForSelector:s3];
+        return func(data, s3, 0);
+    } else {
+        return nil;
+    }
+}
+
+CDVFile *filePlugin = nil;
+
+extern NSString * const NSURLIsExcludedFromBackupKey __attribute__((weak_import));
+
+#ifndef __IPHONE_5_1
+    NSString* const NSURLIsExcludedFromBackupKey = @"NSURLIsExcludedFromBackupKey";
+#endif
+
+NSString* const kCDVFilesystemURLPrefix = @"cdvfile";
+
+@implementation CDVFilesystemURL
+@synthesize url=_url;
+@synthesize fileSystemName=_fileSystemName;
+@synthesize fullPath=_fullPath;
+
+- (id) initWithString:(NSString *)strURL
+{
+    if ( self = [super init] ) {
+        NSURL *decodedURL = [NSURL URLWithString:strURL];
+        return [self initWithURL:decodedURL];
+    }
+    return nil;
+}
+
+-(id) initWithURL:(NSURL *)URL
+{
+    if ( self = [super init] ) {
+        self.url = URL;
+        self.fileSystemName = [self filesystemNameForLocalURI:URL];
+        self.fullPath = [self fullPathForLocalURI:URL];
+    }
+    return self;
+}
+
+/*
+ * IN
+ *  NSString localURI
+ * OUT
+ *  NSString FileSystem Name for this URI, or nil if it is not recognized.
+ */
+- (NSString *)filesystemNameForLocalURI:(NSURL *)uri
+{
+    if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
+        NSArray *pathComponents = [uri pathComponents];
+        if (pathComponents != nil && pathComponents.count > 1) {
+            return [pathComponents objectAtIndex:1];
+        }
+    } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
+        return @"assets-library";
+    }
+    return nil;
+}
+
+/*
+ * IN
+ *  NSString localURI
+ * OUT
+ *  NSString fullPath component suitable for an Entry object.
+ * The incoming URI should be properly escaped. The returned fullPath is unescaped.
+ */
+- (NSString *)fullPathForLocalURI:(NSURL *)uri
+{
+    if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
+        NSString *path = [uri path];
+        if ([uri query]) {
+            path = [NSString stringWithFormat:@"%@?%@", path, [uri query]];
+        }
+        NSRange slashRange = [path rangeOfString:@"/" options:0 range:NSMakeRange(1, path.length-1)];
+        if (slashRange.location == NSNotFound) {
+            return @"";
+        }
+        return [path substringFromIndex:slashRange.location];
+    } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
+        return [[uri absoluteString] substringFromIndex:[kCDVAssetsLibraryScheme length]+2];
+    }
+    return nil;
+}
+
++ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL
+{
+    return [[CDVFilesystemURL alloc] initWithString:strURL];
+}
+
++ (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL
+{
+    return [[CDVFilesystemURL alloc] initWithURL:URL];
+}
+
+- (NSString *)absoluteURL
+{
+    return [NSString stringWithFormat:@"cdvfile://localhost/%@%@", self.fileSystemName, self.fullPath];
+}
+
+@end
+
+@implementation CDVFilesystemURLProtocol
+
++ (BOOL)canInitWithRequest:(NSURLRequest*)request
+{
+    NSURL* url = [request URL];
+    return [[url scheme] isEqualToString:kCDVFilesystemURLPrefix];
+}
+
++ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
+{
+    return request;
+}
+
++ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
+{
+    return [[[requestA URL] resourceSpecifier] isEqualToString:[[requestB URL] resourceSpecifier]];
+}
+
+- (void)startLoading
+{
+    CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithURL:[[self request] URL]];
+    NSObject<CDVFileSystem> *fs = [filePlugin filesystemForURL:url];
+    __weak CDVFilesystemURLProtocol* weakSelf = self;
+    
+    [fs readFileAtURL:url start:0 end:-1 callback:^void(NSData *data, NSString *mimetype, CDVFileError error) {
+        NSMutableDictionary* responseHeaders = [[NSMutableDictionary alloc] init];
+        responseHeaders[@"Cache-Control"] = @"no-cache";
+
+        if (!error) {
+            responseHeaders[@"Content-Type"] = mimetype;
+            NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:200 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
+            [[weakSelf client] URLProtocol:weakSelf didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+            [[weakSelf client] URLProtocol:weakSelf didLoadData:data];
+            [[weakSelf client] URLProtocolDidFinishLoading:weakSelf];
+        } else {
+            NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:404 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
+            [[weakSelf client] URLProtocol:weakSelf didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+            [[weakSelf client] URLProtocolDidFinishLoading:weakSelf];
+        }
+    }];
+}
+
+- (void)stopLoading
+{}
+
+- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
+                  willCacheResponse:(NSCachedURLResponse*)cachedResponse {
+    return nil;
+}
+
+@end
+
+
+@implementation CDVFile
+
+@synthesize rootDocsPath, appDocsPath, appLibraryPath, appTempPath, userHasAllowed, fileSystems=fileSystems_;
+
+- (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs {
+    __weak CDVFile* weakSelf = self;
+    SEL sel = NSSelectorFromString(@"urlTransformer");
+    // for backwards compatibility - we check if this property is there
+    // we create a wrapper block because the urlTransformer property
+    // on the commandDelegate might be set dynamically at a future time
+    // (and not dependent on plugin loading order)
+    if ([self.commandDelegate respondsToSelector:sel]) {
+        fs.urlTransformer = ^NSURL*(NSURL* urlToTransform) {
+            // grab the block from the commandDelegate
+            NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(weakSelf.commandDelegate, sel);
+            // if block is not null, we call it
+            if (urlTransformer) {
+                return urlTransformer(urlToTransform);
+            } else { // else we return the same url
+                return urlToTransform;
+            }
+        };
+    }
+    [fileSystems_ addObject:fs];
+}
+
+- (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName
+{
+    if (self.fileSystems != nil) {
+        for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
+            if ([fs.name isEqualToString:fsName]) {
+                return fs;
+            }
+        }
+    }
+    return nil;
+}
+
+- (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL {
+    if (localURL.fileSystemName == nil) return nil;
+    @try {
+        return [self fileSystemByName:localURL.fileSystemName];
+    }
+    @catch (NSException *e) {
+        return nil;
+    }
+}
+
+- (NSArray *)getExtraFileSystemsPreference:(UIViewController *)vc
+{
+    NSString *filesystemsStr = nil;
+    if([self.viewController isKindOfClass:[CDVViewController class]]) {
+        CDVViewController *vc = (CDVViewController *)self.viewController;
+        NSDictionary *settings = [vc settings];
+        filesystemsStr = [settings[@"iosextrafilesystems"] lowercaseString];
+    }
+    if (!filesystemsStr) {
+        filesystemsStr = @"library,library-nosync,documents,documents-nosync,cache,bundle,root";
+    }
+    return [filesystemsStr componentsSeparatedByString:@","];
+}
+
+- (void)makeNonSyncable:(NSString*)path {
+    [[NSFileManager defaultManager] createDirectoryAtPath:path
+              withIntermediateDirectories:YES
+                               attributes:nil
+                                    error:nil];
+    NSURL* url = [NSURL fileURLWithPath:path];
+    [url setResourceValue: [NSNumber numberWithBool: YES]
+                   forKey: NSURLIsExcludedFromBackupKey error:nil];
+
+}
+
+- (void)registerExtraFileSystems:(NSArray *)filesystems fromAvailableSet:(NSDictionary *)availableFileSystems
+{
+    NSMutableSet *installedFilesystems = [[NSMutableSet alloc] initWithCapacity:7];
+
+    /* Build non-syncable directories as necessary */
+    for (NSString *nonSyncFS in @[@"library-nosync", @"documents-nosync"]) {
+        if ([filesystems containsObject:nonSyncFS]) {
+            [self makeNonSyncable:availableFileSystems[nonSyncFS]];
+        }
+    }
+
+    /* Register filesystems in order */
+    for (NSString *fsName in filesystems) {
+        if (![installedFilesystems containsObject:fsName]) {
+            NSString *fsRoot = availableFileSystems[fsName];
+            if (fsRoot) {
+                [filePlugin registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:fsName root:fsRoot]];
+                [installedFilesystems addObject:fsName];
+            } else {
+                NSLog(@"Unrecognized extra filesystem identifier: %@", fsName);
+            }
+        }
+    }
+}
+
+- (NSDictionary *)getAvailableFileSystems
+{
+    NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+    return @{
+        @"library": libPath,
+        @"library-nosync": [libPath stringByAppendingPathComponent:@"NoCloud"],
+        @"documents": docPath,
+        @"documents-nosync": [docPath stringByAppendingPathComponent:@"NoCloud"],
+        @"cache": [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0],
+        @"bundle": [[NSBundle mainBundle] bundlePath],
+        @"root": @"/"
+    };
+}
+
+- (void)pluginInitialize
+{
+    filePlugin = self;
+    [NSURLProtocol registerClass:[CDVFilesystemURLProtocol class]];
+
+    fileSystems_ = [[NSMutableArray alloc] initWithCapacity:3];
+
+    // Get the Library directory path
+    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
+    self.appLibraryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"files"];
+
+    // Get the Temporary directory path
+    self.appTempPath = [NSTemporaryDirectory()stringByStandardizingPath];   // remove trailing slash from NSTemporaryDirectory()
+
+    // Get the Documents directory path
+    paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+    self.rootDocsPath = [paths objectAtIndex:0];
+    self.appDocsPath = [self.rootDocsPath stringByAppendingPathComponent:@"files"];
+
+
+    NSString *location = nil;
+    if([self.viewController isKindOfClass:[CDVViewController class]]) {
+        CDVViewController *vc = (CDVViewController *)self.viewController;
+        NSMutableDictionary *settings = vc.settings;
+        location = [[settings objectForKey:@"iospersistentfilelocation"] lowercaseString];
+    }
+    if (location == nil) {
+        // Compatibilty by default (if the config preference is not set, or
+        // if we're not embedded in a CDVViewController somehow.)
+        location = @"compatibility";
+    }
+
+    NSError *error;
+    if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appTempPath
+                                  withIntermediateDirectories:YES
+                                                   attributes:nil
+                                                        error:&error]) {
+        [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"temporary" root:self.appTempPath]];
+    } else {
+        NSLog(@"Unable to create temporary directory: %@", error);
+    }
+    if ([location isEqualToString:@"library"]) {
+        if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appLibraryPath
+                                      withIntermediateDirectories:YES
+                                                       attributes:nil
+                                                            error:&error]) {
+            [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.appLibraryPath]];
+        } else {
+            NSLog(@"Unable to create library directory: %@", error);
+        }
+    } else if ([location isEqualToString:@"compatibility"]) {
+        /*
+         *  Fall-back to compatibility mode -- this is the logic implemented in
+         *  earlier versions of this plugin, and should be maintained here so
+         *  that apps which were originally deployed with older versions of the
+         *  plugin can continue to provide access to files stored under those
+         *  versions.
+         */
+        [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.rootDocsPath]];
+    } else {
+        NSAssert(false,
+            @"File plugin configuration error: Please set iosPersistentFileLocation in config.xml to one of \"library\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
+    }
+    [self registerFilesystem:[[CDVAssetLibraryFilesystem alloc] initWithName:@"assets-library"]];
+
+    [self registerExtraFileSystems:[self getExtraFileSystemsPreference:self.viewController]
+                  fromAvailableSet:[self getAvailableFileSystems]];
+
+}
+
+- (CDVFilesystemURL *)fileSystemURLforArg:(NSString *)urlArg
+{
+    CDVFilesystemURL* ret = nil;
+    if ([urlArg hasPrefix:@"file://"]) {
+        /* This looks like a file url. Get the path, and see if any handlers recognize it. */
+        NSURL *fileURL = [NSURL URLWithString:urlArg];
+        NSURL *resolvedFileURL = [fileURL URLByResolvingSymlinksInPath];
+        NSString *path = [resolvedFileURL path];
+        ret = [self fileSystemURLforLocalPath:path];
+    } else {
+        ret = [CDVFilesystemURL fileSystemURLWithString:urlArg];
+    }
+    return ret;
+}
+
+- (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath
+{
+    CDVFilesystemURL *localURL = nil;
+    NSUInteger shortestFullPath = 0;
+
+    // Try all installed filesystems, in order. Return the most match url.
+    for (id object in self.fileSystems) {
+        if ([object respondsToSelector:@selector(URLforFilesystemPath:)]) {
+            CDVFilesystemURL *url = [object URLforFilesystemPath:localPath];
+            if (url){
+                // A shorter fullPath would imply that the filesystem is a better match for the local path
+                if (!localURL || ([[url fullPath] length] < shortestFullPath)) {
+                    localURL = url;
+                    shortestFullPath = [[url fullPath] length];
+                }
+            }
+        }
+    }
+    return localURL;
+}
+
+- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath
+{
+    NSFileManager* fMgr = [[NSFileManager alloc] init];
+
+    NSError* __autoreleasing pError = nil;
+
+    NSDictionary* pDict = [fMgr attributesOfFileSystemForPath:appPath error:&pError];
+    NSNumber* pNumAvail = (NSNumber*)[pDict objectForKey:NSFileSystemFreeSize];
+
+    return pNumAvail;
+}
+
+/* Request the File System info
+ *
+ * IN:
+ * arguments[0] - type (number as string)
+ *	TEMPORARY = 0, PERSISTENT = 1;
+ * arguments[1] - size
+ *
+ * OUT:
+ *	Dictionary representing FileSystem object
+ *		name - the human readable directory name
+ *		root = DirectoryEntry object
+ *			bool isDirectory
+ *			bool isFile
+ *			string name
+ *			string fullPath
+ *			fileSystem = FileSystem object - !! ignored because creates circular reference !!
+ */
+
+- (void)requestFileSystem:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    NSString* strType = [command argumentAtIndex:0];
+    unsigned long long size = [[command argumentAtIndex:1] longLongValue];
+
+    int type = [strType intValue];
+    CDVPluginResult* result = nil;
+
+    if (type >= self.fileSystems.count) {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
+        NSLog(@"No filesystem of type requested");
+    } else {
+        NSString* fullPath = @"/";
+        // check for avail space for size request
+        NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
+        // NSLog(@"Free space: %@", [NSString stringWithFormat:@"%qu", [ pNumAvail unsignedLongLongValue ]]);
+        if (pNumAvail && ([pNumAvail unsignedLongLongValue] < size)) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:QUOTA_EXCEEDED_ERR];
+        } else {
+            NSObject<CDVFileSystem> *rootFs = [self.fileSystems objectAtIndex:type];
+            if (rootFs == nil) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
+                NSLog(@"No filesystem of type requested");
+            } else {
+                NSMutableDictionary* fileSystem = [NSMutableDictionary dictionaryWithCapacity:2];
+                [fileSystem setObject:rootFs.name forKey:@"name"];
+                NSDictionary* dirEntry = [self makeEntryForPath:fullPath fileSystemName:rootFs.name isDirectory:YES];
+                [fileSystem setObject:dirEntry forKey:@"root"];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem];
+            }
+        }
+    }
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+
+- (void)requestAllFileSystems:(CDVInvokedUrlCommand*)command
+{
+    NSMutableArray* ret = [[NSMutableArray alloc] init];
+    for (NSObject<CDVFileSystem>* root in fileSystems_) {
+        [ret addObject:[self makeEntryForPath:@"/" fileSystemName:root.name isDirectory:YES]];
+    }
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:ret];
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+- (void)requestAllPaths:(CDVInvokedUrlCommand*)command
+{
+    NSString* libPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
+    NSString* libPathSync = [libPath stringByAppendingPathComponent:@"Cloud"];
+    NSString* libPathNoSync = [libPath stringByAppendingPathComponent:@"NoCloud"];
+    NSString* docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
+    NSString* storagePath = [libPath stringByDeletingLastPathComponent];
+    NSString* cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
+
+    // Create the directories if necessary.
+    [[NSFileManager defaultManager] createDirectoryAtPath:libPathSync withIntermediateDirectories:YES attributes:nil error:nil];
+    [[NSFileManager defaultManager] createDirectoryAtPath:libPathNoSync withIntermediateDirectories:YES attributes:nil error:nil];
+    // Mark NoSync as non-iCloud.
+    [[NSURL fileURLWithPath:libPathNoSync] setResourceValue: [NSNumber numberWithBool: YES]
+                                                     forKey: NSURLIsExcludedFromBackupKey error:nil];
+
+    NSDictionary* ret = @{
+        @"applicationDirectory": [[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]] absoluteString],
+        @"applicationStorageDirectory": [[NSURL fileURLWithPath:storagePath] absoluteString],
+        @"dataDirectory": [[NSURL fileURLWithPath:libPathNoSync] absoluteString],
+        @"syncedDataDirectory": [[NSURL fileURLWithPath:libPathSync] absoluteString],
+        @"documentsDirectory": [[NSURL fileURLWithPath:docPath] absoluteString],
+        @"cacheDirectory": [[NSURL fileURLWithPath:cachePath] absoluteString],
+        @"tempDirectory": [[NSURL fileURLWithPath:NSTemporaryDirectory()] absoluteString]
+    };
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:ret];
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/* Creates and returns a dictionary representing an Entry Object
+ *
+ * IN:
+ * NSString* fullPath of the entry
+ * int fsType - FileSystem type
+ * BOOL isDirectory - YES if this is a directory, NO if is a file
+ * OUT:
+ * NSDictionary* Entry object
+ *		bool as NSNumber isDirectory
+ *		bool as NSNumber isFile
+ *		NSString*  name - last part of path
+ *		NSString* fullPath
+ *		NSString* filesystemName - FileSystem name -- actual filesystem will be created on the JS side if necessary, to avoid
+ *         creating circular reference (FileSystem contains DirectoryEntry which contains FileSystem.....!!)
+ */
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir
+{
+    NSObject<CDVFileSystem> *fs = [self fileSystemByName:fsName];
+    return [fs makeEntryForPath:fullPath isDirectory:isDir];
+}
+
+- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)localURL
+{
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURL];
+    return [fs makeEntryForLocalURL:localURL];
+}
+
+- (NSDictionary *)makeEntryForURL:(NSURL *)URL
+{
+    CDVFilesystemURL* fsURL = [self fileSystemURLforArg:[URL absoluteString]];
+    return [self makeEntryForLocalURL:fsURL];
+}
+
+/*
+ * Given a URI determine the File System information associated with it and return an appropriate W3C entry object
+ * IN
+ *	NSString* localURI: Should be an escaped local filesystem URI
+ * OUT
+ *	Entry object
+ *		bool isDirectory
+ *		bool isFile
+ *		string name
+ *		string fullPath
+ *		fileSystem = FileSystem object - !! ignored because creates circular reference FileSystem contains DirectoryEntry which contains FileSystem.....!!
+ */
+- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    NSString* localURIstr = [command argumentAtIndex:0];
+    CDVPluginResult* result;
+
+    localURIstr = [self encodePath:localURIstr]; //encode path before resolving
+    CDVFilesystemURL* inputURI = [self fileSystemURLforArg:localURIstr];
+
+    if (inputURI == nil || inputURI.fileSystemName == nil) {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
+    } else {
+        NSObject<CDVFileSystem> *fs = [self filesystemForURL:inputURI];
+        if (fs == nil) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
+        } else {
+            result = [fs entryForLocalURI:inputURI];
+        }
+    }
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+//encode path with percent escapes
+-(NSString *)encodePath:(NSString *)path
+{
+    NSString *decodedPath = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //decode incase it's already encoded to avoid encoding twice
+    return [decodedPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+}
+
+
+/* Part of DirectoryEntry interface,  creates or returns the specified directory
+ * IN:
+ *	NSString* localURI - local filesystem URI for this directory
+ *	NSString* path - directory to be created/returned; may be full path or relative path
+ *	NSDictionary* - Flags object
+ *		boolean as NSNumber create -
+ *			if create is true and directory does not exist, create dir and return directory entry
+ *			if create is true and exclusive is true and directory does exist, return error
+ *			if create is false and directory does not exist, return error
+ *			if create is false and the path represents a file, return error
+ *		boolean as NSNumber exclusive - used in conjunction with create
+ *			if exclusive is true and create is true - specifies failure if directory already exists
+ *
+ *
+ */
+- (void)getDirectory:(CDVInvokedUrlCommand*)command
+{
+    NSMutableArray* arguments = [NSMutableArray arrayWithArray:command.arguments];
+    NSMutableDictionary* options = nil;
+
+    if ([arguments count] >= 3) {
+        options = [command argumentAtIndex:2 withDefault:nil];
+    }
+    // add getDir to options and call getFile()
+    if (options != nil) {
+        options = [NSMutableDictionary dictionaryWithDictionary:options];
+    } else {
+        options = [NSMutableDictionary dictionaryWithCapacity:1];
+    }
+    [options setObject:[NSNumber numberWithInt:1] forKey:@"getDir"];
+    if ([arguments count] >= 3) {
+        [arguments replaceObjectAtIndex:2 withObject:options];
+    } else {
+        [arguments addObject:options];
+    }
+    CDVInvokedUrlCommand* subCommand =
+        [[CDVInvokedUrlCommand alloc] initWithArguments:arguments
+                                             callbackId:command.callbackId
+                                              className:command.className
+                                             methodName:command.methodName];
+
+    [self getFile:subCommand];
+}
+
+/* Part of DirectoryEntry interface,  creates or returns the specified file
+ * IN:
+ *	NSString* baseURI - local filesytem URI for the base directory to search
+ *	NSString* requestedPath - file to be created/returned; may be absolute path or relative path
+ *	NSDictionary* options - Flags object
+ *		boolean as NSNumber create -
+ *			if create is true and file does not exist, create file and return File entry
+ *			if create is true and exclusive is true and file does exist, return error
+ *			if create is false and file does not exist, return error
+ *			if create is false and the path represents a directory, return error
+ *		boolean as NSNumber exclusive - used in conjunction with create
+ *			if exclusive is true and create is true - specifies failure if file already exists
+ */
+- (void)getFile:(CDVInvokedUrlCommand*)command
+{
+    NSString* baseURIstr = [command argumentAtIndex:0];
+    CDVFilesystemURL* baseURI = [self fileSystemURLforArg:baseURIstr];
+    NSString* requestedPath = [command argumentAtIndex:1];
+    NSDictionary* options = [command argumentAtIndex:2 withDefault:nil];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:baseURI];
+    CDVPluginResult* result = [fs getFileForURL:baseURI requestedPath:requestedPath options:options];
+
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/*
+ * Look up the parent Entry containing this Entry.
+ * If this Entry is the root of its filesystem, its parent is itself.
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* localURI
+ * NSMutableDictionary* options
+ *	empty
+ */
+- (void)getParent:(CDVInvokedUrlCommand*)command
+{
+    // arguments are URL encoded
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+    CDVPluginResult* result = [fs getParentForURL:localURI];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/*
+ * set MetaData of entry
+ * Currently we only support "com.apple.MobileBackup" (boolean)
+ */
+- (void)setMetadata:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSDictionary* options = [command argumentAtIndex:1 withDefault:nil];
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+    CDVPluginResult* result = [fs setMetadataForURL:localURI withObject:options];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/* removes the directory or file entry
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* localURI
+ *
+ * returns NO_MODIFICATION_ALLOWED_ERR  if is top level directory or no permission to delete dir
+ * returns INVALID_MODIFICATION_ERR if is non-empty dir or asset library file
+ * returns NOT_FOUND_ERR if file or dir is not found
+*/
+- (void)remove:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    CDVPluginResult* result = nil;
+
+    if ([localURI.fullPath isEqualToString:@""]) {
+        // error if try to remove top level (documents or tmp) dir
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
+    } else {
+        NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+        result = [fs removeFileAtURL:localURI];
+    }
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/* recursively removes the directory
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* localURI
+ *
+ * returns NO_MODIFICATION_ALLOWED_ERR  if is top level directory or no permission to delete dir
+ * returns NOT_FOUND_ERR if file or dir is not found
+ */
+- (void)removeRecursively:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    CDVPluginResult* result = nil;
+
+    if ([localURI.fullPath isEqualToString:@""]) {
+        // error if try to remove top level (documents or tmp) dir
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
+    } else {
+        NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+        result = [fs recursiveRemoveFileAtURL:localURI];
+    }
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+- (void)copyTo:(CDVInvokedUrlCommand*)command
+{
+    [self doCopyMove:command isCopy:YES];
+}
+
+- (void)moveTo:(CDVInvokedUrlCommand*)command
+{
+    [self doCopyMove:command isCopy:NO];
+}
+
+/* Copy/move a file or directory to a new location
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* URL of entry to copy
+ *  1 - NSString* URL of the directory into which to copy/move the entry
+ *  2 - Optionally, the new name of the entry, defaults to the current name
+ *	BOOL - bCopy YES if copy, NO if move
+ */
+- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy
+{
+    NSArray* arguments = command.arguments;
+
+    // arguments
+    NSString* srcURLstr = [command argumentAtIndex:0];
+    NSString* destURLstr = [command argumentAtIndex:1];
+
+    CDVPluginResult *result;
+
+    if (!srcURLstr || !destURLstr) {
+        // either no source or no destination provided
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        return;
+    }
+
+    CDVFilesystemURL* srcURL = [self fileSystemURLforArg:srcURLstr];
+    CDVFilesystemURL* destURL = [self fileSystemURLforArg:destURLstr];
+
+    NSObject<CDVFileSystem> *srcFs = [self filesystemForURL:srcURL];
+    NSObject<CDVFileSystem> *destFs = [self filesystemForURL:destURL];
+
+    // optional argument; use last component from srcFullPath if new name not provided
+    NSString* newName = ([arguments count] > 2) ? [command argumentAtIndex:2] : [srcURL.url lastPathComponent];
+    if ([newName rangeOfString:@":"].location != NSNotFound) {
+        // invalid chars in new name
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
+        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        return;
+    }
+
+    __weak CDVFile* weakSelf = self;
+    [self.commandDelegate runInBackground:^ {
+        [destFs copyFileToURL:destURL withName:newName fromFileSystem:srcFs atURL:srcURL copy:bCopy callback:^(CDVPluginResult* result) {
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        }];
+    }];
+
+}
+
+- (void)getFileMetadata:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+    __weak CDVFile* weakSelf = self;
+    [fs getFileMetadataForURL:localURI callback:^(CDVPluginResult* result) {
+        [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+    }];
+}
+
+- (void)readEntries:(CDVInvokedUrlCommand*)command
+{
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+    CDVPluginResult *result = [fs readEntriesAtURL:localURI];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/* read and return file data
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* fullPath
+ *	1 - NSString* encoding
+ *	2 - NSString* start
+ *	3 - NSString* end
+ */
+- (void)readAsText:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSString* encoding = [command argumentAtIndex:1];
+    NSInteger start = [[command argumentAtIndex:2] integerValue];
+    NSInteger end = [[command argumentAtIndex:3] integerValue];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+
+    if (fs == nil) {
+        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        return;
+    }
+
+    // TODO: implement
+    if ([@"UTF-8" caseInsensitiveCompare : encoding] != NSOrderedSame) {
+        NSLog(@"Only UTF-8 encodings are currently supported by readAsText");
+        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
+        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        return;
+    }
+
+    __weak CDVFile* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^ {
+        [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
+            CDVPluginResult* result = nil;
+            if (data != nil) {
+                NSString* str = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSUTF8StringEncoding freeWhenDone:NO];
+                // Check that UTF8 conversion did not fail.
+                if (str != nil) {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:str];
+                    result.associatedObject = data;
+                } else {
+                    errorCode = ENCODING_ERR;
+                }
+            }
+            if (result == nil) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+            }
+
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        }];
+    }];
+}
+
+/* Read content of text file and return as base64 encoded data url.
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* fullPath
+ *	1 - NSString* start
+ *	2 - NSString* end
+ *
+ * Determines the mime type from the file extension, returns ENCODING_ERR if mimetype can not be determined.
+ */
+
+- (void)readAsDataURL:(CDVInvokedUrlCommand*)command
+{
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSInteger start = [[command argumentAtIndex:1] integerValue];
+    NSInteger end = [[command argumentAtIndex:2] integerValue];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+
+    __weak CDVFile* weakSelf = self;
+    [self.commandDelegate runInBackground:^ {
+        [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
+            CDVPluginResult* result = nil;
+            if (data != nil) {
+                NSString* b64Str = toBase64(data);
+                NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, b64Str];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:output];
+            } else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+            }
+
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        }];
+    }];
+}
+
+/* Read content of text file and return as an arraybuffer
+ * IN:
+ * NSArray* arguments
+ *	0 - NSString* fullPath
+ *	1 - NSString* start
+ *	2 - NSString* end
+ */
+
+- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command
+{
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSInteger start = [[command argumentAtIndex:1] integerValue];
+    NSInteger end = [[command argumentAtIndex:2] integerValue];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+
+    __weak CDVFile* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^ {
+        [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
+            CDVPluginResult* result = nil;
+            if (data != nil) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:data];
+            } else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+            }
+
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        }];
+    }];
+}
+
+- (void)readAsBinaryString:(CDVInvokedUrlCommand*)command
+{
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    NSInteger start = [[command argumentAtIndex:1] integerValue];
+    NSInteger end = [[command argumentAtIndex:2] integerValue];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+
+    __weak CDVFile* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^ {
+        [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
+            CDVPluginResult* result = nil;
+            if (data != nil) {
+                NSString* payload = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSASCIIStringEncoding freeWhenDone:NO];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
+                result.associatedObject = data;
+            } else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+            }
+
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        }];
+    }];
+}
+
+
+- (void)truncate:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+    unsigned long long pos = (unsigned long long)[[command argumentAtIndex:1] longLongValue];
+
+    NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+    CDVPluginResult *result = [fs truncateFileAtURL:localURI atPosition:pos];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+/* write
+ * IN:
+ * NSArray* arguments
+ *  0 - NSString* localURI of file to write to
+ *  1 - NSString* or NSData* data to write
+ *  2 - NSNumber* position to begin writing
+ */
+- (void)write:(CDVInvokedUrlCommand*)command
+{
+    __weak CDVFile* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^ {
+        NSString* callbackId = command.callbackId;
+
+        // arguments
+        CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
+        id argData = [command argumentAtIndex:1];
+        unsigned long long pos = (unsigned long long)[[command argumentAtIndex:2] longLongValue];
+
+        NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
+
+
+        [fs truncateFileAtURL:localURI atPosition:pos];
+        CDVPluginResult *result;
+        if ([argData isKindOfClass:[NSString class]]) {
+            NSData *encData = [argData dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
+            result = [fs writeToFileAtURL:localURI withData:encData append:YES];
+        } else if ([argData isKindOfClass:[NSData class]]) {
+            result = [fs writeToFileAtURL:localURI withData:argData append:YES];
+        } else {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid parameter type"];
+        }
+        [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
+    }];
+}
+
+#pragma mark Methods for converting between URLs and paths
+
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURL
+{
+    for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
+        if ([fs.name isEqualToString:localURL.fileSystemName]) {
+            if ([fs respondsToSelector:@selector(filesystemPathForURL:)]) {
+                return [fs filesystemPathForURL:localURL];
+            }
+        }
+    }
+    return nil;
+}
+
+#pragma mark Undocumented Filesystem API
+
+- (void)testFileExists:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    NSString* argPath = [command argumentAtIndex:0];
+
+    // Get the file manager
+    NSFileManager* fMgr = [NSFileManager defaultManager];
+    NSString* appFile = argPath; // [ self getFullPath: argPath];
+
+    BOOL bExists = [fMgr fileExistsAtPath:appFile];
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(bExists ? 1 : 0)];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command
+{
+    // arguments
+    NSString* argPath = [command argumentAtIndex:0];
+
+    // Get the file manager
+    NSFileManager* fMgr = [[NSFileManager alloc] init];
+    NSString* appFile = argPath; // [self getFullPath: argPath];
+    BOOL bIsDir = NO;
+    BOOL bExists = [fMgr fileExistsAtPath:appFile isDirectory:&bIsDir];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:((bExists && bIsDir) ? 1 : 0)];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+// Returns number of bytes available via callback
+- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command
+{
+    // no arguments
+    
+    NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
+
+    NSString* strFreeSpace = [NSString stringWithFormat:@"%qu", [pNumAvail unsignedLongLongValue]];
+    // NSLog(@"Free space is %@", strFreeSpace );
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:strFreeSpace];
+
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+#pragma mark Compatibility with older File API
+
+- (NSString*)getMimeTypeFromPath:(NSString*)fullPath
+{
+    return [CDVLocalFilesystem getMimeTypeFromPath:fullPath];
+}
+
+- (NSDictionary *)getDirectoryEntry:(NSString *)localPath isDirectory:(BOOL)bDirRequest
+{
+    CDVFilesystemURL *localURL = [self fileSystemURLforLocalPath:localPath];
+    return [self makeEntryForPath:localURL.fullPath fileSystemName:localURL.fileSystemName isDirectory:bDirRequest];
+}
+
+#pragma mark Internal methods for testing
+// Internal methods for testing: Get the on-disk location of a local filesystem url.
+// [Currently used for testing file-transfer]
+
+- (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command
+{
+    CDVFilesystemURL* localURL = [self fileSystemURLforArg:command.arguments[0]];
+
+    NSString* fsPath = [self filesystemPathForURL:localURL];
+    CDVPluginResult* result;
+    if (fsPath) {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:fsPath];
+    } else {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot resolve URL to a file"];
+    }
+    [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.h b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.h
new file mode 100644
index 0000000..a0186c8
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.h
@@ -0,0 +1,32 @@
+/*
+ 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.
+ */
+
+#import "CDVFile.h"
+
+@interface CDVLocalFilesystem : NSObject<CDVFileSystem> {
+    NSString *_name;
+    NSString *_fsRoot;
+}
+
+- (id) initWithName:(NSString *)name root:(NSString *)fsRoot;
++ (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
+
+@property (nonatomic,strong) NSString *fsRoot;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.m b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.m
new file mode 100644
index 0000000..c340ce0
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-file/CDVLocalFilesystem.m
@@ -0,0 +1,750 @@
+/*
+ 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.
+ */
+
+#import "CDVFile.h"
+#import "CDVLocalFilesystem.h"
+#import <Cordova/CDV.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+#import <sys/xattr.h>
+
+@implementation CDVLocalFilesystem
+@synthesize name=_name, fsRoot=_fsRoot, urlTransformer;
+
+- (id) initWithName:(NSString *)name root:(NSString *)fsRoot
+{
+    if (self) {
+        self.name = name;
+        self.fsRoot = fsRoot;
+    }
+    return self;
+}
+
+/*
+ * IN
+ *  NSString localURI
+ * OUT
+ *  CDVPluginResult result containing a file or directoryEntry for the localURI, or an error if the
+ *   URI represents a non-existent path, or is unrecognized or otherwise malformed.
+ */
+- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
+{
+    CDVPluginResult* result = nil;
+    NSDictionary* entry = [self makeEntryForLocalURL:url];
+    if (entry) {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
+    } else {
+        // return NOT_FOUND_ERR
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+    }
+    return result;
+}
+- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
+    NSString *path = [self filesystemPathForURL:url];
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    BOOL isDir = NO;
+    // see if exists and is file or dir
+    BOOL bExists = [fileMgr fileExistsAtPath:path isDirectory:&isDir];
+    if (bExists) {
+        return [self makeEntryForPath:url.fullPath isDirectory:isDir];
+    } else {
+        return nil;
+    }
+}
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
+{
+    NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
+    NSString* lastPart = [[self stripQueryParametersFromPath:fullPath] lastPathComponent];
+    if (isDir && ![fullPath hasSuffix:@"/"]) {
+        fullPath = [fullPath stringByAppendingString:@"/"];
+    }
+    [dirEntry setObject:[NSNumber numberWithBool:!isDir]  forKey:@"isFile"];
+    [dirEntry setObject:[NSNumber numberWithBool:isDir]  forKey:@"isDirectory"];
+    [dirEntry setObject:fullPath forKey:@"fullPath"];
+    [dirEntry setObject:lastPart forKey:@"name"];
+    [dirEntry setObject:self.name forKey: @"filesystemName"];
+
+    NSURL* nativeURL = [NSURL fileURLWithPath:[self filesystemPathForFullPath:fullPath]];
+    if (self.urlTransformer) {
+        nativeURL = self.urlTransformer(nativeURL);
+    }
+
+    dirEntry[@"nativeURL"] = [nativeURL absoluteString];
+
+    return dirEntry;
+}
+
+- (NSString *)stripQueryParametersFromPath:(NSString *)fullPath
+{
+    NSRange questionMark = [fullPath rangeOfString:@"?"];
+    if (questionMark.location != NSNotFound) {
+        return [fullPath substringWithRange:NSMakeRange(0,questionMark.location)];
+    }
+    return fullPath;
+}
+
+- (NSString *)filesystemPathForFullPath:(NSString *)fullPath
+{
+    NSString *path = nil;
+    NSString *strippedFullPath = [self stripQueryParametersFromPath:fullPath];
+    path = [NSString stringWithFormat:@"%@%@", self.fsRoot, strippedFullPath];
+    if ([path length] > 1 && [path hasSuffix:@"/"]) {
+      path = [path substringToIndex:([path length]-1)];
+    }
+    return path;
+}
+/*
+ * IN
+ *  NSString localURI
+ * OUT
+ *  NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
+ *  The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
+ *  or if the URL is malformed.
+ * The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
+ */
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
+{
+    return [self filesystemPathForFullPath:url.fullPath];
+}
+
+- (CDVFilesystemURL *)URLforFullPath:(NSString *)fullPath
+{
+    if (fullPath) {
+        NSString* escapedPath = [fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+        if ([fullPath hasPrefix:@"/"]) {
+            return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
+        }
+        return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@/%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
+    }
+    return nil;
+}
+
+- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path
+{
+    return [self URLforFullPath:[self fullPathForFileSystemPath:path]];
+
+}
+
+- (NSString *)normalizePath:(NSString *)rawPath
+{
+    // If this is an absolute path, the first path component will be '/'. Skip it if that's the case
+    BOOL isAbsolutePath = [rawPath hasPrefix:@"/"];
+    if (isAbsolutePath) {
+        rawPath = [rawPath substringFromIndex:1];
+    }
+    NSMutableArray *components = [NSMutableArray arrayWithArray:[rawPath pathComponents]];
+    for (int index = 0; index < [components count]; ++index) {
+        if ([[components objectAtIndex:index] isEqualToString:@".."]) {
+            [components removeObjectAtIndex:index];
+            if (index > 0) {
+                [components removeObjectAtIndex:index-1];
+                --index;
+            }
+        }
+    }
+
+    if (isAbsolutePath) {
+        return [NSString stringWithFormat:@"/%@", [components componentsJoinedByString:@"/"]];
+    } else {
+        return [components componentsJoinedByString:@"/"];
+    }
+
+
+}
+
+- (BOOL)valueForKeyIsNumber:(NSDictionary*)dict key:(NSString*)key
+{
+    BOOL bNumber = NO;
+    NSObject* value = dict[key];
+    if (value) {
+        bNumber = [value isKindOfClass:[NSNumber class]];
+    }
+    return bNumber;
+}
+
+- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
+{
+    CDVPluginResult* result = nil;
+    BOOL bDirRequest = NO;
+    BOOL create = NO;
+    BOOL exclusive = NO;
+    int errorCode = 0;  // !!! risky - no error code currently defined for 0
+
+    if ([self valueForKeyIsNumber:options key:@"create"]) {
+        create = [(NSNumber*)[options valueForKey:@"create"] boolValue];
+    }
+    if ([self valueForKeyIsNumber:options key:@"exclusive"]) {
+        exclusive = [(NSNumber*)[options valueForKey:@"exclusive"] boolValue];
+    }
+    if ([self valueForKeyIsNumber:options key:@"getDir"]) {
+        // this will not exist for calls directly to getFile but will have been set by getDirectory before calling this method
+        bDirRequest = [(NSNumber*)[options valueForKey:@"getDir"] boolValue];
+    }
+    // see if the requested path has invalid characters - should we be checking for  more than just ":"?
+    if ([requestedPath rangeOfString:@":"].location != NSNotFound) {
+        errorCode = ENCODING_ERR;
+    } else {
+        // Build new fullPath for the requested resource.
+        // We concatenate the two paths together, and then scan the resulting string to remove
+        // parent ("..") references. Any parent references at the beginning of the string are
+        // silently removed.
+        NSString *combinedPath = [baseURI.fullPath stringByAppendingPathComponent:requestedPath];
+        combinedPath = [self normalizePath:combinedPath];
+        CDVFilesystemURL* requestedURL = [self URLforFullPath:combinedPath];
+
+        NSFileManager* fileMgr = [[NSFileManager alloc] init];
+        BOOL bIsDir;
+        BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:requestedURL] isDirectory:&bIsDir];
+        if (bExists && (create == NO) && (bIsDir == !bDirRequest)) {
+            // path exists and is not of requested type  - return TYPE_MISMATCH_ERR
+            errorCode = TYPE_MISMATCH_ERR;
+        } else if (!bExists && (create == NO)) {
+            // path does not exist and create is false - return NOT_FOUND_ERR
+            errorCode = NOT_FOUND_ERR;
+        } else if (bExists && (create == YES) && (exclusive == YES)) {
+            // file/dir already exists and exclusive and create are both true - return PATH_EXISTS_ERR
+            errorCode = PATH_EXISTS_ERR;
+        } else {
+            // if bExists and create == YES - just return data
+            // if bExists and create == NO  - just return data
+            // if !bExists and create == YES - create and return data
+            BOOL bSuccess = YES;
+            NSError __autoreleasing* pError = nil;
+            if (!bExists && (create == YES)) {
+                if (bDirRequest) {
+                    // create the dir
+                    bSuccess = [fileMgr createDirectoryAtPath:[self filesystemPathForURL:requestedURL] withIntermediateDirectories:NO attributes:nil error:&pError];
+                } else {
+                    // create the empty file
+                    bSuccess = [fileMgr createFileAtPath:[self filesystemPathForURL:requestedURL] contents:nil attributes:nil];
+                }
+            }
+            if (!bSuccess) {
+                errorCode = ABORT_ERR;
+                if (pError) {
+                    NSLog(@"error creating directory: %@", [pError localizedDescription]);
+                }
+            } else {
+                // NSLog(@"newly created file/dir (%@) exists: %d", reqFullPath, [fileMgr fileExistsAtPath:reqFullPath]);
+                // file existed or was created
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:requestedURL.fullPath isDirectory:bDirRequest]];
+            }
+        } // are all possible conditions met?
+    }
+
+    if (errorCode > 0) {
+        // create error callback
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+    }
+    return result;
+
+}
+
+- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
+{
+    CDVPluginResult* result = nil;
+    CDVFilesystemURL *newURI = nil;
+    if ([localURI.fullPath isEqualToString:@""]) {
+        // return self
+        newURI = localURI;
+    } else {
+        newURI = [CDVFilesystemURL fileSystemURLWithURL:[localURI.url URLByDeletingLastPathComponent]]; /* TODO: UGLY - FIX */
+    }
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    BOOL bIsDir;
+    BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:newURI] isDirectory:&bIsDir];
+    if (bExists) {
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:newURI.fullPath isDirectory:bIsDir]];
+    } else {
+        // invalid path or file does not exist
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+    }
+    return result;
+}
+
+- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
+{
+    BOOL ok = NO;
+
+    NSString* filePath = [self filesystemPathForURL:localURI];
+    // we only care about this iCloud key for now.
+    // set to 1/true to skip backup, set to 0/false to back it up (effectively removing the attribute)
+    NSString* iCloudBackupExtendedAttributeKey = @"com.apple.MobileBackup";
+    id iCloudBackupExtendedAttributeValue = [options objectForKey:iCloudBackupExtendedAttributeKey];
+
+    if ((iCloudBackupExtendedAttributeValue != nil) && [iCloudBackupExtendedAttributeValue isKindOfClass:[NSNumber class]]) {
+        if (IsAtLeastiOSVersion(@"5.1")) {
+            NSURL* url = [NSURL fileURLWithPath:filePath];
+            NSError* __autoreleasing error = nil;
+
+            ok = [url setResourceValue:[NSNumber numberWithBool:[iCloudBackupExtendedAttributeValue boolValue]] forKey:NSURLIsExcludedFromBackupKey error:&error];
+        } else { // below 5.1 (deprecated - only really supported in 5.01)
+            u_int8_t value = [iCloudBackupExtendedAttributeValue intValue];
+            if (value == 0) { // remove the attribute (allow backup, the default)
+                ok = (removexattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], 0) == 0);
+            } else { // set the attribute (skip backup)
+                ok = (setxattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], &value, sizeof(value), 0, 0) == 0);
+            }
+        }
+    }
+
+    if (ok) {
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    } else {
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
+    }
+}
+
+/* remove the file or directory (recursively)
+ * IN:
+ * NSString* fullPath - the full path to the file or directory to be removed
+ * NSString* callbackId
+ * called from remove and removeRecursively - check all pubic api specific error conditions (dir not empty, etc) before calling
+ */
+
+- (CDVPluginResult*)doRemove:(NSString*)fullPath
+{
+    CDVPluginResult* result = nil;
+    BOOL bSuccess = NO;
+    NSError* __autoreleasing pError = nil;
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+
+    @try {
+        bSuccess = [fileMgr removeItemAtPath:fullPath error:&pError];
+        if (bSuccess) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+        } else {
+            // see if we can give a useful error
+            CDVFileError errorCode = ABORT_ERR;
+            NSLog(@"error removing filesystem entry at %@: %@", fullPath, [pError localizedDescription]);
+            if ([pError code] == NSFileNoSuchFileError) {
+                errorCode = NOT_FOUND_ERR;
+            } else if ([pError code] == NSFileWriteNoPermissionError) {
+                errorCode = NO_MODIFICATION_ALLOWED_ERR;
+            }
+
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+        }
+    } @catch(NSException* e) {  // NSInvalidArgumentException if path is . or ..
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:SYNTAX_ERR];
+    }
+
+    return result;
+}
+
+- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
+{
+    NSString *fileSystemPath = [self filesystemPathForURL:localURI];
+
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    BOOL bIsDir = NO;
+    BOOL bExists = [fileMgr fileExistsAtPath:fileSystemPath isDirectory:&bIsDir];
+    if (!bExists) {
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+    }
+    if (bIsDir && ([[fileMgr contentsOfDirectoryAtPath:fileSystemPath error:nil] count] != 0)) {
+        // dir is not empty
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
+    }
+    return [self doRemove:fileSystemPath];
+}
+
+- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
+{
+    NSString *fileSystemPath = [self filesystemPathForURL:localURI];
+    return [self doRemove:fileSystemPath];
+}
+
+/*
+ * IN
+ *  NSString localURI
+ * OUT
+ *  NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
+ *  The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
+ *  or if the URL is malformed.
+ * The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
+ */
+- (NSString *)fullPathForFileSystemPath:(NSString *)fsPath
+{
+    if ([fsPath hasPrefix:self.fsRoot]) {
+        return [fsPath substringFromIndex:[self.fsRoot length]];
+    }
+    return nil;
+}
+
+
+- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
+{
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+    NSError* __autoreleasing error = nil;
+    NSString *fileSystemPath = [self filesystemPathForURL:localURI];
+
+    NSArray* contents = [fileMgr contentsOfDirectoryAtPath:fileSystemPath error:&error];
+
+    if (contents) {
+        NSMutableArray* entries = [NSMutableArray arrayWithCapacity:1];
+        if ([contents count] > 0) {
+            // create an Entry (as JSON) for each file/dir
+            for (NSString* name in contents) {
+                // see if is dir or file
+                NSString* entryPath = [fileSystemPath stringByAppendingPathComponent:name];
+                BOOL bIsDir = NO;
+                [fileMgr fileExistsAtPath:entryPath isDirectory:&bIsDir];
+                NSDictionary* entryDict = [self makeEntryForPath:[self fullPathForFileSystemPath:entryPath] isDirectory:bIsDir];
+                [entries addObject:entryDict];
+            }
+        }
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:entries];
+    } else {
+        // assume not found but could check error for more specific error conditions
+        return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+    }
+}
+
+- (unsigned long long)truncateFile:(NSString*)filePath atPosition:(unsigned long long)pos
+{
+    unsigned long long newPos = 0UL;
+
+    NSFileHandle* file = [NSFileHandle fileHandleForWritingAtPath:filePath];
+
+    if (file) {
+        [file truncateFileAtOffset:(unsigned long long)pos];
+        newPos = [file offsetInFile];
+        [file synchronizeFile];
+        [file closeFile];
+    }
+    return newPos;
+}
+
+- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
+{
+    unsigned long long newPos = [self truncateFile:[self filesystemPathForURL:localURI] atPosition:pos];
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)newPos];
+}
+
+- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
+{
+    NSString *filePath = [self filesystemPathForURL:localURL];
+
+    CDVPluginResult* result = nil;
+    CDVFileError errCode = INVALID_MODIFICATION_ERR;
+    int bytesWritten = 0;
+
+    if (filePath) {
+        NSOutputStream* fileStream = [NSOutputStream outputStreamToFileAtPath:filePath append:shouldAppend];
+        if (fileStream) {
+            NSUInteger len = [encData length];
+            if (len == 0) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:(double)len];
+            } else {
+                [fileStream open];
+
+                bytesWritten = (int)[fileStream write:[encData bytes] maxLength:len];
+
+                [fileStream close];
+                if (bytesWritten > 0) {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:bytesWritten];
+                    // } else {
+                    // can probably get more detailed error info via [fileStream streamError]
+                    // errCode already set to INVALID_MODIFICATION_ERR;
+                    // bytesWritten = 0; // may be set to -1 on error
+                }
+            }
+        } // else fileStream not created return INVALID_MODIFICATION_ERR
+    } else {
+        // invalid filePath
+        errCode = NOT_FOUND_ERR;
+    }
+    if (!result) {
+        // was an error
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
+    }
+    return result;
+}
+
+/**
+ * Helper function to check to see if the user attempted to copy an entry into its parent without changing its name,
+ * or attempted to copy a directory into a directory that it contains directly or indirectly.
+ *
+ * IN:
+ *  NSString* srcDir
+ *  NSString* destinationDir
+ * OUT:
+ *  YES copy/ move is allows
+ *  NO move is onto itself
+ */
+- (BOOL)canCopyMoveSrc:(NSString*)src ToDestination:(NSString*)dest
+{
+    // This weird test is to determine if we are copying or moving a directory into itself.
+    // Copy /Documents/myDir to /Documents/myDir-backup is okay but
+    // Copy /Documents/myDir to /Documents/myDir/backup not okay
+    BOOL copyOK = YES;
+    NSRange range = [dest rangeOfString:src];
+
+    if (range.location != NSNotFound) {
+        NSRange testRange = {range.length - 1, ([dest length] - range.length)};
+        NSRange resultRange = [dest rangeOfString:@"/" options:0 range:testRange];
+        if (resultRange.location != NSNotFound) {
+            copyOK = NO;
+        }
+    }
+    return copyOK;
+}
+
+- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
+{
+    NSFileManager *fileMgr = [[NSFileManager alloc] init];
+    NSString *destRootPath = [self filesystemPathForURL:destURL];
+    BOOL bDestIsDir = NO;
+    BOOL bDestExists = [fileMgr fileExistsAtPath:destRootPath isDirectory:&bDestIsDir];
+
+    NSString *newFileSystemPath = [destRootPath stringByAppendingPathComponent:newName];
+    NSString *newFullPath = [self fullPathForFileSystemPath:newFileSystemPath];
+
+    BOOL bNewIsDir = NO;
+    BOOL bNewExists = [fileMgr fileExistsAtPath:newFileSystemPath isDirectory:&bNewIsDir];
+
+    CDVPluginResult *result = nil;
+    int errCode = 0;
+
+    if (!bDestExists) {
+        // the destination root does not exist
+        errCode = NOT_FOUND_ERR;
+    }
+
+    else if ([srcFs isKindOfClass:[CDVLocalFilesystem class]]) {
+        /* Same FS, we can shortcut with NSFileManager operations */
+        NSString *srcFullPath = [srcFs filesystemPathForURL:srcURL];
+
+        BOOL bSrcIsDir = NO;
+        BOOL bSrcExists = [fileMgr fileExistsAtPath:srcFullPath isDirectory:&bSrcIsDir];
+
+        if (!bSrcExists) {
+            // the source does not exist
+            errCode = NOT_FOUND_ERR;
+        } else if ([newFileSystemPath isEqualToString:srcFullPath]) {
+            // source and destination can not be the same
+            errCode = INVALID_MODIFICATION_ERR;
+        } else if (bSrcIsDir && (bNewExists && !bNewIsDir)) {
+            // can't copy/move dir to file
+            errCode = INVALID_MODIFICATION_ERR;
+        } else { // no errors yet
+            NSError* __autoreleasing error = nil;
+            BOOL bSuccess = NO;
+            if (bCopy) {
+                if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
+                    // can't copy dir into self
+                    errCode = INVALID_MODIFICATION_ERR;
+                } else if (bNewExists) {
+                    // the full destination should NOT already exist if a copy
+                    errCode = PATH_EXISTS_ERR;
+                } else {
+                    bSuccess = [fileMgr copyItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
+                }
+            } else { // move
+                // iOS requires that destination must not exist before calling moveTo
+                // is W3C INVALID_MODIFICATION_ERR error if destination dir exists and has contents
+                //
+                if (!bSrcIsDir && (bNewExists && bNewIsDir)) {
+                    // can't move a file to directory
+                    errCode = INVALID_MODIFICATION_ERR;
+                } else if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
+                    // can't move a dir into itself
+                    errCode = INVALID_MODIFICATION_ERR;
+                } else if (bNewExists) {
+                    if (bNewIsDir && ([[fileMgr contentsOfDirectoryAtPath:newFileSystemPath error:NULL] count] != 0)) {
+                        // can't move dir to a dir that is not empty
+                        errCode = INVALID_MODIFICATION_ERR;
+                        newFileSystemPath = nil;  // so we won't try to move
+                    } else {
+                        // remove destination so can perform the moveItemAtPath
+                        bSuccess = [fileMgr removeItemAtPath:newFileSystemPath error:NULL];
+                        if (!bSuccess) {
+                            errCode = INVALID_MODIFICATION_ERR; // is this the correct error?
+                            newFileSystemPath = nil;
+                        }
+                    }
+                } else if (bNewIsDir && [newFileSystemPath hasPrefix:srcFullPath]) {
+                    // can't move a directory inside itself or to any child at any depth;
+                    errCode = INVALID_MODIFICATION_ERR;
+                    newFileSystemPath = nil;
+                }
+
+                if (newFileSystemPath != nil) {
+                    bSuccess = [fileMgr moveItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
+                }
+            }
+            if (bSuccess) {
+                // should verify it is there and of the correct type???
+                NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:bSrcIsDir];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
+            } else {
+                if (error) {
+                    if (([error code] == NSFileReadUnknownError) || ([error code] == NSFileReadTooLargeError)) {
+                        errCode = NOT_READABLE_ERR;
+                    } else if ([error code] == NSFileWriteOutOfSpaceError) {
+                        errCode = QUOTA_EXCEEDED_ERR;
+                    } else if ([error code] == NSFileWriteNoPermissionError) {
+                        errCode = NO_MODIFICATION_ALLOWED_ERR;
+                    }
+                }
+            }
+        }
+    } else {
+        // Need to copy the hard way
+        [srcFs readFileAtURL:srcURL start:0 end:-1 callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
+            CDVPluginResult* result = nil;
+            if (data != nil) {
+                BOOL bSuccess = [data writeToFile:newFileSystemPath atomically:YES];
+                if (bSuccess) {
+                    // should verify it is there and of the correct type???
+                    NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:NO];
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
+                } else {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ABORT_ERR];
+                }
+            } else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+            }
+            callback(result);
+        }];
+        return; // Async IO; return without callback.
+    }
+    if (result == nil) {
+        if (!errCode) {
+            errCode = INVALID_MODIFICATION_ERR; // Catch-all default
+        }
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errCode];
+    }
+    callback(result);
+}
+
+/* helper function to get the mimeType from the file extension
+ * IN:
+ *	NSString* fullPath - filename (may include path)
+ * OUT:
+ *	NSString* the mime type as type/subtype.  nil if not able to determine
+ */
++ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
+{
+    NSString* mimeType = nil;
+
+    if (fullPath) {
+        CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
+        if (typeId) {
+            mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
+            if (!mimeType) {
+                // special case for m4a
+                if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
+                    mimeType = @"audio/mp4";
+                } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
+                    mimeType = @"audio/wav";
+                } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
+                    mimeType = @"text/css";
+                }
+            }
+            CFRelease(typeId);
+        }
+    }
+    return mimeType;
+}
+
+- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
+{
+    NSString *path = [self filesystemPathForURL:localURL];
+
+    NSString* mimeType = [CDVLocalFilesystem getMimeTypeFromPath:path];
+    if (mimeType == nil) {
+        mimeType = @"*/*";
+    }
+    NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:path];
+    if (start > 0) {
+        [file seekToFileOffset:start];
+    }
+
+    NSData* readData;
+    if (end < 0) {
+        readData = [file readDataToEndOfFile];
+    } else {
+        readData = [file readDataOfLength:(end - start)];
+    }
+    [file closeFile];
+
+    callback(readData, mimeType, readData != nil ? NO_ERROR : NOT_FOUND_ERR);
+}
+
+- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
+{
+    NSString *path = [self filesystemPathForURL:localURL];
+    CDVPluginResult *result;
+    NSFileManager* fileMgr = [[NSFileManager alloc] init];
+
+    NSError* __autoreleasing error = nil;
+    NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:path error:&error];
+
+    if (fileAttrs) {
+
+        // create dictionary of file info
+        NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
+
+        [fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
+        [fileInfo setObject:[self mimeTypeForFileAtPath: path] forKey:@"type"];
+        [fileInfo setObject:[path lastPathComponent] forKey:@"name"];
+
+        // Ensure that directories (and other non-regular files) report size of 0
+        unsigned long long size = ([fileAttrs fileType] == NSFileTypeRegular ? [fileAttrs fileSize] : 0);
+        [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:size] forKey:@"size"];
+
+        NSDate* modDate = [fileAttrs fileModificationDate];
+        if (modDate) {
+            [fileInfo setObject:[NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000] forKey:@"lastModifiedDate"];
+        }
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo];
+
+    } else {
+        // didn't get fileAttribs
+        CDVFileError errorCode = ABORT_ERR;
+        NSLog(@"error getting metadata: %@", [error localizedDescription]);
+        if ([error code] == NSFileNoSuchFileError || [error code] == NSFileReadNoSuchFileError) {
+            errorCode = NOT_FOUND_ERR;
+        }
+        // log [NSNumber numberWithDouble: theMessage] objCtype to see what it returns
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode];
+    }
+
+    callback(result);
+}
+
+// fix errors that base on Alexsander Akers from http://stackoverflow.com/a/5998683/2613194
+- (NSString*) mimeTypeForFileAtPath: (NSString *) path {
+    if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
+        return nil;
+    }
+    
+    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
+    CFStringRef mimeType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
+    CFRelease(UTI);
+    
+    if (!mimeType) {
+        return @"application/octet-stream";
+    }
+    return (__bridge NSString *)mimeType;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Bridging-Header.h b/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Bridging-Header.h
new file mode 100644
index 0000000..98c0410
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Bridging-Header.h
@@ -0,0 +1,5 @@
+//

+//  Use this file to import your target's public headers that you would like to expose to Swift.

+//

+

+#import <Cordova/CDV.h>
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Fingerprint.swift b/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Fingerprint.swift
new file mode 100644
index 0000000..547aeb2
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-fingerprint-aio/Fingerprint.swift
@@ -0,0 +1,85 @@
+import Foundation
+import LocalAuthentication
+
+@objc(Fingerprint) class Fingerprint : CDVPlugin {
+
+    @objc(isAvailable:)
+    func isAvailable(_ command: CDVInvokedUrlCommand){
+        let authenticationContext = LAContext();
+        var biometryType = "finger";
+        var error:NSError?;
+        let policy:LAPolicy = .deviceOwnerAuthenticationWithBiometrics;
+
+        let available = authenticationContext.canEvaluatePolicy(policy, error: &error);
+
+        if(error != nil){
+            biometryType = "none";
+        }
+
+        var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Not available");
+        if available == true {
+            if #available(iOS 11.0, *) {
+                switch(authenticationContext.biometryType) {
+                case .none:
+                    biometryType = "none";
+                case .touchID:
+                    biometryType = "finger";
+                case .faceID:
+                    biometryType = "face"
+                }
+            }
+
+            pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: biometryType);
+        }
+
+        commandDelegate.send(pluginResult, callbackId:command.callbackId);
+    }
+
+
+    @objc(authenticate:)
+    func authenticate(_ command: CDVInvokedUrlCommand){
+        let authenticationContext = LAContext();
+        var pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Something went wrong");
+        var reason = "Authentication";
+        var policy:LAPolicy = .deviceOwnerAuthentication;
+        let data  = command.arguments[0] as AnyObject?;
+
+        if let disableBackup = data?["disableBackup"] as! Bool? {
+            if disableBackup {
+                authenticationContext.localizedFallbackTitle = "";
+                policy = .deviceOwnerAuthenticationWithBiometrics;
+            } else {
+                if let localizedFallbackTitle = data?["localizedFallbackTitle"] as! String? {
+                    authenticationContext.localizedFallbackTitle = localizedFallbackTitle;
+                }
+            }
+        }
+
+        // Localized reason
+        if let localizedReason = data?["localizedReason"] as! String? {
+            reason = localizedReason;
+        }else if let clientId = data?["clientId"] as! String? {
+            reason = clientId;
+        }
+
+        authenticationContext.evaluatePolicy(
+            policy,
+            localizedReason: reason,
+            reply: { [unowned self] (success, error) -> Void in
+                if( success ) {
+                    pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "Success");
+                }else {
+                    // Check if there is an error
+                    if error != nil {
+                        pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Error: \(String(describing: error?.localizedDescription))")
+                    }
+                }
+                self.commandDelegate.send(pluginResult, callbackId:command.callbackId);
+        });
+    }
+
+    override func pluginInitialize() {
+        super.pluginInitialize()
+    }
+}
+
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.h b/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.h
new file mode 100644
index 0000000..25fae3f
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.h
@@ -0,0 +1,118 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Cordova/CDVPlugin.h>
+#import <Cordova/CDVInvokedUrlCommand.h>
+#import <Cordova/CDVScreenOrientationDelegate.h>
+
+#ifdef __CORDOVA_4_0_0
+    #import <Cordova/CDVUIWebViewDelegate.h>
+#else
+    #import <Cordova/CDVWebViewDelegate.h>
+#endif
+
+@class CDVInAppBrowserViewController;
+
+@interface CDVInAppBrowser : CDVPlugin {
+}
+
+@property (nonatomic, retain) CDVInAppBrowserViewController* inAppBrowserViewController;
+@property (nonatomic, copy) NSString* callbackId;
+@property (nonatomic, copy) NSRegularExpression *callbackIdPattern;
+
+- (void)open:(CDVInvokedUrlCommand*)command;
+- (void)close:(CDVInvokedUrlCommand*)command;
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
+- (void)show:(CDVInvokedUrlCommand*)command;
+- (void)hide:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVInAppBrowserOptions : NSObject {}
+
+@property (nonatomic, assign) BOOL location;
+@property (nonatomic, assign) BOOL toolbar;
+@property (nonatomic, copy) NSString* closebuttoncaption;
+@property (nonatomic, copy) NSString* closebuttoncolor;
+@property (nonatomic, copy) NSString* toolbarposition;
+@property (nonatomic, copy) NSString* toolbarcolor;
+@property (nonatomic, assign) BOOL toolbartranslucent;
+@property (nonatomic, assign) BOOL hidenavigationbuttons;
+@property (nonatomic, copy) NSString* navigationbuttoncolor;
+@property (nonatomic, assign) BOOL clearcache;
+@property (nonatomic, assign) BOOL clearsessioncache;
+@property (nonatomic, assign) BOOL hidespinner;
+
+@property (nonatomic, copy) NSString* presentationstyle;
+@property (nonatomic, copy) NSString* transitionstyle;
+
+@property (nonatomic, assign) BOOL enableviewportscale;
+@property (nonatomic, assign) BOOL mediaplaybackrequiresuseraction;
+@property (nonatomic, assign) BOOL allowinlinemediaplayback;
+@property (nonatomic, assign) BOOL keyboarddisplayrequiresuseraction;
+@property (nonatomic, assign) BOOL suppressesincrementalrendering;
+@property (nonatomic, assign) BOOL hidden;
+@property (nonatomic, assign) BOOL disallowoverscroll;
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
+
+@end
+
+@interface CDVInAppBrowserViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{
+    @private
+    NSString* _userAgent;
+    NSString* _prevUserAgent;
+    NSInteger _userAgentLockToken;
+    CDVInAppBrowserOptions *_browserOptions;
+
+#ifdef __CORDOVA_4_0_0
+    CDVUIWebViewDelegate* _webViewDelegate;
+#else
+    CDVWebViewDelegate* _webViewDelegate;
+#endif
+
+}
+
+@property (nonatomic, strong) IBOutlet UIWebView* webView;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* closeButton;
+@property (nonatomic, strong) IBOutlet UILabel* addressLabel;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* backButton;
+@property (nonatomic, strong) IBOutlet UIBarButtonItem* forwardButton;
+@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinner;
+@property (nonatomic, strong) IBOutlet UIToolbar* toolbar;
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+@property (nonatomic, weak) CDVInAppBrowser* navigationDelegate;
+@property (nonatomic) NSURL* currentURL;
+
+- (void)close;
+- (void)navigateTo:(NSURL*)url;
+- (void)showLocationBar:(BOOL)show;
+- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition;
+- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString;
+
+- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVInAppBrowserOptions*) browserOptions;
+
+@end
+
+@interface CDVInAppBrowserNavigationController : UINavigationController
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.m b/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.m
new file mode 100644
index 0000000..c65e3e1
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.m
@@ -0,0 +1,1144 @@
+/*
+ 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.
+ */
+
+#import "CDVInAppBrowser.h"
+#import <Cordova/CDVPluginResult.h>
+#import <Cordova/CDVUserAgentUtil.h>
+
+#define    kInAppBrowserTargetSelf @"_self"
+#define    kInAppBrowserTargetSystem @"_system"
+#define    kInAppBrowserTargetBlank @"_blank"
+
+#define    kInAppBrowserToolbarBarPositionBottom @"bottom"
+#define    kInAppBrowserToolbarBarPositionTop @"top"
+
+#define    TOOLBAR_HEIGHT 44.0
+#define    STATUSBAR_HEIGHT 20.0
+#define    LOCATIONBAR_HEIGHT 21.0
+#define    FOOTER_HEIGHT ((TOOLBAR_HEIGHT) + (LOCATIONBAR_HEIGHT))
+
+#pragma mark CDVInAppBrowser
+
+@interface CDVInAppBrowser () {
+    NSInteger _previousStatusBarStyle;
+}
+@end
+
+@implementation CDVInAppBrowser
+
+- (void)pluginInitialize
+{
+    _previousStatusBarStyle = -1;
+    _callbackIdPattern = nil;
+}
+
+- (id)settingForKey:(NSString*)key
+{
+    return [self.commandDelegate.settings objectForKey:[key lowercaseString]];
+}
+
+- (void)onReset
+{
+    [self close:nil];
+}
+
+- (void)close:(CDVInvokedUrlCommand*)command
+{
+    if (self.inAppBrowserViewController == nil) {
+        NSLog(@"IAB.close() called but it was already closed.");
+        return;
+    }
+    // Things are cleaned up in browserExit.
+    [self.inAppBrowserViewController close];
+}
+
+- (BOOL) isSystemUrl:(NSURL*)url
+{
+	if ([[url host] isEqualToString:@"itunes.apple.com"]) {
+		return YES;
+	}
+
+	return NO;
+}
+
+- (void)open:(CDVInvokedUrlCommand*)command
+{
+    CDVPluginResult* pluginResult;
+
+    NSString* url = [command argumentAtIndex:0];
+    NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
+    NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
+
+    self.callbackId = command.callbackId;
+
+    if (url != nil) {
+#ifdef __CORDOVA_4_0_0
+        NSURL* baseUrl = [self.webViewEngine URL];
+#else
+        NSURL* baseUrl = [self.webView.request URL];
+#endif
+        NSURL* absoluteUrl = [[NSURL URLWithString:url relativeToURL:baseUrl] absoluteURL];
+
+        if ([self isSystemUrl:absoluteUrl]) {
+            target = kInAppBrowserTargetSystem;
+        }
+
+        if ([target isEqualToString:kInAppBrowserTargetSelf]) {
+            [self openInCordovaWebView:absoluteUrl withOptions:options];
+        } else if ([target isEqualToString:kInAppBrowserTargetSystem]) {
+            [self openInSystem:absoluteUrl];
+        } else { // _blank or anything else
+            [self openInInAppBrowser:absoluteUrl withOptions:options];
+        }
+
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    } else {
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"];
+    }
+
+    [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
+{
+    CDVInAppBrowserOptions* browserOptions = [CDVInAppBrowserOptions parseOptions:options];
+
+    if (browserOptions.clearcache) {
+        NSHTTPCookie *cookie;
+        NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+        for (cookie in [storage cookies])
+        {
+            if (![cookie.domain isEqual: @".^filecookies^"]) {
+                [storage deleteCookie:cookie];
+            }
+        }
+    }
+
+    if (browserOptions.clearsessioncache) {
+        NSHTTPCookie *cookie;
+        NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+        for (cookie in [storage cookies])
+        {
+            if (![cookie.domain isEqual: @".^filecookies^"] && cookie.isSessionOnly) {
+                [storage deleteCookie:cookie];
+            }
+        }
+    }
+
+    if (self.inAppBrowserViewController == nil) {
+        NSString* userAgent = [CDVUserAgentUtil originalUserAgent];
+        NSString* overrideUserAgent = [self settingForKey:@"OverrideUserAgent"];
+        NSString* appendUserAgent = [self settingForKey:@"AppendUserAgent"];
+        if(overrideUserAgent){
+            userAgent = overrideUserAgent;
+        }
+        if(appendUserAgent){
+            userAgent = [userAgent stringByAppendingString: appendUserAgent];
+        }
+        self.inAppBrowserViewController = [[CDVInAppBrowserViewController alloc] initWithUserAgent:userAgent prevUserAgent:[self.commandDelegate userAgent] browserOptions: browserOptions];
+        self.inAppBrowserViewController.navigationDelegate = self;
+
+        if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) {
+            self.inAppBrowserViewController.orientationDelegate = (UIViewController <CDVScreenOrientationDelegate>*)self.viewController;
+        }
+    }
+
+    [self.inAppBrowserViewController showLocationBar:browserOptions.location];
+    [self.inAppBrowserViewController showToolBar:browserOptions.toolbar :browserOptions.toolbarposition];
+    if (browserOptions.closebuttoncaption != nil || browserOptions.closebuttoncolor != nil) {
+        [self.inAppBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption :browserOptions.closebuttoncolor];
+    }
+    // Set Presentation Style
+    UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default
+    if (browserOptions.presentationstyle != nil) {
+        if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"pagesheet"]) {
+            presentationStyle = UIModalPresentationPageSheet;
+        } else if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"formsheet"]) {
+            presentationStyle = UIModalPresentationFormSheet;
+        }
+    }
+    self.inAppBrowserViewController.modalPresentationStyle = presentationStyle;
+
+    // Set Transition Style
+    UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default
+    if (browserOptions.transitionstyle != nil) {
+        if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"fliphorizontal"]) {
+            transitionStyle = UIModalTransitionStyleFlipHorizontal;
+        } else if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"crossdissolve"]) {
+            transitionStyle = UIModalTransitionStyleCrossDissolve;
+        }
+    }
+    self.inAppBrowserViewController.modalTransitionStyle = transitionStyle;
+
+    // prevent webView from bouncing
+    if (browserOptions.disallowoverscroll) {
+        if ([self.inAppBrowserViewController.webView respondsToSelector:@selector(scrollView)]) {
+            ((UIScrollView*)[self.inAppBrowserViewController.webView scrollView]).bounces = NO;
+        } else {
+            for (id subview in self.inAppBrowserViewController.webView.subviews) {
+                if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+                    ((UIScrollView*)subview).bounces = NO;
+                }
+            }
+        }
+    }
+
+    // UIWebView options
+    self.inAppBrowserViewController.webView.scalesPageToFit = browserOptions.enableviewportscale;
+    self.inAppBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction;
+    self.inAppBrowserViewController.webView.allowsInlineMediaPlayback = browserOptions.allowinlinemediaplayback;
+    if (IsAtLeastiOSVersion(@"6.0")) {
+        self.inAppBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction;
+        self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
+    }
+
+    [self.inAppBrowserViewController navigateTo:url];
+    if (!browserOptions.hidden) {
+        [self show:nil];
+    }
+}
+
+- (void)show:(CDVInvokedUrlCommand*)command
+{
+    if (self.inAppBrowserViewController == nil) {
+        NSLog(@"Tried to show IAB after it was closed.");
+        return;
+    }
+    if (_previousStatusBarStyle != -1) {
+        NSLog(@"Tried to show IAB while already shown");
+        return;
+    }
+
+    _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
+
+    __block CDVInAppBrowserNavigationController* nav = [[CDVInAppBrowserNavigationController alloc]
+                                   initWithRootViewController:self.inAppBrowserViewController];
+    nav.orientationDelegate = self.inAppBrowserViewController;
+    nav.navigationBarHidden = YES;
+    nav.modalPresentationStyle = self.inAppBrowserViewController.modalPresentationStyle;
+
+    __weak CDVInAppBrowser* weakSelf = self;
+
+    // Run later to avoid the "took a long time" log message.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (weakSelf.inAppBrowserViewController != nil) {
+            CGRect frame = [[UIScreen mainScreen] bounds];
+            UIWindow *tmpWindow = [[UIWindow alloc] initWithFrame:frame];
+            UIViewController *tmpController = [[UIViewController alloc] init];
+            [tmpWindow setRootViewController:tmpController];
+            [tmpWindow setWindowLevel:UIWindowLevelNormal];
+
+            [tmpWindow makeKeyAndVisible];
+            [tmpController presentViewController:nav animated:YES completion:nil];
+        }
+    });
+}
+
+- (void)hide:(CDVInvokedUrlCommand*)command
+{
+    if (self.inAppBrowserViewController == nil) {
+        NSLog(@"Tried to hide IAB after it was closed.");
+        return;
+
+
+    }
+    if (_previousStatusBarStyle == -1) {
+        NSLog(@"Tried to hide IAB while already hidden");
+        return;
+    }
+
+    _previousStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
+
+    // Run later to avoid the "took a long time" log message.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (self.inAppBrowserViewController != nil) {
+            _previousStatusBarStyle = -1;
+            [self.inAppBrowserViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
+        }
+    });
+}
+
+- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
+{
+    NSURLRequest* request = [NSURLRequest requestWithURL:url];
+
+#ifdef __CORDOVA_4_0_0
+    // the webview engine itself will filter for this according to <allow-navigation> policy
+    // in config.xml for cordova-ios-4.0
+    [self.webViewEngine loadRequest:request];
+#else
+    if ([self.commandDelegate URLIsWhitelisted:url]) {
+        [self.webView loadRequest:request];
+    } else { // this assumes the InAppBrowser can be excepted from the white-list
+        [self openInInAppBrowser:url withOptions:options];
+    }
+#endif
+}
+
+- (void)openInSystem:(NSURL*)url
+{
+    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+    [[UIApplication sharedApplication] openURL:url];
+}
+
+// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
+// provides a consistent method for injecting JavaScript code into the document.
+//
+// If a wrapper string is supplied, then the source string will be JSON-encoded (adding
+// quotes) and wrapped using string formatting. (The wrapper string should have a single
+// '%@' marker).
+//
+// If no wrapper is supplied, then the source string is executed directly.
+
+- (void)injectDeferredObject:(NSString*)source withWrapper:(NSString*)jsWrapper
+{
+    // Ensure an iframe bridge is created to communicate with the CDVInAppBrowserViewController
+    [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:@"(function(d){_cdvIframeBridge=d.getElementById('_cdvIframeBridge');if(!_cdvIframeBridge) {var e = _cdvIframeBridge = d.createElement('iframe');e.id='_cdvIframeBridge'; e.style.display='none';d.body.appendChild(e);}})(document)"];
+
+    if (jsWrapper != nil) {
+        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@[source] options:0 error:nil];
+        NSString* sourceArrayString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+        if (sourceArrayString) {
+            NSString* sourceString = [sourceArrayString substringWithRange:NSMakeRange(1, [sourceArrayString length] - 2)];
+            NSString* jsToInject = [NSString stringWithFormat:jsWrapper, sourceString];
+            [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:jsToInject];
+        }
+    } else {
+        [self.inAppBrowserViewController.webView stringByEvaluatingJavaScriptFromString:source];
+    }
+}
+
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper = nil;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"_cdvIframeBridge.src='gap-iab://%@/'+encodeURIComponent(JSON.stringify([eval(%%@)]));", command.callbackId];
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectScriptFile:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleCode:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleFile:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (BOOL)isValidCallbackId:(NSString *)callbackId
+{
+    NSError *err = nil;
+    // Initialize on first use
+    if (self.callbackIdPattern == nil) {
+        self.callbackIdPattern = [NSRegularExpression regularExpressionWithPattern:@"^InAppBrowser[0-9]{1,10}$" options:0 error:&err];
+        if (err != nil) {
+            // Couldn't initialize Regex; No is safer than Yes.
+            return NO;
+        }
+    }
+    if ([self.callbackIdPattern firstMatchInString:callbackId options:0 range:NSMakeRange(0, [callbackId length])]) {
+        return YES;
+    }
+    return NO;
+}
+
+/**
+ * The iframe bridge provided for the InAppBrowser is capable of executing any oustanding callback belonging
+ * to the InAppBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no
+ * other code execution is possible.
+ *
+ * To trigger the bridge, the iframe (or any other resource) should attempt to load a url of the form:
+ *
+ * gap-iab://<callbackId>/<arguments>
+ *
+ * where <callbackId> is the string id of the callback to trigger (something like "InAppBrowser0123456789")
+ *
+ * If present, the path component of the special gap-iab:// url is expected to be a URL-escaped JSON-encoded
+ * value to pass to the callback. [NSURL path] should take care of the URL-unescaping, and a JSON_EXCEPTION
+ * is returned if the JSON is invalid.
+ */
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    NSURL* url = request.URL;
+    BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+    // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
+    // and the path, if present, should be a JSON-encoded value to pass to the callback.
+    if ([[url scheme] isEqualToString:@"gap-iab"]) {
+        NSString* scriptCallbackId = [url host];
+        CDVPluginResult* pluginResult = nil;
+
+        if ([self isValidCallbackId:scriptCallbackId]) {
+            NSString* scriptResult = [url path];
+            NSError* __autoreleasing error = nil;
+
+            // The message should be a JSON-encoded array of the result of the script which executed.
+            if ((scriptResult != nil) && ([scriptResult length] > 1)) {
+                scriptResult = [scriptResult substringFromIndex:1];
+                NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
+                if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) {
+                    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult];
+                } else {
+                    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION];
+                }
+            } else {
+                pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]];
+            }
+            [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
+            return NO;
+        }
+    }
+    //if is an app store link, let the system handle it, otherwise it fails to load it
+    else if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"]) {
+        [theWebView stopLoading];
+        [self openInSystem:url];
+        return NO;
+    }
+    else if ((self.callbackId != nil) && isTopLevelNavigation) {
+        // Send a loadstart event for each top-level navigation (includes redirects).
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+
+    return YES;
+}
+
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    if (self.callbackId != nil) {
+        // TODO: It would be more useful to return the URL the page is actually on (e.g. if it's been redirected).
+        NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"loadstop", @"url":url}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    if (self.callbackId != nil) {
+        NSString* url = [self.inAppBrowserViewController.currentURL absoluteString];
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+                                                      messageAsDictionary:@{@"type":@"loaderror", @"url":url, @"code": [NSNumber numberWithInteger:error.code], @"message": error.localizedDescription}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+}
+
+- (void)browserExit
+{
+    if (self.callbackId != nil) {
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"exit"}];
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+        self.callbackId = nil;
+    }
+    // Set navigationDelegate to nil to ensure no callbacks are received from it.
+    self.inAppBrowserViewController.navigationDelegate = nil;
+    // Don't recycle the ViewController since it may be consuming a lot of memory.
+    // Also - this is required for the PDF/User-Agent bug work-around.
+    self.inAppBrowserViewController = nil;
+
+    if (IsAtLeastiOSVersion(@"7.0")) {
+        if (_previousStatusBarStyle != -1) {
+            [[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle];
+        }
+    }
+
+    _previousStatusBarStyle = -1; // this value was reset before reapplying it. caused statusbar to stay black on ios7
+}
+
+@end
+
+#pragma mark CDVInAppBrowserViewController
+
+@implementation CDVInAppBrowserViewController
+
+@synthesize currentURL;
+
+- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVInAppBrowserOptions*) browserOptions
+{
+    self = [super init];
+    if (self != nil) {
+        _userAgent = userAgent;
+        _prevUserAgent = prevUserAgent;
+        _browserOptions = browserOptions;
+#ifdef __CORDOVA_4_0_0
+        _webViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:self];
+#else
+        _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
+#endif
+
+        [self createViews];
+    }
+
+    return self;
+}
+
+// Prevent crashes on closing windows
+-(void)dealloc {
+   self.webView.delegate = nil;
+}
+
+- (void)createViews
+{
+    // We create the views in code for primarily for ease of upgrades and not requiring an external .xib to be included
+
+    CGRect webViewBounds = self.view.bounds;
+    BOOL toolbarIsAtBottom = ![_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop];
+    webViewBounds.size.height -= _browserOptions.location ? FOOTER_HEIGHT : TOOLBAR_HEIGHT;
+    self.webView = [[UIWebView alloc] initWithFrame:webViewBounds];
+
+    self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+    [self.view addSubview:self.webView];
+    [self.view sendSubviewToBack:self.webView];
+
+    self.webView.delegate = _webViewDelegate;
+    self.webView.backgroundColor = [UIColor whiteColor];
+
+    self.webView.clearsContextBeforeDrawing = YES;
+    self.webView.clipsToBounds = YES;
+    self.webView.contentMode = UIViewContentModeScaleToFill;
+    self.webView.multipleTouchEnabled = YES;
+    self.webView.opaque = YES;
+    self.webView.scalesPageToFit = NO;
+    self.webView.userInteractionEnabled = YES;
+
+    self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
+    self.spinner.alpha = 1.000;
+    self.spinner.autoresizesSubviews = YES;
+    self.spinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin);
+    self.spinner.clearsContextBeforeDrawing = NO;
+    self.spinner.clipsToBounds = NO;
+    self.spinner.contentMode = UIViewContentModeScaleToFill;
+    self.spinner.frame = CGRectMake(CGRectGetMidX(self.webView.frame), CGRectGetMidY(self.webView.frame), 20.0, 20.0);
+    self.spinner.hidden = NO;
+    self.spinner.hidesWhenStopped = YES;
+    self.spinner.multipleTouchEnabled = NO;
+    self.spinner.opaque = NO;
+    self.spinner.userInteractionEnabled = NO;
+    [self.spinner stopAnimating];
+
+    self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
+    self.closeButton.enabled = YES;
+
+    UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
+
+    UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
+    fixedSpaceButton.width = 20;
+
+    float toolbarY = toolbarIsAtBottom ? self.view.bounds.size.height - TOOLBAR_HEIGHT : 0.0;
+    CGRect toolbarFrame = CGRectMake(0.0, toolbarY, self.view.bounds.size.width, TOOLBAR_HEIGHT);
+
+    self.toolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame];
+    self.toolbar.alpha = 1.000;
+    self.toolbar.autoresizesSubviews = YES;
+    self.toolbar.autoresizingMask = toolbarIsAtBottom ? (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin) : UIViewAutoresizingFlexibleWidth;
+    self.toolbar.barStyle = UIBarStyleBlackOpaque;
+    self.toolbar.clearsContextBeforeDrawing = NO;
+    self.toolbar.clipsToBounds = NO;
+    self.toolbar.contentMode = UIViewContentModeScaleToFill;
+    self.toolbar.hidden = NO;
+    self.toolbar.multipleTouchEnabled = NO;
+    self.toolbar.opaque = NO;
+    self.toolbar.userInteractionEnabled = YES;
+    if (_browserOptions.toolbarcolor != nil) { // Set toolbar color if user sets it in options
+      self.toolbar.barTintColor = [self colorFromHexString:_browserOptions.toolbarcolor];
+    }
+    if (!_browserOptions.toolbartranslucent) { // Set toolbar translucent to no if user sets it in options
+      self.toolbar.translucent = NO;
+    }
+
+    CGFloat labelInset = 5.0;
+    float locationBarY = toolbarIsAtBottom ? self.view.bounds.size.height - FOOTER_HEIGHT : self.view.bounds.size.height - LOCATIONBAR_HEIGHT;
+
+    self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelInset, locationBarY, self.view.bounds.size.width - labelInset, LOCATIONBAR_HEIGHT)];
+    self.addressLabel.adjustsFontSizeToFitWidth = NO;
+    self.addressLabel.alpha = 1.000;
+    self.addressLabel.autoresizesSubviews = YES;
+    self.addressLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
+    self.addressLabel.backgroundColor = [UIColor clearColor];
+    self.addressLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
+    self.addressLabel.clearsContextBeforeDrawing = YES;
+    self.addressLabel.clipsToBounds = YES;
+    self.addressLabel.contentMode = UIViewContentModeScaleToFill;
+    self.addressLabel.enabled = YES;
+    self.addressLabel.hidden = NO;
+    self.addressLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+
+    if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumScaleFactor:")]) {
+        [self.addressLabel setValue:@(10.0/[UIFont labelFontSize]) forKey:@"minimumScaleFactor"];
+    } else if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumFontSize:")]) {
+        [self.addressLabel setValue:@(10.0) forKey:@"minimumFontSize"];
+    }
+
+    self.addressLabel.multipleTouchEnabled = NO;
+    self.addressLabel.numberOfLines = 1;
+    self.addressLabel.opaque = NO;
+    self.addressLabel.shadowOffset = CGSizeMake(0.0, -1.0);
+    self.addressLabel.text = NSLocalizedString(@"Loading...", nil);
+    self.addressLabel.textAlignment = NSTextAlignmentLeft;
+    self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000];
+    self.addressLabel.userInteractionEnabled = NO;
+
+    NSString* frontArrowString = NSLocalizedString(@"►", nil); // create arrow from Unicode char
+    self.forwardButton = [[UIBarButtonItem alloc] initWithTitle:frontArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goForward:)];
+    self.forwardButton.enabled = YES;
+    self.forwardButton.imageInsets = UIEdgeInsetsZero;
+    if (_browserOptions.navigationbuttoncolor != nil) { // Set button color if user sets it in options
+      self.forwardButton.tintColor = [self colorFromHexString:_browserOptions.navigationbuttoncolor];
+    }
+
+    NSString* backArrowString = NSLocalizedString(@"◄", nil); // create arrow from Unicode char
+    self.backButton = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goBack:)];
+    self.backButton.enabled = YES;
+    self.backButton.imageInsets = UIEdgeInsetsZero;
+    if (_browserOptions.navigationbuttoncolor != nil) { // Set button color if user sets it in options
+      self.backButton.tintColor = [self colorFromHexString:_browserOptions.navigationbuttoncolor];
+    }
+
+    // Filter out Navigation Buttons if user requests so
+    if (_browserOptions.hidenavigationbuttons) {
+      [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton]];
+    } else {
+      [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]];
+    }
+
+    self.view.backgroundColor = [UIColor grayColor];
+    [self.view addSubview:self.toolbar];
+    [self.view addSubview:self.addressLabel];
+    [self.view addSubview:self.spinner];
+}
+
+- (void) setWebViewFrame : (CGRect) frame {
+    NSLog(@"Setting the WebView's frame to %@", NSStringFromCGRect(frame));
+    [self.webView setFrame:frame];
+}
+
+- (void)setCloseButtonTitle:(NSString*)title : (NSString*) colorString
+{
+    // the advantage of using UIBarButtonSystemItemDone is the system will localize it for you automatically
+    // but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one)
+    self.closeButton = nil;
+    // Initialize with title if title is set, otherwise the title will be 'Done' localized
+    self.closeButton = title != nil ? [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)] : [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)];
+    self.closeButton.enabled = YES;
+    // If color on closebutton is requested then initialize with that that color, otherwise use initialize with default
+    self.closeButton.tintColor = colorString != nil ? [self colorFromHexString:colorString] : [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
+
+    NSMutableArray* items = [self.toolbar.items mutableCopy];
+    [items replaceObjectAtIndex:0 withObject:self.closeButton];
+    [self.toolbar setItems:items];
+}
+
+- (void)showLocationBar:(BOOL)show
+{
+    CGRect locationbarFrame = self.addressLabel.frame;
+
+    BOOL toolbarVisible = !self.toolbar.hidden;
+
+    // prevent double show/hide
+    if (show == !(self.addressLabel.hidden)) {
+        return;
+    }
+
+    if (show) {
+        self.addressLabel.hidden = NO;
+
+        if (toolbarVisible) {
+            // toolBar at the bottom, leave as is
+            // put locationBar on top of the toolBar
+
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= FOOTER_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        } else {
+            // no toolBar, so put locationBar at the bottom
+
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        }
+    } else {
+        self.addressLabel.hidden = YES;
+
+        if (toolbarVisible) {
+            // locationBar is on top of toolBar, hide locationBar
+
+            // webView take up whole height less toolBar height
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= TOOLBAR_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+        } else {
+            // no toolBar, expand webView to screen dimensions
+            [self setWebViewFrame:self.view.bounds];
+        }
+    }
+}
+
+- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition
+{
+    CGRect toolbarFrame = self.toolbar.frame;
+    CGRect locationbarFrame = self.addressLabel.frame;
+
+    BOOL locationbarVisible = !self.addressLabel.hidden;
+
+    // prevent double show/hide
+    if (show == !(self.toolbar.hidden)) {
+        return;
+    }
+
+    if (show) {
+        self.toolbar.hidden = NO;
+        CGRect webViewBounds = self.view.bounds;
+
+        if (locationbarVisible) {
+            // locationBar at the bottom, move locationBar up
+            // put toolBar at the bottom
+            webViewBounds.size.height -= FOOTER_HEIGHT;
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+            self.toolbar.frame = toolbarFrame;
+        } else {
+            // no locationBar, so put toolBar at the bottom
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= TOOLBAR_HEIGHT;
+            self.toolbar.frame = toolbarFrame;
+        }
+
+        if ([toolbarPosition isEqualToString:kInAppBrowserToolbarBarPositionTop]) {
+            toolbarFrame.origin.y = 0;
+            webViewBounds.origin.y += toolbarFrame.size.height;
+            [self setWebViewFrame:webViewBounds];
+        } else {
+            toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT);
+        }
+        [self setWebViewFrame:webViewBounds];
+
+    } else {
+        self.toolbar.hidden = YES;
+
+        if (locationbarVisible) {
+            // locationBar is on top of toolBar, hide toolBar
+            // put locationBar at the bottom
+
+            // webView take up whole height less locationBar height
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+
+            // move locationBar down
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        } else {
+            // no locationBar, expand webView to screen dimensions
+            [self setWebViewFrame:self.view.bounds];
+        }
+    }
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+}
+
+- (void)viewDidUnload
+{
+    [self.webView loadHTMLString:nil baseURL:nil];
+    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+    [super viewDidUnload];
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle
+{
+    return UIStatusBarStyleDefault;
+}
+
+- (BOOL)prefersStatusBarHidden {
+    return NO;
+}
+
+- (void)close
+{
+    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+    self.currentURL = nil;
+
+    if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) {
+        [self.navigationDelegate browserExit];
+    }
+
+    __weak UIViewController* weakSelf = self;
+
+    // Run later to avoid the "took a long time" log message.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if ([weakSelf respondsToSelector:@selector(presentingViewController)]) {
+            [[weakSelf presentingViewController] dismissViewControllerAnimated:YES completion:nil];
+        } else {
+            [[weakSelf parentViewController] dismissViewControllerAnimated:YES completion:nil];
+        }
+    });
+}
+
+- (void)navigateTo:(NSURL*)url
+{
+    NSURLRequest* request = [NSURLRequest requestWithURL:url];
+
+    if (_userAgentLockToken != 0) {
+        [self.webView loadRequest:request];
+    } else {
+        __weak CDVInAppBrowserViewController* weakSelf = self;
+        [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
+            _userAgentLockToken = lockToken;
+            [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken];
+            [weakSelf.webView loadRequest:request];
+        }];
+    }
+}
+
+- (void)goBack:(id)sender
+{
+    [self.webView goBack];
+}
+
+- (void)goForward:(id)sender
+{
+    [self.webView goForward];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    if (IsAtLeastiOSVersion(@"7.0")) {
+        [[UIApplication sharedApplication] setStatusBarStyle:[self preferredStatusBarStyle]];
+    }
+    [self rePositionViews];
+
+    [super viewWillAppear:animated];
+}
+
+//
+// On iOS 7 the status bar is part of the view's dimensions, therefore it's height has to be taken into account.
+// The height of it could be hardcoded as 20 pixels, but that would assume that the upcoming releases of iOS won't
+// change that value.
+//
+- (float) getStatusBarOffset {
+    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
+    float statusBarOffset = IsAtLeastiOSVersion(@"7.0") ? MIN(statusBarFrame.size.width, statusBarFrame.size.height) : 0.0;
+    return statusBarOffset;
+}
+
+- (void) rePositionViews {
+    if ([_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop]) {
+        [self.webView setFrame:CGRectMake(self.webView.frame.origin.x, TOOLBAR_HEIGHT, self.webView.frame.size.width, self.webView.frame.size.height)];
+        [self.toolbar setFrame:CGRectMake(self.toolbar.frame.origin.x, [self getStatusBarOffset], self.toolbar.frame.size.width, self.toolbar.frame.size.height)];
+    }
+}
+
+// Helper function to convert hex color string to UIColor
+// Assumes input like "#00FF00" (#RRGGBB).
+// Taken from https://stackoverflow.com/questions/1560081/how-can-i-create-a-uicolor-from-a-hex-string
+- (UIColor *)colorFromHexString:(NSString *)hexString {
+    unsigned rgbValue = 0;
+    NSScanner *scanner = [NSScanner scannerWithString:hexString];
+    [scanner setScanLocation:1]; // bypass '#' character
+    [scanner scanHexInt:&rgbValue];
+    return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
+}
+
+#pragma mark UIWebViewDelegate
+
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+    // loading url, start spinner, update back/forward
+
+    self.addressLabel.text = NSLocalizedString(@"Loading...", nil);
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+
+    NSLog(_browserOptions.hidespinner ? @"Yes" : @"No");
+    if(!_browserOptions.hidespinner) {
+        [self.spinner startAnimating];
+    }
+
+    return [self.navigationDelegate webViewDidStartLoad:theWebView];
+}
+
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+    if (isTopLevelNavigation) {
+        self.currentURL = request.URL;
+    }
+    return [self.navigationDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    // update url, stop spinner, update back/forward
+
+    self.addressLabel.text = [self.currentURL absoluteString];
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+
+    [self.spinner stopAnimating];
+
+    // Work around a bug where the first time a PDF is opened, all UIWebViews
+    // reload their User-Agent from NSUserDefaults.
+    // This work-around makes the following assumptions:
+    // 1. The app has only a single Cordova Webview. If not, then the app should
+    //    take it upon themselves to load a PDF in the background as a part of
+    //    their start-up flow.
+    // 2. That the PDF does not require any additional network requests. We change
+    //    the user-agent here back to that of the CDVViewController, so requests
+    //    from it must pass through its white-list. This *does* break PDFs that
+    //    contain links to other remote PDF/websites.
+    // More info at https://issues.apache.org/jira/browse/CB-2225
+    BOOL isPDF = [@"true" isEqualToString :[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]];
+    if (isPDF) {
+        [CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken];
+    }
+
+    [self.navigationDelegate webViewDidFinishLoad:theWebView];
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    // log fail message, stop spinner, update back/forward
+    NSLog(@"webView:didFailLoadWithError - %ld: %@", (long)error.code, [error localizedDescription]);
+
+    self.backButton.enabled = theWebView.canGoBack;
+    self.forwardButton.enabled = theWebView.canGoForward;
+    [self.spinner stopAnimating];
+
+    self.addressLabel.text = NSLocalizedString(@"Load Error", nil);
+
+    [self.navigationDelegate webView:theWebView didFailLoadWithError:error];
+}
+
+#pragma mark CDVScreenOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+        return [self.orientationDelegate shouldAutorotate];
+    }
+    return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+        return [self.orientationDelegate supportedInterfaceOrientations];
+    }
+
+    return 1 << UIInterfaceOrientationPortrait;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
+@end
+
+@implementation CDVInAppBrowserOptions
+
+- (id)init
+{
+    if (self = [super init]) {
+        // default values
+        self.location = YES;
+        self.toolbar = YES;
+        self.closebuttoncaption = nil;
+        self.toolbarposition = kInAppBrowserToolbarBarPositionBottom;
+        self.clearcache = NO;
+        self.clearsessioncache = NO;
+        self.hidespinner = NO;
+
+        self.enableviewportscale = NO;
+        self.mediaplaybackrequiresuseraction = NO;
+        self.allowinlinemediaplayback = NO;
+        self.keyboarddisplayrequiresuseraction = YES;
+        self.suppressesincrementalrendering = NO;
+        self.hidden = NO;
+        self.disallowoverscroll = NO;
+        self.hidenavigationbuttons = NO;
+        self.closebuttoncolor = nil;
+        self.toolbarcolor = nil;
+        self.toolbartranslucent = YES;
+    }
+
+    return self;
+}
+
++ (CDVInAppBrowserOptions*)parseOptions:(NSString*)options
+{
+    CDVInAppBrowserOptions* obj = [[CDVInAppBrowserOptions alloc] init];
+
+    // NOTE: this parsing does not handle quotes within values
+    NSArray* pairs = [options componentsSeparatedByString:@","];
+
+    // parse keys and values, set the properties
+    for (NSString* pair in pairs) {
+        NSArray* keyvalue = [pair componentsSeparatedByString:@"="];
+
+        if ([keyvalue count] == 2) {
+            NSString* key = [[keyvalue objectAtIndex:0] lowercaseString];
+            NSString* value = [keyvalue objectAtIndex:1];
+            NSString* value_lc = [value lowercaseString];
+
+            BOOL isBoolean = [value_lc isEqualToString:@"yes"] || [value_lc isEqualToString:@"no"];
+            NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
+            [numberFormatter setAllowsFloats:YES];
+            BOOL isNumber = [numberFormatter numberFromString:value_lc] != nil;
+
+            // set the property according to the key name
+            if ([obj respondsToSelector:NSSelectorFromString(key)]) {
+                if (isNumber) {
+                    [obj setValue:[numberFormatter numberFromString:value_lc] forKey:key];
+                } else if (isBoolean) {
+                    [obj setValue:[NSNumber numberWithBool:[value_lc isEqualToString:@"yes"]] forKey:key];
+                } else {
+                    [obj setValue:value forKey:key];
+                }
+            }
+        }
+    }
+
+    return obj;
+}
+
+@end
+
+@implementation CDVInAppBrowserNavigationController : UINavigationController
+
+- (void) dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
+    if ( self.presentedViewController) {
+        [super dismissViewControllerAnimated:flag completion:completion];
+    }
+}
+
+- (void) viewDidLoad {
+
+    CGRect statusBarFrame = [self invertFrameIfNeeded:[UIApplication sharedApplication].statusBarFrame];
+    statusBarFrame.size.height = STATUSBAR_HEIGHT;
+    // simplified from: http://stackoverflow.com/a/25669695/219684
+
+    UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:statusBarFrame];
+    bgToolbar.barStyle = UIBarStyleDefault;
+    [bgToolbar setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
+    [self.view addSubview:bgToolbar];
+
+    [super viewDidLoad];
+}
+
+- (CGRect) invertFrameIfNeeded:(CGRect)rect {
+    // We need to invert since on iOS 7 frames are always in Portrait context
+    if (!IsAtLeastiOSVersion(@"8.0")) {
+        if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
+            CGFloat temp = rect.size.width;
+            rect.size.width = rect.size.height;
+            rect.size.height = temp;
+        }
+        rect.origin = CGPointZero;
+    }
+    return rect;
+}
+
+#pragma mark CDVScreenOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+        return [self.orientationDelegate shouldAutorotate];
+    }
+    return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+        return [self.orientationDelegate supportedInterfaceOrientations];
+    }
+
+    return 1 << UIInterfaceOrientationPortrait;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-qrscanner/QRScanner.swift b/platforms/ios/dlapp/Plugins/cordova-plugin-qrscanner/QRScanner.swift
new file mode 100644
index 0000000..1397edf
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-qrscanner/QRScanner.swift
@@ -0,0 +1,491 @@
+import Foundation
+import AVFoundation
+
+@objc(QRScanner)
+class QRScanner : CDVPlugin, AVCaptureMetadataOutputObjectsDelegate {
+    
+    class CameraView: UIView {
+        var videoPreviewLayer:AVCaptureVideoPreviewLayer?
+        
+        func interfaceOrientationToVideoOrientation(_ orientation : UIInterfaceOrientation) -> AVCaptureVideoOrientation {
+            switch (orientation) {
+            case UIInterfaceOrientation.portrait:
+                return AVCaptureVideoOrientation.portrait;
+            case UIInterfaceOrientation.portraitUpsideDown:
+                return AVCaptureVideoOrientation.portraitUpsideDown;
+            case UIInterfaceOrientation.landscapeLeft:
+                return AVCaptureVideoOrientation.landscapeLeft;
+            case UIInterfaceOrientation.landscapeRight:
+                return AVCaptureVideoOrientation.landscapeRight;
+            default:
+                return AVCaptureVideoOrientation.portraitUpsideDown;
+            }
+        }
+
+        override func layoutSubviews() {
+            super.layoutSubviews();
+            if let sublayers = self.layer.sublayers {
+                for layer in sublayers {
+                    layer.frame = self.bounds;
+                }
+            }
+            
+            self.videoPreviewLayer?.connection?.videoOrientation = interfaceOrientationToVideoOrientation(UIApplication.shared.statusBarOrientation);
+        }
+        
+        
+        func addPreviewLayer(_ previewLayer:AVCaptureVideoPreviewLayer?) {
+            previewLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill
+            previewLayer!.frame = self.bounds
+            self.layer.addSublayer(previewLayer!)
+            self.videoPreviewLayer = previewLayer;
+        }
+        
+        func removePreviewLayer() {
+            if self.videoPreviewLayer != nil {
+                self.videoPreviewLayer!.removeFromSuperlayer()
+                self.videoPreviewLayer = nil
+            }
+        }
+    }
+
+    var cameraView: CameraView!
+    var captureSession:AVCaptureSession?
+    var captureVideoPreviewLayer:AVCaptureVideoPreviewLayer?
+    var metaOutput: AVCaptureMetadataOutput?
+
+    var currentCamera: Int = 0;
+    var frontCamera: AVCaptureDevice?
+    var backCamera: AVCaptureDevice?
+
+    var scanning: Bool = false
+    var paused: Bool = false
+    var nextScanningCommand: CDVInvokedUrlCommand?
+
+    enum QRScannerError: Int32 {
+        case unexpected_error = 0,
+        camera_access_denied = 1,
+        camera_access_restricted = 2,
+        back_camera_unavailable = 3,
+        front_camera_unavailable = 4,
+        camera_unavailable = 5,
+        scan_canceled = 6,
+        light_unavailable = 7,
+        open_settings_unavailable = 8
+    }
+
+    enum CaptureError: Error {
+        case backCameraUnavailable
+        case frontCameraUnavailable
+        case couldNotCaptureInput(error: NSError)
+    }
+
+    enum LightError: Error {
+        case torchUnavailable
+    }
+
+    override func pluginInitialize() {
+        super.pluginInitialize()
+        NotificationCenter.default.addObserver(self, selector: #selector(pageDidLoad), name: NSNotification.Name.CDVPageDidLoad, object: nil)
+        self.cameraView = CameraView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
+        self.cameraView.autoresizingMask = [.flexibleWidth, .flexibleHeight];
+    }
+
+    func sendErrorCode(command: CDVInvokedUrlCommand, error: QRScannerError){
+        let pluginResult = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: error.rawValue)
+        commandDelegate!.send(pluginResult, callbackId:command.callbackId)
+    }
+
+    // utility method
+    @objc func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
+        if #available(iOS 8.0, *) {
+            DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {
+                if (background != nil) {
+                    background!()
+                }
+                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay * Double(NSEC_PER_SEC)) {
+                    if(completion != nil){
+                        completion!()
+                    }
+                }
+            }
+        } else {
+            // Fallback for iOS < 8.0
+            if(background != nil){
+                background!()
+            }
+            if(completion != nil){
+                completion!()
+            }
+        }
+    }
+
+    @objc func prepScanner(command: CDVInvokedUrlCommand) -> Bool{
+        let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
+        if (status == AVAuthorizationStatus.restricted) {
+            self.sendErrorCode(command: command, error: QRScannerError.camera_access_restricted)
+            return false
+        } else if status == AVAuthorizationStatus.denied {
+            self.sendErrorCode(command: command, error: QRScannerError.camera_access_denied)
+            return false
+        }
+        do {
+            if (captureSession?.isRunning != true){
+                cameraView.backgroundColor = UIColor.clear
+                self.webView!.superview!.insertSubview(cameraView, belowSubview: self.webView!)
+                let availableVideoDevices =  AVCaptureDevice.devices(for: AVMediaType.video)
+                for device in availableVideoDevices {
+                    if device.position == AVCaptureDevice.Position.back {
+                        backCamera = device
+                    }
+                    else if device.position == AVCaptureDevice.Position.front {
+                        frontCamera = device
+                    }
+                }
+                // older iPods have no back camera
+                if(backCamera == nil){
+                    currentCamera = 1
+                }
+                let input: AVCaptureDeviceInput
+                input = try self.createCaptureDeviceInput()
+                captureSession = AVCaptureSession()
+                captureSession!.addInput(input)
+                metaOutput = AVCaptureMetadataOutput()
+                captureSession!.addOutput(metaOutput!)
+                metaOutput!.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
+                metaOutput!.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
+                captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
+                cameraView.addPreviewLayer(captureVideoPreviewLayer)
+                captureSession!.startRunning()
+            }
+            return true
+        } catch CaptureError.backCameraUnavailable {
+            self.sendErrorCode(command: command, error: QRScannerError.back_camera_unavailable)
+        } catch CaptureError.frontCameraUnavailable {
+            self.sendErrorCode(command: command, error: QRScannerError.front_camera_unavailable)
+        } catch CaptureError.couldNotCaptureInput(let error){
+            print(error.localizedDescription)
+            self.sendErrorCode(command: command, error: QRScannerError.camera_unavailable)
+        } catch {
+            self.sendErrorCode(command: command, error: QRScannerError.unexpected_error)
+        }
+        return false
+    }
+
+    @objc func createCaptureDeviceInput() throws -> AVCaptureDeviceInput {
+        var captureDevice: AVCaptureDevice
+        if(currentCamera == 0){
+            if(backCamera != nil){
+                captureDevice = backCamera!
+            } else {
+                throw CaptureError.backCameraUnavailable
+            }
+        } else {
+            if(frontCamera != nil){
+                captureDevice = frontCamera!
+            } else {
+                throw CaptureError.frontCameraUnavailable
+            }
+        }
+        let captureDeviceInput: AVCaptureDeviceInput
+        do {
+            captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
+        } catch let error as NSError {
+            throw CaptureError.couldNotCaptureInput(error: error)
+        }
+        return captureDeviceInput
+    }
+
+    @objc func makeOpaque(){
+        self.webView?.isOpaque = false
+        self.webView?.backgroundColor = UIColor.clear
+    }
+
+    @objc func boolToNumberString(bool: Bool) -> String{
+        if(bool) {
+            return "1"
+        } else {
+            return "0"
+        }
+    }
+
+    @objc func configureLight(command: CDVInvokedUrlCommand, state: Bool){
+        var useMode = AVCaptureDevice.TorchMode.on
+        if(state == false){
+            useMode = AVCaptureDevice.TorchMode.off
+        }
+        do {
+            // torch is only available for back camera
+            if(backCamera == nil || backCamera!.hasTorch == false || backCamera!.isTorchAvailable == false || backCamera!.isTorchModeSupported(useMode) == false){
+                throw LightError.torchUnavailable
+            }
+            try backCamera!.lockForConfiguration()
+            backCamera!.torchMode = useMode
+            backCamera!.unlockForConfiguration()
+            self.getStatus(command)
+        } catch LightError.torchUnavailable {
+            self.sendErrorCode(command: command, error: QRScannerError.light_unavailable)
+        } catch let error as NSError {
+            print(error.localizedDescription)
+            self.sendErrorCode(command: command, error: QRScannerError.unexpected_error)
+        }
+    }
+
+    // This method processes metadataObjects captured by iOS.
+    func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
+        if metadataObjects.count == 0 || scanning == false {
+            // while nothing is detected, or if scanning is false, do nothing.
+            return
+        }
+        let found = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
+        if found.type == AVMetadataObject.ObjectType.qr && found.stringValue != nil {
+            scanning = false
+            let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: found.stringValue)
+            commandDelegate!.send(pluginResult, callbackId: nextScanningCommand?.callbackId!)
+            nextScanningCommand = nil
+        }
+    }
+
+    @objc func pageDidLoad() {
+        self.webView?.isOpaque = false
+        self.webView?.backgroundColor = UIColor.clear
+    }
+
+    // ---- BEGIN EXTERNAL API ----
+
+    @objc func prepare(_ command: CDVInvokedUrlCommand){
+        let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
+        if (status == AVAuthorizationStatus.notDetermined) {
+            // Request permission before preparing scanner
+            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted) -> Void in
+                // attempt to prepScanner only after the request returns
+                self.backgroundThread(delay: 0, completion: {
+                    if(self.prepScanner(command: command)){
+                        self.getStatus(command)
+                    }
+                })
+            })
+        } else {
+            if(self.prepScanner(command: command)){
+                self.getStatus(command)
+            }
+        }
+    }
+
+    @objc func scan(_ command: CDVInvokedUrlCommand){
+        if(self.prepScanner(command: command)){
+            nextScanningCommand = command
+            scanning = true
+        }
+    }
+
+    @objc func cancelScan(_ command: CDVInvokedUrlCommand){
+        if(self.prepScanner(command: command)){
+            scanning = false
+            if(nextScanningCommand != nil){
+                self.sendErrorCode(command: nextScanningCommand!, error: QRScannerError.scan_canceled)
+            }
+            self.getStatus(command)
+        }
+    }
+
+    @objc func show(_ command: CDVInvokedUrlCommand) {
+        self.webView?.isOpaque = false
+        self.webView?.backgroundColor = UIColor.clear
+        self.getStatus(command)
+    }
+
+    @objc func hide(_ command: CDVInvokedUrlCommand) {
+        self.makeOpaque()
+        self.getStatus(command)
+    }
+
+    @objc func pausePreview(_ command: CDVInvokedUrlCommand) {
+        if(scanning){
+            paused = true;
+            scanning = false;
+        }
+        captureVideoPreviewLayer?.connection?.isEnabled = false
+        self.getStatus(command)
+    }
+
+    @objc func resumePreview(_ command: CDVInvokedUrlCommand) {
+        if(paused){
+            paused = false;
+            scanning = true;
+        }
+        captureVideoPreviewLayer?.connection?.isEnabled = true
+        self.getStatus(command)
+    }
+
+    // backCamera is 0, frontCamera is 1
+
+    @objc func useCamera(_ command: CDVInvokedUrlCommand){
+        let index = command.arguments[0] as! Int
+        if(currentCamera != index){
+            // camera change only available if both backCamera and frontCamera exist
+            if(backCamera != nil && frontCamera != nil){
+                // switch camera
+                currentCamera = index
+                if(self.prepScanner(command: command)){
+                    do {
+                        captureSession!.beginConfiguration()
+                        let currentInput = captureSession?.inputs[0] as! AVCaptureDeviceInput
+                        captureSession!.removeInput(currentInput)
+                        let input = try self.createCaptureDeviceInput()
+                        captureSession!.addInput(input)
+                        captureSession!.commitConfiguration()
+                        self.getStatus(command)
+                    } catch CaptureError.backCameraUnavailable {
+                        self.sendErrorCode(command: command, error: QRScannerError.back_camera_unavailable)
+                    } catch CaptureError.frontCameraUnavailable {
+                        self.sendErrorCode(command: command, error: QRScannerError.front_camera_unavailable)
+                    } catch CaptureError.couldNotCaptureInput(let error){
+                        print(error.localizedDescription)
+                        self.sendErrorCode(command: command, error: QRScannerError.camera_unavailable)
+                    } catch {
+                        self.sendErrorCode(command: command, error: QRScannerError.unexpected_error)
+                    }
+
+                }
+            } else {
+                if(backCamera == nil){
+                    self.sendErrorCode(command: command, error: QRScannerError.back_camera_unavailable)
+                } else {
+                    self.sendErrorCode(command: command, error: QRScannerError.front_camera_unavailable)
+                }
+            }
+        } else {
+            // immediately return status if camera is unchanged
+            self.getStatus(command)
+        }
+    }
+
+    @objc func enableLight(_ command: CDVInvokedUrlCommand) {
+        if(self.prepScanner(command: command)){
+            self.configureLight(command: command, state: true)
+        }
+    }
+
+    @objc func disableLight(_ command: CDVInvokedUrlCommand) {
+        if(self.prepScanner(command: command)){
+            self.configureLight(command: command, state: false)
+        }
+    }
+
+    @objc func destroy(_ command: CDVInvokedUrlCommand) {
+        self.makeOpaque()
+        if(self.captureSession != nil){
+            backgroundThread(delay: 0, background: {
+                self.captureSession!.stopRunning()
+                self.cameraView.removePreviewLayer()
+                self.captureVideoPreviewLayer = nil
+                self.metaOutput = nil
+                self.captureSession = nil
+                self.currentCamera = 0
+                self.frontCamera = nil
+                self.backCamera = nil
+            }, completion: {
+                self.getStatus(command)
+            })
+        } else {
+            self.getStatus(command)
+        }
+    }
+
+    @objc func getStatus(_ command: CDVInvokedUrlCommand){
+
+        let authorizationStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video);
+
+        var authorized = false
+        if(authorizationStatus == AVAuthorizationStatus.authorized){
+            authorized = true
+        }
+
+        var denied = false
+        if(authorizationStatus == AVAuthorizationStatus.denied){
+            denied = true
+        }
+
+        var restricted = false
+        if(authorizationStatus == AVAuthorizationStatus.restricted){
+            restricted = true
+        }
+
+        var prepared = false
+        if(captureSession?.isRunning == true){
+            prepared = true
+        }
+
+        var previewing = false
+        if(captureVideoPreviewLayer != nil){
+            previewing = captureVideoPreviewLayer!.connection!.isEnabled
+        }
+
+        var showing = false
+        if(self.webView!.backgroundColor == UIColor.clear){
+            showing = true
+        }
+
+        var lightEnabled = false
+        if(backCamera?.torchMode == AVCaptureDevice.TorchMode.on){
+            lightEnabled = true
+        }
+
+        var canOpenSettings = false
+        if #available(iOS 8.0, *) {
+            canOpenSettings = true
+        }
+
+        var canEnableLight = false
+        if(backCamera?.hasTorch == true && backCamera?.isTorchAvailable == true && backCamera?.isTorchModeSupported(AVCaptureDevice.TorchMode.on) == true){
+            canEnableLight = true
+        }
+
+        var canChangeCamera = false;
+        if(backCamera != nil && frontCamera != nil){
+            canChangeCamera = true
+        }
+
+        let status = [
+            "authorized": boolToNumberString(bool: authorized),
+            "denied": boolToNumberString(bool: denied),
+            "restricted": boolToNumberString(bool: restricted),
+            "prepared": boolToNumberString(bool: prepared),
+            "scanning": boolToNumberString(bool: scanning),
+            "previewing": boolToNumberString(bool: previewing),
+            "showing": boolToNumberString(bool: showing),
+            "lightEnabled": boolToNumberString(bool: lightEnabled),
+            "canOpenSettings": boolToNumberString(bool: canOpenSettings),
+            "canEnableLight": boolToNumberString(bool: canEnableLight),
+            "canChangeCamera": boolToNumberString(bool: canChangeCamera),
+            "currentCamera": String(currentCamera)
+        ]
+
+        let pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: status)
+        commandDelegate!.send(pluginResult, callbackId:command.callbackId)
+    }
+
+    @objc func openSettings(_ command: CDVInvokedUrlCommand) {
+        if #available(iOS 10.0, *) {
+            guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
+            return
+        }
+        if UIApplication.shared.canOpenURL(settingsUrl) {
+            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
+                self.getStatus(command)
+            })
+        } else {
+            self.sendErrorCode(command: command, error: QRScannerError.open_settings_unavailable)
+            }
+        } else {
+            // pre iOS 10.0
+            if #available(iOS 8.0, *) {
+                UIApplication.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
+                self.getStatus(command)
+            } else {
+                self.sendErrorCode(command: command, error: QRScannerError.open_settings_unavailable)
+            }
+        }
+    }
+}
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.h b/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.h
new file mode 100644
index 0000000..0be08cc
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.h
@@ -0,0 +1,50 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+#import <Cordova/CDVInvokedUrlCommand.h>
+
+@interface CDVStatusBar : CDVPlugin {
+    @protected
+    BOOL _statusBarOverlaysWebView;
+    UIView* _statusBarBackgroundView;
+    BOOL _uiviewControllerBasedStatusBarAppearance;
+    UIColor* _statusBarBackgroundColor;
+    NSString* _eventsCallbackId;
+}
+
+@property (atomic, assign) BOOL statusBarOverlaysWebView;
+@property (atomic, assign) BOOL statusBarVisible;
+
+- (void) overlaysWebView:(CDVInvokedUrlCommand*)command;
+
+- (void) styleDefault:(CDVInvokedUrlCommand*)command;
+- (void) styleLightContent:(CDVInvokedUrlCommand*)command;
+- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command;
+- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command;
+
+- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command;
+- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command;
+
+- (void) hide:(CDVInvokedUrlCommand*)command;
+- (void) show:(CDVInvokedUrlCommand*)command;
+    
+- (void) _ready:(CDVInvokedUrlCommand*)command;
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.m b/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.m
new file mode 100644
index 0000000..c67f137
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-statusbar/CDVStatusBar.m
@@ -0,0 +1,479 @@
+/*
+ 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.
+ */
+
+/*
+ NOTE: plugman/cordova cli should have already installed this,
+ but you need the value UIViewControllerBasedStatusBarAppearance
+ in your Info.plist as well to set the styles in iOS 7
+ */
+
+#import "CDVStatusBar.h"
+#import <objc/runtime.h>
+#import <Cordova/CDVViewController.h>
+
+static const void *kHideStatusBar = &kHideStatusBar;
+static const void *kStatusBarStyle = &kStatusBarStyle;
+
+@interface CDVViewController (StatusBar)
+
+@property (nonatomic, retain) id sb_hideStatusBar;
+@property (nonatomic, retain) id sb_statusBarStyle;
+
+@end
+
+@implementation CDVViewController (StatusBar)
+
+@dynamic sb_hideStatusBar;
+@dynamic sb_statusBarStyle;
+
+- (id)sb_hideStatusBar {
+    return objc_getAssociatedObject(self, kHideStatusBar);
+}
+
+- (void)setSb_hideStatusBar:(id)newHideStatusBar {
+    objc_setAssociatedObject(self, kHideStatusBar, newHideStatusBar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (id)sb_statusBarStyle {
+    return objc_getAssociatedObject(self, kStatusBarStyle);
+}
+
+- (void)setSb_statusBarStyle:(id)newStatusBarStyle {
+    objc_setAssociatedObject(self, kStatusBarStyle, newStatusBarStyle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (BOOL) prefersStatusBarHidden {
+    return [self.sb_hideStatusBar boolValue];
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle
+{
+    return (UIStatusBarStyle)[self.sb_statusBarStyle intValue];
+}
+
+@end
+
+
+@interface CDVStatusBar () <UIScrollViewDelegate>
+- (void)fireTappedEvent;
+- (void)updateIsVisible:(BOOL)visible;
+@end
+
+@implementation CDVStatusBar
+
+- (id)settingForKey:(NSString*)key
+{
+    return [self.commandDelegate.settings objectForKey:[key lowercaseString]];
+}
+
+- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
+{
+    if ([keyPath isEqual:@"statusBarHidden"]) {
+        NSNumber* newValue = [change objectForKey:NSKeyValueChangeNewKey];
+        [self updateIsVisible:![newValue boolValue]];
+    }
+}
+
+-(void)cordovaViewWillAppear:(NSNotification*)notification
+{
+    [self resizeWebView];
+}
+
+-(void)statusBarDidChangeFrame:(NSNotification*)notification
+{
+    //add a small delay ( 0.1 seconds ) or statusbar size will be wrong
+    __weak CDVStatusBar* weakSelf = self;
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+        [weakSelf resizeStatusBarBackgroundView];
+        [weakSelf resizeWebView];
+    });
+}
+
+- (void)pluginInitialize
+{
+    // init
+    NSNumber* uiviewControllerBasedStatusBarAppearance = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"];
+    _uiviewControllerBasedStatusBarAppearance = (uiviewControllerBasedStatusBarAppearance == nil || [uiviewControllerBasedStatusBarAppearance boolValue]);
+
+    // observe the statusBarHidden property
+    [[UIApplication sharedApplication] addObserver:self forKeyPath:@"statusBarHidden" options:NSKeyValueObservingOptionNew context:NULL];
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarDidChangeFrame:) name: UIApplicationDidChangeStatusBarFrameNotification object:nil];
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cordovaViewWillAppear:) name: @"CDVViewWillAppearNotification" object:nil];
+
+    _statusBarOverlaysWebView = YES; // default
+
+    [self initializeStatusBarBackgroundView];
+
+    self.viewController.view.autoresizesSubviews = YES;
+
+    NSString* setting;
+
+    setting  = @"StatusBarBackgroundColor";
+    if ([self settingForKey:setting]) {
+        [self _backgroundColorByHexString:[self settingForKey:setting]];
+    }
+
+    setting  = @"StatusBarStyle";
+    if ([self settingForKey:setting]) {
+        [self setStatusBarStyle:[self settingForKey:setting]];
+    }
+
+    setting  = @"StatusBarDefaultScrollToTop";
+    if ([self settingForKey:setting]) {
+        self.webView.scrollView.scrollsToTop = [(NSNumber*)[self settingForKey:setting] boolValue];
+    } else {
+        self.webView.scrollView.scrollsToTop = NO;
+    }
+ 
+    // blank scroll view to intercept status bar taps
+    UIScrollView *fakeScrollView = [[UIScrollView alloc] initWithFrame:UIScreen.mainScreen.bounds];
+    fakeScrollView.delegate = self;
+    fakeScrollView.scrollsToTop = YES;
+    [self.viewController.view addSubview:fakeScrollView]; // Add scrollview to the view heirarchy so that it will begin accepting status bar taps
+    [self.viewController.view sendSubviewToBack:fakeScrollView]; // Send it to the very back of the view heirarchy
+    fakeScrollView.contentSize = CGSizeMake(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height * 2.0f); // Make the scroll view longer than the screen itself
+    fakeScrollView.contentOffset = CGPointMake(0.0f, UIScreen.mainScreen.bounds.size.height); // Scroll down so a tap will take scroll view back to the top
+
+    _statusBarVisible = ![UIApplication sharedApplication].isStatusBarHidden;
+}
+
+- (void)onReset {
+    _eventsCallbackId = nil;
+}
+
+- (void)fireTappedEvent {
+    if (_eventsCallbackId == nil) {
+        return;
+    }
+    NSDictionary* payload = @{@"type": @"tap"};
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:payload];
+    [result setKeepCallbackAsBool:YES];
+    [self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId];
+}
+
+- (void)updateIsVisible:(BOOL)visible {
+    if (_eventsCallbackId == nil) {
+        return;
+    }
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:visible];
+    [result setKeepCallbackAsBool:YES];
+    [self.commandDelegate sendPluginResult:result callbackId:_eventsCallbackId];
+}
+
+- (void) _ready:(CDVInvokedUrlCommand*)command
+{
+    _eventsCallbackId = command.callbackId;
+    [self updateIsVisible:![UIApplication sharedApplication].statusBarHidden];
+    NSString* setting = @"StatusBarOverlaysWebView";
+    if ([self settingForKey:setting]) {
+        self.statusBarOverlaysWebView = [(NSNumber*)[self settingForKey:setting] boolValue];
+        if (self.statusBarOverlaysWebView) {
+            [self resizeWebView];
+        }
+    }
+}
+
+- (void) initializeStatusBarBackgroundView
+{
+    CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
+
+    if ([[UIApplication sharedApplication]statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown &&
+        statusBarFrame.size.height + statusBarFrame.origin.y == [self.viewController.view.window bounds].size.height) {
+
+        // When started in upside-down orientation on iOS 7, status bar will be bound to lower edge of the
+        // screen (statusBarFrame.origin.y will be somewhere around screen height). In this case we need to
+        // correct frame's coordinates
+        statusBarFrame.origin.y = 0;
+    }
+
+    _statusBarBackgroundView = [[UIView alloc] initWithFrame:statusBarFrame];
+    _statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor;
+    _statusBarBackgroundView.autoresizingMask = (UIViewAutoresizingFlexibleWidth  | UIViewAutoresizingFlexibleBottomMargin);
+    _statusBarBackgroundView.autoresizesSubviews = YES;
+}
+
+- (void) setStatusBarOverlaysWebView:(BOOL)statusBarOverlaysWebView
+{
+    // we only care about the latest iOS version or a change in setting
+    if (statusBarOverlaysWebView == _statusBarOverlaysWebView) {
+        return;
+    }
+
+    _statusBarOverlaysWebView = statusBarOverlaysWebView;
+
+    [self resizeWebView];
+
+    if (statusBarOverlaysWebView) {
+
+        [_statusBarBackgroundView removeFromSuperview];
+
+    } else {
+
+        [self initializeStatusBarBackgroundView];
+        [self.webView.superview addSubview:_statusBarBackgroundView];
+
+    }
+
+}
+
+- (BOOL) statusBarOverlaysWebView
+{
+    return _statusBarOverlaysWebView;
+}
+
+- (void) overlaysWebView:(CDVInvokedUrlCommand*)command
+{
+    id value = [command argumentAtIndex:0];
+    if (!([value isKindOfClass:[NSNumber class]])) {
+        value = [NSNumber numberWithBool:YES];
+    }
+
+    self.statusBarOverlaysWebView = [value boolValue];
+}
+
+- (void) refreshStatusBarAppearance
+{
+    SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
+    if ([self.viewController respondsToSelector:sel]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+        [self.viewController performSelector:sel withObject:nil];
+#pragma clang diagnostic pop
+    }
+}
+
+- (void) setStyleForStatusBar:(UIStatusBarStyle)style
+{
+    if (_uiviewControllerBasedStatusBarAppearance) {
+        CDVViewController* vc = (CDVViewController*)self.viewController;
+        vc.sb_statusBarStyle = [NSNumber numberWithInt:style];
+        [self refreshStatusBarAppearance];
+
+    } else {
+        [[UIApplication sharedApplication] setStatusBarStyle:style];
+    }
+}
+
+- (void) setStatusBarStyle:(NSString*)statusBarStyle
+{
+    // default, lightContent, blackTranslucent, blackOpaque
+    NSString* lcStatusBarStyle = [statusBarStyle lowercaseString];
+
+    if ([lcStatusBarStyle isEqualToString:@"default"]) {
+        [self styleDefault:nil];
+    } else if ([lcStatusBarStyle isEqualToString:@"lightcontent"]) {
+        [self styleLightContent:nil];
+    } else if ([lcStatusBarStyle isEqualToString:@"blacktranslucent"]) {
+        [self styleBlackTranslucent:nil];
+    } else if ([lcStatusBarStyle isEqualToString:@"blackopaque"]) {
+        [self styleBlackOpaque:nil];
+    }
+}
+
+- (void) styleDefault:(CDVInvokedUrlCommand*)command
+{
+    [self setStyleForStatusBar:UIStatusBarStyleDefault];
+}
+
+- (void) styleLightContent:(CDVInvokedUrlCommand*)command
+{
+    [self setStyleForStatusBar:UIStatusBarStyleLightContent];
+}
+
+- (void) styleBlackTranslucent:(CDVInvokedUrlCommand*)command
+{
+    [self setStyleForStatusBar:UIStatusBarStyleLightContent];
+}
+
+- (void) styleBlackOpaque:(CDVInvokedUrlCommand*)command
+{
+    [self setStyleForStatusBar:UIStatusBarStyleLightContent];
+}
+
+- (void) backgroundColorByName:(CDVInvokedUrlCommand*)command
+{
+    id value = [command argumentAtIndex:0];
+    if (!([value isKindOfClass:[NSString class]])) {
+        value = @"black";
+    }
+
+    SEL selector = NSSelectorFromString([value stringByAppendingString:@"Color"]);
+    if ([UIColor respondsToSelector:selector]) {
+        _statusBarBackgroundView.backgroundColor = [UIColor performSelector:selector];
+    }
+}
+
+- (void) _backgroundColorByHexString:(NSString*)hexString
+{
+    unsigned int rgbValue = 0;
+    NSScanner* scanner = [NSScanner scannerWithString:hexString];
+    [scanner setScanLocation:1];
+    [scanner scanHexInt:&rgbValue];
+
+    _statusBarBackgroundColor = [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
+    _statusBarBackgroundView.backgroundColor = _statusBarBackgroundColor;
+}
+
+- (void) backgroundColorByHexString:(CDVInvokedUrlCommand*)command
+{
+    NSString* value = [command argumentAtIndex:0];
+    if (!([value isKindOfClass:[NSString class]])) {
+        value = @"#000000";
+    }
+
+    if (![value hasPrefix:@"#"] || [value length] < 7) {
+        return;
+    }
+
+    [self _backgroundColorByHexString:value];
+}
+
+- (void) hideStatusBar
+{
+    if (_uiviewControllerBasedStatusBarAppearance) {
+        CDVViewController* vc = (CDVViewController*)self.viewController;
+        vc.sb_hideStatusBar = [NSNumber numberWithBool:YES];
+        [self refreshStatusBarAppearance];
+
+    } else {
+        UIApplication* app = [UIApplication sharedApplication];
+        [app setStatusBarHidden:YES];
+    }
+}
+
+- (void) hide:(CDVInvokedUrlCommand*)command
+{
+    _statusBarVisible = NO;
+    UIApplication* app = [UIApplication sharedApplication];
+
+    if (!app.isStatusBarHidden)
+    {
+
+        [self hideStatusBar];
+
+        [_statusBarBackgroundView removeFromSuperview];
+
+        [self resizeWebView];
+
+        _statusBarBackgroundView.hidden = YES;
+    }
+}
+
+- (void) showStatusBar
+{
+    if (_uiviewControllerBasedStatusBarAppearance) {
+        CDVViewController* vc = (CDVViewController*)self.viewController;
+        vc.sb_hideStatusBar = [NSNumber numberWithBool:NO];
+        [self refreshStatusBarAppearance];
+
+    } else {
+        UIApplication* app = [UIApplication sharedApplication];
+        [app setStatusBarHidden:NO];
+    }
+}
+
+- (void) show:(CDVInvokedUrlCommand*)command
+{
+    _statusBarVisible = YES;
+    UIApplication* app = [UIApplication sharedApplication];
+
+    if (app.isStatusBarHidden)
+    {
+        [self showStatusBar];
+        [self resizeWebView];
+
+        if (!self.statusBarOverlaysWebView) {
+
+            // there is a possibility that when the statusbar was hidden, it was in a different orientation
+            // from the current one. Therefore we need to expand the statusBarBackgroundView as well to the
+            // statusBar's current size
+            [self resizeStatusBarBackgroundView];
+            [self.webView.superview addSubview:_statusBarBackgroundView];
+
+        }
+
+        _statusBarBackgroundView.hidden = NO;
+    }
+}
+
+-(void)resizeStatusBarBackgroundView {
+    CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
+    CGRect sbBgFrame = _statusBarBackgroundView.frame;
+    sbBgFrame.size = statusBarFrame.size;
+    _statusBarBackgroundView.frame = sbBgFrame;
+}
+
+-(void)resizeWebView
+{
+    BOOL isIOS11 = (IsAtLeastiOSVersion(@"11.0"));
+
+    CGRect bounds = [self.viewController.view.window bounds];
+    if (CGRectEqualToRect(bounds, CGRectZero)) {
+        bounds = [[UIScreen mainScreen] bounds];
+    }
+
+    self.viewController.view.frame = bounds;
+
+    self.webView.frame = bounds;
+
+    CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
+    CGRect frame = self.webView.frame;
+    CGFloat height = statusBarFrame.size.height;
+
+    if (!self.statusBarOverlaysWebView) {
+        frame.origin.y = height;
+    } else {
+        frame.origin.y = height >= 20 ? height - 20 : 0;
+        if (isIOS11) {
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+            if (@available(iOS 11.0, *)) {
+                float safeAreaTop = self.webView.safeAreaInsets.top;
+                if (height >= safeAreaTop && safeAreaTop >0) {
+                    // Sometimes when in-call/recording/hotspot larger status bar is present, the safeAreaTop is 40 but we want frame.origin.y to be 20
+                    frame.origin.y = safeAreaTop == 40 ? 20 : height - safeAreaTop;
+                } else {
+                    frame.origin.y = 0;
+                }
+            }
+#endif
+        }
+    }
+    frame.size.height -= frame.origin.y;
+    self.webView.frame = frame;
+    
+}
+
+- (void) dealloc
+{
+    [[UIApplication sharedApplication] removeObserver:self forKeyPath:@"statusBarHidden"];
+    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
+}
+
+
+#pragma mark - UIScrollViewDelegate
+
+- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
+{
+    [self fireTappedEvent];
+    return NO;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.h b/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.h
new file mode 100644
index 0000000..ed59e22
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.h
@@ -0,0 +1,135 @@
+/*
+ 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.
+ */
+
+#import <Cordova/CDVPlugin.h>
+#import <Cordova/CDVInvokedUrlCommand.h>
+#import <Cordova/CDVScreenOrientationDelegate.h>
+
+#ifdef __CORDOVA_4_0_0
+    #import <Cordova/CDVUIWebViewDelegate.h>
+#else
+    #import <Cordova/CDVWebViewDelegate.h>
+#endif
+
+@interface CDVThemeableBrowserOptions : NSObject {}
+
+@property (nonatomic) BOOL location;
+@property (nonatomic) NSString* closebuttoncaption;
+@property (nonatomic) NSString* toolbarposition;
+@property (nonatomic) BOOL clearcache;
+@property (nonatomic) BOOL clearsessioncache;
+
+@property (nonatomic) NSString* presentationstyle;
+@property (nonatomic) NSString* transitionstyle;
+
+@property (nonatomic) BOOL zoom;
+@property (nonatomic) BOOL mediaplaybackrequiresuseraction;
+@property (nonatomic) BOOL allowinlinemediaplayback;
+@property (nonatomic) BOOL keyboarddisplayrequiresuseraction;
+@property (nonatomic) BOOL suppressesincrementalrendering;
+@property (nonatomic) BOOL hidden;
+@property (nonatomic) BOOL disallowoverscroll;
+
+@property (nonatomic) NSDictionary* statusbar;
+@property (nonatomic) NSDictionary* toolbar;
+@property (nonatomic) NSDictionary* title;
+@property (nonatomic) NSDictionary* backButton;
+@property (nonatomic) NSDictionary* forwardButton;
+@property (nonatomic) NSDictionary* closeButton;
+@property (nonatomic) NSDictionary* menu;
+@property (nonatomic) NSArray* customButtons;
+@property (nonatomic) BOOL backButtonCanClose;
+@property (nonatomic) BOOL disableAnimation;
+@property (nonatomic) BOOL fullscreen;
+
+@end
+
+@class CDVThemeableBrowserViewController;
+
+@interface CDVThemeableBrowser : CDVPlugin {
+    BOOL _injectedIframeBridge;
+}
+
+@property (nonatomic, retain) CDVThemeableBrowserViewController* themeableBrowserViewController;
+@property (nonatomic, copy) NSString* callbackId;
+@property (nonatomic, copy) NSRegularExpression *callbackIdPattern;
+
+- (CDVThemeableBrowserOptions*)parseOptions:(NSString*)options;
+- (void)open:(CDVInvokedUrlCommand*)command;
+- (void)close:(CDVInvokedUrlCommand*)command;
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
+- (void)show:(CDVInvokedUrlCommand*)command;
+- (void)show:(CDVInvokedUrlCommand*)command withAnimation:(BOOL)animated;
+- (void)reload:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVThemeableBrowserViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate, UIActionSheetDelegate>{
+    @private
+    NSString* _userAgent;
+    NSString* _prevUserAgent;
+    NSInteger _userAgentLockToken;
+    UIStatusBarStyle _statusBarStyle;
+    CDVThemeableBrowserOptions *_browserOptions;
+    
+#ifdef __CORDOVA_4_0_0
+    CDVUIWebViewDelegate* _webViewDelegate;
+#else
+    CDVWebViewDelegate* _webViewDelegate;
+#endif
+    
+}
+
+@property (nonatomic, strong) IBOutlet UIWebView* webView;
+@property (nonatomic, strong) IBOutlet UIButton* closeButton;
+@property (nonatomic, strong) IBOutlet UILabel* addressLabel;
+@property (nonatomic, strong) IBOutlet UILabel* titleLabel;
+@property (nonatomic, strong) IBOutlet UIButton* backButton;
+@property (nonatomic, strong) IBOutlet UIButton* forwardButton;
+@property (nonatomic, strong) IBOutlet UIButton* menuButton;
+@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinner;
+@property (nonatomic, strong) IBOutlet UIView* toolbar;
+
+@property (nonatomic, strong) NSArray* leftButtons;
+@property (nonatomic, strong) NSArray* rightButtons;
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+@property (nonatomic, weak) CDVThemeableBrowser* navigationDelegate;
+@property (nonatomic) NSURL* currentURL;
+@property (nonatomic) CGFloat titleOffset;
+
+- (void)close;
+- (void)reload;
+- (void)navigateTo:(NSURL*)url;
+- (void)showLocationBar:(BOOL)show;
+- (void)showToolBar:(BOOL)show : (NSString*) toolbarPosition;
+- (void)setCloseButtonTitle:(NSString*)title;
+
+- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVThemeableBrowserOptions*) browserOptions navigationDelete:(CDVThemeableBrowser*) navigationDelegate statusBarStyle:(UIStatusBarStyle) statusBarStyle;
+
++ (UIColor *)colorFromRGBA:(NSString *)rgba;
+
+@end
+
+@interface CDVThemeableBrowserNavigationController : UINavigationController
+
+@property (nonatomic, weak) id <CDVScreenOrientationDelegate> orientationDelegate;
+
+@end
+
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.m b/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.m
new file mode 100644
index 0000000..adebd94
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-themeablebrowser/CDVThemeableBrowser.m
@@ -0,0 +1,1635 @@
+/*
+ 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.
+ */
+
+#import "CDVThemeableBrowser.h"
+#import <Cordova/CDVPluginResult.h>
+#import <Cordova/CDVUserAgentUtil.h>
+
+#define    kThemeableBrowserTargetSelf @"_self"
+#define    kThemeableBrowserTargetSystem @"_system"
+#define    kThemeableBrowserTargetBlank @"_blank"
+
+#define    kThemeableBrowserToolbarBarPositionBottom @"bottom"
+#define    kThemeableBrowserToolbarBarPositionTop @"top"
+
+#define    kThemeableBrowserAlignLeft @"left"
+#define    kThemeableBrowserAlignRight @"right"
+
+#define    kThemeableBrowserPropEvent @"event"
+#define    kThemeableBrowserPropLabel @"label"
+#define    kThemeableBrowserPropColor @"color"
+#define    kThemeableBrowserPropHeight @"height"
+#define    kThemeableBrowserPropImage @"image"
+#define    kThemeableBrowserPropWwwImage @"wwwImage"
+#define    kThemeableBrowserPropImagePressed @"imagePressed"
+#define    kThemeableBrowserPropWwwImagePressed @"wwwImagePressed"
+#define    kThemeableBrowserPropWwwImageDensity @"wwwImageDensity"
+#define    kThemeableBrowserPropStaticText @"staticText"
+#define    kThemeableBrowserPropShowPageTitle @"showPageTitle"
+#define    kThemeableBrowserPropAlign @"align"
+#define    kThemeableBrowserPropTitle @"title"
+#define    kThemeableBrowserPropCancel @"cancel"
+#define    kThemeableBrowserPropItems @"items"
+
+#define    kThemeableBrowserEmitError @"ThemeableBrowserError"
+#define    kThemeableBrowserEmitWarning @"ThemeableBrowserWarning"
+#define    kThemeableBrowserEmitCodeCritical @"critical"
+#define    kThemeableBrowserEmitCodeLoadFail @"loadfail"
+#define    kThemeableBrowserEmitCodeUnexpected @"unexpected"
+#define    kThemeableBrowserEmitCodeUndefined @"undefined"
+
+#define    TOOLBAR_DEF_HEIGHT 44.0
+#define    LOCATIONBAR_HEIGHT 21.0
+#define    FOOTER_HEIGHT ((TOOLBAR_HEIGHT) + (LOCATIONBAR_HEIGHT))
+
+#pragma mark CDVThemeableBrowser
+
+@interface CDVThemeableBrowser () {
+    BOOL _isShown;
+    int _framesOpened;  // number of frames opened since the last time browser exited
+    NSURL *initUrl;  // initial URL ThemeableBrowser opened with
+    NSURL *originalUrl;
+}
+@end
+
+@implementation CDVThemeableBrowser
+
+#ifdef __CORDOVA_4_0_0
+- (void)pluginInitialize
+{
+    _isShown = NO;
+    _framesOpened = 0;
+    _callbackIdPattern = nil;
+}
+#else
+- (CDVThemeableBrowser*)initWithWebView:(UIWebView*)theWebView
+{
+    self = [super initWithWebView:theWebView];
+    if (self != nil) {
+        _isShown = NO;
+        _framesOpened = 0;
+        _callbackIdPattern = nil;
+    }
+
+    return self;
+}
+#endif
+
+- (void)onReset
+{
+    [self close:nil];
+}
+
+- (void)close:(CDVInvokedUrlCommand*)command
+{
+    if (self.themeableBrowserViewController == nil) {
+        [self emitWarning:kThemeableBrowserEmitCodeUnexpected
+              withMessage:@"Close called but already closed."];
+        return;
+    }
+    // Things are cleaned up in browserExit.
+    [self.themeableBrowserViewController close];
+}
+
+- (BOOL) isSystemUrl:(NSURL*)url
+{
+  NSDictionary *systemUrls = @{
+    @"itunes.apple.com": @YES,
+    @"search.itunes.apple.com": @YES,
+    @"appsto.re": @YES
+  };
+
+  if (systemUrls[[url host]]) {
+    return YES;
+  }
+
+  return NO;
+}
+
+- (void)open:(CDVInvokedUrlCommand*)command
+{
+    CDVPluginResult* pluginResult;
+
+    NSString* url = [command argumentAtIndex:0];
+    NSString* target = [command argumentAtIndex:1 withDefault:kThemeableBrowserTargetSelf];
+    NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
+
+    self.callbackId = command.callbackId;
+
+    if (url != nil) {
+#ifdef __CORDOVA_4_0_0
+        NSURL* baseUrl = [self.webViewEngine URL];
+#else
+        NSURL* baseUrl = [self.webView.request URL];
+#endif
+        NSURL* absoluteUrl = [[NSURL URLWithString:url relativeToURL:baseUrl] absoluteURL];
+
+        initUrl = absoluteUrl;
+
+        if ([self isSystemUrl:absoluteUrl]) {
+            target = kThemeableBrowserTargetSystem;
+        }
+
+        if ([target isEqualToString:kThemeableBrowserTargetSelf]) {
+            [self openInCordovaWebView:absoluteUrl withOptions:options];
+        } else if ([target isEqualToString:kThemeableBrowserTargetSystem]) {
+            [self openInSystem:absoluteUrl];
+        } else { // _blank or anything else
+            [self openInThemeableBrowser:absoluteUrl withOptions:options];
+        }
+
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
+    } else {
+        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"incorrect number of arguments"];
+    }
+
+    [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+}
+
+- (void)reload:(CDVInvokedUrlCommand*)command
+{
+    if (self.themeableBrowserViewController) {
+        [self.themeableBrowserViewController reload];
+    }
+}
+
+- (CDVThemeableBrowserOptions*)parseOptions:(NSString*)options
+{
+    CDVThemeableBrowserOptions* obj = [[CDVThemeableBrowserOptions alloc] init];
+
+    if (options && [options length] > 0) {
+        // Min support, iOS 5. We will use the JSON parser that comes with iOS
+        // 5.
+        NSError *error = nil;
+        NSData *data = [options dataUsingEncoding:NSUTF8StringEncoding];
+        id jsonObj = [NSJSONSerialization
+                      JSONObjectWithData:data
+                      options:0
+                      error:&error];
+
+        if(error) {
+            [self emitError:kThemeableBrowserEmitCodeCritical
+                withMessage:[NSString stringWithFormat:@"Invalid JSON %@", error]];
+        } else if([jsonObj isKindOfClass:[NSDictionary class]]) {
+            NSDictionary *dict = jsonObj;
+            for (NSString *key in dict) {
+                if ([obj respondsToSelector:NSSelectorFromString(key)]) {
+                    [obj setValue:dict[key] forKey:key];
+                }
+            }
+        }
+    } else {
+        [self emitWarning:kThemeableBrowserEmitCodeUndefined
+            withMessage:@"No config was given, defaults will be used, which is quite boring."];
+    }
+
+    return obj;
+}
+
+- (void)openInThemeableBrowser:(NSURL*)url withOptions:(NSString*)options
+{
+    CDVThemeableBrowserOptions* browserOptions = [self parseOptions:options];
+
+    // Among all the options, there are a few that ThemedBrowser would like to
+    // disable, since ThemedBrowser's purpose is to provide an integrated look
+    // and feel that is consistent across platforms. We'd do this hack to
+    // minimize changes from the original ThemeableBrowser so when merge from the
+    // ThemeableBrowser is needed, it wouldn't be super pain in the ass.
+    browserOptions.toolbarposition = kThemeableBrowserToolbarBarPositionTop;
+
+    if (browserOptions.clearcache) {
+        NSHTTPCookie *cookie;
+        NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+        for (cookie in [storage cookies])
+        {
+            if (![cookie.domain isEqual: @".^filecookies^"]) {
+                [storage deleteCookie:cookie];
+            }
+        }
+    }
+
+    if (browserOptions.clearsessioncache) {
+        NSHTTPCookie *cookie;
+        NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+        for (cookie in [storage cookies])
+        {
+            if (![cookie.domain isEqual: @".^filecookies^"] && cookie.isSessionOnly) {
+                [storage deleteCookie:cookie];
+            }
+        }
+    }
+
+    if (self.themeableBrowserViewController == nil) {
+        NSString* originalUA = [CDVUserAgentUtil originalUserAgent];
+        self.themeableBrowserViewController = [[CDVThemeableBrowserViewController alloc]
+                                               initWithUserAgent:originalUA prevUserAgent:[self.commandDelegate userAgent]
+                                               browserOptions: browserOptions
+                                               navigationDelete:self
+                                               statusBarStyle:[UIApplication sharedApplication].statusBarStyle];
+
+        if ([self.viewController conformsToProtocol:@protocol(CDVScreenOrientationDelegate)]) {
+            self.themeableBrowserViewController.orientationDelegate = (UIViewController <CDVScreenOrientationDelegate>*)self.viewController;
+        }
+    }
+
+    [self.themeableBrowserViewController showLocationBar:browserOptions.location];
+    [self.themeableBrowserViewController showToolBar:YES:browserOptions.toolbarposition];
+    if (browserOptions.closebuttoncaption != nil) {
+        // [self.themeableBrowserViewController setCloseButtonTitle:browserOptions.closebuttoncaption];
+    }
+    // Set Presentation Style
+    UIModalPresentationStyle presentationStyle = UIModalPresentationFullScreen; // default
+    if (browserOptions.presentationstyle != nil) {
+        if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"pagesheet"]) {
+            presentationStyle = UIModalPresentationPageSheet;
+        } else if ([[browserOptions.presentationstyle lowercaseString] isEqualToString:@"formsheet"]) {
+            presentationStyle = UIModalPresentationFormSheet;
+        }
+    }
+    self.themeableBrowserViewController.modalPresentationStyle = presentationStyle;
+
+    // Set Transition Style
+    UIModalTransitionStyle transitionStyle = UIModalTransitionStyleCoverVertical; // default
+    if (browserOptions.transitionstyle != nil) {
+        if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"fliphorizontal"]) {
+            transitionStyle = UIModalTransitionStyleFlipHorizontal;
+        } else if ([[browserOptions.transitionstyle lowercaseString] isEqualToString:@"crossdissolve"]) {
+            transitionStyle = UIModalTransitionStyleCrossDissolve;
+        }
+    }
+    self.themeableBrowserViewController.modalTransitionStyle = transitionStyle;
+
+    // prevent webView from bouncing
+    if (browserOptions.disallowoverscroll) {
+        if ([self.themeableBrowserViewController.webView respondsToSelector:@selector(scrollView)]) {
+            ((UIScrollView*)[self.themeableBrowserViewController.webView scrollView]).bounces = NO;
+        } else {
+            for (id subview in self.themeableBrowserViewController.webView.subviews) {
+                if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
+                    ((UIScrollView*)subview).bounces = NO;
+                }
+            }
+        }
+    }
+
+    // UIWebView options
+    self.themeableBrowserViewController.webView.scalesPageToFit = browserOptions.zoom;
+    self.themeableBrowserViewController.webView.mediaPlaybackRequiresUserAction = browserOptions.mediaplaybackrequiresuseraction;
+    self.themeableBrowserViewController.webView.allowsInlineMediaPlayback = browserOptions.allowinlinemediaplayback;
+    if (IsAtLeastiOSVersion(@"6.0")) {
+        self.themeableBrowserViewController.webView.keyboardDisplayRequiresUserAction = browserOptions.keyboarddisplayrequiresuseraction;
+        self.themeableBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
+    }
+
+    [self.themeableBrowserViewController navigateTo:url];
+    if (!browserOptions.hidden) {
+        [self show:nil withAnimation:!browserOptions.disableAnimation];
+    }
+}
+
+- (void)show:(CDVInvokedUrlCommand*)command
+{
+    [self show:command withAnimation:YES];
+}
+
+- (void)show:(CDVInvokedUrlCommand*)command withAnimation:(BOOL)animated
+{
+    if (self.themeableBrowserViewController == nil) {
+        [self emitWarning:kThemeableBrowserEmitCodeUnexpected
+              withMessage:@"Show called but already closed."];
+        return;
+    }
+    if (_isShown) {
+        [self emitWarning:kThemeableBrowserEmitCodeUnexpected
+              withMessage:@"Show called but already shown"];
+        return;
+    }
+
+    _isShown = YES;
+
+    CDVThemeableBrowserNavigationController* nav = [[CDVThemeableBrowserNavigationController alloc]
+                                   initWithRootViewController:self.themeableBrowserViewController];
+    nav.orientationDelegate = self.themeableBrowserViewController;
+    nav.navigationBarHidden = YES;
+    // Run later to avoid the "took a long time" log message.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if (self.themeableBrowserViewController != nil) {
+            [self.viewController presentViewController:nav animated:animated completion:nil];
+        }
+    });
+}
+
+- (void)openInCordovaWebView:(NSURL*)url withOptions:(NSString*)options
+{
+    NSURLRequest* request = [NSURLRequest requestWithURL:url];
+
+#ifdef __CORDOVA_4_0_0
+    // the webview engine itself will filter for this according to <allow-navigation> policy
+    // in config.xml for cordova-ios-4.0
+    [self.webViewEngine loadRequest:request];
+#else
+    if ([self.commandDelegate URLIsWhitelisted:url]) {
+        [self.webView loadRequest:request];
+    } else { // this assumes the openInThemeableBrowser can be excepted from the white-list
+        [self openInThemeableBrowser:url withOptions:options];
+    }
+#endif
+}
+
+- (void)openInSystem:(NSURL*)url
+{
+    if ([[UIApplication sharedApplication] canOpenURL:url]) {
+        [[UIApplication sharedApplication] openURL:url];
+    } else { // handle any custom schemes to plugins
+        [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
+    }
+}
+
+// This is a helper method for the inject{Script|Style}{Code|File} API calls, which
+// provides a consistent method for injecting JavaScript code into the document.
+//
+// If a wrapper string is supplied, then the source string will be JSON-encoded (adding
+// quotes) and wrapped using string formatting. (The wrapper string should have a single
+// '%@' marker).
+//
+// If no wrapper is supplied, then the source string is executed directly.
+
+- (void)injectDeferredObject:(NSString*)source withWrapper:(NSString*)jsWrapper
+{
+    if (!_injectedIframeBridge) {
+        _injectedIframeBridge = YES;
+        // Create an iframe bridge in the new document to communicate with the CDVThemeableBrowserViewController
+        [self.themeableBrowserViewController.webView stringByEvaluatingJavaScriptFromString:@"(function(d){var e = _cdvIframeBridge = d.createElement('iframe');e.style.display='none';d.body.appendChild(e);})(document)"];
+    }
+
+    if (jsWrapper != nil) {
+        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@[source] options:0 error:nil];
+        NSString* sourceArrayString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
+        if (sourceArrayString) {
+            NSString* sourceString = [sourceArrayString substringWithRange:NSMakeRange(1, [sourceArrayString length] - 2)];
+            NSString* jsToInject = [NSString stringWithFormat:jsWrapper, sourceString];
+            [self.themeableBrowserViewController.webView stringByEvaluatingJavaScriptFromString:jsToInject];
+        }
+    } else {
+        [self.themeableBrowserViewController.webView stringByEvaluatingJavaScriptFromString:source];
+    }
+}
+
+- (void)injectScriptCode:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper = nil;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"_cdvIframeBridge.src='gap-iab://%@/'+encodeURIComponent(JSON.stringify([eval(%%@)]));", command.callbackId];
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectScriptFile:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('script'); c.src = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('script'); c.src = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleCode:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('style'); c.innerHTML = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('style'); c.innerHTML = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (void)injectStyleFile:(CDVInvokedUrlCommand*)command
+{
+    NSString* jsWrapper;
+
+    if ((command.callbackId != nil) && ![command.callbackId isEqualToString:@"INVALID"]) {
+        jsWrapper = [NSString stringWithFormat:@"(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%@; c.onload = function() { _cdvIframeBridge.src='gap-iab://%@'; }; d.body.appendChild(c); })(document)", command.callbackId];
+    } else {
+        jsWrapper = @"(function(d) { var c = d.createElement('link'); c.rel='stylesheet', c.type='text/css'; c.href = %@; d.body.appendChild(c); })(document)";
+    }
+    [self injectDeferredObject:[command argumentAtIndex:0] withWrapper:jsWrapper];
+}
+
+- (BOOL)isValidCallbackId:(NSString *)callbackId
+{
+    NSError *err = nil;
+    // Initialize on first use
+    if (self.callbackIdPattern == nil) {
+        self.callbackIdPattern = [NSRegularExpression regularExpressionWithPattern:@"^ThemeableBrowser[0-9]{1,10}$" options:0 error:&err];
+        if (err != nil) {
+            // Couldn't initialize Regex; No is safer than Yes.
+            return NO;
+        }
+    }
+    if ([self.callbackIdPattern firstMatchInString:callbackId options:0 range:NSMakeRange(0, [callbackId length])]) {
+        return YES;
+    }
+    return NO;
+}
+
+/**
+ * The iframe bridge provided for the ThemeableBrowser is capable of executing any oustanding callback belonging
+ * to the ThemeableBrowser plugin. Care has been taken that other callbacks cannot be triggered, and that no
+ * other code execution is possible.
+ *
+ * To trigger the bridge, the iframe (or any other resource) should attempt to load a url of the form:
+ *
+ * gap-iab://<callbackId>/<arguments>
+ *
+ * where <callbackId> is the string id of the callback to trigger (something like "ThemeableBrowser0123456789")
+ *
+ * If present, the path component of the special gap-iab:// url is expected to be a URL-escaped JSON-encoded
+ * value to pass to the callback. [NSURL path] should take care of the URL-unescaping, and a JSON_EXCEPTION
+ * is returned if the JSON is invalid.
+ */
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    NSURL* url = request.URL;
+    BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+    // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a callback to execute,
+    // and the path, if present, should be a JSON-encoded value to pass to the callback.
+    if ([[url scheme] isEqualToString:@"gap-iab"]) {
+        NSString* scriptCallbackId = [url host];
+        CDVPluginResult* pluginResult = nil;
+
+        if ([self isValidCallbackId:scriptCallbackId]) {
+            NSString* scriptResult = [url path];
+            NSError* __autoreleasing error = nil;
+
+            // The message should be a JSON-encoded array of the result of the script which executed.
+            if ((scriptResult != nil) && ([scriptResult length] > 1)) {
+                scriptResult = [scriptResult substringFromIndex:1];
+                NSData* decodedResult = [NSJSONSerialization JSONObjectWithData:[scriptResult dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
+                if ((error == nil) && [decodedResult isKindOfClass:[NSArray class]]) {
+                    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:(NSArray*)decodedResult];
+                } else {
+                    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_JSON_EXCEPTION];
+                }
+            } else {
+                pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:@[]];
+            }
+            [self.commandDelegate sendPluginResult:pluginResult callbackId:scriptCallbackId];
+            return NO;
+        }
+    } else if ([self isSystemUrl:url]) {
+      // Do not allow iTunes store links from ThemeableBrowser as they do not work
+      // instead open them with App Store app or Safari
+      [[UIApplication sharedApplication] openURL:url];
+
+      // only in the case where a redirect link is opened in a freshly started
+      // ThemeableBrowser frame, trigger ThemeableBrowserRedirectExternalOnOpen
+      // event. This event can be handled in the app-side -- for instance, to
+      // close the ThemeableBrowser as the frame will contain a blank page
+      if (
+        originalUrl != nil
+        && [[originalUrl absoluteString] isEqualToString:[initUrl absoluteString]]
+        && _framesOpened == 1
+      ) {
+        NSDictionary *event = @{
+          @"type": @"ThemeableBrowserRedirectExternalOnOpen",
+          @"message": @"ThemeableBrowser redirected to open an external app on fresh start"
+        };
+
+        [self emitEvent:event];
+      }
+
+      // do not load content in the web view since this URL is handled by an
+      // external app
+      return NO;
+    } else if ((self.callbackId != nil) && isTopLevelNavigation) {
+        // Send a loadstart event for each top-level navigation (includes redirects).
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"loadstart", @"url":[url absoluteString]}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+
+    // originalUrl is used to detect redirect. This works by storing the
+    // request URL of the original frame when it's about to be loaded. A redirect
+    // will cause shouldStartLoadWithRequest to be called again before the
+    // original frame finishes loading (originalUrl becomes nil upon the frame
+    // finishing loading). On second time shouldStartLoadWithRequest
+    // is called, this stored original frame's URL can be compared against
+    // the URL of the new request. A mismatch implies redirect.
+    originalUrl = request.URL;
+
+    return YES;
+}
+
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+    _injectedIframeBridge = NO;
+    _framesOpened++;
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    if (self.callbackId != nil) {
+        // TODO: It would be more useful to return the URL the page is actually on (e.g. if it's been redirected).
+        NSString* url = [self.themeableBrowserViewController.currentURL absoluteString];
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"loadstop", @"url":url}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        // once a web view finished loading a frame, reset the stored original
+        // URL of the frame so that it can be used to detect next redirection
+        originalUrl = nil;
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    if (self.callbackId != nil) {
+        NSString* url = [self.themeableBrowserViewController.currentURL absoluteString];
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+                                                      messageAsDictionary:@{@"type":@"loaderror", @"url":url, @"code": [NSNumber numberWithInteger:error.code], @"message": error.localizedDescription}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+}
+
+- (void)browserExit
+{
+    if (self.callbackId != nil) {
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"exit"}];
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+        self.callbackId = nil;
+    }
+    // Set navigationDelegate to nil to ensure no callbacks are received from it.
+    self.themeableBrowserViewController.navigationDelegate = nil;
+    // Don't recycle the ViewController since it may be consuming a lot of memory.
+    // Also - this is required for the PDF/User-Agent bug work-around.
+    self.themeableBrowserViewController = nil;
+    self.callbackId = nil;
+    self.callbackIdPattern = nil;
+
+    _framesOpened = 0;
+    _isShown = NO;
+}
+
+- (void)emitEvent:(NSDictionary*)event
+{
+    if (self.callbackId != nil) {
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:event];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+    }
+}
+
+- (void)emitError:(NSString*)code withMessage:(NSString*)message
+{
+    NSDictionary *event = @{
+        @"type": kThemeableBrowserEmitError,
+        @"code": code,
+        @"message": message
+    };
+
+    [self emitEvent:event];
+}
+
+- (void)emitWarning:(NSString*)code withMessage:(NSString*)message
+{
+    NSDictionary *event = @{
+       @"type": kThemeableBrowserEmitWarning,
+       @"code": code,
+       @"message": message
+    };
+
+    [self emitEvent:event];
+}
+
+@end
+
+#pragma mark CDVThemeableBrowserViewController
+
+@implementation CDVThemeableBrowserViewController
+
+@synthesize currentURL;
+
+- (id)initWithUserAgent:(NSString*)userAgent prevUserAgent:(NSString*)prevUserAgent browserOptions: (CDVThemeableBrowserOptions*) browserOptions navigationDelete:(CDVThemeableBrowser*) navigationDelegate statusBarStyle:(UIStatusBarStyle) statusBarStyle
+{
+    self = [super init];
+    if (self != nil) {
+        _userAgent = userAgent;
+        _prevUserAgent = prevUserAgent;
+        _browserOptions = browserOptions;
+#ifdef __CORDOVA_4_0_0
+        _webViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:self];
+#else
+        _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self];
+#endif
+        _navigationDelegate = navigationDelegate;
+        _statusBarStyle = statusBarStyle;
+        [self createViews];
+    }
+
+    return self;
+}
+
+- (void)createViews
+{
+    // We create the views in code for primarily for ease of upgrades and not requiring an external .xib to be included
+
+    CGRect webViewBounds = self.view.bounds;
+    BOOL toolbarIsAtBottom = ![_browserOptions.toolbarposition isEqualToString:kThemeableBrowserToolbarBarPositionTop];
+    NSDictionary* toolbarProps = _browserOptions.toolbar;
+    CGFloat toolbarHeight = [self getFloatFromDict:toolbarProps withKey:kThemeableBrowserPropHeight withDefault:TOOLBAR_DEF_HEIGHT];
+    if (!_browserOptions.fullscreen) {
+        webViewBounds.size.height -= toolbarHeight;
+    }
+    self.webView = [[UIWebView alloc] initWithFrame:webViewBounds];
+
+    self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+    [self.view addSubview:self.webView];
+    [self.view sendSubviewToBack:self.webView];
+
+    self.webView.delegate = _webViewDelegate;
+    self.webView.backgroundColor = [UIColor whiteColor];
+
+    self.webView.clearsContextBeforeDrawing = YES;
+    self.webView.clipsToBounds = YES;
+    self.webView.contentMode = UIViewContentModeScaleToFill;
+    self.webView.multipleTouchEnabled = YES;
+    self.webView.opaque = YES;
+    self.webView.scalesPageToFit = NO;
+    self.webView.userInteractionEnabled = YES;
+
+    self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
+    self.spinner.alpha = 1.000;
+    self.spinner.autoresizesSubviews = YES;
+    self.spinner.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
+    self.spinner.clearsContextBeforeDrawing = NO;
+    self.spinner.clipsToBounds = NO;
+    self.spinner.contentMode = UIViewContentModeScaleToFill;
+    self.spinner.frame = CGRectMake(454.0, 231.0, 20.0, 20.0);
+    self.spinner.hidden = YES;
+    self.spinner.hidesWhenStopped = YES;
+    self.spinner.multipleTouchEnabled = NO;
+    self.spinner.opaque = NO;
+    self.spinner.userInteractionEnabled = NO;
+    [self.spinner stopAnimating];
+
+    CGFloat toolbarY = toolbarIsAtBottom ? self.view.bounds.size.height - toolbarHeight : 0.0;
+    CGRect toolbarFrame = CGRectMake(0.0, toolbarY, self.view.bounds.size.width, toolbarHeight);
+
+    self.toolbar = [[UIView alloc] initWithFrame:toolbarFrame];
+    self.toolbar.alpha = 1.000;
+    self.toolbar.autoresizesSubviews = YES;
+    self.toolbar.autoresizingMask = toolbarIsAtBottom ? (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin) : UIViewAutoresizingFlexibleWidth;
+    self.toolbar.clearsContextBeforeDrawing = NO;
+    self.toolbar.clipsToBounds = YES;
+    self.toolbar.contentMode = UIViewContentModeScaleToFill;
+    self.toolbar.hidden = NO;
+    self.toolbar.multipleTouchEnabled = NO;
+    self.toolbar.opaque = NO;
+    self.toolbar.userInteractionEnabled = YES;
+    self.toolbar.backgroundColor = [CDVThemeableBrowserViewController colorFromRGBA:[self getStringFromDict:toolbarProps withKey:kThemeableBrowserPropColor withDefault:@"#ffffffff"]];
+
+    if (toolbarProps[kThemeableBrowserPropImage] || toolbarProps[kThemeableBrowserPropWwwImage]) {
+        UIImage *image = [self getImage:toolbarProps[kThemeableBrowserPropImage]
+                               altPath:toolbarProps[kThemeableBrowserPropWwwImage]
+                               altDensity:[toolbarProps[kThemeableBrowserPropWwwImageDensity] doubleValue]];
+
+        if (image) {
+            self.toolbar.backgroundColor = [UIColor colorWithPatternImage:image];
+        } else {
+            [self.navigationDelegate emitError:kThemeableBrowserEmitCodeLoadFail
+                                   withMessage:[NSString stringWithFormat:@"Image for toolbar, %@, failed to load.",
+                                                toolbarProps[kThemeableBrowserPropImage]
+                                                ? toolbarProps[kThemeableBrowserPropImage] : toolbarProps[kThemeableBrowserPropWwwImage]]];
+        }
+    }
+
+    CGFloat labelInset = 5.0;
+    float locationBarY = self.view.bounds.size.height - LOCATIONBAR_HEIGHT;
+
+    self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelInset, locationBarY, self.view.bounds.size.width - labelInset, LOCATIONBAR_HEIGHT)];
+    self.addressLabel.adjustsFontSizeToFitWidth = NO;
+    self.addressLabel.alpha = 1.000;
+    self.addressLabel.autoresizesSubviews = YES;
+    self.addressLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
+    self.addressLabel.backgroundColor = [UIColor clearColor];
+    self.addressLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
+    self.addressLabel.clearsContextBeforeDrawing = YES;
+    self.addressLabel.clipsToBounds = YES;
+    self.addressLabel.contentMode = UIViewContentModeScaleToFill;
+    self.addressLabel.enabled = YES;
+    self.addressLabel.hidden = NO;
+    self.addressLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+
+    if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumScaleFactor:")]) {
+        [self.addressLabel setValue:@(10.0/[UIFont labelFontSize]) forKey:@"minimumScaleFactor"];
+    } else if ([self.addressLabel respondsToSelector:NSSelectorFromString(@"setMinimumFontSize:")]) {
+        [self.addressLabel setValue:@(10.0) forKey:@"minimumFontSize"];
+    }
+
+    self.addressLabel.multipleTouchEnabled = NO;
+    self.addressLabel.numberOfLines = 1;
+    self.addressLabel.opaque = NO;
+    self.addressLabel.shadowOffset = CGSizeMake(0.0, -1.0);
+    self.addressLabel.text = NSLocalizedString(@"Loading...", nil);
+    self.addressLabel.textAlignment = NSTextAlignmentLeft;
+    self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000];
+    self.addressLabel.userInteractionEnabled = NO;
+
+    self.closeButton = [self createButton:_browserOptions.closeButton action:@selector(close) withDescription:@"close button"];
+    self.backButton = [self createButton:_browserOptions.backButton action:@selector(goBack:) withDescription:@"back button"];
+    self.forwardButton = [self createButton:_browserOptions.forwardButton action:@selector(goForward:) withDescription:@"forward button"];
+    self.menuButton = [self createButton:_browserOptions.menu action:@selector(goMenu:) withDescription:@"menu button"];
+
+    // Arramge toolbar buttons with respect to user configuration.
+    CGFloat leftWidth = 0;
+    CGFloat rightWidth = 0;
+
+    // Both left and right side buttons will be ordered from outside to inside.
+    NSMutableArray* leftButtons = [NSMutableArray new];
+    NSMutableArray* rightButtons = [NSMutableArray new];
+
+    if (self.closeButton) {
+        CGFloat width = [self getWidthFromButton:self.closeButton];
+
+        if ([kThemeableBrowserAlignRight isEqualToString:_browserOptions.closeButton[kThemeableBrowserPropAlign]]) {
+            [rightButtons addObject:self.closeButton];
+            rightWidth += width;
+        } else {
+            [leftButtons addObject:self.closeButton];
+            leftWidth += width;
+        }
+    }
+
+    if (self.menuButton) {
+        CGFloat width = [self getWidthFromButton:self.menuButton];
+
+        if ([kThemeableBrowserAlignRight isEqualToString:_browserOptions.menu[kThemeableBrowserPropAlign]]) {
+            [rightButtons addObject:self.menuButton];
+            rightWidth += width;
+        } else {
+            [leftButtons addObject:self.menuButton];
+            leftWidth += width;
+        }
+    }
+
+    // Back and forward buttons must be added with special ordering logic such
+    // that back button is always on the left of forward button if both buttons
+    // are on the same side.
+    if (self.backButton && ![kThemeableBrowserAlignRight isEqualToString:_browserOptions.backButton[kThemeableBrowserPropAlign]]) {
+        CGFloat width = [self getWidthFromButton:self.backButton];
+        [leftButtons addObject:self.backButton];
+        leftWidth += width;
+    }
+
+    if (self.forwardButton && [kThemeableBrowserAlignRight isEqualToString:_browserOptions.forwardButton[kThemeableBrowserPropAlign]]) {
+        CGFloat width = [self getWidthFromButton:self.forwardButton];
+        [rightButtons addObject:self.forwardButton];
+        rightWidth += width;
+    }
+
+    if (self.forwardButton && ![kThemeableBrowserAlignRight isEqualToString:_browserOptions.forwardButton[kThemeableBrowserPropAlign]]) {
+        CGFloat width = [self getWidthFromButton:self.forwardButton];
+        [leftButtons addObject:self.forwardButton];
+        leftWidth += width;
+    }
+
+    if (self.backButton && [kThemeableBrowserAlignRight isEqualToString:_browserOptions.backButton[kThemeableBrowserPropAlign]]) {
+        CGFloat width = [self getWidthFromButton:self.backButton];
+        [rightButtons addObject:self.backButton];
+        rightWidth += width;
+    }
+
+    NSArray* customButtons = _browserOptions.customButtons;
+    if (customButtons) {
+        NSInteger cnt = 0;
+        // Reverse loop because we are laying out from outer to inner.
+        for (NSDictionary* customButton in [customButtons reverseObjectEnumerator]) {
+            UIButton* button = [self createButton:customButton action:@selector(goCustomButton:) withDescription:[NSString stringWithFormat:@"custom button at %ld", (long)cnt]];
+            if (button) {
+                button.tag = cnt;
+                CGFloat width = [self getWidthFromButton:button];
+                if ([kThemeableBrowserAlignRight isEqualToString:customButton[kThemeableBrowserPropAlign]]) {
+                    [rightButtons addObject:button];
+                    rightWidth += width;
+                } else {
+                    [leftButtons addObject:button];
+                    leftWidth += width;
+                }
+            }
+
+            cnt += 1;
+        }
+    }
+
+    self.rightButtons = rightButtons;
+    self.leftButtons = leftButtons;
+
+    for (UIButton* button in self.leftButtons) {
+        [self.toolbar addSubview:button];
+    }
+
+    for (UIButton* button in self.rightButtons) {
+        [self.toolbar addSubview:button];
+    }
+
+    [self layoutButtons];
+
+    self.titleOffset = fmaxf(leftWidth, rightWidth);
+    // The correct positioning of title is not that important right now, since
+    // rePositionViews will take care of it a bit later.
+    self.titleLabel = nil;
+    if (_browserOptions.title) {
+        self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 10, toolbarHeight)];
+        self.titleLabel.textAlignment = NSTextAlignmentCenter;
+        self.titleLabel.numberOfLines = 1;
+        self.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+        self.titleLabel.textColor = [CDVThemeableBrowserViewController colorFromRGBA:[self getStringFromDict:_browserOptions.title withKey:kThemeableBrowserPropColor withDefault:@"#000000ff"]];
+
+        if (_browserOptions.title[kThemeableBrowserPropStaticText]) {
+            self.titleLabel.text = _browserOptions.title[kThemeableBrowserPropStaticText];
+        }
+
+        [self.toolbar addSubview:self.titleLabel];
+    }
+
+    self.view.backgroundColor = [CDVThemeableBrowserViewController colorFromRGBA:[self getStringFromDict:_browserOptions.statusbar withKey:kThemeableBrowserPropColor withDefault:@"#ffffffff"]];
+    [self.view addSubview:self.toolbar];
+    // [self.view addSubview:self.addressLabel];
+    // [self.view addSubview:self.spinner];
+}
+
+/**
+ * This is a rather unintuitive helper method to load images. The reason why this method exists
+ * is because due to some service limitations, one may not be able to add images to native
+ * resource bundle. So this method offers a way to load image from www contents instead.
+ * However loading from native resource bundle is already preferred over loading from www. So
+ * if name is given, then it simply loads from resource bundle and the other two parameters are
+ * ignored. If name is not given, then altPath is assumed to be a file path _under_ www and
+ * altDensity is the desired density of the given image file, because without native resource
+ * bundle, we can't tell what densitiy the image is supposed to be so it needs to be given
+ * explicitly.
+ */
+- (UIImage*) getImage:(NSString*) name altPath:(NSString*) altPath altDensity:(CGFloat) altDensity
+{
+    UIImage* result = nil;
+    if (name) {
+        result = [UIImage imageNamed:name];
+    } else if (altPath) {
+        NSString* path = [[[NSBundle mainBundle] bundlePath]
+                          stringByAppendingPathComponent:[NSString pathWithComponents:@[@"www", altPath]]];
+        if (!altDensity) {
+            altDensity = 1.0;
+        }
+        NSData* data = [NSData dataWithContentsOfFile:path];
+        result = [UIImage imageWithData:data scale:altDensity];
+    }
+
+    return result;
+}
+
+- (UIButton*) createButton:(NSDictionary*) buttonProps action:(SEL)action withDescription:(NSString*)description
+{
+    UIButton* result = nil;
+    if (buttonProps) {
+        UIImage *buttonImage = nil;
+        if (buttonProps[kThemeableBrowserPropImage] || buttonProps[kThemeableBrowserPropWwwImage]) {
+            buttonImage = [self getImage:buttonProps[kThemeableBrowserPropImage]
+                                altPath:buttonProps[kThemeableBrowserPropWwwImage]
+                                altDensity:[buttonProps[kThemeableBrowserPropWwwImageDensity] doubleValue]];
+
+            if (!buttonImage) {
+                [self.navigationDelegate emitError:kThemeableBrowserEmitCodeLoadFail
+                                       withMessage:[NSString stringWithFormat:@"Image for %@, %@, failed to load.",
+                                                    description,
+                                                    buttonProps[kThemeableBrowserPropImage]
+                                                    ? buttonProps[kThemeableBrowserPropImage] : buttonProps[kThemeableBrowserPropWwwImage]]];
+            }
+        } else {
+            [self.navigationDelegate emitWarning:kThemeableBrowserEmitCodeUndefined
+                                 withMessage:[NSString stringWithFormat:@"Image for %@ is not defined. Button will not be shown.", description]];
+        }
+
+        UIImage *buttonImagePressed = nil;
+        if (buttonProps[kThemeableBrowserPropImagePressed] || buttonProps[kThemeableBrowserPropWwwImagePressed]) {
+            buttonImagePressed = [self getImage:buttonProps[kThemeableBrowserPropImagePressed]
+                                       altPath:buttonProps[kThemeableBrowserPropWwwImagePressed]
+                                       altDensity:[buttonProps[kThemeableBrowserPropWwwImageDensity] doubleValue]];;
+
+            if (!buttonImagePressed) {
+                [self.navigationDelegate emitError:kThemeableBrowserEmitCodeLoadFail
+                                       withMessage:[NSString stringWithFormat:@"Pressed image for %@, %@, failed to load.",
+                                                    description,
+                                                    buttonProps[kThemeableBrowserPropImagePressed]
+                                                    ? buttonProps[kThemeableBrowserPropImagePressed] : buttonProps[kThemeableBrowserPropWwwImagePressed]]];
+            }
+        } else {
+            [self.navigationDelegate emitWarning:kThemeableBrowserEmitCodeUndefined
+                             withMessage:[NSString stringWithFormat:@"Pressed image for %@ is not defined.", description]];
+        }
+
+        if (buttonImage) {
+            result = [UIButton buttonWithType:UIButtonTypeCustom];
+            result.bounds = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
+
+            if (buttonImagePressed) {
+                [result setImage:buttonImagePressed forState:UIControlStateHighlighted];
+                result.adjustsImageWhenHighlighted = NO;
+            }
+
+            [result setImage:buttonImage forState:UIControlStateNormal];
+            [result addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
+        }
+    } else if (!buttonProps) {
+        [self.navigationDelegate emitWarning:kThemeableBrowserEmitCodeUndefined
+                                 withMessage:[NSString stringWithFormat:@"%@ is not defined. Button will not be shown.", description]];
+    } else if (!buttonProps[kThemeableBrowserPropImage]) {
+    }
+
+    return result;
+}
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
+{
+    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+
+    // Reposition views.
+    [self rePositionViews];
+}
+
+- (void) setWebViewFrame : (CGRect) frame {
+    [self.webView setFrame:frame];
+}
+
+- (void)layoutButtons
+{
+    CGFloat screenWidth = CGRectGetWidth(self.view.frame);
+    CGFloat toolbarHeight = self.toolbar.frame.size.height;
+
+    // Layout leftButtons and rightButtons from outer to inner.
+    CGFloat left = 0;
+    for (UIButton* button in self.leftButtons) {
+        CGSize size = button.frame.size;
+        button.frame = CGRectMake(left, floorf((toolbarHeight - size.height) / 2), size.width, size.height);
+        left += size.width;
+    }
+
+    CGFloat right = 0;
+    for (UIButton* button in self.rightButtons) {
+        CGSize size = button.frame.size;
+        button.frame = CGRectMake(screenWidth - right - size.width, floorf((toolbarHeight - size.height) / 2), size.width, size.height);
+        right += size.width;
+    }
+}
+
+- (void)setCloseButtonTitle:(NSString*)title
+{
+    // This method is not used by ThemeableBrowser. It is inherited from
+    // InAppBrowser and is kept for merge purposes.
+
+    // the advantage of using UIBarButtonSystemItemDone is the system will localize it for you automatically
+    // but, if you want to set this yourself, knock yourself out (we can't set the title for a system Done button, so we have to create a new one)
+    // self.closeButton = nil;
+    // self.closeButton = [[UIBarButtonItem alloc] initWithTitle:title style:UIBarButtonItemStyleBordered target:self action:@selector(close)];
+    // self.closeButton.enabled = YES;
+    // self.closeButton.tintColor = [UIColor colorWithRed:60.0 / 255.0 green:136.0 / 255.0 blue:230.0 / 255.0 alpha:1];
+
+    // NSMutableArray* items = [self.toolbar.items mutableCopy];
+    // [items replaceObjectAtIndex:0 withObject:self.closeButton];
+    // [self.toolbar setItems:items];
+}
+
+- (void)showLocationBar:(BOOL)show
+{
+    CGRect locationbarFrame = self.addressLabel.frame;
+    CGFloat toolbarHeight = [self getFloatFromDict:_browserOptions.toolbar withKey:kThemeableBrowserPropHeight withDefault:TOOLBAR_DEF_HEIGHT];
+
+    BOOL toolbarVisible = !self.toolbar.hidden;
+
+    // prevent double show/hide
+    if (show == !(self.addressLabel.hidden)) {
+        return;
+    }
+
+    if (show) {
+        self.addressLabel.hidden = NO;
+
+        if (toolbarVisible) {
+            // toolBar at the bottom, leave as is
+            // put locationBar on top of the toolBar
+
+            CGRect webViewBounds = self.view.bounds;
+            if (!_browserOptions.fullscreen) {
+                webViewBounds.size.height -= toolbarHeight;
+            }
+            [self setWebViewFrame:webViewBounds];
+
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        } else {
+            // no toolBar, so put locationBar at the bottom
+
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        }
+    } else {
+        self.addressLabel.hidden = YES;
+
+        if (toolbarVisible) {
+            // locationBar is on top of toolBar, hide locationBar
+
+            // webView take up whole height less toolBar height
+            CGRect webViewBounds = self.view.bounds;
+            if (!_browserOptions.fullscreen) {
+                webViewBounds.size.height -= toolbarHeight;
+            }
+            [self setWebViewFrame:webViewBounds];
+        } else {
+            // no toolBar, expand webView to screen dimensions
+            [self setWebViewFrame:self.view.bounds];
+        }
+    }
+}
+
+- (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition
+{
+    CGRect toolbarFrame = self.toolbar.frame;
+    CGRect locationbarFrame = self.addressLabel.frame;
+    CGFloat toolbarHeight = [self getFloatFromDict:_browserOptions.toolbar withKey:kThemeableBrowserPropHeight withDefault:TOOLBAR_DEF_HEIGHT];
+
+    BOOL locationbarVisible = !self.addressLabel.hidden;
+
+    // prevent double show/hide
+    if (show == !(self.toolbar.hidden)) {
+        return;
+    }
+
+    if (show) {
+        self.toolbar.hidden = NO;
+        CGRect webViewBounds = self.view.bounds;
+
+        if (locationbarVisible) {
+            // locationBar at the bottom, move locationBar up
+            // put toolBar at the bottom
+            if (!_browserOptions.fullscreen) {
+                webViewBounds.size.height -= toolbarHeight;
+            }
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+            self.toolbar.frame = toolbarFrame;
+        } else {
+            // no locationBar, so put toolBar at the bottom
+            self.toolbar.frame = toolbarFrame;
+        }
+
+        if ([toolbarPosition isEqualToString:kThemeableBrowserToolbarBarPositionTop]) {
+            toolbarFrame.origin.y = 0;
+            if (!_browserOptions.fullscreen) {
+                webViewBounds.origin.y += toolbarFrame.size.height;
+            }
+            [self setWebViewFrame:webViewBounds];
+        } else {
+            toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT);
+        }
+        [self setWebViewFrame:webViewBounds];
+
+    } else {
+        self.toolbar.hidden = YES;
+
+        if (locationbarVisible) {
+            // locationBar is on top of toolBar, hide toolBar
+            // put locationBar at the bottom
+
+            // webView take up whole height less locationBar height
+            CGRect webViewBounds = self.view.bounds;
+            webViewBounds.size.height -= LOCATIONBAR_HEIGHT;
+            [self setWebViewFrame:webViewBounds];
+
+            // move locationBar down
+            locationbarFrame.origin.y = webViewBounds.size.height;
+            self.addressLabel.frame = locationbarFrame;
+        } else {
+            // no locationBar, expand webView to screen dimensions
+            [self setWebViewFrame:self.view.bounds];
+        }
+    }
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+}
+
+- (void)viewDidUnload
+{
+    [self.webView loadHTMLString:nil baseURL:nil];
+    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+    [super viewDidUnload];
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle
+{
+    return _statusBarStyle;
+}
+
+- (void)close
+{
+    [self emitEventForButton:_browserOptions.closeButton];
+
+    [CDVUserAgentUtil releaseLock:&_userAgentLockToken];
+    self.currentURL = nil;
+
+    if ((self.navigationDelegate != nil) && [self.navigationDelegate respondsToSelector:@selector(browserExit)]) {
+        [self.navigationDelegate browserExit];
+    }
+
+    // Run later to avoid the "took a long time" log message.
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if ([self respondsToSelector:@selector(presentingViewController)]) {
+            [[self presentingViewController] dismissViewControllerAnimated:!_browserOptions.disableAnimation completion:nil];
+        } else {
+            [[self parentViewController] dismissViewControllerAnimated:!_browserOptions.disableAnimation completion:nil];
+        }
+    });
+
+}
+
+- (void)reload
+{
+    [self.webView reload];
+}
+
+- (void)navigateTo:(NSURL*)url
+{
+    NSURLRequest* request = [NSURLRequest requestWithURL:url];
+
+    if (_userAgentLockToken != 0) {
+        [self.webView loadRequest:request];
+    } else {
+        [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) {
+            _userAgentLockToken = lockToken;
+            [CDVUserAgentUtil setUserAgent:_userAgent lockToken:lockToken];
+            [self.webView loadRequest:request];
+        }];
+    }
+}
+
+- (void)goBack:(id)sender
+{
+    [self emitEventForButton:_browserOptions.backButton];
+
+    if (self.webView.canGoBack) {
+        [self.webView goBack];
+        [self updateButtonDelayed:self.webView];
+    } else if (_browserOptions.backButtonCanClose) {
+        [self close];
+    }
+}
+
+- (void)goForward:(id)sender
+{
+    [self emitEventForButton:_browserOptions.forwardButton];
+
+    [self.webView goForward];
+    [self updateButtonDelayed:self.webView];
+}
+
+- (void)goCustomButton:(id)sender
+{
+    UIButton* button = sender;
+    NSInteger index = button.tag;
+    [self emitEventForButton:_browserOptions.customButtons[index] withIndex:[NSNumber numberWithLong:index]];
+}
+
+- (void)goMenu:(id)sender
+{
+    [self emitEventForButton:_browserOptions.menu];
+
+    if (_browserOptions.menu && _browserOptions.menu[kThemeableBrowserPropItems]) {
+        NSArray* menuItems = _browserOptions.menu[kThemeableBrowserPropItems];
+        if (IsAtLeastiOSVersion(@"8.0")) {
+            // iOS > 8 implementation using UIAlertController, which is the new way
+            // to do this going forward.
+            UIAlertController *alertController = [UIAlertController
+                                                  alertControllerWithTitle:_browserOptions.menu[kThemeableBrowserPropTitle]
+                                                  message:nil
+                                                  preferredStyle:UIAlertControllerStyleActionSheet];
+            alertController.popoverPresentationController.sourceView
+                    = self.menuButton;
+            alertController.popoverPresentationController.sourceRect
+                    = self.menuButton.bounds;
+
+            for (NSInteger i = 0; i < menuItems.count; i++) {
+                NSInteger index = i;
+                NSDictionary *item = menuItems[index];
+
+                UIAlertAction *a = [UIAlertAction
+                                     actionWithTitle:item[@"label"]
+                                     style:UIAlertActionStyleDefault
+                                     handler:^(UIAlertAction *action) {
+                                         [self menuSelected:index];
+                                     }];
+                [alertController addAction:a];
+            }
+
+            if (_browserOptions.menu[kThemeableBrowserPropCancel]) {
+                UIAlertAction *cancelAction = [UIAlertAction
+                                               actionWithTitle:_browserOptions.menu[kThemeableBrowserPropCancel]
+                                               style:UIAlertActionStyleCancel
+                                               handler:nil];
+                [alertController addAction:cancelAction];
+            }
+
+            [self presentViewController:alertController animated:YES completion:nil];
+        } else {
+            // iOS < 8 implementation using UIActionSheet, which is deprecated.
+            UIActionSheet *popup = [[UIActionSheet alloc]
+                                    initWithTitle:_browserOptions.menu[kThemeableBrowserPropTitle]
+                                    delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
+
+            for (NSDictionary *item in menuItems) {
+                [popup addButtonWithTitle:item[@"label"]];
+            }
+            if (_browserOptions.menu[kThemeableBrowserPropCancel]) {
+                [popup addButtonWithTitle:_browserOptions.menu[kThemeableBrowserPropCancel]];
+                popup.cancelButtonIndex = menuItems.count;
+            }
+
+            [popup showFromRect:self.menuButton.frame inView:self.view animated:YES];
+        }
+    } else {
+        [self.navigationDelegate emitWarning:kThemeableBrowserEmitCodeUndefined
+                                 withMessage:@"Menu items undefined. No menu will be shown."];
+    }
+}
+
+- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    [self menuSelected:buttonIndex];
+}
+
+- (void) menuSelected:(NSInteger)index
+{
+    NSArray* menuItems = _browserOptions.menu[kThemeableBrowserPropItems];
+    if (index < menuItems.count) {
+        [self emitEventForButton:menuItems[index] withIndex:[NSNumber numberWithLong:index]];
+    }
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    if (IsAtLeastiOSVersion(@"7.0")) {
+        [[UIApplication sharedApplication] setStatusBarStyle:[self preferredStatusBarStyle]];
+    }
+    [self rePositionViews];
+
+    [super viewWillAppear:animated];
+}
+
+//
+// On iOS 7 the status bar is part of the view's dimensions, therefore it's height has to be taken into account.
+// The height of it could be hardcoded as 20 pixels, but that would assume that the upcoming releases of iOS won't
+// change that value.
+//
+- (float) getStatusBarOffset {
+    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
+    float statusBarOffset = IsAtLeastiOSVersion(@"7.0") ? MIN(statusBarFrame.size.width, statusBarFrame.size.height) : 0.0;
+    return statusBarOffset;
+}
+
+- (void) rePositionViews {
+    CGFloat toolbarHeight = [self getFloatFromDict:_browserOptions.toolbar withKey:kThemeableBrowserPropHeight withDefault:TOOLBAR_DEF_HEIGHT];
+    CGFloat webviewOffset = _browserOptions.fullscreen ? 0.0 : toolbarHeight;
+    CGFloat statusBarOffset = [self getStatusBarOffset]; 
+    webviewOffset = _browserOptions.fullscreen ? 0.0 : toolbarHeight + statusBarOffset;
+    if ([_browserOptions.toolbarposition isEqualToString:kThemeableBrowserToolbarBarPositionTop]) {
+        [self.webView setFrame:CGRectMake(self.webView.frame.origin.x, webviewOffset, self.webView.frame.size.width, self.webView.frame.size.height)];
+        [self.toolbar setFrame:CGRectMake(self.toolbar.frame.origin.x, [self getStatusBarOffset], self.toolbar.frame.size.width, self.toolbar.frame.size.height)];
+    }
+
+    CGFloat screenWidth = CGRectGetWidth(self.view.frame);
+    NSInteger width = floorf(screenWidth - self.titleOffset * 2.0f);
+    if (self.titleLabel) {
+        self.titleLabel.frame = CGRectMake(floorf((screenWidth - width) / 2.0f), 0, width, toolbarHeight);
+    }
+
+    [self layoutButtons];
+}
+
+- (CGFloat) getFloatFromDict:(NSDictionary*)dict withKey:(NSString*)key withDefault:(CGFloat)def
+{
+    CGFloat result = def;
+    if (dict && dict[key]) {
+        result = [(NSNumber*) dict[key] floatValue];
+    }
+    return result;
+}
+
+- (NSString*) getStringFromDict:(NSDictionary*)dict withKey:(NSString*)key withDefault:(NSString*)def
+{
+    NSString* result = def;
+    if (dict && dict[key]) {
+        result = dict[key];
+    }
+    return result;
+}
+
+- (BOOL) getBoolFromDict:(NSDictionary*)dict withKey:(NSString*)key
+{
+    BOOL result = NO;
+    if (dict && dict[key]) {
+        result = [(NSNumber*) dict[key] boolValue];
+    }
+    return result;
+}
+
+- (CGFloat) getWidthFromButton:(UIButton*)button
+{
+    return button.frame.size.width;
+}
+
+- (void)emitEventForButton:(NSDictionary*)buttonProps
+{
+    [self emitEventForButton:buttonProps withIndex:nil];
+}
+
+- (void)emitEventForButton:(NSDictionary*)buttonProps withIndex:(NSNumber*)index
+{
+    if (buttonProps) {
+        NSString* event = buttonProps[kThemeableBrowserPropEvent];
+        if (event) {
+            NSMutableDictionary* dict = [NSMutableDictionary new];
+            [dict setObject:event forKey:@"type"];
+            [dict setObject:[self.navigationDelegate.themeableBrowserViewController.currentURL absoluteString] forKey:@"url"];
+
+            if (index) {
+                [dict setObject:index forKey:@"index"];
+            }
+            [self.navigationDelegate emitEvent:dict];
+        } else {
+            [self.navigationDelegate emitWarning:kThemeableBrowserEmitCodeUndefined
+                                     withMessage:@"Button clicked, but event property undefined. No event will be raised."];
+        }
+    }
+}
+
+#pragma mark UIWebViewDelegate
+
+- (void)webViewDidStartLoad:(UIWebView*)theWebView
+{
+    // loading url, start spinner
+
+    self.addressLabel.text = NSLocalizedString(@"Loading...", nil);
+
+    [self.spinner startAnimating];
+
+    return [self.navigationDelegate webViewDidStartLoad:theWebView];
+}
+
+- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+
+    if (isTopLevelNavigation) {
+        self.currentURL = request.URL;
+    }
+
+    [self updateButtonDelayed:theWebView];
+
+    return [self.navigationDelegate webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
+}
+
+- (void)webViewDidFinishLoad:(UIWebView*)theWebView
+{
+    // update url, stop spinner, update back/forward
+
+    self.addressLabel.text = [self.currentURL absoluteString];
+    [self updateButton:theWebView];
+
+    if (self.titleLabel && _browserOptions.title
+            && !_browserOptions.title[kThemeableBrowserPropStaticText]
+            && [self getBoolFromDict:_browserOptions.title withKey:kThemeableBrowserPropShowPageTitle]) {
+        // Update title text to page title when title is shown and we are not
+        // required to show a static text.
+        self.titleLabel.text = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
+    }
+
+    [self.spinner stopAnimating];
+
+    // Work around a bug where the first time a PDF is opened, all UIWebViews
+    // reload their User-Agent from NSUserDefaults.
+    // This work-around makes the following assumptions:
+    // 1. The app has only a single Cordova Webview. If not, then the app should
+    //    take it upon themselves to load a PDF in the background as a part of
+    //    their start-up flow.
+    // 2. That the PDF does not require any additional network requests. We change
+    //    the user-agent here back to that of the CDVViewController, so requests
+    //    from it must pass through its white-list. This *does* break PDFs that
+    //    contain links to other remote PDF/websites.
+    // More info at https://issues.apache.org/jira/browse/CB-2225
+    BOOL isPDF = [@"true" isEqualToString :[theWebView stringByEvaluatingJavaScriptFromString:@"document.body==null"]];
+    if (isPDF) {
+        [CDVUserAgentUtil setUserAgent:_prevUserAgent lockToken:_userAgentLockToken];
+    }
+
+    [self.navigationDelegate webViewDidFinishLoad:theWebView];
+}
+
+- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
+{
+    [self updateButton:theWebView];
+
+    [self.spinner stopAnimating];
+
+    self.addressLabel.text = NSLocalizedString(@"Load Error", nil);
+
+    [self.navigationDelegate webView:theWebView didFailLoadWithError:error];
+}
+
+- (void)updateButton:(UIWebView*)theWebView
+{
+    if (self.backButton) {
+        self.backButton.enabled = _browserOptions.backButtonCanClose || theWebView.canGoBack;
+    }
+
+    if (self.forwardButton) {
+        self.forwardButton.enabled = theWebView.canGoForward;
+    }
+}
+
+/**
+ * The reason why this method exists at all is because UIWebView is quite
+ * terrible with dealing this hash change, which IS a history change. However
+ * when moving to a new hash, only shouldStartLoadWithRequest will be called.
+ * Even then it's being called too early such that canGoback and canGoForward
+ * hasn't been updated yet. What makes it worse is that when navigating history
+ * involving hash by goBack and goForward, no callback is called at all, so we
+ * will have to depend on the back and forward button to give us hints when to
+ * change button states.
+ */
+- (void)updateButtonDelayed:(UIWebView*)theWebView
+{
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+        [self updateButton:theWebView];
+    });
+}
+
+#pragma mark CDVScreenOrientationDelegate
+
+- (BOOL)shouldAutorotate
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+        return [self.orientationDelegate shouldAutorotate];
+    }
+    return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+        return [self.orientationDelegate supportedInterfaceOrientations];
+    }
+
+    return 1 << UIInterfaceOrientationPortrait;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
++ (UIColor *)colorFromRGBA:(NSString *)rgba {
+    unsigned rgbaVal = 0;
+
+    if ([[rgba substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"#"]) {
+        // First char is #, get rid of that.
+        rgba = [rgba substringFromIndex:1];
+    }
+
+    if (rgba.length < 8) {
+        // If alpha is not given, just append ff.
+        rgba = [NSString stringWithFormat:@"%@ff", rgba];
+    }
+
+    NSScanner *scanner = [NSScanner scannerWithString:rgba];
+    [scanner setScanLocation:0];
+    [scanner scanHexInt:&rgbaVal];
+
+    return [UIColor colorWithRed:(rgbaVal >> 24 & 0xFF) / 255.0f
+        green:(rgbaVal >> 16 & 0xFF) / 255.0f
+        blue:(rgbaVal >> 8 & 0xFF) / 255.0f
+        alpha:(rgbaVal & 0xFF) / 255.0f];
+}
+
+@end
+
+@implementation CDVThemeableBrowserOptions
+
+- (id)init
+{
+    if (self = [super init]) {
+        // default values
+        self.location = YES;
+        self.closebuttoncaption = nil;
+        self.toolbarposition = kThemeableBrowserToolbarBarPositionBottom;
+        self.clearcache = NO;
+        self.clearsessioncache = NO;
+
+        self.zoom = YES;
+        self.mediaplaybackrequiresuseraction = NO;
+        self.allowinlinemediaplayback = NO;
+        self.keyboarddisplayrequiresuseraction = YES;
+        self.suppressesincrementalrendering = NO;
+        self.hidden = NO;
+        self.disallowoverscroll = NO;
+
+        self.statusbar = nil;
+        self.toolbar = nil;
+        self.title = nil;
+        self.backButton = nil;
+        self.forwardButton = nil;
+        self.closeButton = nil;
+        self.menu = nil;
+        self.backButtonCanClose = NO;
+        self.disableAnimation = NO;
+        self.fullscreen = NO;
+    }
+
+    return self;
+}
+
+@end
+
+#pragma mark CDVScreenOrientationDelegate
+
+@implementation CDVThemeableBrowserNavigationController : UINavigationController
+
+- (BOOL)shouldAutorotate
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotate)]) {
+        return [self.orientationDelegate shouldAutorotate];
+    }
+    return YES;
+}
+
+- (NSUInteger)supportedInterfaceOrientations
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(supportedInterfaceOrientations)]) {
+        return [self.orientationDelegate supportedInterfaceOrientations];
+    }
+
+    return 1 << UIInterfaceOrientationPortrait;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    if ((self.orientationDelegate != nil) && [self.orientationDelegate respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
+        return [self.orientationDelegate shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+    }
+
+    return YES;
+}
+
+
+@end
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.h b/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.h
new file mode 100755
index 0000000..2f8496f
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.h
@@ -0,0 +1,13 @@
+#import <Cordova/CDVPlugin.h>
+
+@interface TouchID :CDVPlugin
+
+- (void) isAvailable:(CDVInvokedUrlCommand*)command;
+
+- (void) didFingerprintDatabaseChange:(CDVInvokedUrlCommand*)command;
+
+- (void) verifyFingerprint:(CDVInvokedUrlCommand*)command;
+- (void) verifyFingerprintWithCustomPasswordFallback:(CDVInvokedUrlCommand*)command;
+- (void) verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel:(CDVInvokedUrlCommand*)command;
+
+@end
\ No newline at end of file
diff --git a/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.m b/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.m
new file mode 100755
index 0000000..f8bd832
--- /dev/null
+++ b/platforms/ios/dlapp/Plugins/cordova-plugin-touch-id/TouchID.m
@@ -0,0 +1,214 @@
+#import "TouchID.h"
+#import <LocalAuthentication/LocalAuthentication.h>
+
+static NSString *const FingerprintDatabaseStateKey = @"FingerprintDatabaseStateKey";
+
+@implementation TouchID
+
+// These two combined need to be unique, so one can be fixed
+NSString *keychainItemIdentifier = @"TouchIDKey";
+NSString *keychainItemServiceName;
+
+- (void) isAvailable:(CDVInvokedUrlCommand*)command {
+
+  if (NSClassFromString(@"LAContext") == NULL) {
+    [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR] callbackId:command.callbackId];
+    return;
+  }
+
+  [self.commandDelegate runInBackground:^{
+
+    NSError *error = nil;
+    LAContext *laContext = [[LAContext alloc] init];
+
+    if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
+      NSString *biometryType = @"touch";
+      if (@available(iOS 11.0, *)) {
+        if (laContext.biometryType == LABiometryTypeFaceID) {
+          biometryType = @"face";
+        }
+      }
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:biometryType]
+                                  callbackId:command.callbackId];
+    } else {
+      NSArray *errorKeys = @[@"code", @"localizedDescription"];
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[error dictionaryWithValuesForKeys:errorKeys]]
+                                  callbackId:command.callbackId];
+    }
+  }];
+}
+
+- (void) didFingerprintDatabaseChange:(CDVInvokedUrlCommand*)command {
+  // Get enrollment state
+  [self.commandDelegate runInBackground:^{
+    LAContext *laContext = [[LAContext alloc] init];
+    NSError *error = nil;
+
+    // we expect the dev to have checked 'isAvailable' already so this should not return an error,
+    // we do however need to run canEvaluatePolicy here in order to get a non-nil evaluatedPolicyDomainState
+    if (![laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]] callbackId:command.callbackId];
+      return;
+    }
+
+    // only supported on iOS9+, so check this.. if not supported just report back as false
+    if (![laContext respondsToSelector:@selector(evaluatedPolicyDomainState)]) {
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:NO] callbackId:command.callbackId];
+      return;
+    }
+
+    NSData * state = [laContext evaluatedPolicyDomainState];
+    if (state != nil) {
+
+      NSString * stateStr = [state base64EncodedStringWithOptions:0];
+
+      NSString * storedState = [[NSUserDefaults standardUserDefaults] stringForKey:FingerprintDatabaseStateKey];
+
+      // whenever a finger is added/changed/removed the value of the storedState changes,
+      // so compare agains a value we previously stored in the context of this app
+      BOOL changed = storedState != nil && ![stateStr isEqualToString:storedState];
+
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:changed] callbackId:command.callbackId];
+
+      // Store enrollment
+      [[NSUserDefaults standardUserDefaults] setObject:stateStr forKey:FingerprintDatabaseStateKey];
+      [[NSUserDefaults standardUserDefaults] synchronize];
+    }
+  }];
+}
+
+// this 'default' method uses keychain instead of localauth so the passcode fallback can be used
+- (void) verifyFingerprint:(CDVInvokedUrlCommand*)command {
+
+  NSString *message = [command.arguments objectAtIndex:0];
+  NSString *callbackId = command.callbackId;
+
+  [self.commandDelegate runInBackground:^{
+
+    if (keychainItemServiceName == nil) {
+      NSString *bundleID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
+      keychainItemServiceName = [bundleID stringByAppendingString:@".TouchIDPlugin"];
+    }
+
+    if (![self createKeyChainEntry]) {
+      NSLog(@"Keychain trouble. Falling back to verifyFingerprintWithCustomPasswordFallback.");
+      [self verifyFingerprintWithCustomPasswordFallback:command];
+      return;
+    }
+
+    // Create the keychain query attributes using the values from the first part of the code.
+    NSMutableDictionary * query = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
+                                   (__bridge id)(kSecClassGenericPassword), kSecClass,
+                                   keychainItemIdentifier, kSecAttrAccount,
+                                   keychainItemServiceName, kSecAttrService,
+                                   message, kSecUseOperationPrompt,
+                                   nil];
+
+    // Start the query and the fingerprint scan and/or device passcode validation
+    OSStatus userPresenceStatus = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL);
+
+    // Ignore the found content of the key chain entry (the dummy password) and only evaluate the return code.
+    if (noErr == userPresenceStatus)
+    {
+      NSLog(@"Fingerprint or device passcode validated.");
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
+                                  callbackId:command.callbackId];
+    }
+    else
+    {
+      NSLog(@"Fingerprint or device passcode could not be validated. Status %d.", (int) userPresenceStatus);
+
+      NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:userPresenceStatus userInfo:nil];
+      NSArray *errorKeys = @[@"code", @"localizedDescription"];
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+                                                           messageAsDictionary:[error dictionaryWithValuesForKeys:errorKeys]]
+                                  callbackId:callbackId];
+      return;
+    }
+  }];
+}
+
+// This implementation uses LocalAuthentication and has no built-in passcode fallback
+- (void) verifyFingerprintWithCustomPasswordFallback:(CDVInvokedUrlCommand*)command {
+  NSString *message = [command.arguments objectAtIndex:0];
+  [self verifyFingerprintWithCustomPasswordFallback:command.callbackId withMessage:message andEnterPasswordLabel:nil];
+}
+
+- (void) verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel:(CDVInvokedUrlCommand*)command {
+  NSString *message = [command.arguments objectAtIndex:0];
+  NSString *enterPasswordLabel = [command.arguments objectAtIndex:1];
+  [self verifyFingerprintWithCustomPasswordFallback:command.callbackId withMessage:message andEnterPasswordLabel:enterPasswordLabel];
+}
+
+- (void) verifyFingerprintWithCustomPasswordFallback:(NSString*)callbackId withMessage:(NSString*)message andEnterPasswordLabel:(NSString*)enterPasswordLabel {
+
+  if (NSClassFromString(@"LAContext") == NULL) {
+    [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]
+                                callbackId:callbackId];
+    return;
+  }
+
+  [self.commandDelegate runInBackground:^{
+    NSError *error = nil;
+    LAContext *laContext = [[LAContext alloc] init];
+
+    if (![laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
+      [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]
+                                  callbackId:callbackId];
+      return;
+    }
+
+    // if we add a 'verifyFingerprintWithOptions' method we can add stuff like this:
+    // the nr of seconds you allow to reuse the last touchid device unlock (default 0, so never reuse)
+//    laContext.touchIDAuthenticationAllowableReuseDuration = 30;
+
+    // this replaces the default 'Enter password' button label
+    if (enterPasswordLabel != nil) {
+      laContext.localizedFallbackTitle = enterPasswordLabel;
+    }
+
+    [laContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:message reply:^(BOOL authOK, NSError *error) {
+      if (authOK) {
+        [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
+                                    callbackId:callbackId];
+      } else {
+        // invoked when the scan failed 3 times in a row, the cancel button was pressed, or the 'enter password' button was pressed
+        NSArray *errorKeys = @[@"code", @"localizedDescription"];
+        [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
+                                                           messageAsDictionary:[error dictionaryWithValuesForKeys:errorKeys]]
+                                    callbackId:callbackId];
+      }
+    }];
+  }];
+}
+
+// Note that this needs to run only once but it can deal with multiple runs
+- (BOOL) createKeyChainEntry {
+  NSMutableDictionary	* attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
+                                      (__bridge id)(kSecClassGenericPassword), kSecClass,
+                                      keychainItemIdentifier, kSecAttrAccount,
+                                      keychainItemServiceName, kSecAttrService,
+                                      nil];
+
+  CFErrorRef accessControlError = NULL;
+  SecAccessControlRef accessControlRef = SecAccessControlCreateWithFlags(
+                                                                         kCFAllocatorDefault,
+                                                                         kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
+                                                                         2, // either kSecAccessControlBiometryAny (iOS 11.3+) or kSecAccessControlTouchIDAny (iOS < 11.3),
+                                                                         &accessControlError);
+  if (accessControlRef == NULL || accessControlError != NULL)
+  {
+    NSLog(@"Can't store identifier '%@' in the KeyChain: %@.", keychainItemIdentifier, accessControlError);
+    return NO;
+  }
+
+  attributes[(__bridge id)kSecAttrAccessControl] = (__bridge id)accessControlRef;
+  attributes[(__bridge id)kSecUseAuthenticationUI] = @YES;
+  // The content of the password is not important.
+  attributes[(__bridge id)kSecValueData] = [@"dummy content" dataUsingEncoding:NSUTF8StringEncoding];
+
+  SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
+  return YES;
+}
+
+@end
diff --git a/platforms/ios/dlapp/Scripts/copy-www-build-step.sh b/platforms/ios/dlapp/Scripts/copy-www-build-step.sh
new file mode 100755
index 0000000..ba0a1b4
--- /dev/null
+++ b/platforms/ios/dlapp/Scripts/copy-www-build-step.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+#    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.
+#
+#
+#   This script copies the www directory into the Xcode project.
+#
+#   This script should not be called directly.
+#   It is called as a build step from Xcode.
+
+SRC_DIR="www"
+DST_DIR="$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME"
+DST_DIR_WWW="$DST_DIR/www"
+COPY_HIDDEN=
+ORIG_IFS=$IFS
+IFS=$(echo -en "\n\b")
+
+if [[ -z "$BUILT_PRODUCTS_DIR" ]]; then
+  echo "The script is meant to be run as an Xcode build step and relies on env variables set by Xcode."
+  exit 1
+fi
+
+if [[ ! -e "$SRC_DIR" ]]; then
+  echo "error: Path does not exist: $SRC_DIR"
+  exit 2
+fi
+
+rm -rf "$DST_DIR_WWW"
+
+# Copy www dir recursively
+CODE=
+if [[ -n $COPY_HIDDEN ]]; then
+    rsync -Lra "$SRC_DIR" "$DST_DIR"
+    CODE=$?
+else
+    rsync -Lra --exclude="- .*" "$SRC_DIR" "$DST_DIR"
+    CODE=$?
+fi
+
+if [ $CODE -ne 0 ]; then
+    echo "error: Error occurred on copying www. Code $CODE"
+    exit 3
+fi
+
+# Copy the config.xml file.
+cp -f "${PROJECT_FILE_PATH%.xcodeproj}/config.xml" "$DST_DIR"
+
+IFS=$ORIG_IFS
diff --git a/platforms/ios/dlapp/config.xml b/platforms/ios/dlapp/config.xml
new file mode 100755
index 0000000..b9c0ba5
--- /dev/null
+++ b/platforms/ios/dlapp/config.xml
@@ -0,0 +1,104 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage" />
+    </feature>
+    <feature name="Console">
+        <param name="ios-package" value="CDVLogger" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="HandleOpenUrl">
+        <param name="ios-package" value="CDVHandleOpenURL" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="IntentAndNavigationFilter">
+        <param name="ios-package" value="CDVIntentAndNavigationFilter" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="GestureHandler">
+        <param name="ios-package" value="CDVGestureHandler" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="File">
+        <param name="ios-package" value="CDVFile" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="CordovaHttpPlugin">
+        <param name="ios-package" value="CordovaHttpPlugin" />
+    </feature>
+    <feature name="Fingerprint">
+        <param name="ios-package" value="Fingerprint" />
+    </feature>
+    <feature name="StatusBar">
+        <param name="ios-package" value="CDVStatusBar" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="TouchID">
+        <param name="ios-package" value="TouchID" />
+    </feature>
+    <feature name="DisableStatusbar">
+        <param name="ios-package" value="DisableStatusbar" />
+        <param name="onload" value="true" />
+    </feature>
+    <feature name="QRScanner">
+        <param name="ios-package" value="QRScanner" />
+    </feature>
+    <feature name="Camera">
+        <param name="ios-package" value="CDVCamera" />
+    </feature>
+    <feature name="InAppBrowser">
+        <param name="ios-package" value="CDVInAppBrowser" />
+    </feature>
+    <feature name="Device">
+        <param name="ios-package" value="CDVDevice" />
+    </feature>
+    <feature name="ThemeableBrowser">
+        <param name="ios-package" value="CDVThemeableBrowser" />
+    </feature>
+    <name>dlapp</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <allow-intent href="http://*/*" />
+    <allow-intent href="https://*/*" />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*" />
+    <allow-intent href="geo:*" />
+    <allow-navigation href="http://*/*" />
+    <allow-navigation href="https://*/*" />
+    <allow-navigation href="data:*" />
+    <access origin="http://ip*" />
+    <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
+        <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+    </edit-config>
+    <allow-intent href="itms:*" />
+    <allow-intent href="itms-apps:*" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="BackupWebStorage" value="local" />
+    <preference name="DisallowOverscroll" value="true" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="SuppressesLongPressGesture" value="false" />
+    <preference name="Suppresses3DTouchGesture" value="false" />
+    <preference name="GapBetweenPages" value="0" />
+    <preference name="PageLength" value="0" />
+    <preference name="PaginationBreakingMode" value="page" />
+    <preference name="PaginationMode" value="unpaginated" />
+    <preference name="StatusBarOverlaysWebView" value="true" />
+    <preference name="StatusBarStyle" value="lightcontent" />
+    <preference name="CameraUsesGeolocation" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="SplashScreenDelay" value="0" />
+    <preference name="ErrorUrl" value="error.html" />
+    <preference name="Orientation" value="portrait" />
+    <preference name="UseSwiftLanguageVersion" value="4.0" />
+    <preference name="UIWebViewBounce" value="false" />
+</widget>
diff --git a/platforms/ios/dlapp/dlapp-Info.plist b/platforms/ios/dlapp/dlapp-Info.plist
new file mode 100644
index 0000000..332d3ce
--- /dev/null
+++ b/platforms/ios/dlapp/dlapp-Info.plist
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en_US</string>
+	<key>CFBundleDisplayName</key>
+	<string>dlapp</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>大理市民卡</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0.0</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
+		<key>NSExceptionDomains</key>
+		<dict>
+			<key>ip</key>
+			<dict>
+				<key>NSExceptionAllowsInsecureHTTPLoads</key>
+				<true/>
+			</dict>
+		</dict>
+	</dict>
+	<key>NSCameraUsageDescription</key>
+	<string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
+	<key>NSFaceIDUsageDescription</key>
+	<string/>
+	<key>NSMainNibFile</key>
+	<string/>
+	<key>NSMainNibFile~ipad</key>
+	<string/>
+	<key>UIInterfaceOrientation</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>UIRequiresFullScreen</key>
+	<true/>
+	<key>UIStatusBarStyle</key>
+	<string>UIStatusBarStyleLightContent</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+</dict>
+</plist>
\ No newline at end of file
diff --git a/platforms/ios/dlapp/dlapp-Prefix.pch b/platforms/ios/dlapp/dlapp-Prefix.pch
new file mode 100644
index 0000000..fd3b34b
--- /dev/null
+++ b/platforms/ios/dlapp/dlapp-Prefix.pch
@@ -0,0 +1,26 @@
+/*
+ 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.
+ */
+//
+// Prefix header for all source files of the 'dlapp' target in the 'dlapp' project
+//
+
+#ifdef __OBJC__
+    #import <Foundation/Foundation.h>
+    #import <UIKit/UIKit.h>
+#endif
diff --git a/platforms/ios/dlapp/main.m b/platforms/ios/dlapp/main.m
new file mode 100644
index 0000000..99d577f
--- /dev/null
+++ b/platforms/ios/dlapp/main.m
@@ -0,0 +1,35 @@
+/*
+ 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.
+ */
+//
+//  main.m
+//  dlapp
+//
+//  Created by ___FULLUSERNAME___ on ___DATE___.
+//  Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+int main(int argc, char* argv[])
+{
+    @autoreleasepool {
+        int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
+        return retVal;
+    }
+}
diff --git a/platforms/ios/exportOptions.plist b/platforms/ios/exportOptions.plist
new file mode 100644
index 0000000..00b0541
--- /dev/null
+++ b/platforms/ios/exportOptions.plist
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+  <dict>
+    <key>compileBitcode</key>
+    <false/>
+    <key>method</key>
+    <string>development</string>
+  </dict>
+</plist>
\ No newline at end of file
diff --git a/platforms/ios/frameworks.json b/platforms/ios/frameworks.json
new file mode 100644
index 0000000..be943cc
--- /dev/null
+++ b/platforms/ios/frameworks.json
@@ -0,0 +1,8 @@
+{
+    "Security.framework": 2,
+    "SystemConfiguration.framework": 1,
+    "LocalAuthentication.framework": 1,
+    "ImageIO.framework": 1,
+    "CoreLocation.framework": 1,
+    "AVFoundation.framework": 1
+}
\ No newline at end of file
diff --git a/platforms/ios/ios.json b/platforms/ios/ios.json
new file mode 100644
index 0000000..ba7facb
--- /dev/null
+++ b/platforms/ios/ios.json
@@ -0,0 +1,475 @@
+{
+  "prepare_queue": {
+    "installed": [],
+    "uninstalled": []
+  },
+  "config_munge": {
+    "files": {
+      "config.xml": {
+        "parents": {
+          "/*": [
+            {
+              "xml": "<feature name=\"File\"><param name=\"ios-package\" value=\"CDVFile\" /><param name=\"onload\" value=\"true\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"CordovaHttpPlugin\"><param name=\"ios-package\" value=\"CordovaHttpPlugin\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Fingerprint\"><param name=\"ios-package\" value=\"Fingerprint\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"StatusBar\"><param name=\"ios-package\" value=\"CDVStatusBar\" /><param name=\"onload\" value=\"true\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"StatusBarOverlaysWebView\" value=\"true\" />",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"StatusBarStyle\" value=\"lightcontent\" />",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"TouchID\"><param name=\"ios-package\" value=\"TouchID\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"DisableStatusbar\"><param name=\"ios-package\" value=\"DisableStatusbar\" /><param name=\"onload\" value=\"true\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"QRScanner\"><param name=\"ios-package\" value=\"QRScanner\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Camera\"><param name=\"ios-package\" value=\"CDVCamera\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<preference name=\"CameraUsesGeolocation\" value=\"false\" />",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"InAppBrowser\"><param name=\"ios-package\" value=\"CDVInAppBrowser\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"Device\"><param name=\"ios-package\" value=\"CDVDevice\" /></feature>",
+              "count": 1
+            },
+            {
+              "xml": "<feature name=\"ThemeableBrowser\"><param name=\"ios-package\" value=\"CDVThemeableBrowser\" /></feature>",
+              "count": 1
+            }
+          ]
+        }
+      },
+      "*-Info.plist": {
+        "parents": {
+          "NSFaceIDUsageDescription": [
+            {
+              "xml": "<string>认证中...</string>",
+              "count": 1
+            },
+            {
+              "xml": "<string> </string>",
+              "count": 1
+            }
+          ],
+          "NSCameraUsageDescription": [
+            {
+              "xml": "<string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>",
+              "count": 1,
+              "mode": "merge",
+              "id": "config.xml"
+            }
+          ]
+        }
+      }
+    }
+  },
+  "installed_plugins": {
+    "cordova-plugin-add-swift-support": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-file": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-advanced-http": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-fingerprint-aio": {
+      "FACEID_USAGE_DESCRIPTION": "认证中...",
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-statusbar": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-touch-id": {
+      "FACEID_USAGE_DESCRIPTION": " ",
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-whitelist": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-disable-ios11-statusbar": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-qrscanner": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-camera": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-inappbrowser": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-device": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    },
+    "cordova-plugin-themeablebrowser": {
+      "PACKAGE_NAME": "$(PRODUCT_BUNDLE_IDENTIFIER)"
+    }
+  },
+  "dependent_plugins": {},
+  "modules": [
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.iosFileSystem",
+      "file": "plugins/cordova-plugin-file/www/ios/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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/ios/CameraPopoverHandle.js",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "CameraPopoverHandle"
+      ]
+    },
+    {
+      "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-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ],
+  "plugin_metadata": {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  }
+}
diff --git a/platforms/ios/platform_www/cordova-js-src/exec.js b/platforms/ios/platform_www/cordova-js-src/exec.js
new file mode 100644
index 0000000..3fb7fa1
--- /dev/null
+++ b/platforms/ios/platform_www/cordova-js-src/exec.js
@@ -0,0 +1,262 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/*global require, module, atob, document */
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    execIframe,
+    commandQueue = [], // Contains pending JS->Native messages.
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
+
+function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+        return args;
+    }
+    var ret = [];
+    args.forEach(function(arg, i) {
+        if (utils.typeName(arg) == 'ArrayBuffer') {
+            ret.push({
+                'CDVType': 'ArrayBuffer',
+                'data': base64.fromArrayBuffer(arg)
+            });
+        } else {
+            ret.push(arg);
+        }
+    });
+    return ret;
+}
+
+function massageMessageNativeToJs(message) {
+    if (message.CDVType == 'ArrayBuffer') {
+        var stringToArrayBuffer = function(str) {
+            var ret = new Uint8Array(str.length);
+            for (var i = 0; i < str.length; i++) {
+                ret[i] = str.charCodeAt(i);
+            }
+            return ret.buffer;
+        };
+        var base64ToArrayBuffer = function(b64) {
+            return stringToArrayBuffer(atob(b64));
+        };
+        message = base64ToArrayBuffer(message.data);
+    }
+    return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+    var args = [];
+    if (!message || !message.hasOwnProperty('CDVType')) {
+        args.push(message);
+    } else if (message.CDVType == 'MultiPart') {
+        message.messages.forEach(function(e) {
+            args.push(massageMessageNativeToJs(e));
+        });
+    } else {
+        args.push(massageMessageNativeToJs(message));
+    }
+    return args;
+}
+
+function iOSExec() {
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== 'string') {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+            'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
+        );
+    }
+
+    // If actionArgs is not provided, default to an empty array
+    actionArgs = actionArgs || [];
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] =
+            {success:successCallback, fail:failCallback};
+    }
+
+    actionArgs = massageArgsJsToNative(actionArgs);
+
+    var command = [callbackId, service, action, actionArgs];
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    commandQueue.push(JSON.stringify(command));
+
+    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+    // then the queue will be flushed when it returns; no need for a poke.
+    // Also, if there is already a command in the queue, then we've already
+    // poked the native side, so there is no reason to do so again.
+    if (!isInContextOfEvalJs && commandQueue.length == 1) {
+        pokeNative();
+    }
+}
+
+// CB-10530
+function proxyChanged() {
+    var cexec = cordovaExec();
+       
+    return (execProxy !== cexec && // proxy objects are different
+            iOSExec !== cexec      // proxy object is not the current iOSExec
+            );
+}
+
+// CB-10106
+function handleBridgeChange() {
+    if (proxyChanged()) {
+        var commandString = commandQueue.shift();
+        while(commandString) {
+            var command = JSON.parse(commandString);
+            var callbackId = command[0];
+            var service = command[1];
+            var action = command[2];
+            var actionArgs = command[3];
+            var callbacks = cordova.callbacks[callbackId] || {};
+            
+            execProxy(callbacks.success, callbacks.fail, service, action, actionArgs);
+            
+            commandString = commandQueue.shift();
+        };
+        return true;
+    }
+    
+    return false;
+}
+
+function pokeNative() {
+    // CB-5488 - Don't attempt to create iframe before document.body is available.
+    if (!document.body) {
+        setTimeout(pokeNative);
+        return;
+    }
+    
+    // Check if they've removed it from the DOM, and put it back if so.
+    if (execIframe && execIframe.contentWindow) {
+        execIframe.contentWindow.location = 'gap://ready';
+    } else {
+        execIframe = document.createElement('iframe');
+        execIframe.style.display = 'none';
+        execIframe.src = 'gap://ready';
+        document.body.appendChild(execIframe);
+    }
+    // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+    // This makes the bridge ~ 7% slower, but works around the poke getting lost
+    // when the iframe is removed from the DOM.
+    // An onunload listener could be used in the case where the iframe has just been
+    // created, but since unload events fire only once, it doesn't work in the normal
+    // case of iframe reuse (where unload will have already fired due to the attempted
+    // navigation of the page).
+    failSafeTimerId = setTimeout(function() {
+        if (commandQueue.length) {
+            // CB-10106 - flush the queue on bridge change
+            if (!handleBridgeChange()) {
+                pokeNative();
+             }
+        }
+    }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+}
+
+iOSExec.nativeFetchMessages = function() {
+    // Stop listing for window detatch once native side confirms poke.
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
+    }
+    // Each entry in commandQueue is a JSON string already.
+    if (!commandQueue.length) {
+        return '';
+    }
+    var json = '[' + commandQueue.join(',') + ']';
+    commandQueue.length = 0;
+    return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+    return iOSExec.nativeEvalAndFetch(function() {
+        var success = status === 0 || status === 1;
+        var args = convertMessageToArgsNativeToJs(message);
+        function nc2() {
+            cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+        }
+        setTimeout(nc2, 0);
+    });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+    // This shouldn't be nested, but better to be safe.
+    isInContextOfEvalJs++;
+    try {
+        func();
+        return iOSExec.nativeFetchMessages();
+    } finally {
+        isInContextOfEvalJs--;
+    }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+    var cexec = require('cordova/exec');
+    var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+    return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+    cordovaExec().apply(null, arguments);
+};
+
+execProxy.nativeFetchMessages = function() {
+    return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+    return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+    return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
diff --git a/platforms/ios/platform_www/cordova-js-src/platform.js b/platforms/ios/platform_www/cordova-js-src/platform.js
new file mode 100644
index 0000000..2345fa5
--- /dev/null
+++ b/platforms/ios/platform_www/cordova-js-src/platform.js
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+module.exports = {
+    id: 'ios',
+    bootstrap: function () {
+        // Attach the console polyfill that is iOS-only to window.console
+        // see the file under plugin/ios/console.js
+        require('cordova/modulemapper').clobbers('cordova/plugin/ios/console', 'window.console');
+
+        require('cordova/channel').onNativeReady.fire();
+    }
+};
diff --git a/platforms/ios/platform_www/cordova-js-src/plugin/ios/console.js b/platforms/ios/platform_www/cordova-js-src/plugin/ios/console.js
new file mode 100644
index 0000000..6224fb4
--- /dev/null
+++ b/platforms/ios/platform_www/cordova-js-src/plugin/ios/console.js
@@ -0,0 +1,186 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+//------------------------------------------------------------------------------
+
+var logger = require('cordova/plugin/ios/logger');
+
+//------------------------------------------------------------------------------
+// object that we're exporting
+//------------------------------------------------------------------------------
+var console = module.exports;
+
+//------------------------------------------------------------------------------
+// copy of the original console object
+//------------------------------------------------------------------------------
+var WinConsole = window.console;
+
+//------------------------------------------------------------------------------
+// whether to use the logger
+//------------------------------------------------------------------------------
+var UseLogger = false;
+
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+var Timers = {};
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+function noop() {}
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+console.useLogger = function (value) {
+    if (arguments.length) UseLogger = !!value;
+
+    if (UseLogger) {
+        if (logger.useConsole()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+    }
+
+    return UseLogger;
+};
+
+//------------------------------------------------------------------------------
+console.log = function() {
+    if (logger.useConsole()) return;
+    logger.log.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.error = function() {
+    if (logger.useConsole()) return;
+    logger.error.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.warn = function() {
+    if (logger.useConsole()) return;
+    logger.warn.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.info = function() {
+    if (logger.useConsole()) return;
+    logger.info.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.debug = function() {
+    if (logger.useConsole()) return;
+    logger.debug.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.assert = function(expression) {
+    if (expression) return;
+
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
+    console.log("ASSERT: " + message);
+};
+
+//------------------------------------------------------------------------------
+console.clear = function() {};
+
+//------------------------------------------------------------------------------
+console.dir = function(object) {
+    console.log("%o", object);
+};
+
+//------------------------------------------------------------------------------
+console.dirxml = function(node) {
+    console.log(node.innerHTML);
+};
+
+//------------------------------------------------------------------------------
+console.trace = noop;
+
+//------------------------------------------------------------------------------
+console.group = console.log;
+
+//------------------------------------------------------------------------------
+console.groupCollapsed = console.log;
+
+//------------------------------------------------------------------------------
+console.groupEnd = noop;
+
+//------------------------------------------------------------------------------
+console.time = function(name) {
+    Timers[name] = new Date().valueOf();
+};
+
+//------------------------------------------------------------------------------
+console.timeEnd = function(name) {
+    var timeStart = Timers[name];
+    if (!timeStart) {
+        console.warn("unknown timer: " + name);
+        return;
+    }
+
+    var timeElapsed = new Date().valueOf() - timeStart;
+    console.log(name + ": " + timeElapsed + "ms");
+};
+
+//------------------------------------------------------------------------------
+console.timeStamp = noop;
+
+//------------------------------------------------------------------------------
+console.profile = noop;
+
+//------------------------------------------------------------------------------
+console.profileEnd = noop;
+
+//------------------------------------------------------------------------------
+console.count = noop;
+
+//------------------------------------------------------------------------------
+console.exception = console.log;
+
+//------------------------------------------------------------------------------
+console.table = function(data, columns) {
+    console.log("%o", data);
+};
+
+//------------------------------------------------------------------------------
+// return a new function that calls both functions passed as args
+//------------------------------------------------------------------------------
+function wrappedOrigCall(orgFunc, newFunc) {
+    return function() {
+        var args = [].slice.call(arguments);
+        try { orgFunc.apply(WinConsole, args); } catch (e) {}
+        try { newFunc.apply(console,    args); } catch (e) {}
+    };
+}
+
+//------------------------------------------------------------------------------
+// For every function that exists in the original console object, that
+// also exists in the new console object, wrap the new console method
+// with one that calls both
+//------------------------------------------------------------------------------
+for (var key in console) {
+    if (typeof WinConsole[key] == "function") {
+        console[key] = wrappedOrigCall(WinConsole[key], console[key]);
+    }
+}
diff --git a/platforms/ios/platform_www/cordova-js-src/plugin/ios/logger.js b/platforms/ios/platform_www/cordova-js-src/plugin/ios/logger.js
new file mode 100644
index 0000000..430d887
--- /dev/null
+++ b/platforms/ios/platform_www/cordova-js-src/plugin/ios/logger.js
@@ -0,0 +1,354 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports;
+
+var exec    = require('cordova/exec');
+
+var UseConsole   = false;
+var UseLogger    = true;
+var Queued       = [];
+var DeviceReady  = false;
+var CurrentLevel;
+
+var originalConsole = console;
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+];
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {};
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i];
+    LevelsMap[level] = i;
+    logger[level]    = level;
+}
+
+CurrentLevel = LevelsMap.WARN;
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  E.g., the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] === null) {
+            throw new Error("invalid logging level: " + value);
+        }
+        CurrentLevel = LevelsMap[value];
+    }
+
+    return Levels[CurrentLevel];
+};
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value;
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined");
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function");
+        }
+
+        if (typeof console.useLogger == "function") {
+            if (console.useLogger()) {
+                throw new Error("console and logger are too intertwingly");
+            }
+        }
+    }
+
+    return UseConsole;
+};
+
+/**
+ * Getter/Setter for the useLogger functionality
+ *
+ * When useLogger is true, the logger will log via the
+ * native Logger plugin.
+ */
+logger.useLogger = function (value) {
+    // Enforce boolean
+    if (arguments.length) UseLogger = !!value;
+    return UseLogger;
+};
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments); };
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments); };
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments); };
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    args = [level].concat([].slice.call(args));
+    logger.logLevel.apply(logger, args);
+}
+
+// return the correct formatString for an object
+function formatStringForMessage(message) {
+    return (typeof message === "string") ? "" : "%o"; 
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 1);
+    var fmtString = formatStringForMessage(formatArgs[0]);
+    if (fmtString.length > 0){
+        formatArgs.unshift(fmtString); // add formatString
+    }
+
+    var message    = logger.format.apply(logger.format, formatArgs);
+
+    if (LevelsMap[level] === null) {
+        throw new Error("invalid logging level: " + level);
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return;
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message]);
+        return;
+    }
+
+    // Log using the native logger if that is enabled
+    if (UseLogger) {
+        exec(null, null, "Console", "logLevel", [level, message]);
+    }
+
+    // Log using the console if that is enabled
+    if (UseConsole) {
+        // make sure console is not using logger
+        if (console.useLogger()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+
+        // log to the console
+        switch (level) {
+            case logger.LOG:   originalConsole.log(message); break;
+            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
+            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
+            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
+            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
+        }
+    }
+};
+
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return;
+
+    DeviceReady = true;
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i];
+        logger.logLevel(messageArgs[0], messageArgs[1]);
+    }
+
+    Queued = null;
+};
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false);
diff --git a/platforms/ios/platform_www/cordova.js b/platforms/ios/platform_www/cordova.js
new file mode 100644
index 0000000..2e2b33a
--- /dev/null
+++ b/platforms/ios/platform_www/cordova.js
@@ -0,0 +1,2162 @@
+// Platform: ios
+// 948e932548412305aa7f24b3a90e386aa5c3d12c
+/*
+ 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.
+*/
+;(function() {
+var PLATFORM_VERSION_BUILD_LABEL = '5.0.1';
+// file: src/scripts/require.js
+
+var require;
+var define;
+
+(function () {
+    var modules = {};
+    // Stack of moduleIds currently being built.
+    var requireStack = [];
+    // Map of module ID -> index into requireStack of modules currently being built.
+    var inProgressModules = {};
+    var SEPARATOR = '.';
+
+    function build (module) {
+        var factory = module.factory;
+        var localRequire = function (id) {
+            var resultantId = id;
+            // Its a relative path, so lop off the last portion and add the id (minus "./")
+            if (id.charAt(0) === '.') {
+                resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
+            }
+            return require(resultantId);
+        };
+        module.exports = {};
+        delete module.factory;
+        factory(localRequire, module.exports, module);
+        return module.exports;
+    }
+
+    require = function (id) {
+        if (!modules[id]) {
+            throw 'module ' + id + ' not found';
+        } else if (id in inProgressModules) {
+            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
+            throw 'Cycle in require graph: ' + cycle;
+        }
+        if (modules[id].factory) {
+            try {
+                inProgressModules[id] = requireStack.length;
+                requireStack.push(id);
+                return build(modules[id]);
+            } finally {
+                delete inProgressModules[id];
+                requireStack.pop();
+            }
+        }
+        return modules[id].exports;
+    };
+
+    define = function (id, factory) {
+        if (modules[id]) {
+            throw 'module ' + id + ' already defined';
+        }
+
+        modules[id] = {
+            id: id,
+            factory: factory
+        };
+    };
+
+    define.remove = function (id) {
+        delete modules[id];
+    };
+
+    define.moduleMap = modules;
+})();
+
+// Export for use in node
+if (typeof module === 'object' && typeof require === 'function') {
+    module.exports.require = require;
+    module.exports.define = define;
+}
+
+// file: src/cordova.js
+define("cordova", function(require, exports, module) {
+
+// Workaround for Windows 10 in hosted environment case
+// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
+if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
+    throw new Error('cordova already defined');
+}
+
+var channel = require('cordova/channel');
+var platform = require('cordova/platform');
+
+/**
+ * Intercept calls to addEventListener + removeEventListener and handle deviceready,
+ * resume, and pause events.
+ */
+var m_document_addEventListener = document.addEventListener;
+var m_document_removeEventListener = document.removeEventListener;
+var m_window_addEventListener = window.addEventListener;
+var m_window_removeEventListener = window.removeEventListener;
+
+/**
+ * Houses custom event handlers to intercept on document + window event listeners.
+ */
+var documentEventHandlers = {};
+var windowEventHandlers = {};
+
+document.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].subscribe(handler);
+    } else {
+        m_document_addEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.addEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].subscribe(handler);
+    } else {
+        m_window_addEventListener.call(window, evt, handler, capture);
+    }
+};
+
+document.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof documentEventHandlers[e] !== 'undefined') {
+        documentEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_document_removeEventListener.call(document, evt, handler, capture);
+    }
+};
+
+window.removeEventListener = function (evt, handler, capture) {
+    var e = evt.toLowerCase();
+    // If unsubscribing from an event that is handled by a plugin
+    if (typeof windowEventHandlers[e] !== 'undefined') {
+        windowEventHandlers[e].unsubscribe(handler);
+    } else {
+        m_window_removeEventListener.call(window, evt, handler, capture);
+    }
+};
+
+function createEvent (type, data) {
+    var event = document.createEvent('Events');
+    event.initEvent(type, false, false);
+    if (data) {
+        for (var i in data) {
+            if (data.hasOwnProperty(i)) {
+                event[i] = data[i];
+            }
+        }
+    }
+    return event;
+}
+
+/* eslint-disable no-undef */
+var cordova = {
+    define: define,
+    require: require,
+    version: PLATFORM_VERSION_BUILD_LABEL,
+    platformVersion: PLATFORM_VERSION_BUILD_LABEL,
+    platformId: platform.id,
+
+    /* eslint-enable no-undef */
+
+    /**
+     * Methods to add/remove your own addEventListener hijacking on document + window.
+     */
+    addWindowEventHandler: function (event) {
+        return (windowEventHandlers[event] = channel.create(event));
+    },
+    addStickyDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.createSticky(event));
+    },
+    addDocumentEventHandler: function (event) {
+        return (documentEventHandlers[event] = channel.create(event));
+    },
+    removeWindowEventHandler: function (event) {
+        delete windowEventHandlers[event];
+    },
+    removeDocumentEventHandler: function (event) {
+        delete documentEventHandlers[event];
+    },
+    /**
+     * Retrieve original event handlers that were replaced by Cordova
+     *
+     * @return object
+     */
+    getOriginalHandlers: function () {
+        return { 'document': { 'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener },
+            'window': { 'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener } };
+    },
+    /**
+     * Method to fire event from native code
+     * bNoDetach is required for events which cause an exception which needs to be caught in native code
+     */
+    fireDocumentEvent: function (type, data, bNoDetach) {
+        var evt = createEvent(type, data);
+        if (typeof documentEventHandlers[type] !== 'undefined') {
+            if (bNoDetach) {
+                documentEventHandlers[type].fire(evt);
+            } else {
+                setTimeout(function () {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type === 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
+            }
+        } else {
+            document.dispatchEvent(evt);
+        }
+    },
+    fireWindowEvent: function (type, data) {
+        var evt = createEvent(type, data);
+        if (typeof windowEventHandlers[type] !== 'undefined') {
+            setTimeout(function () {
+                windowEventHandlers[type].fire(evt);
+            }, 0);
+        } else {
+            window.dispatchEvent(evt);
+        }
+    },
+
+    /**
+     * Plugin callback mechanism.
+     */
+    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
+    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
+    callbackId: Math.floor(Math.random() * 2000000000),
+    callbacks: {},
+    callbackStatus: {
+        NO_RESULT: 0,
+        OK: 1,
+        CLASS_NOT_FOUND_EXCEPTION: 2,
+        ILLEGAL_ACCESS_EXCEPTION: 3,
+        INSTANTIATION_EXCEPTION: 4,
+        MALFORMED_URL_EXCEPTION: 5,
+        IO_EXCEPTION: 6,
+        INVALID_ACTION: 7,
+        JSON_EXCEPTION: 8,
+        ERROR: 9
+    },
+
+    /**
+     * Called by native code when returning successful result from an action.
+     */
+    callbackSuccess: function (callbackId, args) {
+        cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning error result from an action.
+     */
+    callbackError: function (callbackId, args) {
+        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
+        // Derive success from status.
+        cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
+    },
+
+    /**
+     * Called by native code when returning the result from an action.
+     */
+    callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
+        try {
+            var callback = cordova.callbacks[callbackId];
+            if (callback) {
+                if (isSuccess && status === cordova.callbackStatus.OK) {
+                    callback.success && callback.success.apply(null, args);
+                } else if (!isSuccess) {
+                    callback.fail && callback.fail.apply(null, args);
+                }
+                /*
+                else
+                    Note, this case is intentionally not caught.
+                    this can happen if isSuccess is true, but callbackStatus is NO_RESULT
+                    which is used to remove a callback from the list without calling the callbacks
+                    typically keepCallback is false in this case
+                */
+                // Clear callback if not expecting any more results
+                if (!keepCallback) {
+                    delete cordova.callbacks[callbackId];
+                }
+            }
+        } catch (err) {
+            var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
+            console && console.log && console.log(msg);
+            console && console.log && err.stack && console.log(err.stack);
+            cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
+            throw err;
+        }
+    },
+    addConstructor: function (func) {
+        channel.onCordovaReady.subscribe(function () {
+            try {
+                func();
+            } catch (e) {
+                console.log('Failed to run constructor: ' + e);
+            }
+        });
+    }
+};
+
+module.exports = cordova;
+
+});
+
+// file: src/common/argscheck.js
+define("cordova/argscheck", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+var moduleExports = module.exports;
+
+var typeMap = {
+    'A': 'Array',
+    'D': 'Date',
+    'N': 'Number',
+    'S': 'String',
+    'F': 'Function',
+    'O': 'Object'
+};
+
+function extractParamName (callee, argIndex) {
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+}
+
+function checkArgs (spec, functionName, args, opt_callee) {
+    if (!moduleExports.enableChecks) {
+        return;
+    }
+    var errMsg = null;
+    var typeName;
+    for (var i = 0; i < spec.length; ++i) {
+        var c = spec.charAt(i);
+        var cUpper = c.toUpperCase();
+        var arg = args[i];
+        // Asterix means allow anything.
+        if (c === '*') {
+            continue;
+        }
+        typeName = utils.typeName(arg);
+        if ((arg === null || arg === undefined) && c === cUpper) {
+            continue;
+        }
+        if (typeName !== typeMap[cUpper]) {
+            errMsg = 'Expected ' + typeMap[cUpper];
+            break;
+        }
+    }
+    if (errMsg) {
+        errMsg += ', but got ' + typeName + '.';
+        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
+        // Don't log when running unit tests.
+        if (typeof jasmine === 'undefined') {
+            console.error(errMsg);
+        }
+        throw TypeError(errMsg);
+    }
+}
+
+function getValue (value, defaultValue) {
+    return value === undefined ? defaultValue : value;
+}
+
+moduleExports.checkArgs = checkArgs;
+moduleExports.getValue = getValue;
+moduleExports.enableChecks = true;
+
+});
+
+// file: src/common/base64.js
+define("cordova/base64", function(require, exports, module) {
+
+var base64 = exports;
+
+base64.fromArrayBuffer = function (arrayBuffer) {
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function (str) {
+    var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i = 0, len = decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
+};
+
+// ------------------------------------------------------------------------------
+
+/* This code is based on the performance tests at http://jsperf.com/b64tests
+ * This 12-bit-at-a-time algorithm was the best performing version on all
+ * platforms tested.
+ */
+
+var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var b64_12bit;
+
+var b64_12bitTable = function () {
+    b64_12bit = [];
+    for (var i = 0; i < 64; i++) {
+        for (var j = 0; j < 64; j++) {
+            b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
+        }
+    }
+    b64_12bitTable = function () { return b64_12bit; };
+    return b64_12bit;
+};
+
+function uint8ToBase64 (rawData) {
+    var numBytes = rawData.byteLength;
+    var output = '';
+    var segment;
+    var table = b64_12bitTable();
+    for (var i = 0; i < numBytes - 2; i += 3) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
+        output += table[segment >> 12];
+        output += table[segment & 0xfff];
+    }
+    if (numBytes - i === 2) {
+        segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
+        output += table[segment >> 12];
+        output += b64_6bit[(segment & 0xfff) >> 6];
+        output += '=';
+    } else if (numBytes - i === 1) {
+        segment = (rawData[i] << 16);
+        output += table[segment >> 12];
+        output += '==';
+    }
+    return output;
+}
+
+});
+
+// file: src/common/builder.js
+define("cordova/builder", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+
+function each (objects, func, context) {
+    for (var prop in objects) {
+        if (objects.hasOwnProperty(prop)) {
+            func.apply(context, [objects[prop], prop]);
+        }
+    }
+}
+
+function clobber (obj, key, value) {
+    exports.replaceHookForTesting(obj, key);
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
+    // Getters can only be overridden by getters.
+    if (needsProperty || obj[key] !== value) {
+        utils.defineGetter(obj, key, function () {
+            return value;
+        });
+    }
+}
+
+function assignOrWrapInDeprecateGetter (obj, key, value, message) {
+    if (message) {
+        utils.defineGetter(obj, key, function () {
+            console.log(message);
+            delete obj[key];
+            clobber(obj, key, value);
+            return value;
+        });
+    } else {
+        clobber(obj, key, value);
+    }
+}
+
+function include (parent, objects, clobber, merge) {
+    each(objects, function (obj, key) {
+        try {
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
+            } else {
+                // Overwrite if not currently defined.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
+            }
+
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
+        } catch (e) {
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
+        }
+    });
+}
+
+/**
+ * Merge properties from one object onto another recursively.  Properties from
+ * the src object will overwrite existing target property.
+ *
+ * @param target Object to merge properties into.
+ * @param src Object to merge properties from.
+ */
+function recursiveMerge (target, src) {
+    for (var prop in src) {
+        if (src.hasOwnProperty(prop)) {
+            if (target.prototype && target.prototype.constructor === target) {
+                // If the target object is a constructor override off prototype.
+                clobber(target.prototype, prop, src[prop]);
+            } else {
+                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
+                    recursiveMerge(target[prop], src[prop]);
+                } else {
+                    clobber(target, prop, src[prop]);
+                }
+            }
+        }
+    }
+}
+
+exports.buildIntoButDoNotClobber = function (objects, target) {
+    include(target, objects, false, false);
+};
+exports.buildIntoAndClobber = function (objects, target) {
+    include(target, objects, true, false);
+};
+exports.buildIntoAndMerge = function (objects, target) {
+    include(target, objects, true, true);
+};
+exports.recursiveMerge = recursiveMerge;
+exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
+exports.replaceHookForTesting = function () {};
+
+});
+
+// file: src/common/channel.js
+define("cordova/channel", function(require, exports, module) {
+
+var utils = require('cordova/utils');
+var nextGuid = 1;
+
+/**
+ * Custom pub-sub "channel" that can have functions subscribed to it
+ * This object is used to define and control firing of events for
+ * cordova initialization, as well as for custom events thereafter.
+ *
+ * The order of events during page load and Cordova startup is as follows:
+ *
+ * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
+ * onNativeReady*              Internal event that indicates the Cordova native side is ready.
+ * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
+ * onDeviceReady*              User event fired to indicate that Cordova is ready
+ * onResume                    User event fired to indicate a start/resume lifecycle event
+ * onPause                     User event fired to indicate a pause lifecycle event
+ *
+ * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
+ * All listeners that subscribe after the event is fired will be executed right away.
+ *
+ * The only Cordova events that user code should register for are:
+ *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
+ *      pause                 App has moved to background
+ *      resume                App has returned to foreground
+ *
+ * Listeners can be registered as:
+ *      document.addEventListener("deviceready", myDeviceReadyListener, false);
+ *      document.addEventListener("resume", myResumeListener, false);
+ *      document.addEventListener("pause", myPauseListener, false);
+ *
+ * The DOM lifecycle events should be used for saving and restoring state
+ *      window.onload
+ *      window.onunload
+ *
+ */
+
+/**
+ * Channel
+ * @constructor
+ * @param type  String the channel name
+ */
+var Channel = function (type, sticky) {
+    this.type = type;
+    // Map of guid -> function.
+    this.handlers = {};
+    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
+    this.state = sticky ? 1 : 0;
+    // Used in sticky mode to remember args passed to fire().
+    this.fireArgs = null;
+    // Used by onHasSubscribersChange to know if there are any listeners.
+    this.numHandlers = 0;
+    // Function that is called when the first listener is subscribed, or when
+    // the last listener is unsubscribed.
+    this.onHasSubscribersChange = null;
+};
+var channel = {
+    /**
+     * Calls the provided function only after all of the channels specified
+     * have been fired. All channels must be sticky channels.
+     */
+    join: function (h, c) {
+        var len = c.length;
+        var i = len;
+        var f = function () {
+            if (!(--i)) h();
+        };
+        for (var j = 0; j < len; j++) {
+            if (c[j].state === 0) {
+                throw Error('Can only use join with sticky channels.');
+            }
+            c[j].subscribe(f);
+        }
+        if (!len) h();
+    },
+    /* eslint-disable no-return-assign */
+    create: function (type) {
+        return channel[type] = new Channel(type, false);
+    },
+    createSticky: function (type) {
+        return channel[type] = new Channel(type, true);
+    },
+    /* eslint-enable no-return-assign */
+    /**
+     * cordova Channels that must fire before "deviceready" is fired.
+     */
+    deviceReadyChannelsArray: [],
+    deviceReadyChannelsMap: {},
+
+    /**
+     * Indicate that a feature needs to be initialized before it is ready to be used.
+     * This holds up Cordova's "deviceready" event until the feature has been initialized
+     * and Cordova.initComplete(feature) is called.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    waitForInitialization: function (feature) {
+        if (feature) {
+            var c = channel[feature] || this.createSticky(feature);
+            this.deviceReadyChannelsMap[feature] = c;
+            this.deviceReadyChannelsArray.push(c);
+        }
+    },
+
+    /**
+     * Indicate that initialization code has completed and the feature is ready to be used.
+     *
+     * @param feature {String}     The unique feature name
+     */
+    initializationComplete: function (feature) {
+        var c = this.deviceReadyChannelsMap[feature];
+        if (c) {
+            c.fire();
+        }
+    }
+};
+
+function checkSubscriptionArgument (argument) {
+    if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
+        throw new Error(
+            'Must provide a function or an EventListener object ' +
+                'implementing the handleEvent interface.'
+        );
+    }
+}
+
+/**
+ * Subscribes the given function to the channel. Any time that
+ * Channel.fire is called so too will the function.
+ * Optionally specify an execution context for the function
+ * and a guid that can be used to stop subscribing to the channel.
+ * Returns the guid.
+ */
+Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+        eventListener = eventListenerOrFunction;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    if (this.state === 2) {
+        handleEvent.apply(eventListener || this, this.fireArgs);
+        return;
+    }
+
+    guid = eventListenerOrFunction.observer_guid;
+    if (typeof eventListener === 'object') {
+        handleEvent = utils.close(eventListener, handleEvent);
+    }
+
+    if (!guid) {
+        // First time any channel has seen this subscriber
+        guid = '' + nextGuid++;
+    }
+    handleEvent.observer_guid = guid;
+    eventListenerOrFunction.observer_guid = guid;
+
+    // Don't add the same handler more than once.
+    if (!this.handlers[guid]) {
+        this.handlers[guid] = handleEvent;
+        this.numHandlers++;
+        if (this.numHandlers === 1) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Unsubscribes the function with the given guid from the channel.
+ */
+Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
+    checkSubscriptionArgument(eventListenerOrFunction);
+    var handleEvent, guid, handler;
+
+    if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
+        // Received an EventListener object implementing the handleEvent interface
+        handleEvent = eventListenerOrFunction.handleEvent;
+    } else {
+        // Received a function to handle event
+        handleEvent = eventListenerOrFunction;
+    }
+
+    guid = handleEvent.observer_guid;
+    handler = this.handlers[guid];
+    if (handler) {
+        delete this.handlers[guid];
+        this.numHandlers--;
+        if (this.numHandlers === 0) {
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+/**
+ * Calls all functions subscribed to this channel.
+ */
+Channel.prototype.fire = function (e) {
+    var fail = false; // eslint-disable-line no-unused-vars
+    var fireArgs = Array.prototype.slice.call(arguments);
+    // Apply stickiness.
+    if (this.state === 1) {
+        this.state = 2;
+        this.fireArgs = fireArgs;
+    }
+    if (this.numHandlers) {
+        // Copy the values first so that it is safe to modify it from within
+        // callbacks.
+        var toCall = [];
+        for (var item in this.handlers) {
+            toCall.push(this.handlers[item]);
+        }
+        for (var i = 0; i < toCall.length; ++i) {
+            toCall[i].apply(this, fireArgs);
+        }
+        if (this.state === 2 && this.numHandlers) {
+            this.numHandlers = 0;
+            this.handlers = {};
+            this.onHasSubscribersChange && this.onHasSubscribersChange();
+        }
+    }
+};
+
+// defining them here so they are ready super fast!
+// DOM event that is received when the web page is loaded and parsed.
+channel.createSticky('onDOMContentLoaded');
+
+// Event to indicate the Cordova native side is ready.
+channel.createSticky('onNativeReady');
+
+// Event to indicate that all Cordova JavaScript objects have been created
+// and it's time to run plugin constructors.
+channel.createSticky('onCordovaReady');
+
+// Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
+channel.createSticky('onPluginsReady');
+
+// Event to indicate that Cordova is ready
+channel.createSticky('onDeviceReady');
+
+// Event to indicate a resume lifecycle event
+channel.create('onResume');
+
+// Event to indicate a pause lifecycle event
+channel.create('onPause');
+
+// Channels that must fire before "deviceready" is fired.
+channel.waitForInitialization('onCordovaReady');
+channel.waitForInitialization('onDOMContentLoaded');
+
+module.exports = channel;
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/exec.js
+define("cordova/exec", function(require, exports, module) {
+
+/*global require, module, atob, document */
+
+/**
+ * Creates a gap bridge iframe used to notify the native code about queued
+ * commands.
+ */
+var cordova = require('cordova'),
+    utils = require('cordova/utils'),
+    base64 = require('cordova/base64'),
+    execIframe,
+    commandQueue = [], // Contains pending JS->Native messages.
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
+
+function massageArgsJsToNative(args) {
+    if (!args || utils.typeName(args) != 'Array') {
+        return args;
+    }
+    var ret = [];
+    args.forEach(function(arg, i) {
+        if (utils.typeName(arg) == 'ArrayBuffer') {
+            ret.push({
+                'CDVType': 'ArrayBuffer',
+                'data': base64.fromArrayBuffer(arg)
+            });
+        } else {
+            ret.push(arg);
+        }
+    });
+    return ret;
+}
+
+function massageMessageNativeToJs(message) {
+    if (message.CDVType == 'ArrayBuffer') {
+        var stringToArrayBuffer = function(str) {
+            var ret = new Uint8Array(str.length);
+            for (var i = 0; i < str.length; i++) {
+                ret[i] = str.charCodeAt(i);
+            }
+            return ret.buffer;
+        };
+        var base64ToArrayBuffer = function(b64) {
+            return stringToArrayBuffer(atob(b64));
+        };
+        message = base64ToArrayBuffer(message.data);
+    }
+    return message;
+}
+
+function convertMessageToArgsNativeToJs(message) {
+    var args = [];
+    if (!message || !message.hasOwnProperty('CDVType')) {
+        args.push(message);
+    } else if (message.CDVType == 'MultiPart') {
+        message.messages.forEach(function(e) {
+            args.push(massageMessageNativeToJs(e));
+        });
+    } else {
+        args.push(massageMessageNativeToJs(message));
+    }
+    return args;
+}
+
+function iOSExec() {
+
+    var successCallback, failCallback, service, action, actionArgs;
+    var callbackId = null;
+    if (typeof arguments[0] !== 'string') {
+        // FORMAT ONE
+        successCallback = arguments[0];
+        failCallback = arguments[1];
+        service = arguments[2];
+        action = arguments[3];
+        actionArgs = arguments[4];
+
+        // Since we need to maintain backwards compatibility, we have to pass
+        // an invalid callbackId even if no callback was provided since plugins
+        // will be expecting it. The Cordova.exec() implementation allocates
+        // an invalid callbackId and passes it even if no callbacks were given.
+        callbackId = 'INVALID';
+    } else {
+        throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
+            'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
+        );
+    }
+
+    // If actionArgs is not provided, default to an empty array
+    actionArgs = actionArgs || [];
+
+    // Register the callbacks and add the callbackId to the positional
+    // arguments if given.
+    if (successCallback || failCallback) {
+        callbackId = service + cordova.callbackId++;
+        cordova.callbacks[callbackId] =
+            {success:successCallback, fail:failCallback};
+    }
+
+    actionArgs = massageArgsJsToNative(actionArgs);
+
+    var command = [callbackId, service, action, actionArgs];
+
+    // Stringify and queue the command. We stringify to command now to
+    // effectively clone the command arguments in case they are mutated before
+    // the command is executed.
+    commandQueue.push(JSON.stringify(command));
+
+    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
+    // then the queue will be flushed when it returns; no need for a poke.
+    // Also, if there is already a command in the queue, then we've already
+    // poked the native side, so there is no reason to do so again.
+    if (!isInContextOfEvalJs && commandQueue.length == 1) {
+        pokeNative();
+    }
+}
+
+// CB-10530
+function proxyChanged() {
+    var cexec = cordovaExec();
+       
+    return (execProxy !== cexec && // proxy objects are different
+            iOSExec !== cexec      // proxy object is not the current iOSExec
+            );
+}
+
+// CB-10106
+function handleBridgeChange() {
+    if (proxyChanged()) {
+        var commandString = commandQueue.shift();
+        while(commandString) {
+            var command = JSON.parse(commandString);
+            var callbackId = command[0];
+            var service = command[1];
+            var action = command[2];
+            var actionArgs = command[3];
+            var callbacks = cordova.callbacks[callbackId] || {};
+            
+            execProxy(callbacks.success, callbacks.fail, service, action, actionArgs);
+            
+            commandString = commandQueue.shift();
+        };
+        return true;
+    }
+    
+    return false;
+}
+
+function pokeNative() {
+    // CB-5488 - Don't attempt to create iframe before document.body is available.
+    if (!document.body) {
+        setTimeout(pokeNative);
+        return;
+    }
+    
+    // Check if they've removed it from the DOM, and put it back if so.
+    if (execIframe && execIframe.contentWindow) {
+        execIframe.contentWindow.location = 'gap://ready';
+    } else {
+        execIframe = document.createElement('iframe');
+        execIframe.style.display = 'none';
+        execIframe.src = 'gap://ready';
+        document.body.appendChild(execIframe);
+    }
+    // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+    // This makes the bridge ~ 7% slower, but works around the poke getting lost
+    // when the iframe is removed from the DOM.
+    // An onunload listener could be used in the case where the iframe has just been
+    // created, but since unload events fire only once, it doesn't work in the normal
+    // case of iframe reuse (where unload will have already fired due to the attempted
+    // navigation of the page).
+    failSafeTimerId = setTimeout(function() {
+        if (commandQueue.length) {
+            // CB-10106 - flush the queue on bridge change
+            if (!handleBridgeChange()) {
+                pokeNative();
+             }
+        }
+    }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
+}
+
+iOSExec.nativeFetchMessages = function() {
+    // Stop listing for window detatch once native side confirms poke.
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
+    }
+    // Each entry in commandQueue is a JSON string already.
+    if (!commandQueue.length) {
+        return '';
+    }
+    var json = '[' + commandQueue.join(',') + ']';
+    commandQueue.length = 0;
+    return json;
+};
+
+iOSExec.nativeCallback = function(callbackId, status, message, keepCallback, debug) {
+    return iOSExec.nativeEvalAndFetch(function() {
+        var success = status === 0 || status === 1;
+        var args = convertMessageToArgsNativeToJs(message);
+        function nc2() {
+            cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
+        }
+        setTimeout(nc2, 0);
+    });
+};
+
+iOSExec.nativeEvalAndFetch = function(func) {
+    // This shouldn't be nested, but better to be safe.
+    isInContextOfEvalJs++;
+    try {
+        func();
+        return iOSExec.nativeFetchMessages();
+    } finally {
+        isInContextOfEvalJs--;
+    }
+};
+
+// Proxy the exec for bridge changes. See CB-10106
+
+function cordovaExec() {
+    var cexec = require('cordova/exec');
+    var cexec_valid = (typeof cexec.nativeFetchMessages === 'function') && (typeof cexec.nativeEvalAndFetch === 'function') && (typeof cexec.nativeCallback === 'function');
+    return (cexec_valid && execProxy !== cexec)? cexec : iOSExec;
+}
+
+function execProxy() {
+    cordovaExec().apply(null, arguments);
+};
+
+execProxy.nativeFetchMessages = function() {
+    return cordovaExec().nativeFetchMessages.apply(null, arguments);
+};
+
+execProxy.nativeEvalAndFetch = function() {
+    return cordovaExec().nativeEvalAndFetch.apply(null, arguments);
+};
+
+execProxy.nativeCallback = function() {
+    return cordovaExec().nativeCallback.apply(null, arguments);
+};
+
+module.exports = execProxy;
+
+});
+
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add: function (id, proxyObj) {
+        console.log('adding proxy for ' + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove: function (id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get: function (service, action) {
+        return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
+    }
+};
+
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+var utils = require('cordova/utils');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels (arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state !== 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function () {
+    if (channel.onDeviceReady.state !== 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator (origNavigator) {
+    var CordovaNavigator = function () {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] === 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            } else {
+                (function (k) {
+                    utils.defineGetterSetter(newNavigator, key, function () {
+                        return origNavigator[k];
+                    });
+                })(key);
+            }
+        }
+    }
+    return newNavigator;
+}
+
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function () {}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function (msg) {
+        this.log('warn: ' + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onActivated = cordova.addDocumentEventHandler('activated');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function () {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function () {
+    pluginloader.load(function () {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function () {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function () {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
+define("cordova/modulemapper", function(require, exports, module) {
+
+var builder = require('cordova/builder');
+var moduleMap = define.moduleMap; // eslint-disable-line no-undef
+var symbolList;
+var deprecationMap;
+
+exports.reset = function () {
+    symbolList = [];
+    deprecationMap = {};
+};
+
+function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
+    if (!(moduleName in moduleMap)) {
+        throw new Error('Module ' + moduleName + ' does not exist.');
+    }
+    symbolList.push(strategy, moduleName, symbolPath);
+    if (opt_deprecationMessage) {
+        deprecationMap[symbolPath] = opt_deprecationMessage;
+    }
+}
+
+// Note: Android 2.3 does have Function.bind().
+exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
+    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
+};
+
+exports.runs = function (moduleName) {
+    addEntry('r', moduleName, null);
+};
+
+function prepareNamespace (symbolPath, context) {
+    if (!symbolPath) {
+        return context;
+    }
+    var parts = symbolPath.split('.');
+    var cur = context;
+    for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
+        cur = cur[part] = cur[part] || {};
+    }
+    return cur;
+}
+
+exports.mapModules = function (context) {
+    var origSymbols = {};
+    context.CDV_origSymbols = origSymbols;
+    for (var i = 0, len = symbolList.length; i < len; i += 3) {
+        var strategy = symbolList[i];
+        var moduleName = symbolList[i + 1];
+        var module = require(moduleName);
+        // <runs/>
+        if (strategy === 'r') {
+            continue;
+        }
+        var symbolPath = symbolList[i + 2];
+        var lastDot = symbolPath.lastIndexOf('.');
+        var namespace = symbolPath.substr(0, lastDot);
+        var lastName = symbolPath.substr(lastDot + 1);
+
+        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
+        var parentObj = prepareNamespace(namespace, context);
+        var target = parentObj[lastName];
+
+        if (strategy === 'm' && target) {
+            builder.recursiveMerge(target, module);
+        } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
+            if (!(symbolPath in origSymbols)) {
+                origSymbols[symbolPath] = target;
+            }
+            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
+        }
+    }
+};
+
+exports.getOriginalSymbol = function (context, symbolPath) {
+    var origSymbols = context.CDV_origSymbols;
+    if (origSymbols && (symbolPath in origSymbols)) {
+        return origSymbols[symbolPath];
+    }
+    var parts = symbolPath.split('.');
+    var obj = context;
+    for (var i = 0; i < parts.length; ++i) {
+        obj = obj && obj[parts[i]];
+    }
+    return obj;
+};
+
+exports.reset();
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/platform.js
+define("cordova/platform", function(require, exports, module) {
+
+module.exports = {
+    id: 'ios',
+    bootstrap: function () {
+        // Attach the console polyfill that is iOS-only to window.console
+        // see the file under plugin/ios/console.js
+        require('cordova/modulemapper').clobbers('cordova/plugin/ios/console', 'window.console');
+
+        require('cordova/channel').onNativeReady.fire();
+    }
+};
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/console.js
+define("cordova/plugin/ios/console", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+
+var logger = require('cordova/plugin/ios/logger');
+
+//------------------------------------------------------------------------------
+// object that we're exporting
+//------------------------------------------------------------------------------
+var console = module.exports;
+
+//------------------------------------------------------------------------------
+// copy of the original console object
+//------------------------------------------------------------------------------
+var WinConsole = window.console;
+
+//------------------------------------------------------------------------------
+// whether to use the logger
+//------------------------------------------------------------------------------
+var UseLogger = false;
+
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+var Timers = {};
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+function noop() {}
+
+//------------------------------------------------------------------------------
+// used for unimplemented methods
+//------------------------------------------------------------------------------
+console.useLogger = function (value) {
+    if (arguments.length) UseLogger = !!value;
+
+    if (UseLogger) {
+        if (logger.useConsole()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+    }
+
+    return UseLogger;
+};
+
+//------------------------------------------------------------------------------
+console.log = function() {
+    if (logger.useConsole()) return;
+    logger.log.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.error = function() {
+    if (logger.useConsole()) return;
+    logger.error.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.warn = function() {
+    if (logger.useConsole()) return;
+    logger.warn.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.info = function() {
+    if (logger.useConsole()) return;
+    logger.info.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.debug = function() {
+    if (logger.useConsole()) return;
+    logger.debug.apply(logger, [].slice.call(arguments));
+};
+
+//------------------------------------------------------------------------------
+console.assert = function(expression) {
+    if (expression) return;
+
+    var message = logger.format.apply(logger.format, [].slice.call(arguments, 1));
+    console.log("ASSERT: " + message);
+};
+
+//------------------------------------------------------------------------------
+console.clear = function() {};
+
+//------------------------------------------------------------------------------
+console.dir = function(object) {
+    console.log("%o", object);
+};
+
+//------------------------------------------------------------------------------
+console.dirxml = function(node) {
+    console.log(node.innerHTML);
+};
+
+//------------------------------------------------------------------------------
+console.trace = noop;
+
+//------------------------------------------------------------------------------
+console.group = console.log;
+
+//------------------------------------------------------------------------------
+console.groupCollapsed = console.log;
+
+//------------------------------------------------------------------------------
+console.groupEnd = noop;
+
+//------------------------------------------------------------------------------
+console.time = function(name) {
+    Timers[name] = new Date().valueOf();
+};
+
+//------------------------------------------------------------------------------
+console.timeEnd = function(name) {
+    var timeStart = Timers[name];
+    if (!timeStart) {
+        console.warn("unknown timer: " + name);
+        return;
+    }
+
+    var timeElapsed = new Date().valueOf() - timeStart;
+    console.log(name + ": " + timeElapsed + "ms");
+};
+
+//------------------------------------------------------------------------------
+console.timeStamp = noop;
+
+//------------------------------------------------------------------------------
+console.profile = noop;
+
+//------------------------------------------------------------------------------
+console.profileEnd = noop;
+
+//------------------------------------------------------------------------------
+console.count = noop;
+
+//------------------------------------------------------------------------------
+console.exception = console.log;
+
+//------------------------------------------------------------------------------
+console.table = function(data, columns) {
+    console.log("%o", data);
+};
+
+//------------------------------------------------------------------------------
+// return a new function that calls both functions passed as args
+//------------------------------------------------------------------------------
+function wrappedOrigCall(orgFunc, newFunc) {
+    return function() {
+        var args = [].slice.call(arguments);
+        try { orgFunc.apply(WinConsole, args); } catch (e) {}
+        try { newFunc.apply(console,    args); } catch (e) {}
+    };
+}
+
+//------------------------------------------------------------------------------
+// For every function that exists in the original console object, that
+// also exists in the new console object, wrap the new console method
+// with one that calls both
+//------------------------------------------------------------------------------
+for (var key in console) {
+    if (typeof WinConsole[key] == "function") {
+        console[key] = wrappedOrigCall(WinConsole[key], console[key]);
+    }
+}
+
+});
+
+// file: /Users/dpogue/Coding/cordova-ios/cordova-js-src/plugin/ios/logger.js
+define("cordova/plugin/ios/logger", function(require, exports, module) {
+
+//------------------------------------------------------------------------------
+// The logger module exports the following properties/functions:
+//
+// LOG                          - constant for the level LOG
+// ERROR                        - constant for the level ERROR
+// WARN                         - constant for the level WARN
+// INFO                         - constant for the level INFO
+// DEBUG                        - constant for the level DEBUG
+// logLevel()                   - returns current log level
+// logLevel(value)              - sets and returns a new log level
+// useConsole()                 - returns whether logger is using console
+// useConsole(value)            - sets and returns whether logger is using console
+// log(message,...)             - logs a message at level LOG
+// error(message,...)           - logs a message at level ERROR
+// warn(message,...)            - logs a message at level WARN
+// info(message,...)            - logs a message at level INFO
+// debug(message,...)           - logs a message at level DEBUG
+// logLevel(level,message,...)  - logs a message specified level
+//
+//------------------------------------------------------------------------------
+
+var logger = exports;
+
+var exec    = require('cordova/exec');
+
+var UseConsole   = false;
+var UseLogger    = true;
+var Queued       = [];
+var DeviceReady  = false;
+var CurrentLevel;
+
+var originalConsole = console;
+
+/**
+ * Logging levels
+ */
+
+var Levels = [
+    "LOG",
+    "ERROR",
+    "WARN",
+    "INFO",
+    "DEBUG"
+];
+
+/*
+ * add the logging levels to the logger object and
+ * to a separate levelsMap object for testing
+ */
+
+var LevelsMap = {};
+for (var i=0; i<Levels.length; i++) {
+    var level = Levels[i];
+    LevelsMap[level] = i;
+    logger[level]    = level;
+}
+
+CurrentLevel = LevelsMap.WARN;
+
+/**
+ * Getter/Setter for the logging level
+ *
+ * Returns the current logging level.
+ *
+ * When a value is passed, sets the logging level to that value.
+ * The values should be one of the following constants:
+ *    logger.LOG
+ *    logger.ERROR
+ *    logger.WARN
+ *    logger.INFO
+ *    logger.DEBUG
+ *
+ * The value used determines which messages get printed.  The logging
+ * values above are in order, and only messages logged at the logging
+ * level or above will actually be displayed to the user.  E.g., the
+ * default level is WARN, so only messages logged with LOG, ERROR, or
+ * WARN will be displayed; INFO and DEBUG messages will be ignored.
+ */
+logger.level = function (value) {
+    if (arguments.length) {
+        if (LevelsMap[value] === null) {
+            throw new Error("invalid logging level: " + value);
+        }
+        CurrentLevel = LevelsMap[value];
+    }
+
+    return Levels[CurrentLevel];
+};
+
+/**
+ * Getter/Setter for the useConsole functionality
+ *
+ * When useConsole is true, the logger will log via the
+ * browser 'console' object.
+ */
+logger.useConsole = function (value) {
+    if (arguments.length) UseConsole = !!value;
+
+    if (UseConsole) {
+        if (typeof console == "undefined") {
+            throw new Error("global console object is not defined");
+        }
+
+        if (typeof console.log != "function") {
+            throw new Error("global console object does not have a log function");
+        }
+
+        if (typeof console.useLogger == "function") {
+            if (console.useLogger()) {
+                throw new Error("console and logger are too intertwingly");
+            }
+        }
+    }
+
+    return UseConsole;
+};
+
+/**
+ * Getter/Setter for the useLogger functionality
+ *
+ * When useLogger is true, the logger will log via the
+ * native Logger plugin.
+ */
+logger.useLogger = function (value) {
+    // Enforce boolean
+    if (arguments.length) UseLogger = !!value;
+    return UseLogger;
+};
+
+/**
+ * Logs a message at the LOG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.log   = function(message) { logWithArgs("LOG",   arguments); };
+
+/**
+ * Logs a message at the ERROR level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.error = function(message) { logWithArgs("ERROR", arguments); };
+
+/**
+ * Logs a message at the WARN level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.warn  = function(message) { logWithArgs("WARN",  arguments); };
+
+/**
+ * Logs a message at the INFO level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.info  = function(message) { logWithArgs("INFO",  arguments); };
+
+/**
+ * Logs a message at the DEBUG level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.debug = function(message) { logWithArgs("DEBUG", arguments); };
+
+// log at the specified level with args
+function logWithArgs(level, args) {
+    args = [level].concat([].slice.call(args));
+    logger.logLevel.apply(logger, args);
+}
+
+// return the correct formatString for an object
+function formatStringForMessage(message) {
+    return (typeof message === "string") ? "" : "%o"; 
+}
+
+/**
+ * Logs a message at the specified level.
+ *
+ * Parameters passed after message are used applied to
+ * the message with utils.format()
+ */
+logger.logLevel = function(level /* , ... */) {
+    // format the message with the parameters
+    var formatArgs = [].slice.call(arguments, 1);
+    var fmtString = formatStringForMessage(formatArgs[0]);
+    if (fmtString.length > 0){
+        formatArgs.unshift(fmtString); // add formatString
+    }
+
+    var message    = logger.format.apply(logger.format, formatArgs);
+
+    if (LevelsMap[level] === null) {
+        throw new Error("invalid logging level: " + level);
+    }
+
+    if (LevelsMap[level] > CurrentLevel) return;
+
+    // queue the message if not yet at deviceready
+    if (!DeviceReady && !UseConsole) {
+        Queued.push([level, message]);
+        return;
+    }
+
+    // Log using the native logger if that is enabled
+    if (UseLogger) {
+        exec(null, null, "Console", "logLevel", [level, message]);
+    }
+
+    // Log using the console if that is enabled
+    if (UseConsole) {
+        // make sure console is not using logger
+        if (console.useLogger()) {
+            throw new Error("console and logger are too intertwingly");
+        }
+
+        // log to the console
+        switch (level) {
+            case logger.LOG:   originalConsole.log(message); break;
+            case logger.ERROR: originalConsole.log("ERROR: " + message); break;
+            case logger.WARN:  originalConsole.log("WARN: "  + message); break;
+            case logger.INFO:  originalConsole.log("INFO: "  + message); break;
+            case logger.DEBUG: originalConsole.log("DEBUG: " + message); break;
+        }
+    }
+};
+
+
+/**
+ * Formats a string and arguments following it ala console.log()
+ *
+ * Any remaining arguments will be appended to the formatted string.
+ *
+ * for rationale, see FireBug's Console API:
+ *    http://getfirebug.com/wiki/index.php/Console_API
+ */
+logger.format = function(formatString, args) {
+    return __format(arguments[0], [].slice.call(arguments,1)).join(' ');
+};
+
+
+//------------------------------------------------------------------------------
+/**
+ * Formats a string and arguments following it ala vsprintf()
+ *
+ * format chars:
+ *   %j - format arg as JSON
+ *   %o - format arg as JSON
+ *   %c - format arg as ''
+ *   %% - replace with '%'
+ * any other char following % will format it's
+ * arg via toString().
+ *
+ * Returns an array containing the formatted string and any remaining
+ * arguments.
+ */
+function __format(formatString, args) {
+    if (formatString === null || formatString === undefined) return [""];
+    if (arguments.length == 1) return [formatString.toString()];
+
+    if (typeof formatString != "string")
+        formatString = formatString.toString();
+
+    var pattern = /(.*?)%(.)(.*)/;
+    var rest    = formatString;
+    var result  = [];
+
+    while (args.length) {
+        var match = pattern.exec(rest);
+        if (!match) break;
+
+        var arg   = args.shift();
+        rest = match[3];
+        result.push(match[1]);
+
+        if (match[2] == '%') {
+            result.push('%');
+            args.unshift(arg);
+            continue;
+        }
+
+        result.push(__formatted(arg, match[2]));
+    }
+
+    result.push(rest);
+
+    var remainingArgs = [].slice.call(args);
+    remainingArgs.unshift(result.join(''));
+    return remainingArgs;
+}
+
+function __formatted(object, formatChar) {
+
+    try {
+        switch(formatChar) {
+            case 'j':
+            case 'o': return JSON.stringify(object);
+            case 'c': return '';
+        }
+    }
+    catch (e) {
+        return "error JSON.stringify()ing argument: " + e;
+    }
+
+    if ((object === null) || (object === undefined)) {
+        return Object.prototype.toString.call(object);
+    }
+
+    return object.toString();
+}
+
+
+//------------------------------------------------------------------------------
+// when deviceready fires, log queued messages
+logger.__onDeviceReady = function() {
+    if (DeviceReady) return;
+
+    DeviceReady = true;
+
+    for (var i=0; i<Queued.length; i++) {
+        var messageArgs = Queued[i];
+        logger.logLevel(messageArgs[0], messageArgs[1]);
+    }
+
+    Queued = null;
+};
+
+// add a deviceready event to log queued messages
+document.addEventListener("deviceready", logger.__onDeviceReady, false);
+
+});
+
+// file: src/common/pluginloader.js
+define("cordova/pluginloader", function(require, exports, module) {
+
+var modulemapper = require('cordova/modulemapper');
+
+// Helper function to inject a <script> tag.
+// Exported for testing.
+exports.injectScript = function (url, onload, onerror) {
+    var script = document.createElement('script');
+    // onload fires even when script fails loads with an error.
+    script.onload = onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
+    script.src = url;
+    document.head.appendChild(script);
+};
+
+function injectIfNecessary (id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) { // eslint-disable-line no-undef
+        onload();
+    } else {
+        exports.injectScript(url, function () {
+            if (id in define.moduleMap) { // eslint-disable-line no-undef
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
+}
+
+function onScriptLoadingComplete (moduleList, finishPluginLoading) {
+    // Loop through all the plugins and then through their clobbers and merges.
+    for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
+            }
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
+            }
+        }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
+    }
+
+    finishPluginLoading();
+}
+
+// Handler for the cordova_plugins.js content.
+// See plugman's plugin_loader.js for the details of this object.
+// This function is only called if the really is a plugins array that isn't empty.
+// Otherwise the onerror response handler will just call finishPluginLoading().
+function handlePluginsObject (path, moduleList, finishPluginLoading) {
+    // Now inject the scripts.
+    var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
+    function scriptLoadedCallback () {
+        if (!--scriptCounter) {
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
+        }
+    }
+
+    for (var i = 0; i < moduleList.length; i++) {
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
+    }
+}
+
+function findCordovaPath () {
+    var path = null;
+    var scripts = document.getElementsByTagName('script');
+    var term = '/cordova.js';
+    for (var n = scripts.length - 1; n > -1; n--) {
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
+        if (src.indexOf(term) === (src.length - term.length)) {
+            path = src.substring(0, src.length - term.length) + '/';
+            break;
+        }
+    }
+    return path;
+}
+
+// Tries to load all plugins' js-modules.
+// This is an async process, but onDeviceReady is blocked on onPluginsReady.
+// onPluginsReady is fired when there are no plugins to load, or they are all done.
+exports.load = function (callback) {
+    var pathPrefix = findCordovaPath();
+    if (pathPrefix === null) {
+        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
+        pathPrefix = '';
+    }
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function () {
+        var moduleList = require('cordova/plugin_list');
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
+};
+
+});
+
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
+
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute (url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
+});
+
+// file: src/common/utils.js
+define("cordova/utils", function(require, exports, module) {
+
+var utils = exports;
+
+/**
+ * Defines a property getter / setter for obj[key].
+ */
+utils.defineGetterSetter = function (obj, key, getFunc, opt_setFunc) {
+    if (Object.defineProperty) {
+        var desc = {
+            get: getFunc,
+            configurable: true
+        };
+        if (opt_setFunc) {
+            desc.set = opt_setFunc;
+        }
+        Object.defineProperty(obj, key, desc);
+    } else {
+        obj.__defineGetter__(key, getFunc);
+        if (opt_setFunc) {
+            obj.__defineSetter__(key, opt_setFunc);
+        }
+    }
+};
+
+/**
+ * Defines a property getter for obj[key].
+ */
+utils.defineGetter = utils.defineGetterSetter;
+
+utils.arrayIndexOf = function (a, item) {
+    if (a.indexOf) {
+        return a.indexOf(item);
+    }
+    var len = a.length;
+    for (var i = 0; i < len; ++i) {
+        if (a[i] === item) {
+            return i;
+        }
+    }
+    return -1;
+};
+
+/**
+ * Returns whether the item was found in the array.
+ */
+utils.arrayRemove = function (a, item) {
+    var index = utils.arrayIndexOf(a, item);
+    if (index !== -1) {
+        a.splice(index, 1);
+    }
+    return index !== -1;
+};
+
+utils.typeName = function (val) {
+    return Object.prototype.toString.call(val).slice(8, -1);
+};
+
+/**
+ * Returns an indication of whether the argument is an array or not
+ */
+utils.isArray = Array.isArray ||
+                function (a) { return utils.typeName(a) === 'Array'; };
+
+/**
+ * Returns an indication of whether the argument is a Date or not
+ */
+utils.isDate = function (d) {
+    return (d instanceof Date);
+};
+
+/**
+ * Does a deep clone of the object.
+ */
+utils.clone = function (obj) {
+    if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
+        return obj;
+    }
+
+    var retVal, i;
+
+    if (utils.isArray(obj)) {
+        retVal = [];
+        for (i = 0; i < obj.length; ++i) {
+            retVal.push(utils.clone(obj[i]));
+        }
+        return retVal;
+    }
+
+    retVal = {};
+    for (i in obj) {
+        // https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
+        // custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
+        // on cloning.
+        if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
+            retVal[i] = utils.clone(obj[i]);
+        }
+    }
+    return retVal;
+};
+
+/**
+ * Returns a wrapped version of the function
+ */
+utils.close = function (context, func, params) {
+    return function () {
+        var args = params || arguments;
+        return func.apply(context, args);
+    };
+};
+
+// ------------------------------------------------------------------------------
+function UUIDcreatePart (length) {
+    var uuidpart = '';
+    for (var i = 0; i < length; i++) {
+        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
+        if (uuidchar.length === 1) {
+            uuidchar = '0' + uuidchar;
+        }
+        uuidpart += uuidchar;
+    }
+    return uuidpart;
+}
+
+/**
+ * Create a UUID
+ */
+utils.createUUID = function () {
+    return UUIDcreatePart(4) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(2) + '-' +
+        UUIDcreatePart(6);
+};
+
+/**
+ * Extends a child object from a parent object using classical inheritance
+ * pattern.
+ */
+utils.extend = (function () {
+    // proxy used to establish prototype chain
+    var F = function () {};
+    // extend Child from Parent
+    return function (Child, Parent) {
+
+        F.prototype = Parent.prototype;
+        Child.prototype = new F();
+        Child.__super__ = Parent.prototype;
+        Child.prototype.constructor = Child;
+    };
+}());
+
+/**
+ * Alerts a message in any available way: alert or console.log.
+ */
+utils.alert = function (msg) {
+    if (window.alert) {
+        window.alert(msg);
+    } else if (console && console.log) {
+        console.log(msg);
+    }
+};
+
+});
+
+window.cordova = require('cordova');
+// file: src/scripts/bootstrap.js
+
+require('cordova/init');
+
+})();
\ No newline at end of file
diff --git a/platforms/ios/platform_www/cordova_plugins.js b/platforms/ios/platform_www/cordova_plugins.js
new file mode 100644
index 0000000..79df2d5
--- /dev/null
+++ b/platforms/ios/platform_www/cordova_plugins.js
@@ -0,0 +1,339 @@
+cordova.define('cordova/plugin_list', function(require, exports, module) {
+  module.exports = [
+    {
+      "id": "cordova-plugin-file.DirectoryEntry",
+      "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.DirectoryReader",
+      "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.DirectoryReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Entry",
+      "file": "plugins/cordova-plugin-file/www/Entry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Entry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.File",
+      "file": "plugins/cordova-plugin-file/www/File.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.File"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileEntry",
+      "file": "plugins/cordova-plugin-file/www/FileEntry.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileEntry"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileError",
+      "file": "plugins/cordova-plugin-file/www/FileError.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileError"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileReader",
+      "file": "plugins/cordova-plugin-file/www/FileReader.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileReader"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileSystem",
+      "file": "plugins/cordova-plugin-file/www/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadOptions",
+      "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadOptions"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileUploadResult",
+      "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileUploadResult"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.FileWriter",
+      "file": "plugins/cordova-plugin-file/www/FileWriter.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.FileWriter"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Flags",
+      "file": "plugins/cordova-plugin-file/www/Flags.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Flags"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.LocalFileSystem",
+      "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.LocalFileSystem"
+      ],
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.Metadata",
+      "file": "plugins/cordova-plugin-file/www/Metadata.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.Metadata"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.ProgressEvent",
+      "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.ProgressEvent"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems",
+      "file": "plugins/cordova-plugin-file/www/fileSystems.js",
+      "pluginId": "cordova-plugin-file"
+    },
+    {
+      "id": "cordova-plugin-file.requestFileSystem",
+      "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "clobbers": [
+        "window.requestFileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.resolveLocalFileSystemURI",
+      "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "window"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.isChrome",
+      "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.iosFileSystem",
+      "file": "plugins/cordova-plugin-file/www/ios/FileSystem.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "FileSystem"
+      ]
+    },
+    {
+      "id": "cordova-plugin-file.fileSystems-roots",
+      "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
+      "pluginId": "cordova-plugin-file",
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-file.fileSystemPaths",
+      "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
+      "pluginId": "cordova-plugin-file",
+      "merges": [
+        "cordova"
+      ],
+      "runs": true
+    },
+    {
+      "id": "cordova-plugin-advanced-http.cookie-handler",
+      "file": "plugins/cordova-plugin-advanced-http/www/cookie-handler.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.global-configs",
+      "file": "plugins/cordova-plugin-advanced-http/www/global-configs.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.helpers",
+      "file": "plugins/cordova-plugin-advanced-http/www/helpers.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.js-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/js-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.local-storage-store",
+      "file": "plugins/cordova-plugin-advanced-http/www/local-storage-store.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.lodash",
+      "file": "plugins/cordova-plugin-advanced-http/www/lodash.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.messages",
+      "file": "plugins/cordova-plugin-advanced-http/www/messages.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.public-interface",
+      "file": "plugins/cordova-plugin-advanced-http/www/public-interface.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.tough-cookie",
+      "file": "plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.url-util",
+      "file": "plugins/cordova-plugin-advanced-http/www/url-util.js",
+      "pluginId": "cordova-plugin-advanced-http"
+    },
+    {
+      "id": "cordova-plugin-advanced-http.http",
+      "file": "plugins/cordova-plugin-advanced-http/www/advanced-http.js",
+      "pluginId": "cordova-plugin-advanced-http",
+      "clobbers": [
+        "cordova.plugin.http"
+      ]
+    },
+    {
+      "id": "cordova-plugin-fingerprint-aio.Fingerprint",
+      "file": "plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js",
+      "pluginId": "cordova-plugin-fingerprint-aio",
+      "clobbers": [
+        "Fingerprint"
+      ]
+    },
+    {
+      "id": "cordova-plugin-statusbar.statusbar",
+      "file": "plugins/cordova-plugin-statusbar/www/statusbar.js",
+      "pluginId": "cordova-plugin-statusbar",
+      "clobbers": [
+        "window.StatusBar"
+      ]
+    },
+    {
+      "id": "cordova-plugin-touch-id.TouchID",
+      "file": "plugins/cordova-plugin-touch-id/www/TouchID.js",
+      "pluginId": "cordova-plugin-touch-id",
+      "clobbers": [
+        "window.plugins.touchid"
+      ]
+    },
+    {
+      "id": "cordova-plugin-qrscanner.QRScanner",
+      "file": "plugins/cordova-plugin-qrscanner/www/www.min.js",
+      "pluginId": "cordova-plugin-qrscanner",
+      "clobbers": [
+        "QRScanner"
+      ]
+    },
+    {
+      "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/ios/CameraPopoverHandle.js",
+      "pluginId": "cordova-plugin-camera",
+      "clobbers": [
+        "CameraPopoverHandle"
+      ]
+    },
+    {
+      "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-device.device",
+      "file": "plugins/cordova-plugin-device/www/device.js",
+      "pluginId": "cordova-plugin-device",
+      "clobbers": [
+        "device"
+      ]
+    },
+    {
+      "id": "cordova-plugin-themeablebrowser.themeablebrowser",
+      "file": "plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js",
+      "pluginId": "cordova-plugin-themeablebrowser",
+      "clobbers": [
+        "cordova.ThemeableBrowser"
+      ]
+    }
+  ];
+  module.exports.metadata = {
+    "cordova-plugin-add-swift-support": "2.0.2",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-advanced-http": "2.1.1",
+    "cordova-plugin-fingerprint-aio": "1.7.0",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-touch-id": "3.3.1",
+    "cordova-plugin-whitelist": "1.3.3",
+    "cordova-plugin-disable-ios11-statusbar": "1.0.0",
+    "cordova-plugin-qrscanner": "3.0.1",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-inappbrowser": "3.0.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-themeablebrowser": "0.2.17"
+  };
+});
\ No newline at end of file
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
new file mode 100644
index 0000000..5faece0
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/advanced-http.js
@@ -0,0 +1,23 @@
+cordova.define("cordova-plugin-advanced-http.http", function(require, exports, module) {
+/*
+ * A native HTTP Plugin for Cordova / PhoneGap.
+ */
+
+var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
+
+var exec = require('cordova/exec');
+var base64 = require('cordova/base64');
+var messages = require(pluginId + '.messages');
+var globalConfigs = require(pluginId + '.global-configs');
+var jsUtil = require(pluginId + '.js-util');
+var ToughCookie = require(pluginId + '.tough-cookie');
+var lodash = require(pluginId + '.lodash');
+var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash);
+var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore);
+var helpers = require(pluginId + '.helpers')(jsUtil, cookieHandler, messages, base64);
+var urlUtil = require(pluginId + '.url-util')(jsUtil);
+var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs);
+
+module.exports = publicInterface;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
new file mode 100644
index 0000000..e7cdb39
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/cookie-handler.js
@@ -0,0 +1,73 @@
+cordova.define("cordova-plugin-advanced-http.cookie-handler", function(require, exports, module) {
+module.exports = function init(storage, ToughCookie, WebStorageCookieStore) {
+  var storeKey = '__advancedHttpCookieStore__';
+
+  var store = new WebStorageCookieStore(storage, storeKey);
+  var cookieJar = new ToughCookie.CookieJar(store);
+
+  return {
+    setCookieFromString: setCookieFromString,
+    setCookie: setCookie,
+    getCookieString: getCookieString,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies
+  };
+
+  function splitCookieString(cookieStr) {
+    var cookieParts = cookieStr.split(',');
+    var splitCookies = [];
+    var processedCookie = null;
+
+    for (var i = 0; i < cookieParts.length; ++i) {
+      if (cookieParts[i].substr(-11, 8).toLowerCase() === 'expires=') {
+        processedCookie = cookieParts[i] + ',' + cookieParts[i + 1];
+        i++;
+      } else {
+        processedCookie = cookieParts[i];
+      }
+
+      processedCookie = processedCookie.trim();
+      splitCookies.push(processedCookie);
+    }
+
+    return splitCookies;
+  }
+
+  function setCookieFromString(url, cookieStr) {
+    if (!cookieStr) return;
+
+    var cookies = splitCookieString(cookieStr);
+
+    for (var i = 0; i < cookies.length; ++i) {
+      cookieJar.setCookieSync(cookies[i], url, { ignoreError: true });
+    }
+  }
+
+  function setCookie(url, cookie, options) {
+    options = options || {};
+    options.ignoreError = false;
+    cookieJar.setCookieSync(cookie, url, options);
+  }
+
+  function getCookieString(url) {
+    return cookieJar.getCookieStringSync(url);
+  }
+
+  function clearCookies() {
+    window.localStorage.removeItem(storeKey);
+  }
+
+  function removeCookies(url, cb) {
+    cookieJar.getCookies(url, function (error, cookies) {
+      if (!cookies || cookies.length === 0) {
+        return cb(null, []);
+      }
+
+      var domain = cookies[0].domain;
+
+      cookieJar.store.removeCookies(domain, null, cb);
+    });
+  }
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
new file mode 100644
index 0000000..5e85416
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/global-configs.js
@@ -0,0 +1,11 @@
+cordova.define("cordova-plugin-advanced-http.global-configs", function(require, exports, module) {
+var globalConfigs = {
+  headers: {},
+  serializer: 'urlencoded',
+  followRedirect: true,
+  timeout: 60.0,
+};
+
+module.exports = globalConfigs;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
new file mode 100644
index 0000000..855e84c
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/helpers.js
@@ -0,0 +1,353 @@
+cordova.define("cordova-plugin-advanced-http.helpers", function(require, exports, module) {
+module.exports = function init(jsUtil, cookieHandler, messages, base64) {
+  var validSerializers = ['urlencoded', 'json', 'utf8'];
+  var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
+  var validClientAuthModes = ['none', 'systemstore', 'buffer'];
+  var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download'];
+  var validResponseTypes = ['text','arraybuffer', 'blob'];
+
+  var interface = {
+    b64EncodeUnicode: b64EncodeUnicode,
+    checkSerializer: checkSerializer,
+    checkSSLCertMode: checkSSLCertMode,
+    checkClientAuthMode: checkClientAuthMode,
+    checkClientAuthOptions: checkClientAuthOptions,
+    checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
+    checkForInvalidHeaderValue: checkForInvalidHeaderValue,
+    checkTimeoutValue: checkTimeoutValue,
+    checkFollowRedirectValue: checkFollowRedirectValue,
+    injectCookieHandler: injectCookieHandler,
+    injectRawResponseHandler: injectRawResponseHandler,
+    injectFileEntryHandler: injectFileEntryHandler,
+    getMergedHeaders: getMergedHeaders,
+    getProcessedData: getProcessedData,
+    handleMissingCallbacks: handleMissingCallbacks,
+    handleMissingOptions: handleMissingOptions
+  };
+
+  // expose all functions for testing purposes
+  if (init.debug) {
+    interface.mergeHeaders = mergeHeaders;
+    interface.checkForValidStringValue = checkForValidStringValue;
+    interface.checkKeyValuePairObject = checkKeyValuePairObject;
+    interface.checkHttpMethod = checkHttpMethod;
+    interface.checkResponseType = checkResponseType;
+    interface.checkHeadersObject = checkHeadersObject;
+    interface.checkParamsObject = checkParamsObject;
+    interface.resolveCookieString = resolveCookieString;
+    interface.createFileEntry = createFileEntry;
+    interface.getCookieHeader = getCookieHeader;
+    interface.getMatchingHostHeaders = getMatchingHostHeaders;
+    interface.getAllowedDataTypes = getAllowedDataTypes;
+  }
+
+  return interface;
+
+  // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
+  function b64EncodeUnicode(str) {
+    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
+      return String.fromCharCode('0x' + p1);
+    }));
+  }
+
+  function mergeHeaders(globalHeaders, localHeaders) {
+    var globalKeys = Object.keys(globalHeaders);
+    var key;
+
+    for (var i = 0; i < globalKeys.length; i++) {
+      key = globalKeys[i];
+
+      if (!localHeaders.hasOwnProperty(key)) {
+        localHeaders[key] = globalHeaders[key];
+      }
+    }
+
+    return localHeaders;
+  }
+
+  function checkForValidStringValue(list, value, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    value = value.trim().toLowerCase();
+
+    if (list.indexOf(value) === -1) {
+      throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
+    }
+
+    return value;
+  }
+
+  function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
+    if (jsUtil.getTypeOf(obj) !== 'Object') {
+      throw new Error(onInvalidValueMessage);
+    }
+
+    var keys = Object.keys(obj);
+
+    for (var i = 0; i < keys.length; i++) {
+      if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
+        throw new Error(onInvalidValueMessage);
+      }
+    }
+
+    return obj;
+  }
+
+  function checkHttpMethod(method) {
+    return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
+  }
+
+  function checkResponseType(type) {
+    return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
+  }
+
+  function checkSerializer(serializer) {
+    return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
+  }
+
+  function checkSSLCertMode(mode) {
+    return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
+  }
+
+  function checkClientAuthMode(mode) {
+    return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
+  }
+
+  function checkClientAuthOptions(mode, options) {
+    options = options || {};
+
+    // none
+    if (mode === validClientAuthModes[0]) {
+      return {
+        alias: null,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    if (jsUtil.getTypeOf(options) !== 'Object') {
+      throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
+    }
+
+    // systemstore
+    if (mode === validClientAuthModes[1]) {
+      if (jsUtil.getTypeOf(options.alias) !== 'String'
+        && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
+      }
+
+      return {
+        alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
+        rawPkcs: null,
+        pkcsPassword: ''
+      };
+    }
+
+    // buffer
+    if (mode === validClientAuthModes[2]) {
+      if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
+      }
+
+      if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
+        throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
+      }
+
+      return {
+        alias: null,
+        rawPkcs: options.rawPkcs,
+        pkcsPassword: options.pkcsPassword
+      }
+    }
+  }
+
+  function checkForBlacklistedHeaderKey(key) {
+    if (key.toLowerCase() === 'cookie') {
+      throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
+    }
+
+    return key;
+  }
+
+  function checkForInvalidHeaderValue(value) {
+    if (jsUtil.getTypeOf(value) !== 'String') {
+      throw new Error(messages.INVALID_HEADERS_VALUE);
+    }
+
+    return value;
+  }
+
+  function checkTimeoutValue(timeout) {
+    if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
+      throw new Error(messages.INVALID_TIMEOUT_VALUE);
+    }
+
+    return timeout;
+  }
+
+  function checkFollowRedirectValue(follow) {
+    if (jsUtil.getTypeOf(follow) !== 'Boolean') {
+      throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
+    }
+
+    return follow;
+  }
+
+  function checkHeadersObject(headers) {
+    return checkKeyValuePairObject(headers, ['String'], messages.INVALID_HEADERS_VALUE);
+  }
+
+  function checkParamsObject(params) {
+    return checkKeyValuePairObject(params, ['String', 'Array'], messages.INVALID_PARAMS_VALUE);
+  }
+
+  function resolveCookieString(headers) {
+    var keys = Object.keys(headers || {});
+
+    for (var i = 0; i < keys.length; ++i) {
+      if (keys[i].match(/^set-cookie$/i)) {
+        return headers[keys[i]];
+      }
+    }
+
+    return null;
+  }
+
+  function createFileEntry(rawEntry) {
+    var entry = new (require('cordova-plugin-file.FileEntry'))();
+
+    entry.isDirectory = rawEntry.isDirectory;
+    entry.isFile = rawEntry.isFile;
+    entry.name = rawEntry.name;
+    entry.fullPath = rawEntry.fullPath;
+    entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary'));
+    entry.nativeURL = rawEntry.nativeURL;
+
+    return entry;
+  }
+
+  function injectCookieHandler(url, cb) {
+    return function (response) {
+      cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
+      cb(response);
+    }
+  }
+
+  function injectRawResponseHandler(responseType, cb) {
+    return function (response) {
+      var dataType = jsUtil.getTypeOf(response.data);
+
+      // don't need post-processing if it's already binary type (on browser platform)
+      if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
+        return cb(response);
+      }
+
+      // arraybuffer
+      if (responseType === validResponseTypes[1]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        response.data = buffer;
+      }
+
+      // blob
+      if (responseType === validResponseTypes[2]) {
+        var buffer = base64.toArrayBuffer(response.data);
+        var type = response.headers['content-type'] || '';
+        var blob = new Blob([ buffer ], { type: type });
+        response.data = blob;
+      }
+
+      cb(response);
+    }
+  }
+
+  function injectFileEntryHandler(cb) {
+    return function (response) {
+      cb(createFileEntry(response.file));
+    }
+  }
+
+  function getCookieHeader(url) {
+    var cookieString = cookieHandler.getCookieString(url);
+
+    if (cookieString.length) {
+      return { Cookie: cookieHandler.getCookieString(url) };
+    }
+
+    return {};
+  }
+
+  function getMatchingHostHeaders(url, headersList) {
+    var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
+    var domain = matches && matches[1];
+
+    return headersList[domain] || null;
+  }
+
+  function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
+    var globalHeaders = predefinedHeaders['*'] || {};
+    var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
+    var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
+
+    mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
+    mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
+
+    return mergedHeaders;
+  }
+
+  function getAllowedDataTypes(dataSerializer) {
+    switch (dataSerializer) {
+      case 'utf8':
+        return ['String'];
+      case 'urlencoded':
+        return ['Object'];
+      default:
+        return ['Array', 'Object'];
+    }
+  }
+
+  function getProcessedData(data, dataSerializer) {
+    var currentDataType = jsUtil.getTypeOf(data);
+    var allowedDataTypes = getAllowedDataTypes(dataSerializer);
+
+    if (allowedDataTypes.indexOf(currentDataType) === -1) {
+      throw new Error(messages.DATA_TYPE_MISMATCH + ' ' + allowedDataTypes.join(', '));
+    }
+
+    if (dataSerializer === 'utf8') {
+      data = { text: data };
+    }
+
+    return data;
+  }
+
+  function handleMissingCallbacks(successFn, failFn) {
+    if (jsUtil.getTypeOf(successFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_SUCCESS);
+    }
+
+    if (jsUtil.getTypeOf(failFn) !== 'Function') {
+      throw new Error(messages.MANDATORY_FAIL);
+    }
+  }
+
+  function handleMissingOptions(options, globals) {
+    options = options || {};
+
+    return {
+      method: checkHttpMethod(options.method || validHttpMethods[0]),
+      responseType: checkResponseType(options.responseType || validResponseTypes[0]),
+      serializer: checkSerializer(options.serializer || globals.serializer),
+      timeout: checkTimeoutValue(options.timeout || globals.timeout),
+      followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
+      headers: checkHeadersObject(options.headers || {}),
+      params: checkParamsObject(options.params || {}),
+      data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
+      filePath: options.filePath || '',
+      name: options.name || ''
+    };
+  }
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
new file mode 100644
index 0000000..cbe1c51
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/js-util.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-advanced-http.js-util", function(require, exports, module) {
+module.exports = {
+  // typeof is not working reliably in JS
+  getTypeOf: function (object) {
+    switch (Object.prototype.toString.call(object)) {
+      case '[object Array]':
+        return 'Array';
+      case '[object Blob]':
+        return 'Blob';
+      case '[object ArrayBuffer]':
+        return 'ArrayBuffer';
+      case '[object Boolean]':
+        return 'Boolean';
+      case '[object Function]':
+        return 'Function';
+      case '[object Null]':
+        return 'Null';
+      case '[object Number]':
+        return 'Number';
+      case '[object Object]':
+        return 'Object';
+      case '[object String]':
+        return 'String';
+      case '[object Undefined]':
+        return 'Undefined';
+      default:
+        return 'Unknown';
+    }
+  }
+}
+
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
new file mode 100644
index 0000000..800c6b7
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/local-storage-store.js
@@ -0,0 +1,184 @@
+cordova.define("cordova-plugin-advanced-http.local-storage-store", function(require, exports, module) {
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Exponent
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Based on "tough-cookie-web-storage-store" v1.0.0
+ * Thanks James Ide: https://github.com/exponentjs/tough-cookie-web-storage-store
+ *
+ * Modified by Sefa Ilkimen for cordova plugin integration
+ *
+ */
+
+'use strict';
+
+module.exports = function init(ToughCookie, _) {
+  function WebStorageCookieStore(storage, storeKey) {
+    ToughCookie.Store.call(this);
+    this._storage = storage;
+    this._storeKey = storeKey || '__cookieStore__';
+    this.synchronous = true;
+  }
+
+  WebStorageCookieStore.prototype = Object.create(ToughCookie.Store);
+
+  WebStorageCookieStore.prototype.findCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+    var cookie = _.get(store, [domain, path, key], null);
+
+    callback(null, ToughCookie.Cookie.fromJSON(cookie));
+  };
+
+  WebStorageCookieStore.prototype.findCookies = function (domain, path, callback) {
+    if (!domain) {
+      callback(null, []);
+      return;
+    }
+
+    var that = this;
+    var cookies = [];
+    var store = this._readStore();
+    var domains = ToughCookie.permuteDomain(domain) || [domain];
+
+    domains.forEach(function (domain) {
+      if (!store[domain]) {
+        return;
+      }
+
+      var matchingPaths = Object.keys(store[domain]);
+
+      if (path != null) {
+        matchingPaths = matchingPaths.filter(function (cookiePath) {
+          return that._isOnPath(cookiePath, path);
+        });
+      }
+
+      matchingPaths.forEach(function (path) {
+        Array.prototype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    callback(null, cookies);
+  };
+
+  /**
+   * Returns whether `cookiePath` is on the given `urlPath`
+   */
+  WebStorageCookieStore.prototype._isOnPath = function (cookiePath, urlPath) {
+    if (!cookiePath) {
+      return false;
+    }
+
+    if (cookiePath === urlPath) {
+      return true;
+    }
+
+    if (urlPath.indexOf(cookiePath) !== 0) {
+      return false;
+    }
+
+    if (cookiePath[cookiePath.length - 1] !== '/' && urlPath[cookiePath.length] !== '/') {
+      return false;
+    }
+
+    return true;
+  };
+
+  WebStorageCookieStore.prototype.putCookie = function (cookie, callback) {
+    var store = this._readStore();
+
+    _.set(store, [cookie.domain, cookie.path, cookie.key], cookie);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.updateCookie = function (oldCookie, newCookie, callback) {
+    this.putCookie(newCookie, callback);
+  };
+
+
+  WebStorageCookieStore.prototype.removeCookie = function (domain, path, key, callback) {
+    var store = this._readStore();
+
+    _.unset(store, [domain, path, key]);
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.removeCookies = function (domain, path, callback) {
+    var store = this._readStore();
+
+    if (path == null) {
+      _.unset(store, [domain]);
+    } else {
+      _.unset(store, [domain, path]);
+    }
+
+    this._writeStore(store);
+    callback(null);
+  };
+
+  WebStorageCookieStore.prototype.getAllCookies = function (callback) {
+    var cookies = [];
+    var store = this._readStore();
+
+    Object.keys(store).forEach(function (domain) {
+      Object.keys(store[domain]).forEach(function (path) {
+        Array.protype.push.apply(cookies, _.values(store[domain][path]));
+      });
+    });
+
+    cookies = cookies.map(function (cookie) {
+      return ToughCookie.Cookie.fromJSON(cookie);
+    });
+
+    cookies.sort(function (c1, c2) {
+      return (c1.creationIndex || 0) - (c2.creationIndex || 0);
+    });
+
+    callback(null, cookies);
+  };
+
+  WebStorageCookieStore.prototype._readStore = function () {
+    var json = this._storage.getItem(this._storeKey);
+
+    if (json !== null) {
+      try {
+        return JSON.parse(json);
+      } catch (e) { }
+    }
+
+    return {};
+  };
+
+  WebStorageCookieStore.prototype._writeStore = function (store) {
+    this._storage.setItem(this._storeKey, JSON.stringify(store));
+  };
+
+  return WebStorageCookieStore;
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
new file mode 100644
index 0000000..f35be77
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/lodash.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.lodash", function(require, exports, module) {
+/**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash include="get,set,unset,values" exports="node"`
+ */
+;(function(){function t(t,e){for(var r=-1,n=null==t?0:t.length,o=Array(n);++r<n;)o[r]=e(t[r],r,t);return o}function e(t){return function(e){return t(e)}}function r(e,r){return t(r,function(t){return e[t]})}function n(){}function o(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function u(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function i(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1]);
+}}function c(t,e){for(var r=t.length;r--;)if(m(t[r][0],e))return r;return-1}function a(t,e){e=h(e,t);for(var r=0,n=e.length;null!=t&&r<n;)t=t[j(e[r++])];return r&&r==n?t:E}function l(t){if(null==t)return t===E?"[object Undefined]":"[object Null]";t=Object(t);var e;if(nt&&nt in t){var r=Q.call(t,nt),n=t[nt];try{t[nt]=E,e=true}catch(t){}var o=Y.call(t);e&&(r?t[nt]=n:delete t[nt]),e=o}else e=Y.call(t);return e}function s(t){return w(t)&&"[object Arguments]"==l(t)}function f(t){return w(t)&&z(t.length)&&!!M[l(t)];
+}function p(e){if(typeof e=="string")return e;if(ft(e))return t(e,p)+"";if(x(e))return at?at.call(e):"";var r=e+"";return"0"==r&&1/e==-T?"-0":r}function h(t,e){var r;return ft(t)?r=t:(ft(t)?r=false:(r=typeof t,r=!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!x(t))||(B.test(t)||!I.test(t)||null!=e&&t in Object(e))),r=r?[t]:lt(F(t))),r}function y(t,e){var r=t.__data__,n=typeof e;return("string"==n||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?r[typeof e=="string"?"string":"hash"]:r.map;
+}function b(t,e){var r=null==t?E:t[e];return(!S(r)||X&&X in r?0:(O(r)?Z:L).test(g(r)))?r:E}function _(t,e){return e=null==e?9007199254740991:e,!!e&&(typeof t=="number"||R.test(t))&&-1<t&&0==t%1&&t<e}function j(t){if(typeof t=="string"||x(t))return t;var e=t+"";return"0"==e&&1/t==-T?"-0":e}function g(t){if(null!=t){try{return K.call(t)}catch(t){}return t+""}return""}function v(t){var e=null==t?0:t.length;return e?t[e-1]:E}function d(t,e){function r(){var n=arguments,o=e?e.apply(this,n):n[0],u=r.cache;
+return u.has(o)?u.get(o):(n=t.apply(this,n),r.cache=u.set(o,n)||u,n)}if(typeof t!="function"||null!=e&&typeof e!="function")throw new TypeError("Expected a function");return r.cache=new(d.Cache||i),r}function m(t,e){return t===e||t!==t&&e!==e}function A(t){return null!=t&&z(t.length)&&!O(t)}function O(t){return!!S(t)&&(t=l(t),"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t)}function z(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t;
+}function S(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function w(t){return null!=t&&typeof t=="object"}function x(t){return typeof t=="symbol"||w(t)&&"[object Symbol]"==l(t)}function F(t){return null==t?"":p(t)}function $(t){if(A(t)){var e=ft(t),r=!e&&st(t),n=!e&&!r&&pt(t),o=!e&&!r&&!n&&ht(t);if(e=e||r||n||o){for(var r=t.length,u=String,i=-1,c=Array(r);++i<r;)c[i]=u(i);r=c}else r=[];var a,u=r.length;for(a in t)!Q.call(t,a)||e&&("length"==a||n&&("offset"==a||"parent"==a)||o&&("buffer"==a||"byteLength"==a||"byteOffset"==a)||_(a,u))||r.push(a);
+t=r}else if(a=t&&t.constructor,t===(typeof a=="function"&&a.prototype||H)){a=[];for(n in Object(t))Q.call(t,n)&&"constructor"!=n&&a.push(n);t=a}else t=ut(t);return t}function k(){return false}var E,T=1/0,I=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,B=/^\w*$/,P=/^\./,U=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,C=/\\(\\)?/g,L=/^\[object .+?Constructor\]$/,R=/^(?:0|[1-9]\d*)$/,M={};M["[object Float32Array]"]=M["[object Float64Array]"]=M["[object Int8Array]"]=M["[object Int16Array]"]=M["[object Int32Array]"]=M["[object Uint8Array]"]=M["[object Uint8ClampedArray]"]=M["[object Uint16Array]"]=M["[object Uint32Array]"]=true,
+M["[object Arguments]"]=M["[object Array]"]=M["[object ArrayBuffer]"]=M["[object Boolean]"]=M["[object DataView]"]=M["[object Date]"]=M["[object Error]"]=M["[object Function]"]=M["[object Map]"]=M["[object Number]"]=M["[object Object]"]=M["[object RegExp]"]=M["[object Set]"]=M["[object String]"]=M["[object WeakMap]"]=false;var N,D=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,q=D||V||Function("return this")(),G=(V=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,W=G&&G.exports===V,D=W&&D.process;
+t:{try{N=D&&D.binding&&D.binding("util");break t}catch(t){}N=void 0}N=N&&N.isTypedArray;var D=Array.prototype,H=Object.prototype,J=q["__core-js_shared__"],K=Function.prototype.toString,Q=H.hasOwnProperty,X=function(){var t=/[^.]+$/.exec(J&&J.keys&&J.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Y=H.toString,Z=RegExp("^"+K.call(Q).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),tt=W?q.Buffer:E,W=q.Symbol,et=H.propertyIsEnumerable,rt=D.splice,nt=W?W.toStringTag:E,ot=function(){
+try{var t=b(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),D=tt?tt.isBuffer:E,ut=function(t,e){return function(r){return t(e(r))}}(Object.keys,Object),it=b(q,"Map"),ct=b(Object,"create"),at=(q=W?W.prototype:E)?q.toString:E;o.prototype.clear=function(){this.__data__=ct?ct(null):{},this.size=0},o.prototype.delete=function(t){return t=this.has(t)&&delete this.__data__[t],this.size-=t?1:0,t},o.prototype.get=function(t){var e=this.__data__;return ct?(t=e[t],"__lodash_hash_undefined__"===t?E:t):Q.call(e,t)?e[t]:E;
+},o.prototype.has=function(t){var e=this.__data__;return ct?e[t]!==E:Q.call(e,t)},o.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=ct&&e===E?"__lodash_hash_undefined__":e,this},u.prototype.clear=function(){this.__data__=[],this.size=0},u.prototype.delete=function(t){var e=this.__data__;return t=c(e,t),!(0>t)&&(t==e.length-1?e.pop():rt.call(e,t,1),--this.size,true)},u.prototype.get=function(t){var e=this.__data__;return t=c(e,t),0>t?E:e[t][1]},u.prototype.has=function(t){
+return-1<c(this.__data__,t)},u.prototype.set=function(t,e){var r=this.__data__,n=c(r,t);return 0>n?(++this.size,r.push([t,e])):r[n][1]=e,this},i.prototype.clear=function(){this.size=0,this.__data__={hash:new o,map:new(it||u),string:new o}},i.prototype.delete=function(t){return t=y(this,t).delete(t),this.size-=t?1:0,t},i.prototype.get=function(t){return y(this,t).get(t)},i.prototype.has=function(t){return y(this,t).has(t)},i.prototype.set=function(t,e){var r=y(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,
+this};var lt=function(t){t=d(t,function(t){return 500===e.size&&e.clear(),t});var e=t.cache;return t}(function(t){var e=[];return P.test(t)&&e.push(""),t.replace(U,function(t,r,n,o){e.push(n?o.replace(C,"$1"):r||t)}),e});d.Cache=i;var st=s(function(){return arguments}())?s:function(t){return w(t)&&Q.call(t,"callee")&&!et.call(t,"callee")},ft=Array.isArray,pt=D||k,ht=N?e(N):f;n.keys=$,n.memoize=d,n.set=function(t,e,r){if(null!=t&&S(t)){e=h(e,t);for(var n=-1,o=e.length,u=o-1,i=t;null!=i&&++n<o;){var c=j(e[n]),a=r;
+if(n!=u){var l=i[c],a=E;a===E&&(a=S(l)?l:_(e[n+1])?[]:{})}var s=i,l=c,f=s[l];Q.call(s,l)&&m(f,a)&&(a!==E||l in s)||("__proto__"==l&&ot?ot(s,l,{configurable:true,enumerable:true,value:a,writable:true}):s[l]=a),i=i[c]}}return t},n.unset=function(t,e){var r;if(null==t)r=true;else{var n=t,o=r=h(e,n);if(!(2>o.length)){var u=0,i=-1,c=-1,l=o.length;for(0>u&&(u=-u>l?0:l+u),i=i>l?l:i,0>i&&(i+=l),l=u>i?0:i-u>>>0,u>>>=0,i=Array(l);++c<l;)i[c]=o[c+u];n=a(n,i)}r=j(v(r)),r=!(null!=n&&Q.call(n,r))||delete n[r]}return r;
+},n.values=function(t){return null==t?[]:r(t,$(t))},n.eq=m,n.get=function(t,e,r){return t=null==t?E:a(t,e),t===E?r:t},n.isArguments=st,n.isArray=ft,n.isArrayLike=A,n.isBuffer=pt,n.isFunction=O,n.isLength=z,n.isObject=S,n.isObjectLike=w,n.isSymbol=x,n.isTypedArray=ht,n.last=v,n.stubFalse=k,n.toString=F,n.VERSION="4.17.1",G&&((G.exports=n)._=n,V._=n)}).call(this);
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
new file mode 100644
index 0000000..13efb2b
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/messages.js
@@ -0,0 +1,22 @@
+cordova.define("cordova-plugin-advanced-http.messages", function(require, exports, module) {
+module.exports = {
+  ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
+  DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
+  INVALID_CLIENT_AUTH_ALIAS: 'advanced-http: invalid client certificate alias, needs to be a string or undefined',
+  INVALID_CLIENT_AUTH_MODE: 'advanced-http: invalid client certificate authentication mode, supported modes are:',
+  INVALID_CLIENT_AUTH_OPTIONS: 'advanced-http: invalid client certificate authentication options, needs to be an object',
+  INVALID_CLIENT_AUTH_PKCS_PASSWORD: 'advanced-http: invalid PKCS12 container password, needs to be a string',
+  INVALID_CLIENT_AUTH_RAW_PKCS: 'advanced-http: invalid PKCS12 container, needs to be an array buffer',
+  INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
+  INVALID_FOLLOW_REDIRECT_VALUE: 'advanced-http: invalid follow redirect value, needs to be a boolean value',
+  INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
+  INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
+  INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings',
+  INVALID_RESPONSE_TYPE: 'advanced-http: invalid response type, supported types are:',
+  INVALID_SSL_CERT_MODE: 'advanced-http: invalid SSL cert mode, supported modes are:',
+  INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
+  MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
+  MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
new file mode 100644
index 0000000..a77c8e0
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/public-interface.js
@@ -0,0 +1,202 @@
+cordova.define("cordova-plugin-advanced-http.public-interface", function(require, exports, module) {
+module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConfigs) {
+  const publicInterface = {
+    getBasicAuthHeader: getBasicAuthHeader,
+    useBasicAuth: useBasicAuth,
+    getHeaders: getHeaders,
+    setHeader: setHeader,
+    getDataSerializer: getDataSerializer,
+    setDataSerializer: setDataSerializer,
+    setCookie: setCookie,
+    clearCookies: clearCookies,
+    removeCookies: removeCookies,
+    getCookieString: getCookieString,
+    getRequestTimeout: getRequestTimeout,
+    setRequestTimeout: setRequestTimeout,
+    getFollowRedirect: getFollowRedirect,
+    setFollowRedirect: setFollowRedirect,
+    // @DEPRECATED
+    disableRedirect: disableRedirect,
+    // @DEPRECATED
+    setSSLCertMode: setServerTrustMode,
+    setServerTrustMode: setServerTrustMode,
+    setClientAuthMode: setClientAuthMode,
+    sendRequest: sendRequest,
+    post: post,
+    get: get,
+    put: put,
+    patch: patch,
+    delete: del,
+    head: head,
+    uploadFile: uploadFile,
+    downloadFile: downloadFile
+  };
+
+  function getBasicAuthHeader(username, password) {
+    return { 'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password) };
+  }
+
+  function useBasicAuth(username, password) {
+    this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
+  }
+
+  function getHeaders(host) {
+    return globalConfigs.headers[host || '*'] || null;
+  }
+
+  function setHeader() {
+    // this one is for being backward compatible
+    var host = '*';
+    var header = arguments[0];
+    var value = arguments[1];
+
+    if (arguments.length === 3) {
+      host = arguments[0];
+      header = arguments[1];
+      value = arguments[2];
+    }
+
+    helpers.checkForBlacklistedHeaderKey(header);
+    helpers.checkForInvalidHeaderValue(value);
+
+    globalConfigs.headers[host] = globalConfigs.headers[host] || {};
+    globalConfigs.headers[host][header] = value;
+  }
+
+  function getDataSerializer() {
+    return globalConfigs.serializer;
+  }
+
+  function setDataSerializer(serializer) {
+    globalConfigs.serializer = helpers.checkSerializer(serializer);
+  }
+
+  function setCookie(url, cookie, options) {
+    cookieHandler.setCookie(url, cookie, options);
+  }
+
+  function clearCookies() {
+    cookieHandler.clearCookies();
+  }
+
+  function removeCookies(url, callback) {
+    cookieHandler.removeCookies(url, callback);
+  }
+
+  function getCookieString(url) {
+    return cookieHandler.getCookieString(url);
+  }
+
+  function getRequestTimeout() {
+    return globalConfigs.timeout;
+  }
+
+  function setRequestTimeout(timeout) {
+    globalConfigs.timeout = helpers.checkTimeoutValue(timeout);
+  }
+
+  function getFollowRedirect() {
+    return globalConfigs.followRedirect;
+  }
+
+  function setFollowRedirect(follow) {
+    globalConfigs.followRedirect = helpers.checkFollowRedirectValue(follow);
+  }
+
+  // @DEPRECATED
+  function disableRedirect(disable, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    setFollowRedirect(!disable);
+    success();
+  }
+
+  function setServerTrustMode(mode, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setServerTrustMode', [helpers.checkSSLCertMode(mode)]);
+  }
+
+  function setClientAuthMode() {
+    var mode = arguments[0];
+    var options = null;
+    var success = arguments[1];
+    var failure = arguments[2];
+
+    if (arguments.length === 4) {
+      options = arguments[1];
+      success = arguments[2];
+      failure = arguments[3];
+    }
+
+    mode = helpers.checkClientAuthMode(mode);
+    options = helpers.checkClientAuthOptions(mode, options);
+
+    helpers.handleMissingCallbacks(success, failure);
+
+    return exec(success, failure, 'CordovaHttpPlugin', 'setClientAuthMode', [mode, options.alias, options.rawPkcs, options.pkcsPassword]);
+  }
+
+  function sendRequest(url, options, success, failure) {
+    helpers.handleMissingCallbacks(success, failure);
+
+    options = helpers.handleMissingOptions(options, globalConfigs);
+    url = urlUtil.appendQueryParamsString(url, urlUtil.serializeQueryParams(options.params, true));
+
+    var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
+
+    var onFail = helpers.injectCookieHandler(url, failure);
+    var onSuccess = helpers.injectCookieHandler(url, helpers.injectRawResponseHandler(options.responseType, success));
+
+    switch (options.method) {
+      case 'post':
+      case 'put':
+      case 'patch':
+        var data = helpers.getProcessedData(options.data, options.serializer);
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]);
+      case 'upload':
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, headers, options.filePath, options.name, options.timeout, options.followRedirect, options.responseType]);
+      case 'download':
+        var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
+        return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, headers, options.filePath, options.timeout, options.followRedirect]);
+      default:
+        return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, headers, options.timeout, options.followRedirect, options.responseType]);
+    }
+  }
+
+  function post(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
+  };
+
+  function get(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
+  };
+
+  function put(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
+  }
+
+  function patch(url, data, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
+  }
+
+  function del(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
+  }
+
+  function head(url, params, headers, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
+  }
+
+  function uploadFile(url, params, headers, filePath, name, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
+  }
+
+  function downloadFile(url, params, headers, filePath, success, failure) {
+    return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
+  }
+
+  return publicInterface;
+}
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
new file mode 100644
index 0000000..bd8ab68
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/umd-tough-cookie.js
@@ -0,0 +1,5091 @@
+cordova.define("cordova-plugin-advanced-http.tough-cookie", function(require, exports, module) {
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["ToughCookie"] = factory();
+	else
+		root["ToughCookie"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var net = __webpack_require__(1);
+	var urlParse = __webpack_require__(2).parse;
+	var util = __webpack_require__(9);
+	var pubsuffix = __webpack_require__(13);
+	var Store = __webpack_require__(17).Store;
+	var MemoryCookieStore = __webpack_require__(18).MemoryCookieStore;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var VERSION = __webpack_require__(21).version;
+
+	var punycode;
+	try {
+	  punycode = __webpack_require__(15);
+	} catch(e) {
+	  console.warn("tough-cookie: can't load punycode; won't use punycode for domain normalization");
+	}
+
+	// From RFC6265 S4.1.1
+	// note that it excludes \x3B ";"
+	var COOKIE_OCTETS = /^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/;
+
+	var CONTROL_CHARS = /[\x00-\x1F]/;
+
+	// From Chromium // '\r', '\n' and '\0' should be treated as a terminator in
+	// the "relaxed" mode, see:
+	// https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/parsed_cookie.cc#L60
+	var TERMINATORS = ['\n', '\r', '\0'];
+
+	// RFC6265 S4.1.1 defines path value as 'any CHAR except CTLs or ";"'
+	// Note ';' is \x3B
+	var PATH_VALUE = /[\x20-\x3A\x3C-\x7E]+/;
+
+	// date-time parsing constants (RFC6265 S5.1.1)
+
+	var DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/;
+
+	var MONTH_TO_NUM = {
+	  jan:0, feb:1, mar:2, apr:3, may:4, jun:5,
+	  jul:6, aug:7, sep:8, oct:9, nov:10, dec:11
+	};
+	var NUM_TO_MONTH = [
+	  'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
+	];
+	var NUM_TO_DAY = [
+	  'Sun','Mon','Tue','Wed','Thu','Fri','Sat'
+	];
+
+	var MAX_TIME = 2147483647000; // 31-bit max
+	var MIN_TIME = 0; // 31-bit min
+
+	/*
+	 * Parses a Natural number (i.e., non-negative integer) with either the
+	 *    <min>*<max>DIGIT ( non-digit *OCTET )
+	 * or
+	 *    <min>*<max>DIGIT
+	 * grammar (RFC6265 S5.1.1).
+	 *
+	 * The "trailingOK" boolean controls if the grammar accepts a
+	 * "( non-digit *OCTET )" trailer.
+	 */
+	function parseDigits(token, minDigits, maxDigits, trailingOK) {
+	  var count = 0;
+	  while (count < token.length) {
+	    var c = token.charCodeAt(count);
+	    // "non-digit = %x00-2F / %x3A-FF"
+	    if (c <= 0x2F || c >= 0x3A) {
+	      break;
+	    }
+	    count++;
+	  }
+
+	  // constrain to a minimum and maximum number of digits.
+	  if (count < minDigits || count > maxDigits) {
+	    return null;
+	  }
+
+	  if (!trailingOK && count != token.length) {
+	    return null;
+	  }
+
+	  return parseInt(token.substr(0,count), 10);
+	}
+
+	function parseTime(token) {
+	  var parts = token.split(':');
+	  var result = [0,0,0];
+
+	  /* RF6256 S5.1.1:
+	   *      time            = hms-time ( non-digit *OCTET )
+	   *      hms-time        = time-field ":" time-field ":" time-field
+	   *      time-field      = 1*2DIGIT
+	   */
+
+	  if (parts.length !== 3) {
+	    return null;
+	  }
+
+	  for (var i = 0; i < 3; i++) {
+	    // "time-field" must be strictly "1*2DIGIT", HOWEVER, "hms-time" can be
+	    // followed by "( non-digit *OCTET )" so therefore the last time-field can
+	    // have a trailer
+	    var trailingOK = (i == 2);
+	    var num = parseDigits(parts[i], 1, 2, trailingOK);
+	    if (num === null) {
+	      return null;
+	    }
+	    result[i] = num;
+	  }
+
+	  return result;
+	}
+
+	function parseMonth(token) {
+	  token = String(token).substr(0,3).toLowerCase();
+	  var num = MONTH_TO_NUM[token];
+	  return num >= 0 ? num : null;
+	}
+
+	/*
+	 * RFC6265 S5.1.1 date parser (see RFC for full grammar)
+	 */
+	function parseDate(str) {
+	  if (!str) {
+	    return;
+	  }
+
+	  /* RFC6265 S5.1.1:
+	   * 2. Process each date-token sequentially in the order the date-tokens
+	   * appear in the cookie-date
+	   */
+	  var tokens = str.split(DATE_DELIM);
+	  if (!tokens) {
+	    return;
+	  }
+
+	  var hour = null;
+	  var minute = null;
+	  var second = null;
+	  var dayOfMonth = null;
+	  var month = null;
+	  var year = null;
+
+	  for (var i=0; i<tokens.length; i++) {
+	    var token = tokens[i].trim();
+	    if (!token.length) {
+	      continue;
+	    }
+
+	    var result;
+
+	    /* 2.1. If the found-time flag is not set and the token matches the time
+	     * production, set the found-time flag and set the hour- value,
+	     * minute-value, and second-value to the numbers denoted by the digits in
+	     * the date-token, respectively.  Skip the remaining sub-steps and continue
+	     * to the next date-token.
+	     */
+	    if (second === null) {
+	      result = parseTime(token);
+	      if (result) {
+	        hour = result[0];
+	        minute = result[1];
+	        second = result[2];
+	        continue;
+	      }
+	    }
+
+	    /* 2.2. If the found-day-of-month flag is not set and the date-token matches
+	     * the day-of-month production, set the found-day-of- month flag and set
+	     * the day-of-month-value to the number denoted by the date-token.  Skip
+	     * the remaining sub-steps and continue to the next date-token.
+	     */
+	    if (dayOfMonth === null) {
+	      // "day-of-month = 1*2DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 1, 2, true);
+	      if (result !== null) {
+	        dayOfMonth = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.3. If the found-month flag is not set and the date-token matches the
+	     * month production, set the found-month flag and set the month-value to
+	     * the month denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (month === null) {
+	      result = parseMonth(token);
+	      if (result !== null) {
+	        month = result;
+	        continue;
+	      }
+	    }
+
+	    /* 2.4. If the found-year flag is not set and the date-token matches the
+	     * year production, set the found-year flag and set the year-value to the
+	     * number denoted by the date-token.  Skip the remaining sub-steps and
+	     * continue to the next date-token.
+	     */
+	    if (year === null) {
+	      // "year = 2*4DIGIT ( non-digit *OCTET )"
+	      result = parseDigits(token, 2, 4, true);
+	      if (result !== null) {
+	        year = result;
+	        /* From S5.1.1:
+	         * 3.  If the year-value is greater than or equal to 70 and less
+	         * than or equal to 99, increment the year-value by 1900.
+	         * 4.  If the year-value is greater than or equal to 0 and less
+	         * than or equal to 69, increment the year-value by 2000.
+	         */
+	        if (year >= 70 && year <= 99) {
+	          year += 1900;
+	        } else if (year >= 0 && year <= 69) {
+	          year += 2000;
+	        }
+	      }
+	    }
+	  }
+
+	  /* RFC 6265 S5.1.1
+	   * "5. Abort these steps and fail to parse the cookie-date if:
+	   *     *  at least one of the found-day-of-month, found-month, found-
+	   *        year, or found-time flags is not set,
+	   *     *  the day-of-month-value is less than 1 or greater than 31,
+	   *     *  the year-value is less than 1601,
+	   *     *  the hour-value is greater than 23,
+	   *     *  the minute-value is greater than 59, or
+	   *     *  the second-value is greater than 59.
+	   *     (Note that leap seconds cannot be represented in this syntax.)"
+	   *
+	   * So, in order as above:
+	   */
+	  if (
+	    dayOfMonth === null || month === null || year === null || second === null ||
+	    dayOfMonth < 1 || dayOfMonth > 31 ||
+	    year < 1601 ||
+	    hour > 23 ||
+	    minute > 59 ||
+	    second > 59
+	  ) {
+	    return;
+	  }
+
+	  return new Date(Date.UTC(year, month, dayOfMonth, hour, minute, second));
+	}
+
+	function formatDate(date) {
+	  var d = date.getUTCDate(); d = d >= 10 ? d : '0'+d;
+	  var h = date.getUTCHours(); h = h >= 10 ? h : '0'+h;
+	  var m = date.getUTCMinutes(); m = m >= 10 ? m : '0'+m;
+	  var s = date.getUTCSeconds(); s = s >= 10 ? s : '0'+s;
+	  return NUM_TO_DAY[date.getUTCDay()] + ', ' +
+	    d+' '+ NUM_TO_MONTH[date.getUTCMonth()] +' '+ date.getUTCFullYear() +' '+
+	    h+':'+m+':'+s+' GMT';
+	}
+
+	// S5.1.2 Canonicalized Host Names
+	function canonicalDomain(str) {
+	  if (str == null) {
+	    return null;
+	  }
+	  str = str.trim().replace(/^\./,''); // S4.1.2.3 & S5.2.3: ignore leading .
+
+	  // convert to IDN if any non-ASCII characters
+	  if (punycode && /[^\u0001-\u007f]/.test(str)) {
+	    str = punycode.toASCII(str);
+	  }
+
+	  return str.toLowerCase();
+	}
+
+	// S5.1.3 Domain Matching
+	function domainMatch(str, domStr, canonicalize) {
+	  if (str == null || domStr == null) {
+	    return null;
+	  }
+	  if (canonicalize !== false) {
+	    str = canonicalDomain(str);
+	    domStr = canonicalDomain(domStr);
+	  }
+
+	  /*
+	   * "The domain string and the string are identical. (Note that both the
+	   * domain string and the string will have been canonicalized to lower case at
+	   * this point)"
+	   */
+	  if (str == domStr) {
+	    return true;
+	  }
+
+	  /* "All of the following [three] conditions hold:" (order adjusted from the RFC) */
+
+	  /* "* The string is a host name (i.e., not an IP address)." */
+	  if (net.isIP(str)) {
+	    return false;
+	  }
+
+	  /* "* The domain string is a suffix of the string" */
+	  var idx = str.indexOf(domStr);
+	  if (idx <= 0) {
+	    return false; // it's a non-match (-1) or prefix (0)
+	  }
+
+	  // e.g "a.b.c".indexOf("b.c") === 2
+	  // 5 === 3+2
+	  if (str.length !== domStr.length + idx) { // it's not a suffix
+	    return false;
+	  }
+
+	  /* "* The last character of the string that is not included in the domain
+	  * string is a %x2E (".") character." */
+	  if (str.substr(idx-1,1) !== '.') {
+	    return false;
+	  }
+
+	  return true;
+	}
+
+
+	// RFC6265 S5.1.4 Paths and Path-Match
+
+	/*
+	 * "The user agent MUST use an algorithm equivalent to the following algorithm
+	 * to compute the default-path of a cookie:"
+	 *
+	 * Assumption: the path (and not query part or absolute uri) is passed in.
+	 */
+	function defaultPath(path) {
+	  // "2. If the uri-path is empty or if the first character of the uri-path is not
+	  // a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
+	  if (!path || path.substr(0,1) !== "/") {
+	    return "/";
+	  }
+
+	  // "3. If the uri-path contains no more than one %x2F ("/") character, output
+	  // %x2F ("/") and skip the remaining step."
+	  if (path === "/") {
+	    return path;
+	  }
+
+	  var rightSlash = path.lastIndexOf("/");
+	  if (rightSlash === 0) {
+	    return "/";
+	  }
+
+	  // "4. Output the characters of the uri-path from the first character up to,
+	  // but not including, the right-most %x2F ("/")."
+	  return path.slice(0, rightSlash);
+	}
+
+	function trimTerminator(str) {
+	  for (var t = 0; t < TERMINATORS.length; t++) {
+	    var terminatorIdx = str.indexOf(TERMINATORS[t]);
+	    if (terminatorIdx !== -1) {
+	      str = str.substr(0,terminatorIdx);
+	    }
+	  }
+
+	  return str;
+	}
+
+	function parseCookiePair(cookiePair, looseMode) {
+	  cookiePair = trimTerminator(cookiePair);
+
+	  var firstEq = cookiePair.indexOf('=');
+	  if (looseMode) {
+	    if (firstEq === 0) { // '=' is immediately at start
+	      cookiePair = cookiePair.substr(1);
+	      firstEq = cookiePair.indexOf('='); // might still need to split on '='
+	    }
+	  } else { // non-loose mode
+	    if (firstEq <= 0) { // no '=' or is at start
+	      return; // needs to have non-empty "cookie-name"
+	    }
+	  }
+
+	  var cookieName, cookieValue;
+	  if (firstEq <= 0) {
+	    cookieName = "";
+	    cookieValue = cookiePair.trim();
+	  } else {
+	    cookieName = cookiePair.substr(0, firstEq).trim();
+	    cookieValue = cookiePair.substr(firstEq+1).trim();
+	  }
+
+	  if (CONTROL_CHARS.test(cookieName) || CONTROL_CHARS.test(cookieValue)) {
+	    return;
+	  }
+
+	  var c = new Cookie();
+	  c.key = cookieName;
+	  c.value = cookieValue;
+	  return c;
+	}
+
+	function parse(str, options) {
+	  if (!options || typeof options !== 'object') {
+	    options = {};
+	  }
+	  str = str.trim();
+
+	  // We use a regex to parse the "name-value-pair" part of S5.2
+	  var firstSemi = str.indexOf(';'); // S5.2 step 1
+	  var cookiePair = (firstSemi === -1) ? str : str.substr(0, firstSemi);
+	  var c = parseCookiePair(cookiePair, !!options.loose);
+	  if (!c) {
+	    return;
+	  }
+
+	  if (firstSemi === -1) {
+	    return c;
+	  }
+
+	  // S5.2.3 "unparsed-attributes consist of the remainder of the set-cookie-string
+	  // (including the %x3B (";") in question)." plus later on in the same section
+	  // "discard the first ";" and trim".
+	  var unparsed = str.slice(firstSemi + 1).trim();
+
+	  // "If the unparsed-attributes string is empty, skip the rest of these
+	  // steps."
+	  if (unparsed.length === 0) {
+	    return c;
+	  }
+
+	  /*
+	   * S5.2 says that when looping over the items "[p]rocess the attribute-name
+	   * and attribute-value according to the requirements in the following
+	   * subsections" for every item.  Plus, for many of the individual attributes
+	   * in S5.3 it says to use the "attribute-value of the last attribute in the
+	   * cookie-attribute-list".  Therefore, in this implementation, we overwrite
+	   * the previous value.
+	   */
+	  var cookie_avs = unparsed.split(';');
+	  while (cookie_avs.length) {
+	    var av = cookie_avs.shift().trim();
+	    if (av.length === 0) { // happens if ";;" appears
+	      continue;
+	    }
+	    var av_sep = av.indexOf('=');
+	    var av_key, av_value;
+
+	    if (av_sep === -1) {
+	      av_key = av;
+	      av_value = null;
+	    } else {
+	      av_key = av.substr(0,av_sep);
+	      av_value = av.substr(av_sep+1);
+	    }
+
+	    av_key = av_key.trim().toLowerCase();
+
+	    if (av_value) {
+	      av_value = av_value.trim();
+	    }
+
+	    switch(av_key) {
+	    case 'expires': // S5.2.1
+	      if (av_value) {
+	        var exp = parseDate(av_value);
+	        // "If the attribute-value failed to parse as a cookie date, ignore the
+	        // cookie-av."
+	        if (exp) {
+	          // over and underflow not realistically a concern: V8's getTime() seems to
+	          // store something larger than a 32-bit time_t (even with 32-bit node)
+	          c.expires = exp;
+	        }
+	      }
+	      break;
+
+	    case 'max-age': // S5.2.2
+	      if (av_value) {
+	        // "If the first character of the attribute-value is not a DIGIT or a "-"
+	        // character ...[or]... If the remainder of attribute-value contains a
+	        // non-DIGIT character, ignore the cookie-av."
+	        if (/^-?[0-9]+$/.test(av_value)) {
+	          var delta = parseInt(av_value, 10);
+	          // "If delta-seconds is less than or equal to zero (0), let expiry-time
+	          // be the earliest representable date and time."
+	          c.setMaxAge(delta);
+	        }
+	      }
+	      break;
+
+	    case 'domain': // S5.2.3
+	      // "If the attribute-value is empty, the behavior is undefined.  However,
+	      // the user agent SHOULD ignore the cookie-av entirely."
+	      if (av_value) {
+	        // S5.2.3 "Let cookie-domain be the attribute-value without the leading %x2E
+	        // (".") character."
+	        var domain = av_value.trim().replace(/^\./, '');
+	        if (domain) {
+	          // "Convert the cookie-domain to lower case."
+	          c.domain = domain.toLowerCase();
+	        }
+	      }
+	      break;
+
+	    case 'path': // S5.2.4
+	      /*
+	       * "If the attribute-value is empty or if the first character of the
+	       * attribute-value is not %x2F ("/"):
+	       *   Let cookie-path be the default-path.
+	       * Otherwise:
+	       *   Let cookie-path be the attribute-value."
+	       *
+	       * We'll represent the default-path as null since it depends on the
+	       * context of the parsing.
+	       */
+	      c.path = av_value && av_value[0] === "/" ? av_value : null;
+	      break;
+
+	    case 'secure': // S5.2.5
+	      /*
+	       * "If the attribute-name case-insensitively matches the string "Secure",
+	       * the user agent MUST append an attribute to the cookie-attribute-list
+	       * with an attribute-name of Secure and an empty attribute-value."
+	       */
+	      c.secure = true;
+	      break;
+
+	    case 'httponly': // S5.2.6 -- effectively the same as 'secure'
+	      c.httpOnly = true;
+	      break;
+
+	    default:
+	      c.extensions = c.extensions || [];
+	      c.extensions.push(av);
+	      break;
+	    }
+	  }
+
+	  return c;
+	}
+
+	// avoid the V8 deoptimization monster!
+	function jsonParse(str) {
+	  var obj;
+	  try {
+	    obj = JSON.parse(str);
+	  } catch (e) {
+	    return e;
+	  }
+	  return obj;
+	}
+
+	function fromJSON(str) {
+	  if (!str) {
+	    return null;
+	  }
+
+	  var obj;
+	  if (typeof str === 'string') {
+	    obj = jsonParse(str);
+	    if (obj instanceof Error) {
+	      return null;
+	    }
+	  } else {
+	    // assume it's an Object
+	    obj = str;
+	  }
+
+	  var c = new Cookie();
+	  for (var i=0; i<Cookie.serializableProperties.length; i++) {
+	    var prop = Cookie.serializableProperties[i];
+	    if (obj[prop] === undefined ||
+	        obj[prop] === Cookie.prototype[prop])
+	    {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (obj[prop] === null) {
+	        c[prop] = null;
+	      } else {
+	        c[prop] = obj[prop] == "Infinity" ?
+	          "Infinity" : new Date(obj[prop]);
+	      }
+	    } else {
+	      c[prop] = obj[prop];
+	    }
+	  }
+
+	  return c;
+	}
+
+	/* Section 5.4 part 2:
+	 * "*  Cookies with longer paths are listed before cookies with
+	 *     shorter paths.
+	 *
+	 *  *  Among cookies that have equal-length path fields, cookies with
+	 *     earlier creation-times are listed before cookies with later
+	 *     creation-times."
+	 */
+
+	function cookieCompare(a,b) {
+	  var cmp = 0;
+
+	  // descending for length: b CMP a
+	  var aPathLen = a.path ? a.path.length : 0;
+	  var bPathLen = b.path ? b.path.length : 0;
+	  cmp = bPathLen - aPathLen;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // ascending for time: a CMP b
+	  var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
+	  var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
+	  cmp = aTime - bTime;
+	  if (cmp !== 0) {
+	    return cmp;
+	  }
+
+	  // break ties for the same millisecond (precision of JavaScript's clock)
+	  cmp = a.creationIndex - b.creationIndex;
+
+	  return cmp;
+	}
+
+	// Gives the permutation of all possible pathMatch()es of a given path. The
+	// array is in longest-to-shortest order.  Handy for indexing.
+	function permutePath(path) {
+	  if (path === '/') {
+	    return ['/'];
+	  }
+	  if (path.lastIndexOf('/') === path.length-1) {
+	    path = path.substr(0,path.length-1);
+	  }
+	  var permutations = [path];
+	  while (path.length > 1) {
+	    var lindex = path.lastIndexOf('/');
+	    if (lindex === 0) {
+	      break;
+	    }
+	    path = path.substr(0,lindex);
+	    permutations.push(path);
+	  }
+	  permutations.push('/');
+	  return permutations;
+	}
+
+	function getCookieContext(url) {
+	  if (url instanceof Object) {
+	    return url;
+	  }
+	  // NOTE: decodeURI will throw on malformed URIs (see GH-32).
+	  // Therefore, we will just skip decoding for such URIs.
+	  try {
+	    url = decodeURI(url);
+	  }
+	  catch(err) {
+	    // Silently swallow error
+	  }
+
+	  return urlParse(url);
+	}
+
+	function Cookie(options) {
+	  options = options || {};
+
+	  Object.keys(options).forEach(function(prop) {
+	    if (Cookie.prototype.hasOwnProperty(prop) &&
+	        Cookie.prototype[prop] !== options[prop] &&
+	        prop.substr(0,1) !== '_')
+	    {
+	      this[prop] = options[prop];
+	    }
+	  }, this);
+
+	  this.creation = this.creation || new Date();
+
+	  // used to break creation ties in cookieCompare():
+	  Object.defineProperty(this, 'creationIndex', {
+	    configurable: false,
+	    enumerable: false, // important for assert.deepEqual checks
+	    writable: true,
+	    value: ++Cookie.cookiesCreated
+	  });
+	}
+
+	Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
+	Cookie.parse = parse;
+	Cookie.fromJSON = fromJSON;
+
+	Cookie.prototype.key = "";
+	Cookie.prototype.value = "";
+
+	// the order in which the RFC has them:
+	Cookie.prototype.expires = "Infinity"; // coerces to literal Infinity
+	Cookie.prototype.maxAge = null; // takes precedence over expires for TTL
+	Cookie.prototype.domain = null;
+	Cookie.prototype.path = null;
+	Cookie.prototype.secure = false;
+	Cookie.prototype.httpOnly = false;
+	Cookie.prototype.extensions = null;
+
+	// set by the CookieJar:
+	Cookie.prototype.hostOnly = null; // boolean when set
+	Cookie.prototype.pathIsDefault = null; // boolean when set
+	Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
+	Cookie.prototype.lastAccessed = null; // Date when set
+	Object.defineProperty(Cookie.prototype, 'creationIndex', {
+	  configurable: true,
+	  enumerable: false,
+	  writable: true,
+	  value: 0
+	});
+
+	Cookie.serializableProperties = Object.keys(Cookie.prototype)
+	  .filter(function(prop) {
+	    return !(
+	      Cookie.prototype[prop] instanceof Function ||
+	      prop === 'creationIndex' ||
+	      prop.substr(0,1) === '_'
+	    );
+	  });
+
+	Cookie.prototype.inspect = function inspect() {
+	  var now = Date.now();
+	  return 'Cookie="'+this.toString() +
+	    '; hostOnly='+(this.hostOnly != null ? this.hostOnly : '?') +
+	    '; aAge='+(this.lastAccessed ? (now-this.lastAccessed.getTime())+'ms' : '?') +
+	    '; cAge='+(this.creation ? (now-this.creation.getTime())+'ms' : '?') +
+	    '"';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  Cookie.prototype[util.inspect.custom] = Cookie.prototype.inspect;
+	}
+
+	Cookie.prototype.toJSON = function() {
+	  var obj = {};
+
+	  var props = Cookie.serializableProperties;
+	  for (var i=0; i<props.length; i++) {
+	    var prop = props[i];
+	    if (this[prop] === Cookie.prototype[prop]) {
+	      continue; // leave as prototype default
+	    }
+
+	    if (prop === 'expires' ||
+	        prop === 'creation' ||
+	        prop === 'lastAccessed')
+	    {
+	      if (this[prop] === null) {
+	        obj[prop] = null;
+	      } else {
+	        obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+	          "Infinity" : this[prop].toISOString();
+	      }
+	    } else if (prop === 'maxAge') {
+	      if (this[prop] !== null) {
+	        // again, intentionally not ===
+	        obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+	          this[prop].toString() : this[prop];
+	      }
+	    } else {
+	      if (this[prop] !== Cookie.prototype[prop]) {
+	        obj[prop] = this[prop];
+	      }
+	    }
+	  }
+
+	  return obj;
+	};
+
+	Cookie.prototype.clone = function() {
+	  return fromJSON(this.toJSON());
+	};
+
+	Cookie.prototype.validate = function validate() {
+	  if (!COOKIE_OCTETS.test(this.value)) {
+	    return false;
+	  }
+	  if (this.expires != Infinity && !(this.expires instanceof Date) && !parseDate(this.expires)) {
+	    return false;
+	  }
+	  if (this.maxAge != null && this.maxAge <= 0) {
+	    return false; // "Max-Age=" non-zero-digit *DIGIT
+	  }
+	  if (this.path != null && !PATH_VALUE.test(this.path)) {
+	    return false;
+	  }
+
+	  var cdomain = this.cdomain();
+	  if (cdomain) {
+	    if (cdomain.match(/\.$/)) {
+	      return false; // S4.1.2.3 suggests that this is bad. domainMatch() tests confirm this
+	    }
+	    var suffix = pubsuffix.getPublicSuffix(cdomain);
+	    if (suffix == null) { // it's a public suffix
+	      return false;
+	    }
+	  }
+	  return true;
+	};
+
+	Cookie.prototype.setExpires = function setExpires(exp) {
+	  if (exp instanceof Date) {
+	    this.expires = exp;
+	  } else {
+	    this.expires = parseDate(exp) || "Infinity";
+	  }
+	};
+
+	Cookie.prototype.setMaxAge = function setMaxAge(age) {
+	  if (age === Infinity || age === -Infinity) {
+	    this.maxAge = age.toString(); // so JSON.stringify() works
+	  } else {
+	    this.maxAge = age;
+	  }
+	};
+
+	// gives Cookie header format
+	Cookie.prototype.cookieString = function cookieString() {
+	  var val = this.value;
+	  if (val == null) {
+	    val = '';
+	  }
+	  if (this.key === '') {
+	    return val;
+	  }
+	  return this.key+'='+val;
+	};
+
+	// gives Set-Cookie header format
+	Cookie.prototype.toString = function toString() {
+	  var str = this.cookieString();
+
+	  if (this.expires != Infinity) {
+	    if (this.expires instanceof Date) {
+	      str += '; Expires='+formatDate(this.expires);
+	    } else {
+	      str += '; Expires='+this.expires;
+	    }
+	  }
+
+	  if (this.maxAge != null && this.maxAge != Infinity) {
+	    str += '; Max-Age='+this.maxAge;
+	  }
+
+	  if (this.domain && !this.hostOnly) {
+	    str += '; Domain='+this.domain;
+	  }
+	  if (this.path) {
+	    str += '; Path='+this.path;
+	  }
+
+	  if (this.secure) {
+	    str += '; Secure';
+	  }
+	  if (this.httpOnly) {
+	    str += '; HttpOnly';
+	  }
+	  if (this.extensions) {
+	    this.extensions.forEach(function(ext) {
+	      str += '; '+ext;
+	    });
+	  }
+
+	  return str;
+	};
+
+	// TTL() partially replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	// S5.3 says to give the "latest representable date" for which we use Infinity
+	// For "expired" we use 0
+	Cookie.prototype.TTL = function TTL(now) {
+	  /* RFC6265 S4.1.2.2 If a cookie has both the Max-Age and the Expires
+	   * attribute, the Max-Age attribute has precedence and controls the
+	   * expiration date of the cookie.
+	   * (Concurs with S5.3 step 3)
+	   */
+	  if (this.maxAge != null) {
+	    return this.maxAge<=0 ? 0 : this.maxAge*1000;
+	  }
+
+	  var expires = this.expires;
+	  if (expires != Infinity) {
+	    if (!(expires instanceof Date)) {
+	      expires = parseDate(expires) || Infinity;
+	    }
+
+	    if (expires == Infinity) {
+	      return Infinity;
+	    }
+
+	    return expires.getTime() - (now || Date.now());
+	  }
+
+	  return Infinity;
+	};
+
+	// expiryTime() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere)
+	Cookie.prototype.expiryTime = function expiryTime(now) {
+	  if (this.maxAge != null) {
+	    var relativeTo = now || this.creation || new Date();
+	    var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
+	    return relativeTo.getTime() + age;
+	  }
+
+	  if (this.expires == Infinity) {
+	    return Infinity;
+	  }
+	  return this.expires.getTime();
+	};
+
+	// expiryDate() replaces the "expiry-time" parts of S5.3 step 3 (setCookie()
+	// elsewhere), except it returns a Date
+	Cookie.prototype.expiryDate = function expiryDate(now) {
+	  var millisec = this.expiryTime(now);
+	  if (millisec == Infinity) {
+	    return new Date(MAX_TIME);
+	  } else if (millisec == -Infinity) {
+	    return new Date(MIN_TIME);
+	  } else {
+	    return new Date(millisec);
+	  }
+	};
+
+	// This replaces the "persistent-flag" parts of S5.3 step 3
+	Cookie.prototype.isPersistent = function isPersistent() {
+	  return (this.maxAge != null || this.expires != Infinity);
+	};
+
+	// Mostly S5.1.2 and S5.2.3:
+	Cookie.prototype.cdomain =
+	Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
+	  if (this.domain == null) {
+	    return null;
+	  }
+	  return canonicalDomain(this.domain);
+	};
+
+	function CookieJar(store, options) {
+	  if (typeof options === "boolean") {
+	    options = {rejectPublicSuffixes: options};
+	  } else if (options == null) {
+	    options = {};
+	  }
+	  if (options.rejectPublicSuffixes != null) {
+	    this.rejectPublicSuffixes = options.rejectPublicSuffixes;
+	  }
+	  if (options.looseMode != null) {
+	    this.enableLooseMode = options.looseMode;
+	  }
+
+	  if (!store) {
+	    store = new MemoryCookieStore();
+	  }
+	  this.store = store;
+	}
+	CookieJar.prototype.store = null;
+	CookieJar.prototype.rejectPublicSuffixes = true;
+	CookieJar.prototype.enableLooseMode = false;
+	var CAN_BE_SYNC = [];
+
+	CAN_BE_SYNC.push('setCookie');
+	CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
+	  var err;
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var loose = this.enableLooseMode;
+	  if (options.loose != null) {
+	    loose = options.loose;
+	  }
+
+	  // S5.3 step 1
+	  if (!(cookie instanceof Cookie)) {
+	    cookie = Cookie.parse(cookie, { loose: loose });
+	  }
+	  if (!cookie) {
+	    err = new Error("Cookie failed to parse");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  // S5.3 step 2
+	  var now = options.now || new Date(); // will assign later to save effort in the face of errors
+
+	  // S5.3 step 3: NOOP; persistent-flag and expiry-time is handled by getCookie()
+
+	  // S5.3 step 4: NOOP; domain is null by default
+
+	  // S5.3 step 5: public suffixes
+	  if (this.rejectPublicSuffixes && cookie.domain) {
+	    var suffix = pubsuffix.getPublicSuffix(cookie.cdomain());
+	    if (suffix == null) { // e.g. "com"
+	      err = new Error("Cookie has domain set to a public suffix");
+	      return cb(options.ignoreError ? null : err);
+	    }
+	  }
+
+	  // S5.3 step 6:
+	  if (cookie.domain) {
+	    if (!domainMatch(host, cookie.cdomain(), false)) {
+	      err = new Error("Cookie not in this host's domain. Cookie:"+cookie.cdomain()+" Request:"+host);
+	      return cb(options.ignoreError ? null : err);
+	    }
+
+	    if (cookie.hostOnly == null) { // don't reset if already set
+	      cookie.hostOnly = false;
+	    }
+
+	  } else {
+	    cookie.hostOnly = true;
+	    cookie.domain = host;
+	  }
+
+	  //S5.2.4 If the attribute-value is empty or if the first character of the
+	  //attribute-value is not %x2F ("/"):
+	  //Let cookie-path be the default-path.
+	  if (!cookie.path || cookie.path[0] !== '/') {
+	    cookie.path = defaultPath(context.pathname);
+	    cookie.pathIsDefault = true;
+	  }
+
+	  // S5.3 step 8: NOOP; secure attribute
+	  // S5.3 step 9: NOOP; httpOnly attribute
+
+	  // S5.3 step 10
+	  if (options.http === false && cookie.httpOnly) {
+	    err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
+	    return cb(options.ignoreError ? null : err);
+	  }
+
+	  var store = this.store;
+
+	  if (!store.updateCookie) {
+	    store.updateCookie = function(oldCookie, newCookie, cb) {
+	      this.putCookie(newCookie, cb);
+	    };
+	  }
+
+	  function withCookie(err, oldCookie) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    var next = function(err) {
+	      if (err) {
+	        return cb(err);
+	      } else {
+	        cb(null, cookie);
+	      }
+	    };
+
+	    if (oldCookie) {
+	      // S5.3 step 11 - "If the cookie store contains a cookie with the same name,
+	      // domain, and path as the newly created cookie:"
+	      if (options.http === false && oldCookie.httpOnly) { // step 11.2
+	        err = new Error("old Cookie is HttpOnly and this isn't an HTTP API");
+	        return cb(options.ignoreError ? null : err);
+	      }
+	      cookie.creation = oldCookie.creation; // step 11.3
+	      cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
+	      cookie.lastAccessed = now;
+	      // Step 11.4 (delete cookie) is implied by just setting the new one:
+	      store.updateCookie(oldCookie, cookie, next); // step 12
+
+	    } else {
+	      cookie.creation = cookie.lastAccessed = now;
+	      store.putCookie(cookie, next); // step 12
+	    }
+	  }
+
+	  store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie);
+	};
+
+	// RFC6365 S5.4
+	CAN_BE_SYNC.push('getCookies');
+	CookieJar.prototype.getCookies = function(url, options, cb) {
+	  var context = getCookieContext(url);
+	  if (options instanceof Function) {
+	    cb = options;
+	    options = {};
+	  }
+
+	  var host = canonicalDomain(context.hostname);
+	  var path = context.pathname || '/';
+
+	  var secure = options.secure;
+	  if (secure == null && context.protocol &&
+	      (context.protocol == 'https:' || context.protocol == 'wss:'))
+	  {
+	    secure = true;
+	  }
+
+	  var http = options.http;
+	  if (http == null) {
+	    http = true;
+	  }
+
+	  var now = options.now || Date.now();
+	  var expireCheck = options.expire !== false;
+	  var allPaths = !!options.allPaths;
+	  var store = this.store;
+
+	  function matchingCookie(c) {
+	    // "Either:
+	    //   The cookie's host-only-flag is true and the canonicalized
+	    //   request-host is identical to the cookie's domain.
+	    // Or:
+	    //   The cookie's host-only-flag is false and the canonicalized
+	    //   request-host domain-matches the cookie's domain."
+	    if (c.hostOnly) {
+	      if (c.domain != host) {
+	        return false;
+	      }
+	    } else {
+	      if (!domainMatch(host, c.domain, false)) {
+	        return false;
+	      }
+	    }
+
+	    // "The request-uri's path path-matches the cookie's path."
+	    if (!allPaths && !pathMatch(path, c.path)) {
+	      return false;
+	    }
+
+	    // "If the cookie's secure-only-flag is true, then the request-uri's
+	    // scheme must denote a "secure" protocol"
+	    if (c.secure && !secure) {
+	      return false;
+	    }
+
+	    // "If the cookie's http-only-flag is true, then exclude the cookie if the
+	    // cookie-string is being generated for a "non-HTTP" API"
+	    if (c.httpOnly && !http) {
+	      return false;
+	    }
+
+	    // deferred from S5.3
+	    // non-RFC: allow retention of expired cookies by choice
+	    if (expireCheck && c.expiryTime() <= now) {
+	      store.removeCookie(c.domain, c.path, c.key, function(){}); // result ignored
+	      return false;
+	    }
+
+	    return true;
+	  }
+
+	  store.findCookies(host, allPaths ? null : path, function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    cookies = cookies.filter(matchingCookie);
+
+	    // sorting of S5.4 part 2
+	    if (options.sort !== false) {
+	      cookies = cookies.sort(cookieCompare);
+	    }
+
+	    // S5.4 part 3
+	    var now = new Date();
+	    cookies.forEach(function(c) {
+	      c.lastAccessed = now;
+	    });
+	    // TODO persist lastAccessed
+
+	    cb(null,cookies);
+	  });
+	};
+
+	CAN_BE_SYNC.push('getCookieString');
+	CookieJar.prototype.getCookieString = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies
+	        .sort(cookieCompare)
+	        .map(function(c){
+	          return c.cookieString();
+	        })
+	        .join('; '));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('getSetCookieStrings');
+	CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
+	  var args = Array.prototype.slice.call(arguments,0);
+	  var cb = args.pop();
+	  var next = function(err,cookies) {
+	    if (err) {
+	      cb(err);
+	    } else {
+	      cb(null, cookies.map(function(c){
+	        return c.toString();
+	      }));
+	    }
+	  };
+	  args.push(next);
+	  this.getCookies.apply(this,args);
+	};
+
+	CAN_BE_SYNC.push('serialize');
+	CookieJar.prototype.serialize = function(cb) {
+	  var type = this.store.constructor.name;
+	  if (type === 'Object') {
+	    type = null;
+	  }
+
+	  // update README.md "Serialization Format" if you change this, please!
+	  var serialized = {
+	    // The version of tough-cookie that serialized this jar. Generally a good
+	    // practice since future versions can make data import decisions based on
+	    // known past behavior. When/if this matters, use `semver`.
+	    version: 'tough-cookie@'+VERSION,
+
+	    // add the store type, to make humans happy:
+	    storeType: type,
+
+	    // CookieJar configuration:
+	    rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+	    // this gets filled from getAllCookies:
+	    cookies: []
+	  };
+
+	  if (!(this.store.getAllCookies &&
+	        typeof this.store.getAllCookies === 'function'))
+	  {
+	    return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+	  }
+
+	  this.store.getAllCookies(function(err,cookies) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    serialized.cookies = cookies.map(function(cookie) {
+	      // convert to serialized 'raw' cookies
+	      cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+	      // Remove the index so new ones get assigned during deserialization
+	      delete cookie.creationIndex;
+
+	      return cookie;
+	    });
+
+	    return cb(null, serialized);
+	  });
+	};
+
+	// well-known name that JSON.stringify calls
+	CookieJar.prototype.toJSON = function() {
+	  return this.serializeSync();
+	};
+
+	// use the class method CookieJar.deserialize instead of calling this directly
+	CAN_BE_SYNC.push('_importCookies');
+	CookieJar.prototype._importCookies = function(serialized, cb) {
+	  var jar = this;
+	  var cookies = serialized.cookies;
+	  if (!cookies || !Array.isArray(cookies)) {
+	    return cb(new Error('serialized jar has no cookies array'));
+	  }
+	  cookies = cookies.slice(); // do not modify the original
+
+	  function putNext(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+
+	    if (!cookies.length) {
+	      return cb(err, jar);
+	    }
+
+	    var cookie;
+	    try {
+	      cookie = fromJSON(cookies.shift());
+	    } catch (e) {
+	      return cb(e);
+	    }
+
+	    if (cookie === null) {
+	      return putNext(null); // skip this cookie
+	    }
+
+	    jar.store.putCookie(cookie, putNext);
+	  }
+
+	  putNext();
+	};
+
+	CookieJar.deserialize = function(strOrObj, store, cb) {
+	  if (arguments.length !== 3) {
+	    // store is optional
+	    cb = store;
+	    store = null;
+	  }
+
+	  var serialized;
+	  if (typeof strOrObj === 'string') {
+	    serialized = jsonParse(strOrObj);
+	    if (serialized instanceof Error) {
+	      return cb(serialized);
+	    }
+	  } else {
+	    serialized = strOrObj;
+	  }
+
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+	  jar._importCookies(serialized, function(err) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    cb(null, jar);
+	  });
+	};
+
+	CookieJar.deserializeSync = function(strOrObj, store) {
+	  var serialized = typeof strOrObj === 'string' ?
+	    JSON.parse(strOrObj) : strOrObj;
+	  var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+	  // catch this mistake early:
+	  if (!jar.store.synchronous) {
+	    throw new Error('CookieJar store is not synchronous; use async API instead.');
+	  }
+
+	  jar._importCookiesSync(serialized);
+	  return jar;
+	};
+	CookieJar.fromJSON = CookieJar.deserializeSync;
+
+	CAN_BE_SYNC.push('clone');
+	CookieJar.prototype.clone = function(newStore, cb) {
+	  if (arguments.length === 1) {
+	    cb = newStore;
+	    newStore = null;
+	  }
+
+	  this.serialize(function(err,serialized) {
+	    if (err) {
+	      return cb(err);
+	    }
+	    CookieJar.deserialize(newStore, serialized, cb);
+	  });
+	};
+
+	// Use a closure to provide a true imperative API for synchronous stores.
+	function syncWrap(method) {
+	  return function() {
+	    if (!this.store.synchronous) {
+	      throw new Error('CookieJar store is not synchronous; use async API instead.');
+	    }
+
+	    var args = Array.prototype.slice.call(arguments);
+	    var syncErr, syncResult;
+	    args.push(function syncCb(err, result) {
+	      syncErr = err;
+	      syncResult = result;
+	    });
+	    this[method].apply(this, args);
+
+	    if (syncErr) {
+	      throw syncErr;
+	    }
+	    return syncResult;
+	  };
+	}
+
+	// wrap all declared CAN_BE_SYNC methods in the sync wrapper
+	CAN_BE_SYNC.forEach(function(method) {
+	  CookieJar.prototype[method+'Sync'] = syncWrap(method);
+	});
+
+	exports.CookieJar = CookieJar;
+	exports.Cookie = Cookie;
+	exports.Store = Store;
+	exports.MemoryCookieStore = MemoryCookieStore;
+	exports.parseDate = parseDate;
+	exports.formatDate = formatDate;
+	exports.parse = parse;
+	exports.fromJSON = fromJSON;
+	exports.domainMatch = domainMatch;
+	exports.defaultPath = defaultPath;
+	exports.pathMatch = pathMatch;
+	exports.getPublicSuffix = pubsuffix.getPublicSuffix;
+	exports.cookieCompare = cookieCompare;
+	exports.permuteDomain = __webpack_require__(19).permuteDomain;
+	exports.permutePath = permutePath;
+	exports.canonicalDomain = canonicalDomain;
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports) {
+
+	/*
+	* Tests if a given ip or host string is a valid IPv4 or IPv6 address.
+	* Regex found at: https://stackoverflow.com/questions/9208814/validate-ipv4-ipv6-and-hostname
+	*/
+
+	var patternIPv4 = /^\s*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\s*$/g;
+	var patternIPv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/g;
+
+	function isIPv4(hostOrIp) {
+	  return hostOrIp.match(patternIPv4) ? true : false;
+	}
+
+	function isIPv6(hostOrIp) {
+	  return hostOrIp.match(patternIPv6) ? true : false;
+	}
+
+	function isIP(hostOrIp) {
+	  if (isIPv4(hostOrIp)) {
+	    return 4;
+	  }
+
+	  if (isIPv6(hostOrIp)) {
+	    return 6;
+	  }
+
+	  return 0;
+	}
+
+	module.exports = {
+	  isIPv4: isIPv4,
+	  isIPv6: isIPv6,
+	  isIP: isIP
+	};
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var punycode = __webpack_require__(3);
+	var util = __webpack_require__(5);
+
+	exports.parse = urlParse;
+	exports.resolve = urlResolve;
+	exports.resolveObject = urlResolveObject;
+	exports.format = urlFormat;
+
+	exports.Url = Url;
+
+	function Url() {
+	  this.protocol = null;
+	  this.slashes = null;
+	  this.auth = null;
+	  this.host = null;
+	  this.port = null;
+	  this.hostname = null;
+	  this.hash = null;
+	  this.search = null;
+	  this.query = null;
+	  this.pathname = null;
+	  this.path = null;
+	  this.href = null;
+	}
+
+	// Reference: RFC 3986, RFC 1808, RFC 2396
+
+	// define these here so at least they only have to be
+	// compiled once on the first module load.
+	var protocolPattern = /^([a-z0-9.+-]+:)/i,
+	    portPattern = /:[0-9]*$/,
+
+	    // Special case for a simple path URL
+	    simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+
+	    // RFC 2396: characters reserved for delimiting URLs.
+	    // We actually just auto-escape these.
+	    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+
+	    // RFC 2396: characters not allowed for various reasons.
+	    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+
+	    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
+	    autoEscape = ['\''].concat(unwise),
+	    // Characters that are never ever allowed in a hostname.
+	    // Note that any invalid chars are also handled, but these
+	    // are the ones that are *expected* to be seen, so we fast-path
+	    // them.
+	    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+	    hostEndingChars = ['/', '?', '#'],
+	    hostnameMaxLen = 255,
+	    hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+	    hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+	    // protocols that can allow "unsafe" and "unwise" chars.
+	    unsafeProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that never have a hostname.
+	    hostlessProtocol = {
+	      'javascript': true,
+	      'javascript:': true
+	    },
+	    // protocols that always contain a // bit.
+	    slashedProtocol = {
+	      'http': true,
+	      'https': true,
+	      'ftp': true,
+	      'gopher': true,
+	      'file': true,
+	      'http:': true,
+	      'https:': true,
+	      'ftp:': true,
+	      'gopher:': true,
+	      'file:': true
+	    },
+	    querystring = __webpack_require__(6);
+
+	function urlParse(url, parseQueryString, slashesDenoteHost) {
+	  if (url && util.isObject(url) && url instanceof Url) return url;
+
+	  var u = new Url;
+	  u.parse(url, parseQueryString, slashesDenoteHost);
+	  return u;
+	}
+
+	Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+	  if (!util.isString(url)) {
+	    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+	  }
+
+	  // Copy chrome, IE, opera backslash-handling behavior.
+	  // Back slashes before the query string get converted to forward slashes
+	  // See: https://code.google.com/p/chromium/issues/detail?id=25916
+	  var queryIndex = url.indexOf('?'),
+	      splitter =
+	          (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+	      uSplit = url.split(splitter),
+	      slashRegex = /\\/g;
+	  uSplit[0] = uSplit[0].replace(slashRegex, '/');
+	  url = uSplit.join(splitter);
+
+	  var rest = url;
+
+	  // trim before proceeding.
+	  // This is to support parse stuff like "  http://foo.com  \n"
+	  rest = rest.trim();
+
+	  if (!slashesDenoteHost && url.split('#').length === 1) {
+	    // Try fast path regexp
+	    var simplePath = simplePathPattern.exec(rest);
+	    if (simplePath) {
+	      this.path = rest;
+	      this.href = rest;
+	      this.pathname = simplePath[1];
+	      if (simplePath[2]) {
+	        this.search = simplePath[2];
+	        if (parseQueryString) {
+	          this.query = querystring.parse(this.search.substr(1));
+	        } else {
+	          this.query = this.search.substr(1);
+	        }
+	      } else if (parseQueryString) {
+	        this.search = '';
+	        this.query = {};
+	      }
+	      return this;
+	    }
+	  }
+
+	  var proto = protocolPattern.exec(rest);
+	  if (proto) {
+	    proto = proto[0];
+	    var lowerProto = proto.toLowerCase();
+	    this.protocol = lowerProto;
+	    rest = rest.substr(proto.length);
+	  }
+
+	  // figure out if it's got a host
+	  // user@server is *always* interpreted as a hostname, and url
+	  // resolution will treat //foo/bar as host=foo,path=bar because that's
+	  // how the browser resolves relative URLs.
+	  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+	    var slashes = rest.substr(0, 2) === '//';
+	    if (slashes && !(proto && hostlessProtocol[proto])) {
+	      rest = rest.substr(2);
+	      this.slashes = true;
+	    }
+	  }
+
+	  if (!hostlessProtocol[proto] &&
+	      (slashes || (proto && !slashedProtocol[proto]))) {
+
+	    // there's a hostname.
+	    // the first instance of /, ?, ;, or # ends the host.
+	    //
+	    // If there is an @ in the hostname, then non-host chars *are* allowed
+	    // to the left of the last @ sign, unless some host-ending character
+	    // comes *before* the @-sign.
+	    // URLs are obnoxious.
+	    //
+	    // ex:
+	    // http://a@b@c/ => user:a@b host:c
+	    // http://a@b?@c => user:a host:c path:/?@c
+
+	    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+	    // Review our test case against browsers more comprehensively.
+
+	    // find the first instance of any hostEndingChars
+	    var hostEnd = -1;
+	    for (var i = 0; i < hostEndingChars.length; i++) {
+	      var hec = rest.indexOf(hostEndingChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+
+	    // at this point, either we have an explicit point where the
+	    // auth portion cannot go past, or the last @ char is the decider.
+	    var auth, atSign;
+	    if (hostEnd === -1) {
+	      // atSign can be anywhere.
+	      atSign = rest.lastIndexOf('@');
+	    } else {
+	      // atSign must be in auth portion.
+	      // http://a@b/c@d => host:b auth:a path:/c@d
+	      atSign = rest.lastIndexOf('@', hostEnd);
+	    }
+
+	    // Now we have a portion which is definitely the auth.
+	    // Pull that off.
+	    if (atSign !== -1) {
+	      auth = rest.slice(0, atSign);
+	      rest = rest.slice(atSign + 1);
+	      this.auth = decodeURIComponent(auth);
+	    }
+
+	    // the host is the remaining to the left of the first non-host char
+	    hostEnd = -1;
+	    for (var i = 0; i < nonHostChars.length; i++) {
+	      var hec = rest.indexOf(nonHostChars[i]);
+	      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+	        hostEnd = hec;
+	    }
+	    // if we still have not hit it, then the entire thing is a host.
+	    if (hostEnd === -1)
+	      hostEnd = rest.length;
+
+	    this.host = rest.slice(0, hostEnd);
+	    rest = rest.slice(hostEnd);
+
+	    // pull out port.
+	    this.parseHost();
+
+	    // we've indicated that there is a hostname,
+	    // so even if it's empty, it has to be present.
+	    this.hostname = this.hostname || '';
+
+	    // if hostname begins with [ and ends with ]
+	    // assume that it's an IPv6 address.
+	    var ipv6Hostname = this.hostname[0] === '[' &&
+	        this.hostname[this.hostname.length - 1] === ']';
+
+	    // validate a little.
+	    if (!ipv6Hostname) {
+	      var hostparts = this.hostname.split(/\./);
+	      for (var i = 0, l = hostparts.length; i < l; i++) {
+	        var part = hostparts[i];
+	        if (!part) continue;
+	        if (!part.match(hostnamePartPattern)) {
+	          var newpart = '';
+	          for (var j = 0, k = part.length; j < k; j++) {
+	            if (part.charCodeAt(j) > 127) {
+	              // we replace non-ASCII char with a temporary placeholder
+	              // we need this to make sure size of hostname is not
+	              // broken by replacing non-ASCII by nothing
+	              newpart += 'x';
+	            } else {
+	              newpart += part[j];
+	            }
+	          }
+	          // we test again with ASCII char only
+	          if (!newpart.match(hostnamePartPattern)) {
+	            var validParts = hostparts.slice(0, i);
+	            var notHost = hostparts.slice(i + 1);
+	            var bit = part.match(hostnamePartStart);
+	            if (bit) {
+	              validParts.push(bit[1]);
+	              notHost.unshift(bit[2]);
+	            }
+	            if (notHost.length) {
+	              rest = '/' + notHost.join('.') + rest;
+	            }
+	            this.hostname = validParts.join('.');
+	            break;
+	          }
+	        }
+	      }
+	    }
+
+	    if (this.hostname.length > hostnameMaxLen) {
+	      this.hostname = '';
+	    } else {
+	      // hostnames are always lower case.
+	      this.hostname = this.hostname.toLowerCase();
+	    }
+
+	    if (!ipv6Hostname) {
+	      // IDNA Support: Returns a punycoded representation of "domain".
+	      // It only converts parts of the domain name that
+	      // have non-ASCII characters, i.e. it doesn't matter if
+	      // you call it with a domain that already is ASCII-only.
+	      this.hostname = punycode.toASCII(this.hostname);
+	    }
+
+	    var p = this.port ? ':' + this.port : '';
+	    var h = this.hostname || '';
+	    this.host = h + p;
+	    this.href += this.host;
+
+	    // strip [ and ] from the hostname
+	    // the host field still retains them, though
+	    if (ipv6Hostname) {
+	      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+	      if (rest[0] !== '/') {
+	        rest = '/' + rest;
+	      }
+	    }
+	  }
+
+	  // now rest is set to the post-host stuff.
+	  // chop off any delim chars.
+	  if (!unsafeProtocol[lowerProto]) {
+
+	    // First, make 100% sure that any "autoEscape" chars get
+	    // escaped, even if encodeURIComponent doesn't think they
+	    // need to be.
+	    for (var i = 0, l = autoEscape.length; i < l; i++) {
+	      var ae = autoEscape[i];
+	      if (rest.indexOf(ae) === -1)
+	        continue;
+	      var esc = encodeURIComponent(ae);
+	      if (esc === ae) {
+	        esc = escape(ae);
+	      }
+	      rest = rest.split(ae).join(esc);
+	    }
+	  }
+
+
+	  // chop off from the tail first.
+	  var hash = rest.indexOf('#');
+	  if (hash !== -1) {
+	    // got a fragment string.
+	    this.hash = rest.substr(hash);
+	    rest = rest.slice(0, hash);
+	  }
+	  var qm = rest.indexOf('?');
+	  if (qm !== -1) {
+	    this.search = rest.substr(qm);
+	    this.query = rest.substr(qm + 1);
+	    if (parseQueryString) {
+	      this.query = querystring.parse(this.query);
+	    }
+	    rest = rest.slice(0, qm);
+	  } else if (parseQueryString) {
+	    // no query string, but parseQueryString still requested
+	    this.search = '';
+	    this.query = {};
+	  }
+	  if (rest) this.pathname = rest;
+	  if (slashedProtocol[lowerProto] &&
+	      this.hostname && !this.pathname) {
+	    this.pathname = '/';
+	  }
+
+	  //to support http.request
+	  if (this.pathname || this.search) {
+	    var p = this.pathname || '';
+	    var s = this.search || '';
+	    this.path = p + s;
+	  }
+
+	  // finally, reconstruct the href based on what has been validated.
+	  this.href = this.format();
+	  return this;
+	};
+
+	// format a parsed object into a url string
+	function urlFormat(obj) {
+	  // ensure it's an object, and not a string url.
+	  // If it's an obj, this is a no-op.
+	  // this way, you can call url_format() on strings
+	  // to clean up potentially wonky urls.
+	  if (util.isString(obj)) obj = urlParse(obj);
+	  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+	  return obj.format();
+	}
+
+	Url.prototype.format = function() {
+	  var auth = this.auth || '';
+	  if (auth) {
+	    auth = encodeURIComponent(auth);
+	    auth = auth.replace(/%3A/i, ':');
+	    auth += '@';
+	  }
+
+	  var protocol = this.protocol || '',
+	      pathname = this.pathname || '',
+	      hash = this.hash || '',
+	      host = false,
+	      query = '';
+
+	  if (this.host) {
+	    host = auth + this.host;
+	  } else if (this.hostname) {
+	    host = auth + (this.hostname.indexOf(':') === -1 ?
+	        this.hostname :
+	        '[' + this.hostname + ']');
+	    if (this.port) {
+	      host += ':' + this.port;
+	    }
+	  }
+
+	  if (this.query &&
+	      util.isObject(this.query) &&
+	      Object.keys(this.query).length) {
+	    query = querystring.stringify(this.query);
+	  }
+
+	  var search = this.search || (query && ('?' + query)) || '';
+
+	  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+	  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
+	  // unless they had them to begin with.
+	  if (this.slashes ||
+	      (!protocol || slashedProtocol[protocol]) && host !== false) {
+	    host = '//' + (host || '');
+	    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+	  } else if (!host) {
+	    host = '';
+	  }
+
+	  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+	  if (search && search.charAt(0) !== '?') search = '?' + search;
+
+	  pathname = pathname.replace(/[?#]/g, function(match) {
+	    return encodeURIComponent(match);
+	  });
+	  search = search.replace('#', '%23');
+
+	  return protocol + host + pathname + search + hash;
+	};
+
+	function urlResolve(source, relative) {
+	  return urlParse(source, false, true).resolve(relative);
+	}
+
+	Url.prototype.resolve = function(relative) {
+	  return this.resolveObject(urlParse(relative, false, true)).format();
+	};
+
+	function urlResolveObject(source, relative) {
+	  if (!source) return relative;
+	  return urlParse(source, false, true).resolveObject(relative);
+	}
+
+	Url.prototype.resolveObject = function(relative) {
+	  if (util.isString(relative)) {
+	    var rel = new Url();
+	    rel.parse(relative, false, true);
+	    relative = rel;
+	  }
+
+	  var result = new Url();
+	  var tkeys = Object.keys(this);
+	  for (var tk = 0; tk < tkeys.length; tk++) {
+	    var tkey = tkeys[tk];
+	    result[tkey] = this[tkey];
+	  }
+
+	  // hash is always overridden, no matter what.
+	  // even href="" will remove it.
+	  result.hash = relative.hash;
+
+	  // if the relative url is empty, then there's nothing left to do here.
+	  if (relative.href === '') {
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // hrefs like //foo/bar always cut to the protocol.
+	  if (relative.slashes && !relative.protocol) {
+	    // take everything except the protocol from relative
+	    var rkeys = Object.keys(relative);
+	    for (var rk = 0; rk < rkeys.length; rk++) {
+	      var rkey = rkeys[rk];
+	      if (rkey !== 'protocol')
+	        result[rkey] = relative[rkey];
+	    }
+
+	    //urlParse appends trailing / to urls like http://www.example.com
+	    if (slashedProtocol[result.protocol] &&
+	        result.hostname && !result.pathname) {
+	      result.path = result.pathname = '/';
+	    }
+
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (relative.protocol && relative.protocol !== result.protocol) {
+	    // if it's a known url protocol, then changing
+	    // the protocol does weird things
+	    // first, if it's not file:, then we MUST have a host,
+	    // and if there was a path
+	    // to begin with, then we MUST have a path.
+	    // if it is file:, then the host is dropped,
+	    // because that's known to be hostless.
+	    // anything else is assumed to be absolute.
+	    if (!slashedProtocol[relative.protocol]) {
+	      var keys = Object.keys(relative);
+	      for (var v = 0; v < keys.length; v++) {
+	        var k = keys[v];
+	        result[k] = relative[k];
+	      }
+	      result.href = result.format();
+	      return result;
+	    }
+
+	    result.protocol = relative.protocol;
+	    if (!relative.host && !hostlessProtocol[relative.protocol]) {
+	      var relPath = (relative.pathname || '').split('/');
+	      while (relPath.length && !(relative.host = relPath.shift()));
+	      if (!relative.host) relative.host = '';
+	      if (!relative.hostname) relative.hostname = '';
+	      if (relPath[0] !== '') relPath.unshift('');
+	      if (relPath.length < 2) relPath.unshift('');
+	      result.pathname = relPath.join('/');
+	    } else {
+	      result.pathname = relative.pathname;
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    result.host = relative.host || '';
+	    result.auth = relative.auth;
+	    result.hostname = relative.hostname || relative.host;
+	    result.port = relative.port;
+	    // to support http.request
+	    if (result.pathname || result.search) {
+	      var p = result.pathname || '';
+	      var s = result.search || '';
+	      result.path = p + s;
+	    }
+	    result.slashes = result.slashes || relative.slashes;
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+	      isRelAbs = (
+	          relative.host ||
+	          relative.pathname && relative.pathname.charAt(0) === '/'
+	      ),
+	      mustEndAbs = (isRelAbs || isSourceAbs ||
+	                    (result.host && relative.pathname)),
+	      removeAllDots = mustEndAbs,
+	      srcPath = result.pathname && result.pathname.split('/') || [],
+	      relPath = relative.pathname && relative.pathname.split('/') || [],
+	      psychotic = result.protocol && !slashedProtocol[result.protocol];
+
+	  // if the url is a non-slashed url, then relative
+	  // links like ../.. should be able
+	  // to crawl up to the hostname, as well.  This is strange.
+	  // result.protocol has already been set by now.
+	  // Later on, put the first path part into the host field.
+	  if (psychotic) {
+	    result.hostname = '';
+	    result.port = null;
+	    if (result.host) {
+	      if (srcPath[0] === '') srcPath[0] = result.host;
+	      else srcPath.unshift(result.host);
+	    }
+	    result.host = '';
+	    if (relative.protocol) {
+	      relative.hostname = null;
+	      relative.port = null;
+	      if (relative.host) {
+	        if (relPath[0] === '') relPath[0] = relative.host;
+	        else relPath.unshift(relative.host);
+	      }
+	      relative.host = null;
+	    }
+	    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+	  }
+
+	  if (isRelAbs) {
+	    // it's absolute.
+	    result.host = (relative.host || relative.host === '') ?
+	                  relative.host : result.host;
+	    result.hostname = (relative.hostname || relative.hostname === '') ?
+	                      relative.hostname : result.hostname;
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    srcPath = relPath;
+	    // fall through to the dot-handling below.
+	  } else if (relPath.length) {
+	    // it's relative
+	    // throw away the existing file, and take the new path instead.
+	    if (!srcPath) srcPath = [];
+	    srcPath.pop();
+	    srcPath = srcPath.concat(relPath);
+	    result.search = relative.search;
+	    result.query = relative.query;
+	  } else if (!util.isNullOrUndefined(relative.search)) {
+	    // just pull out the search.
+	    // like href='?foo'.
+	    // Put this after the other two cases because it simplifies the booleans
+	    if (psychotic) {
+	      result.hostname = result.host = srcPath.shift();
+	      //occationaly the auth can get stuck only in host
+	      //this especially happens in cases like
+	      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	      var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                       result.host.split('@') : false;
+	      if (authInHost) {
+	        result.auth = authInHost.shift();
+	        result.host = result.hostname = authInHost.shift();
+	      }
+	    }
+	    result.search = relative.search;
+	    result.query = relative.query;
+	    //to support http.request
+	    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	      result.path = (result.pathname ? result.pathname : '') +
+	                    (result.search ? result.search : '');
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  if (!srcPath.length) {
+	    // no path at all.  easy.
+	    // we've already handled the other stuff above.
+	    result.pathname = null;
+	    //to support http.request
+	    if (result.search) {
+	      result.path = '/' + result.search;
+	    } else {
+	      result.path = null;
+	    }
+	    result.href = result.format();
+	    return result;
+	  }
+
+	  // if a url ENDs in . or .., then it must get a trailing slash.
+	  // however, if it ends in anything else non-slashy,
+	  // then it must NOT get a trailing slash.
+	  var last = srcPath.slice(-1)[0];
+	  var hasTrailingSlash = (
+	      (result.host || relative.host || srcPath.length > 1) &&
+	      (last === '.' || last === '..') || last === '');
+
+	  // strip single dots, resolve double dots to parent dir
+	  // if the path tries to go above the root, `up` ends up > 0
+	  var up = 0;
+	  for (var i = srcPath.length; i >= 0; i--) {
+	    last = srcPath[i];
+	    if (last === '.') {
+	      srcPath.splice(i, 1);
+	    } else if (last === '..') {
+	      srcPath.splice(i, 1);
+	      up++;
+	    } else if (up) {
+	      srcPath.splice(i, 1);
+	      up--;
+	    }
+	  }
+
+	  // if the path is allowed to go above the root, restore leading ..s
+	  if (!mustEndAbs && !removeAllDots) {
+	    for (; up--; up) {
+	      srcPath.unshift('..');
+	    }
+	  }
+
+	  if (mustEndAbs && srcPath[0] !== '' &&
+	      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+	    srcPath.unshift('');
+	  }
+
+	  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+	    srcPath.push('');
+	  }
+
+	  var isAbsolute = srcPath[0] === '' ||
+	      (srcPath[0] && srcPath[0].charAt(0) === '/');
+
+	  // put the host back
+	  if (psychotic) {
+	    result.hostname = result.host = isAbsolute ? '' :
+	                                    srcPath.length ? srcPath.shift() : '';
+	    //occationaly the auth can get stuck only in host
+	    //this especially happens in cases like
+	    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+	    var authInHost = result.host && result.host.indexOf('@') > 0 ?
+	                     result.host.split('@') : false;
+	    if (authInHost) {
+	      result.auth = authInHost.shift();
+	      result.host = result.hostname = authInHost.shift();
+	    }
+	  }
+
+	  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+
+	  if (mustEndAbs && !isAbsolute) {
+	    srcPath.unshift('');
+	  }
+
+	  if (!srcPath.length) {
+	    result.pathname = null;
+	    result.path = null;
+	  } else {
+	    result.pathname = srcPath.join('/');
+	  }
+
+	  //to support request.http
+	  if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+	    result.path = (result.pathname ? result.pathname : '') +
+	                  (result.search ? result.search : '');
+	  }
+	  result.auth = relative.auth || result.auth;
+	  result.slashes = result.slashes || relative.slashes;
+	  result.href = result.format();
+	  return result;
+	};
+
+	Url.prototype.parseHost = function() {
+	  var host = this.host;
+	  var port = portPattern.exec(host);
+	  if (port) {
+	    port = port[0];
+	    if (port !== ':') {
+	      this.port = port.substr(1);
+	    }
+	    host = host.substr(0, host.length - port.length);
+	  }
+	  if (host) this.hostname = host;
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * http://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.3.2',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else { // in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else { // in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+	module.exports = function(module) {

+		if(!module.webpackPolyfill) {

+			module.deprecate = function() {};

+			module.paths = [];

+			// module.parent = undefined by default

+			module.children = [];

+			module.webpackPolyfill = 1;

+		}

+		return module;

+	}

+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+	'use strict';
+
+	module.exports = {
+	  isString: function(arg) {
+	    return typeof(arg) === 'string';
+	  },
+	  isObject: function(arg) {
+	    return typeof(arg) === 'object' && arg !== null;
+	  },
+	  isNull: function(arg) {
+	    return arg === null;
+	  },
+	  isNullOrUndefined: function(arg) {
+	    return arg == null;
+	  }
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	exports.decode = exports.parse = __webpack_require__(7);
+	exports.encode = exports.stringify = __webpack_require__(8);
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	// If obj.hasOwnProperty has been overridden, then calling
+	// obj.hasOwnProperty(prop) will break.
+	// See: https://github.com/joyent/node/issues/1707
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	module.exports = function(qs, sep, eq, options) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  var obj = {};
+
+	  if (typeof qs !== 'string' || qs.length === 0) {
+	    return obj;
+	  }
+
+	  var regexp = /\+/g;
+	  qs = qs.split(sep);
+
+	  var maxKeys = 1000;
+	  if (options && typeof options.maxKeys === 'number') {
+	    maxKeys = options.maxKeys;
+	  }
+
+	  var len = qs.length;
+	  // maxKeys <= 0 means that we should not limit keys count
+	  if (maxKeys > 0 && len > maxKeys) {
+	    len = maxKeys;
+	  }
+
+	  for (var i = 0; i < len; ++i) {
+	    var x = qs[i].replace(regexp, '%20'),
+	        idx = x.indexOf(eq),
+	        kstr, vstr, k, v;
+
+	    if (idx >= 0) {
+	      kstr = x.substr(0, idx);
+	      vstr = x.substr(idx + 1);
+	    } else {
+	      kstr = x;
+	      vstr = '';
+	    }
+
+	    k = decodeURIComponent(kstr);
+	    v = decodeURIComponent(vstr);
+
+	    if (!hasOwnProperty(obj, k)) {
+	      obj[k] = v;
+	    } else if (Array.isArray(obj[k])) {
+	      obj[k].push(v);
+	    } else {
+	      obj[k] = [obj[k], v];
+	    }
+	  }
+
+	  return obj;
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	'use strict';
+
+	var stringifyPrimitive = function(v) {
+	  switch (typeof v) {
+	    case 'string':
+	      return v;
+
+	    case 'boolean':
+	      return v ? 'true' : 'false';
+
+	    case 'number':
+	      return isFinite(v) ? v : '';
+
+	    default:
+	      return '';
+	  }
+	};
+
+	module.exports = function(obj, sep, eq, name) {
+	  sep = sep || '&';
+	  eq = eq || '=';
+	  if (obj === null) {
+	    obj = undefined;
+	  }
+
+	  if (typeof obj === 'object') {
+	    return Object.keys(obj).map(function(k) {
+	      var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+	      if (Array.isArray(obj[k])) {
+	        return obj[k].map(function(v) {
+	          return ks + encodeURIComponent(stringifyPrimitive(v));
+	        }).join(sep);
+	      } else {
+	        return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+	      }
+	    }).join(sep);
+
+	  }
+
+	  if (!name) return '';
+	  return encodeURIComponent(stringifyPrimitive(name)) + eq +
+	         encodeURIComponent(stringifyPrimitive(obj));
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
+	//
+	// Permission is hereby granted, free of charge, to any person obtaining a
+	// copy of this software and associated documentation files (the
+	// "Software"), to deal in the Software without restriction, including
+	// without limitation the rights to use, copy, modify, merge, publish,
+	// distribute, sublicense, and/or sell copies of the Software, and to permit
+	// persons to whom the Software is furnished to do so, subject to the
+	// following conditions:
+	//
+	// The above copyright notice and this permission notice shall be included
+	// in all copies or substantial portions of the Software.
+	//
+	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+	// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+	// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+	// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+	// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+	var formatRegExp = /%[sdj%]/g;
+	exports.format = function(f) {
+	  if (!isString(f)) {
+	    var objects = [];
+	    for (var i = 0; i < arguments.length; i++) {
+	      objects.push(inspect(arguments[i]));
+	    }
+	    return objects.join(' ');
+	  }
+
+	  var i = 1;
+	  var args = arguments;
+	  var len = args.length;
+	  var str = String(f).replace(formatRegExp, function(x) {
+	    if (x === '%%') return '%';
+	    if (i >= len) return x;
+	    switch (x) {
+	      case '%s': return String(args[i++]);
+	      case '%d': return Number(args[i++]);
+	      case '%j':
+	        try {
+	          return JSON.stringify(args[i++]);
+	        } catch (_) {
+	          return '[Circular]';
+	        }
+	      default:
+	        return x;
+	    }
+	  });
+	  for (var x = args[i]; i < len; x = args[++i]) {
+	    if (isNull(x) || !isObject(x)) {
+	      str += ' ' + x;
+	    } else {
+	      str += ' ' + inspect(x);
+	    }
+	  }
+	  return str;
+	};
+
+
+	// Mark that a method should not be used.
+	// Returns a modified function which warns once by default.
+	// If --no-deprecation is set, then it is a no-op.
+	exports.deprecate = function(fn, msg) {
+	  // Allow for deprecating things in the process of starting up.
+	  if (isUndefined(global.process)) {
+	    return function() {
+	      return exports.deprecate(fn, msg).apply(this, arguments);
+	    };
+	  }
+
+	  if (process.noDeprecation === true) {
+	    return fn;
+	  }
+
+	  var warned = false;
+	  function deprecated() {
+	    if (!warned) {
+	      if (process.throwDeprecation) {
+	        throw new Error(msg);
+	      } else if (process.traceDeprecation) {
+	        console.trace(msg);
+	      } else {
+	        console.error(msg);
+	      }
+	      warned = true;
+	    }
+	    return fn.apply(this, arguments);
+	  }
+
+	  return deprecated;
+	};
+
+
+	var debugs = {};
+	var debugEnviron;
+	exports.debuglog = function(set) {
+	  if (isUndefined(debugEnviron))
+	    debugEnviron = process.env.NODE_DEBUG || '';
+	  set = set.toUpperCase();
+	  if (!debugs[set]) {
+	    if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
+	      var pid = process.pid;
+	      debugs[set] = function() {
+	        var msg = exports.format.apply(exports, arguments);
+	        console.error('%s %d: %s', set, pid, msg);
+	      };
+	    } else {
+	      debugs[set] = function() {};
+	    }
+	  }
+	  return debugs[set];
+	};
+
+
+	/**
+	 * Echos the value of a value. Trys to print the value out
+	 * in the best way possible given the different types.
+	 *
+	 * @param {Object} obj The object to print out.
+	 * @param {Object} opts Optional options object that alters the output.
+	 */
+	/* legacy: obj, showHidden, depth, colors*/
+	function inspect(obj, opts) {
+	  // default options
+	  var ctx = {
+	    seen: [],
+	    stylize: stylizeNoColor
+	  };
+	  // legacy...
+	  if (arguments.length >= 3) ctx.depth = arguments[2];
+	  if (arguments.length >= 4) ctx.colors = arguments[3];
+	  if (isBoolean(opts)) {
+	    // legacy...
+	    ctx.showHidden = opts;
+	  } else if (opts) {
+	    // got an "options" object
+	    exports._extend(ctx, opts);
+	  }
+	  // set default options
+	  if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
+	  if (isUndefined(ctx.depth)) ctx.depth = 2;
+	  if (isUndefined(ctx.colors)) ctx.colors = false;
+	  if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
+	  if (ctx.colors) ctx.stylize = stylizeWithColor;
+	  return formatValue(ctx, obj, ctx.depth);
+	}
+	exports.inspect = inspect;
+
+
+	// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
+	inspect.colors = {
+	  'bold' : [1, 22],
+	  'italic' : [3, 23],
+	  'underline' : [4, 24],
+	  'inverse' : [7, 27],
+	  'white' : [37, 39],
+	  'grey' : [90, 39],
+	  'black' : [30, 39],
+	  'blue' : [34, 39],
+	  'cyan' : [36, 39],
+	  'green' : [32, 39],
+	  'magenta' : [35, 39],
+	  'red' : [31, 39],
+	  'yellow' : [33, 39]
+	};
+
+	// Don't use 'blue' not visible on cmd.exe
+	inspect.styles = {
+	  'special': 'cyan',
+	  'number': 'yellow',
+	  'boolean': 'yellow',
+	  'undefined': 'grey',
+	  'null': 'bold',
+	  'string': 'green',
+	  'date': 'magenta',
+	  // "name": intentionally not styling
+	  'regexp': 'red'
+	};
+
+
+	function stylizeWithColor(str, styleType) {
+	  var style = inspect.styles[styleType];
+
+	  if (style) {
+	    return '\u001b[' + inspect.colors[style][0] + 'm' + str +
+	           '\u001b[' + inspect.colors[style][1] + 'm';
+	  } else {
+	    return str;
+	  }
+	}
+
+
+	function stylizeNoColor(str, styleType) {
+	  return str;
+	}
+
+
+	function arrayToHash(array) {
+	  var hash = {};
+
+	  array.forEach(function(val, idx) {
+	    hash[val] = true;
+	  });
+
+	  return hash;
+	}
+
+
+	function formatValue(ctx, value, recurseTimes) {
+	  // Provide a hook for user-specified inspect functions.
+	  // Check that value is an object with an inspect function on it
+	  if (ctx.customInspect &&
+	      value &&
+	      isFunction(value.inspect) &&
+	      // Filter out the util module, it's inspect function is special
+	      value.inspect !== exports.inspect &&
+	      // Also filter out any prototype objects using the circular check.
+	      !(value.constructor && value.constructor.prototype === value)) {
+	    var ret = value.inspect(recurseTimes, ctx);
+	    if (!isString(ret)) {
+	      ret = formatValue(ctx, ret, recurseTimes);
+	    }
+	    return ret;
+	  }
+
+	  // Primitive types cannot have properties
+	  var primitive = formatPrimitive(ctx, value);
+	  if (primitive) {
+	    return primitive;
+	  }
+
+	  // Look up the keys of the object.
+	  var keys = Object.keys(value);
+	  var visibleKeys = arrayToHash(keys);
+
+	  if (ctx.showHidden) {
+	    keys = Object.getOwnPropertyNames(value);
+	  }
+
+	  // IE doesn't make error fields non-enumerable
+	  // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
+	  if (isError(value)
+	      && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
+	    return formatError(value);
+	  }
+
+	  // Some type of object without properties can be shortcutted.
+	  if (keys.length === 0) {
+	    if (isFunction(value)) {
+	      var name = value.name ? ': ' + value.name : '';
+	      return ctx.stylize('[Function' + name + ']', 'special');
+	    }
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    }
+	    if (isDate(value)) {
+	      return ctx.stylize(Date.prototype.toString.call(value), 'date');
+	    }
+	    if (isError(value)) {
+	      return formatError(value);
+	    }
+	  }
+
+	  var base = '', array = false, braces = ['{', '}'];
+
+	  // Make Array say that they are Array
+	  if (isArray(value)) {
+	    array = true;
+	    braces = ['[', ']'];
+	  }
+
+	  // Make functions say that they are functions
+	  if (isFunction(value)) {
+	    var n = value.name ? ': ' + value.name : '';
+	    base = ' [Function' + n + ']';
+	  }
+
+	  // Make RegExps say that they are RegExps
+	  if (isRegExp(value)) {
+	    base = ' ' + RegExp.prototype.toString.call(value);
+	  }
+
+	  // Make dates with properties first say the date
+	  if (isDate(value)) {
+	    base = ' ' + Date.prototype.toUTCString.call(value);
+	  }
+
+	  // Make error with message first say the error
+	  if (isError(value)) {
+	    base = ' ' + formatError(value);
+	  }
+
+	  if (keys.length === 0 && (!array || value.length == 0)) {
+	    return braces[0] + base + braces[1];
+	  }
+
+	  if (recurseTimes < 0) {
+	    if (isRegExp(value)) {
+	      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
+	    } else {
+	      return ctx.stylize('[Object]', 'special');
+	    }
+	  }
+
+	  ctx.seen.push(value);
+
+	  var output;
+	  if (array) {
+	    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
+	  } else {
+	    output = keys.map(function(key) {
+	      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
+	    });
+	  }
+
+	  ctx.seen.pop();
+
+	  return reduceToSingleString(output, base, braces);
+	}
+
+
+	function formatPrimitive(ctx, value) {
+	  if (isUndefined(value))
+	    return ctx.stylize('undefined', 'undefined');
+	  if (isString(value)) {
+	    var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
+	                                             .replace(/'/g, "\\'")
+	                                             .replace(/\\"/g, '"') + '\'';
+	    return ctx.stylize(simple, 'string');
+	  }
+	  if (isNumber(value))
+	    return ctx.stylize('' + value, 'number');
+	  if (isBoolean(value))
+	    return ctx.stylize('' + value, 'boolean');
+	  // For some reason typeof null is "object", so special case here.
+	  if (isNull(value))
+	    return ctx.stylize('null', 'null');
+	}
+
+
+	function formatError(value) {
+	  return '[' + Error.prototype.toString.call(value) + ']';
+	}
+
+
+	function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
+	  var output = [];
+	  for (var i = 0, l = value.length; i < l; ++i) {
+	    if (hasOwnProperty(value, String(i))) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          String(i), true));
+	    } else {
+	      output.push('');
+	    }
+	  }
+	  keys.forEach(function(key) {
+	    if (!key.match(/^\d+$/)) {
+	      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
+	          key, true));
+	    }
+	  });
+	  return output;
+	}
+
+
+	function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
+	  var name, str, desc;
+	  desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
+	  if (desc.get) {
+	    if (desc.set) {
+	      str = ctx.stylize('[Getter/Setter]', 'special');
+	    } else {
+	      str = ctx.stylize('[Getter]', 'special');
+	    }
+	  } else {
+	    if (desc.set) {
+	      str = ctx.stylize('[Setter]', 'special');
+	    }
+	  }
+	  if (!hasOwnProperty(visibleKeys, key)) {
+	    name = '[' + key + ']';
+	  }
+	  if (!str) {
+	    if (ctx.seen.indexOf(desc.value) < 0) {
+	      if (isNull(recurseTimes)) {
+	        str = formatValue(ctx, desc.value, null);
+	      } else {
+	        str = formatValue(ctx, desc.value, recurseTimes - 1);
+	      }
+	      if (str.indexOf('\n') > -1) {
+	        if (array) {
+	          str = str.split('\n').map(function(line) {
+	            return '  ' + line;
+	          }).join('\n').substr(2);
+	        } else {
+	          str = '\n' + str.split('\n').map(function(line) {
+	            return '   ' + line;
+	          }).join('\n');
+	        }
+	      }
+	    } else {
+	      str = ctx.stylize('[Circular]', 'special');
+	    }
+	  }
+	  if (isUndefined(name)) {
+	    if (array && key.match(/^\d+$/)) {
+	      return str;
+	    }
+	    name = JSON.stringify('' + key);
+	    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
+	      name = name.substr(1, name.length - 2);
+	      name = ctx.stylize(name, 'name');
+	    } else {
+	      name = name.replace(/'/g, "\\'")
+	                 .replace(/\\"/g, '"')
+	                 .replace(/(^"|"$)/g, "'");
+	      name = ctx.stylize(name, 'string');
+	    }
+	  }
+
+	  return name + ': ' + str;
+	}
+
+
+	function reduceToSingleString(output, base, braces) {
+	  var numLinesEst = 0;
+	  var length = output.reduce(function(prev, cur) {
+	    numLinesEst++;
+	    if (cur.indexOf('\n') >= 0) numLinesEst++;
+	    return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
+	  }, 0);
+
+	  if (length > 60) {
+	    return braces[0] +
+	           (base === '' ? '' : base + '\n ') +
+	           ' ' +
+	           output.join(',\n  ') +
+	           ' ' +
+	           braces[1];
+	  }
+
+	  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
+	}
+
+
+	// NOTE: These type checking functions intentionally don't use `instanceof`
+	// because it is fragile and can be easily faked with `Object.create()`.
+	function isArray(ar) {
+	  return Array.isArray(ar);
+	}
+	exports.isArray = isArray;
+
+	function isBoolean(arg) {
+	  return typeof arg === 'boolean';
+	}
+	exports.isBoolean = isBoolean;
+
+	function isNull(arg) {
+	  return arg === null;
+	}
+	exports.isNull = isNull;
+
+	function isNullOrUndefined(arg) {
+	  return arg == null;
+	}
+	exports.isNullOrUndefined = isNullOrUndefined;
+
+	function isNumber(arg) {
+	  return typeof arg === 'number';
+	}
+	exports.isNumber = isNumber;
+
+	function isString(arg) {
+	  return typeof arg === 'string';
+	}
+	exports.isString = isString;
+
+	function isSymbol(arg) {
+	  return typeof arg === 'symbol';
+	}
+	exports.isSymbol = isSymbol;
+
+	function isUndefined(arg) {
+	  return arg === void 0;
+	}
+	exports.isUndefined = isUndefined;
+
+	function isRegExp(re) {
+	  return isObject(re) && objectToString(re) === '[object RegExp]';
+	}
+	exports.isRegExp = isRegExp;
+
+	function isObject(arg) {
+	  return typeof arg === 'object' && arg !== null;
+	}
+	exports.isObject = isObject;
+
+	function isDate(d) {
+	  return isObject(d) && objectToString(d) === '[object Date]';
+	}
+	exports.isDate = isDate;
+
+	function isError(e) {
+	  return isObject(e) &&
+	      (objectToString(e) === '[object Error]' || e instanceof Error);
+	}
+	exports.isError = isError;
+
+	function isFunction(arg) {
+	  return typeof arg === 'function';
+	}
+	exports.isFunction = isFunction;
+
+	function isPrimitive(arg) {
+	  return arg === null ||
+	         typeof arg === 'boolean' ||
+	         typeof arg === 'number' ||
+	         typeof arg === 'string' ||
+	         typeof arg === 'symbol' ||  // ES6 symbol
+	         typeof arg === 'undefined';
+	}
+	exports.isPrimitive = isPrimitive;
+
+	exports.isBuffer = __webpack_require__(11);
+
+	function objectToString(o) {
+	  return Object.prototype.toString.call(o);
+	}
+
+
+	function pad(n) {
+	  return n < 10 ? '0' + n.toString(10) : n.toString(10);
+	}
+
+
+	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
+	              'Oct', 'Nov', 'Dec'];
+
+	// 26 Feb 16:19:34
+	function timestamp() {
+	  var d = new Date();
+	  var time = [pad(d.getHours()),
+	              pad(d.getMinutes()),
+	              pad(d.getSeconds())].join(':');
+	  return [d.getDate(), months[d.getMonth()], time].join(' ');
+	}
+
+
+	// log is just a thin wrapper to console.log that prepends a timestamp
+	exports.log = function() {
+	  console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
+	};
+
+
+	/**
+	 * Inherit the prototype methods from one constructor into another.
+	 *
+	 * The Function.prototype.inherits from lang.js rewritten as a standalone
+	 * function (not on Function.prototype). NOTE: If this file is to be loaded
+	 * during bootstrapping this function needs to be rewritten using some native
+	 * functions as prototype setup using normal JavaScript does not work as
+	 * expected during bootstrapping (see mirror.js in r114903).
+	 *
+	 * @param {function} ctor Constructor function which needs to inherit the
+	 *     prototype.
+	 * @param {function} superCtor Constructor function to inherit prototype from.
+	 */
+	exports.inherits = __webpack_require__(12);
+
+	exports._extend = function(origin, add) {
+	  // Don't do anything if add isn't an object
+	  if (!add || !isObject(add)) return origin;
+
+	  var keys = Object.keys(add);
+	  var i = keys.length;
+	  while (i--) {
+	    origin[keys[i]] = add[keys[i]];
+	  }
+	  return origin;
+	};
+
+	function hasOwnProperty(obj, prop) {
+	  return Object.prototype.hasOwnProperty.call(obj, prop);
+	}
+
+	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(10)))
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+	// shim for using process in browser
+	var process = module.exports = {};
+
+	// cached from whatever global is present so that test runners that stub it
+	// don't break things.  But we need to wrap it in a try catch in case it is
+	// wrapped in strict mode code which doesn't define any globals.  It's inside a
+	// function because try/catches deoptimize in certain engines.
+
+	var cachedSetTimeout;
+	var cachedClearTimeout;
+
+	function defaultSetTimout() {
+	    throw new Error('setTimeout has not been defined');
+	}
+	function defaultClearTimeout () {
+	    throw new Error('clearTimeout has not been defined');
+	}
+	(function () {
+	    try {
+	        if (typeof setTimeout === 'function') {
+	            cachedSetTimeout = setTimeout;
+	        } else {
+	            cachedSetTimeout = defaultSetTimout;
+	        }
+	    } catch (e) {
+	        cachedSetTimeout = defaultSetTimout;
+	    }
+	    try {
+	        if (typeof clearTimeout === 'function') {
+	            cachedClearTimeout = clearTimeout;
+	        } else {
+	            cachedClearTimeout = defaultClearTimeout;
+	        }
+	    } catch (e) {
+	        cachedClearTimeout = defaultClearTimeout;
+	    }
+	} ())
+	function runTimeout(fun) {
+	    if (cachedSetTimeout === setTimeout) {
+	        //normal enviroments in sane situations
+	        return setTimeout(fun, 0);
+	    }
+	    // if setTimeout wasn't available but was latter defined
+	    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+	        cachedSetTimeout = setTimeout;
+	        return setTimeout(fun, 0);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedSetTimeout(fun, 0);
+	    } catch(e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+	            return cachedSetTimeout.call(null, fun, 0);
+	        } catch(e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+	            return cachedSetTimeout.call(this, fun, 0);
+	        }
+	    }
+
+
+	}
+	function runClearTimeout(marker) {
+	    if (cachedClearTimeout === clearTimeout) {
+	        //normal enviroments in sane situations
+	        return clearTimeout(marker);
+	    }
+	    // if clearTimeout wasn't available but was latter defined
+	    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+	        cachedClearTimeout = clearTimeout;
+	        return clearTimeout(marker);
+	    }
+	    try {
+	        // when when somebody has screwed with setTimeout but no I.E. maddness
+	        return cachedClearTimeout(marker);
+	    } catch (e){
+	        try {
+	            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
+	            return cachedClearTimeout.call(null, marker);
+	        } catch (e){
+	            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+	            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+	            return cachedClearTimeout.call(this, marker);
+	        }
+	    }
+
+
+
+	}
+	var queue = [];
+	var draining = false;
+	var currentQueue;
+	var queueIndex = -1;
+
+	function cleanUpNextTick() {
+	    if (!draining || !currentQueue) {
+	        return;
+	    }
+	    draining = false;
+	    if (currentQueue.length) {
+	        queue = currentQueue.concat(queue);
+	    } else {
+	        queueIndex = -1;
+	    }
+	    if (queue.length) {
+	        drainQueue();
+	    }
+	}
+
+	function drainQueue() {
+	    if (draining) {
+	        return;
+	    }
+	    var timeout = runTimeout(cleanUpNextTick);
+	    draining = true;
+
+	    var len = queue.length;
+	    while(len) {
+	        currentQueue = queue;
+	        queue = [];
+	        while (++queueIndex < len) {
+	            if (currentQueue) {
+	                currentQueue[queueIndex].run();
+	            }
+	        }
+	        queueIndex = -1;
+	        len = queue.length;
+	    }
+	    currentQueue = null;
+	    draining = false;
+	    runClearTimeout(timeout);
+	}
+
+	process.nextTick = function (fun) {
+	    var args = new Array(arguments.length - 1);
+	    if (arguments.length > 1) {
+	        for (var i = 1; i < arguments.length; i++) {
+	            args[i - 1] = arguments[i];
+	        }
+	    }
+	    queue.push(new Item(fun, args));
+	    if (queue.length === 1 && !draining) {
+	        runTimeout(drainQueue);
+	    }
+	};
+
+	// v8 likes predictible objects
+	function Item(fun, array) {
+	    this.fun = fun;
+	    this.array = array;
+	}
+	Item.prototype.run = function () {
+	    this.fun.apply(null, this.array);
+	};
+	process.title = 'browser';
+	process.browser = true;
+	process.env = {};
+	process.argv = [];
+	process.version = ''; // empty string to avoid regexp issues
+	process.versions = {};
+
+	function noop() {}
+
+	process.on = noop;
+	process.addListener = noop;
+	process.once = noop;
+	process.off = noop;
+	process.removeListener = noop;
+	process.removeAllListeners = noop;
+	process.emit = noop;
+	process.prependListener = noop;
+	process.prependOnceListener = noop;
+
+	process.listeners = function (name) { return [] }
+
+	process.binding = function (name) {
+	    throw new Error('process.binding is not supported');
+	};
+
+	process.cwd = function () { return '/' };
+	process.chdir = function (dir) {
+	    throw new Error('process.chdir is not supported');
+	};
+	process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	module.exports = function isBuffer(arg) {
+	  return arg && typeof arg === 'object'
+	    && typeof arg.copy === 'function'
+	    && typeof arg.fill === 'function'
+	    && typeof arg.readUInt8 === 'function';
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports) {
+
+	if (typeof Object.create === 'function') {
+	  // implementation from standard node.js 'util' module
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    ctor.prototype = Object.create(superCtor.prototype, {
+	      constructor: {
+	        value: ctor,
+	        enumerable: false,
+	        writable: true,
+	        configurable: true
+	      }
+	    });
+	  };
+	} else {
+	  // old school shim for old browsers
+	  module.exports = function inherits(ctor, superCtor) {
+	    ctor.super_ = superCtor
+	    var TempCtor = function () {}
+	    TempCtor.prototype = superCtor.prototype
+	    ctor.prototype = new TempCtor()
+	    ctor.prototype.constructor = ctor
+	  }
+	}
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2018, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var psl = __webpack_require__(14);
+
+	function getPublicSuffix(domain) {
+	  return psl.get(domain);
+	}
+
+	exports.getPublicSuffix = getPublicSuffix;
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*eslint no-var:0, prefer-arrow-callback: 0, object-shorthand: 0 */
+	'use strict';
+
+
+	var Punycode = __webpack_require__(15);
+
+
+	var internals = {};
+
+
+	//
+	// Read rules from file.
+	//
+	internals.rules = __webpack_require__(16).map(function (rule) {
+
+	  return {
+	    rule: rule,
+	    suffix: rule.replace(/^(\*\.|\!)/, ''),
+	    punySuffix: -1,
+	    wildcard: rule.charAt(0) === '*',
+	    exception: rule.charAt(0) === '!'
+	  };
+	});
+
+
+	//
+	// Check is given string ends with `suffix`.
+	//
+	internals.endsWith = function (str, suffix) {
+
+	  return str.indexOf(suffix, str.length - suffix.length) !== -1;
+	};
+
+
+	//
+	// Find rule for a given domain.
+	//
+	internals.findRule = function (domain) {
+
+	  var punyDomain = Punycode.toASCII(domain);
+	  return internals.rules.reduce(function (memo, rule) {
+
+	    if (rule.punySuffix === -1){
+	      rule.punySuffix = Punycode.toASCII(rule.suffix);
+	    }
+	    if (!internals.endsWith(punyDomain, '.' + rule.punySuffix) && punyDomain !== rule.punySuffix) {
+	      return memo;
+	    }
+	    // This has been commented out as it never seems to run. This is because
+	    // sub tlds always appear after their parents and we never find a shorter
+	    // match.
+	    //if (memo) {
+	    //  var memoSuffix = Punycode.toASCII(memo.suffix);
+	    //  if (memoSuffix.length >= punySuffix.length) {
+	    //    return memo;
+	    //  }
+	    //}
+	    return rule;
+	  }, null);
+	};
+
+
+	//
+	// Error codes and messages.
+	//
+	exports.errorCodes = {
+	  DOMAIN_TOO_SHORT: 'Domain name too short.',
+	  DOMAIN_TOO_LONG: 'Domain name too long. It should be no more than 255 chars.',
+	  LABEL_STARTS_WITH_DASH: 'Domain name label can not start with a dash.',
+	  LABEL_ENDS_WITH_DASH: 'Domain name label can not end with a dash.',
+	  LABEL_TOO_LONG: 'Domain name label should be at most 63 chars long.',
+	  LABEL_TOO_SHORT: 'Domain name label should be at least 1 character long.',
+	  LABEL_INVALID_CHARS: 'Domain name label can only contain alphanumeric characters or dashes.'
+	};
+
+
+	//
+	// Validate domain name and throw if not valid.
+	//
+	// From wikipedia:
+	//
+	// Hostnames are composed of series of labels concatenated with dots, as are all
+	// domain names. Each label must be between 1 and 63 characters long, and the
+	// entire hostname (including the delimiting dots) has a maximum of 255 chars.
+	//
+	// Allowed chars:
+	//
+	// * `a-z`
+	// * `0-9`
+	// * `-` but not as a starting or ending character
+	// * `.` as a separator for the textual portions of a domain name
+	//
+	// * http://en.wikipedia.org/wiki/Domain_name
+	// * http://en.wikipedia.org/wiki/Hostname
+	//
+	internals.validate = function (input) {
+
+	  // Before we can validate we need to take care of IDNs with unicode chars.
+	  var ascii = Punycode.toASCII(input);
+
+	  if (ascii.length < 1) {
+	    return 'DOMAIN_TOO_SHORT';
+	  }
+	  if (ascii.length > 255) {
+	    return 'DOMAIN_TOO_LONG';
+	  }
+
+	  // Check each part's length and allowed chars.
+	  var labels = ascii.split('.');
+	  var label;
+
+	  for (var i = 0; i < labels.length; ++i) {
+	    label = labels[i];
+	    if (!label.length) {
+	      return 'LABEL_TOO_SHORT';
+	    }
+	    if (label.length > 63) {
+	      return 'LABEL_TOO_LONG';
+	    }
+	    if (label.charAt(0) === '-') {
+	      return 'LABEL_STARTS_WITH_DASH';
+	    }
+	    if (label.charAt(label.length - 1) === '-') {
+	      return 'LABEL_ENDS_WITH_DASH';
+	    }
+	    if (!/^[a-z0-9\-]+$/.test(label)) {
+	      return 'LABEL_INVALID_CHARS';
+	    }
+	  }
+	};
+
+
+	//
+	// Public API
+	//
+
+
+	//
+	// Parse domain.
+	//
+	exports.parse = function (input) {
+
+	  if (typeof input !== 'string') {
+	    throw new TypeError('Domain name must be a string.');
+	  }
+
+	  // Force domain to lowercase.
+	  var domain = input.slice(0).toLowerCase();
+
+	  // Handle FQDN.
+	  // TODO: Simply remove trailing dot?
+	  if (domain.charAt(domain.length - 1) === '.') {
+	    domain = domain.slice(0, domain.length - 1);
+	  }
+
+	  // Validate and sanitise input.
+	  var error = internals.validate(domain);
+	  if (error) {
+	    return {
+	      input: input,
+	      error: {
+	        message: exports.errorCodes[error],
+	        code: error
+	      }
+	    };
+	  }
+
+	  var parsed = {
+	    input: input,
+	    tld: null,
+	    sld: null,
+	    domain: null,
+	    subdomain: null,
+	    listed: false
+	  };
+
+	  var domainParts = domain.split('.');
+
+	  // Non-Internet TLD
+	  if (domainParts[domainParts.length - 1] === 'local') {
+	    return parsed;
+	  }
+
+	  var handlePunycode = function () {
+
+	    if (!/xn--/.test(domain)) {
+	      return parsed;
+	    }
+	    if (parsed.domain) {
+	      parsed.domain = Punycode.toASCII(parsed.domain);
+	    }
+	    if (parsed.subdomain) {
+	      parsed.subdomain = Punycode.toASCII(parsed.subdomain);
+	    }
+	    return parsed;
+	  };
+
+	  var rule = internals.findRule(domain);
+
+	  // Unlisted tld.
+	  if (!rule) {
+	    if (domainParts.length < 2) {
+	      return parsed;
+	    }
+	    parsed.tld = domainParts.pop();
+	    parsed.sld = domainParts.pop();
+	    parsed.domain = [parsed.sld, parsed.tld].join('.');
+	    if (domainParts.length) {
+	      parsed.subdomain = domainParts.pop();
+	    }
+	    return handlePunycode();
+	  }
+
+	  // At this point we know the public suffix is listed.
+	  parsed.listed = true;
+
+	  var tldParts = rule.suffix.split('.');
+	  var privateParts = domainParts.slice(0, domainParts.length - tldParts.length);
+
+	  if (rule.exception) {
+	    privateParts.push(tldParts.shift());
+	  }
+
+	  parsed.tld = tldParts.join('.');
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  if (rule.wildcard) {
+	    tldParts.unshift(privateParts.pop());
+	    parsed.tld = tldParts.join('.');
+	  }
+
+	  if (!privateParts.length) {
+	    return handlePunycode();
+	  }
+
+	  parsed.sld = privateParts.pop();
+	  parsed.domain = [parsed.sld,  parsed.tld].join('.');
+
+	  if (privateParts.length) {
+	    parsed.subdomain = privateParts.join('.');
+	  }
+
+	  return handlePunycode();
+	};
+
+
+	//
+	// Get domain.
+	//
+	exports.get = function (domain) {
+
+	  if (!domain) {
+	    return null;
+	  }
+	  return exports.parse(domain).domain || null;
+	};
+
+
+	//
+	// Check whether domain belongs to a known public suffix.
+	//
+	exports.isValid = function (domain) {
+
+	  var parsed = exports.parse(domain);
+	  return Boolean(parsed.domain && parsed.listed);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.4.1 by @mathias */
+	;(function(root) {
+
+		/** Detect free variables */
+		var freeExports = typeof exports == 'object' && exports &&
+			!exports.nodeType && exports;
+		var freeModule = typeof module == 'object' && module &&
+			!module.nodeType && module;
+		var freeGlobal = typeof global == 'object' && global;
+		if (
+			freeGlobal.global === freeGlobal ||
+			freeGlobal.window === freeGlobal ||
+			freeGlobal.self === freeGlobal
+		) {
+			root = freeGlobal;
+		}
+
+		/**
+		 * The `punycode` object.
+		 * @name punycode
+		 * @type Object
+		 */
+		var punycode,
+
+		/** Highest positive signed 32-bit float value */
+		maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+
+		/** Bootstring parameters */
+		base = 36,
+		tMin = 1,
+		tMax = 26,
+		skew = 38,
+		damp = 700,
+		initialBias = 72,
+		initialN = 128, // 0x80
+		delimiter = '-', // '\x2D'
+
+		/** Regular expressions */
+		regexPunycode = /^xn--/,
+		regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+		regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+
+		/** Error messages */
+		errors = {
+			'overflow': 'Overflow: input needs wider integers to process',
+			'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+			'invalid-input': 'Invalid input'
+		},
+
+		/** Convenience shortcuts */
+		baseMinusTMin = base - tMin,
+		floor = Math.floor,
+		stringFromCharCode = String.fromCharCode,
+
+		/** Temporary variable */
+		key;
+
+		/*--------------------------------------------------------------------------*/
+
+		/**
+		 * A generic error utility function.
+		 * @private
+		 * @param {String} type The error type.
+		 * @returns {Error} Throws a `RangeError` with the applicable error message.
+		 */
+		function error(type) {
+			throw new RangeError(errors[type]);
+		}
+
+		/**
+		 * A generic `Array#map` utility function.
+		 * @private
+		 * @param {Array} array The array to iterate over.
+		 * @param {Function} callback The function that gets called for every array
+		 * item.
+		 * @returns {Array} A new array of values returned by the callback function.
+		 */
+		function map(array, fn) {
+			var length = array.length;
+			var result = [];
+			while (length--) {
+				result[length] = fn(array[length]);
+			}
+			return result;
+		}
+
+		/**
+		 * A simple `Array#map`-like wrapper to work with domain name strings or email
+		 * addresses.
+		 * @private
+		 * @param {String} domain The domain name or email address.
+		 * @param {Function} callback The function that gets called for every
+		 * character.
+		 * @returns {Array} A new string of characters returned by the callback
+		 * function.
+		 */
+		function mapDomain(string, fn) {
+			var parts = string.split('@');
+			var result = '';
+			if (parts.length > 1) {
+				// In email addresses, only the domain name should be punycoded. Leave
+				// the local part (i.e. everything up to `@`) intact.
+				result = parts[0] + '@';
+				string = parts[1];
+			}
+			// Avoid `split(regex)` for IE8 compatibility. See #17.
+			string = string.replace(regexSeparators, '\x2E');
+			var labels = string.split('.');
+			var encoded = map(labels, fn).join('.');
+			return result + encoded;
+		}
+
+		/**
+		 * Creates an array containing the numeric code points of each Unicode
+		 * character in the string. While JavaScript uses UCS-2 internally,
+		 * this function will convert a pair of surrogate halves (each of which
+		 * UCS-2 exposes as separate characters) into a single code point,
+		 * matching UTF-16.
+		 * @see `punycode.ucs2.encode`
+		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+		 * @memberOf punycode.ucs2
+		 * @name decode
+		 * @param {String} string The Unicode input string (UCS-2).
+		 * @returns {Array} The new array of code points.
+		 */
+		function ucs2decode(string) {
+			var output = [],
+			    counter = 0,
+			    length = string.length,
+			    value,
+			    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;
+		}
+
+		/**
+		 * Creates a string based on an array of numeric code points.
+		 * @see `punycode.ucs2.decode`
+		 * @memberOf punycode.ucs2
+		 * @name encode
+		 * @param {Array} codePoints The array of numeric code points.
+		 * @returns {String} The new Unicode string (UCS-2).
+		 */
+		function ucs2encode(array) {
+			return map(array, function(value) {
+				var output = '';
+				if (value > 0xFFFF) {
+					value -= 0x10000;
+					output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+					value = 0xDC00 | value & 0x3FF;
+				}
+				output += stringFromCharCode(value);
+				return output;
+			}).join('');
+		}
+
+		/**
+		 * Converts a basic code point into a digit/integer.
+		 * @see `digitToBasic()`
+		 * @private
+		 * @param {Number} codePoint The basic numeric code point value.
+		 * @returns {Number} The numeric value of a basic code point (for use in
+		 * representing integers) in the range `0` to `base - 1`, or `base` if
+		 * the code point does not represent a value.
+		 */
+		function basicToDigit(codePoint) {
+			if (codePoint - 48 < 10) {
+				return codePoint - 22;
+			}
+			if (codePoint - 65 < 26) {
+				return codePoint - 65;
+			}
+			if (codePoint - 97 < 26) {
+				return codePoint - 97;
+			}
+			return base;
+		}
+
+		/**
+		 * Converts a digit/integer into a basic code point.
+		 * @see `basicToDigit()`
+		 * @private
+		 * @param {Number} digit The numeric value of a basic code point.
+		 * @returns {Number} The basic code point whose value (when used for
+		 * representing integers) is `digit`, which needs to be in the range
+		 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+		 * used; else, the lowercase form is used. The behavior is undefined
+		 * if `flag` is non-zero and `digit` has no uppercase form.
+		 */
+		function digitToBasic(digit, flag) {
+			//  0..25 map to ASCII a..z or A..Z
+			// 26..35 map to ASCII 0..9
+			return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+		}
+
+		/**
+		 * Bias adaptation function as per section 3.4 of RFC 3492.
+		 * https://tools.ietf.org/html/rfc3492#section-3.4
+		 * @private
+		 */
+		function adapt(delta, numPoints, firstTime) {
+			var k = 0;
+			delta = firstTime ? floor(delta / damp) : delta >> 1;
+			delta += floor(delta / numPoints);
+			for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+				delta = floor(delta / baseMinusTMin);
+			}
+			return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+		}
+
+		/**
+		 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+		 * symbols.
+		 * @memberOf punycode
+		 * @param {String} input The Punycode string of ASCII-only symbols.
+		 * @returns {String} The resulting string of Unicode symbols.
+		 */
+		function decode(input) {
+			// Don't use UCS-2
+			var output = [],
+			    inputLength = input.length,
+			    out,
+			    i = 0,
+			    n = initialN,
+			    bias = initialBias,
+			    basic,
+			    j,
+			    index,
+			    oldi,
+			    w,
+			    k,
+			    digit,
+			    t,
+			    /** Cached calculation results */
+			    baseMinusT;
+
+			// Handle the basic code points: let `basic` be the number of input code
+			// points before the last delimiter, or `0` if there is none, then copy
+			// the first basic code points to the output.
+
+			basic = input.lastIndexOf(delimiter);
+			if (basic < 0) {
+				basic = 0;
+			}
+
+			for (j = 0; j < basic; ++j) {
+				// if it's not a basic code point
+				if (input.charCodeAt(j) >= 0x80) {
+					error('not-basic');
+				}
+				output.push(input.charCodeAt(j));
+			}
+
+			// Main decoding loop: start just after the last delimiter if any basic code
+			// points were copied; start at the beginning otherwise.
+
+			for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+
+				// `index` is the index of the next character to be consumed.
+				// Decode a generalized variable-length integer into `delta`,
+				// which gets added to `i`. The overflow checking is easier
+				// if we increase `i` as we go, then subtract off its starting
+				// value at the end to obtain `delta`.
+				for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+
+					if (index >= inputLength) {
+						error('invalid-input');
+					}
+
+					digit = basicToDigit(input.charCodeAt(index++));
+
+					if (digit >= base || digit > floor((maxInt - i) / w)) {
+						error('overflow');
+					}
+
+					i += digit * w;
+					t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+
+					if (digit < t) {
+						break;
+					}
+
+					baseMinusT = base - t;
+					if (w > floor(maxInt / baseMinusT)) {
+						error('overflow');
+					}
+
+					w *= baseMinusT;
+
+				}
+
+				out = output.length + 1;
+				bias = adapt(i - oldi, out, oldi == 0);
+
+				// `i` was supposed to wrap around from `out` to `0`,
+				// incrementing `n` each time, so we'll fix that now:
+				if (floor(i / out) > maxInt - n) {
+					error('overflow');
+				}
+
+				n += floor(i / out);
+				i %= out;
+
+				// Insert `n` at position `i` of the output
+				output.splice(i++, 0, n);
+
+			}
+
+			return ucs2encode(output);
+		}
+
+		/**
+		 * Converts a string of Unicode symbols (e.g. a domain name label) to a
+		 * Punycode string of ASCII-only symbols.
+		 * @memberOf punycode
+		 * @param {String} input The string of Unicode symbols.
+		 * @returns {String} The resulting Punycode string of ASCII-only symbols.
+		 */
+		function encode(input) {
+			var n,
+			    delta,
+			    handledCPCount,
+			    basicLength,
+			    bias,
+			    j,
+			    m,
+			    q,
+			    k,
+			    t,
+			    currentValue,
+			    output = [],
+			    /** `inputLength` will hold the number of code points in `input`. */
+			    inputLength,
+			    /** Cached calculation results */
+			    handledCPCountPlusOne,
+			    baseMinusT,
+			    qMinusT;
+
+			// Convert the input in UCS-2 to Unicode
+			input = ucs2decode(input);
+
+			// Cache the length
+			inputLength = input.length;
+
+			// Initialize the state
+			n = initialN;
+			delta = 0;
+			bias = initialBias;
+
+			// Handle the basic code points
+			for (j = 0; j < inputLength; ++j) {
+				currentValue = input[j];
+				if (currentValue < 0x80) {
+					output.push(stringFromCharCode(currentValue));
+				}
+			}
+
+			handledCPCount = basicLength = output.length;
+
+			// `handledCPCount` is the number of code points that have been handled;
+			// `basicLength` is the number of basic code points.
+
+			// Finish the basic string - if it is not empty - with a delimiter
+			if (basicLength) {
+				output.push(delimiter);
+			}
+
+			// Main encoding loop:
+			while (handledCPCount < inputLength) {
+
+				// All non-basic code points < n have been handled already. Find the next
+				// larger one:
+				for (m = maxInt, j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+					if (currentValue >= n && currentValue < m) {
+						m = currentValue;
+					}
+				}
+
+				// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
+				// but guard against overflow
+				handledCPCountPlusOne = handledCPCount + 1;
+				if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+					error('overflow');
+				}
+
+				delta += (m - n) * handledCPCountPlusOne;
+				n = m;
+
+				for (j = 0; j < inputLength; ++j) {
+					currentValue = input[j];
+
+					if (currentValue < n && ++delta > maxInt) {
+						error('overflow');
+					}
+
+					if (currentValue == n) {
+						// Represent delta as a generalized variable-length integer
+						for (q = delta, k = base; /* no condition */; k += base) {
+							t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+							if (q < t) {
+								break;
+							}
+							qMinusT = q - t;
+							baseMinusT = base - t;
+							output.push(
+								stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+							);
+							q = floor(qMinusT / baseMinusT);
+						}
+
+						output.push(stringFromCharCode(digitToBasic(q, 0)));
+						bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+						delta = 0;
+						++handledCPCount;
+					}
+				}
+
+				++delta;
+				++n;
+
+			}
+			return output.join('');
+		}
+
+		/**
+		 * Converts a Punycode string representing a domain name or an email address
+		 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+		 * it doesn't matter if you call it on a string that has already been
+		 * converted to Unicode.
+		 * @memberOf punycode
+		 * @param {String} input The Punycoded domain name or email address to
+		 * convert to Unicode.
+		 * @returns {String} The Unicode representation of the given Punycode
+		 * string.
+		 */
+		function toUnicode(input) {
+			return mapDomain(input, function(string) {
+				return regexPunycode.test(string)
+					? decode(string.slice(4).toLowerCase())
+					: string;
+			});
+		}
+
+		/**
+		 * Converts a Unicode string representing a domain name or an email address to
+		 * Punycode. Only the non-ASCII parts of the domain name will be converted,
+		 * i.e. it doesn't matter if you call it with a domain that's already in
+		 * ASCII.
+		 * @memberOf punycode
+		 * @param {String} input The domain name or email address to convert, as a
+		 * Unicode string.
+		 * @returns {String} The Punycode representation of the given domain name or
+		 * email address.
+		 */
+		function toASCII(input) {
+			return mapDomain(input, function(string) {
+				return regexNonASCII.test(string)
+					? 'xn--' + encode(string)
+					: string;
+			});
+		}
+
+		/*--------------------------------------------------------------------------*/
+
+		/** Define the public API */
+		punycode = {
+			/**
+			 * A string representing the current Punycode.js version number.
+			 * @memberOf punycode
+			 * @type String
+			 */
+			'version': '1.4.1',
+			/**
+			 * An object of methods to convert from JavaScript's internal character
+			 * representation (UCS-2) to Unicode code points, and back.
+			 * @see <https://mathiasbynens.be/notes/javascript-encoding>
+			 * @memberOf punycode
+			 * @type Object
+			 */
+			'ucs2': {
+				'decode': ucs2decode,
+				'encode': ucs2encode
+			},
+			'decode': decode,
+			'encode': encode,
+			'toASCII': toASCII,
+			'toUnicode': toUnicode
+		};
+
+		/** Expose `punycode` */
+		// Some AMD build optimizers, like r.js, check for specific condition patterns
+		// like the following:
+		if (
+			true
+		) {
+			!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
+				return punycode;
+			}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+		} else if (freeExports && freeModule) {
+			if (module.exports == freeExports) {
+				// in Node.js, io.js, or RingoJS v0.8.0+
+				freeModule.exports = punycode;
+			} else {
+				// in Narwhal or RingoJS v0.7.0-
+				for (key in punycode) {
+					punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+				}
+			}
+		} else {
+			// in Rhino or a web browser
+			root.punycode = punycode;
+		}
+
+	}(this));
+
+	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4)(module), (function() { return this; }())))
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports) {
+
+	module.exports = ["ac","com.ac","edu.ac","gov.ac","net.ac","mil.ac","org.ac","ad","nom.ad","ae","co.ae","net.ae","org.ae","sch.ae","ac.ae","gov.ae","mil.ae","aero","accident-investigation.aero","accident-prevention.aero","aerobatic.aero","aeroclub.aero","aerodrome.aero","agents.aero","aircraft.aero","airline.aero","airport.aero","air-surveillance.aero","airtraffic.aero","air-traffic-control.aero","ambulance.aero","amusement.aero","association.aero","author.aero","ballooning.aero","broker.aero","caa.aero","cargo.aero","catering.aero","certification.aero","championship.aero","charter.aero","civilaviation.aero","club.aero","conference.aero","consultant.aero","consulting.aero","control.aero","council.aero","crew.aero","design.aero","dgca.aero","educator.aero","emergency.aero","engine.aero","engineer.aero","entertainment.aero","equipment.aero","exchange.aero","express.aero","federation.aero","flight.aero","freight.aero","fuel.aero","gliding.aero","government.aero","groundhandling.aero","group.aero","hanggliding.aero","homebuilt.aero","insurance.aero","journal.aero","journalist.aero","leasing.aero","logistics.aero","magazine.aero","maintenance.aero","media.aero","microlight.aero","modelling.aero","navigation.aero","parachuting.aero","paragliding.aero","passenger-association.aero","pilot.aero","press.aero","production.aero","recreation.aero","repbody.aero","res.aero","research.aero","rotorcraft.aero","safety.aero","scientist.aero","services.aero","show.aero","skydiving.aero","software.aero","student.aero","trader.aero","trading.aero","trainer.aero","union.aero","workinggroup.aero","works.aero","af","gov.af","com.af","org.af","net.af","edu.af","ag","com.ag","org.ag","net.ag","co.ag","nom.ag","ai","off.ai","com.ai","net.ai","org.ai","al","com.al","edu.al","gov.al","mil.al","net.al","org.al","am","ao","ed.ao","gv.ao","og.ao","co.ao","pb.ao","it.ao","aq","ar","com.ar","edu.ar","gob.ar","gov.ar","int.ar","mil.ar","musica.ar","net.ar","org.ar","tur.ar","arpa","e164.arpa","in-addr.arpa","ip6.arpa","iris.arpa","uri.arpa","urn.arpa","as","gov.as","asia","at","ac.at","co.at","gv.at","or.at","au","com.au","net.au","org.au","edu.au","gov.au","asn.au","id.au","info.au","conf.au","oz.au","act.au","nsw.au","nt.au","qld.au","sa.au","tas.au","vic.au","wa.au","act.edu.au","nsw.edu.au","nt.edu.au","qld.edu.au","sa.edu.au","tas.edu.au","vic.edu.au","wa.edu.au","qld.gov.au","sa.gov.au","tas.gov.au","vic.gov.au","wa.gov.au","aw","com.aw","ax","az","com.az","net.az","int.az","gov.az","org.az","edu.az","info.az","pp.az","mil.az","name.az","pro.az","biz.az","ba","com.ba","edu.ba","gov.ba","mil.ba","net.ba","org.ba","bb","biz.bb","co.bb","com.bb","edu.bb","gov.bb","info.bb","net.bb","org.bb","store.bb","tv.bb","*.bd","be","ac.be","bf","gov.bf","bg","a.bg","b.bg","c.bg","d.bg","e.bg","f.bg","g.bg","h.bg","i.bg","j.bg","k.bg","l.bg","m.bg","n.bg","o.bg","p.bg","q.bg","r.bg","s.bg","t.bg","u.bg","v.bg","w.bg","x.bg","y.bg","z.bg","0.bg","1.bg","2.bg","3.bg","4.bg","5.bg","6.bg","7.bg","8.bg","9.bg","bh","com.bh","edu.bh","net.bh","org.bh","gov.bh","bi","co.bi","com.bi","edu.bi","or.bi","org.bi","biz","bj","asso.bj","barreau.bj","gouv.bj","bm","com.bm","edu.bm","gov.bm","net.bm","org.bm","*.bn","bo","com.bo","edu.bo","gob.bo","int.bo","org.bo","net.bo","mil.bo","tv.bo","web.bo","academia.bo","agro.bo","arte.bo","blog.bo","bolivia.bo","ciencia.bo","cooperativa.bo","democracia.bo","deporte.bo","ecologia.bo","economia.bo","empresa.bo","indigena.bo","industria.bo","info.bo","medicina.bo","movimiento.bo","musica.bo","natural.bo","nombre.bo","noticias.bo","patria.bo","politica.bo","profesional.bo","plurinacional.bo","pueblo.bo","revista.bo","salud.bo","tecnologia.bo","tksat.bo","transporte.bo","wiki.bo","br","9guacu.br","abc.br","adm.br","adv.br","agr.br","aju.br","am.br","anani.br","aparecida.br","arq.br","art.br","ato.br","b.br","barueri.br","belem.br","bhz.br","bio.br","blog.br","bmd.br","boavista.br","bsb.br","campinagrande.br","campinas.br","caxias.br","cim.br","cng.br","cnt.br","com.br","contagem.br","coop.br","cri.br","cuiaba.br","curitiba.br","def.br","ecn.br","eco.br","edu.br","emp.br","eng.br","esp.br","etc.br","eti.br","far.br","feira.br","flog.br","floripa.br","fm.br","fnd.br","fortal.br","fot.br","foz.br","fst.br","g12.br","ggf.br","goiania.br","gov.br","ac.gov.br","al.gov.br","am.gov.br","ap.gov.br","ba.gov.br","ce.gov.br","df.gov.br","es.gov.br","go.gov.br","ma.gov.br","mg.gov.br","ms.gov.br","mt.gov.br","pa.gov.br","pb.gov.br","pe.gov.br","pi.gov.br","pr.gov.br","rj.gov.br","rn.gov.br","ro.gov.br","rr.gov.br","rs.gov.br","sc.gov.br","se.gov.br","sp.gov.br","to.gov.br","gru.br","imb.br","ind.br","inf.br","jab.br","jampa.br","jdf.br","joinville.br","jor.br","jus.br","leg.br","lel.br","londrina.br","macapa.br","maceio.br","manaus.br","maringa.br","mat.br","med.br","mil.br","morena.br","mp.br","mus.br","natal.br","net.br","niteroi.br","*.nom.br","not.br","ntr.br","odo.br","org.br","osasco.br","palmas.br","poa.br","ppg.br","pro.br","psc.br","psi.br","pvh.br","qsl.br","radio.br","rec.br","recife.br","ribeirao.br","rio.br","riobranco.br","riopreto.br","salvador.br","sampa.br","santamaria.br","santoandre.br","saobernardo.br","saogonca.br","sjc.br","slg.br","slz.br","sorocaba.br","srv.br","taxi.br","teo.br","the.br","tmp.br","trd.br","tur.br","tv.br","udi.br","vet.br","vix.br","vlog.br","wiki.br","zlg.br","bs","com.bs","net.bs","org.bs","edu.bs","gov.bs","bt","com.bt","edu.bt","gov.bt","net.bt","org.bt","bv","bw","co.bw","org.bw","by","gov.by","mil.by","com.by","of.by","bz","com.bz","net.bz","org.bz","edu.bz","gov.bz","ca","ab.ca","bc.ca","mb.ca","nb.ca","nf.ca","nl.ca","ns.ca","nt.ca","nu.ca","on.ca","pe.ca","qc.ca","sk.ca","yk.ca","gc.ca","cat","cc","cd","gov.cd","cf","cg","ch","ci","org.ci","or.ci","com.ci","co.ci","edu.ci","ed.ci","ac.ci","net.ci","go.ci","asso.ci","aéroport.ci","int.ci","presse.ci","md.ci","gouv.ci","*.ck","!www.ck","cl","gov.cl","gob.cl","co.cl","mil.cl","cm","co.cm","com.cm","gov.cm","net.cm","cn","ac.cn","com.cn","edu.cn","gov.cn","net.cn","org.cn","mil.cn","公司.cn","网络.cn","網絡.cn","ah.cn","bj.cn","cq.cn","fj.cn","gd.cn","gs.cn","gz.cn","gx.cn","ha.cn","hb.cn","he.cn","hi.cn","hl.cn","hn.cn","jl.cn","js.cn","jx.cn","ln.cn","nm.cn","nx.cn","qh.cn","sc.cn","sd.cn","sh.cn","sn.cn","sx.cn","tj.cn","xj.cn","xz.cn","yn.cn","zj.cn","hk.cn","mo.cn","tw.cn","co","arts.co","com.co","edu.co","firm.co","gov.co","info.co","int.co","mil.co","net.co","nom.co","org.co","rec.co","web.co","com","coop","cr","ac.cr","co.cr","ed.cr","fi.cr","go.cr","or.cr","sa.cr","cu","com.cu","edu.cu","org.cu","net.cu","gov.cu","inf.cu","cv","cw","com.cw","edu.cw","net.cw","org.cw","cx","gov.cx","cy","ac.cy","biz.cy","com.cy","ekloges.cy","gov.cy","ltd.cy","name.cy","net.cy","org.cy","parliament.cy","press.cy","pro.cy","tm.cy","cz","de","dj","dk","dm","com.dm","net.dm","org.dm","edu.dm","gov.dm","do","art.do","com.do","edu.do","gob.do","gov.do","mil.do","net.do","org.do","sld.do","web.do","dz","com.dz","org.dz","net.dz","gov.dz","edu.dz","asso.dz","pol.dz","art.dz","ec","com.ec","info.ec","net.ec","fin.ec","k12.ec","med.ec","pro.ec","org.ec","edu.ec","gov.ec","gob.ec","mil.ec","edu","ee","edu.ee","gov.ee","riik.ee","lib.ee","med.ee","com.ee","pri.ee","aip.ee","org.ee","fie.ee","eg","com.eg","edu.eg","eun.eg","gov.eg","mil.eg","name.eg","net.eg","org.eg","sci.eg","*.er","es","com.es","nom.es","org.es","gob.es","edu.es","et","com.et","gov.et","org.et","edu.et","biz.et","name.et","info.et","net.et","eu","fi","aland.fi","*.fj","*.fk","fm","fo","fr","com.fr","asso.fr","nom.fr","prd.fr","presse.fr","tm.fr","aeroport.fr","assedic.fr","avocat.fr","avoues.fr","cci.fr","chambagri.fr","chirurgiens-dentistes.fr","experts-comptables.fr","geometre-expert.fr","gouv.fr","greta.fr","huissier-justice.fr","medecin.fr","notaires.fr","pharmacien.fr","port.fr","veterinaire.fr","ga","gb","gd","ge","com.ge","edu.ge","gov.ge","org.ge","mil.ge","net.ge","pvt.ge","gf","gg","co.gg","net.gg","org.gg","gh","com.gh","edu.gh","gov.gh","org.gh","mil.gh","gi","com.gi","ltd.gi","gov.gi","mod.gi","edu.gi","org.gi","gl","co.gl","com.gl","edu.gl","net.gl","org.gl","gm","gn","ac.gn","com.gn","edu.gn","gov.gn","org.gn","net.gn","gov","gp","com.gp","net.gp","mobi.gp","edu.gp","org.gp","asso.gp","gq","gr","com.gr","edu.gr","net.gr","org.gr","gov.gr","gs","gt","com.gt","edu.gt","gob.gt","ind.gt","mil.gt","net.gt","org.gt","gu","com.gu","edu.gu","gov.gu","guam.gu","info.gu","net.gu","org.gu","web.gu","gw","gy","co.gy","com.gy","edu.gy","gov.gy","net.gy","org.gy","hk","com.hk","edu.hk","gov.hk","idv.hk","net.hk","org.hk","公司.hk","教育.hk","敎育.hk","政府.hk","個人.hk","个人.hk","箇人.hk","網络.hk","网络.hk","组織.hk","網絡.hk","网絡.hk","组织.hk","組織.hk","組织.hk","hm","hn","com.hn","edu.hn","org.hn","net.hn","mil.hn","gob.hn","hr","iz.hr","from.hr","name.hr","com.hr","ht","com.ht","shop.ht","firm.ht","info.ht","adult.ht","net.ht","pro.ht","org.ht","med.ht","art.ht","coop.ht","pol.ht","asso.ht","edu.ht","rel.ht","gouv.ht","perso.ht","hu","co.hu","info.hu","org.hu","priv.hu","sport.hu","tm.hu","2000.hu","agrar.hu","bolt.hu","casino.hu","city.hu","erotica.hu","erotika.hu","film.hu","forum.hu","games.hu","hotel.hu","ingatlan.hu","jogasz.hu","konyvelo.hu","lakas.hu","media.hu","news.hu","reklam.hu","sex.hu","shop.hu","suli.hu","szex.hu","tozsde.hu","utazas.hu","video.hu","id","ac.id","biz.id","co.id","desa.id","go.id","mil.id","my.id","net.id","or.id","sch.id","web.id","ie","gov.ie","il","ac.il","co.il","gov.il","idf.il","k12.il","muni.il","net.il","org.il","im","ac.im","co.im","com.im","ltd.co.im","net.im","org.im","plc.co.im","tt.im","tv.im","in","co.in","firm.in","net.in","org.in","gen.in","ind.in","nic.in","ac.in","edu.in","res.in","gov.in","mil.in","info","int","eu.int","io","com.io","iq","gov.iq","edu.iq","mil.iq","com.iq","org.iq","net.iq","ir","ac.ir","co.ir","gov.ir","id.ir","net.ir","org.ir","sch.ir","ایران.ir","ايران.ir","is","net.is","com.is","edu.is","gov.is","org.is","int.is","it","gov.it","edu.it","abr.it","abruzzo.it","aosta-valley.it","aostavalley.it","bas.it","basilicata.it","cal.it","calabria.it","cam.it","campania.it","emilia-romagna.it","emiliaromagna.it","emr.it","friuli-v-giulia.it","friuli-ve-giulia.it","friuli-vegiulia.it","friuli-venezia-giulia.it","friuli-veneziagiulia.it","friuli-vgiulia.it","friuliv-giulia.it","friulive-giulia.it","friulivegiulia.it","friulivenezia-giulia.it","friuliveneziagiulia.it","friulivgiulia.it","fvg.it","laz.it","lazio.it","lig.it","liguria.it","lom.it","lombardia.it","lombardy.it","lucania.it","mar.it","marche.it","mol.it","molise.it","piedmont.it","piemonte.it","pmn.it","pug.it","puglia.it","sar.it","sardegna.it","sardinia.it","sic.it","sicilia.it","sicily.it","taa.it","tos.it","toscana.it","trentin-sud-tirol.it","trentin-süd-tirol.it","trentin-sudtirol.it","trentin-südtirol.it","trentin-sued-tirol.it","trentin-suedtirol.it","trentino-a-adige.it","trentino-aadige.it","trentino-alto-adige.it","trentino-altoadige.it","trentino-s-tirol.it","trentino-stirol.it","trentino-sud-tirol.it","trentino-süd-tirol.it","trentino-sudtirol.it","trentino-südtirol.it","trentino-sued-tirol.it","trentino-suedtirol.it","trentino.it","trentinoa-adige.it","trentinoaadige.it","trentinoalto-adige.it","trentinoaltoadige.it","trentinos-tirol.it","trentinostirol.it","trentinosud-tirol.it","trentinosüd-tirol.it","trentinosudtirol.it","trentinosüdtirol.it","trentinosued-tirol.it","trentinosuedtirol.it","trentinsud-tirol.it","trentinsüd-tirol.it","trentinsudtirol.it","trentinsüdtirol.it","trentinsued-tirol.it","trentinsuedtirol.it","tuscany.it","umb.it","umbria.it","val-d-aosta.it","val-daosta.it","vald-aosta.it","valdaosta.it","valle-aosta.it","valle-d-aosta.it","valle-daosta.it","valleaosta.it","valled-aosta.it","valledaosta.it","vallee-aoste.it","vallée-aoste.it","vallee-d-aoste.it","vallée-d-aoste.it","valleeaoste.it","valléeaoste.it","valleedaoste.it","valléedaoste.it","vao.it","vda.it","ven.it","veneto.it","ag.it","agrigento.it","al.it","alessandria.it","alto-adige.it","altoadige.it","an.it","ancona.it","andria-barletta-trani.it","andria-trani-barletta.it","andriabarlettatrani.it","andriatranibarletta.it","ao.it","aosta.it","aoste.it","ap.it","aq.it","aquila.it","ar.it","arezzo.it","ascoli-piceno.it","ascolipiceno.it","asti.it","at.it","av.it","avellino.it","ba.it","balsan-sudtirol.it","balsan-südtirol.it","balsan-suedtirol.it","balsan.it","bari.it","barletta-trani-andria.it","barlettatraniandria.it","belluno.it","benevento.it","bergamo.it","bg.it","bi.it","biella.it","bl.it","bn.it","bo.it","bologna.it","bolzano-altoadige.it","bolzano.it","bozen-sudtirol.it","bozen-südtirol.it","bozen-suedtirol.it","bozen.it","br.it","brescia.it","brindisi.it","bs.it","bt.it","bulsan-sudtirol.it","bulsan-südtirol.it","bulsan-suedtirol.it","bulsan.it","bz.it","ca.it","cagliari.it","caltanissetta.it","campidano-medio.it","campidanomedio.it","campobasso.it","carbonia-iglesias.it","carboniaiglesias.it","carrara-massa.it","carraramassa.it","caserta.it","catania.it","catanzaro.it","cb.it","ce.it","cesena-forli.it","cesena-forlì.it","cesenaforli.it","cesenaforlì.it","ch.it","chieti.it","ci.it","cl.it","cn.it","co.it","como.it","cosenza.it","cr.it","cremona.it","crotone.it","cs.it","ct.it","cuneo.it","cz.it","dell-ogliastra.it","dellogliastra.it","en.it","enna.it","fc.it","fe.it","fermo.it","ferrara.it","fg.it","fi.it","firenze.it","florence.it","fm.it","foggia.it","forli-cesena.it","forlì-cesena.it","forlicesena.it","forlìcesena.it","fr.it","frosinone.it","ge.it","genoa.it","genova.it","go.it","gorizia.it","gr.it","grosseto.it","iglesias-carbonia.it","iglesiascarbonia.it","im.it","imperia.it","is.it","isernia.it","kr.it","la-spezia.it","laquila.it","laspezia.it","latina.it","lc.it","le.it","lecce.it","lecco.it","li.it","livorno.it","lo.it","lodi.it","lt.it","lu.it","lucca.it","macerata.it","mantova.it","massa-carrara.it","massacarrara.it","matera.it","mb.it","mc.it","me.it","medio-campidano.it","mediocampidano.it","messina.it","mi.it","milan.it","milano.it","mn.it","mo.it","modena.it","monza-brianza.it","monza-e-della-brianza.it","monza.it","monzabrianza.it","monzaebrianza.it","monzaedellabrianza.it","ms.it","mt.it","na.it","naples.it","napoli.it","no.it","novara.it","nu.it","nuoro.it","og.it","ogliastra.it","olbia-tempio.it","olbiatempio.it","or.it","oristano.it","ot.it","pa.it","padova.it","padua.it","palermo.it","parma.it","pavia.it","pc.it","pd.it","pe.it","perugia.it","pesaro-urbino.it","pesarourbino.it","pescara.it","pg.it","pi.it","piacenza.it","pisa.it","pistoia.it","pn.it","po.it","pordenone.it","potenza.it","pr.it","prato.it","pt.it","pu.it","pv.it","pz.it","ra.it","ragusa.it","ravenna.it","rc.it","re.it","reggio-calabria.it","reggio-emilia.it","reggiocalabria.it","reggioemilia.it","rg.it","ri.it","rieti.it","rimini.it","rm.it","rn.it","ro.it","roma.it","rome.it","rovigo.it","sa.it","salerno.it","sassari.it","savona.it","si.it","siena.it","siracusa.it","so.it","sondrio.it","sp.it","sr.it","ss.it","suedtirol.it","südtirol.it","sv.it","ta.it","taranto.it","te.it","tempio-olbia.it","tempioolbia.it","teramo.it","terni.it","tn.it","to.it","torino.it","tp.it","tr.it","trani-andria-barletta.it","trani-barletta-andria.it","traniandriabarletta.it","tranibarlettaandria.it","trapani.it","trento.it","treviso.it","trieste.it","ts.it","turin.it","tv.it","ud.it","udine.it","urbino-pesaro.it","urbinopesaro.it","va.it","varese.it","vb.it","vc.it","ve.it","venezia.it","venice.it","verbania.it","vercelli.it","verona.it","vi.it","vibo-valentia.it","vibovalentia.it","vicenza.it","viterbo.it","vr.it","vs.it","vt.it","vv.it","je","co.je","net.je","org.je","*.jm","jo","com.jo","org.jo","net.jo","edu.jo","sch.jo","gov.jo","mil.jo","name.jo","jobs","jp","ac.jp","ad.jp","co.jp","ed.jp","go.jp","gr.jp","lg.jp","ne.jp","or.jp","aichi.jp","akita.jp","aomori.jp","chiba.jp","ehime.jp","fukui.jp","fukuoka.jp","fukushima.jp","gifu.jp","gunma.jp","hiroshima.jp","hokkaido.jp","hyogo.jp","ibaraki.jp","ishikawa.jp","iwate.jp","kagawa.jp","kagoshima.jp","kanagawa.jp","kochi.jp","kumamoto.jp","kyoto.jp","mie.jp","miyagi.jp","miyazaki.jp","nagano.jp","nagasaki.jp","nara.jp","niigata.jp","oita.jp","okayama.jp","okinawa.jp","osaka.jp","saga.jp","saitama.jp","shiga.jp","shimane.jp","shizuoka.jp","tochigi.jp","tokushima.jp","tokyo.jp","tottori.jp","toyama.jp","wakayama.jp","yamagata.jp","yamaguchi.jp","yamanashi.jp","栃木.jp","愛知.jp","愛媛.jp","兵庫.jp","熊本.jp","茨城.jp","北海道.jp","千葉.jp","和歌山.jp","長崎.jp","長野.jp","新潟.jp","青森.jp","静岡.jp","東京.jp","石川.jp","埼玉.jp","三重.jp","京都.jp","佐賀.jp","大分.jp","大阪.jp","奈良.jp","宮城.jp","宮崎.jp","富山.jp","山口.jp","山形.jp","山梨.jp","岩手.jp","岐阜.jp","岡山.jp","島根.jp","広島.jp","徳島.jp","沖縄.jp","滋賀.jp","神奈川.jp","福井.jp","福岡.jp","福島.jp","秋田.jp","群馬.jp","香川.jp","高知.jp","鳥取.jp","鹿児島.jp","*.kawasaki.jp","*.kitakyushu.jp","*.kobe.jp","*.nagoya.jp","*.sapporo.jp","*.sendai.jp","*.yokohama.jp","!city.kawasaki.jp","!city.kitakyushu.jp","!city.kobe.jp","!city.nagoya.jp","!city.sapporo.jp","!city.sendai.jp","!city.yokohama.jp","aisai.aichi.jp","ama.aichi.jp","anjo.aichi.jp","asuke.aichi.jp","chiryu.aichi.jp","chita.aichi.jp","fuso.aichi.jp","gamagori.aichi.jp","handa.aichi.jp","hazu.aichi.jp","hekinan.aichi.jp","higashiura.aichi.jp","ichinomiya.aichi.jp","inazawa.aichi.jp","inuyama.aichi.jp","isshiki.aichi.jp","iwakura.aichi.jp","kanie.aichi.jp","kariya.aichi.jp","kasugai.aichi.jp","kira.aichi.jp","kiyosu.aichi.jp","komaki.aichi.jp","konan.aichi.jp","kota.aichi.jp","mihama.aichi.jp","miyoshi.aichi.jp","nishio.aichi.jp","nisshin.aichi.jp","obu.aichi.jp","oguchi.aichi.jp","oharu.aichi.jp","okazaki.aichi.jp","owariasahi.aichi.jp","seto.aichi.jp","shikatsu.aichi.jp","shinshiro.aichi.jp","shitara.aichi.jp","tahara.aichi.jp","takahama.aichi.jp","tobishima.aichi.jp","toei.aichi.jp","togo.aichi.jp","tokai.aichi.jp","tokoname.aichi.jp","toyoake.aichi.jp","toyohashi.aichi.jp","toyokawa.aichi.jp","toyone.aichi.jp","toyota.aichi.jp","tsushima.aichi.jp","yatomi.aichi.jp","akita.akita.jp","daisen.akita.jp","fujisato.akita.jp","gojome.akita.jp","hachirogata.akita.jp","happou.akita.jp","higashinaruse.akita.jp","honjo.akita.jp","honjyo.akita.jp","ikawa.akita.jp","kamikoani.akita.jp","kamioka.akita.jp","katagami.akita.jp","kazuno.akita.jp","kitaakita.akita.jp","kosaka.akita.jp","kyowa.akita.jp","misato.akita.jp","mitane.akita.jp","moriyoshi.akita.jp","nikaho.akita.jp","noshiro.akita.jp","odate.akita.jp","oga.akita.jp","ogata.akita.jp","semboku.akita.jp","yokote.akita.jp","yurihonjo.akita.jp","aomori.aomori.jp","gonohe.aomori.jp","hachinohe.aomori.jp","hashikami.aomori.jp","hiranai.aomori.jp","hirosaki.aomori.jp","itayanagi.aomori.jp","kuroishi.aomori.jp","misawa.aomori.jp","mutsu.aomori.jp","nakadomari.aomori.jp","noheji.aomori.jp","oirase.aomori.jp","owani.aomori.jp","rokunohe.aomori.jp","sannohe.aomori.jp","shichinohe.aomori.jp","shingo.aomori.jp","takko.aomori.jp","towada.aomori.jp","tsugaru.aomori.jp","tsuruta.aomori.jp","abiko.chiba.jp","asahi.chiba.jp","chonan.chiba.jp","chosei.chiba.jp","choshi.chiba.jp","chuo.chiba.jp","funabashi.chiba.jp","futtsu.chiba.jp","hanamigawa.chiba.jp","ichihara.chiba.jp","ichikawa.chiba.jp","ichinomiya.chiba.jp","inzai.chiba.jp","isumi.chiba.jp","kamagaya.chiba.jp","kamogawa.chiba.jp","kashiwa.chiba.jp","katori.chiba.jp","katsuura.chiba.jp","kimitsu.chiba.jp","kisarazu.chiba.jp","kozaki.chiba.jp","kujukuri.chiba.jp","kyonan.chiba.jp","matsudo.chiba.jp","midori.chiba.jp","mihama.chiba.jp","minamiboso.chiba.jp","mobara.chiba.jp","mutsuzawa.chiba.jp","nagara.chiba.jp","nagareyama.chiba.jp","narashino.chiba.jp","narita.chiba.jp","noda.chiba.jp","oamishirasato.chiba.jp","omigawa.chiba.jp","onjuku.chiba.jp","otaki.chiba.jp","sakae.chiba.jp","sakura.chiba.jp","shimofusa.chiba.jp","shirako.chiba.jp","shiroi.chiba.jp","shisui.chiba.jp","sodegaura.chiba.jp","sosa.chiba.jp","tako.chiba.jp","tateyama.chiba.jp","togane.chiba.jp","tohnosho.chiba.jp","tomisato.chiba.jp","urayasu.chiba.jp","yachimata.chiba.jp","yachiyo.chiba.jp","yokaichiba.chiba.jp","yokoshibahikari.chiba.jp","yotsukaido.chiba.jp","ainan.ehime.jp","honai.ehime.jp","ikata.ehime.jp","imabari.ehime.jp","iyo.ehime.jp","kamijima.ehime.jp","kihoku.ehime.jp","kumakogen.ehime.jp","masaki.ehime.jp","matsuno.ehime.jp","matsuyama.ehime.jp","namikata.ehime.jp","niihama.ehime.jp","ozu.ehime.jp","saijo.ehime.jp","seiyo.ehime.jp","shikokuchuo.ehime.jp","tobe.ehime.jp","toon.ehime.jp","uchiko.ehime.jp","uwajima.ehime.jp","yawatahama.ehime.jp","echizen.fukui.jp","eiheiji.fukui.jp","fukui.fukui.jp","ikeda.fukui.jp","katsuyama.fukui.jp","mihama.fukui.jp","minamiechizen.fukui.jp","obama.fukui.jp","ohi.fukui.jp","ono.fukui.jp","sabae.fukui.jp","sakai.fukui.jp","takahama.fukui.jp","tsuruga.fukui.jp","wakasa.fukui.jp","ashiya.fukuoka.jp","buzen.fukuoka.jp","chikugo.fukuoka.jp","chikuho.fukuoka.jp","chikujo.fukuoka.jp","chikushino.fukuoka.jp","chikuzen.fukuoka.jp","chuo.fukuoka.jp","dazaifu.fukuoka.jp","fukuchi.fukuoka.jp","hakata.fukuoka.jp","higashi.fukuoka.jp","hirokawa.fukuoka.jp","hisayama.fukuoka.jp","iizuka.fukuoka.jp","inatsuki.fukuoka.jp","kaho.fukuoka.jp","kasuga.fukuoka.jp","kasuya.fukuoka.jp","kawara.fukuoka.jp","keisen.fukuoka.jp","koga.fukuoka.jp","kurate.fukuoka.jp","kurogi.fukuoka.jp","kurume.fukuoka.jp","minami.fukuoka.jp","miyako.fukuoka.jp","miyama.fukuoka.jp","miyawaka.fukuoka.jp","mizumaki.fukuoka.jp","munakata.fukuoka.jp","nakagawa.fukuoka.jp","nakama.fukuoka.jp","nishi.fukuoka.jp","nogata.fukuoka.jp","ogori.fukuoka.jp","okagaki.fukuoka.jp","okawa.fukuoka.jp","oki.fukuoka.jp","omuta.fukuoka.jp","onga.fukuoka.jp","onojo.fukuoka.jp","oto.fukuoka.jp","saigawa.fukuoka.jp","sasaguri.fukuoka.jp","shingu.fukuoka.jp","shinyoshitomi.fukuoka.jp","shonai.fukuoka.jp","soeda.fukuoka.jp","sue.fukuoka.jp","tachiarai.fukuoka.jp","tagawa.fukuoka.jp","takata.fukuoka.jp","toho.fukuoka.jp","toyotsu.fukuoka.jp","tsuiki.fukuoka.jp","ukiha.fukuoka.jp","umi.fukuoka.jp","usui.fukuoka.jp","yamada.fukuoka.jp","yame.fukuoka.jp","yanagawa.fukuoka.jp","yukuhashi.fukuoka.jp","aizubange.fukushima.jp","aizumisato.fukushima.jp","aizuwakamatsu.fukushima.jp","asakawa.fukushima.jp","bandai.fukushima.jp","date.fukushima.jp","fukushima.fukushima.jp","furudono.fukushima.jp","futaba.fukushima.jp","hanawa.fukushima.jp","higashi.fukushima.jp","hirata.fukushima.jp","hirono.fukushima.jp","iitate.fukushima.jp","inawashiro.fukushima.jp","ishikawa.fukushima.jp","iwaki.fukushima.jp","izumizaki.fukushima.jp","kagamiishi.fukushima.jp","kaneyama.fukushima.jp","kawamata.fukushima.jp","kitakata.fukushima.jp","kitashiobara.fukushima.jp","koori.fukushima.jp","koriyama.fukushima.jp","kunimi.fukushima.jp","miharu.fukushima.jp","mishima.fukushima.jp","namie.fukushima.jp","nango.fukushima.jp","nishiaizu.fukushima.jp","nishigo.fukushima.jp","okuma.fukushima.jp","omotego.fukushima.jp","ono.fukushima.jp","otama.fukushima.jp","samegawa.fukushima.jp","shimogo.fukushima.jp","shirakawa.fukushima.jp","showa.fukushima.jp","soma.fukushima.jp","sukagawa.fukushima.jp","taishin.fukushima.jp","tamakawa.fukushima.jp","tanagura.fukushima.jp","tenei.fukushima.jp","yabuki.fukushima.jp","yamato.fukushima.jp","yamatsuri.fukushima.jp","yanaizu.fukushima.jp","yugawa.fukushima.jp","anpachi.gifu.jp","ena.gifu.jp","gifu.gifu.jp","ginan.gifu.jp","godo.gifu.jp","gujo.gifu.jp","hashima.gifu.jp","hichiso.gifu.jp","hida.gifu.jp","higashishirakawa.gifu.jp","ibigawa.gifu.jp","ikeda.gifu.jp","kakamigahara.gifu.jp","kani.gifu.jp","kasahara.gifu.jp","kasamatsu.gifu.jp","kawaue.gifu.jp","kitagata.gifu.jp","mino.gifu.jp","minokamo.gifu.jp","mitake.gifu.jp","mizunami.gifu.jp","motosu.gifu.jp","nakatsugawa.gifu.jp","ogaki.gifu.jp","sakahogi.gifu.jp","seki.gifu.jp","sekigahara.gifu.jp","shirakawa.gifu.jp","tajimi.gifu.jp","takayama.gifu.jp","tarui.gifu.jp","toki.gifu.jp","tomika.gifu.jp","wanouchi.gifu.jp","yamagata.gifu.jp","yaotsu.gifu.jp","yoro.gifu.jp","annaka.gunma.jp","chiyoda.gunma.jp","fujioka.gunma.jp","higashiagatsuma.gunma.jp","isesaki.gunma.jp","itakura.gunma.jp","kanna.gunma.jp","kanra.gunma.jp","katashina.gunma.jp","kawaba.gunma.jp","kiryu.gunma.jp","kusatsu.gunma.jp","maebashi.gunma.jp","meiwa.gunma.jp","midori.gunma.jp","minakami.gunma.jp","naganohara.gunma.jp","nakanojo.gunma.jp","nanmoku.gunma.jp","numata.gunma.jp","oizumi.gunma.jp","ora.gunma.jp","ota.gunma.jp","shibukawa.gunma.jp","shimonita.gunma.jp","shinto.gunma.jp","showa.gunma.jp","takasaki.gunma.jp","takayama.gunma.jp","tamamura.gunma.jp","tatebayashi.gunma.jp","tomioka.gunma.jp","tsukiyono.gunma.jp","tsumagoi.gunma.jp","ueno.gunma.jp","yoshioka.gunma.jp","asaminami.hiroshima.jp","daiwa.hiroshima.jp","etajima.hiroshima.jp","fuchu.hiroshima.jp","fukuyama.hiroshima.jp","hatsukaichi.hiroshima.jp","higashihiroshima.hiroshima.jp","hongo.hiroshima.jp","jinsekikogen.hiroshima.jp","kaita.hiroshima.jp","kui.hiroshima.jp","kumano.hiroshima.jp","kure.hiroshima.jp","mihara.hiroshima.jp","miyoshi.hiroshima.jp","naka.hiroshima.jp","onomichi.hiroshima.jp","osakikamijima.hiroshima.jp","otake.hiroshima.jp","saka.hiroshima.jp","sera.hiroshima.jp","seranishi.hiroshima.jp","shinichi.hiroshima.jp","shobara.hiroshima.jp","takehara.hiroshima.jp","abashiri.hokkaido.jp","abira.hokkaido.jp","aibetsu.hokkaido.jp","akabira.hokkaido.jp","akkeshi.hokkaido.jp","asahikawa.hokkaido.jp","ashibetsu.hokkaido.jp","ashoro.hokkaido.jp","assabu.hokkaido.jp","atsuma.hokkaido.jp","bibai.hokkaido.jp","biei.hokkaido.jp","bifuka.hokkaido.jp","bihoro.hokkaido.jp","biratori.hokkaido.jp","chippubetsu.hokkaido.jp","chitose.hokkaido.jp","date.hokkaido.jp","ebetsu.hokkaido.jp","embetsu.hokkaido.jp","eniwa.hokkaido.jp","erimo.hokkaido.jp","esan.hokkaido.jp","esashi.hokkaido.jp","fukagawa.hokkaido.jp","fukushima.hokkaido.jp","furano.hokkaido.jp","furubira.hokkaido.jp","haboro.hokkaido.jp","hakodate.hokkaido.jp","hamatonbetsu.hokkaido.jp","hidaka.hokkaido.jp","higashikagura.hokkaido.jp","higashikawa.hokkaido.jp","hiroo.hokkaido.jp","hokuryu.hokkaido.jp","hokuto.hokkaido.jp","honbetsu.hokkaido.jp","horokanai.hokkaido.jp","horonobe.hokkaido.jp","ikeda.hokkaido.jp","imakane.hokkaido.jp","ishikari.hokkaido.jp","iwamizawa.hokkaido.jp","iwanai.hokkaido.jp","kamifurano.hokkaido.jp","kamikawa.hokkaido.jp","kamishihoro.hokkaido.jp","kamisunagawa.hokkaido.jp","kamoenai.hokkaido.jp","kayabe.hokkaido.jp","kembuchi.hokkaido.jp","kikonai.hokkaido.jp","kimobetsu.hokkaido.jp","kitahiroshima.hokkaido.jp","kitami.hokkaido.jp","kiyosato.hokkaido.jp","koshimizu.hokkaido.jp","kunneppu.hokkaido.jp","kuriyama.hokkaido.jp","kuromatsunai.hokkaido.jp","kushiro.hokkaido.jp","kutchan.hokkaido.jp","kyowa.hokkaido.jp","mashike.hokkaido.jp","matsumae.hokkaido.jp","mikasa.hokkaido.jp","minamifurano.hokkaido.jp","mombetsu.hokkaido.jp","moseushi.hokkaido.jp","mukawa.hokkaido.jp","muroran.hokkaido.jp","naie.hokkaido.jp","nakagawa.hokkaido.jp","nakasatsunai.hokkaido.jp","nakatombetsu.hokkaido.jp","nanae.hokkaido.jp","nanporo.hokkaido.jp","nayoro.hokkaido.jp","nemuro.hokkaido.jp","niikappu.hokkaido.jp","niki.hokkaido.jp","nishiokoppe.hokkaido.jp","noboribetsu.hokkaido.jp","numata.hokkaido.jp","obihiro.hokkaido.jp","obira.hokkaido.jp","oketo.hokkaido.jp","okoppe.hokkaido.jp","otaru.hokkaido.jp","otobe.hokkaido.jp","otofuke.hokkaido.jp","otoineppu.hokkaido.jp","oumu.hokkaido.jp","ozora.hokkaido.jp","pippu.hokkaido.jp","rankoshi.hokkaido.jp","rebun.hokkaido.jp","rikubetsu.hokkaido.jp","rishiri.hokkaido.jp","rishirifuji.hokkaido.jp","saroma.hokkaido.jp","sarufutsu.hokkaido.jp","shakotan.hokkaido.jp","shari.hokkaido.jp","shibecha.hokkaido.jp","shibetsu.hokkaido.jp","shikabe.hokkaido.jp","shikaoi.hokkaido.jp","shimamaki.hokkaido.jp","shimizu.hokkaido.jp","shimokawa.hokkaido.jp","shinshinotsu.hokkaido.jp","shintoku.hokkaido.jp","shiranuka.hokkaido.jp","shiraoi.hokkaido.jp","shiriuchi.hokkaido.jp","sobetsu.hokkaido.jp","sunagawa.hokkaido.jp","taiki.hokkaido.jp","takasu.hokkaido.jp","takikawa.hokkaido.jp","takinoue.hokkaido.jp","teshikaga.hokkaido.jp","tobetsu.hokkaido.jp","tohma.hokkaido.jp","tomakomai.hokkaido.jp","tomari.hokkaido.jp","toya.hokkaido.jp","toyako.hokkaido.jp","toyotomi.hokkaido.jp","toyoura.hokkaido.jp","tsubetsu.hokkaido.jp","tsukigata.hokkaido.jp","urakawa.hokkaido.jp","urausu.hokkaido.jp","uryu.hokkaido.jp","utashinai.hokkaido.jp","wakkanai.hokkaido.jp","wassamu.hokkaido.jp","yakumo.hokkaido.jp","yoichi.hokkaido.jp","aioi.hyogo.jp","akashi.hyogo.jp","ako.hyogo.jp","amagasaki.hyogo.jp","aogaki.hyogo.jp","asago.hyogo.jp","ashiya.hyogo.jp","awaji.hyogo.jp","fukusaki.hyogo.jp","goshiki.hyogo.jp","harima.hyogo.jp","himeji.hyogo.jp","ichikawa.hyogo.jp","inagawa.hyogo.jp","itami.hyogo.jp","kakogawa.hyogo.jp","kamigori.hyogo.jp","kamikawa.hyogo.jp","kasai.hyogo.jp","kasuga.hyogo.jp","kawanishi.hyogo.jp","miki.hyogo.jp","minamiawaji.hyogo.jp","nishinomiya.hyogo.jp","nishiwaki.hyogo.jp","ono.hyogo.jp","sanda.hyogo.jp","sannan.hyogo.jp","sasayama.hyogo.jp","sayo.hyogo.jp","shingu.hyogo.jp","shinonsen.hyogo.jp","shiso.hyogo.jp","sumoto.hyogo.jp","taishi.hyogo.jp","taka.hyogo.jp","takarazuka.hyogo.jp","takasago.hyogo.jp","takino.hyogo.jp","tamba.hyogo.jp","tatsuno.hyogo.jp","toyooka.hyogo.jp","yabu.hyogo.jp","yashiro.hyogo.jp","yoka.hyogo.jp","yokawa.hyogo.jp","ami.ibaraki.jp","asahi.ibaraki.jp","bando.ibaraki.jp","chikusei.ibaraki.jp","daigo.ibaraki.jp","fujishiro.ibaraki.jp","hitachi.ibaraki.jp","hitachinaka.ibaraki.jp","hitachiomiya.ibaraki.jp","hitachiota.ibaraki.jp","ibaraki.ibaraki.jp","ina.ibaraki.jp","inashiki.ibaraki.jp","itako.ibaraki.jp","iwama.ibaraki.jp","joso.ibaraki.jp","kamisu.ibaraki.jp","kasama.ibaraki.jp","kashima.ibaraki.jp","kasumigaura.ibaraki.jp","koga.ibaraki.jp","miho.ibaraki.jp","mito.ibaraki.jp","moriya.ibaraki.jp","naka.ibaraki.jp","namegata.ibaraki.jp","oarai.ibaraki.jp","ogawa.ibaraki.jp","omitama.ibaraki.jp","ryugasaki.ibaraki.jp","sakai.ibaraki.jp","sakuragawa.ibaraki.jp","shimodate.ibaraki.jp","shimotsuma.ibaraki.jp","shirosato.ibaraki.jp","sowa.ibaraki.jp","suifu.ibaraki.jp","takahagi.ibaraki.jp","tamatsukuri.ibaraki.jp","tokai.ibaraki.jp","tomobe.ibaraki.jp","tone.ibaraki.jp","toride.ibaraki.jp","tsuchiura.ibaraki.jp","tsukuba.ibaraki.jp","uchihara.ibaraki.jp","ushiku.ibaraki.jp","yachiyo.ibaraki.jp","yamagata.ibaraki.jp","yawara.ibaraki.jp","yuki.ibaraki.jp","anamizu.ishikawa.jp","hakui.ishikawa.jp","hakusan.ishikawa.jp","kaga.ishikawa.jp","kahoku.ishikawa.jp","kanazawa.ishikawa.jp","kawakita.ishikawa.jp","komatsu.ishikawa.jp","nakanoto.ishikawa.jp","nanao.ishikawa.jp","nomi.ishikawa.jp","nonoichi.ishikawa.jp","noto.ishikawa.jp","shika.ishikawa.jp","suzu.ishikawa.jp","tsubata.ishikawa.jp","tsurugi.ishikawa.jp","uchinada.ishikawa.jp","wajima.ishikawa.jp","fudai.iwate.jp","fujisawa.iwate.jp","hanamaki.iwate.jp","hiraizumi.iwate.jp","hirono.iwate.jp","ichinohe.iwate.jp","ichinoseki.iwate.jp","iwaizumi.iwate.jp","iwate.iwate.jp","joboji.iwate.jp","kamaishi.iwate.jp","kanegasaki.iwate.jp","karumai.iwate.jp","kawai.iwate.jp","kitakami.iwate.jp","kuji.iwate.jp","kunohe.iwate.jp","kuzumaki.iwate.jp","miyako.iwate.jp","mizusawa.iwate.jp","morioka.iwate.jp","ninohe.iwate.jp","noda.iwate.jp","ofunato.iwate.jp","oshu.iwate.jp","otsuchi.iwate.jp","rikuzentakata.iwate.jp","shiwa.iwate.jp","shizukuishi.iwate.jp","sumita.iwate.jp","tanohata.iwate.jp","tono.iwate.jp","yahaba.iwate.jp","yamada.iwate.jp","ayagawa.kagawa.jp","higashikagawa.kagawa.jp","kanonji.kagawa.jp","kotohira.kagawa.jp","manno.kagawa.jp","marugame.kagawa.jp","mitoyo.kagawa.jp","naoshima.kagawa.jp","sanuki.kagawa.jp","tadotsu.kagawa.jp","takamatsu.kagawa.jp","tonosho.kagawa.jp","uchinomi.kagawa.jp","utazu.kagawa.jp","zentsuji.kagawa.jp","akune.kagoshima.jp","amami.kagoshima.jp","hioki.kagoshima.jp","isa.kagoshima.jp","isen.kagoshima.jp","izumi.kagoshima.jp","kagoshima.kagoshima.jp","kanoya.kagoshima.jp","kawanabe.kagoshima.jp","kinko.kagoshima.jp","kouyama.kagoshima.jp","makurazaki.kagoshima.jp","matsumoto.kagoshima.jp","minamitane.kagoshima.jp","nakatane.kagoshima.jp","nishinoomote.kagoshima.jp","satsumasendai.kagoshima.jp","soo.kagoshima.jp","tarumizu.kagoshima.jp","yusui.kagoshima.jp","aikawa.kanagawa.jp","atsugi.kanagawa.jp","ayase.kanagawa.jp","chigasaki.kanagawa.jp","ebina.kanagawa.jp","fujisawa.kanagawa.jp","hadano.kanagawa.jp","hakone.kanagawa.jp","hiratsuka.kanagawa.jp","isehara.kanagawa.jp","kaisei.kanagawa.jp","kamakura.kanagawa.jp","kiyokawa.kanagawa.jp","matsuda.kanagawa.jp","minamiashigara.kanagawa.jp","miura.kanagawa.jp","nakai.kanagawa.jp","ninomiya.kanagawa.jp","odawara.kanagawa.jp","oi.kanagawa.jp","oiso.kanagawa.jp","sagamihara.kanagawa.jp","samukawa.kanagawa.jp","tsukui.kanagawa.jp","yamakita.kanagawa.jp","yamato.kanagawa.jp","yokosuka.kanagawa.jp","yugawara.kanagawa.jp","zama.kanagawa.jp","zushi.kanagawa.jp","aki.kochi.jp","geisei.kochi.jp","hidaka.kochi.jp","higashitsuno.kochi.jp","ino.kochi.jp","kagami.kochi.jp","kami.kochi.jp","kitagawa.kochi.jp","kochi.kochi.jp","mihara.kochi.jp","motoyama.kochi.jp","muroto.kochi.jp","nahari.kochi.jp","nakamura.kochi.jp","nankoku.kochi.jp","nishitosa.kochi.jp","niyodogawa.kochi.jp","ochi.kochi.jp","okawa.kochi.jp","otoyo.kochi.jp","otsuki.kochi.jp","sakawa.kochi.jp","sukumo.kochi.jp","susaki.kochi.jp","tosa.kochi.jp","tosashimizu.kochi.jp","toyo.kochi.jp","tsuno.kochi.jp","umaji.kochi.jp","yasuda.kochi.jp","yusuhara.kochi.jp","amakusa.kumamoto.jp","arao.kumamoto.jp","aso.kumamoto.jp","choyo.kumamoto.jp","gyokuto.kumamoto.jp","kamiamakusa.kumamoto.jp","kikuchi.kumamoto.jp","kumamoto.kumamoto.jp","mashiki.kumamoto.jp","mifune.kumamoto.jp","minamata.kumamoto.jp","minamioguni.kumamoto.jp","nagasu.kumamoto.jp","nishihara.kumamoto.jp","oguni.kumamoto.jp","ozu.kumamoto.jp","sumoto.kumamoto.jp","takamori.kumamoto.jp","uki.kumamoto.jp","uto.kumamoto.jp","yamaga.kumamoto.jp","yamato.kumamoto.jp","yatsushiro.kumamoto.jp","ayabe.kyoto.jp","fukuchiyama.kyoto.jp","higashiyama.kyoto.jp","ide.kyoto.jp","ine.kyoto.jp","joyo.kyoto.jp","kameoka.kyoto.jp","kamo.kyoto.jp","kita.kyoto.jp","kizu.kyoto.jp","kumiyama.kyoto.jp","kyotamba.kyoto.jp","kyotanabe.kyoto.jp","kyotango.kyoto.jp","maizuru.kyoto.jp","minami.kyoto.jp","minamiyamashiro.kyoto.jp","miyazu.kyoto.jp","muko.kyoto.jp","nagaokakyo.kyoto.jp","nakagyo.kyoto.jp","nantan.kyoto.jp","oyamazaki.kyoto.jp","sakyo.kyoto.jp","seika.kyoto.jp","tanabe.kyoto.jp","uji.kyoto.jp","ujitawara.kyoto.jp","wazuka.kyoto.jp","yamashina.kyoto.jp","yawata.kyoto.jp","asahi.mie.jp","inabe.mie.jp","ise.mie.jp","kameyama.mie.jp","kawagoe.mie.jp","kiho.mie.jp","kisosaki.mie.jp","kiwa.mie.jp","komono.mie.jp","kumano.mie.jp","kuwana.mie.jp","matsusaka.mie.jp","meiwa.mie.jp","mihama.mie.jp","minamiise.mie.jp","misugi.mie.jp","miyama.mie.jp","nabari.mie.jp","shima.mie.jp","suzuka.mie.jp","tado.mie.jp","taiki.mie.jp","taki.mie.jp","tamaki.mie.jp","toba.mie.jp","tsu.mie.jp","udono.mie.jp","ureshino.mie.jp","watarai.mie.jp","yokkaichi.mie.jp","furukawa.miyagi.jp","higashimatsushima.miyagi.jp","ishinomaki.miyagi.jp","iwanuma.miyagi.jp","kakuda.miyagi.jp","kami.miyagi.jp","kawasaki.miyagi.jp","marumori.miyagi.jp","matsushima.miyagi.jp","minamisanriku.miyagi.jp","misato.miyagi.jp","murata.miyagi.jp","natori.miyagi.jp","ogawara.miyagi.jp","ohira.miyagi.jp","onagawa.miyagi.jp","osaki.miyagi.jp","rifu.miyagi.jp","semine.miyagi.jp","shibata.miyagi.jp","shichikashuku.miyagi.jp","shikama.miyagi.jp","shiogama.miyagi.jp","shiroishi.miyagi.jp","tagajo.miyagi.jp","taiwa.miyagi.jp","tome.miyagi.jp","tomiya.miyagi.jp","wakuya.miyagi.jp","watari.miyagi.jp","yamamoto.miyagi.jp","zao.miyagi.jp","aya.miyazaki.jp","ebino.miyazaki.jp","gokase.miyazaki.jp","hyuga.miyazaki.jp","kadogawa.miyazaki.jp","kawaminami.miyazaki.jp","kijo.miyazaki.jp","kitagawa.miyazaki.jp","kitakata.miyazaki.jp","kitaura.miyazaki.jp","kobayashi.miyazaki.jp","kunitomi.miyazaki.jp","kushima.miyazaki.jp","mimata.miyazaki.jp","miyakonojo.miyazaki.jp","miyazaki.miyazaki.jp","morotsuka.miyazaki.jp","nichinan.miyazaki.jp","nishimera.miyazaki.jp","nobeoka.miyazaki.jp","saito.miyazaki.jp","shiiba.miyazaki.jp","shintomi.miyazaki.jp","takaharu.miyazaki.jp","takanabe.miyazaki.jp","takazaki.miyazaki.jp","tsuno.miyazaki.jp","achi.nagano.jp","agematsu.nagano.jp","anan.nagano.jp","aoki.nagano.jp","asahi.nagano.jp","azumino.nagano.jp","chikuhoku.nagano.jp","chikuma.nagano.jp","chino.nagano.jp","fujimi.nagano.jp","hakuba.nagano.jp","hara.nagano.jp","hiraya.nagano.jp","iida.nagano.jp","iijima.nagano.jp","iiyama.nagano.jp","iizuna.nagano.jp","ikeda.nagano.jp","ikusaka.nagano.jp","ina.nagano.jp","karuizawa.nagano.jp","kawakami.nagano.jp","kiso.nagano.jp","kisofukushima.nagano.jp","kitaaiki.nagano.jp","komagane.nagano.jp","komoro.nagano.jp","matsukawa.nagano.jp","matsumoto.nagano.jp","miasa.nagano.jp","minamiaiki.nagano.jp","minamimaki.nagano.jp","minamiminowa.nagano.jp","minowa.nagano.jp","miyada.nagano.jp","miyota.nagano.jp","mochizuki.nagano.jp","nagano.nagano.jp","nagawa.nagano.jp","nagiso.nagano.jp","nakagawa.nagano.jp","nakano.nagano.jp","nozawaonsen.nagano.jp","obuse.nagano.jp","ogawa.nagano.jp","okaya.nagano.jp","omachi.nagano.jp","omi.nagano.jp","ookuwa.nagano.jp","ooshika.nagano.jp","otaki.nagano.jp","otari.nagano.jp","sakae.nagano.jp","sakaki.nagano.jp","saku.nagano.jp","sakuho.nagano.jp","shimosuwa.nagano.jp","shinanomachi.nagano.jp","shiojiri.nagano.jp","suwa.nagano.jp","suzaka.nagano.jp","takagi.nagano.jp","takamori.nagano.jp","takayama.nagano.jp","tateshina.nagano.jp","tatsuno.nagano.jp","togakushi.nagano.jp","togura.nagano.jp","tomi.nagano.jp","ueda.nagano.jp","wada.nagano.jp","yamagata.nagano.jp","yamanouchi.nagano.jp","yasaka.nagano.jp","yasuoka.nagano.jp","chijiwa.nagasaki.jp","futsu.nagasaki.jp","goto.nagasaki.jp","hasami.nagasaki.jp","hirado.nagasaki.jp","iki.nagasaki.jp","isahaya.nagasaki.jp","kawatana.nagasaki.jp","kuchinotsu.nagasaki.jp","matsuura.nagasaki.jp","nagasaki.nagasaki.jp","obama.nagasaki.jp","omura.nagasaki.jp","oseto.nagasaki.jp","saikai.nagasaki.jp","sasebo.nagasaki.jp","seihi.nagasaki.jp","shimabara.nagasaki.jp","shinkamigoto.nagasaki.jp","togitsu.nagasaki.jp","tsushima.nagasaki.jp","unzen.nagasaki.jp","ando.nara.jp","gose.nara.jp","heguri.nara.jp","higashiyoshino.nara.jp","ikaruga.nara.jp","ikoma.nara.jp","kamikitayama.nara.jp","kanmaki.nara.jp","kashiba.nara.jp","kashihara.nara.jp","katsuragi.nara.jp","kawai.nara.jp","kawakami.nara.jp","kawanishi.nara.jp","koryo.nara.jp","kurotaki.nara.jp","mitsue.nara.jp","miyake.nara.jp","nara.nara.jp","nosegawa.nara.jp","oji.nara.jp","ouda.nara.jp","oyodo.nara.jp","sakurai.nara.jp","sango.nara.jp","shimoichi.nara.jp","shimokitayama.nara.jp","shinjo.nara.jp","soni.nara.jp","takatori.nara.jp","tawaramoto.nara.jp","tenkawa.nara.jp","tenri.nara.jp","uda.nara.jp","yamatokoriyama.nara.jp","yamatotakada.nara.jp","yamazoe.nara.jp","yoshino.nara.jp","aga.niigata.jp","agano.niigata.jp","gosen.niigata.jp","itoigawa.niigata.jp","izumozaki.niigata.jp","joetsu.niigata.jp","kamo.niigata.jp","kariwa.niigata.jp","kashiwazaki.niigata.jp","minamiuonuma.niigata.jp","mitsuke.niigata.jp","muika.niigata.jp","murakami.niigata.jp","myoko.niigata.jp","nagaoka.niigata.jp","niigata.niigata.jp","ojiya.niigata.jp","omi.niigata.jp","sado.niigata.jp","sanjo.niigata.jp","seiro.niigata.jp","seirou.niigata.jp","sekikawa.niigata.jp","shibata.niigata.jp","tagami.niigata.jp","tainai.niigata.jp","tochio.niigata.jp","tokamachi.niigata.jp","tsubame.niigata.jp","tsunan.niigata.jp","uonuma.niigata.jp","yahiko.niigata.jp","yoita.niigata.jp","yuzawa.niigata.jp","beppu.oita.jp","bungoono.oita.jp","bungotakada.oita.jp","hasama.oita.jp","hiji.oita.jp","himeshima.oita.jp","hita.oita.jp","kamitsue.oita.jp","kokonoe.oita.jp","kuju.oita.jp","kunisaki.oita.jp","kusu.oita.jp","oita.oita.jp","saiki.oita.jp","taketa.oita.jp","tsukumi.oita.jp","usa.oita.jp","usuki.oita.jp","yufu.oita.jp","akaiwa.okayama.jp","asakuchi.okayama.jp","bizen.okayama.jp","hayashima.okayama.jp","ibara.okayama.jp","kagamino.okayama.jp","kasaoka.okayama.jp","kibichuo.okayama.jp","kumenan.okayama.jp","kurashiki.okayama.jp","maniwa.okayama.jp","misaki.okayama.jp","nagi.okayama.jp","niimi.okayama.jp","nishiawakura.okayama.jp","okayama.okayama.jp","satosho.okayama.jp","setouchi.okayama.jp","shinjo.okayama.jp","shoo.okayama.jp","soja.okayama.jp","takahashi.okayama.jp","tamano.okayama.jp","tsuyama.okayama.jp","wake.okayama.jp","yakage.okayama.jp","aguni.okinawa.jp","ginowan.okinawa.jp","ginoza.okinawa.jp","gushikami.okinawa.jp","haebaru.okinawa.jp","higashi.okinawa.jp","hirara.okinawa.jp","iheya.okinawa.jp","ishigaki.okinawa.jp","ishikawa.okinawa.jp","itoman.okinawa.jp","izena.okinawa.jp","kadena.okinawa.jp","kin.okinawa.jp","kitadaito.okinawa.jp","kitanakagusuku.okinawa.jp","kumejima.okinawa.jp","kunigami.okinawa.jp","minamidaito.okinawa.jp","motobu.okinawa.jp","nago.okinawa.jp","naha.okinawa.jp","nakagusuku.okinawa.jp","nakijin.okinawa.jp","nanjo.okinawa.jp","nishihara.okinawa.jp","ogimi.okinawa.jp","okinawa.okinawa.jp","onna.okinawa.jp","shimoji.okinawa.jp","taketomi.okinawa.jp","tarama.okinawa.jp","tokashiki.okinawa.jp","tomigusuku.okinawa.jp","tonaki.okinawa.jp","urasoe.okinawa.jp","uruma.okinawa.jp","yaese.okinawa.jp","yomitan.okinawa.jp","yonabaru.okinawa.jp","yonaguni.okinawa.jp","zamami.okinawa.jp","abeno.osaka.jp","chihayaakasaka.osaka.jp","chuo.osaka.jp","daito.osaka.jp","fujiidera.osaka.jp","habikino.osaka.jp","hannan.osaka.jp","higashiosaka.osaka.jp","higashisumiyoshi.osaka.jp","higashiyodogawa.osaka.jp","hirakata.osaka.jp","ibaraki.osaka.jp","ikeda.osaka.jp","izumi.osaka.jp","izumiotsu.osaka.jp","izumisano.osaka.jp","kadoma.osaka.jp","kaizuka.osaka.jp","kanan.osaka.jp","kashiwara.osaka.jp","katano.osaka.jp","kawachinagano.osaka.jp","kishiwada.osaka.jp","kita.osaka.jp","kumatori.osaka.jp","matsubara.osaka.jp","minato.osaka.jp","minoh.osaka.jp","misaki.osaka.jp","moriguchi.osaka.jp","neyagawa.osaka.jp","nishi.osaka.jp","nose.osaka.jp","osakasayama.osaka.jp","sakai.osaka.jp","sayama.osaka.jp","sennan.osaka.jp","settsu.osaka.jp","shijonawate.osaka.jp","shimamoto.osaka.jp","suita.osaka.jp","tadaoka.osaka.jp","taishi.osaka.jp","tajiri.osaka.jp","takaishi.osaka.jp","takatsuki.osaka.jp","tondabayashi.osaka.jp","toyonaka.osaka.jp","toyono.osaka.jp","yao.osaka.jp","ariake.saga.jp","arita.saga.jp","fukudomi.saga.jp","genkai.saga.jp","hamatama.saga.jp","hizen.saga.jp","imari.saga.jp","kamimine.saga.jp","kanzaki.saga.jp","karatsu.saga.jp","kashima.saga.jp","kitagata.saga.jp","kitahata.saga.jp","kiyama.saga.jp","kouhoku.saga.jp","kyuragi.saga.jp","nishiarita.saga.jp","ogi.saga.jp","omachi.saga.jp","ouchi.saga.jp","saga.saga.jp","shiroishi.saga.jp","taku.saga.jp","tara.saga.jp","tosu.saga.jp","yoshinogari.saga.jp","arakawa.saitama.jp","asaka.saitama.jp","chichibu.saitama.jp","fujimi.saitama.jp","fujimino.saitama.jp","fukaya.saitama.jp","hanno.saitama.jp","hanyu.saitama.jp","hasuda.saitama.jp","hatogaya.saitama.jp","hatoyama.saitama.jp","hidaka.saitama.jp","higashichichibu.saitama.jp","higashimatsuyama.saitama.jp","honjo.saitama.jp","ina.saitama.jp","iruma.saitama.jp","iwatsuki.saitama.jp","kamiizumi.saitama.jp","kamikawa.saitama.jp","kamisato.saitama.jp","kasukabe.saitama.jp","kawagoe.saitama.jp","kawaguchi.saitama.jp","kawajima.saitama.jp","kazo.saitama.jp","kitamoto.saitama.jp","koshigaya.saitama.jp","kounosu.saitama.jp","kuki.saitama.jp","kumagaya.saitama.jp","matsubushi.saitama.jp","minano.saitama.jp","misato.saitama.jp","miyashiro.saitama.jp","miyoshi.saitama.jp","moroyama.saitama.jp","nagatoro.saitama.jp","namegawa.saitama.jp","niiza.saitama.jp","ogano.saitama.jp","ogawa.saitama.jp","ogose.saitama.jp","okegawa.saitama.jp","omiya.saitama.jp","otaki.saitama.jp","ranzan.saitama.jp","ryokami.saitama.jp","saitama.saitama.jp","sakado.saitama.jp","satte.saitama.jp","sayama.saitama.jp","shiki.saitama.jp","shiraoka.saitama.jp","soka.saitama.jp","sugito.saitama.jp","toda.saitama.jp","tokigawa.saitama.jp","tokorozawa.saitama.jp","tsurugashima.saitama.jp","urawa.saitama.jp","warabi.saitama.jp","yashio.saitama.jp","yokoze.saitama.jp","yono.saitama.jp","yorii.saitama.jp","yoshida.saitama.jp","yoshikawa.saitama.jp","yoshimi.saitama.jp","aisho.shiga.jp","gamo.shiga.jp","higashiomi.shiga.jp","hikone.shiga.jp","koka.shiga.jp","konan.shiga.jp","kosei.shiga.jp","koto.shiga.jp","kusatsu.shiga.jp","maibara.shiga.jp","moriyama.shiga.jp","nagahama.shiga.jp","nishiazai.shiga.jp","notogawa.shiga.jp","omihachiman.shiga.jp","otsu.shiga.jp","ritto.shiga.jp","ryuoh.shiga.jp","takashima.shiga.jp","takatsuki.shiga.jp","torahime.shiga.jp","toyosato.shiga.jp","yasu.shiga.jp","akagi.shimane.jp","ama.shimane.jp","gotsu.shimane.jp","hamada.shimane.jp","higashiizumo.shimane.jp","hikawa.shimane.jp","hikimi.shimane.jp","izumo.shimane.jp","kakinoki.shimane.jp","masuda.shimane.jp","matsue.shimane.jp","misato.shimane.jp","nishinoshima.shimane.jp","ohda.shimane.jp","okinoshima.shimane.jp","okuizumo.shimane.jp","shimane.shimane.jp","tamayu.shimane.jp","tsuwano.shimane.jp","unnan.shimane.jp","yakumo.shimane.jp","yasugi.shimane.jp","yatsuka.shimane.jp","arai.shizuoka.jp","atami.shizuoka.jp","fuji.shizuoka.jp","fujieda.shizuoka.jp","fujikawa.shizuoka.jp","fujinomiya.shizuoka.jp","fukuroi.shizuoka.jp","gotemba.shizuoka.jp","haibara.shizuoka.jp","hamamatsu.shizuoka.jp","higashiizu.shizuoka.jp","ito.shizuoka.jp","iwata.shizuoka.jp","izu.shizuoka.jp","izunokuni.shizuoka.jp","kakegawa.shizuoka.jp","kannami.shizuoka.jp","kawanehon.shizuoka.jp","kawazu.shizuoka.jp","kikugawa.shizuoka.jp","kosai.shizuoka.jp","makinohara.shizuoka.jp","matsuzaki.shizuoka.jp","minamiizu.shizuoka.jp","mishima.shizuoka.jp","morimachi.shizuoka.jp","nishiizu.shizuoka.jp","numazu.shizuoka.jp","omaezaki.shizuoka.jp","shimada.shizuoka.jp","shimizu.shizuoka.jp","shimoda.shizuoka.jp","shizuoka.shizuoka.jp","susono.shizuoka.jp","yaizu.shizuoka.jp","yoshida.shizuoka.jp","ashikaga.tochigi.jp","bato.tochigi.jp","haga.tochigi.jp","ichikai.tochigi.jp","iwafune.tochigi.jp","kaminokawa.tochigi.jp","kanuma.tochigi.jp","karasuyama.tochigi.jp","kuroiso.tochigi.jp","mashiko.tochigi.jp","mibu.tochigi.jp","moka.tochigi.jp","motegi.tochigi.jp","nasu.tochigi.jp","nasushiobara.tochigi.jp","nikko.tochigi.jp","nishikata.tochigi.jp","nogi.tochigi.jp","ohira.tochigi.jp","ohtawara.tochigi.jp","oyama.tochigi.jp","sakura.tochigi.jp","sano.tochigi.jp","shimotsuke.tochigi.jp","shioya.tochigi.jp","takanezawa.tochigi.jp","tochigi.tochigi.jp","tsuga.tochigi.jp","ujiie.tochigi.jp","utsunomiya.tochigi.jp","yaita.tochigi.jp","aizumi.tokushima.jp","anan.tokushima.jp","ichiba.tokushima.jp","itano.tokushima.jp","kainan.tokushima.jp","komatsushima.tokushima.jp","matsushige.tokushima.jp","mima.tokushima.jp","minami.tokushima.jp","miyoshi.tokushima.jp","mugi.tokushima.jp","nakagawa.tokushima.jp","naruto.tokushima.jp","sanagochi.tokushima.jp","shishikui.tokushima.jp","tokushima.tokushima.jp","wajiki.tokushima.jp","adachi.tokyo.jp","akiruno.tokyo.jp","akishima.tokyo.jp","aogashima.tokyo.jp","arakawa.tokyo.jp","bunkyo.tokyo.jp","chiyoda.tokyo.jp","chofu.tokyo.jp","chuo.tokyo.jp","edogawa.tokyo.jp","fuchu.tokyo.jp","fussa.tokyo.jp","hachijo.tokyo.jp","hachioji.tokyo.jp","hamura.tokyo.jp","higashikurume.tokyo.jp","higashimurayama.tokyo.jp","higashiyamato.tokyo.jp","hino.tokyo.jp","hinode.tokyo.jp","hinohara.tokyo.jp","inagi.tokyo.jp","itabashi.tokyo.jp","katsushika.tokyo.jp","kita.tokyo.jp","kiyose.tokyo.jp","kodaira.tokyo.jp","koganei.tokyo.jp","kokubunji.tokyo.jp","komae.tokyo.jp","koto.tokyo.jp","kouzushima.tokyo.jp","kunitachi.tokyo.jp","machida.tokyo.jp","meguro.tokyo.jp","minato.tokyo.jp","mitaka.tokyo.jp","mizuho.tokyo.jp","musashimurayama.tokyo.jp","musashino.tokyo.jp","nakano.tokyo.jp","nerima.tokyo.jp","ogasawara.tokyo.jp","okutama.tokyo.jp","ome.tokyo.jp","oshima.tokyo.jp","ota.tokyo.jp","setagaya.tokyo.jp","shibuya.tokyo.jp","shinagawa.tokyo.jp","shinjuku.tokyo.jp","suginami.tokyo.jp","sumida.tokyo.jp","tachikawa.tokyo.jp","taito.tokyo.jp","tama.tokyo.jp","toshima.tokyo.jp","chizu.tottori.jp","hino.tottori.jp","kawahara.tottori.jp","koge.tottori.jp","kotoura.tottori.jp","misasa.tottori.jp","nanbu.tottori.jp","nichinan.tottori.jp","sakaiminato.tottori.jp","tottori.tottori.jp","wakasa.tottori.jp","yazu.tottori.jp","yonago.tottori.jp","asahi.toyama.jp","fuchu.toyama.jp","fukumitsu.toyama.jp","funahashi.toyama.jp","himi.toyama.jp","imizu.toyama.jp","inami.toyama.jp","johana.toyama.jp","kamiichi.toyama.jp","kurobe.toyama.jp","nakaniikawa.toyama.jp","namerikawa.toyama.jp","nanto.toyama.jp","nyuzen.toyama.jp","oyabe.toyama.jp","taira.toyama.jp","takaoka.toyama.jp","tateyama.toyama.jp","toga.toyama.jp","tonami.toyama.jp","toyama.toyama.jp","unazuki.toyama.jp","uozu.toyama.jp","yamada.toyama.jp","arida.wakayama.jp","aridagawa.wakayama.jp","gobo.wakayama.jp","hashimoto.wakayama.jp","hidaka.wakayama.jp","hirogawa.wakayama.jp","inami.wakayama.jp","iwade.wakayama.jp","kainan.wakayama.jp","kamitonda.wakayama.jp","katsuragi.wakayama.jp","kimino.wakayama.jp","kinokawa.wakayama.jp","kitayama.wakayama.jp","koya.wakayama.jp","koza.wakayama.jp","kozagawa.wakayama.jp","kudoyama.wakayama.jp","kushimoto.wakayama.jp","mihama.wakayama.jp","misato.wakayama.jp","nachikatsuura.wakayama.jp","shingu.wakayama.jp","shirahama.wakayama.jp","taiji.wakayama.jp","tanabe.wakayama.jp","wakayama.wakayama.jp","yuasa.wakayama.jp","yura.wakayama.jp","asahi.yamagata.jp","funagata.yamagata.jp","higashine.yamagata.jp","iide.yamagata.jp","kahoku.yamagata.jp","kaminoyama.yamagata.jp","kaneyama.yamagata.jp","kawanishi.yamagata.jp","mamurogawa.yamagata.jp","mikawa.yamagata.jp","murayama.yamagata.jp","nagai.yamagata.jp","nakayama.yamagata.jp","nanyo.yamagata.jp","nishikawa.yamagata.jp","obanazawa.yamagata.jp","oe.yamagata.jp","oguni.yamagata.jp","ohkura.yamagata.jp","oishida.yamagata.jp","sagae.yamagata.jp","sakata.yamagata.jp","sakegawa.yamagata.jp","shinjo.yamagata.jp","shirataka.yamagata.jp","shonai.yamagata.jp","takahata.yamagata.jp","tendo.yamagata.jp","tozawa.yamagata.jp","tsuruoka.yamagata.jp","yamagata.yamagata.jp","yamanobe.yamagata.jp","yonezawa.yamagata.jp","yuza.yamagata.jp","abu.yamaguchi.jp","hagi.yamaguchi.jp","hikari.yamaguchi.jp","hofu.yamaguchi.jp","iwakuni.yamaguchi.jp","kudamatsu.yamaguchi.jp","mitou.yamaguchi.jp","nagato.yamaguchi.jp","oshima.yamaguchi.jp","shimonoseki.yamaguchi.jp","shunan.yamaguchi.jp","tabuse.yamaguchi.jp","tokuyama.yamaguchi.jp","toyota.yamaguchi.jp","ube.yamaguchi.jp","yuu.yamaguchi.jp","chuo.yamanashi.jp","doshi.yamanashi.jp","fuefuki.yamanashi.jp","fujikawa.yamanashi.jp","fujikawaguchiko.yamanashi.jp","fujiyoshida.yamanashi.jp","hayakawa.yamanashi.jp","hokuto.yamanashi.jp","ichikawamisato.yamanashi.jp","kai.yamanashi.jp","kofu.yamanashi.jp","koshu.yamanashi.jp","kosuge.yamanashi.jp","minami-alps.yamanashi.jp","minobu.yamanashi.jp","nakamichi.yamanashi.jp","nanbu.yamanashi.jp","narusawa.yamanashi.jp","nirasaki.yamanashi.jp","nishikatsura.yamanashi.jp","oshino.yamanashi.jp","otsuki.yamanashi.jp","showa.yamanashi.jp","tabayama.yamanashi.jp","tsuru.yamanashi.jp","uenohara.yamanashi.jp","yamanakako.yamanashi.jp","yamanashi.yamanashi.jp","ke","ac.ke","co.ke","go.ke","info.ke","me.ke","mobi.ke","ne.ke","or.ke","sc.ke","kg","org.kg","net.kg","com.kg","edu.kg","gov.kg","mil.kg","*.kh","ki","edu.ki","biz.ki","net.ki","org.ki","gov.ki","info.ki","com.ki","km","org.km","nom.km","gov.km","prd.km","tm.km","edu.km","mil.km","ass.km","com.km","coop.km","asso.km","presse.km","medecin.km","notaires.km","pharmaciens.km","veterinaire.km","gouv.km","kn","net.kn","org.kn","edu.kn","gov.kn","kp","com.kp","edu.kp","gov.kp","org.kp","rep.kp","tra.kp","kr","ac.kr","co.kr","es.kr","go.kr","hs.kr","kg.kr","mil.kr","ms.kr","ne.kr","or.kr","pe.kr","re.kr","sc.kr","busan.kr","chungbuk.kr","chungnam.kr","daegu.kr","daejeon.kr","gangwon.kr","gwangju.kr","gyeongbuk.kr","gyeonggi.kr","gyeongnam.kr","incheon.kr","jeju.kr","jeonbuk.kr","jeonnam.kr","seoul.kr","ulsan.kr","kw","com.kw","edu.kw","emb.kw","gov.kw","ind.kw","net.kw","org.kw","ky","edu.ky","gov.ky","com.ky","org.ky","net.ky","kz","org.kz","edu.kz","net.kz","gov.kz","mil.kz","com.kz","la","int.la","net.la","info.la","edu.la","gov.la","per.la","com.la","org.la","lb","com.lb","edu.lb","gov.lb","net.lb","org.lb","lc","com.lc","net.lc","co.lc","org.lc","edu.lc","gov.lc","li","lk","gov.lk","sch.lk","net.lk","int.lk","com.lk","org.lk","edu.lk","ngo.lk","soc.lk","web.lk","ltd.lk","assn.lk","grp.lk","hotel.lk","ac.lk","lr","com.lr","edu.lr","gov.lr","org.lr","net.lr","ls","co.ls","org.ls","lt","gov.lt","lu","lv","com.lv","edu.lv","gov.lv","org.lv","mil.lv","id.lv","net.lv","asn.lv","conf.lv","ly","com.ly","net.ly","gov.ly","plc.ly","edu.ly","sch.ly","med.ly","org.ly","id.ly","ma","co.ma","net.ma","gov.ma","org.ma","ac.ma","press.ma","mc","tm.mc","asso.mc","md","me","co.me","net.me","org.me","edu.me","ac.me","gov.me","its.me","priv.me","mg","org.mg","nom.mg","gov.mg","prd.mg","tm.mg","edu.mg","mil.mg","com.mg","co.mg","mh","mil","mk","com.mk","org.mk","net.mk","edu.mk","gov.mk","inf.mk","name.mk","ml","com.ml","edu.ml","gouv.ml","gov.ml","net.ml","org.ml","presse.ml","*.mm","mn","gov.mn","edu.mn","org.mn","mo","com.mo","net.mo","org.mo","edu.mo","gov.mo","mobi","mp","mq","mr","gov.mr","ms","com.ms","edu.ms","gov.ms","net.ms","org.ms","mt","com.mt","edu.mt","net.mt","org.mt","mu","com.mu","net.mu","org.mu","gov.mu","ac.mu","co.mu","or.mu","museum","academy.museum","agriculture.museum","air.museum","airguard.museum","alabama.museum","alaska.museum","amber.museum","ambulance.museum","american.museum","americana.museum","americanantiques.museum","americanart.museum","amsterdam.museum","and.museum","annefrank.museum","anthro.museum","anthropology.museum","antiques.museum","aquarium.museum","arboretum.museum","archaeological.museum","archaeology.museum","architecture.museum","art.museum","artanddesign.museum","artcenter.museum","artdeco.museum","arteducation.museum","artgallery.museum","arts.museum","artsandcrafts.museum","asmatart.museum","assassination.museum","assisi.museum","association.museum","astronomy.museum","atlanta.museum","austin.museum","australia.museum","automotive.museum","aviation.museum","axis.museum","badajoz.museum","baghdad.museum","bahn.museum","bale.museum","baltimore.museum","barcelona.museum","baseball.museum","basel.museum","baths.museum","bauern.museum","beauxarts.museum","beeldengeluid.museum","bellevue.museum","bergbau.museum","berkeley.museum","berlin.museum","bern.museum","bible.museum","bilbao.museum","bill.museum","birdart.museum","birthplace.museum","bonn.museum","boston.museum","botanical.museum","botanicalgarden.museum","botanicgarden.museum","botany.museum","brandywinevalley.museum","brasil.museum","bristol.museum","british.museum","britishcolumbia.museum","broadcast.museum","brunel.museum","brussel.museum","brussels.museum","bruxelles.museum","building.museum","burghof.museum","bus.museum","bushey.museum","cadaques.museum","california.museum","cambridge.museum","can.museum","canada.museum","capebreton.museum","carrier.museum","cartoonart.museum","casadelamoneda.museum","castle.museum","castres.museum","celtic.museum","center.museum","chattanooga.museum","cheltenham.museum","chesapeakebay.museum","chicago.museum","children.museum","childrens.museum","childrensgarden.museum","chiropractic.museum","chocolate.museum","christiansburg.museum","cincinnati.museum","cinema.museum","circus.museum","civilisation.museum","civilization.museum","civilwar.museum","clinton.museum","clock.museum","coal.museum","coastaldefence.museum","cody.museum","coldwar.museum","collection.museum","colonialwilliamsburg.museum","coloradoplateau.museum","columbia.museum","columbus.museum","communication.museum","communications.museum","community.museum","computer.museum","computerhistory.museum","comunicações.museum","contemporary.museum","contemporaryart.museum","convent.museum","copenhagen.museum","corporation.museum","correios-e-telecomunicações.museum","corvette.museum","costume.museum","countryestate.museum","county.museum","crafts.museum","cranbrook.museum","creation.museum","cultural.museum","culturalcenter.museum","culture.museum","cyber.museum","cymru.museum","dali.museum","dallas.museum","database.museum","ddr.museum","decorativearts.museum","delaware.museum","delmenhorst.museum","denmark.museum","depot.museum","design.museum","detroit.museum","dinosaur.museum","discovery.museum","dolls.museum","donostia.museum","durham.museum","eastafrica.museum","eastcoast.museum","education.museum","educational.museum","egyptian.museum","eisenbahn.museum","elburg.museum","elvendrell.museum","embroidery.museum","encyclopedic.museum","england.museum","entomology.museum","environment.museum","environmentalconservation.museum","epilepsy.museum","essex.museum","estate.museum","ethnology.museum","exeter.museum","exhibition.museum","family.museum","farm.museum","farmequipment.museum","farmers.museum","farmstead.museum","field.museum","figueres.museum","filatelia.museum","film.museum","fineart.museum","finearts.museum","finland.museum","flanders.museum","florida.museum","force.museum","fortmissoula.museum","fortworth.museum","foundation.museum","francaise.museum","frankfurt.museum","franziskaner.museum","freemasonry.museum","freiburg.museum","fribourg.museum","frog.museum","fundacio.museum","furniture.museum","gallery.museum","garden.museum","gateway.museum","geelvinck.museum","gemological.museum","geology.museum","georgia.museum","giessen.museum","glas.museum","glass.museum","gorge.museum","grandrapids.museum","graz.museum","guernsey.museum","halloffame.museum","hamburg.museum","handson.museum","harvestcelebration.museum","hawaii.museum","health.museum","heimatunduhren.museum","hellas.museum","helsinki.museum","hembygdsforbund.museum","heritage.museum","histoire.museum","historical.museum","historicalsociety.museum","historichouses.museum","historisch.museum","historisches.museum","history.museum","historyofscience.museum","horology.museum","house.museum","humanities.museum","illustration.museum","imageandsound.museum","indian.museum","indiana.museum","indianapolis.museum","indianmarket.museum","intelligence.museum","interactive.museum","iraq.museum","iron.museum","isleofman.museum","jamison.museum","jefferson.museum","jerusalem.museum","jewelry.museum","jewish.museum","jewishart.museum","jfk.museum","journalism.museum","judaica.museum","judygarland.museum","juedisches.museum","juif.museum","karate.museum","karikatur.museum","kids.museum","koebenhavn.museum","koeln.museum","kunst.museum","kunstsammlung.museum","kunstunddesign.museum","labor.museum","labour.museum","lajolla.museum","lancashire.museum","landes.museum","lans.museum","läns.museum","larsson.museum","lewismiller.museum","lincoln.museum","linz.museum","living.museum","livinghistory.museum","localhistory.museum","london.museum","losangeles.museum","louvre.museum","loyalist.museum","lucerne.museum","luxembourg.museum","luzern.museum","mad.museum","madrid.museum","mallorca.museum","manchester.museum","mansion.museum","mansions.museum","manx.museum","marburg.museum","maritime.museum","maritimo.museum","maryland.museum","marylhurst.museum","media.museum","medical.museum","medizinhistorisches.museum","meeres.museum","memorial.museum","mesaverde.museum","michigan.museum","midatlantic.museum","military.museum","mill.museum","miners.museum","mining.museum","minnesota.museum","missile.museum","missoula.museum","modern.museum","moma.museum","money.museum","monmouth.museum","monticello.museum","montreal.museum","moscow.museum","motorcycle.museum","muenchen.museum","muenster.museum","mulhouse.museum","muncie.museum","museet.museum","museumcenter.museum","museumvereniging.museum","music.museum","national.museum","nationalfirearms.museum","nationalheritage.museum","nativeamerican.museum","naturalhistory.museum","naturalhistorymuseum.museum","naturalsciences.museum","nature.museum","naturhistorisches.museum","natuurwetenschappen.museum","naumburg.museum","naval.museum","nebraska.museum","neues.museum","newhampshire.museum","newjersey.museum","newmexico.museum","newport.museum","newspaper.museum","newyork.museum","niepce.museum","norfolk.museum","north.museum","nrw.museum","nuernberg.museum","nuremberg.museum","nyc.museum","nyny.museum","oceanographic.museum","oceanographique.museum","omaha.museum","online.museum","ontario.museum","openair.museum","oregon.museum","oregontrail.museum","otago.museum","oxford.museum","pacific.museum","paderborn.museum","palace.museum","paleo.museum","palmsprings.museum","panama.museum","paris.museum","pasadena.museum","pharmacy.museum","philadelphia.museum","philadelphiaarea.museum","philately.museum","phoenix.museum","photography.museum","pilots.museum","pittsburgh.museum","planetarium.museum","plantation.museum","plants.museum","plaza.museum","portal.museum","portland.museum","portlligat.museum","posts-and-telecommunications.museum","preservation.museum","presidio.museum","press.museum","project.museum","public.museum","pubol.museum","quebec.museum","railroad.museum","railway.museum","research.museum","resistance.museum","riodejaneiro.museum","rochester.museum","rockart.museum","roma.museum","russia.museum","saintlouis.museum","salem.museum","salvadordali.museum","salzburg.museum","sandiego.museum","sanfrancisco.museum","santabarbara.museum","santacruz.museum","santafe.museum","saskatchewan.museum","satx.museum","savannahga.museum","schlesisches.museum","schoenbrunn.museum","schokoladen.museum","school.museum","schweiz.museum","science.museum","scienceandhistory.museum","scienceandindustry.museum","sciencecenter.museum","sciencecenters.museum","science-fiction.museum","sciencehistory.museum","sciences.museum","sciencesnaturelles.museum","scotland.museum","seaport.museum","settlement.museum","settlers.museum","shell.museum","sherbrooke.museum","sibenik.museum","silk.museum","ski.museum","skole.museum","society.museum","sologne.museum","soundandvision.museum","southcarolina.museum","southwest.museum","space.museum","spy.museum","square.museum","stadt.museum","stalbans.museum","starnberg.museum","state.museum","stateofdelaware.museum","station.museum","steam.museum","steiermark.museum","stjohn.museum","stockholm.museum","stpetersburg.museum","stuttgart.museum","suisse.museum","surgeonshall.museum","surrey.museum","svizzera.museum","sweden.museum","sydney.museum","tank.museum","tcm.museum","technology.museum","telekommunikation.museum","television.museum","texas.museum","textile.museum","theater.museum","time.museum","timekeeping.museum","topology.museum","torino.museum","touch.museum","town.museum","transport.museum","tree.museum","trolley.museum","trust.museum","trustee.museum","uhren.museum","ulm.museum","undersea.museum","university.museum","usa.museum","usantiques.museum","usarts.museum","uscountryestate.museum","usculture.museum","usdecorativearts.museum","usgarden.museum","ushistory.museum","ushuaia.museum","uslivinghistory.museum","utah.museum","uvic.museum","valley.museum","vantaa.museum","versailles.museum","viking.museum","village.museum","virginia.museum","virtual.museum","virtuel.museum","vlaanderen.museum","volkenkunde.museum","wales.museum","wallonie.museum","war.museum","washingtondc.museum","watchandclock.museum","watch-and-clock.museum","western.museum","westfalen.museum","whaling.museum","wildlife.museum","williamsburg.museum","windmill.museum","workshop.museum","york.museum","yorkshire.museum","yosemite.museum","youth.museum","zoological.museum","zoology.museum","ירושלים.museum","иком.museum","mv","aero.mv","biz.mv","com.mv","coop.mv","edu.mv","gov.mv","info.mv","int.mv","mil.mv","museum.mv","name.mv","net.mv","org.mv","pro.mv","mw","ac.mw","biz.mw","co.mw","com.mw","coop.mw","edu.mw","gov.mw","int.mw","museum.mw","net.mw","org.mw","mx","com.mx","org.mx","gob.mx","edu.mx","net.mx","my","com.my","net.my","org.my","gov.my","edu.my","mil.my","name.my","mz","ac.mz","adv.mz","co.mz","edu.mz","gov.mz","mil.mz","net.mz","org.mz","na","info.na","pro.na","name.na","school.na","or.na","dr.na","us.na","mx.na","ca.na","in.na","cc.na","tv.na","ws.na","mobi.na","co.na","com.na","org.na","name","nc","asso.nc","nom.nc","ne","net","nf","com.nf","net.nf","per.nf","rec.nf","web.nf","arts.nf","firm.nf","info.nf","other.nf","store.nf","ng","com.ng","edu.ng","gov.ng","i.ng","mil.ng","mobi.ng","name.ng","net.ng","org.ng","sch.ng","ni","ac.ni","biz.ni","co.ni","com.ni","edu.ni","gob.ni","in.ni","info.ni","int.ni","mil.ni","net.ni","nom.ni","org.ni","web.ni","nl","bv.nl","no","fhs.no","vgs.no","fylkesbibl.no","folkebibl.no","museum.no","idrett.no","priv.no","mil.no","stat.no","dep.no","kommune.no","herad.no","aa.no","ah.no","bu.no","fm.no","hl.no","hm.no","jan-mayen.no","mr.no","nl.no","nt.no","of.no","ol.no","oslo.no","rl.no","sf.no","st.no","svalbard.no","tm.no","tr.no","va.no","vf.no","gs.aa.no","gs.ah.no","gs.bu.no","gs.fm.no","gs.hl.no","gs.hm.no","gs.jan-mayen.no","gs.mr.no","gs.nl.no","gs.nt.no","gs.of.no","gs.ol.no","gs.oslo.no","gs.rl.no","gs.sf.no","gs.st.no","gs.svalbard.no","gs.tm.no","gs.tr.no","gs.va.no","gs.vf.no","akrehamn.no","åkrehamn.no","algard.no","ålgård.no","arna.no","brumunddal.no","bryne.no","bronnoysund.no","brønnøysund.no","drobak.no","drøbak.no","egersund.no","fetsund.no","floro.no","florø.no","fredrikstad.no","hokksund.no","honefoss.no","hønefoss.no","jessheim.no","jorpeland.no","jørpeland.no","kirkenes.no","kopervik.no","krokstadelva.no","langevag.no","langevåg.no","leirvik.no","mjondalen.no","mjøndalen.no","mo-i-rana.no","mosjoen.no","mosjøen.no","nesoddtangen.no","orkanger.no","osoyro.no","osøyro.no","raholt.no","råholt.no","sandnessjoen.no","sandnessjøen.no","skedsmokorset.no","slattum.no","spjelkavik.no","stathelle.no","stavern.no","stjordalshalsen.no","stjørdalshalsen.no","tananger.no","tranby.no","vossevangen.no","afjord.no","åfjord.no","agdenes.no","al.no","ål.no","alesund.no","ålesund.no","alstahaug.no","alta.no","áltá.no","alaheadju.no","álaheadju.no","alvdal.no","amli.no","åmli.no","amot.no","åmot.no","andebu.no","andoy.no","andøy.no","andasuolo.no","ardal.no","årdal.no","aremark.no","arendal.no","ås.no","aseral.no","åseral.no","asker.no","askim.no","askvoll.no","askoy.no","askøy.no","asnes.no","åsnes.no","audnedaln.no","aukra.no","aure.no","aurland.no","aurskog-holand.no","aurskog-høland.no","austevoll.no","austrheim.no","averoy.no","averøy.no","balestrand.no","ballangen.no","balat.no","bálát.no","balsfjord.no","bahccavuotna.no","báhccavuotna.no","bamble.no","bardu.no","beardu.no","beiarn.no","bajddar.no","bájddar.no","baidar.no","báidár.no","berg.no","bergen.no","berlevag.no","berlevåg.no","bearalvahki.no","bearalváhki.no","bindal.no","birkenes.no","bjarkoy.no","bjarkøy.no","bjerkreim.no","bjugn.no","bodo.no","bodø.no","badaddja.no","bådåddjå.no","budejju.no","bokn.no","bremanger.no","bronnoy.no","brønnøy.no","bygland.no","bykle.no","barum.no","bærum.no","bo.telemark.no","bø.telemark.no","bo.nordland.no","bø.nordland.no","bievat.no","bievát.no","bomlo.no","bømlo.no","batsfjord.no","båtsfjord.no","bahcavuotna.no","báhcavuotna.no","dovre.no","drammen.no","drangedal.no","dyroy.no","dyrøy.no","donna.no","dønna.no","eid.no","eidfjord.no","eidsberg.no","eidskog.no","eidsvoll.no","eigersund.no","elverum.no","enebakk.no","engerdal.no","etne.no","etnedal.no","evenes.no","evenassi.no","evenášši.no","evje-og-hornnes.no","farsund.no","fauske.no","fuossko.no","fuoisku.no","fedje.no","fet.no","finnoy.no","finnøy.no","fitjar.no","fjaler.no","fjell.no","flakstad.no","flatanger.no","flekkefjord.no","flesberg.no","flora.no","fla.no","flå.no","folldal.no","forsand.no","fosnes.no","frei.no","frogn.no","froland.no","frosta.no","frana.no","fræna.no","froya.no","frøya.no","fusa.no","fyresdal.no","forde.no","førde.no","gamvik.no","gangaviika.no","gáŋgaviika.no","gaular.no","gausdal.no","gildeskal.no","gildeskål.no","giske.no","gjemnes.no","gjerdrum.no","gjerstad.no","gjesdal.no","gjovik.no","gjøvik.no","gloppen.no","gol.no","gran.no","grane.no","granvin.no","gratangen.no","grimstad.no","grong.no","kraanghke.no","kråanghke.no","grue.no","gulen.no","hadsel.no","halden.no","halsa.no","hamar.no","hamaroy.no","habmer.no","hábmer.no","hapmir.no","hápmir.no","hammerfest.no","hammarfeasta.no","hámmárfeasta.no","haram.no","hareid.no","harstad.no","hasvik.no","aknoluokta.no","ákŋoluokta.no","hattfjelldal.no","aarborte.no","haugesund.no","hemne.no","hemnes.no","hemsedal.no","heroy.more-og-romsdal.no","herøy.møre-og-romsdal.no","heroy.nordland.no","herøy.nordland.no","hitra.no","hjartdal.no","hjelmeland.no","hobol.no","hobøl.no","hof.no","hol.no","hole.no","holmestrand.no","holtalen.no","holtålen.no","hornindal.no","horten.no","hurdal.no","hurum.no","hvaler.no","hyllestad.no","hagebostad.no","hægebostad.no","hoyanger.no","høyanger.no","hoylandet.no","høylandet.no","ha.no","hå.no","ibestad.no","inderoy.no","inderøy.no","iveland.no","jevnaker.no","jondal.no","jolster.no","jølster.no","karasjok.no","karasjohka.no","kárášjohka.no","karlsoy.no","galsa.no","gálsá.no","karmoy.no","karmøy.no","kautokeino.no","guovdageaidnu.no","klepp.no","klabu.no","klæbu.no","kongsberg.no","kongsvinger.no","kragero.no","kragerø.no","kristiansand.no","kristiansund.no","krodsherad.no","krødsherad.no","kvalsund.no","rahkkeravju.no","ráhkkerávju.no","kvam.no","kvinesdal.no","kvinnherad.no","kviteseid.no","kvitsoy.no","kvitsøy.no","kvafjord.no","kvæfjord.no","giehtavuoatna.no","kvanangen.no","kvænangen.no","navuotna.no","návuotna.no","kafjord.no","kåfjord.no","gaivuotna.no","gáivuotna.no","larvik.no","lavangen.no","lavagis.no","loabat.no","loabát.no","lebesby.no","davvesiida.no","leikanger.no","leirfjord.no","leka.no","leksvik.no","lenvik.no","leangaviika.no","leaŋgaviika.no","lesja.no","levanger.no","lier.no","lierne.no","lillehammer.no","lillesand.no","lindesnes.no","lindas.no","lindås.no","lom.no","loppa.no","lahppi.no","láhppi.no","lund.no","lunner.no","luroy.no","lurøy.no","luster.no","lyngdal.no","lyngen.no","ivgu.no","lardal.no","lerdal.no","lærdal.no","lodingen.no","lødingen.no","lorenskog.no","lørenskog.no","loten.no","løten.no","malvik.no","masoy.no","måsøy.no","muosat.no","muosát.no","mandal.no","marker.no","marnardal.no","masfjorden.no","meland.no","meldal.no","melhus.no","meloy.no","meløy.no","meraker.no","meråker.no","moareke.no","moåreke.no","midsund.no","midtre-gauldal.no","modalen.no","modum.no","molde.no","moskenes.no","moss.no","mosvik.no","malselv.no","målselv.no","malatvuopmi.no","málatvuopmi.no","namdalseid.no","aejrie.no","namsos.no","namsskogan.no","naamesjevuemie.no","nååmesjevuemie.no","laakesvuemie.no","nannestad.no","narvik.no","narviika.no","naustdal.no","nedre-eiker.no","nes.akershus.no","nes.buskerud.no","nesna.no","nesodden.no","nesseby.no","unjarga.no","unjárga.no","nesset.no","nissedal.no","nittedal.no","nord-aurdal.no","nord-fron.no","nord-odal.no","norddal.no","nordkapp.no","davvenjarga.no","davvenjárga.no","nordre-land.no","nordreisa.no","raisa.no","ráisa.no","nore-og-uvdal.no","notodden.no","naroy.no","nærøy.no","notteroy.no","nøtterøy.no","odda.no","oksnes.no","øksnes.no","oppdal.no","oppegard.no","oppegård.no","orkdal.no","orland.no","ørland.no","orskog.no","ørskog.no","orsta.no","ørsta.no","os.hedmark.no","os.hordaland.no","osen.no","osteroy.no","osterøy.no","ostre-toten.no","østre-toten.no","overhalla.no","ovre-eiker.no","øvre-eiker.no","oyer.no","øyer.no","oygarden.no","øygarden.no","oystre-slidre.no","øystre-slidre.no","porsanger.no","porsangu.no","porsáŋgu.no","porsgrunn.no","radoy.no","radøy.no","rakkestad.no","rana.no","ruovat.no","randaberg.no","rauma.no","rendalen.no","rennebu.no","rennesoy.no","rennesøy.no","rindal.no","ringebu.no","ringerike.no","ringsaker.no","rissa.no","risor.no","risør.no","roan.no","rollag.no","rygge.no","ralingen.no","rælingen.no","rodoy.no","rødøy.no","romskog.no","rømskog.no","roros.no","røros.no","rost.no","røst.no","royken.no","røyken.no","royrvik.no","røyrvik.no","rade.no","råde.no","salangen.no","siellak.no","saltdal.no","salat.no","sálát.no","sálat.no","samnanger.no","sande.more-og-romsdal.no","sande.møre-og-romsdal.no","sande.vestfold.no","sandefjord.no","sandnes.no","sandoy.no","sandøy.no","sarpsborg.no","sauda.no","sauherad.no","sel.no","selbu.no","selje.no","seljord.no","sigdal.no","siljan.no","sirdal.no","skaun.no","skedsmo.no","ski.no","skien.no","skiptvet.no","skjervoy.no","skjervøy.no","skierva.no","skiervá.no","skjak.no","skjåk.no","skodje.no","skanland.no","skånland.no","skanit.no","skánit.no","smola.no","smøla.no","snillfjord.no","snasa.no","snåsa.no","snoasa.no","snaase.no","snåase.no","sogndal.no","sokndal.no","sola.no","solund.no","songdalen.no","sortland.no","spydeberg.no","stange.no","stavanger.no","steigen.no","steinkjer.no","stjordal.no","stjørdal.no","stokke.no","stor-elvdal.no","stord.no","stordal.no","storfjord.no","omasvuotna.no","strand.no","stranda.no","stryn.no","sula.no","suldal.no","sund.no","sunndal.no","surnadal.no","sveio.no","svelvik.no","sykkylven.no","sogne.no","søgne.no","somna.no","sømna.no","sondre-land.no","søndre-land.no","sor-aurdal.no","sør-aurdal.no","sor-fron.no","sør-fron.no","sor-odal.no","sør-odal.no","sor-varanger.no","sør-varanger.no","matta-varjjat.no","mátta-várjjat.no","sorfold.no","sørfold.no","sorreisa.no","sørreisa.no","sorum.no","sørum.no","tana.no","deatnu.no","time.no","tingvoll.no","tinn.no","tjeldsund.no","dielddanuorri.no","tjome.no","tjøme.no","tokke.no","tolga.no","torsken.no","tranoy.no","tranøy.no","tromso.no","tromsø.no","tromsa.no","romsa.no","trondheim.no","troandin.no","trysil.no","trana.no","træna.no","trogstad.no","trøgstad.no","tvedestrand.no","tydal.no","tynset.no","tysfjord.no","divtasvuodna.no","divttasvuotna.no","tysnes.no","tysvar.no","tysvær.no","tonsberg.no","tønsberg.no","ullensaker.no","ullensvang.no","ulvik.no","utsira.no","vadso.no","vadsø.no","cahcesuolo.no","čáhcesuolo.no","vaksdal.no","valle.no","vang.no","vanylven.no","vardo.no","vardø.no","varggat.no","várggát.no","vefsn.no","vaapste.no","vega.no","vegarshei.no","vegårshei.no","vennesla.no","verdal.no","verran.no","vestby.no","vestnes.no","vestre-slidre.no","vestre-toten.no","vestvagoy.no","vestvågøy.no","vevelstad.no","vik.no","vikna.no","vindafjord.no","volda.no","voss.no","varoy.no","værøy.no","vagan.no","vågan.no","voagat.no","vagsoy.no","vågsøy.no","vaga.no","vågå.no","valer.ostfold.no","våler.østfold.no","valer.hedmark.no","våler.hedmark.no","*.np","nr","biz.nr","info.nr","gov.nr","edu.nr","org.nr","net.nr","com.nr","nu","nz","ac.nz","co.nz","cri.nz","geek.nz","gen.nz","govt.nz","health.nz","iwi.nz","kiwi.nz","maori.nz","mil.nz","māori.nz","net.nz","org.nz","parliament.nz","school.nz","om","co.om","com.om","edu.om","gov.om","med.om","museum.om","net.om","org.om","pro.om","onion","org","pa","ac.pa","gob.pa","com.pa","org.pa","sld.pa","edu.pa","net.pa","ing.pa","abo.pa","med.pa","nom.pa","pe","edu.pe","gob.pe","nom.pe","mil.pe","org.pe","com.pe","net.pe","pf","com.pf","org.pf","edu.pf","*.pg","ph","com.ph","net.ph","org.ph","gov.ph","edu.ph","ngo.ph","mil.ph","i.ph","pk","com.pk","net.pk","edu.pk","org.pk","fam.pk","biz.pk","web.pk","gov.pk","gob.pk","gok.pk","gon.pk","gop.pk","gos.pk","info.pk","pl","com.pl","net.pl","org.pl","aid.pl","agro.pl","atm.pl","auto.pl","biz.pl","edu.pl","gmina.pl","gsm.pl","info.pl","mail.pl","miasta.pl","media.pl","mil.pl","nieruchomosci.pl","nom.pl","pc.pl","powiat.pl","priv.pl","realestate.pl","rel.pl","sex.pl","shop.pl","sklep.pl","sos.pl","szkola.pl","targi.pl","tm.pl","tourism.pl","travel.pl","turystyka.pl","gov.pl","ap.gov.pl","ic.gov.pl","is.gov.pl","us.gov.pl","kmpsp.gov.pl","kppsp.gov.pl","kwpsp.gov.pl","psp.gov.pl","wskr.gov.pl","kwp.gov.pl","mw.gov.pl","ug.gov.pl","um.gov.pl","umig.gov.pl","ugim.gov.pl","upow.gov.pl","uw.gov.pl","starostwo.gov.pl","pa.gov.pl","po.gov.pl","psse.gov.pl","pup.gov.pl","rzgw.gov.pl","sa.gov.pl","so.gov.pl","sr.gov.pl","wsa.gov.pl","sko.gov.pl","uzs.gov.pl","wiih.gov.pl","winb.gov.pl","pinb.gov.pl","wios.gov.pl","witd.gov.pl","wzmiuw.gov.pl","piw.gov.pl","wiw.gov.pl","griw.gov.pl","wif.gov.pl","oum.gov.pl","sdn.gov.pl","zp.gov.pl","uppo.gov.pl","mup.gov.pl","wuoz.gov.pl","konsulat.gov.pl","oirm.gov.pl","augustow.pl","babia-gora.pl","bedzin.pl","beskidy.pl","bialowieza.pl","bialystok.pl","bielawa.pl","bieszczady.pl","boleslawiec.pl","bydgoszcz.pl","bytom.pl","cieszyn.pl","czeladz.pl","czest.pl","dlugoleka.pl","elblag.pl","elk.pl","glogow.pl","gniezno.pl","gorlice.pl","grajewo.pl","ilawa.pl","jaworzno.pl","jelenia-gora.pl","jgora.pl","kalisz.pl","kazimierz-dolny.pl","karpacz.pl","kartuzy.pl","kaszuby.pl","katowice.pl","kepno.pl","ketrzyn.pl","klodzko.pl","kobierzyce.pl","kolobrzeg.pl","konin.pl","konskowola.pl","kutno.pl","lapy.pl","lebork.pl","legnica.pl","lezajsk.pl","limanowa.pl","lomza.pl","lowicz.pl","lubin.pl","lukow.pl","malbork.pl","malopolska.pl","mazowsze.pl","mazury.pl","mielec.pl","mielno.pl","mragowo.pl","naklo.pl","nowaruda.pl","nysa.pl","olawa.pl","olecko.pl","olkusz.pl","olsztyn.pl","opoczno.pl","opole.pl","ostroda.pl","ostroleka.pl","ostrowiec.pl","ostrowwlkp.pl","pila.pl","pisz.pl","podhale.pl","podlasie.pl","polkowice.pl","pomorze.pl","pomorskie.pl","prochowice.pl","pruszkow.pl","przeworsk.pl","pulawy.pl","radom.pl","rawa-maz.pl","rybnik.pl","rzeszow.pl","sanok.pl","sejny.pl","slask.pl","slupsk.pl","sosnowiec.pl","stalowa-wola.pl","skoczow.pl","starachowice.pl","stargard.pl","suwalki.pl","swidnica.pl","swiebodzin.pl","swinoujscie.pl","szczecin.pl","szczytno.pl","tarnobrzeg.pl","tgory.pl","turek.pl","tychy.pl","ustka.pl","walbrzych.pl","warmia.pl","warszawa.pl","waw.pl","wegrow.pl","wielun.pl","wlocl.pl","wloclawek.pl","wodzislaw.pl","wolomin.pl","wroclaw.pl","zachpomor.pl","zagan.pl","zarow.pl","zgora.pl","zgorzelec.pl","pm","pn","gov.pn","co.pn","org.pn","edu.pn","net.pn","post","pr","com.pr","net.pr","org.pr","gov.pr","edu.pr","isla.pr","pro.pr","biz.pr","info.pr","name.pr","est.pr","prof.pr","ac.pr","pro","aaa.pro","aca.pro","acct.pro","avocat.pro","bar.pro","cpa.pro","eng.pro","jur.pro","law.pro","med.pro","recht.pro","ps","edu.ps","gov.ps","sec.ps","plo.ps","com.ps","org.ps","net.ps","pt","net.pt","gov.pt","org.pt","edu.pt","int.pt","publ.pt","com.pt","nome.pt","pw","co.pw","ne.pw","or.pw","ed.pw","go.pw","belau.pw","py","com.py","coop.py","edu.py","gov.py","mil.py","net.py","org.py","qa","com.qa","edu.qa","gov.qa","mil.qa","name.qa","net.qa","org.qa","sch.qa","re","asso.re","com.re","nom.re","ro","arts.ro","com.ro","firm.ro","info.ro","nom.ro","nt.ro","org.ro","rec.ro","store.ro","tm.ro","www.ro","rs","ac.rs","co.rs","edu.rs","gov.rs","in.rs","org.rs","ru","ac.ru","edu.ru","gov.ru","int.ru","mil.ru","test.ru","rw","gov.rw","net.rw","edu.rw","ac.rw","com.rw","co.rw","int.rw","mil.rw","gouv.rw","sa","com.sa","net.sa","org.sa","gov.sa","med.sa","pub.sa","edu.sa","sch.sa","sb","com.sb","edu.sb","gov.sb","net.sb","org.sb","sc","com.sc","gov.sc","net.sc","org.sc","edu.sc","sd","com.sd","net.sd","org.sd","edu.sd","med.sd","tv.sd","gov.sd","info.sd","se","a.se","ac.se","b.se","bd.se","brand.se","c.se","d.se","e.se","f.se","fh.se","fhsk.se","fhv.se","g.se","h.se","i.se","k.se","komforb.se","kommunalforbund.se","komvux.se","l.se","lanbib.se","m.se","n.se","naturbruksgymn.se","o.se","org.se","p.se","parti.se","pp.se","press.se","r.se","s.se","t.se","tm.se","u.se","w.se","x.se","y.se","z.se","sg","com.sg","net.sg","org.sg","gov.sg","edu.sg","per.sg","sh","com.sh","net.sh","gov.sh","org.sh","mil.sh","si","sj","sk","sl","com.sl","net.sl","edu.sl","gov.sl","org.sl","sm","sn","art.sn","com.sn","edu.sn","gouv.sn","org.sn","perso.sn","univ.sn","so","com.so","net.so","org.so","sr","st","co.st","com.st","consulado.st","edu.st","embaixada.st","gov.st","mil.st","net.st","org.st","principe.st","saotome.st","store.st","su","sv","com.sv","edu.sv","gob.sv","org.sv","red.sv","sx","gov.sx","sy","edu.sy","gov.sy","net.sy","mil.sy","com.sy","org.sy","sz","co.sz","ac.sz","org.sz","tc","td","tel","tf","tg","th","ac.th","co.th","go.th","in.th","mi.th","net.th","or.th","tj","ac.tj","biz.tj","co.tj","com.tj","edu.tj","go.tj","gov.tj","int.tj","mil.tj","name.tj","net.tj","nic.tj","org.tj","test.tj","web.tj","tk","tl","gov.tl","tm","com.tm","co.tm","org.tm","net.tm","nom.tm","gov.tm","mil.tm","edu.tm","tn","com.tn","ens.tn","fin.tn","gov.tn","ind.tn","intl.tn","nat.tn","net.tn","org.tn","info.tn","perso.tn","tourism.tn","edunet.tn","rnrt.tn","rns.tn","rnu.tn","mincom.tn","agrinet.tn","defense.tn","turen.tn","to","com.to","gov.to","net.to","org.to","edu.to","mil.to","tr","com.tr","info.tr","biz.tr","net.tr","org.tr","web.tr","gen.tr","tv.tr","av.tr","dr.tr","bbs.tr","name.tr","tel.tr","gov.tr","bel.tr","pol.tr","mil.tr","k12.tr","edu.tr","kep.tr","nc.tr","gov.nc.tr","tt","co.tt","com.tt","org.tt","net.tt","biz.tt","info.tt","pro.tt","int.tt","coop.tt","jobs.tt","mobi.tt","travel.tt","museum.tt","aero.tt","name.tt","gov.tt","edu.tt","tv","tw","edu.tw","gov.tw","mil.tw","com.tw","net.tw","org.tw","idv.tw","game.tw","ebiz.tw","club.tw","網路.tw","組織.tw","商業.tw","tz","ac.tz","co.tz","go.tz","hotel.tz","info.tz","me.tz","mil.tz","mobi.tz","ne.tz","or.tz","sc.tz","tv.tz","ua","com.ua","edu.ua","gov.ua","in.ua","net.ua","org.ua","cherkassy.ua","cherkasy.ua","chernigov.ua","chernihiv.ua","chernivtsi.ua","chernovtsy.ua","ck.ua","cn.ua","cr.ua","crimea.ua","cv.ua","dn.ua","dnepropetrovsk.ua","dnipropetrovsk.ua","dominic.ua","donetsk.ua","dp.ua","if.ua","ivano-frankivsk.ua","kh.ua","kharkiv.ua","kharkov.ua","kherson.ua","khmelnitskiy.ua","khmelnytskyi.ua","kiev.ua","kirovograd.ua","km.ua","kr.ua","krym.ua","ks.ua","kv.ua","kyiv.ua","lg.ua","lt.ua","lugansk.ua","lutsk.ua","lv.ua","lviv.ua","mk.ua","mykolaiv.ua","nikolaev.ua","od.ua","odesa.ua","odessa.ua","pl.ua","poltava.ua","rivne.ua","rovno.ua","rv.ua","sb.ua","sebastopol.ua","sevastopol.ua","sm.ua","sumy.ua","te.ua","ternopil.ua","uz.ua","uzhgorod.ua","vinnica.ua","vinnytsia.ua","vn.ua","volyn.ua","yalta.ua","zaporizhzhe.ua","zaporizhzhia.ua","zhitomir.ua","zhytomyr.ua","zp.ua","zt.ua","ug","co.ug","or.ug","ac.ug","sc.ug","go.ug","ne.ug","com.ug","org.ug","uk","ac.uk","co.uk","gov.uk","ltd.uk","me.uk","net.uk","nhs.uk","org.uk","plc.uk","police.uk","*.sch.uk","us","dni.us","fed.us","isa.us","kids.us","nsn.us","ak.us","al.us","ar.us","as.us","az.us","ca.us","co.us","ct.us","dc.us","de.us","fl.us","ga.us","gu.us","hi.us","ia.us","id.us","il.us","in.us","ks.us","ky.us","la.us","ma.us","md.us","me.us","mi.us","mn.us","mo.us","ms.us","mt.us","nc.us","nd.us","ne.us","nh.us","nj.us","nm.us","nv.us","ny.us","oh.us","ok.us","or.us","pa.us","pr.us","ri.us","sc.us","sd.us","tn.us","tx.us","ut.us","vi.us","vt.us","va.us","wa.us","wi.us","wv.us","wy.us","k12.ak.us","k12.al.us","k12.ar.us","k12.as.us","k12.az.us","k12.ca.us","k12.co.us","k12.ct.us","k12.dc.us","k12.de.us","k12.fl.us","k12.ga.us","k12.gu.us","k12.ia.us","k12.id.us","k12.il.us","k12.in.us","k12.ks.us","k12.ky.us","k12.la.us","k12.ma.us","k12.md.us","k12.me.us","k12.mi.us","k12.mn.us","k12.mo.us","k12.ms.us","k12.mt.us","k12.nc.us","k12.ne.us","k12.nh.us","k12.nj.us","k12.nm.us","k12.nv.us","k12.ny.us","k12.oh.us","k12.ok.us","k12.or.us","k12.pa.us","k12.pr.us","k12.ri.us","k12.sc.us","k12.tn.us","k12.tx.us","k12.ut.us","k12.vi.us","k12.vt.us","k12.va.us","k12.wa.us","k12.wi.us","k12.wy.us","cc.ak.us","cc.al.us","cc.ar.us","cc.as.us","cc.az.us","cc.ca.us","cc.co.us","cc.ct.us","cc.dc.us","cc.de.us","cc.fl.us","cc.ga.us","cc.gu.us","cc.hi.us","cc.ia.us","cc.id.us","cc.il.us","cc.in.us","cc.ks.us","cc.ky.us","cc.la.us","cc.ma.us","cc.md.us","cc.me.us","cc.mi.us","cc.mn.us","cc.mo.us","cc.ms.us","cc.mt.us","cc.nc.us","cc.nd.us","cc.ne.us","cc.nh.us","cc.nj.us","cc.nm.us","cc.nv.us","cc.ny.us","cc.oh.us","cc.ok.us","cc.or.us","cc.pa.us","cc.pr.us","cc.ri.us","cc.sc.us","cc.sd.us","cc.tn.us","cc.tx.us","cc.ut.us","cc.vi.us","cc.vt.us","cc.va.us","cc.wa.us","cc.wi.us","cc.wv.us","cc.wy.us","lib.ak.us","lib.al.us","lib.ar.us","lib.as.us","lib.az.us","lib.ca.us","lib.co.us","lib.ct.us","lib.dc.us","lib.fl.us","lib.ga.us","lib.gu.us","lib.hi.us","lib.ia.us","lib.id.us","lib.il.us","lib.in.us","lib.ks.us","lib.ky.us","lib.la.us","lib.ma.us","lib.md.us","lib.me.us","lib.mi.us","lib.mn.us","lib.mo.us","lib.ms.us","lib.mt.us","lib.nc.us","lib.nd.us","lib.ne.us","lib.nh.us","lib.nj.us","lib.nm.us","lib.nv.us","lib.ny.us","lib.oh.us","lib.ok.us","lib.or.us","lib.pa.us","lib.pr.us","lib.ri.us","lib.sc.us","lib.sd.us","lib.tn.us","lib.tx.us","lib.ut.us","lib.vi.us","lib.vt.us","lib.va.us","lib.wa.us","lib.wi.us","lib.wy.us","pvt.k12.ma.us","chtr.k12.ma.us","paroch.k12.ma.us","ann-arbor.mi.us","cog.mi.us","dst.mi.us","eaton.mi.us","gen.mi.us","mus.mi.us","tec.mi.us","washtenaw.mi.us","uy","com.uy","edu.uy","gub.uy","mil.uy","net.uy","org.uy","uz","co.uz","com.uz","net.uz","org.uz","va","vc","com.vc","net.vc","org.vc","gov.vc","mil.vc","edu.vc","ve","arts.ve","co.ve","com.ve","e12.ve","edu.ve","firm.ve","gob.ve","gov.ve","info.ve","int.ve","mil.ve","net.ve","org.ve","rec.ve","store.ve","tec.ve","web.ve","vg","vi","co.vi","com.vi","k12.vi","net.vi","org.vi","vn","com.vn","net.vn","org.vn","edu.vn","gov.vn","int.vn","ac.vn","biz.vn","info.vn","name.vn","pro.vn","health.vn","vu","com.vu","edu.vu","net.vu","org.vu","wf","ws","com.ws","net.ws","org.ws","gov.ws","edu.ws","yt","امارات","հայ","বাংলা","бг","бел","中国","中國","الجزائر","مصر","ею","გე","ελ","香港","公司.香港","教育.香港","政府.香港","個人.香港","網絡.香港","組織.香港","ಭಾರತ","ଭାରତ","ভাৰত","भारतम्","भारोत","ڀارت","ഭാരതം","भारत","بارت","بھارت","భారత్","ભારત","ਭਾਰਤ","ভারত","இந்தியா","ایران","ايران","عراق","الاردن","한국","қаз","ලංකා","இலங்கை","المغرب","мкд","мон","澳門","澳门","مليسيا","عمان","پاکستان","پاكستان","فلسطين","срб","пр.срб","орг.срб","обр.срб","од.срб","упр.срб","ак.срб","рф","قطر","السعودية","السعودیة","السعودیۃ","السعوديه","سودان","新加坡","சிங்கப்பூர்","سورية","سوريا","ไทย","ศึกษา.ไทย","ธุรกิจ.ไทย","รัฐบาล.ไทย","ทหาร.ไทย","เน็ต.ไทย","องค์กร.ไทย","تونس","台灣","台湾","臺灣","укр","اليمن","xxx","*.ye","ac.za","agric.za","alt.za","co.za","edu.za","gov.za","grondar.za","law.za","mil.za","net.za","ngo.za","nis.za","nom.za","org.za","school.za","tm.za","web.za","zm","ac.zm","biz.zm","co.zm","com.zm","edu.zm","gov.zm","info.zm","mil.zm","net.zm","org.zm","sch.zm","zw","ac.zw","co.zw","gov.zw","mil.zw","org.zw","aaa","aarp","abarth","abb","abbott","abbvie","abc","able","abogado","abudhabi","academy","accenture","accountant","accountants","aco","active","actor","adac","ads","adult","aeg","aetna","afamilycompany","afl","africa","agakhan","agency","aig","aigo","airbus","airforce","airtel","akdn","alfaromeo","alibaba","alipay","allfinanz","allstate","ally","alsace","alstom","americanexpress","americanfamily","amex","amfam","amica","amsterdam","analytics","android","anquan","anz","aol","apartments","app","apple","aquarelle","arab","aramco","archi","army","art","arte","asda","associates","athleta","attorney","auction","audi","audible","audio","auspost","author","auto","autos","avianca","aws","axa","azure","baby","baidu","banamex","bananarepublic","band","bank","bar","barcelona","barclaycard","barclays","barefoot","bargains","baseball","basketball","bauhaus","bayern","bbc","bbt","bbva","bcg","bcn","beats","beauty","beer","bentley","berlin","best","bestbuy","bet","bharti","bible","bid","bike","bing","bingo","bio","black","blackfriday","blanco","blockbuster","blog","bloomberg","blue","bms","bmw","bnl","bnpparibas","boats","boehringer","bofa","bom","bond","boo","book","booking","bosch","bostik","boston","bot","boutique","box","bradesco","bridgestone","broadway","broker","brother","brussels","budapest","bugatti","build","builders","business","buy","buzz","bzh","cab","cafe","cal","call","calvinklein","cam","camera","camp","cancerresearch","canon","capetown","capital","capitalone","car","caravan","cards","care","career","careers","cars","cartier","casa","case","caseih","cash","casino","catering","catholic","cba","cbn","cbre","cbs","ceb","center","ceo","cern","cfa","cfd","chanel","channel","charity","chase","chat","cheap","chintai","christmas","chrome","chrysler","church","cipriani","circle","cisco","citadel","citi","citic","city","cityeats","claims","cleaning","click","clinic","clinique","clothing","cloud","club","clubmed","coach","codes","coffee","college","cologne","comcast","commbank","community","company","compare","computer","comsec","condos","construction","consulting","contact","contractors","cooking","cookingchannel","cool","corsica","country","coupon","coupons","courses","credit","creditcard","creditunion","cricket","crown","crs","cruise","cruises","csc","cuisinella","cymru","cyou","dabur","dad","dance","data","date","dating","datsun","day","dclk","dds","deal","dealer","deals","degree","delivery","dell","deloitte","delta","democrat","dental","dentist","desi","design","dev","dhl","diamonds","diet","digital","direct","directory","discount","discover","dish","diy","dnp","docs","doctor","dodge","dog","doha","domains","dot","download","drive","dtv","dubai","duck","dunlop","duns","dupont","durban","dvag","dvr","earth","eat","eco","edeka","education","email","emerck","energy","engineer","engineering","enterprises","epost","epson","equipment","ericsson","erni","esq","estate","esurance","etisalat","eurovision","eus","events","everbank","exchange","expert","exposed","express","extraspace","fage","fail","fairwinds","faith","family","fan","fans","farm","farmers","fashion","fast","fedex","feedback","ferrari","ferrero","fiat","fidelity","fido","film","final","finance","financial","fire","firestone","firmdale","fish","fishing","fit","fitness","flickr","flights","flir","florist","flowers","fly","foo","food","foodnetwork","football","ford","forex","forsale","forum","foundation","fox","free","fresenius","frl","frogans","frontdoor","frontier","ftr","fujitsu","fujixerox","fun","fund","furniture","futbol","fyi","gal","gallery","gallo","gallup","game","games","gap","garden","gbiz","gdn","gea","gent","genting","george","ggee","gift","gifts","gives","giving","glade","glass","gle","global","globo","gmail","gmbh","gmo","gmx","godaddy","gold","goldpoint","golf","goo","goodhands","goodyear","goog","google","gop","got","grainger","graphics","gratis","green","gripe","grocery","group","guardian","gucci","guge","guide","guitars","guru","hair","hamburg","hangout","haus","hbo","hdfc","hdfcbank","health","healthcare","help","helsinki","here","hermes","hgtv","hiphop","hisamitsu","hitachi","hiv","hkt","hockey","holdings","holiday","homedepot","homegoods","homes","homesense","honda","honeywell","horse","hospital","host","hosting","hot","hoteles","hotels","hotmail","house","how","hsbc","hughes","hyatt","hyundai","ibm","icbc","ice","icu","ieee","ifm","ikano","imamat","imdb","immo","immobilien","inc","industries","infiniti","ing","ink","institute","insurance","insure","intel","international","intuit","investments","ipiranga","irish","iselect","ismaili","ist","istanbul","itau","itv","iveco","jaguar","java","jcb","jcp","jeep","jetzt","jewelry","jio","jlc","jll","jmp","jnj","joburg","jot","joy","jpmorgan","jprs","juegos","juniper","kaufen","kddi","kerryhotels","kerrylogistics","kerryproperties","kfh","kia","kim","kinder","kindle","kitchen","kiwi","koeln","komatsu","kosher","kpmg","kpn","krd","kred","kuokgroup","kyoto","lacaixa","ladbrokes","lamborghini","lamer","lancaster","lancia","lancome","land","landrover","lanxess","lasalle","lat","latino","latrobe","law","lawyer","lds","lease","leclerc","lefrak","legal","lego","lexus","lgbt","liaison","lidl","life","lifeinsurance","lifestyle","lighting","like","lilly","limited","limo","lincoln","linde","link","lipsy","live","living","lixil","llc","loan","loans","locker","locus","loft","lol","london","lotte","lotto","love","lpl","lplfinancial","ltd","ltda","lundbeck","lupin","luxe","luxury","macys","madrid","maif","maison","makeup","man","management","mango","map","market","marketing","markets","marriott","marshalls","maserati","mattel","mba","mckinsey","med","media","meet","melbourne","meme","memorial","men","menu","merckmsd","metlife","miami","microsoft","mini","mint","mit","mitsubishi","mlb","mls","mma","mobile","mobily","moda","moe","moi","mom","monash","money","monster","mopar","mormon","mortgage","moscow","moto","motorcycles","mov","movie","movistar","msd","mtn","mtr","mutual","nab","nadex","nagoya","nationwide","natura","navy","nba","nec","netbank","netflix","network","neustar","new","newholland","news","next","nextdirect","nexus","nfl","ngo","nhk","nico","nike","nikon","ninja","nissan","nissay","nokia","northwesternmutual","norton","now","nowruz","nowtv","nra","nrw","ntt","nyc","obi","observer","off","office","okinawa","olayan","olayangroup","oldnavy","ollo","omega","one","ong","onl","online","onyourside","ooo","open","oracle","orange","organic","origins","osaka","otsuka","ott","ovh","page","panasonic","panerai","paris","pars","partners","parts","party","passagens","pay","pccw","pet","pfizer","pharmacy","phd","philips","phone","photo","photography","photos","physio","piaget","pics","pictet","pictures","pid","pin","ping","pink","pioneer","pizza","place","play","playstation","plumbing","plus","pnc","pohl","poker","politie","porn","pramerica","praxi","press","prime","prod","productions","prof","progressive","promo","properties","property","protection","pru","prudential","pub","pwc","qpon","quebec","quest","qvc","racing","radio","raid","read","realestate","realtor","realty","recipes","red","redstone","redumbrella","rehab","reise","reisen","reit","reliance","ren","rent","rentals","repair","report","republican","rest","restaurant","review","reviews","rexroth","rich","richardli","ricoh","rightathome","ril","rio","rip","rmit","rocher","rocks","rodeo","rogers","room","rsvp","rugby","ruhr","run","rwe","ryukyu","saarland","safe","safety","sakura","sale","salon","samsclub","samsung","sandvik","sandvikcoromant","sanofi","sap","sarl","sas","save","saxo","sbi","sbs","sca","scb","schaeffler","schmidt","scholarships","school","schule","schwarz","science","scjohnson","scor","scot","search","seat","secure","security","seek","select","sener","services","ses","seven","sew","sex","sexy","sfr","shangrila","sharp","shaw","shell","shia","shiksha","shoes","shop","shopping","shouji","show","showtime","shriram","silk","sina","singles","site","ski","skin","sky","skype","sling","smart","smile","sncf","soccer","social","softbank","software","sohu","solar","solutions","song","sony","soy","space","spiegel","sport","spot","spreadbetting","srl","srt","stada","staples","star","starhub","statebank","statefarm","statoil","stc","stcgroup","stockholm","storage","store","stream","studio","study","style","sucks","supplies","supply","support","surf","surgery","suzuki","swatch","swiftcover","swiss","sydney","symantec","systems","tab","taipei","talk","taobao","target","tatamotors","tatar","tattoo","tax","taxi","tci","tdk","team","tech","technology","telecity","telefonica","temasek","tennis","teva","thd","theater","theatre","tiaa","tickets","tienda","tiffany","tips","tires","tirol","tjmaxx","tjx","tkmaxx","tmall","today","tokyo","tools","top","toray","toshiba","total","tours","town","toyota","toys","trade","trading","training","travel","travelchannel","travelers","travelersinsurance","trust","trv","tube","tui","tunes","tushu","tvs","ubank","ubs","uconnect","unicom","university","uno","uol","ups","vacations","vana","vanguard","vegas","ventures","verisign","versicherung","vet","viajes","video","vig","viking","villas","vin","vip","virgin","visa","vision","vista","vistaprint","viva","vivo","vlaanderen","vodka","volkswagen","volvo","vote","voting","voto","voyage","vuelos","wales","walmart","walter","wang","wanggou","warman","watch","watches","weather","weatherchannel","webcam","weber","website","wed","wedding","weibo","weir","whoswho","wien","wiki","williamhill","win","windows","wine","winners","wme","wolterskluwer","woodside","work","works","world","wow","wtc","wtf","xbox","xerox","xfinity","xihuan","xin","कॉम","セール","佛山","慈善","集团","在线","大众汽车","点看","คอม","八卦","موقع","公益","公司","香格里拉","网站","移动","我爱你","москва","католик","онлайн","сайт","联通","קום","时尚","微博","淡马锡","ファッション","орг","नेट","ストア","삼성","商标","商店","商城","дети","ポイント","新闻","工行","家電","كوم","中文网","中信","娱乐","谷歌","電訊盈科","购物","クラウド","通販","网店","संगठन","餐厅","网络","ком","诺基亚","食品","飞利浦","手表","手机","ارامكو","العليان","اتصالات","بازار","موبايلي","ابوظبي","كاثوليك","همراه","닷컴","政府","شبكة","بيتك","عرب","机构","组织机构","健康","招聘","рус","珠宝","大拿","みんな","グーグル","世界","書籍","网址","닷넷","コム","天主教","游戏","vermögensberater","vermögensberatung","企业","信息","嘉里大酒店","嘉里","广东","政务","xyz","yachts","yahoo","yamaxun","yandex","yodobashi","yoga","yokohama","you","youtube","yun","zappos","zara","zero","zip","zippo","zone","zuerich","cc.ua","inf.ua","ltd.ua","beep.pl","*.compute.estate","*.alces.network","alwaysdata.net","cloudfront.net","*.compute.amazonaws.com","*.compute-1.amazonaws.com","*.compute.amazonaws.com.cn","us-east-1.amazonaws.com","cn-north-1.eb.amazonaws.com.cn","elasticbeanstalk.com","ap-northeast-1.elasticbeanstalk.com","ap-northeast-2.elasticbeanstalk.com","ap-northeast-3.elasticbeanstalk.com","ap-south-1.elasticbeanstalk.com","ap-southeast-1.elasticbeanstalk.com","ap-southeast-2.elasticbeanstalk.com","ca-central-1.elasticbeanstalk.com","eu-central-1.elasticbeanstalk.com","eu-west-1.elasticbeanstalk.com","eu-west-2.elasticbeanstalk.com","eu-west-3.elasticbeanstalk.com","sa-east-1.elasticbeanstalk.com","us-east-1.elasticbeanstalk.com","us-east-2.elasticbeanstalk.com","us-gov-west-1.elasticbeanstalk.com","us-west-1.elasticbeanstalk.com","us-west-2.elasticbeanstalk.com","*.elb.amazonaws.com","*.elb.amazonaws.com.cn","s3.amazonaws.com","s3-ap-northeast-1.amazonaws.com","s3-ap-northeast-2.amazonaws.com","s3-ap-south-1.amazonaws.com","s3-ap-southeast-1.amazonaws.com","s3-ap-southeast-2.amazonaws.com","s3-ca-central-1.amazonaws.com","s3-eu-central-1.amazonaws.com","s3-eu-west-1.amazonaws.com","s3-eu-west-2.amazonaws.com","s3-eu-west-3.amazonaws.com","s3-external-1.amazonaws.com","s3-fips-us-gov-west-1.amazonaws.com","s3-sa-east-1.amazonaws.com","s3-us-gov-west-1.amazonaws.com","s3-us-east-2.amazonaws.com","s3-us-west-1.amazonaws.com","s3-us-west-2.amazonaws.com","s3.ap-northeast-2.amazonaws.com","s3.ap-south-1.amazonaws.com","s3.cn-north-1.amazonaws.com.cn","s3.ca-central-1.amazonaws.com","s3.eu-central-1.amazonaws.com","s3.eu-west-2.amazonaws.com","s3.eu-west-3.amazonaws.com","s3.us-east-2.amazonaws.com","s3.dualstack.ap-northeast-1.amazonaws.com","s3.dualstack.ap-northeast-2.amazonaws.com","s3.dualstack.ap-south-1.amazonaws.com","s3.dualstack.ap-southeast-1.amazonaws.com","s3.dualstack.ap-southeast-2.amazonaws.com","s3.dualstack.ca-central-1.amazonaws.com","s3.dualstack.eu-central-1.amazonaws.com","s3.dualstack.eu-west-1.amazonaws.com","s3.dualstack.eu-west-2.amazonaws.com","s3.dualstack.eu-west-3.amazonaws.com","s3.dualstack.sa-east-1.amazonaws.com","s3.dualstack.us-east-1.amazonaws.com","s3.dualstack.us-east-2.amazonaws.com","s3-website-us-east-1.amazonaws.com","s3-website-us-west-1.amazonaws.com","s3-website-us-west-2.amazonaws.com","s3-website-ap-northeast-1.amazonaws.com","s3-website-ap-southeast-1.amazonaws.com","s3-website-ap-southeast-2.amazonaws.com","s3-website-eu-west-1.amazonaws.com","s3-website-sa-east-1.amazonaws.com","s3-website.ap-northeast-2.amazonaws.com","s3-website.ap-south-1.amazonaws.com","s3-website.ca-central-1.amazonaws.com","s3-website.eu-central-1.amazonaws.com","s3-website.eu-west-2.amazonaws.com","s3-website.eu-west-3.amazonaws.com","s3-website.us-east-2.amazonaws.com","t3l3p0rt.net","tele.amune.org","on-aptible.com","user.party.eus","pimienta.org","poivron.org","potager.org","sweetpepper.org","myasustor.com","myfritz.net","*.awdev.ca","*.advisor.ws","backplaneapp.io","betainabox.com","bnr.la","blackbaudcdn.net","boomla.net","boxfuse.io","square7.ch","bplaced.com","bplaced.de","square7.de","bplaced.net","square7.net","browsersafetymark.io","mycd.eu","ae.org","ar.com","br.com","cn.com","com.de","com.se","de.com","eu.com","gb.com","gb.net","hu.com","hu.net","jp.net","jpn.com","kr.com","mex.com","no.com","qc.com","ru.com","sa.com","se.net","uk.com","uk.net","us.com","uy.com","za.bz","za.com","africa.com","gr.com","in.net","us.org","co.com","c.la","certmgr.org","xenapponazure.com","virtueeldomein.nl","cleverapps.io","c66.me","cloud66.ws","jdevcloud.com","wpdevcloud.com","cloudaccess.host","freesite.host","cloudaccess.net","cloudcontrolled.com","cloudcontrolapp.com","co.ca","*.otap.co","co.cz","c.cdn77.org","cdn77-ssl.net","r.cdn77.net","rsc.cdn77.org","ssl.origin.cdn77-secure.org","cloudns.asia","cloudns.biz","cloudns.club","cloudns.cc","cloudns.eu","cloudns.in","cloudns.info","cloudns.org","cloudns.pro","cloudns.pw","cloudns.us","cloudeity.net","cnpy.gdn","co.nl","co.no","webhosting.be","hosting-cluster.nl","dyn.cosidns.de","dynamisches-dns.de","dnsupdater.de","internet-dns.de","l-o-g-i-n.de","dynamic-dns.info","feste-ip.net","knx-server.net","static-access.net","realm.cz","*.cryptonomic.net","cupcake.is","cyon.link","cyon.site","daplie.me","localhost.daplie.me","dattolocal.com","dattorelay.com","dattoweb.com","mydatto.com","dattolocal.net","mydatto.net","biz.dk","co.dk","firm.dk","reg.dk","store.dk","debian.net","dedyn.io","dnshome.de","drayddns.com","dreamhosters.com","mydrobo.com","drud.io","drud.us","duckdns.org","dy.fi","tunk.org","dyndns-at-home.com","dyndns-at-work.com","dyndns-blog.com","dyndns-free.com","dyndns-home.com","dyndns-ip.com","dyndns-mail.com","dyndns-office.com","dyndns-pics.com","dyndns-remote.com","dyndns-server.com","dyndns-web.com","dyndns-wiki.com","dyndns-work.com","dyndns.biz","dyndns.info","dyndns.org","dyndns.tv","at-band-camp.net","ath.cx","barrel-of-knowledge.info","barrell-of-knowledge.info","better-than.tv","blogdns.com","blogdns.net","blogdns.org","blogsite.org","boldlygoingnowhere.org","broke-it.net","buyshouses.net","cechire.com","dnsalias.com","dnsalias.net","dnsalias.org","dnsdojo.com","dnsdojo.net","dnsdojo.org","does-it.net","doesntexist.com","doesntexist.org","dontexist.com","dontexist.net","dontexist.org","doomdns.com","doomdns.org","dvrdns.org","dyn-o-saur.com","dynalias.com","dynalias.net","dynalias.org","dynathome.net","dyndns.ws","endofinternet.net","endofinternet.org","endoftheinternet.org","est-a-la-maison.com","est-a-la-masion.com","est-le-patron.com","est-mon-blogueur.com","for-better.biz","for-more.biz","for-our.info","for-some.biz","for-the.biz","forgot.her.name","forgot.his.name","from-ak.com","from-al.com","from-ar.com","from-az.net","from-ca.com","from-co.net","from-ct.com","from-dc.com","from-de.com","from-fl.com","from-ga.com","from-hi.com","from-ia.com","from-id.com","from-il.com","from-in.com","from-ks.com","from-ky.com","from-la.net","from-ma.com","from-md.com","from-me.org","from-mi.com","from-mn.com","from-mo.com","from-ms.com","from-mt.com","from-nc.com","from-nd.com","from-ne.com","from-nh.com","from-nj.com","from-nm.com","from-nv.com","from-ny.net","from-oh.com","from-ok.com","from-or.com","from-pa.com","from-pr.com","from-ri.com","from-sc.com","from-sd.com","from-tn.com","from-tx.com","from-ut.com","from-va.com","from-vt.com","from-wa.com","from-wi.com","from-wv.com","from-wy.com","ftpaccess.cc","fuettertdasnetz.de","game-host.org","game-server.cc","getmyip.com","gets-it.net","go.dyndns.org","gotdns.com","gotdns.org","groks-the.info","groks-this.info","ham-radio-op.net","here-for-more.info","hobby-site.com","hobby-site.org","home.dyndns.org","homedns.org","homeftp.net","homeftp.org","homeip.net","homelinux.com","homelinux.net","homelinux.org","homeunix.com","homeunix.net","homeunix.org","iamallama.com","in-the-band.net","is-a-anarchist.com","is-a-blogger.com","is-a-bookkeeper.com","is-a-bruinsfan.org","is-a-bulls-fan.com","is-a-candidate.org","is-a-caterer.com","is-a-celticsfan.org","is-a-chef.com","is-a-chef.net","is-a-chef.org","is-a-conservative.com","is-a-cpa.com","is-a-cubicle-slave.com","is-a-democrat.com","is-a-designer.com","is-a-doctor.com","is-a-financialadvisor.com","is-a-geek.com","is-a-geek.net","is-a-geek.org","is-a-green.com","is-a-guru.com","is-a-hard-worker.com","is-a-hunter.com","is-a-knight.org","is-a-landscaper.com","is-a-lawyer.com","is-a-liberal.com","is-a-libertarian.com","is-a-linux-user.org","is-a-llama.com","is-a-musician.com","is-a-nascarfan.com","is-a-nurse.com","is-a-painter.com","is-a-patsfan.org","is-a-personaltrainer.com","is-a-photographer.com","is-a-player.com","is-a-republican.com","is-a-rockstar.com","is-a-socialist.com","is-a-soxfan.org","is-a-student.com","is-a-teacher.com","is-a-techie.com","is-a-therapist.com","is-an-accountant.com","is-an-actor.com","is-an-actress.com","is-an-anarchist.com","is-an-artist.com","is-an-engineer.com","is-an-entertainer.com","is-by.us","is-certified.com","is-found.org","is-gone.com","is-into-anime.com","is-into-cars.com","is-into-cartoons.com","is-into-games.com","is-leet.com","is-lost.org","is-not-certified.com","is-saved.org","is-slick.com","is-uberleet.com","is-very-bad.org","is-very-evil.org","is-very-good.org","is-very-nice.org","is-very-sweet.org","is-with-theband.com","isa-geek.com","isa-geek.net","isa-geek.org","isa-hockeynut.com","issmarterthanyou.com","isteingeek.de","istmein.de","kicks-ass.net","kicks-ass.org","knowsitall.info","land-4-sale.us","lebtimnetz.de","leitungsen.de","likes-pie.com","likescandy.com","merseine.nu","mine.nu","misconfused.org","mypets.ws","myphotos.cc","neat-url.com","office-on-the.net","on-the-web.tv","podzone.net","podzone.org","readmyblog.org","saves-the-whales.com","scrapper-site.net","scrapping.cc","selfip.biz","selfip.com","selfip.info","selfip.net","selfip.org","sells-for-less.com","sells-for-u.com","sells-it.net","sellsyourhome.org","servebbs.com","servebbs.net","servebbs.org","serveftp.net","serveftp.org","servegame.org","shacknet.nu","simple-url.com","space-to-rent.com","stuff-4-sale.org","stuff-4-sale.us","teaches-yoga.com","thruhere.net","traeumtgerade.de","webhop.biz","webhop.info","webhop.net","webhop.org","worse-than.tv","writesthisblog.com","ddnss.de","dyn.ddnss.de","dyndns.ddnss.de","dyndns1.de","dyn-ip24.de","home-webserver.de","dyn.home-webserver.de","myhome-server.de","ddnss.org","definima.net","definima.io","bci.dnstrace.pro","ddnsfree.com","ddnsgeek.com","giize.com","gleeze.com","kozow.com","loseyourip.com","ooguy.com","theworkpc.com","casacam.net","dynu.net","accesscam.org","camdvr.org","freeddns.org","mywire.org","webredirect.org","myddns.rocks","blogsite.xyz","dynv6.net","e4.cz","mytuleap.com","enonic.io","customer.enonic.io","eu.org","al.eu.org","asso.eu.org","at.eu.org","au.eu.org","be.eu.org","bg.eu.org","ca.eu.org","cd.eu.org","ch.eu.org","cn.eu.org","cy.eu.org","cz.eu.org","de.eu.org","dk.eu.org","edu.eu.org","ee.eu.org","es.eu.org","fi.eu.org","fr.eu.org","gr.eu.org","hr.eu.org","hu.eu.org","ie.eu.org","il.eu.org","in.eu.org","int.eu.org","is.eu.org","it.eu.org","jp.eu.org","kr.eu.org","lt.eu.org","lu.eu.org","lv.eu.org","mc.eu.org","me.eu.org","mk.eu.org","mt.eu.org","my.eu.org","net.eu.org","ng.eu.org","nl.eu.org","no.eu.org","nz.eu.org","paris.eu.org","pl.eu.org","pt.eu.org","q-a.eu.org","ro.eu.org","ru.eu.org","se.eu.org","si.eu.org","sk.eu.org","tr.eu.org","uk.eu.org","us.eu.org","eu-1.evennode.com","eu-2.evennode.com","eu-3.evennode.com","eu-4.evennode.com","us-1.evennode.com","us-2.evennode.com","us-3.evennode.com","us-4.evennode.com","twmail.cc","twmail.net","twmail.org","mymailer.com.tw","url.tw","apps.fbsbx.com","ru.net","adygeya.ru","bashkiria.ru","bir.ru","cbg.ru","com.ru","dagestan.ru","grozny.ru","kalmykia.ru","kustanai.ru","marine.ru","mordovia.ru","msk.ru","mytis.ru","nalchik.ru","nov.ru","pyatigorsk.ru","spb.ru","vladikavkaz.ru","vladimir.ru","abkhazia.su","adygeya.su","aktyubinsk.su","arkhangelsk.su","armenia.su","ashgabad.su","azerbaijan.su","balashov.su","bashkiria.su","bryansk.su","bukhara.su","chimkent.su","dagestan.su","east-kazakhstan.su","exnet.su","georgia.su","grozny.su","ivanovo.su","jambyl.su","kalmykia.su","kaluga.su","karacol.su","karaganda.su","karelia.su","khakassia.su","krasnodar.su","kurgan.su","kustanai.su","lenug.su","mangyshlak.su","mordovia.su","msk.su","murmansk.su","nalchik.su","navoi.su","north-kazakhstan.su","nov.su","obninsk.su","penza.su","pokrovsk.su","sochi.su","spb.su","tashkent.su","termez.su","togliatti.su","troitsk.su","tselinograd.su","tula.su","tuva.su","vladikavkaz.su","vladimir.su","vologda.su","channelsdvr.net","fastlylb.net","map.fastlylb.net","freetls.fastly.net","map.fastly.net","a.prod.fastly.net","global.prod.fastly.net","a.ssl.fastly.net","b.ssl.fastly.net","global.ssl.fastly.net","fastpanel.direct","fastvps-server.com","fhapp.xyz","fedorainfracloud.org","fedorapeople.org","cloud.fedoraproject.org","app.os.fedoraproject.org","app.os.stg.fedoraproject.org","filegear.me","firebaseapp.com","flynnhub.com","flynnhosting.net","freebox-os.com","freeboxos.com","fbx-os.fr","fbxos.fr","freebox-os.fr","freeboxos.fr","freedesktop.org","*.futurecms.at","*.ex.futurecms.at","*.in.futurecms.at","futurehosting.at","futuremailing.at","*.ex.ortsinfo.at","*.kunden.ortsinfo.at","*.statics.cloud","service.gov.uk","github.io","githubusercontent.com","gitlab.io","homeoffice.gov.uk","ro.im","shop.ro","goip.de","*.0emm.com","appspot.com","blogspot.ae","blogspot.al","blogspot.am","blogspot.ba","blogspot.be","blogspot.bg","blogspot.bj","blogspot.ca","blogspot.cf","blogspot.ch","blogspot.cl","blogspot.co.at","blogspot.co.id","blogspot.co.il","blogspot.co.ke","blogspot.co.nz","blogspot.co.uk","blogspot.co.za","blogspot.com","blogspot.com.ar","blogspot.com.au","blogspot.com.br","blogspot.com.by","blogspot.com.co","blogspot.com.cy","blogspot.com.ee","blogspot.com.eg","blogspot.com.es","blogspot.com.mt","blogspot.com.ng","blogspot.com.tr","blogspot.com.uy","blogspot.cv","blogspot.cz","blogspot.de","blogspot.dk","blogspot.fi","blogspot.fr","blogspot.gr","blogspot.hk","blogspot.hr","blogspot.hu","blogspot.ie","blogspot.in","blogspot.is","blogspot.it","blogspot.jp","blogspot.kr","blogspot.li","blogspot.lt","blogspot.lu","blogspot.md","blogspot.mk","blogspot.mr","blogspot.mx","blogspot.my","blogspot.nl","blogspot.no","blogspot.pe","blogspot.pt","blogspot.qa","blogspot.re","blogspot.ro","blogspot.rs","blogspot.ru","blogspot.se","blogspot.sg","blogspot.si","blogspot.sk","blogspot.sn","blogspot.td","blogspot.tw","blogspot.ug","blogspot.vn","cloudfunctions.net","cloud.goog","codespot.com","googleapis.com","googlecode.com","pagespeedmobilizer.com","publishproxy.com","withgoogle.com","withyoutube.com","hashbang.sh","hasura.app","hasura-app.io","hepforge.org","herokuapp.com","herokussl.com","myravendb.com","ravendb.community","ravendb.me","development.run","ravendb.run","moonscale.net","iki.fi","biz.at","info.at","info.cx","ac.leg.br","al.leg.br","am.leg.br","ap.leg.br","ba.leg.br","ce.leg.br","df.leg.br","es.leg.br","go.leg.br","ma.leg.br","mg.leg.br","ms.leg.br","mt.leg.br","pa.leg.br","pb.leg.br","pe.leg.br","pi.leg.br","pr.leg.br","rj.leg.br","rn.leg.br","ro.leg.br","rr.leg.br","rs.leg.br","sc.leg.br","se.leg.br","sp.leg.br","to.leg.br","pixolino.com","ipifony.net","mein-iserv.de","test-iserv.de","myjino.ru","*.hosting.myjino.ru","*.landing.myjino.ru","*.spectrum.myjino.ru","*.vps.myjino.ru","*.triton.zone","*.cns.joyent.com","js.org","keymachine.de","knightpoint.systems","co.krd","edu.krd","git-repos.de","lcube-server.de","svn-repos.de","app.lmpm.com","linkitools.space","linkyard.cloud","linkyard-cloud.ch","we.bs","uklugs.org","glug.org.uk","lug.org.uk","lugs.org.uk","barsy.bg","barsy.co.uk","barsyonline.co.uk","barsycenter.com","barsyonline.com","barsy.club","barsy.de","barsy.eu","barsy.in","barsy.info","barsy.io","barsy.me","barsy.menu","barsy.mobi","barsy.net","barsy.online","barsy.org","barsy.pro","barsy.pub","barsy.shop","barsy.site","barsy.support","barsy.uk","*.magentosite.cloud","mayfirst.info","mayfirst.org","hb.cldmail.ru","miniserver.com","memset.net","cloud.metacentrum.cz","custom.metacentrum.cz","flt.cloud.muni.cz","usr.cloud.muni.cz","meteorapp.com","eu.meteorapp.com","co.pl","azurecontainer.io","azurewebsites.net","azure-mobile.net","cloudapp.net","mozilla-iot.org","bmoattachments.org","net.ru","org.ru","pp.ru","bitballoon.com","netlify.com","4u.com","ngrok.io","nh-serv.co.uk","nfshost.com","dnsking.ch","mypi.co","n4t.co","001www.com","ddnslive.com","myiphost.com","forumz.info","16-b.it","32-b.it","64-b.it","soundcast.me","tcp4.me","dnsup.net","hicam.net","now-dns.net","ownip.net","vpndns.net","dynserv.org","now-dns.org","x443.pw","now-dns.top","ntdll.top","freeddns.us","crafting.xyz","zapto.xyz","nsupdate.info","nerdpol.ovh","blogsyte.com","brasilia.me","cable-modem.org","ciscofreak.com","collegefan.org","couchpotatofries.org","damnserver.com","ddns.me","ditchyourip.com","dnsfor.me","dnsiskinky.com","dvrcam.info","dynns.com","eating-organic.net","fantasyleague.cc","geekgalaxy.com","golffan.us","health-carereform.com","homesecuritymac.com","homesecuritypc.com","hopto.me","ilovecollege.info","loginto.me","mlbfan.org","mmafan.biz","myactivedirectory.com","mydissent.net","myeffect.net","mymediapc.net","mypsx.net","mysecuritycamera.com","mysecuritycamera.net","mysecuritycamera.org","net-freaks.com","nflfan.org","nhlfan.net","no-ip.ca","no-ip.co.uk","no-ip.net","noip.us","onthewifi.com","pgafan.net","point2this.com","pointto.us","privatizehealthinsurance.net","quicksytes.com","read-books.org","securitytactics.com","serveexchange.com","servehumour.com","servep2p.com","servesarcasm.com","stufftoread.com","ufcfan.org","unusualperson.com","workisboring.com","3utilities.com","bounceme.net","ddns.net","ddnsking.com","gotdns.ch","hopto.org","myftp.biz","myftp.org","myvnc.com","no-ip.biz","no-ip.info","no-ip.org","noip.me","redirectme.net","servebeer.com","serveblog.net","servecounterstrike.com","serveftp.com","servegame.com","servehalflife.com","servehttp.com","serveirc.com","serveminecraft.net","servemp3.com","servepics.com","servequake.com","sytes.net","webhop.me","zapto.org","stage.nodeart.io","nodum.co","nodum.io","pcloud.host","nyc.mn","nom.ae","nom.af","nom.ai","nom.al","nym.by","nym.bz","nom.cl","nom.gd","nom.ge","nom.gl","nym.gr","nom.gt","nym.gy","nom.hn","nym.ie","nom.im","nom.ke","nym.kz","nym.la","nym.lc","nom.li","nym.li","nym.lt","nym.lu","nym.me","nom.mk","nym.mn","nym.mx","nom.nu","nym.nz","nym.pe","nym.pt","nom.pw","nom.qa","nym.ro","nom.rs","nom.si","nym.sk","nom.st","nym.su","nym.sx","nom.tj","nym.tw","nom.ug","nom.uy","nom.vc","nom.vg","cya.gg","cloudycluster.net","nid.io","opencraft.hosting","operaunite.com","outsystemscloud.com","ownprovider.com","own.pm","ox.rs","oy.lc","pgfog.com","pagefrontapp.com","art.pl","gliwice.pl","krakow.pl","poznan.pl","wroc.pl","zakopane.pl","pantheonsite.io","gotpantheon.com","mypep.link","on-web.fr","*.platform.sh","*.platformsh.site","xen.prgmr.com","priv.at","protonet.io","chirurgiens-dentistes-en-france.fr","byen.site","ras.ru","qa2.com","dev-myqnapcloud.com","alpha-myqnapcloud.com","myqnapcloud.com","*.quipelements.com","vapor.cloud","vaporcloud.io","rackmaze.com","rackmaze.net","rhcloud.com","resindevice.io","devices.resinstaging.io","hzc.io","wellbeingzone.eu","ptplus.fit","wellbeingzone.co.uk","sandcats.io","logoip.de","logoip.com","schokokeks.net","scrysec.com","firewall-gateway.com","firewall-gateway.de","my-gateway.de","my-router.de","spdns.de","spdns.eu","firewall-gateway.net","my-firewall.org","myfirewall.org","spdns.org","*.s5y.io","*.sensiosite.cloud","biz.ua","co.ua","pp.ua","shiftedit.io","myshopblocks.com","1kapp.com","appchizi.com","applinzi.com","sinaapp.com","vipsinaapp.com","bounty-full.com","alpha.bounty-full.com","beta.bounty-full.com","static.land","dev.static.land","sites.static.land","apps.lair.io","*.stolos.io","spacekit.io","customer.speedpartner.de","storj.farm","utwente.io","temp-dns.com","diskstation.me","dscloud.biz","dscloud.me","dscloud.mobi","dsmynas.com","dsmynas.net","dsmynas.org","familyds.com","familyds.net","familyds.org","i234.me","myds.me","synology.me","vpnplus.to","taifun-dns.de","gda.pl","gdansk.pl","gdynia.pl","med.pl","sopot.pl","gwiddle.co.uk","cust.dev.thingdust.io","cust.disrec.thingdust.io","cust.prod.thingdust.io","cust.testing.thingdust.io","bloxcms.com","townnews-staging.com","12hp.at","2ix.at","4lima.at","lima-city.at","12hp.ch","2ix.ch","4lima.ch","lima-city.ch","trafficplex.cloud","de.cool","12hp.de","2ix.de","4lima.de","lima-city.de","1337.pictures","clan.rip","lima-city.rocks","webspace.rocks","lima.zone","*.transurl.be","*.transurl.eu","*.transurl.nl","tuxfamily.org","dd-dns.de","diskstation.eu","diskstation.org","dray-dns.de","draydns.de","dyn-vpn.de","dynvpn.de","mein-vigor.de","my-vigor.de","my-wan.de","syno-ds.de","synology-diskstation.de","synology-ds.de","uber.space","*.uberspace.de","hk.com","hk.org","ltd.hk","inc.hk","virtualuser.de","virtual-user.de","lib.de.us","2038.io","router.management","v-info.info","wedeploy.io","wedeploy.me","wedeploy.sh","remotewd.com","wmflabs.org","half.host","xnbay.com","u2.xnbay.com","u2-local.xnbay.com","cistron.nl","demon.nl","xs4all.space","official.academy","yolasite.com","ybo.faith","yombo.me","homelink.one","ybo.party","ybo.review","ybo.science","ybo.trade","nohost.me","noho.st","za.net","za.org","now.sh","zone.id"]
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	/*jshint unused:false */
+
+	function Store() {
+	}
+	exports.Store = Store;
+
+	// Stores may be synchronous, but are still required to use a
+	// Continuation-Passing Style API.  The CookieJar itself will expose a "*Sync"
+	// API that converts from synchronous-callbacks to imperative style.
+	Store.prototype.synchronous = false;
+
+	Store.prototype.findCookie = function(domain, path, key, cb) {
+	  throw new Error('findCookie is not implemented');
+	};
+
+	Store.prototype.findCookies = function(domain, path, cb) {
+	  throw new Error('findCookies is not implemented');
+	};
+
+	Store.prototype.putCookie = function(cookie, cb) {
+	  throw new Error('putCookie is not implemented');
+	};
+
+	Store.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // recommended default implementation:
+	  // return this.putCookie(newCookie, cb);
+	  throw new Error('updateCookie is not implemented');
+	};
+
+	Store.prototype.removeCookie = function(domain, path, key, cb) {
+	  throw new Error('removeCookie is not implemented');
+	};
+
+	Store.prototype.removeCookies = function(domain, path, cb) {
+	  throw new Error('removeCookies is not implemented');
+	};
+
+	Store.prototype.getAllCookies = function(cb) {
+	  throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	'use strict';
+	var Store = __webpack_require__(17).Store;
+	var permuteDomain = __webpack_require__(19).permuteDomain;
+	var pathMatch = __webpack_require__(20).pathMatch;
+	var util = __webpack_require__(9);
+
+	function MemoryCookieStore() {
+	  Store.call(this);
+	  this.idx = {};
+	}
+	util.inherits(MemoryCookieStore, Store);
+	exports.MemoryCookieStore = MemoryCookieStore;
+	MemoryCookieStore.prototype.idx = null;
+
+	// Since it's just a struct in RAM, this Store is synchronous
+	MemoryCookieStore.prototype.synchronous = true;
+
+	// force a default depth:
+	MemoryCookieStore.prototype.inspect = function() {
+	  return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
+	};
+
+	// Use the new custom inspection symbol to add the custom inspect function if
+	// available.
+	if (util.inspect.custom) {
+	  MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
+	}
+
+	MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
+	  if (!this.idx[domain]) {
+	    return cb(null,undefined);
+	  }
+	  if (!this.idx[domain][path]) {
+	    return cb(null,undefined);
+	  }
+	  return cb(null,this.idx[domain][path][key]||null);
+	};
+
+	MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
+	  var results = [];
+	  if (!domain) {
+	    return cb(null,[]);
+	  }
+
+	  var pathMatcher;
+	  if (!path) {
+	    // null means "all paths"
+	    pathMatcher = function matchAll(domainIndex) {
+	      for (var curPath in domainIndex) {
+	        var pathIndex = domainIndex[curPath];
+	        for (var key in pathIndex) {
+	          results.push(pathIndex[key]);
+	        }
+	      }
+	    };
+
+	  } else {
+	    pathMatcher = function matchRFC(domainIndex) {
+	       //NOTE: we should use path-match algorithm from S5.1.4 here
+	       //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
+	       Object.keys(domainIndex).forEach(function (cookiePath) {
+	         if (pathMatch(path, cookiePath)) {
+	           var pathIndex = domainIndex[cookiePath];
+
+	           for (var key in pathIndex) {
+	             results.push(pathIndex[key]);
+	           }
+	         }
+	       });
+	     };
+	  }
+
+	  var domains = permuteDomain(domain) || [domain];
+	  var idx = this.idx;
+	  domains.forEach(function(curDomain) {
+	    var domainIndex = idx[curDomain];
+	    if (!domainIndex) {
+	      return;
+	    }
+	    pathMatcher(domainIndex);
+	  });
+
+	  cb(null,results);
+	};
+
+	MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
+	  if (!this.idx[cookie.domain]) {
+	    this.idx[cookie.domain] = {};
+	  }
+	  if (!this.idx[cookie.domain][cookie.path]) {
+	    this.idx[cookie.domain][cookie.path] = {};
+	  }
+	  this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
+	  // updateCookie() may avoid updating cookies that are identical.  For example,
+	  // lastAccessed may not be important to some stores and an equality
+	  // comparison could exclude that field.
+	  this.putCookie(newCookie,cb);
+	};
+
+	MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
+	  if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
+	    delete this.idx[domain][path][key];
+	  }
+	  cb(null);
+	};
+
+	MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
+	  if (this.idx[domain]) {
+	    if (path) {
+	      delete this.idx[domain][path];
+	    } else {
+	      delete this.idx[domain];
+	    }
+	  }
+	  return cb(null);
+	};
+
+	MemoryCookieStore.prototype.getAllCookies = function(cb) {
+	  var cookies = [];
+	  var idx = this.idx;
+
+	  var domains = Object.keys(idx);
+	  domains.forEach(function(domain) {
+	    var paths = Object.keys(idx[domain]);
+	    paths.forEach(function(path) {
+	      var keys = Object.keys(idx[domain][path]);
+	      keys.forEach(function(key) {
+	        if (key !== null) {
+	          cookies.push(idx[domain][path][key]);
+	        }
+	      });
+	    });
+	  });
+
+	  // Sort by creationIndex so deserializing retains the creation order.
+	  // When implementing your own store, this SHOULD retain the order too
+	  cookies.sort(function(a,b) {
+	    return (a.creationIndex||0) - (b.creationIndex||0);
+	  });
+
+	  cb(null, cookies);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	var pubsuffix = __webpack_require__(13);
+
+	// Gives the permutation of all possible domainMatch()es of a given domain. The
+	// array is in shortest-to-longest order.  Handy for indexing.
+	function permuteDomain (domain) {
+	  var pubSuf = pubsuffix.getPublicSuffix(domain);
+	  if (!pubSuf) {
+	    return null;
+	  }
+	  if (pubSuf == domain) {
+	    return [domain];
+	  }
+
+	  var prefix = domain.slice(0, -(pubSuf.length + 1)); // ".example.com"
+	  var parts = prefix.split('.').reverse();
+	  var cur = pubSuf;
+	  var permutations = [cur];
+	  while (parts.length) {
+	    cur = parts.shift() + '.' + cur;
+	    permutations.push(cur);
+	  }
+	  return permutations;
+	}
+
+	exports.permuteDomain = permuteDomain;
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	/*!
+	 * Copyright (c) 2015, Salesforce.com, Inc.
+	 * All rights reserved.
+	 *
+	 * Redistribution and use in source and binary forms, with or without
+	 * modification, are permitted provided that the following conditions are met:
+	 *
+	 * 1. Redistributions of source code must retain the above copyright notice,
+	 * this list of conditions and the following disclaimer.
+	 *
+	 * 2. Redistributions in binary form must reproduce the above copyright notice,
+	 * this list of conditions and the following disclaimer in the documentation
+	 * and/or other materials provided with the distribution.
+	 *
+	 * 3. Neither the name of Salesforce.com nor the names of its contributors may
+	 * be used to endorse or promote products derived from this software without
+	 * specific prior written permission.
+	 *
+	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+	 * POSSIBILITY OF SUCH DAMAGE.
+	 */
+	"use strict";
+	/*
+	 * "A request-path path-matches a given cookie-path if at least one of the
+	 * following conditions holds:"
+	 */
+	function pathMatch (reqPath, cookiePath) {
+	  // "o  The cookie-path and the request-path are identical."
+	  if (cookiePath === reqPath) {
+	    return true;
+	  }
+
+	  var idx = reqPath.indexOf(cookiePath);
+	  if (idx === 0) {
+	    // "o  The cookie-path is a prefix of the request-path, and the last
+	    // character of the cookie-path is %x2F ("/")."
+	    if (cookiePath.substr(-1) === "/") {
+	      return true;
+	    }
+
+	    // " o  The cookie-path is a prefix of the request-path, and the first
+	    // character of the request-path that is not included in the cookie- path
+	    // is a %x2F ("/") character."
+	    if (reqPath.substr(cookiePath.length, 1) === "/") {
+	      return true;
+	    }
+	  }
+
+	  return false;
+	}
+
+	exports.pathMatch = pathMatch;
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	module.exports = {"_from":"tough-cookie@2.4.3","_id":"tough-cookie@2.4.3","_inBundle":false,"_integrity":"sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==","_location":"/tough-cookie","_phantomChildren":{},"_requested":{"type":"version","registry":true,"raw":"tough-cookie@2.4.3","name":"tough-cookie","escapedName":"tough-cookie","rawSpec":"2.4.3","saveSpec":null,"fetchSpec":"2.4.3"},"_requiredBy":["#DEV:/"],"_resolved":"https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz","_shasum":"53f36da3f47783b0925afa06ff9f3b165280f781","_spec":"tough-cookie@2.4.3","_where":"/Users/sefa/Entwicklung/umd-tough-cookie","author":{"name":"Jeremy Stashewsky","email":"jstash@gmail.com"},"bugs":{"url":"https://github.com/salesforce/tough-cookie/issues"},"bundleDependencies":false,"contributors":[{"name":"Alexander Savin"},{"name":"Ian Livingstone"},{"name":"Ivan Nikulin"},{"name":"Lalit Kapoor"},{"name":"Sam Thompson"},{"name":"Sebastian Mayr"}],"dependencies":{"psl":"^1.1.24","punycode":"^1.4.1"},"deprecated":false,"description":"RFC6265 Cookies and Cookie Jar for node.js","devDependencies":{"async":"^1.4.2","nyc":"^11.6.0","string.prototype.repeat":"^0.2.0","vows":"^0.8.1"},"engines":{"node":">=0.8"},"files":["lib"],"homepage":"https://github.com/salesforce/tough-cookie","keywords":["HTTP","cookie","cookies","set-cookie","cookiejar","jar","RFC6265","RFC2965"],"license":"BSD-3-Clause","main":"./lib/cookie","name":"tough-cookie","repository":{"type":"git","url":"git://github.com/salesforce/tough-cookie.git"},"scripts":{"cover":"nyc --reporter=lcov --reporter=html vows test/*_test.js","test":"vows test/*_test.js"},"version":"2.4.3"}
+
+/***/ })
+/******/ ])
+});
+;
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
new file mode 100644
index 0000000..8d9228a
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-advanced-http/www/url-util.js
@@ -0,0 +1,106 @@
+cordova.define("cordova-plugin-advanced-http.url-util", function(require, exports, module) {
+module.exports = function init(jsUtil) {
+  return {
+    parseUrl: parseUrl,
+    appendQueryParamsString: appendQueryParamsString,
+    serializeQueryParams: serializeQueryParams
+  }
+
+  function parseUrl(url) {
+    var match = url.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
+
+    return match && {
+        protocol: match[1],
+        host: match[2],
+        hostname: match[3],
+        port: match[4] || '',
+        pathname: match[5],
+        search: match[6],
+        hash: match[7]
+    }
+  }
+
+  function appendQueryParamsString(url, params) {
+    if (!url.length || !params.length) {
+      return url;
+    }
+
+    var parsed = parseUrl(url);
+
+    return parsed.protocol
+      + '//'
+      + parsed.host
+      + parsed.pathname
+      + (parsed.search.length ? parsed.search + '&' + params : '?' + params)
+      + parsed.hash;
+  }
+
+  function serializeQueryParams(params, encode) {
+    return serializeObject('', params, encode);
+  }
+
+  function serializeObject(parentKey, object, encode) {
+    var parts = [];
+
+    for (var key in object) {
+      if (!object.hasOwnProperty(key)) {
+        continue;
+      }
+
+      var identifier = parentKey.length ? parentKey + '[' + key + ']' : key;
+
+      if (jsUtil.getTypeOf(object[key]) === 'Array') {
+        parts.push(serializeArray(identifier, object[key], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(object[key]) === 'Object') {
+        parts.push(serializeObject(identifier, object[key], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, key, encode) + '=' + serializeValue(object[key], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeArray(parentKey, array, encode) {
+    var parts = [];
+
+    for (var i = 0; i < array.length; ++i) {
+      if (jsUtil.getTypeOf(array[i]) === 'Array') {
+        parts.push(serializeArray(parentKey + '[]', array[i], encode));
+        continue;
+      } else if (jsUtil.getTypeOf(array[i]) === 'Object') {
+        parts.push(serializeObject(parentKey + '[]' + array[i], encode));
+        continue;
+      }
+
+      parts.push(serializeIdentifier(parentKey, '', encode) + '=' + serializeValue(array[i], encode));
+    }
+
+    return parts.join('&');
+  }
+
+  function serializeIdentifier(parentKey, key, encode) {
+    if (!parentKey.length) {
+      return encode ? encodeURIComponent(key) : key;
+    }
+
+    if (encode) {
+      return encodeURIComponent(parentKey) + '[' + encodeURIComponent(key) + ']';
+    } else {
+      return parentKey + '[' + key + ']';
+    }
+  }
+
+  function serializeValue(value, encode) {
+    if (encode) {
+      return encodeURIComponent(value);
+    } else {
+      return value;
+    }
+  }
+};
+
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/Camera.js b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/Camera.js
new file mode 100644
index 0000000..3f614ec
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/Camera.js
@@ -0,0 +1,188 @@
+cordova.define("cordova-plugin-camera.camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var Camera = require('./Camera');
+// XXX: commented out
+// CameraPopoverHandle = require('./CameraPopoverHandle');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * @exports camera
+ */
+var cameraExport = {};
+
+// Tack on the Camera Constants to the base camera plugin.
+for (var key in Camera) {
+    cameraExport[key] = Camera[key];
+}
+
+/**
+ * Callback function that provides an error message.
+ * @callback module:camera.onError
+ * @param {string} message - The message is provided by the device's native code.
+ */
+
+/**
+ * Callback function that provides the image data.
+ * @callback module:camera.onSuccess
+ * @param {string} imageData - Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`]{@link module:camera.CameraOptions} in effect.
+ * @example
+ * // Show image
+ * //
+ * function cameraCallback(imageData) {
+ *    var image = document.getElementById('myImage');
+ *    image.src = "data:image/jpeg;base64," + imageData;
+ * }
+ */
+
+/**
+ * Optional parameters to customize the camera settings.
+ * * [Quirks](#CameraOptions-quirks)
+ * @typedef module:camera.CameraOptions
+ * @type {Object}
+ * @property {number} [quality=50] - Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.)
+ * @property {module:Camera.DestinationType} [destinationType=FILE_URI] - Choose the format of the return value.
+ * @property {module:Camera.PictureSourceType} [sourceType=CAMERA] - Set the source of the picture.
+ * @property {Boolean} [allowEdit=false] - Allow simple editing of image before selection.
+ * @property {module:Camera.EncodingType} [encodingType=JPEG] - Choose the  returned image file's encoding.
+ * @property {number} [targetWidth] - Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant.
+ * @property {number} [targetHeight] - Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant.
+ * @property {module:Camera.MediaType} [mediaType=PICTURE] - Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`.
+ * @property {Boolean} [correctOrientation] - Rotate the image to correct for the orientation of the device during capture.
+ * @property {Boolean} [saveToPhotoAlbum] - Save the image to the photo album on the device after capture.
+ * @property {module:CameraPopoverOptions} [popoverOptions] - iOS-only options that specify popover location in iPad.
+ * @property {module:Camera.Direction} [cameraDirection=BACK] - Choose the camera to use (front- or back-facing).
+ */
+
+/**
+ * @description Takes a photo using the camera, or retrieves a photo from the device's
+ * image gallery.  The image is passed to the success callback as a
+ * Base64-encoded `String`, or as the URI for the image file.
+ *
+ * The `camera.getPicture` function opens the device's default camera
+ * application that allows users to snap pictures by default - this behavior occurs,
+ * when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`]{@link module:Camera.PictureSourceType}.
+ * Once the user snaps the photo, the camera application closes and the application is restored.
+ *
+ * If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
+ * `Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
+ * that allows users to select an existing image.
+ *
+ * The return value is sent to the [`cameraSuccess`]{@link module:camera.onSuccess} callback function, in
+ * one of the following formats, depending on the specified
+ * `cameraOptions`:
+ *
+ * - A `String` containing the Base64-encoded photo image.
+ * - A `String` representing the image file location on local storage (default).
+ *
+ * You can do whatever you want with the encoded image or URI, for
+ * example:
+ *
+ * - Render the image in an `<img>` tag, as in the example below
+ * - Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+ * - Post the data to a remote server
+ *
+ * __NOTE__: Photo resolution on newer devices is quite good. Photos
+ * selected from the device's gallery are not downscaled to a lower
+ * quality, even if a `quality` parameter is specified.  To avoid common
+ * memory problems, set `Camera.destinationType` to `FILE_URI` rather
+ * than `DATA_URL`.
+ *
+ * __Supported Platforms__
+ *
+ * - Android
+ * - BlackBerry
+ * - Browser
+ * - Firefox
+ * - FireOS
+ * - iOS
+ * - Windows
+ * - WP8
+ * - Ubuntu
+ *
+ * More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+ *
+ * @example
+ * navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+ * @param {module:camera.onSuccess} successCallback
+ * @param {module:camera.onError} errorCallback
+ * @param {module:camera.CameraOptions} options CameraOptions
+ */
+cameraExport.getPicture = function (successCallback, errorCallback, options) {
+    argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
+    options = options || {};
+    var getValue = argscheck.getValue;
+
+    var quality = getValue(options.quality, 50);
+    var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
+    var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
+    var targetWidth = getValue(options.targetWidth, -1);
+    var targetHeight = getValue(options.targetHeight, -1);
+    var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
+    var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
+    var allowEdit = !!options.allowEdit;
+    var correctOrientation = !!options.correctOrientation;
+    var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
+    var popoverOptions = getValue(options.popoverOptions, null);
+    var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
+
+    var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
+        mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
+
+    exec(successCallback, errorCallback, 'Camera', 'takePicture', args);
+    // XXX: commented out
+    // return new CameraPopoverHandle();
+};
+
+/**
+ * Removes intermediate image files that are kept in temporary storage
+ * after calling [`camera.getPicture`]{@link module:camera.getPicture}. Applies only when the value of
+ * `Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
+ * `Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.cleanup(onSuccess, onFail);
+ *
+ * function onSuccess() {
+ *     console.log("Camera cleanup success.")
+ * }
+ *
+ * function onFail(message) {
+ *     alert('Failed because: ' + message);
+ * }
+ */
+cameraExport.cleanup = function (successCallback, errorCallback) {
+    exec(successCallback, errorCallback, 'Camera', 'cleanup', []);
+};
+
+module.exports = cameraExport;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
new file mode 100644
index 0000000..4f4b046
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraConstants.js
@@ -0,0 +1,104 @@
+cordova.define("cordova-plugin-camera.Camera", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * @module Camera
+ */
+module.exports = {
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+     * `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+     * disable any image modifications (resize, quality change, cropping, etc.) due
+     * to implementation specific.
+     *
+     * @enum {number}
+     */
+    DestinationType: {
+        /** Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible */
+        DATA_URL: 0,
+        /** Return file uri (content://media/external/images/media/2 for Android) */
+        FILE_URI: 1,
+        /** Return native uri (eg. asset-library://... for iOS) */
+        NATIVE_URI: 2
+    },
+    /**
+     * @enum {number}
+     */
+    EncodingType: {
+        /** Return JPEG encoded image */
+        JPEG: 0,
+        /** Return PNG encoded image */
+        PNG: 1
+    },
+    /**
+     * @enum {number}
+     */
+    MediaType: {
+        /** Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType */
+        PICTURE: 0,
+        /** Allow selection of video only, ONLY RETURNS URL */
+        VIDEO: 1,
+        /** Allow selection from all media types */
+        ALLMEDIA: 2
+    },
+    /**
+     * @description
+     * Defines the output format of `Camera.getPicture` call.
+     * _Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+     * along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+     * change, cropping, etc.) due to implementation specific.
+     *
+     * @enum {number}
+     */
+    PictureSourceType: {
+        /** Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) */
+        PHOTOLIBRARY: 0,
+        /** Take picture from camera */
+        CAMERA: 1,
+        /** Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) */
+        SAVEDPHOTOALBUM: 2
+    },
+    /**
+     * Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+     * @enum {number}
+     */
+    PopoverArrowDirection: {
+        ARROW_UP: 1,
+        ARROW_DOWN: 2,
+        ARROW_LEFT: 4,
+        ARROW_RIGHT: 8,
+        ARROW_ANY: 15
+    },
+    /**
+     * @enum {number}
+     */
+    Direction: {
+        /** Use the back-facing camera */
+        BACK: 0,
+        /** Use the front-facing camera */
+        FRONT: 1
+    }
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
new file mode 100644
index 0000000..81d7d20
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/CameraPopoverOptions.js
@@ -0,0 +1,55 @@
+cordova.define("cordova-plugin-camera.CameraPopoverOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var Camera = require('./Camera');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * iOS-only parameters that specify the anchor element location and arrow
+ * direction of the popover when selecting images from an iPad's library
+ * or album.
+ * Note that the size of the popover may change to adjust to the
+ * direction of the arrow and orientation of the screen.  Make sure to
+ * account for orientation changes when specifying the anchor element
+ * location.
+ * @module CameraPopoverOptions
+ * @param {Number} [x=0] - x pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [y=32] - y pixel coordinate of screen element onto which to anchor the popover.
+ * @param {Number} [width=320] - width, in pixels, of the screen element onto which to anchor the popover.
+ * @param {Number} [height=480] - height, in pixels, of the screen element onto which to anchor the popover.
+ * @param {module:Camera.PopoverArrowDirection} [arrowDir=ARROW_ANY] - Direction the arrow on the popover should point.
+ */
+var CameraPopoverOptions = function (x, y, width, height, arrowDir) {
+    // information of rectangle that popover should be anchored to
+    this.x = x || 0;
+    this.y = y || 32;
+    this.width = width || 320;
+    this.height = height || 480;
+    this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
+};
+
+module.exports = CameraPopoverOptions;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js
new file mode 100644
index 0000000..08a2ab2
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-camera/www/ios/CameraPopoverHandle.js
@@ -0,0 +1,69 @@
+cordova.define("cordova-plugin-camera.CameraPopoverHandle", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+
+/**
+ * @namespace navigator
+ */
+
+/**
+ * A handle to an image picker popover.
+ *
+ * __Supported Platforms__
+ *
+ * - iOS
+ *
+ * @example
+ * navigator.camera.getPicture(onSuccess, onFail,
+ * {
+ *     destinationType: Camera.DestinationType.FILE_URI,
+ *     sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
+ *     popoverOptions: new CameraPopoverOptions(300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)
+ * });
+ *
+ * // Reposition the popover if the orientation changes.
+ * window.onorientationchange = function() {
+ *     var cameraPopoverHandle = new CameraPopoverHandle();
+ *     var cameraPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY);
+ *     cameraPopoverHandle.setPosition(cameraPopoverOptions);
+ * }
+ * @module CameraPopoverHandle
+ */
+var CameraPopoverHandle = function () {
+    /**
+     * Can be used to reposition the image selection dialog,
+     * for example, when the device orientation changes.
+     * @memberof CameraPopoverHandle
+     * @instance
+     * @method setPosition
+     * @param {module:CameraPopoverOptions} popoverOptions
+     */
+    this.setPosition = function (popoverOptions) {
+        var args = [ popoverOptions ];
+        exec(null, null, 'Camera', 'repositionPopover', args);
+    };
+};
+
+module.exports = CameraPopoverHandle;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-device/www/device.js b/platforms/ios/platform_www/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..ae48e35
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,86 @@
+cordova.define("cordova-plugin-device.device", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+    this.available = false;
+    this.platform = null;
+    this.version = null;
+    this.uuid = null;
+    this.cordova = null;
+    this.model = null;
+    this.manufacturer = null;
+    this.isVirtual = null;
+    this.serial = null;
+
+    var me = this;
+
+    channel.onCordovaReady.subscribe(function () {
+        me.getInfo(function (info) {
+            // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+            // TODO: CB-5105 native implementations should not return info.cordova
+            var buildLabel = cordova.version;
+            me.available = true;
+            me.platform = info.platform;
+            me.version = info.version;
+            me.uuid = info.uuid;
+            me.cordova = buildLabel;
+            me.model = info.model;
+            me.isVirtual = info.isVirtual;
+            me.manufacturer = info.manufacturer || 'unknown';
+            me.serial = info.serial || 'unknown';
+            channel.onCordovaInfoReady.fire();
+        }, function (e) {
+            me.available = false;
+            utils.alert('[ERROR] Error initializing Cordova: ' + e);
+        });
+    });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+    argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+    exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
new file mode 100644
index 0000000..bb676eb
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryEntry.js
@@ -0,0 +1,120 @@
+cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileError = require('./FileError');
+var DirectoryReader = require('./DirectoryReader');
+
+/**
+ * An interface representing a directory on the file system.
+ *
+ * {boolean} isFile always false (readonly)
+ * {boolean} isDirectory always true (readonly)
+ * {DOMString} name of the directory, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the directory (readonly)
+ * {FileSystem} filesystem on which the directory resides (readonly)
+ */
+var DirectoryEntry = function (name, fullPath, fileSystem, nativeURL) {
+
+    // add trailing slash if it is missing
+    if ((fullPath) && !/\/$/.test(fullPath)) {
+        fullPath += '/';
+    }
+    // add trailing slash if it is missing
+    if (nativeURL && !/\/$/.test(nativeURL)) {
+        nativeURL += '/';
+    }
+    DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
+};
+
+utils.extend(DirectoryEntry, Entry);
+
+/**
+ * Creates a new DirectoryReader to read entries from this directory
+ */
+DirectoryEntry.prototype.createReader = function () {
+    return new DirectoryReader(this.toInternalURL());
+};
+
+/**
+ * Creates or looks up a directory
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
+ * @param {Flags} options to create or exclusively create the directory
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getDirectory = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getDirectory', [this.toInternalURL(), path, options]);
+};
+
+/**
+ * Deletes a directory and all of it's contents
+ *
+ * @param {Function} successCallback is called with no parameters
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.removeRecursively = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'removeRecursively', [this.toInternalURL()]);
+};
+
+/**
+ * Creates or looks up a file
+ *
+ * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
+ * @param {Flags} options to create or exclusively create the file
+ * @param {Function} successCallback is called with the new entry
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryEntry.prototype.getFile = function (path, options, successCallback, errorCallback) {
+    argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var FileEntry = require('./FileEntry');
+        var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFile', [this.toInternalURL(), path, options]);
+};
+
+module.exports = DirectoryEntry;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
new file mode 100644
index 0000000..417c85f
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/DirectoryReader.js
@@ -0,0 +1,75 @@
+cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+
+/**
+ * An interface that lists the files and directories in a directory.
+ */
+function DirectoryReader (localURL) {
+    this.localURL = localURL || null;
+    this.hasReadEntries = false;
+}
+
+/**
+ * Returns a list of entries from a directory.
+ *
+ * @param {Function} successCallback is called with a list of entries
+ * @param {Function} errorCallback is called with a FileError
+ */
+DirectoryReader.prototype.readEntries = function (successCallback, errorCallback) {
+    // If we've already read and passed on this directory's entries, return an empty list.
+    if (this.hasReadEntries) {
+        successCallback([]);
+        return;
+    }
+    var reader = this;
+    var win = typeof successCallback !== 'function' ? null : function (result) {
+        var retVal = [];
+        for (var i = 0; i < result.length; i++) {
+            var entry = null;
+            if (result[i].isDirectory) {
+                entry = new (require('./DirectoryEntry'))();
+            } else if (result[i].isFile) {
+                entry = new (require('./FileEntry'))();
+            }
+            entry.isDirectory = result[i].isDirectory;
+            entry.isFile = result[i].isFile;
+            entry.name = result[i].name;
+            entry.fullPath = result[i].fullPath;
+            entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
+            entry.nativeURL = result[i].nativeURL;
+            retVal.push(entry);
+        }
+        reader.hasReadEntries = true;
+        successCallback(retVal);
+    };
+    var fail = typeof errorCallback !== 'function' ? null : function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'readEntries', [this.localURL]);
+};
+
+module.exports = DirectoryReader;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Entry.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Entry.js
new file mode 100644
index 0000000..b296d99
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Entry.js
@@ -0,0 +1,263 @@
+cordova.define("cordova-plugin-file.Entry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var argscheck = require('cordova/argscheck');
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var Metadata = require('./Metadata');
+
+/**
+ * Represents a file or directory on the local file system.
+ *
+ * @param isFile
+ *            {boolean} true if Entry is a file (readonly)
+ * @param isDirectory
+ *            {boolean} true if Entry is a directory (readonly)
+ * @param name
+ *            {DOMString} name of the file or directory, excluding the path
+ *            leading to it (readonly)
+ * @param fullPath
+ *            {DOMString} the absolute full path to the file or directory
+ *            (readonly)
+ * @param fileSystem
+ *            {FileSystem} the filesystem on which this entry resides
+ *            (readonly)
+ * @param nativeURL
+ *            {DOMString} an alternate URL which can be used by native
+ *            webview controls, for example media players.
+ *            (optional, readonly)
+ */
+function Entry (isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
+    this.isFile = !!isFile;
+    this.isDirectory = !!isDirectory;
+    this.name = name || '';
+    this.fullPath = fullPath || '';
+    this.filesystem = fileSystem || null;
+    this.nativeURL = nativeURL || null;
+}
+
+/**
+ * Look up the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ */
+Entry.prototype.getMetadata = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
+    var success = successCallback && function (entryMetadata) {
+        var metadata = new Metadata({
+            size: entryMetadata.size,
+            modificationTime: entryMetadata.lastModifiedDate
+        });
+        successCallback(metadata);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(success, fail, 'File', 'getFileMetadata', [this.toInternalURL()]);
+};
+
+/**
+ * Set the metadata of the entry.
+ *
+ * @param successCallback
+ *            {Function} is called with a Metadata object
+ * @param errorCallback
+ *            {Function} is called with a FileError
+ * @param metadataObject
+ *            {Object} keys and values to set
+ */
+Entry.prototype.setMetadata = function (successCallback, errorCallback, metadataObject) {
+    argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
+    exec(successCallback, errorCallback, 'File', 'setMetadata', [this.toInternalURL(), metadataObject]);
+};
+
+/**
+ * Move a file or directory to a new location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to move this entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new DirectoryEntry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.moveTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+    // entry name
+    var name = newName || this.name;
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'moveTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Copy a directory to a different location.
+ *
+ * @param parent
+ *            {DirectoryEntry} the directory to which to copy the entry
+ * @param newName
+ *            {DOMString} new name of the entry, defaults to the current name
+ * @param successCallback
+ *            {Function} called with the new Entry object
+ * @param errorCallback
+ *            {Function} called with a FileError
+ */
+Entry.prototype.copyTo = function (parent, newName, successCallback, errorCallback) {
+    argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    var srcURL = this.toInternalURL();
+        // entry name
+    var name = newName || this.name;
+    // success callback
+    var success = function (entry) {
+        if (entry) {
+            if (successCallback) {
+                // create appropriate Entry object
+                var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
+                var fs = newFSName ? new FileSystem(newFSName, { name: '', fullPath: '/' }) : new FileSystem(parent.filesystem.name, { name: '', fullPath: '/' }); // eslint-disable-line no-undef
+                var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
+                successCallback(result);
+            }
+        } else {
+            // no Entry object returned
+            if (fail) {
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        }
+    };
+
+    // copy
+    exec(success, fail, 'File', 'copyTo', [srcURL, parent.toInternalURL(), name]);
+};
+
+/**
+ * Return a URL that can be passed across the bridge to identify this entry.
+ */
+Entry.prototype.toInternalURL = function () {
+    if (this.filesystem && this.filesystem.__format__) {
+        return this.filesystem.__format__(this.fullPath, this.nativeURL);
+    }
+};
+
+/**
+ * Return a URL that can be used to identify this entry.
+ * Use a URL that can be used to as the src attribute of a <video> or
+ * <audio> tag. If that is not possible, construct a cdvfile:// URL.
+ */
+Entry.prototype.toURL = function () {
+    if (this.nativeURL) {
+        return this.nativeURL;
+    }
+    // fullPath attribute may contain the full URL in the case that
+    // toInternalURL fails.
+    return this.toInternalURL() || 'file://localhost' + this.fullPath;
+};
+
+/**
+ * Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
+ * cdvfile:// URL, and this method was necessary to obtain URLs usable by the
+ * webview.
+ * See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
+ * and CB-6300.
+ */
+Entry.prototype.toNativeURL = function () {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Returns a URI that can be used to identify this entry.
+ *
+ * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
+ * @return uri
+ */
+Entry.prototype.toURI = function (mimeType) {
+    console.log("DEPRECATED: Update your code to use 'toURL'");
+    return this.toURL();
+};
+
+/**
+ * Remove a file or directory. It is an error to attempt to delete a
+ * directory that is not empty. It is an error to attempt to delete a
+ * root directory of a file system.
+ *
+ * @param successCallback {Function} called with no parameters
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.remove = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.remove', arguments);
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(successCallback, fail, 'File', 'remove', [this.toInternalURL()]);
+};
+
+/**
+ * Look up the parent DirectoryEntry of this entry.
+ *
+ * @param successCallback {Function} called with the parent DirectoryEntry object
+ * @param errorCallback {Function} called with a FileError
+ */
+Entry.prototype.getParent = function (successCallback, errorCallback) {
+    argscheck.checkArgs('FF', 'Entry.getParent', arguments);
+    var fs = this.filesystem;
+    var win = successCallback && function (result) {
+        var DirectoryEntry = require('./DirectoryEntry');
+        var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
+        successCallback(entry);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getParent', [this.toInternalURL()]);
+};
+
+module.exports = Entry;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/File.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/File.js
new file mode 100644
index 0000000..c771786
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/File.js
@@ -0,0 +1,81 @@
+cordova.define("cordova-plugin-file.File", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Constructor.
+ * name {DOMString} name of the file, without path information
+ * fullPath {DOMString} the full path of the file, including the name
+ * type {DOMString} mime type
+ * lastModifiedDate {Date} last modified date
+ * size {Number} size of the file in bytes
+ */
+
+var File = function (name, localURL, type, lastModifiedDate, size) {
+    this.name = name || '';
+    this.localURL = localURL || null;
+    this.type = type || null;
+    this.lastModified = lastModifiedDate || null;
+    // For backwards compatibility, store the timestamp in lastModifiedDate as well
+    this.lastModifiedDate = lastModifiedDate || null;
+    this.size = size || 0;
+
+    // These store the absolute start and end for slicing the file.
+    this.start = 0;
+    this.end = this.size;
+};
+
+/**
+ * Returns a "slice" of the file. Since Cordova Files don't contain the actual
+ * content, this really returns a File with adjusted start and end.
+ * Slices of slices are supported.
+ * start {Number} The index at which to start the slice (inclusive).
+ * end {Number} The index at which to end the slice (exclusive).
+ */
+File.prototype.slice = function (start, end) {
+    var size = this.end - this.start;
+    var newStart = 0;
+    var newEnd = size;
+    if (arguments.length) {
+        if (start < 0) {
+            newStart = Math.max(size + start, 0);
+        } else {
+            newStart = Math.min(size, start);
+        }
+    }
+
+    if (arguments.length >= 2) {
+        if (end < 0) {
+            newEnd = Math.max(size + end, 0);
+        } else {
+            newEnd = Math.min(end, size);
+        }
+    }
+
+    var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
+    newFile.start = this.start + newStart;
+    newFile.end = this.start + newEnd;
+    return newFile;
+};
+
+module.exports = File;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileEntry.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
new file mode 100644
index 0000000..6651b55
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileEntry.js
@@ -0,0 +1,95 @@
+cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var utils = require('cordova/utils');
+var exec = require('cordova/exec');
+var Entry = require('./Entry');
+var FileWriter = require('./FileWriter');
+var File = require('./File');
+var FileError = require('./FileError');
+
+/**
+ * An interface representing a file on the file system.
+ *
+ * {boolean} isFile always true (readonly)
+ * {boolean} isDirectory always false (readonly)
+ * {DOMString} name of the file, excluding the path leading to it (readonly)
+ * {DOMString} fullPath the absolute full path to the file (readonly)
+ * {FileSystem} filesystem on which the file resides (readonly)
+ */
+var FileEntry = function (name, fullPath, fileSystem, nativeURL) {
+    // remove trailing slash if it is present
+    if (fullPath && /\/$/.test(fullPath)) {
+        fullPath = fullPath.substring(0, fullPath.length - 1);
+    }
+    if (nativeURL && /\/$/.test(nativeURL)) {
+        nativeURL = nativeURL.substring(0, nativeURL.length - 1);
+    }
+
+    FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
+};
+
+utils.extend(FileEntry, Entry);
+
+/**
+ * Creates a new FileWriter associated with the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new FileWriter
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.createWriter = function (successCallback, errorCallback) {
+    this.file(function (filePointer) {
+        var writer = new FileWriter(filePointer);
+
+        if (writer.localURL === null || writer.localURL === '') {
+            if (errorCallback) {
+                errorCallback(new FileError(FileError.INVALID_STATE_ERR));
+            }
+        } else {
+            if (successCallback) {
+                successCallback(writer);
+            }
+        }
+    }, errorCallback);
+};
+
+/**
+ * Returns a File that represents the current state of the file that this FileEntry represents.
+ *
+ * @param {Function} successCallback is called with the new File object
+ * @param {Function} errorCallback is called with a FileError
+ */
+FileEntry.prototype.file = function (successCallback, errorCallback) {
+    var localURL = this.toInternalURL();
+    var win = successCallback && function (f) {
+        var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
+        successCallback(file);
+    };
+    var fail = errorCallback && function (code) {
+        errorCallback(new FileError(code));
+    };
+    exec(win, fail, 'File', 'getFileMetadata', [localURL]);
+};
+
+module.exports = FileEntry;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileError.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileError.js
new file mode 100644
index 0000000..f378c38
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileError.js
@@ -0,0 +1,49 @@
+cordova.define("cordova-plugin-file.FileError", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileError
+ */
+function FileError (error) {
+    this.code = error || null;
+}
+
+// File error codes
+// Found in DOMException
+FileError.NOT_FOUND_ERR = 1;
+FileError.SECURITY_ERR = 2;
+FileError.ABORT_ERR = 3;
+
+// Added by File API specification
+FileError.NOT_READABLE_ERR = 4;
+FileError.ENCODING_ERR = 5;
+FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
+FileError.INVALID_STATE_ERR = 7;
+FileError.SYNTAX_ERR = 8;
+FileError.INVALID_MODIFICATION_ERR = 9;
+FileError.QUOTA_EXCEEDED_ERR = 10;
+FileError.TYPE_MISMATCH_ERR = 11;
+FileError.PATH_EXISTS_ERR = 12;
+
+module.exports = FileError;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileReader.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileReader.js
new file mode 100644
index 0000000..5c03091
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileReader.js
@@ -0,0 +1,301 @@
+cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var modulemapper = require('cordova/modulemapper');
+var utils = require('cordova/utils');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+var origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
+
+/**
+ * This class reads the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To read from the SD card, the file name is "sdcard/my_file.txt"
+ * @constructor
+ */
+var FileReader = function () {
+    this._readyState = 0;
+    this._error = null;
+    this._result = null;
+    this._progress = null;
+    this._localURL = '';
+    this._realReader = origFileReader ? new origFileReader() : {}; // eslint-disable-line new-cap
+};
+
+/**
+ * Defines the maximum size to read at a time via the native API. The default value is a compromise between
+ * minimizing the overhead of many exec() calls while still reporting progress frequently enough for large files.
+ * (Note attempts to allocate more than a few MB of contiguous memory on the native side are likely to cause
+ * OOM exceptions, while the JS engine seems to have fewer problems managing large strings or ArrayBuffers.)
+ */
+FileReader.READ_CHUNK_SIZE = 256 * 1024;
+
+// States
+FileReader.EMPTY = 0;
+FileReader.LOADING = 1;
+FileReader.DONE = 2;
+
+utils.defineGetter(FileReader.prototype, 'readyState', function () {
+    return this._localURL ? this._readyState : this._realReader.readyState;
+});
+
+utils.defineGetter(FileReader.prototype, 'error', function () {
+    return this._localURL ? this._error : this._realReader.error;
+});
+
+utils.defineGetter(FileReader.prototype, 'result', function () {
+    return this._localURL ? this._result : this._realReader.result;
+});
+
+function defineEvent (eventName) {
+    utils.defineGetterSetter(FileReader.prototype, eventName, function () {
+        return this._realReader[eventName] || null;
+    }, function (value) {
+        this._realReader[eventName] = value;
+    });
+}
+defineEvent('onloadstart');    // When the read starts.
+defineEvent('onprogress');     // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
+defineEvent('onload');         // When the read has successfully completed.
+defineEvent('onerror');        // When the read has failed (see errors).
+defineEvent('onloadend');      // When the request has completed (either in success or failure).
+defineEvent('onabort');        // When the read has been aborted. For instance, by invoking the abort() method.
+
+function initRead (reader, file) {
+    // Already loading something
+    if (reader.readyState === FileReader.LOADING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    reader._result = null;
+    reader._error = null;
+    reader._progress = 0;
+    reader._readyState = FileReader.LOADING;
+
+    if (typeof file.localURL === 'string') {
+        reader._localURL = file.localURL;
+    } else {
+        reader._localURL = '';
+        return true;
+    }
+
+    if (reader.onloadstart) {
+        reader.onloadstart(new ProgressEvent('loadstart', {target: reader}));
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle incremental or final success.
+ * Must be bound to the FileReader's this along with all but the last parameter,
+ * e.g. readSuccessCallback.bind(this, "readAsText", "UTF-8", offset, totalSize, accumulate)
+ * @param readType The name of the read function to call.
+ * @param encoding Text encoding, or null if this is not a text type read.
+ * @param offset Starting offset of the read.
+ * @param totalSize Total number of bytes or chars to read.
+ * @param accumulate A function that takes the callback result and accumulates it in this._result.
+ * @param r Callback result returned by the last read exec() call, or null to begin reading.
+ */
+function readSuccessCallback (readType, encoding, offset, totalSize, accumulate, r) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    var CHUNK_SIZE = FileReader.READ_CHUNK_SIZE;
+    if (readType === 'readAsDataURL') {
+        // Windows proxy does not support reading file slices as Data URLs
+        // so read the whole file at once.
+        CHUNK_SIZE = cordova.platformId === 'windows' ? totalSize : // eslint-disable-line no-undef
+            // Calculate new chunk size for data URLs to be multiply of 3
+            // Otherwise concatenated base64 chunks won't be valid base64 data
+            FileReader.READ_CHUNK_SIZE - (FileReader.READ_CHUNK_SIZE % 3) + 3;
+    }
+
+    if (typeof r !== 'undefined') {
+        accumulate(r);
+        this._progress = Math.min(this._progress + CHUNK_SIZE, totalSize);
+
+        if (typeof this.onprogress === 'function') {
+            this.onprogress(new ProgressEvent('progress', {loaded: this._progress, total: totalSize}));
+        }
+    }
+
+    if (typeof r === 'undefined' || this._progress < totalSize) {
+        var execArgs = [
+            this._localURL,
+            offset + this._progress,
+            offset + this._progress + Math.min(totalSize - this._progress, CHUNK_SIZE)];
+        if (encoding) {
+            execArgs.splice(1, 0, encoding);
+        }
+        exec(
+            readSuccessCallback.bind(this, readType, encoding, offset, totalSize, accumulate),
+            readFailureCallback.bind(this),
+            'File', readType, execArgs);
+    } else {
+        this._readyState = FileReader.DONE;
+
+        if (typeof this.onload === 'function') {
+            this.onload(new ProgressEvent('load', {target: this}));
+        }
+
+        if (typeof this.onloadend === 'function') {
+            this.onloadend(new ProgressEvent('loadend', {target: this}));
+        }
+    }
+}
+
+/**
+ * Callback used by the following read* functions to handle errors.
+ * Must be bound to the FileReader's this, e.g. readFailureCallback.bind(this)
+ */
+function readFailureCallback (e) {
+    if (this._readyState === FileReader.DONE) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+    this._result = null;
+    this._error = new FileError(e);
+
+    if (typeof this.onerror === 'function') {
+        this.onerror(new ProgressEvent('error', {target: this}));
+    }
+
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+}
+
+/**
+ * Abort reading file.
+ */
+FileReader.prototype.abort = function () {
+    if (origFileReader && !this._localURL) {
+        return this._realReader.abort();
+    }
+    this._result = null;
+
+    if (this._readyState === FileReader.DONE || this._readyState === FileReader.EMPTY) {
+        return;
+    }
+
+    this._readyState = FileReader.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {target: this}));
+    }
+    // If load end callback
+    if (typeof this.onloadend === 'function') {
+        this.onloadend(new ProgressEvent('loadend', {target: this}));
+    }
+};
+
+/**
+ * Read text file.
+ *
+ * @param file          {File} File object containing file properties
+ * @param encoding      [Optional] (see http://www.iana.org/assignments/character-sets)
+ */
+FileReader.prototype.readAsText = function (file, encoding) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsText(file, encoding);
+    }
+
+    // Default encoding is UTF-8
+    var enc = encoding || 'UTF-8';
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsText', enc, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a base64 encoded data url.
+ * A data url is of the form:
+ *      data:[<mediatype>][;base64],<data>
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsDataURL = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsDataURL(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsDataURL', null, file.start, totalSize, function (r) {
+        var commaIndex = r.indexOf(',');
+        if (this._progress === 0) {
+            this._result = r;
+        } else {
+            this._result += r.substring(commaIndex + 1);
+        }
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsBinaryString = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsBinaryString(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsBinaryString', null, file.start, totalSize, function (r) {
+        if (this._progress === 0) {
+            this._result = '';
+        }
+        this._result += r;
+    }.bind(this));
+};
+
+/**
+ * Read file and return data as a binary data.
+ *
+ * @param file          {File} File object containing file properties
+ */
+FileReader.prototype.readAsArrayBuffer = function (file) {
+    if (initRead(this, file)) {
+        return this._realReader.readAsArrayBuffer(file);
+    }
+
+    var totalSize = file.end - file.start;
+    readSuccessCallback.bind(this)('readAsArrayBuffer', null, file.start, totalSize, function (r) {
+        var resultArray = (this._progress === 0 ? new Uint8Array(totalSize) : new Uint8Array(this._result));
+        resultArray.set(new Uint8Array(r), this._progress);
+        this._result = resultArray.buffer;
+    }.bind(this));
+};
+
+module.exports = FileReader;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileSystem.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
new file mode 100644
index 0000000..ad9ea78
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileSystem.js
@@ -0,0 +1,58 @@
+cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var DirectoryEntry = require('./DirectoryEntry');
+
+/**
+ * An interface representing a file system
+ *
+ * @constructor
+ * {DOMString} name the unique name of the file system (readonly)
+ * {DirectoryEntry} root directory of the file system (readonly)
+ */
+var FileSystem = function (name, root) {
+    this.name = name;
+    if (root) {
+        this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
+    } else {
+        this.root = new DirectoryEntry(this.name, '/', this);
+    }
+};
+
+FileSystem.prototype.__format__ = function (fullPath, nativeUrl) {
+    return fullPath;
+};
+
+FileSystem.prototype.toJSON = function () {
+    return '<FileSystem: ' + this.name + '>';
+};
+
+// Use instead of encodeURI() when encoding just the path part of a URI rather than an entire URI.
+FileSystem.encodeURIPath = function (path) {
+    // Because # is a valid filename character, it must be encoded to prevent part of the
+    // path from being parsed as a URI fragment.
+    return encodeURI(path).replace(/#/g, '%23');
+};
+
+module.exports = FileSystem;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
new file mode 100644
index 0000000..6acd093
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadOptions.js
@@ -0,0 +1,44 @@
+cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Options to customize the HTTP request used to upload files.
+ * @constructor
+ * @param fileKey {String}   Name of file request parameter.
+ * @param fileName {String}  Filename to be used by the server. Defaults to image.jpg.
+ * @param mimeType {String}  Mimetype of the uploaded file. Defaults to image/jpeg.
+ * @param params {Object}    Object with key: value params to send to the server.
+ * @param headers {Object}   Keys are header names, values are header values. Multiple
+ *                           headers of the same name are not supported.
+ */
+var FileUploadOptions = function (fileKey, fileName, mimeType, params, headers, httpMethod) {
+    this.fileKey = fileKey || null;
+    this.fileName = fileName || null;
+    this.mimeType = mimeType || null;
+    this.params = params || null;
+    this.headers = headers || null;
+    this.httpMethod = httpMethod || null;
+};
+
+module.exports = FileUploadOptions;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
new file mode 100644
index 0000000..e3c3a74
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileUploadResult.js
@@ -0,0 +1,33 @@
+cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * FileUploadResult
+ * @constructor
+ */
+module.exports = function FileUploadResult (size, code, content) {
+    this.bytesSent = size;
+    this.responseCode = code;
+    this.response = content;
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileWriter.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
new file mode 100644
index 0000000..d48a089
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/FileWriter.js
@@ -0,0 +1,327 @@
+cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var FileError = require('./FileError');
+var ProgressEvent = require('./ProgressEvent');
+
+/**
+ * This class writes to the mobile device file system.
+ *
+ * For Android:
+ *      The root directory is the root of the file system.
+ *      To write to the SD card, the file name is "sdcard/my_file.txt"
+ *
+ * @constructor
+ * @param file {File} File object containing file properties
+ * @param append if true write to the end of the file, otherwise overwrite the file
+ */
+var FileWriter = function (file) {
+    this.fileName = '';
+    this.length = 0;
+    if (file) {
+        this.localURL = file.localURL || file;
+        this.length = file.size || 0;
+    }
+    // default is to write at the beginning of the file
+    this.position = 0;
+
+    this.readyState = 0; // EMPTY
+
+    this.result = null;
+
+    // Error
+    this.error = null;
+
+    // Event handlers
+    this.onwritestart = null;   // When writing starts
+    this.onprogress = null;     // While writing the file, and reporting partial file data
+    this.onwrite = null;        // When the write has successfully completed.
+    this.onwriteend = null;     // When the request has completed (either in success or failure).
+    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
+    this.onerror = null;        // When the write has failed (see errors).
+};
+
+// States
+FileWriter.INIT = 0;
+FileWriter.WRITING = 1;
+FileWriter.DONE = 2;
+
+/**
+ * Abort writing file.
+ */
+FileWriter.prototype.abort = function () {
+    // check for invalid state
+    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // set error
+    this.error = new FileError(FileError.ABORT_ERR);
+
+    this.readyState = FileWriter.DONE;
+
+    // If abort callback
+    if (typeof this.onabort === 'function') {
+        this.onabort(new ProgressEvent('abort', {'target': this}));
+    }
+
+    // If write end callback
+    if (typeof this.onwriteend === 'function') {
+        this.onwriteend(new ProgressEvent('writeend', {'target': this}));
+    }
+};
+
+/**
+ * Writes data to the file
+ *
+ * @param data text or blob to be written
+ * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
+ */
+FileWriter.prototype.write = function (data, isPendingBlobReadResult) {
+
+    var that = this;
+    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
+    /* eslint-disable no-undef */
+    var isProxySupportBlobNatively = (cordova.platformId === 'windows8' || cordova.platformId === 'windows');
+    var isBinary;
+
+    // Check to see if the incoming data is a blob
+    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
+        var fileReader = new FileReader();
+        /* eslint-enable no-undef */
+        fileReader.onload = function () {
+            // Call this method again, with the arraybuffer as argument
+            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
+        };
+        fileReader.onerror = function () {
+            // DONE state
+            that.readyState = FileWriter.DONE;
+
+            // Save error
+            that.error = this.error;
+
+            // If onerror callback
+            if (typeof that.onerror === 'function') {
+                that.onerror(new ProgressEvent('error', {'target': that}));
+            }
+
+            // If onwriteend callback
+            if (typeof that.onwriteend === 'function') {
+                that.onwriteend(new ProgressEvent('writeend', {'target': that}));
+            }
+        };
+
+        // WRITING state
+        this.readyState = FileWriter.WRITING;
+
+        if (supportsBinary) {
+            fileReader.readAsArrayBuffer(data);
+        } else {
+            fileReader.readAsText(data);
+        }
+        return;
+    }
+
+    // Mark data type for safer transport over the binary bridge
+    isBinary = supportsBinary && (data instanceof ArrayBuffer);
+    if (isBinary && cordova.platformId === 'windowsphone') { // eslint-disable-line no-undef
+        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
+        data = Array.apply(null, new Uint8Array(data));
+    }
+
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': me}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // position always increases by bytes written because file would be extended
+            me.position += r;
+            // The length of the file is now where we are done writing.
+
+            me.length = me.position;
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'write', [this.localURL, data, this.position, isBinary]);
+};
+
+/**
+ * Moves the file pointer to the location specified.
+ *
+ * If the offset is a negative number the position of the file
+ * pointer is rewound.  If the offset is greater than the file
+ * size the position is set to the end of the file.
+ *
+ * @param offset is the location to move the file pointer to.
+ */
+FileWriter.prototype.seek = function (offset) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    if (!offset && offset !== 0) {
+        return;
+    }
+
+    // See back from end of file.
+    if (offset < 0) {
+        this.position = Math.max(offset + this.length, 0);
+    // Offset is bigger than file size so set position
+    // to the end of the file.
+    } else if (offset > this.length) {
+        this.position = this.length;
+    // Offset is between 0 and file size so set the position
+    // to start writing.
+    } else {
+        this.position = offset;
+    }
+};
+
+/**
+ * Truncates the file to the size specified.
+ *
+ * @param size to chop the file at.
+ */
+FileWriter.prototype.truncate = function (size) {
+    // Throw an exception if we are already writing a file
+    if (this.readyState === FileWriter.WRITING) {
+        throw new FileError(FileError.INVALID_STATE_ERR);
+    }
+
+    // WRITING state
+    this.readyState = FileWriter.WRITING;
+
+    var me = this;
+
+    // If onwritestart callback
+    if (typeof me.onwritestart === 'function') {
+        me.onwritestart(new ProgressEvent('writestart', {'target': this}));
+    }
+
+    // Write file
+    exec(
+        // Success callback
+        function (r) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Update the length of the file
+            me.length = r;
+            me.position = Math.min(me.position, r);
+
+            // If onwrite callback
+            if (typeof me.onwrite === 'function') {
+                me.onwrite(new ProgressEvent('write', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        },
+        // Error callback
+        function (e) {
+            // If DONE (cancelled), then don't do anything
+            if (me.readyState === FileWriter.DONE) {
+                return;
+            }
+
+            // DONE state
+            me.readyState = FileWriter.DONE;
+
+            // Save error
+            me.error = new FileError(e);
+
+            // If onerror callback
+            if (typeof me.onerror === 'function') {
+                me.onerror(new ProgressEvent('error', {'target': me}));
+            }
+
+            // If onwriteend callback
+            if (typeof me.onwriteend === 'function') {
+                me.onwriteend(new ProgressEvent('writeend', {'target': me}));
+            }
+        }, 'File', 'truncate', [this.localURL, size]);
+};
+
+module.exports = FileWriter;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Flags.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Flags.js
new file mode 100644
index 0000000..cdb12bb
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Flags.js
@@ -0,0 +1,39 @@
+cordova.define("cordova-plugin-file.Flags", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Supplies arguments to methods that lookup or create files and directories.
+ *
+ * @param create
+ *            {boolean} file or directory if it doesn't exist
+ * @param exclusive
+ *            {boolean} used with create; if true the command will fail if
+ *            target path exists
+ */
+function Flags (create, exclusive) {
+    this.create = create || false;
+    this.exclusive = exclusive || false;
+}
+
+module.exports = Flags;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
new file mode 100644
index 0000000..4ce6848
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/LocalFileSystem.js
@@ -0,0 +1,26 @@
+cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+exports.TEMPORARY = 0;
+exports.PERSISTENT = 1;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Metadata.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Metadata.js
new file mode 100644
index 0000000..22366e1
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/Metadata.js
@@ -0,0 +1,43 @@
+cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/**
+ * Information about the state of the file or directory
+ *
+ * {Date} modificationTime (readonly)
+ */
+var Metadata = function (metadata) {
+    if (typeof metadata === 'object') {
+        this.modificationTime = new Date(metadata.modificationTime);
+        this.size = metadata.size || 0;
+    } else if (typeof metadata === 'undefined') {
+        this.modificationTime = null;
+        this.size = 0;
+    } else {
+        /* Backwards compatiblity with platforms that only return a timestamp */
+        this.modificationTime = new Date(metadata);
+    }
+};
+
+module.exports = Metadata;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
new file mode 100644
index 0000000..cbecdb1
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ProgressEvent.js
@@ -0,0 +1,70 @@
+cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
+// Feature test: See if we can instantiate a native ProgressEvent;
+// if so, use that approach,
+// otherwise fill-in with our own implementation.
+//
+// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
+var ProgressEvent = (function () {
+    /*
+    var createEvent = function(data) {
+        var event = document.createEvent('Events');
+        event.initEvent('ProgressEvent', false, false);
+        if (data) {
+            for (var i in data) {
+                if (data.hasOwnProperty(i)) {
+                    event[i] = data[i];
+                }
+            }
+            if (data.target) {
+                // TODO: cannot call <some_custom_object>.dispatchEvent
+                // need to first figure out how to implement EventTarget
+            }
+        }
+        return event;
+    };
+    try {
+        var ev = createEvent({type:"abort",target:document});
+        return function ProgressEvent(type, data) {
+            data.type = type;
+            return createEvent(data);
+        };
+    } catch(e){
+    */
+    return function ProgressEvent (type, dict) {
+        this.type = type;
+        this.bubbles = false;
+        this.cancelBubble = false;
+        this.cancelable = false;
+        this.lengthComputable = false;
+        this.loaded = dict && dict.loaded ? dict.loaded : 0;
+        this.total = dict && dict.total ? dict.total : 0;
+        this.target = dict && dict.target ? dict.target : null;
+    };
+    // }
+})();
+
+module.exports = ProgressEvent;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
new file mode 100644
index 0000000..c74fd9c
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/browser/isChrome.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-file.isChrome", function(require, exports, module) {
+/*

+ *

+ * 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.

+ *

+ */

+

+module.exports = function () {

+    // window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL are available only in Chrome and

+    // possibly a good flag to indicate that we're running in Chrome

+    return window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;

+};

+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
new file mode 100644
index 0000000..4bfc0f6
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystemPaths.js
@@ -0,0 +1,65 @@
+cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+
+exports.file = {
+    // Read-only directory where the application is installed.
+    applicationDirectory: null,
+    // Root of app's private writable storage
+    applicationStorageDirectory: null,
+    // Where to put app-specific data files.
+    dataDirectory: null,
+    // Cached files that should survive app restarts.
+    // Apps should not rely on the OS to delete files in here.
+    cacheDirectory: null,
+    // Android: the application space on external storage.
+    externalApplicationStorageDirectory: null,
+    // Android: Where to put app-specific data files on external storage.
+    externalDataDirectory: null,
+    // Android: the application cache on external storage.
+    externalCacheDirectory: null,
+    // Android: the external storage (SD card) root.
+    externalRootDirectory: null,
+    // iOS: Temp directory that the OS can clear at will.
+    tempDirectory: null,
+    // iOS: Holds app-specific files that should be synced (e.g. to iCloud).
+    syncedDataDirectory: null,
+    // iOS: Files private to the app, but that are meaningful to other applications (e.g. Office files)
+    documentsDirectory: null,
+    // BlackBerry10: Files globally available to all apps
+    sharedDirectory: null
+};
+
+channel.waitForInitialization('onFileSystemPathsReady');
+channel.onCordovaReady.subscribe(function () {
+    function after (paths) {
+        for (var k in paths) {
+            exports.file[k] = paths[k];
+        }
+        channel.initializationComplete('onFileSystemPathsReady');
+    }
+    exec(after, null, 'File', 'requestAllPaths', []);
+});
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
new file mode 100644
index 0000000..9351132
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems-roots.js
@@ -0,0 +1,47 @@
+cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Map of fsName -> FileSystem.
+var fsMap = null;
+var FileSystem = require('./FileSystem');
+var exec = require('cordova/exec');
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+require('./fileSystems').getFs = function (name, callback) {
+    function success (response) {
+        fsMap = {};
+        for (var i = 0; i < response.length; ++i) {
+            var fsRoot = response[i];
+            var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
+            fsMap[fs.name] = fs;
+        }
+        callback(fsMap[name]);
+    }
+
+    if (fsMap) {
+        callback(fsMap[name]);
+    } else {
+        exec(success, null, 'File', 'requestAllFileSystems', []);
+    }
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
new file mode 100644
index 0000000..e61ceaf
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/fileSystems.js
@@ -0,0 +1,28 @@
+cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
+module.exports.getFs = function (name, callback) {
+    callback(null);
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ios/FileSystem.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ios/FileSystem.js
new file mode 100644
index 0000000..551b515
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/ios/FileSystem.js
@@ -0,0 +1,32 @@
+cordova.define("cordova-plugin-file.iosFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+/* eslint no-undef : 0 */
+FILESYSTEM_PROTOCOL = 'cdvfile';
+
+module.exports = {
+    __format__: function (fullPath) {
+        var path = ('/' + this.name + (fullPath[0] === '/' ? '' : '/') + FileSystem.encodeURIPath(fullPath)).replace('//', '/');
+        return FILESYSTEM_PROTOCOL + '://localhost' + path;
+    }
+};
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
new file mode 100644
index 0000000..7f65219
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/requestFileSystem.js
@@ -0,0 +1,84 @@
+cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // For browser platform: not all browsers use this file.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports = window.requestFileSystem || window.webkitRequestFileSystem;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var FileError = require('./FileError');
+    var FileSystem = require('./FileSystem');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Request a file system in which to store application data.
+     * @param type  local file system type
+     * @param size  indicates how much storage space, in bytes, the application expects to need
+     * @param successCallback  invoked with a FileSystem object
+     * @param errorCallback  invoked if error occurs retrieving file system
+     */
+    var requestFileSystem = function (type, size, successCallback, errorCallback) {
+        argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
+        var fail = function (code) {
+            if (errorCallback) {
+                errorCallback(new FileError(code));
+            }
+        };
+
+        if (type < 0) {
+            fail(FileError.SYNTAX_ERR);
+        } else {
+            // if successful, return a FileSystem object
+            var success = function (file_system) {
+                if (file_system) {
+                    if (successCallback) {
+                        fileSystems.getFs(file_system.name, function (fs) {
+                            // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                            if (!fs) {
+                                fs = new FileSystem(file_system.name, file_system.root);
+                            }
+                            successCallback(fs);
+                        });
+                    }
+                } else {
+                    // no FileSystem object returned
+                    fail(FileError.NOT_FOUND_ERR);
+                }
+            };
+            exec(success, fail, 'File', 'requestFileSystem', [type, size]);
+        }
+    };
+
+    module.exports = requestFileSystem;
+})();
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
new file mode 100644
index 0000000..73715bc
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js
@@ -0,0 +1,94 @@
+cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+(function () {
+    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
+    function checkBrowser () {
+        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
+            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
+            return true;
+        }
+        return false;
+    }
+    if (checkBrowser()) {
+        return;
+    }
+
+    var argscheck = require('cordova/argscheck');
+    var DirectoryEntry = require('./DirectoryEntry');
+    var FileEntry = require('./FileEntry');
+    var FileError = require('./FileError');
+    var exec = require('cordova/exec');
+    var fileSystems = require('./fileSystems');
+
+    /**
+     * Look up file system Entry referred to by local URI.
+     * @param {DOMString} uri  URI referring to a local file or directory
+     * @param successCallback  invoked with Entry object corresponding to URI
+     * @param errorCallback    invoked if error occurs retrieving file system entry
+     */
+    module.exports.resolveLocalFileSystemURL = module.exports.resolveLocalFileSystemURL || function (uri, successCallback, errorCallback) {
+        argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
+        // error callback
+        var fail = function (error) {
+            if (errorCallback) {
+                errorCallback(new FileError(error));
+            }
+        };
+        // sanity check for 'not:valid:filename' or '/not:valid:filename'
+        // file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
+        if (!uri || uri.split(':').length > 2) {
+            setTimeout(function () {
+                fail(FileError.ENCODING_ERR);
+            }, 0);
+            return;
+        }
+        // if successful, return either a file or directory entry
+        var success = function (entry) {
+            if (entry) {
+                if (successCallback) {
+                    // create appropriate Entry object
+                    var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem === window.PERSISTENT ? 'persistent' : 'temporary'); // eslint-disable-line no-undef
+                    fileSystems.getFs(fsName, function (fs) {
+                        // This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
+                        if (!fs) {
+                            fs = new FileSystem(fsName, {name: '', fullPath: '/'}); // eslint-disable-line no-undef
+                        }
+                        var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
+                        successCallback(result);
+                    });
+                }
+            } else {
+                // no Entry object returned
+                fail(FileError.NOT_FOUND_ERR);
+            }
+        };
+
+        exec(success, fail, 'File', 'resolveLocalFileSystemURI', [uri]);
+    };
+
+    module.exports.resolveLocalFileSystemURI = function () {
+        console.log('resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.');
+        module.exports.resolveLocalFileSystemURL.apply(this, arguments);
+    };
+})();
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js b/platforms/ios/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
new file mode 100644
index 0000000..3982139
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-fingerprint-aio/www/Fingerprint.js
@@ -0,0 +1,29 @@
+cordova.define("cordova-plugin-fingerprint-aio.Fingerprint", function(require, exports, module) {
+/*global cordova */
+
+function Fingerprint() {
+}
+
+Fingerprint.prototype.show = function (params, successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "authenticate",
+    [params]
+  );
+};
+
+Fingerprint.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(
+    successCallback,
+    errorCallback,
+    "Fingerprint",
+    "isAvailable",
+    [{}]
+  );
+};
+
+module.exports = new Fingerprint();
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js b/platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
new file mode 100644
index 0000000..a3021c2
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js
@@ -0,0 +1,118 @@
+cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+(function () {
+    // special patch to correctly work on Ripple emulator (CB-9760)
+    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
+        module.exports = window.open.bind(window); // fallback to default window.open behaviour
+        return;
+    }
+
+    var exec = require('cordova/exec');
+    var channel = require('cordova/channel');
+    var modulemapper = require('cordova/modulemapper');
+    var urlutil = require('cordova/urlutil');
+
+    function InAppBrowser () {
+        this.channels = {
+            'loadstart': channel.create('loadstart'),
+            'loadstop': channel.create('loadstop'),
+            'loaderror': channel.create('loaderror'),
+            'exit': channel.create('exit'),
+            'customscheme': channel.create('customscheme')
+        };
+    }
+
+    InAppBrowser.prototype = {
+        _eventHandler: function (event) {
+            if (event && (event.type in this.channels)) {
+                this.channels[event.type].fire(event);
+            }
+        },
+        close: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'close', []);
+        },
+        show: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'show', []);
+        },
+        hide: function (eventname) {
+            exec(null, null, 'InAppBrowser', 'hide', []);
+        },
+        addEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].subscribe(f);
+            }
+        },
+        removeEventListener: function (eventname, f) {
+            if (eventname in this.channels) {
+                this.channels[eventname].unsubscribe(f);
+            }
+        },
+
+        executeScript: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('executeScript requires exactly one of code or file to be specified');
+            }
+        },
+
+        insertCSS: function (injectDetails, cb) {
+            if (injectDetails.code) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+            } else if (injectDetails.file) {
+                exec(cb, null, 'InAppBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+            } else {
+                throw new Error('insertCSS requires exactly one of code or file to be specified');
+            }
+        }
+    };
+
+    module.exports = function (strUrl, strWindowName, strWindowFeatures, callbacks) {
+        // Don't catch calls that write to existing frames (e.g. named iframes).
+        if (window.frames && window.frames[strWindowName]) {
+            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+            return origOpenFunc.apply(window, arguments);
+        }
+
+        strUrl = urlutil.makeAbsolute(strUrl);
+        var iab = new InAppBrowser();
+
+        callbacks = callbacks || {};
+        for (var callbackName in callbacks) {
+            iab.addEventListener(callbackName, callbacks[callbackName]);
+        }
+
+        var cb = function (eventname) {
+            iab._eventHandler(eventname);
+        };
+
+        strWindowFeatures = strWindowFeatures || '';
+
+        exec(cb, cb, 'InAppBrowser', 'open', [strUrl, strWindowName, strWindowFeatures]);
+        return iab;
+    };
+})();
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js b/platforms/ios/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
new file mode 100644
index 0000000..2469e9e
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-qrscanner/www/www.min.js
@@ -0,0 +1,344 @@
+cordova.define("cordova-plugin-qrscanner.QRScanner", function(require, exports, module) {
+// This file is generated by `npm run build`.
+
+/*global exports:false*/
+/*jshint unused:false */
+// remap parameter names from cordova.define
+// see `externals` in webpack.cordova.config.js
+var cordovaRequire = require;
+var cordovaExports = exports;
+var cordovaModule = module;
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// identity function for calling harmony imports with the correct context
+/******/ 	__webpack_require__.i = function(value) { return value; };
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__webpack_require__.d = function(exports, name, getter) {
+/******/ 		if(!__webpack_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, {
+/******/ 				configurable: false,
+/******/ 				enumerable: true,
+/******/ 				get: getter
+/******/ 			});
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__webpack_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__webpack_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(__webpack_require__.s = 18);
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ 1:
+/***/ (function(module, exports) {
+
+module.exports = cordovaModule;
+
+/***/ }),
+
+/***/ 18:
+/***/ (function(module, exports, __webpack_require__) {
+
+var globalCordova = __webpack_require__(4);
+var cordovaModule = __webpack_require__(1);
+
+var createQRScannerAdapter = __webpack_require__(3);
+
+// pass in global cordova object to expose cordova.exec
+var QRScannerAdapter = createQRScannerAdapter(globalCordova);
+cordovaModule.exports = QRScannerAdapter;
+
+
+/***/ }),
+
+/***/ 3:
+/***/ (function(module, exports) {
+
+module.exports = function createQRScanner(cordova){
+// The native implementations should return their status as ['string':'string']
+// dictionaries. Boolean values are encoded to '0' and '1', respectively.
+function stringToBool(string) {
+  switch (string) {
+    case '1':
+      return true;
+    case '0':
+      return false;
+    default:
+    throw new Error('QRScanner plugin returned an invalid boolean number-string: ' + string);
+  }
+}
+
+// Converts the returned ['string':'string'] dictionary to a status object.
+function convertStatus(statusDictionary) {
+  return {
+    authorized: stringToBool(statusDictionary.authorized),
+    denied: stringToBool(statusDictionary.denied),
+    restricted: stringToBool(statusDictionary.restricted),
+    prepared: stringToBool(statusDictionary.prepared),
+    scanning: stringToBool(statusDictionary.scanning),
+    previewing: stringToBool(statusDictionary.previewing),
+    showing: stringToBool(statusDictionary.showing),
+    lightEnabled: stringToBool(statusDictionary.lightEnabled),
+    canOpenSettings: stringToBool(statusDictionary.canOpenSettings),
+    canEnableLight: stringToBool(statusDictionary.canEnableLight),
+    canChangeCamera: stringToBool(statusDictionary.canChangeCamera),
+    currentCamera: parseInt(statusDictionary.currentCamera)
+  };
+}
+
+// Simple utility method to ensure the background is transparent. Used by the
+// plugin to force re-rendering immediately after the native webview background
+// is made transparent.
+function clearBackground() {
+  var body = document.body;
+  if (body.style) {
+    body.style.backgroundColor = 'rgba(0,0,0,0.01)';
+    body.style.backgroundImage = '';
+    setTimeout(function() {
+      body.style.backgroundColor = 'transparent';
+    }, 1);
+    if (body.parentNode && body.parentNode.style) {
+      body.parentNode.style.backgroundColor = 'transparent';
+      body.parentNode.style.backgroundImage = '';
+    }
+  }
+}
+
+function errorCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(error) {
+    var errorCode = parseInt(error);
+    var QRScannerError = {};
+    switch (errorCode) {
+      case 0:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner experienced an unexpected error.'
+        };
+        break;
+      case 1:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_DENIED',
+          code: 1,
+          _message: 'The user denied camera access.'
+        };
+        break;
+      case 2:
+        QRScannerError = {
+          name: 'CAMERA_ACCESS_RESTRICTED',
+          code: 2,
+          _message: 'Camera access is restricted.'
+        };
+        break;
+      case 3:
+        QRScannerError = {
+          name: 'BACK_CAMERA_UNAVAILABLE',
+          code: 3,
+          _message: 'The back camera is unavailable.'
+        };
+        break;
+      case 4:
+        QRScannerError = {
+          name: 'FRONT_CAMERA_UNAVAILABLE',
+          code: 4,
+          _message: 'The front camera is unavailable.'
+        };
+        break;
+      case 5:
+        QRScannerError = {
+          name: 'CAMERA_UNAVAILABLE',
+          code: 5,
+          _message: 'The camera is unavailable.'
+        };
+        break;
+      case 6:
+        QRScannerError = {
+          name: 'SCAN_CANCELED',
+          code: 6,
+          _message: 'Scan was canceled.'
+        };
+        break;
+      case 7:
+        QRScannerError = {
+          name: 'LIGHT_UNAVAILABLE',
+          code: 7,
+          _message: 'The device light is unavailable.'
+        };
+        break;
+      case 8:
+        // Open settings is only available on iOS 8.0+.
+        QRScannerError = {
+          name: 'OPEN_SETTINGS_UNAVAILABLE',
+          code: 8,
+          _message: 'The device is unable to open settings.'
+        };
+        break;
+      default:
+        QRScannerError = {
+          name: 'UNEXPECTED_ERROR',
+          code: 0,
+          _message: 'QRScanner returned an invalid error code.'
+        };
+        break;
+    }
+    callback(QRScannerError);
+  };
+}
+
+function successCallback(callback) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    callback(null, convertStatus(statusDict));
+  };
+}
+
+function doneCallback(callback, clear) {
+  if (!callback) {
+    return null;
+  }
+  return function(statusDict) {
+    if (clear) {
+      clearBackground();
+    }
+    callback(convertStatus(statusDict));
+  };
+}
+
+return {
+  prepare: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'prepare', []);
+  },
+  destroy: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'destroy', []);
+  },
+  scan: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to scan method.');
+    }
+    var success = function(result) {
+      callback(null, result);
+    };
+    cordova.exec(success, errorCallback(callback), 'QRScanner', 'scan', []);
+  },
+  cancelScan: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'cancelScan', []);
+  },
+  show: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'show', []);
+  },
+  hide: function(callback) {
+    cordova.exec(doneCallback(callback, true), null, 'QRScanner', 'hide', []);
+  },
+  pausePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'pausePreview', []);
+  },
+  resumePreview: function(callback) {
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'resumePreview', []);
+  },
+  enableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'enableLight', []);
+  },
+  disableLight: function(callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'disableLight', []);
+  },
+  useCamera: function(index, callback) {
+    cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'useCamera', [index]);
+  },
+  useFrontCamera: function(callback) {
+    var frontCamera = 1;
+    if (callback) {
+      this.useCamera(frontCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [frontCamera]);
+    }
+  },
+  useBackCamera: function(callback) {
+    var backCamera = 0;
+    if (callback) {
+      this.useCamera(backCamera, callback);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'useCamera', [backCamera]);
+    }
+  },
+  openSettings: function(callback) {
+    if (callback) {
+      cordova.exec(successCallback(callback), errorCallback(callback), 'QRScanner', 'openSettings', []);
+    } else {
+      cordova.exec(null, null, 'QRScanner', 'openSettings', []);
+    }
+  },
+  getStatus: function(callback) {
+    if (!callback) {
+      throw new Error('No callback provided to getStatus method.');
+    }
+    cordova.exec(doneCallback(callback), null, 'QRScanner', 'getStatus', []);
+  }
+};
+};
+
+
+/***/ }),
+
+/***/ 4:
+/***/ (function(module, exports) {
+
+module.exports = cordova;
+
+/***/ })
+
+/******/ });
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js b/platforms/ios/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
new file mode 100644
index 0000000..708186f
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-statusbar/www/statusbar.js
@@ -0,0 +1,116 @@
+cordova.define("cordova-plugin-statusbar.statusbar", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+/* global cordova */
+
+var exec = require('cordova/exec');
+
+var namedColors = {
+    "black": "#000000",
+    "darkGray": "#A9A9A9",
+    "lightGray": "#D3D3D3",
+    "white": "#FFFFFF",
+    "gray": "#808080",
+    "red": "#FF0000",
+    "green": "#00FF00",
+    "blue": "#0000FF",
+    "cyan": "#00FFFF",
+    "yellow": "#FFFF00",
+    "magenta": "#FF00FF",
+    "orange": "#FFA500",
+    "purple": "#800080",
+    "brown": "#A52A2A"
+};
+
+var StatusBar = {
+
+    isVisible: true,
+
+    overlaysWebView: function (doOverlay) {
+        exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
+    },
+
+    styleDefault: function () {
+        // dark text ( to be used on a light background )
+        exec(null, null, "StatusBar", "styleDefault", []);
+    },
+
+    styleLightContent: function () {
+        // light text ( to be used on a dark background )
+        exec(null, null, "StatusBar", "styleLightContent", []);
+    },
+
+    styleBlackTranslucent: function () {
+        // #88000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackTranslucent", []);
+    },
+
+    styleBlackOpaque: function () {
+        // #FF000000 ? Apple says to use lightContent instead
+        exec(null, null, "StatusBar", "styleBlackOpaque", []);
+    },
+
+    backgroundColorByName: function (colorname) {
+        return StatusBar.backgroundColorByHexString(namedColors[colorname]);
+    },
+
+    backgroundColorByHexString: function (hexString) {
+        if (hexString.charAt(0) !== "#") {
+            hexString = "#" + hexString;
+        }
+
+        if (hexString.length === 4) {
+            var split = hexString.split("");
+            hexString = "#" + split[1] + split[1] + split[2] + split[2] + split[3] + split[3];
+        }
+
+        exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
+    },
+
+    hide: function () {
+        exec(null, null, "StatusBar", "hide", []);
+        StatusBar.isVisible = false;
+    },
+
+    show: function () {
+        exec(null, null, "StatusBar", "show", []);
+        StatusBar.isVisible = true;
+    }
+
+};
+
+// prime it. setTimeout so that proxy gets time to init
+window.setTimeout(function () {
+    exec(function (res) {
+        if (typeof res == 'object') {
+            if (res.type == 'tap') {
+                cordova.fireWindowEvent('statusTap');
+            }
+        } else {
+            StatusBar.isVisible = res;
+        }
+    }, null, "StatusBar", "_ready", []);
+}, 0);
+
+module.exports = StatusBar;
+
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js b/platforms/ios/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
new file mode 100644
index 0000000..9c935cb
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-themeablebrowser/www/themeablebrowser.js
@@ -0,0 +1,121 @@
+cordova.define("cordova-plugin-themeablebrowser.themeablebrowser", function(require, exports, module) {
+/*
+ *
+ * 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.
+ *
+*/
+
+var exec = require('cordova/exec');
+var channel = require('cordova/channel');
+var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
+
+function ThemeableBrowser() {
+   this.channels = {};
+}
+
+ThemeableBrowser.prototype = {
+    _eventHandler: function (event) {
+        if (event && (event.type in this.channels)) {
+            this.channels[event.type].fire(event);
+        }
+    },
+    close: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'close', []);
+        return this;
+    },
+    show: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'show', []);
+        return this;
+    },
+    reload: function (eventname) {
+        exec(null, null, 'ThemeableBrowser', 'reload', []);
+        return this;
+    },
+    addEventListener: function (eventname,f) {
+        if (!(eventname in this.channels)) {
+            this.channels[eventname] = channel.create(eventname);
+        }
+        this.channels[eventname].subscribe(f);
+        return this;
+    },
+    removeEventListener: function(eventname, f) {
+        if (eventname in this.channels) {
+            this.channels[eventname].unsubscribe(f);
+        }
+        return this;
+    },
+
+    executeScript: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectScriptFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('executeScript requires exactly one of code or file to be specified');
+        }
+        return this;
+    },
+
+    insertCSS: function(injectDetails, cb) {
+        if (injectDetails.code) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleCode', [injectDetails.code, !!cb]);
+        } else if (injectDetails.file) {
+            exec(cb, null, 'ThemeableBrowser', 'injectStyleFile', [injectDetails.file, !!cb]);
+        } else {
+            throw new Error('insertCSS requires exactly one of code or file to be specified');
+        }
+        return this;
+    }
+};
+
+exports.open = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
+    // Don't catch calls that write to existing frames (e.g. named iframes).
+    if (window.frames && window.frames[strWindowName]) {
+        var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
+        return origOpenFunc.apply(window, arguments);
+    }
+
+    strUrl = urlutil.makeAbsolute(strUrl);
+    var iab = new ThemeableBrowser();
+
+    callbacks = callbacks || {};
+    for (var callbackName in callbacks) {
+        iab.addEventListener(callbackName, callbacks[callbackName]);
+    }
+
+    var cb = function(eventname) {
+       iab._eventHandler(eventname);
+    };
+
+    strWindowFeatures = strWindowFeatures && JSON.stringify(strWindowFeatures);
+    // Slightly delay the actual native call to give the user a chance to
+    // register event listeners first, otherwise some warnings or errors may be missed.
+    setTimeout(function() {
+        exec(cb, cb, 'ThemeableBrowser', 'open', [strUrl, strWindowName, strWindowFeatures || '']);
+    }, 0);
+    return iab;
+};
+
+exports.EVT_ERR = 'ThemeableBrowserError';
+exports.EVT_WRN = 'ThemeableBrowserWarning';
+exports.ERR_CRITICAL = 'critical';
+exports.ERR_LOADFAIL = 'loadfail';
+exports.WRN_UNEXPECTED = 'unexpected';
+exports.WRN_UNDEFINED = 'undefined';
+});
diff --git a/platforms/ios/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js b/platforms/ios/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
new file mode 100644
index 0000000..38a3a85
--- /dev/null
+++ b/platforms/ios/platform_www/plugins/cordova-plugin-touch-id/www/TouchID.js
@@ -0,0 +1,36 @@
+cordova.define("cordova-plugin-touch-id.TouchID", function(require, exports, module) {
+function TouchID() {
+}
+
+TouchID.prototype.isAvailable = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "isAvailable", []);
+};
+
+TouchID.prototype.didFingerprintDatabaseChange = function (successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "didFingerprintDatabaseChange", []);
+};
+
+TouchID.prototype.verifyFingerprint = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprint", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallback = function (message, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallback", [message]);
+};
+
+TouchID.prototype.verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel = function (message, enterPasswordLabel, successCallback, errorCallback) {
+  cordova.exec(successCallback, errorCallback, "TouchID", "verifyFingerprintWithCustomPasswordFallbackAndEnterPasswordLabel", [message, enterPasswordLabel]);
+};
+
+TouchID.install = function () {
+  if (!window.plugins) {
+    window.plugins = {};
+  }
+
+  window.plugins.touchid = new TouchID();
+  return window.plugins.touchid;
+};
+
+cordova.addConstructor(TouchID.install);
+
+});
diff --git a/platforms/ios/pods-debug.xcconfig b/platforms/ios/pods-debug.xcconfig
new file mode 100644
index 0000000..12c7065
--- /dev/null
+++ b/platforms/ios/pods-debug.xcconfig
@@ -0,0 +1,20 @@
+//
+// 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.
+//
+
+// DO NOT MODIFY -- auto-generated by Apache Cordova
diff --git a/platforms/ios/pods-release.xcconfig b/platforms/ios/pods-release.xcconfig
new file mode 100644
index 0000000..12e2b13
--- /dev/null
+++ b/platforms/ios/pods-release.xcconfig
@@ -0,0 +1,20 @@
+//
+// 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.
+//
+
+// DO NOT MODIFY -- auto-generated by Apache Cordova
\ No newline at end of file
diff --git a/platforms/ios/pods.json b/platforms/ios/pods.json
new file mode 100644
index 0000000..ae83877
--- /dev/null
+++ b/platforms/ios/pods.json
@@ -0,0 +1,5 @@
+{
+    "declarations": {},
+    "sources": {},
+    "libraries": {}
+}
\ No newline at end of file